diff --git a/base/applications/dxdiag/lang/tr-TR.rc b/base/applications/dxdiag/lang/tr-TR.rc index 39a43a1a75c..9734d84ce80 100644 --- a/base/applications/dxdiag/lang/tr-TR.rc +++ b/base/applications/dxdiag/lang/tr-TR.rc @@ -118,7 +118,7 @@ BEGIN RTEXT "Sürüm:", -1, 275, 35, 55, 10 RTEXT "Zaman:", -1, 275, 45, 55, 10 RTEXT "WHQL İmleği:", -1, 275, 55, 55, 10 - RTEXT "Diğer Kütükler:", -1, 275, 65, 55, 10 + RTEXT "Başka Kütükler:", -1, 275, 65, 55, 10 RTEXT "Sağlayıcı:", -1, 275, 75, 55, 10 LTEXT "", IDC_STATIC_DSOUND_DRIVER, 335, 25, 100, 10 LTEXT "", IDC_STATIC_DSOUND_VERSION, 335, 35, 100, 10 diff --git a/base/applications/games/solitaire/lang/tr-TR.rc b/base/applications/games/solitaire/lang/tr-TR.rc index d3c6a86ad1e..8ddadb88227 100644 --- a/base/applications/games/solitaire/lang/tr-TR.rc +++ b/base/applications/games/solitaire/lang/tr-TR.rc @@ -3,7 +3,7 @@ * LICENSE: Freeware, permission to use under Public Domain * FILE: base/applications/games/solitaire/lang/tr-TR.rc * PURPOSE: Turkish Resource File for ReactOS Solitaire - * TRANSLATOR: 2013 Erdem Ersoy (eersoy93) (erdemersoy@live.com) + * TRANSLATOR: 2013, 2014 Erdem Ersoy (eersoy93) (erdemersoy@live.com) */ LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT @@ -18,13 +18,13 @@ BEGIN GROUPBOX "Kâğıtlar", -1, 7, 7, 90, 40 AUTORADIOBUTTON "&Tekli Çek", IDC_OPT_DRAWONE, 14, 19, 70, 10, WS_GROUP | WS_TABSTOP AUTORADIOBUTTON "&Üçlü Çek", IDC_OPT_DRAWTHREE, 14, 32, 70, 10 - GROUPBOX "Scoring", -1, 100, 7, 75, 53 - AUTORADIOBUTTON "&Standard", IDC_OPT_STANDARD, 107, 19, 60, 10, WS_GROUP | WS_TABSTOP + GROUPBOX "Sayılama", -1, 100, 7, 75, 53 + AUTORADIOBUTTON "&Ölçünlü", IDC_OPT_STANDARD, 107, 19, 60, 10, WS_GROUP | WS_TABSTOP AUTORADIOBUTTON "&Vegas", IDC_OPT_VEGAS, 107, 32, 60, 10 - AUTORADIOBUTTON "&None", IDC_OPT_NOSCORE, 107, 45, 60, 10 + AUTORADIOBUTTON "&Yok", IDC_OPT_NOSCORE, 107, 45, 60, 10 AUTOCHECKBOX "&Süreyi Göster", IDC_OPT_SHOWTIME, 7 ,51 ,65 ,10, WS_TABSTOP AUTOCHECKBOX "&Durum Çubuğu", IDC_OPT_STATUSBAR, 7, 66, 64, 10, WS_TABSTOP - AUTOCHECKBOX "&Keep Score", IDC_OPT_KEEPSCORE, 100, 66, 65, 10, WS_TABSTOP + AUTOCHECKBOX "S&ayıyı Koru", IDC_OPT_KEEPSCORE, 100, 66, 65, 10, WS_TABSTOP DEFPUSHBUTTON "Tamam", IDOK, 35, 97, 50, 14 PUSHBUTTON "İptal", IDCANCEL, 101, 97, 50, 14 END @@ -59,8 +59,8 @@ BEGIN IDS_SOL_QUIT "Bu oyundan çıkılsın mı?" IDS_SOL_WIN "Tebrikler, kazandınız!" IDS_SOL_DEAL "Yine dağıtılsın mı?" - IDS_SOL_SCORE "Score: %d" - IDS_SOL_TIME "Time: %d" + IDS_SOL_SCORE "Sayı: %d" + IDS_SOL_TIME "Süre: %d" END /* Menus */ diff --git a/base/applications/msconfig/lang/tr-TR.rc b/base/applications/msconfig/lang/tr-TR.rc index a96b9fb9fe2..141d7fce7a4 100644 --- a/base/applications/msconfig/lang/tr-TR.rc +++ b/base/applications/msconfig/lang/tr-TR.rc @@ -1,4 +1,4 @@ -/* TRANSLATOR: 2013 Erdem Ersoy (eersoy93) (erdemersoy@live.com) */ +/* TRANSLATOR: 2013, 2014 Erdem Ersoy (eersoy93) (erdemersoy@live.com) */ LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT diff --git a/base/applications/mscutils/devmgmt/lang/cs-CZ.rc b/base/applications/mscutils/devmgmt/lang/cs-CZ.rc index 10464f614da..f56d94120ed 100644 --- a/base/applications/mscutils/devmgmt/lang/cs-CZ.rc +++ b/base/applications/mscutils/devmgmt/lang/cs-CZ.rc @@ -1,4 +1,4 @@ -LANGUAGE LANG_CZECH, SUBLANG_DEFAULT +LANGUAGE LANG_CZECH, SUBLANG_DEFAULT IDR_MAINMENU MENU BEGIN @@ -21,7 +21,7 @@ BEGIN MENUITEM "Prostředky podle typu", IDC_RESBYTYPE, GRAYED MENUITEM "Prostředky podle připojení", IDC_RESBYCONN, GRAYED MENUITEM SEPARATOR - MENUITEM "Show hidden devices", IDC_SHOWHIDDEN + MENUITEM "Zobrazit skrytá zařízení", IDC_SHOWHIDDEN END POPUP "Nápověda" BEGIN diff --git a/base/applications/mscutils/eventvwr/eventvwr.rc b/base/applications/mscutils/eventvwr/eventvwr.rc index 29058175908..d2c9a69cac5 100644 --- a/base/applications/mscutils/eventvwr/eventvwr.rc +++ b/base/applications/mscutils/eventvwr/eventvwr.rc @@ -24,6 +24,9 @@ IDI_ERRORICON ICON "res/error.ico" #ifdef LANGUAGE_BG_BG #include "lang/bg-BG.rc" #endif +#ifdef LANGUAGE_CS_CZ + #include "lang/cs-CZ.rc" +#endif #ifdef LANGUAGE_DE_DE #include "lang/de-DE.rc" #endif diff --git a/base/applications/mscutils/eventvwr/lang/cs-CZ.rc b/base/applications/mscutils/eventvwr/lang/cs-CZ.rc new file mode 100644 index 00000000000..873bb14f6e1 --- /dev/null +++ b/base/applications/mscutils/eventvwr/lang/cs-CZ.rc @@ -0,0 +1,117 @@ +LANGUAGE LANG_CZECH, SUBLANG_DEFAULT + +IDC_EVENTVWR MENU +BEGIN + POPUP "&Protokol" + BEGIN + MENUITEM "&Aplikace", ID_LOG_APPLICATION + MENUITEM "&Zabezpečení", ID_LOG_SECURITY + MENUITEM "&Systém", ID_LOG_SYSTEM + MENUITEM SEPARATOR + MENUITEM "&Konec", IDM_EXIT + END + POPUP "&Zobrazit" + BEGIN + MENUITEM "&Obnovit", IDM_REFRESH + END + MENUITEM "&Možnosti", ID_OPTIONS + POPUP "&Nápověda" + BEGIN + MENUITEM "Ná&pověda", IDM_HELP + MENUITEM SEPARATOR + MENUITEM "&O programu...", IDM_ABOUT + END +END + +IDC_EVENTVWR ACCELERATORS +BEGIN + "?", IDM_ABOUT, ASCII, ALT + "/", IDM_ABOUT, ASCII, ALT +END + +IDD_ABOUTBOX DIALOGEX 0, 0, 230, 75 +STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_CAPTION | WS_SYSMENU +CAPTION "O programu" +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + ICON IDI_EVENTVWR, IDC_MYICON, 14, 9, 21, 20 + LTEXT "ReactOS Prohlížeč událostí 1.0", IDC_STATIC, 49, 10, 119, 8, SS_NOPREFIX + LTEXT "Copyright (C) 2007 Marc Piulachs (marc.piulachs@codexchange.net)", IDC_STATIC, 49, 20, 119, 22 + DEFPUSHBUTTON "OK", IDOK, 90, 48, 42, 16, WS_GROUP +END + +IDD_PROGRESSBOX DIALOGEX 0, 0, 230, 40 +STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER +CAPTION "Čekejte.." +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + CTEXT "Načítám protokol událostí. Prosím čekejte ...", IDC_STATIC, 0, 15, 230, 8, SS_NOPREFIX +END + +IDD_EVENTDETAILDIALOG DIALOGEX 0, 0, 276, 282 +STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_CONTEXTHELP +CAPTION "Podrobnosti události" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "&Zavřít", IDOK, 12, 258, 50, 14 + PUSHBUTTON "&Předchozí", IDPREVIOUS, 78, 258, 50, 14 + PUSHBUTTON "&Další", IDNEXT, 144, 258, 50, 14 + PUSHBUTTON "&Nápověda", IDHELP, 210, 258, 50, 14 + EDITTEXT IDC_EVENTTEXTEDIT, 14, 81, 247, 108, ES_MULTILINE | ES_READONLY + LTEXT "&Popis:", IDC_STATIC, 15, 70, 39, 8 + LTEXT "Datum:", IDC_STATIC, 14, 14, 36, 8 + EDITTEXT IDC_EVENTDATESTATIC, 56, 14, 72, 8, ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP | ES_AUTOHSCROLL + LTEXT "Čas:", IDC_STATIC, 14, 27, 36, 8 + EDITTEXT IDC_EVENTTIMESTATIC, 56, 27, 72, 8, ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP | ES_AUTOHSCROLL + LTEXT "&Uživatel:", IDC_STATIC, 14, 41, 36, 8 + EDITTEXT IDC_EVENTUSERSTATIC, 56, 41, 72, 8, ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP | ES_AUTOHSCROLL + LTEXT "P&očítač:", IDC_STATIC, 14, 54, 36, 8 + EDITTEXT IDC_EVENTCOMPUTERSTATIC, 56, 54, 72, 8, ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP | ES_AUTOHSCROLL + LTEXT "ID události:", IDC_STATIC, 133, 15, 36, 8 + EDITTEXT IDC_EVENTIDSTATIC, 175, 15, 87, 8, ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP | ES_AUTOHSCROLL + LTEXT "Zdroj:", IDC_STATIC, 133, 28, 36, 8 + EDITTEXT IDC_EVENTSOURCESTATIC, 175, 28, 87, 8, ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP | ES_AUTOHSCROLL + LTEXT "Typ:", IDC_STATIC, 133, 42, 36, 8 + EDITTEXT IDC_EVENTTYPESTATIC, 175, 42, 87, 8, ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP | ES_AUTOHSCROLL + LTEXT "Kategorie:", IDC_STATIC, 133, 55, 36, 8 + EDITTEXT IDC_EVENTCATEGORYSTATIC, 175, 55, 87, 8, ES_LEFT | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP | ES_AUTOHSCROLL + EDITTEXT IDC_EVENTDATAEDIT, 14, 204, 247, 44, ES_MULTILINE | ES_READONLY + LTEXT "D&ata", IDC_STATIC, 14, 194, 20, 8 + CONTROL "&Byty", IDC_BYTESRADIO, "Button", BS_AUTORADIOBUTTON, 39, 194, 34, 8 + CONTROL "&Word", IDC_WORDRADIO, "Button", BS_AUTORADIOBUTTON, 77, 194, 33, 8 +END + +STRINGTABLE +BEGIN + IDS_APP_TITLE "Prohlížeč událostí" + IDS_APP_TITLE_EX "%s - Protkol %s na \\\\" + IDS_STATUS_MSG "Počet událostí v protokolu %s: %lu" + IDS_EVENTSTRINGIDNOTFOUND "Popis ID události ( %lu ) zdroj ( %s ) nebyl nalezen. Místní počítač neobsahuje potřebné informace v registru nebo chybí DLL soubory pro zobrazení zpráv ze vzdáleného počítače." + IDS_EVENTLOG_ERROR_TYPE "Chyba" + IDS_EVENTLOG_WARNING_TYPE "Upozornění" + IDS_EVENTLOG_INFORMATION_TYPE "Informace" + IDS_EVENTLOG_AUDIT_SUCCESS "Úspěšný audit" + IDS_EVENTLOG_AUDIT_FAILURE "Audit selhal" + IDS_EVENTLOG_SUCCESS "Úspěch" + IDS_EVENTLOG_UNKNOWN_TYPE "Neznámá událost" +END + +STRINGTABLE +BEGIN + IDS_COLUMNTYPE "Typ" + IDS_COLUMNDATE "Datum" + IDS_COLUMNTIME "Čas" + IDS_COLUMNSOURCE "Zdroj" + IDS_COLUMNCATEGORY "Kategorie" + IDS_COLUMNEVENT "Událost" + IDS_COLUMNUSER "Uživatel" + IDS_COLUMNCOMPUTER "Počítač" + IDS_COLUMNEVENTDATA "Data události" +END + +STRINGTABLE +BEGIN + IDS_NONE "Žádný" + IDS_NOT_AVAILABLE "Není k dispozici" +END diff --git a/base/applications/mscutils/servman/lang/cs-CZ.rc b/base/applications/mscutils/servman/lang/cs-CZ.rc new file mode 100644 index 00000000000..d05c65d1a3e --- /dev/null +++ b/base/applications/mscutils/servman/lang/cs-CZ.rc @@ -0,0 +1,281 @@ +LANGUAGE LANG_CZECH, SUBLANG_DEFAULT + +IDR_MAINMENU MENU +BEGIN + POPUP "&Soubor" + BEGIN + MENUITEM "Exportovat...", ID_EXPORT + MENUITEM SEPARATOR + MENUITEM "&Konec", ID_EXIT + END + POPUP "Akce" + BEGIN + MENUITEM "Připojit k...", ID_CONNECT, GRAYED + MENUITEM SEPARATOR + MENUITEM "Spustit", ID_START, GRAYED + MENUITEM "Zastavit", ID_STOP, GRAYED + MENUITEM "Pozastavit", ID_PAUSE, GRAYED + MENUITEM "Pokračovat", ID_RESUME, GRAYED + MENUITEM "Restartovat", ID_RESTART, GRAYED + MENUITEM SEPARATOR + MENUITEM "Obnovit", ID_REFRESH + MENUITEM SEPARATOR + MENUITEM "Upravit...", ID_EDIT, GRAYED + MENUITEM "Vytvořit...", ID_CREATE, GRAYED + MENUITEM "Odstranit...", ID_DELETE, GRAYED + MENUITEM SEPARATOR + MENUITEM "Vlastnosti...", ID_PROP, GRAYED + END + POPUP "Zobrazit" + BEGIN + MENUITEM "Velké ikony", ID_VIEW_LARGE + MENUITEM "Malé ikony", ID_VIEW_SMALL + MENUITEM "Seznam", ID_VIEW_LIST + MENUITEM "Detaily", ID_VIEW_DETAILS + MENUITEM SEPARATOR + MENUITEM "Upravit...", ID_VIEW_CUST, GRAYED + END + POPUP "Nápověda" + BEGIN + MENUITEM "Nápověda", ID_HELP + MENUITEM "O programu", ID_ABOUT + END +END + +IDR_POPUP MENU +BEGIN + POPUP "popup" + BEGIN + MENUITEM "Spustit", ID_START, GRAYED + MENUITEM "Zastavit", ID_STOP, GRAYED + MENUITEM "Pozastavit", ID_PAUSE, GRAYED + MENUITEM "pokračovat", ID_RESUME, GRAYED + MENUITEM "Restartovat", ID_RESTART, GRAYED + MENUITEM SEPARATOR + MENUITEM "Obnovit", ID_REFRESH + MENUITEM SEPARATOR + MENUITEM "Upravit...", ID_EDIT, GRAYED + MENUITEM "Odstranit...", ID_DELETE, GRAYED + MENUITEM SEPARATOR + MENUITEM "Vlastnosti...", ID_PROP, GRAYED + MENUITEM SEPARATOR + MENUITEM "Nápověda...", ID_HELP + END +END + +IDD_ABOUTBOX DIALOGEX 22, 16, 190, 182 +CAPTION "O správci služeb" +FONT 8, "MS Shell Dlg", 0, 0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "Správce služeb v0.8\nCopyright (C) 2005-2007\nGed Murphy (gedmurphy@reactos.org)", IDC_STATIC, 48, 7, 135, 30 + PUSHBUTTON "Zavřít", IDOK, 75, 162, 44, 15 + ICON IDI_SM_ICON, IDC_STATIC, 10, 10, 7, 30 + EDITTEXT IDC_LICENSE_EDIT, 8, 44, 174, 107, WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | ES_READONLY | ES_MULTILINE +END + +IDD_DLG_GENERAL DIALOGEX 6, 6, 253, 232 +CAPTION "General" +FONT 8, "MS Shell Dlg", 0, 0 +STYLE DS_SHELLFONT | WS_BORDER | WS_VISIBLE | WS_DLGFRAME | WS_SYSMENU | WS_GROUP | WS_TABSTOP +BEGIN + LTEXT "", IDC_SERV_NAME, 70, 11, 176, 11, WS_CHILD | WS_VISIBLE + EDITTEXT IDC_DISP_NAME, 70, 29, 176, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_READONLY + EDITTEXT IDC_DESCRIPTION, 70, 46, 176, 24, WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | ES_MULTILINE | ES_READONLY + EDITTEXT IDC_EXEPATH, 6, 86, 240, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_READONLY + COMBOBOX IDC_START_TYPE, 70, 107, 176, 40, WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST + PUSHBUTTON "Spustit", IDC_START, 6, 155, 54, 15, WS_DISABLED + PUSHBUTTON "Zastavit", IDC_STOP, 68, 155, 54, 15, WS_DISABLED + PUSHBUTTON "Pozastavit", IDC_PAUSE, 130, 155, 54, 15, WS_DISABLED + PUSHBUTTON "Pokračovat", IDC_RESUME, 192, 155, 54, 15, WS_DISABLED + LTEXT "Název služby:", IDC_STATIC, 4, 11, 53, 11 + LTEXT "Jméno:", IDC_STATIC, 4, 29, 53, 11 + LTEXT "Popis:", IDC_STATIC, 4, 51, 53, 11 + LTEXT "Cesta:", IDC_STATIC, 6, 73, 82, 9 + LTEXT "Typ spuštění:", IDC_STATIC, 6, 108, 53, 11 + LTEXT "Stav služby:", IDC_STATIC, 4, 138, 53, 11 + LTEXT "", IDC_SERV_STATUS, 70, 138, 176, 11, WS_CHILD | WS_VISIBLE + LTEXT "Zde můžete upřesnit parametry, které budou použity při spuštění.", IDC_STATIC, 6, 177, 240, 15 + LTEXT "Parametry:", IDC_STATIC, 6, 200, 58, 11 + EDITTEXT IDC_START_PARAM, 68, 199, 178, 13, WS_CHILD | WS_VISIBLE | WS_TABSTOP + PUSHBUTTON "Upravit", IDC_EDIT, 192, 215, 54, 15, WS_DISABLED +END + +IDD_DLG_DEPEND DIALOGEX 6, 6, 253, 225 +CAPTION "Závislosti" +FONT 8, "MS Shell Dlg", 0, 0 +STYLE DS_SHELLFONT | WS_BORDER | WS_VISIBLE | WS_DLGFRAME | WS_SYSMENU | WS_GROUP | WS_TABSTOP +BEGIN + CONTROL "", IDC_DEPEND_TREE1, "SysTreeView32" , WS_BORDER | WS_CHILDWINDOW | + WS_VISIBLE | WS_TABSTOP | TVS_HASBUTTONS | TVS_HASLINES | + TVS_LINESATROOT | TVS_DISABLEDRAGDROP, 8, 70, 236, 68 + CONTROL "", IDC_DEPEND_TREE2, "SysTreeView32", WS_BORDER | WS_CHILDWINDOW | + WS_VISIBLE | WS_TABSTOP | TVS_HASBUTTONS | TVS_HASLINES | + TVS_LINESATROOT | TVS_DISABLEDRAGDROP, 8, 151, 234, 67 + LTEXT "Některé služby závisí na jiných službách, systémových ovladačích nebo načítají jiné skupiny služeb. Zastavené nebo nesprávně fungující součásti systému mohou ovlivnit závislé služby.", IDC_STATIC, 8, 7, 238, 26 + LTEXT "Tato služba závisí na následujících součástech:", IDC_STATIC, 8, 57, 236, 9 + LTEXT "", IDC_DEPEND_SERVICE, 8, 38, 236, 13 +END + +IDD_DLG_CREATE DIALOGEX 6, 6, 225, 209 +CAPTION "Vytvořit službu" +FONT 8, "MS Shell Dlg", 0, 0 +STYLE DS_SHELLFONT | WS_BORDER | WS_VISIBLE | WS_DLGFRAME | WS_SYSMENU | WS_GROUP | WS_TABSTOP +BEGIN + EDITTEXT IDC_CREATE_SERVNAME, 72, 12, 150, 11, WS_CHILD | WS_VISIBLE | WS_EX_CLIENTEDGE + EDITTEXT IDC_CREATE_DISPNAME, 72, 31, 150, 11, WS_CHILD | WS_VISIBLE + EDITTEXT IDC_CREATE_PATH, 10, 62, 210, 13, WS_CHILD | WS_VISIBLE + EDITTEXT IDC_CREATE_DESC, 10, 97, 210, 48, WS_CHILD | WS_VISIBLE + EDITTEXT IDC_CREATE_OPTIONS, 10, 162, 210, 13, WS_CHILD | WS_VISIBLE + LTEXT "*Název služby :", IDC_STATIC, 12, 12, 54, 9 + LTEXT "*Jméno :", IDC_STATIC, 12, 33, 54, 9 + LTEXT "*Cesta :", IDC_STATIC, 10, 51, 68, 9 + LTEXT "Popis :", IDC_STATIC, 12, 86, 44, 9 + PUSHBUTTON "OK", IDOK, 126, 192, 44, 13 + PUSHBUTTON "Storno", IDCANCEL, 176, 192, 46, 13 + LTEXT "Další možnosti (viz Nápovědu)", IDC_STATIC, 10, 151, 134, 9 + PUSHBUTTON "Nápověda", ID_CREATE_HELP, 10, 192, 44, 13 +END + +IDD_DLG_DELETE DIALOGEX 6, 6, 185, 148 +CAPTION "Odstranit službu" +FONT 8, "MS Shell Dlg", 0, 0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | DS_MODALFRAME +BEGIN + ICON IDI_WARNING, IDC_STATIC, 10, 8, 24, 22 + LTEXT "Opravdu chcete tuto službu odstranit? Tuto akci nelze vrátit!", IDC_STATIC, 50, 6, 125, 25 + LTEXT "Název služby:", IDC_STATIC, 6, 40, 80, 9 + LTEXT "", IDC_DEL_NAME, 15, 53, 160, 15 + EDITTEXT IDC_DEL_DESC, 6, 73, 174, 48, WS_CHILD | WS_VISIBLE | WS_VSCROLL | + WS_EX_STATICEDGE | ES_MULTILINE | ES_READONLY + PUSHBUTTON "Ano", IDOK, 26, 129, 54, 13 + DEFPUSHBUTTON "Ne", IDCANCEL, 102, 129, 54, 13 +END + +IDD_DLG_DEPEND_STOP DIALOGEX 6, 6, 240, 148 +CAPTION "Zastavit jiné služby" +FONT 8, "MS Shell Dlg", 0, 0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | DS_MODALFRAME +BEGIN + ICON IDI_WARNING, IDC_STATIC, 10, 8, 24, 22 + LTEXT "", IDC_STOP_DEPENDS, 40, 8, 170, 25 + LISTBOX IDC_STOP_DEPENDS_LB, 15, 40, 210, 70, WS_CHILD | WS_VISIBLE | WS_EX_STATICEDGE | LBS_NOSEL + LTEXT "Chcete zastavit tyto služby?", IDC_STATIC, 15, 110, 150, 10 + DEFPUSHBUTTON "Ano", IDOK, 60, 129, 54, 14 + PUSHBUTTON "Ne", IDCANCEL, 120, 129, 54, 14 +END + +IDD_DLG_HELP_OPTIONS DIALOGEX 6, 6, 200, 150 +CAPTION "Možnosti" +FONT 8, "MS Shell Dlg", 0, 0 +STYLE 0x10CF0000 +BEGIN + LTEXT "", IDC_CREATE_HELP, 6, 5, 200, 150 + PUSHBUTTON "Ok", IDOK, 75, 130, 44, 13 +END + +IDD_DLG_PROGRESS DIALOGEX 6, 6, 255, 89 +CAPTION "Ovldání služeb" +FONT 8, "MS Shell Dlg", 0, 0 +STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | WS_VISIBLE | DS_MODALFRAME +EXSTYLE WS_EX_TOOLWINDOW +BEGIN + CONTROL "", IDC_SERVCON_PROGRESS, "msctls_progress32", 0x50000000, 8, 46, 238, 13 + LTEXT "", IDC_SERVCON_INFO, 8, 5, 236, 11 + LTEXT "", IDC_SERVCON_NAME, 8, 25, 66, 11 + PUSHBUTTON "&Zavřít", IDOK, 100, 70, 54, 13 +END + +STRINGTABLE +BEGIN + IDS_FIRSTCOLUMN "Název" + IDS_SECONDCOLUMN "Popis" + IDS_THIRDCOLUMN "Stav" + IDS_FOURTHCOLUMN "Typ spuštění" + IDS_FITHCOLUMN "Přihlásit jako" +END + +STRINGTABLE +BEGIN + IDS_SERVICES_STARTED "Spuštěno" + IDS_SERVICES_STOPPED "Zastaveno" + IDS_SERVICES_AUTO "Automaticky" + IDS_SERVICES_MAN "Ručně" + IDS_SERVICES_DIS "Zakázáno" +END + +STRINGTABLE +BEGIN + IDS_NUM_SERVICES "Počet služeb: %d" + IDS_STOP_DEPENDS "Zastavením %s dojde také k zastavení" + IDS_NO_DEPENDS "<Žádné závislosti>" + IDS_LICENSE "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 2 of the License, or (at your option) any later version.\r\n\r\nThis 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.\r\n\r\nYou should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA." +END + +STRINGTABLE +BEGIN + IDS_TOOLTIP_PROP "Vlastnosti" + IDS_TOOLTIP_REFRESH "Obnovit" + IDS_TOOLTIP_EXPORT "Export seznamu" + IDS_TOOLTIP_CREATE "Vytvořit novou službu" + IDS_TOOLTIP_DELETE "Odstraní danou službu" + IDS_TOOLTIP_START "Spustit službu" + IDS_TOOLTIP_STOP "Zastavit službu" + IDS_TOOLTIP_PAUSE "Pozastavit službu" + IDS_TOOLTIP_RESTART "Restartovat službu" +END + +STRINGTABLE +BEGIN + IDS_PROGRESS_INFO_START "ReactOS se pokouší spustit následující službu" + IDS_PROGRESS_INFO_STOP "ReactOS se pokouší zastavit následující službu" + IDS_PROGRESS_INFO_PAUSE "ReactOS se pokouší pozastavit následující službu" + IDS_PROGRESS_INFO_RESUME "ReactOS se pokouší pokračovat s následující službou" + IDS_CREATE_SUCCESS "Služba úspěšně vytvořena" + IDS_DELETE_SUCCESS "Služba úspěšně odstraněna" + IDS_CREATE_REQ "Položky označené hvězdičkou\njsou povinné" + IDS_DELETE_STOP "Před odstraněním musí být služba ručně zastavena!" +END + +STRINGTABLE +BEGIN + IDS_HELP_OPTIONS "MOŽNOSTI VYTVOŘENÍ:\r\nPOZNÁMKA: Jméno parametru zahrnuje i znak rovnítko.\r\n type= \r\n (výchozí = own)\r\n start= \r\n (výchozí = demand) \r\n error= \r\n (výchozí = normal)\r\n group= \r\n tag= \r\n depend= \r\n obj= \r\n (výchozí = LocalSystem)\r\n password= \r\n" +END + +/* Hints */ +STRINGTABLE +BEGIN + IDS_HINT_BLANK " " + IDS_HINT_EXPORT " Vyexportuje daný seznam do souboru." + IDS_HINT_EXIT " Ukončí program." + IDS_HINT_CONNECT " Spravovat jiný počítač." + IDS_HINT_START " Spustit vybranou službu." + IDS_HINT_STOP " Zastavit vybranou službu." + IDS_HINT_PAUSE " Pozastavit vybranou službu." + IDS_HINT_RESUME " Pokračovat s vybranou službou." + IDS_HINT_RESTART " Zastavit a spustit vybranou službu." + IDS_HINT_REFRESH " Obnovit seznam služeb." + IDS_HINT_EDIT " Upravit vlastnosti vybrané služby." + IDS_HINT_CREATE " Vytvořit novou službu." + IDS_HINT_DELETE " Odstranit vybranou službu." + IDS_HINT_PROP " Zobrazit panel vlastností pro vybranou službu." + IDS_HINT_LARGE " Zobrazit služby jako velké ikony." + IDS_HINT_SMALL " Zobrazit služby jako malé ikony." + IDS_HINT_LIST " Zobrazit služby jako seznam." + IDS_HINT_DETAILS " Zobrazit služby jako podrobný seznam." + IDS_HINT_CUST " Upravit zobrazení." + IDS_HINT_HELP " Zobrazit nápovědu." + IDS_HINT_ABOUT " O ReactOS Správci služeb." + IDS_HINT_SYS_RESTORE " Obnovit normální velikost tohoto okna." + IDS_HINT_SYS_MOVE " Přesunout okno." + IDS_HINT_SYS_SIZE " Změnit velikost okna." + IDS_HINT_SYS_MINIMIZE " Minimalizovat na panel start." + IDS_HINT_SYS_MAXIMIZE " Maximalizovat na celou obrazovku." + IDS_HINT_SYS_CLOSE " Zavřít toto okno." +END + +/* Application title */ +STRINGTABLE +BEGIN + IDS_APPNAME "ReactOS Správce služeb" +END diff --git a/base/applications/mscutils/servman/lang/tr-TR.rc b/base/applications/mscutils/servman/lang/tr-TR.rc index 6d90b1c12aa..e9c1274b80b 100644 --- a/base/applications/mscutils/servman/lang/tr-TR.rc +++ b/base/applications/mscutils/servman/lang/tr-TR.rc @@ -114,7 +114,7 @@ BEGIN CONTROL "", IDC_DEPEND_TREE2, "SysTreeView32", WS_BORDER | WS_CHILDWINDOW | WS_VISIBLE | WS_TABSTOP | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_DISABLEDRAGDROP, 8, 151, 234, 67 - LTEXT "Birtakım hizmetler, diğer hizmetlere, dizge sürücülerine ve yükleme sıra öbeklerine bağımlıdır. Eğer bir dizge bileşeni, durdurulmuşsa ya da düzgün bir şekilde çalışmıyorsa bağımlı hizmetler etkilenebilir.", IDC_STATIC, 8, 7, 238, 26 + LTEXT "Birtakım hizmetler, başka hizmetlere, dizge sürücülerine ve yükleme sıra öbeklerine bağımlıdır. Eğer bir dizge bileşeni, durdurulmuşsa ya da düzgün bir şekilde çalışmıyorsa bağımlı hizmetler etkilenebilir.", IDC_STATIC, 8, 7, 238, 26 LTEXT "Bu hizmet aşağıdaki bileşenlere bağımlıdır:", IDC_STATIC, 8, 57, 236, 9 LTEXT "", IDC_DEPEND_SERVICE, 8, 38, 236, 13 END @@ -155,7 +155,7 @@ BEGIN END IDD_DLG_DEPEND_STOP DIALOGEX 6, 6, 240, 148 -CAPTION "Diğer Hizmetleri Kapatma" +CAPTION "Başka Hizmetleri Kapatma" FONT 8, "MS Shell Dlg", 0, 0 STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | DS_MODALFRAME BEGIN diff --git a/base/applications/mscutils/servman/servman.rc b/base/applications/mscutils/servman/servman.rc index 0959200ec13..9c52761b7c9 100644 --- a/base/applications/mscutils/servman/servman.rc +++ b/base/applications/mscutils/servman/servman.rc @@ -36,6 +36,9 @@ IDI_DRIVER ICON "res/driver.ico" #ifdef LANGUAGE_BG_BG #include "lang/bg-BG.rc" #endif +#ifdef LANGUAGE_CS_CZ + #include "lang/cs-CZ.rc" +#endif #ifdef LANGUAGE_DE_DE #include "lang/de-DE.rc" #endif diff --git a/base/applications/rapps/lang/cs-CZ.rc b/base/applications/rapps/lang/cs-CZ.rc index 7202c36141e..3f037363368 100644 --- a/base/applications/rapps/lang/cs-CZ.rc +++ b/base/applications/rapps/lang/cs-CZ.rc @@ -1,6 +1,6 @@ /* FILE: applications/rapps/lang/cs-CZ.rc * TRANSLATOR: Radek Liska aka Black_Fox (radekliska at gmail dot com) - * UPDATED: 2010-12-12 + * UPDATED: 2014-04-20 */ LANGUAGE LANG_CZECH, SUBLANG_DEFAULT @@ -21,9 +21,9 @@ BEGIN MENUITEM SEPARATOR MENUITEM "Odstranit z ®istru", ID_REGREMOVE MENUITEM SEPARATOR - MENUITEM "&Obnovit", ID_REFRESH + MENUITEM "Ob&novit", ID_REFRESH MENUITEM SEPARATOR - MENUITEM "Update Da&tabase", ID_RESETDB + MENUITEM "&Aktualizovat databázi", ID_RESETDB END POPUP "Nápověda" BEGIN @@ -51,9 +51,9 @@ BEGIN MENUITEM SEPARATOR MENUITEM "Odstranit z ®istru", ID_REGREMOVE MENUITEM SEPARATOR - MENUITEM "&Obnovit", ID_REFRESH + MENUITEM "Ob&novit", ID_REFRESH MENUITEM SEPARATOR - MENUITEM "Update Da&tabase", ID_RESETDB + MENUITEM "&Aktualizovat databázi", ID_RESETDB END END @@ -103,7 +103,7 @@ STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME CAPTION "O programu" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "ReactOS Manažer aplikací\nCopyright (C) 2009\nby Dmitry Chapyshev (dmitry@reactos.org)", IDC_STATIC, 48, 7, 130, 39 + LTEXT "ReactOS Správce aplikací\nCopyright (C) 2009\nDmitry Chapyshev (dmitry@reactos.org)", IDC_STATIC, 48, 7, 130, 39 PUSHBUTTON "Zavřít", IDOK, 133, 46, 50, 14 ICON IDI_MAIN, IDC_STATIC, 10, 10, 7, 30 END @@ -168,7 +168,7 @@ BEGIN IDS_CAT_INTERNET "Internet a sítě" IDS_CAT_LIBS "Knihovny" IDS_CAT_OFFICE "Kancelář" - IDS_CAT_OTHER "Jiné" + IDS_CAT_OTHER "Ostatní" IDS_CAT_SCIENCE "Věda" IDS_CAT_TOOLS "Nástroje" IDS_CAT_VIDEO "Video" @@ -176,20 +176,20 @@ END STRINGTABLE BEGIN - IDS_APPTITLE "ReactOS Manažer aplikací" + IDS_APPTITLE "ReactOS Správce aplikací" IDS_SEARCH_TEXT "Hledat..." IDS_INSTALL "Instalovat" IDS_UNINSTALL "Odinstalovat" IDS_MODIFY "Změnit" IDS_APPS_COUNT "Počet aplikací: %d" - IDS_WELCOME_TITLE "Vítejte v ReactOS Manažeru aplikací!\n\n" + IDS_WELCOME_TITLE "Vítejte v ReactOS Správci aplikací!\n\n" IDS_WELCOME_TEXT "Na levé straně zvolte kategorii, pak vpravo zvolte aplikaci, která bude nainstalována nebo odinstalována.\nWebová stránka ReactOS: " IDS_WELCOME_URL "http://www.reactos.org" IDS_INSTALLED "Nainstalováno" - IDS_AVAILABLEFORINST "Dostupné k instalaci" + IDS_AVAILABLEFORINST "Lze instalovat" IDS_UPDATES "Aktualizace" IDS_APPLICATIONS "Aplikace" - IDS_CHOOSE_FOLDER_TEXT "Zvolte složku, do které se budou ukládat stažené soubory:" + IDS_CHOOSE_FOLDER_TEXT "Zvolte složku, do které se budou ukládat stažené soubory: " IDS_CHOOSE_FOLDER_ERROR "Zvolená složka neexistuje. Vytvořit?" IDS_APP_REG_REMOVE "Určitě odstranit data instalovaného programu z registru?" IDS_INFORMATION "Informace" diff --git a/base/applications/rapps/lang/tr-TR.rc b/base/applications/rapps/lang/tr-TR.rc index 7e20c851cb8..bd0a12ffb37 100644 --- a/base/applications/rapps/lang/tr-TR.rc +++ b/base/applications/rapps/lang/tr-TR.rc @@ -165,7 +165,7 @@ BEGIN IDS_CAT_INTERNET "Ağ" IDS_CAT_LIBS "Kitaplıklar" IDS_CAT_OFFICE "Büro" - IDS_CAT_OTHER "Diğer" + IDS_CAT_OTHER "Başka" IDS_CAT_SCIENCE "Bilim" IDS_CAT_TOOLS "Araçlar" IDS_CAT_VIDEO "Vidyo" @@ -188,7 +188,7 @@ BEGIN IDS_APPLICATIONS "Uygulamalar" IDS_CHOOSE_FOLDER_TEXT "İndirilenlerin saklanacağı bir dizin seçiniz:" IDS_CHOOSE_FOLDER_ERROR "Belirttiğiniz dizin yok. Belirttiğiniz dizin oluşturulsun mu?" - IDS_APP_REG_REMOVE "Kurulan izlencenin girişini Değer Defteri'nden silmeyi doğruluyor musunuz?" + IDS_APP_REG_REMOVE "Kurulan izlencenin girişini değer defterinden silmek istemeyi doğruluyor musunuz?" IDS_INFORMATION "Bilgi" - IDS_UNABLE_TO_REMOVE "İzlencenin girişi Değer Defteri'nden silinemiyor." + IDS_UNABLE_TO_REMOVE "İzlencenin girişi değer defterinden silinemiyor." END diff --git a/base/applications/rapps/rapps/abiword.txt b/base/applications/rapps/rapps/abiword.txt index 844f68f59ac..9d6ac792613 100644 --- a/base/applications/rapps/rapps/abiword.txt +++ b/base/applications/rapps/rapps/abiword.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = AbiWord diff --git a/base/applications/rapps/rapps/abiword26.txt b/base/applications/rapps/rapps/abiword26.txt index 0c97d941fbc..0a6ed2a6613 100644 --- a/base/applications/rapps/rapps/abiword26.txt +++ b/base/applications/rapps/rapps/abiword26.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = AbiWord diff --git a/base/applications/rapps/rapps/abyss.txt b/base/applications/rapps/rapps/abyss.txt index 69d4c65955d..7dfbe6ac50f 100644 --- a/base/applications/rapps/rapps/abyss.txt +++ b/base/applications/rapps/rapps/abyss.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Abyss Web server X1 diff --git a/base/applications/rapps/rapps/ac97forvirtualbox.txt b/base/applications/rapps/rapps/ac97forvirtualbox.txt index b760df4ab22..cca6ec4fcf3 100644 --- a/base/applications/rapps/rapps/ac97forvirtualbox.txt +++ b/base/applications/rapps/rapps/ac97forvirtualbox.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = AC97 Driver for VirtualBox @@ -20,6 +20,11 @@ Name = AC97 Treiber für VirtualBox Licence = Unbekannt Description = Entpacken in das "ReactOS"-Verzeichnis und ReactOS zweimal neustarten. +[Section.0410] +Name = Driver AC97 per VirtualBox +License = Sconosciuta +Descrizione = Estrarre nella cartella "ReactOS" e poi riavviare ReactOs due volte. + [Section.040a] Name = Driver AC97 para VirtualBox Licence = Desconocida diff --git a/base/applications/rapps/rapps/alreader.txt b/base/applications/rapps/rapps/alreader.txt index 4dd4561fcff..501ff11ab9c 100644 --- a/base/applications/rapps/rapps/alreader.txt +++ b/base/applications/rapps/rapps/alreader.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = AlReader @@ -13,7 +13,7 @@ CDPath = none Description = Ein FB2 eBook Reader. Unterstützung für folgende Formate: fb2, fbz, txt, epub, html, doc, docx, odt, rtf, mobi, prc (PalmDoc), tcr. ZIP und GZ Archive werden ebenfalls unterstützt. [Section.0410] -Description = Un eBook Reader. +Description = Un eBook Reader. Legge i formati fb2, fbz, txt, epub, html, doc, docx, odt, rtf, mobi, prc (PalmDoc), tcr. Supporta gli archivi ZIP e GZ. [Section.0415] Description = Czytnik eBooków. Obsługuje formaty: fb2, fbz, txt, epub, html, doc, docx, odt, rtf, mobi, prc (PalmDoc), tcr. Obsługiwane są także pliki w archivach ZIP i GZ. diff --git a/base/applications/rapps/rapps/ants.txt b/base/applications/rapps/rapps/ants.txt index 629b5484da0..ac1b79f5468 100644 --- a/base/applications/rapps/rapps/ants.txt +++ b/base/applications/rapps/rapps/ants.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] Name = Ants @@ -14,6 +14,9 @@ CDPath = none [Section.0407] Description = Ein strategisches Kartenspiel. Sie bauen Ihr eigenes Schloss und versuchen, die gegnerische Burg zu zerstören. Sie benötigen ein ZIP-Programm, um es zu installieren. +[Section.0410] +Description = Un gioco di carte strategico. Costruisci il tuo castello e prova a distruggere il castello nemico. Necessita di un programma di estrazione ZIP per essere installato. + [Section.0415] Description = Karciana gra strategiczna. Budujesz zamek, przy okazji próbujesz zniszczyć zamek wroga. Wymaga programu archiwizującego do wypakowania. diff --git a/base/applications/rapps/rapps/audiograbber.txt b/base/applications/rapps/rapps/audiograbber.txt index 6a2d08aebe7..5f59de91cbc 100644 --- a/base/applications/rapps/rapps/audiograbber.txt +++ b/base/applications/rapps/rapps/audiograbber.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Audio Grabber @@ -14,6 +14,9 @@ CDPath = none [Section.0407] Description = Ein sehr guter CD-Ripper/Audio-Datei-Konverter. +[Section.0410] +Description = Un buon CD Ripper/Convertitore di file Audio. + [Section.040a] Description = Un buen CD Ripper/ conversor de archivos de audio. diff --git a/base/applications/rapps/rapps/bittorrent.txt b/base/applications/rapps/rapps/bittorrent.txt index 59fa4fc5ab0..cd600628fdb 100644 --- a/base/applications/rapps/rapps/bittorrent.txt +++ b/base/applications/rapps/rapps/bittorrent.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = BitTorrent diff --git a/base/applications/rapps/rapps/bochs.txt b/base/applications/rapps/rapps/bochs.txt index 4707c75bbca..84094fcd96f 100644 --- a/base/applications/rapps/rapps/bochs.txt +++ b/base/applications/rapps/rapps/bochs.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] @@ -15,6 +15,9 @@ CDPath = none [Section.0407] Description = Bochs ist ein portabler Open-Source IA-32 (x86) PC-Emulator geschrieben in C++, der auf den meisten populären Plattformen läuft. +[Section.0410] +Description = Bochs è un emulatore pc IA-32 (x86) scritto in C++ open source e portatile, che può essere eseguito sulle piattaformi più popolari. + [Section.0415] Description = Bochs to przenośny (portable) emulator platformy IA-32 (x86) napisany w C++, działa na wielu popularnych platformach sprzętowych. diff --git a/base/applications/rapps/rapps/boswars.txt b/base/applications/rapps/rapps/boswars.txt index dd3435ea7aa..58e7b36c1fc 100644 --- a/base/applications/rapps/rapps/boswars.txt +++ b/base/applications/rapps/rapps/boswars.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] diff --git a/base/applications/rapps/rapps/boundaround.txt b/base/applications/rapps/rapps/boundaround.txt index 6c50c4304cf..ef5adb3a1c7 100644 --- a/base/applications/rapps/rapps/boundaround.txt +++ b/base/applications/rapps/rapps/boundaround.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Bound Around (Demo) @@ -13,6 +13,10 @@ CDPath = none [Section.0407] Description = Ein Spiel, ähnlich zu Frozen Fruits. +[Section.0410] +Name = Bound Around (Versione di prova) +Description = Un gioco simile a Frozen Fruits. + [Section.041f] Name = Bound Around (Göstermelik) Licence = Kısıtlı diff --git a/base/applications/rapps/rapps/christmasbound.txt b/base/applications/rapps/rapps/christmasbound.txt index dac37a48392..4b6798c2077 100644 --- a/base/applications/rapps/rapps/christmasbound.txt +++ b/base/applications/rapps/rapps/christmasbound.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Christmas Bound @@ -14,6 +14,9 @@ CDPath = none [Section.0407] Description = Ein Spiel, ähnlich zu Frozen Fruits. +[Section.0410] +Description = Un gioco simile a Frozen Fuits. + [Section.041f] Licence = Ücretsiz Description = Frozen Fruits'e benzeyen bir oyun. diff --git a/base/applications/rapps/rapps/chromium.txt b/base/applications/rapps/rapps/chromium.txt index 1ebd82226a8..693a5884d5b 100644 --- a/base/applications/rapps/rapps/chromium.txt +++ b/base/applications/rapps/rapps/chromium.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] Name = Chromium B.S.U. diff --git a/base/applications/rapps/rapps/cnt.txt b/base/applications/rapps/rapps/cnt.txt index cb13c1f8b51..07fdc789ead 100644 --- a/base/applications/rapps/rapps/cnt.txt +++ b/base/applications/rapps/rapps/cnt.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Click-N-Type Virtual Keyboard diff --git a/base/applications/rapps/rapps/codeblocks.txt b/base/applications/rapps/rapps/codeblocks.txt index a21ed29d735..ac2172c1b83 100644 --- a/base/applications/rapps/rapps/codeblocks.txt +++ b/base/applications/rapps/rapps/codeblocks.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Code::Blocks (no compiler) @@ -14,6 +14,9 @@ CDPath = none [Section.0407] Description = Eine quelloffene, plattformübergreifende, mächtige IDE. Diese enthält keinen Compiler. +[Section.0410] +Description = Un IDE potente, open source, multipiattaforma. Non contiene un compilatore. + [Section.041f] Name = Code::Blocks (Derleyicisiz) Description = Açık kaynak, çapraz platform, güçlü bir tümleşik geliştirme ortamı. Bir derleyici içermez. diff --git a/base/applications/rapps/rapps/codeblocks_gcc.txt b/base/applications/rapps/rapps/codeblocks_gcc.txt index 8f0f87d8367..654057867bf 100644 --- a/base/applications/rapps/rapps/codeblocks_gcc.txt +++ b/base/applications/rapps/rapps/codeblocks_gcc.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Code::Blocks TDM-GCC (version 4.7.1, 32 bit) @@ -14,6 +14,9 @@ CDPath = none [Section.0407] Description = Eine quelloffene, plattformübergreifende, mächtige IDE. Diese enthält den TDM-GCC (version 4.7.1, 32 bit) Compiler. +[Section.0410] +Description = Un IDE potente, open source, multipiattaforma. Contiene il compilatore TDM-GCC (versione 4.7.1, 32 bit). + [Section.041f] Name = Code::Blocks TDM-GCC (sürüm 4.7.1, 32 bitlik) Description = Açık kaynak, çapraz platform, güçlü bir tümleşik geliştirme ortamı. TDM-GCC (sürüm 4.7.1, 32 bitlik) derleyicisini içerir. diff --git a/base/applications/rapps/rapps/codeblocks_gcc_2.txt b/base/applications/rapps/rapps/codeblocks_gcc_2.txt index 20e15bf5dff..e8fadd4c305 100644 --- a/base/applications/rapps/rapps/codeblocks_gcc_2.txt +++ b/base/applications/rapps/rapps/codeblocks_gcc_2.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Code::Blocks TDM-GCC (version 4.8.1, 32 bit) @@ -14,6 +14,9 @@ CDPath = none [Section.0407] Description = Eine quelloffene, plattformübergreifende, mächtige IDE. Diese enthät den TDM-GCC (version 4.8.1, 32 bit) Compiler. +[Section.0410] +Description = Un IDE potente, open source, multipiattaforma. Contiene il compilatore TDM-GCC (versione 4.8.1, 32 bit). + [Section.041f] Name = Code::Blocks TDM-GCC (sürüm 4.8.1, 32 bitlik) Description = Açık kaynak, çapraz platform, güçlü bir tümleşik geliştirme ortamı. TDM-GCC (sürüm 4.8.1, 32 bitlik) derleyicisini içerir. diff --git a/base/applications/rapps/rapps/comctl32ocx.txt b/base/applications/rapps/rapps/comctl32ocx.txt index b9f10def161..b9ea0fd0d71 100644 --- a/base/applications/rapps/rapps/comctl32ocx.txt +++ b/base/applications/rapps/rapps/comctl32ocx.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Microsoft Visual Basic 6.0 Common Controls diff --git a/base/applications/rapps/rapps/devcpp_mingw32.txt b/base/applications/rapps/rapps/devcpp_mingw32.txt index de51e041100..0db353c927c 100644 --- a/base/applications/rapps/rapps/devcpp_mingw32.txt +++ b/base/applications/rapps/rapps/devcpp_mingw32.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Orwell Dev-C++ MinGW32 @@ -14,6 +14,9 @@ CDPath = none [Section.0407] Description = Eine gepflegte Version von Dev-C++. Der MinGW32 Compiler liegt bei. +[Section.0410] +Description = Una versione mantenuta di Dev-C++. Contiene il compilatore MinGW32. + [Section.041f] Description = Dev-C++'nın sürdürülen bir sürümü. MinGW32 derleyicisini içerir. Size = 60,2 MB diff --git a/base/applications/rapps/rapps/devcpp_tdm_gcc_x64.txt b/base/applications/rapps/rapps/devcpp_tdm_gcc_x64.txt index 2761f212b10..f0f490d16e1 100644 --- a/base/applications/rapps/rapps/devcpp_tdm_gcc_x64.txt +++ b/base/applications/rapps/rapps/devcpp_tdm_gcc_x64.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Orwell Dev-C++ TDM GCC x64 @@ -14,6 +14,9 @@ CDPath = none [Section.0407] Description = Eine gepflegte Version von Dev-C++. Der 64 bit TDM-GCC Compiler liegt bei. +[Section.0410] +Description = Una versione sostenuta di Dev-C++. Contiene il compilatore a 64bit TDM-GCC. + [Section.041f] Description = Dev-C++'nın sürdürülen bir sürümü. 64 bitlik TDM-GCC derleyicisini içerir. Size = 44,8 MB diff --git a/base/applications/rapps/rapps/diablo2.txt b/base/applications/rapps/rapps/diablo2.txt index c266f55b2f3..5079c79e3bb 100644 --- a/base/applications/rapps/rapps/diablo2.txt +++ b/base/applications/rapps/rapps/diablo2.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Diablo II diff --git a/base/applications/rapps/rapps/dosblaster.txt b/base/applications/rapps/rapps/dosblaster.txt index 51bb21dfbab..03325b677dc 100644 --- a/base/applications/rapps/rapps/dosblaster.txt +++ b/base/applications/rapps/rapps/dosblaster.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = DosBlaster diff --git a/base/applications/rapps/rapps/dosbox.txt b/base/applications/rapps/rapps/dosbox.txt index 9c5e275c5a1..f38620fa1d4 100644 --- a/base/applications/rapps/rapps/dosbox.txt +++ b/base/applications/rapps/rapps/dosbox.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = DOSBox diff --git a/base/applications/rapps/rapps/doublecommander.txt b/base/applications/rapps/rapps/doublecommander.txt index 422148d8700..8a8975d8b63 100644 --- a/base/applications/rapps/rapps/doublecommander.txt +++ b/base/applications/rapps/rapps/doublecommander.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Double Commander diff --git a/base/applications/rapps/rapps/dplus.txt b/base/applications/rapps/rapps/dplus.txt new file mode 100644 index 00000000000..2a54a7e534d --- /dev/null +++ b/base/applications/rapps/rapps/dplus.txt @@ -0,0 +1,22 @@ +; UTF-8 + +[Section] +Name = D+ Browser +Version = 0.5b +Licence = GPLv3 +Description = DPlus is a graphical web browser with an emphasis on security, performance and portability. It is based on Dillo and it is forked from Dillo-Win32 project. +Size = 1.36 MB +Category = 5 +URLSite = http://dplus-browser.sourceforge.net/ +URLDownload = http://heanet.dl.sourceforge.net/project/dplus-browser/Releases/dplus-0.5b/dplus-0.5b-setup.exe +CDPath = none + +[Section.0410] +License = GPL versione 3 +Description = DPlus è un web browser grafico con un accenno alla sicurezza, le prestazioni e portabilità. è basata su Dillo ed è diviso dal progetto Dillo-Win32. + +[Section.041f] +Name = D+ Tarayıcı +Licence = GPL 3. sürüm +Description = DPlus; güvenlik, başarım ve taşınabilirlik üzerine bir vurguyla, çizgelik bir Umûmî Ağ tarayıcısıdır. Dillo tabanlıdır ve Dillo-Win32 tasarısından çatallanmıştır. +Size = 1,36 MB diff --git a/base/applications/rapps/rapps/dvdwritenow.txt b/base/applications/rapps/rapps/dvdwritenow.txt index c403f526041..d2ff1961b56 100644 --- a/base/applications/rapps/rapps/dvdwritenow.txt +++ b/base/applications/rapps/rapps/dvdwritenow.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] Name = DVD Write Now diff --git a/base/applications/rapps/rapps/excelview.txt b/base/applications/rapps/rapps/excelview.txt index 653e7d0bd0a..35e433d000a 100644 --- a/base/applications/rapps/rapps/excelview.txt +++ b/base/applications/rapps/rapps/excelview.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Microsoft Excel Viewer diff --git a/base/applications/rapps/rapps/fap.txt b/base/applications/rapps/rapps/fap.txt index 0c4631a7d29..49903520e58 100644 --- a/base/applications/rapps/rapps/fap.txt +++ b/base/applications/rapps/rapps/fap.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Fox Audio Player diff --git a/base/applications/rapps/rapps/fira.txt b/base/applications/rapps/rapps/fira.txt index b27dee4a663..30373c7a033 100644 --- a/base/applications/rapps/rapps/fira.txt +++ b/base/applications/rapps/rapps/fira.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] @@ -16,6 +16,10 @@ CDPath = none Licence = Unbekannt Description = Mozilla Fira Font Pack, Beinhaltet Mono und Sans Schriften. Bitte in den "ReactOS" Ordner entpacken. +[Section.0410] +Licence = Sconosciuta +Description = Fira Font Pack di Mozilla, Include i font Mono e Sans. Estrare nella cartella "ReactOS". + [Section.0415] Description = Pakiet czcionek Mozilla Fira Font, zawiera czcionki Mono i Sans. Wypakuj do folderu "ReactOS". Licence = Nieznana diff --git a/base/applications/rapps/rapps/firefox.txt b/base/applications/rapps/rapps/firefox.txt index 89df72c9dcf..038cfe10183 100644 --- a/base/applications/rapps/rapps/firefox.txt +++ b/base/applications/rapps/rapps/firefox.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Mozilla Firefox 28 diff --git a/base/applications/rapps/rapps/firefox2.txt b/base/applications/rapps/rapps/firefox2.txt index 141348b7ca6..ae699823393 100644 --- a/base/applications/rapps/rapps/firefox2.txt +++ b/base/applications/rapps/rapps/firefox2.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Mozilla Firefox 2.0 diff --git a/base/applications/rapps/rapps/firefox3.txt b/base/applications/rapps/rapps/firefox3.txt index 94770847870..e7032cbc1ae 100644 --- a/base/applications/rapps/rapps/firefox3.txt +++ b/base/applications/rapps/rapps/firefox3.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Mozilla Firefox 3.0 diff --git a/base/applications/rapps/rapps/firefox36.txt b/base/applications/rapps/rapps/firefox36.txt index 74af5cb753d..4046e9f1109 100644 --- a/base/applications/rapps/rapps/firefox36.txt +++ b/base/applications/rapps/rapps/firefox36.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Mozilla Firefox 3.6 diff --git a/base/applications/rapps/rapps/freebasic.txt b/base/applications/rapps/rapps/freebasic.txt index bf5a22cdaad..1a40490443a 100644 --- a/base/applications/rapps/rapps/freebasic.txt +++ b/base/applications/rapps/rapps/freebasic.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = FreeBASIC diff --git a/base/applications/rapps/rapps/glidewrapzbag.txt b/base/applications/rapps/rapps/glidewrapzbag.txt index 803f7fbf18e..8d100209291 100644 --- a/base/applications/rapps/rapps/glidewrapzbag.txt +++ b/base/applications/rapps/rapps/glidewrapzbag.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = GlidewrapZbag diff --git a/base/applications/rapps/rapps/globulation2.txt b/base/applications/rapps/rapps/globulation2.txt index 4ecca2c89ca..22747acc973 100644 --- a/base/applications/rapps/rapps/globulation2.txt +++ b/base/applications/rapps/rapps/globulation2.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] Name = Globulation2 @@ -15,7 +15,7 @@ CDPath = none Description = Globulation 2 ist ein Echtzeitstrategiespiel. Das Spiel vereinfacht das Mikromanagement, indem es Einheiten automatisch mit Aufträgen versieht. [Section.0410] -Description = Globulation 2 è un gioco di strategia in tempo reale. +Description = Globulation 2 è un gioco di strategia in tempo reale. Il gioco minimizza la supervisone eccessiva assegnando in automatico compiti alle unità. [Section.0415] Description = Globulation 2 to gra strategiczna czasu rzeczywistego. Gra minimalizuje zarządzanie automatycznie przydzielając zadania jednostkom. diff --git a/base/applications/rapps/rapps/hover.txt b/base/applications/rapps/rapps/hover.txt index d2048ceb54e..a43dd0e119c 100644 --- a/base/applications/rapps/rapps/hover.txt +++ b/base/applications/rapps/rapps/hover.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] diff --git a/base/applications/rapps/rapps/hxd.txt b/base/applications/rapps/rapps/hxd.txt index 9e54d7a5c43..0faa3bbe870 100644 --- a/base/applications/rapps/rapps/hxd.txt +++ b/base/applications/rapps/rapps/hxd.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] @@ -21,6 +21,9 @@ URLDownload = http://mh-nexus.de/downloads/HxDSetupDE.zip [Section.0415] Description = Dobry edytor Hex. Do wypakowania pliku potrzebny jest program archiwizujący np. 7-Zip. +[Section.0410] +Description = Un buon editor hexadecimale. Necessita 7-Zip o un programma simile per estrarlo. + [Section.0418] Licence = Gratuită Description = Un bun editor hexazecimal. E necesar un utilitar de dezarhivare de tip ZIP. diff --git a/base/applications/rapps/rapps/indiftpd.txt b/base/applications/rapps/rapps/indiftpd.txt index 2f71b9a9570..1f146cb8d44 100644 --- a/base/applications/rapps/rapps/indiftpd.txt +++ b/base/applications/rapps/rapps/indiftpd.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] diff --git a/base/applications/rapps/rapps/irfanview.txt b/base/applications/rapps/rapps/irfanview.txt index 0d89c199e16..698ce46dfa8 100644 --- a/base/applications/rapps/rapps/irfanview.txt +++ b/base/applications/rapps/rapps/irfanview.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = IrfanView diff --git a/base/applications/rapps/rapps/irfanviewplugins.txt b/base/applications/rapps/rapps/irfanviewplugins.txt index 7ba442e2c50..54285b9d5e7 100644 --- a/base/applications/rapps/rapps/irfanviewplugins.txt +++ b/base/applications/rapps/rapps/irfanviewplugins.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = IrfanView Plugins diff --git a/base/applications/rapps/rapps/kdewin.txt b/base/applications/rapps/rapps/kdewin.txt index c78c757f65e..ca9bbe5485e 100644 --- a/base/applications/rapps/rapps/kdewin.txt +++ b/base/applications/rapps/rapps/kdewin.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = K Desktop Environment diff --git a/base/applications/rapps/rapps/kyodai.txt b/base/applications/rapps/rapps/kyodai.txt index 9b205d52dab..2e5e11235cc 100644 --- a/base/applications/rapps/rapps/kyodai.txt +++ b/base/applications/rapps/rapps/kyodai.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] Name = Kyodai Mahjongg diff --git a/base/applications/rapps/rapps/lazaruside.txt b/base/applications/rapps/rapps/lazaruside.txt index 903f58b2e73..10395af40ae 100644 --- a/base/applications/rapps/rapps/lazaruside.txt +++ b/base/applications/rapps/rapps/lazaruside.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] diff --git a/base/applications/rapps/rapps/lbreakout2.txt b/base/applications/rapps/rapps/lbreakout2.txt index 19c6e54d935..6f1aec180d8 100644 --- a/base/applications/rapps/rapps/lbreakout2.txt +++ b/base/applications/rapps/rapps/lbreakout2.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = LBreakout2 @@ -22,7 +22,7 @@ Description = Clone de casse-brique utilisant la bibliothèque SDL. Size = 3,03 Mo [Section.0410] -Description = Clone di Breakout utilizza librerie SDL. +Description = Clone di Breakout che utilizza librerie SDL. [Section.0413] Description = Breakout kloon, gebruikt SDL. diff --git a/base/applications/rapps/rapps/lgeneral.txt b/base/applications/rapps/rapps/lgeneral.txt index 6b25b9112cc..e70dc80e590 100644 --- a/base/applications/rapps/rapps/lgeneral.txt +++ b/base/applications/rapps/rapps/lgeneral.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = LGeneral @@ -22,7 +22,7 @@ Description = Clone de Pansez General utilisant la bibliothèque SDL. Size = 1,92 Mo [Section.0410] -Description = Clone di Pansez General utilizza librerie SDL. +Description = Clone di Pansez General che utilizza librerie SDL. [Section.0413] Description = Panzer General kloon, gebruikt SDL. diff --git a/base/applications/rapps/rapps/libreoffice.txt b/base/applications/rapps/rapps/libreoffice.txt index 605e24e9b85..d3d2c50487c 100644 --- a/base/applications/rapps/rapps/libreoffice.txt +++ b/base/applications/rapps/rapps/libreoffice.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = LibreOffice diff --git a/base/applications/rapps/rapps/lmarbles.txt b/base/applications/rapps/rapps/lmarbles.txt index be06d7c1c91..dac8e7a76f4 100644 --- a/base/applications/rapps/rapps/lmarbles.txt +++ b/base/applications/rapps/rapps/lmarbles.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = LMarbles @@ -22,7 +22,7 @@ Description = Clone de Atomix utilisant la bibliothèque SDL. Size = 1,39 Mo [Section.0410] -Description = Clone di Atomix utilizza le librerie SDL. +Description = Clone di Atomix che utilizza le librerie SDL. [Section.0413] Description = Atomix kloon, gebruikt SDL. diff --git a/base/applications/rapps/rapps/mcwin32.txt b/base/applications/rapps/rapps/mcwin32.txt new file mode 100644 index 00000000000..a77b674e709 --- /dev/null +++ b/base/applications/rapps/rapps/mcwin32.txt @@ -0,0 +1,32 @@ +; UTF-8 + +[Section] +Name = Midnight Commander for Windows +Version = Build 183 (4.8.11) +Licence = GPLv3 +Description = 32-bit Windows port of GNU Midnight Commander. +Size = 2.35 MB +Category = 12 +URLSite = http://sourceforge.net/projects/mcwin32/ +URLDownload = http://optimate.dl.sourceforge.net/project/mcwin32/mcwin32-build183-setup.exe +CDPath = none + +[Section.0410] +Name = Midnight Commander per Windows +Version = Revisione 183 (4.8.11) +Licence = GPL versione 3 +Description = Un porting Windows 32bit di Midnight Commander. + +[Section.041f] +Name = Midnight Commander (Windows için) +Version = Yapı 183 (4.8.11) +Licence = GPL 3. sürüm +Description = GNU Midnight Commander'ın 32 bitlik Windows uyarlamasıdır. +Size = 2,35 MB + +[Section.0415] +Name = Midnight Commander dla Windows +Version = Build 183 (4.8.11) +Licence = GPL wersja 3 +Description = 32-bitowy port GNU Midnight Commander dla Windows. +Size = 2,35 MB diff --git a/base/applications/rapps/rapps/mfc40.txt b/base/applications/rapps/rapps/mfc40.txt index fc79d4f1828..e4e1a5bac04 100644 --- a/base/applications/rapps/rapps/mfc40.txt +++ b/base/applications/rapps/rapps/mfc40.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = OLE Viewer and Microsoft Foundation Classes version 4 diff --git a/base/applications/rapps/rapps/mirandaim.txt b/base/applications/rapps/rapps/mirandaim.txt index 3205655075f..51fdc5fa987 100644 --- a/base/applications/rapps/rapps/mirandaim.txt +++ b/base/applications/rapps/rapps/mirandaim.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Miranda IM diff --git a/base/applications/rapps/rapps/mirc.txt b/base/applications/rapps/rapps/mirc.txt index 68e24783903..7bbfff1e58a 100644 --- a/base/applications/rapps/rapps/mirc.txt +++ b/base/applications/rapps/rapps/mirc.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = mIRC 7 diff --git a/base/applications/rapps/rapps/mirc6.txt b/base/applications/rapps/rapps/mirc6.txt index 874ba2a2705..3f90e2bde66 100644 --- a/base/applications/rapps/rapps/mirc6.txt +++ b/base/applications/rapps/rapps/mirc6.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = mIRC 6 diff --git a/base/applications/rapps/rapps/mono2.txt b/base/applications/rapps/rapps/mono2.txt index b0112acfa8f..1bb628fc439 100644 --- a/base/applications/rapps/rapps/mono2.txt +++ b/base/applications/rapps/rapps/mono2.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Mono .net Development Framework diff --git a/base/applications/rapps/rapps/mpc.txt b/base/applications/rapps/rapps/mpc.txt index 0184f79f16d..5958f33126f 100644 --- a/base/applications/rapps/rapps/mpc.txt +++ b/base/applications/rapps/rapps/mpc.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Media Player Classic Home Cinema diff --git a/base/applications/rapps/rapps/mpxplay.txt b/base/applications/rapps/rapps/mpxplay.txt index 6246d0a89d4..9b2cebfdc4c 100644 --- a/base/applications/rapps/rapps/mpxplay.txt +++ b/base/applications/rapps/rapps/mpxplay.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] Name = Mpxplay @@ -14,6 +14,9 @@ CDPath = none [Section.0407] Description = Mpxplay ist ein konsolenbasierter 32-bit Audio Player für Windows. Zum extrahieren wird 7-Zip oder ein ähnliches Tool benötigt. +[Section.0410] +Description = Mpxplay è una console audio 32-bit per Windows. Necessita 7-Zip o un programma simile per essere estratto. + [Section.0415] Description = Mpxplay to 32 bitowy odtwarzacz audio (działający w konsoli) dla Windows. Wymaga programu archiwizującego (np. 7-Zip) do wypakowania. diff --git a/base/applications/rapps/rapps/msxml3.txt b/base/applications/rapps/rapps/msxml3.txt index c7c3cbc3bf6..5945a66a013 100644 --- a/base/applications/rapps/rapps/msxml3.txt +++ b/base/applications/rapps/rapps/msxml3.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Microsoft XML 3 diff --git a/base/applications/rapps/rapps/net11.txt b/base/applications/rapps/rapps/net11.txt index 34eadb61190..e7f7d59ca34 100644 --- a/base/applications/rapps/rapps/net11.txt +++ b/base/applications/rapps/rapps/net11.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Microsoft .NET Framework Version 1.1 Redistributable Package diff --git a/base/applications/rapps/rapps/net20.txt b/base/applications/rapps/rapps/net20.txt index 1a3dd4ce86d..7827168b10c 100644 --- a/base/applications/rapps/rapps/net20.txt +++ b/base/applications/rapps/rapps/net20.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Microsoft .NET Framework Version 2.0 Redistributable Package diff --git a/base/applications/rapps/rapps/net20sp2.txt b/base/applications/rapps/rapps/net20sp2.txt index a6a18a44962..cb285f88c61 100644 --- a/base/applications/rapps/rapps/net20sp2.txt +++ b/base/applications/rapps/rapps/net20sp2.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Microsoft .NET Framework Version 2.0 Service Pack 2 diff --git a/base/applications/rapps/rapps/npp.txt b/base/applications/rapps/rapps/npp.txt index 50b7a72e64c..31009edec5b 100644 --- a/base/applications/rapps/rapps/npp.txt +++ b/base/applications/rapps/rapps/npp.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Notepad++ diff --git a/base/applications/rapps/rapps/offbyone.txt b/base/applications/rapps/rapps/offbyone.txt index e25a216d5bc..7d85199b6e8 100644 --- a/base/applications/rapps/rapps/offbyone.txt +++ b/base/applications/rapps/rapps/offbyone.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Off By One Browser diff --git a/base/applications/rapps/rapps/opencodecs.txt b/base/applications/rapps/rapps/opencodecs.txt index 9dbb401462d..514944e9d2f 100644 --- a/base/applications/rapps/rapps/opencodecs.txt +++ b/base/applications/rapps/rapps/opencodecs.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL trans by wojo664 [Section] diff --git a/base/applications/rapps/rapps/openoffice.txt b/base/applications/rapps/rapps/openoffice.txt index 63ae76581f4..fd27224897a 100644 --- a/base/applications/rapps/rapps/openoffice.txt +++ b/base/applications/rapps/rapps/openoffice.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = OpenOffice 4.0 @@ -30,6 +30,7 @@ Size = 127,22 Mo URLDownload = http://download.sourceforge.net/project/openofficeorg.mirror/4.0.1/binaries/fr/Apache_OpenOffice_4.0.1_Win_x86_install_fr.exe [Section.0410] +Description = La suite di office Open Source. URLSite = http://www.openoffice.org/it/ Size = 132.39 MB URLDownload = http://download.sourceforge.net/project/openofficeorg.mirror/4.0.1/binaries/it/Apache_OpenOffice_4.0.1_Win_x86_install_it.exe diff --git a/base/applications/rapps/rapps/openoffice2.4.txt b/base/applications/rapps/rapps/openoffice2.4.txt index 2021f27d423..4ea78aa2fe0 100644 --- a/base/applications/rapps/rapps/openoffice2.4.txt +++ b/base/applications/rapps/rapps/openoffice2.4.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = OpenOffice 2.4 @@ -31,6 +31,7 @@ URLSite = http://www.openoffice.org/fr/ URLDownload = http://archive.services.openoffice.org/pub/openoffice-archive/localized/fr/2.4.2/OOo_2.4.2_Win32Intel_install_fr.exe [Section.0410] +Description = La suite di office Open Source. Size = 113.79 MB URLSite = http://www.openoffice.org/it/ URLDownload = http://archive.services.openoffice.org/pub/openoffice-archive/localized/it/2.4.3/OOo_2.4.3_Win32Intel_install_it.exe diff --git a/base/applications/rapps/rapps/openttd.txt b/base/applications/rapps/rapps/openttd.txt index cca8069cf2a..f48893de4ca 100644 --- a/base/applications/rapps/rapps/openttd.txt +++ b/base/applications/rapps/rapps/openttd.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = OpenTTD @@ -22,7 +22,7 @@ Description = Clone open source du moteur de jeu "Transport Tycoon Deluxe". Vous Size = 7,0 Mo [Section.0410] -Description = Clone open source del motore di gioco di "Transport Tycoon Deluxe". Hai bisogno di una copia di Transport Tycoon. +Description = Clone open source del motore di gioco di "Transport Tycoon Deluxe". Hai bisogno di una copia di Transport Tycoon. [Section.0413] Description = Open-bron kloon van de "Transport Tycoon Deluxe" spelletjesmotor. Je hebt een kopij van Transport Tycoon nodig. diff --git a/base/applications/rapps/rapps/opera.txt b/base/applications/rapps/rapps/opera.txt index c31b64d2130..8ce86d78d87 100644 --- a/base/applications/rapps/rapps/opera.txt +++ b/base/applications/rapps/rapps/opera.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Opera @@ -25,7 +25,7 @@ Description = Le populaire navigateur Opera avec beaucoup de fonctionnalités av Size = 12,56 Mo [Section.0410] -Description = Il famoso browser Opera con features avanzate come un client BitTorrent integrato e la gestione delle Mail. +Description = Il famoso browser Opera con funzionalità avanzate come un client BitTorrent integrato e la gestione delle Mail. [Section.0413] Description = De populaire Opera Browser met vele gevorderde mogelijkheden, inclusief e-mail en BitTorrent afnemers. diff --git a/base/applications/rapps/rapps/opera9.txt b/base/applications/rapps/rapps/opera9.txt index 4378e545246..c118ee1aa5e 100644 --- a/base/applications/rapps/rapps/opera9.txt +++ b/base/applications/rapps/rapps/opera9.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Opera @@ -22,7 +22,7 @@ Description = Le populaire navigateur Opera avec beaucoup de fonctionnalités av Size = 7,21 Mo [Section.0410] -Description = Il famoso browser Opera con features avanzate come un client BitTorrent integrato e la gestione delle Mail. +Description = Il famoso browser Opera con funzionalità avanzate come un client BitTorrent integrato e la gestione delle Mail. [Section.0413] Description = De populaire Opera Browser met vele gevorderde mogelijkheden, inclusief e-mail en BitTorrent afnemers. diff --git a/base/applications/rapps/rapps/peazip.txt b/base/applications/rapps/rapps/peazip.txt index 52857bd448c..7a6def37c03 100644 --- a/base/applications/rapps/rapps/peazip.txt +++ b/base/applications/rapps/rapps/peazip.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = PeaZip @@ -14,6 +14,12 @@ CDPath = none [Section.0407] Description = PeaZip ist ein freier, plattformübergreifender, quelloffener Datei- und Archivmanager. Er unterstützt über 150 Archiv-Formate. +[Section.0410] +Description = PeaZip è un manager di file e archivi gratis, multipiattaforma e open source. Supporta oltre 150 formati d'archivio. + +[Section.0415] +PeaZip to darmowy, wieloplatformowy menedżer plików i archiwów, o otwartym źródle. Obsługuje ponad 150 formatów archiwów. + [Section.041f] Description = PeaZip; ücretsiz, çapraz platform, açık kaynak bir kütük ve belgelik yöneticisidir. 150'den çok belgelikleme biçimini destekler. Size = 5,8 MB diff --git a/base/applications/rapps/rapps/pengupop.txt b/base/applications/rapps/rapps/pengupop.txt index 9804859b834..b66cffdd33c 100644 --- a/base/applications/rapps/rapps/pengupop.txt +++ b/base/applications/rapps/rapps/pengupop.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] Name = Pengupop diff --git a/base/applications/rapps/rapps/photofiltre.txt b/base/applications/rapps/rapps/photofiltre.txt index 174a39674e8..eac3f5edfde 100644 --- a/base/applications/rapps/rapps/photofiltre.txt +++ b/base/applications/rapps/rapps/photofiltre.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] @@ -18,6 +18,9 @@ Description = Version mit Layers, aber eingeschänkter als die Studio-X Version. [Section.0415] Description = Ta wersja obsługuje warstwy, ale ma większe ograniczenia od Studio X. PhotoFiltre Studio to program do retuszu zdjęć. +[Section.0410] +Description = Questa versione con pannelli ma più limitata della versione Studio X. PhotoFiltre Studio è un programma di fotoritocco completo. + [Section.0418] Licence = Gratuită Description = PhotoFiltre Studio este o aplicație completă de retușare a imaginilor. diff --git a/base/applications/rapps/rapps/pingus.txt b/base/applications/rapps/rapps/pingus.txt index 6e4208a9162..2497dae2553 100644 --- a/base/applications/rapps/rapps/pingus.txt +++ b/base/applications/rapps/rapps/pingus.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] diff --git a/base/applications/rapps/rapps/pptview.txt b/base/applications/rapps/rapps/pptview.txt index b5a4988c98f..bab9cb16534 100644 --- a/base/applications/rapps/rapps/pptview.txt +++ b/base/applications/rapps/rapps/pptview.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Microsoft Powerpoint Viewer diff --git a/base/applications/rapps/rapps/pspad.txt b/base/applications/rapps/rapps/pspad.txt index 1f02aa24c28..9ab8c664c38 100644 --- a/base/applications/rapps/rapps/pspad.txt +++ b/base/applications/rapps/rapps/pspad.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] diff --git a/base/applications/rapps/rapps/ptanks.txt b/base/applications/rapps/rapps/ptanks.txt index 220317a01fa..4af55891617 100644 --- a/base/applications/rapps/rapps/ptanks.txt +++ b/base/applications/rapps/rapps/ptanks.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] @@ -15,6 +15,9 @@ CDPath = none [Section.0407] Description = Das schnellste Artillerie-Spiel, das Sie jemals gespielt haben. +[Section.0410] +Description = Il gioco d'artiglieria più veloce a cui potrai giocare. + [Section.0415] Description = Szybka gra artyleryjska diff --git a/base/applications/rapps/rapps/putty.txt b/base/applications/rapps/rapps/putty.txt index 7284a2e2fbf..5902e63a6ef 100644 --- a/base/applications/rapps/rapps/putty.txt +++ b/base/applications/rapps/rapps/putty.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = PuTTY diff --git a/base/applications/rapps/rapps/python.txt b/base/applications/rapps/rapps/python.txt index 16418b4813b..93e3253980b 100644 --- a/base/applications/rapps/rapps/python.txt +++ b/base/applications/rapps/rapps/python.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Python 3 diff --git a/base/applications/rapps/rapps/python2.txt b/base/applications/rapps/rapps/python2.txt index fd9eeea1a36..049cc5b5172 100644 --- a/base/applications/rapps/rapps/python2.txt +++ b/base/applications/rapps/rapps/python2.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Python 2 diff --git a/base/applications/rapps/rapps/qb64sdl.txt b/base/applications/rapps/rapps/qb64sdl.txt index ef97238df67..75be16553e3 100644 --- a/base/applications/rapps/rapps/qb64sdl.txt +++ b/base/applications/rapps/rapps/qb64sdl.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] Name = QB64 (SDL version) @@ -14,6 +14,9 @@ CDPath = none [Section.0407] Description = QB64 ist ein Self-Hosting BASIC-Compiler für Microsoft Windows, Linux und Mac OS X, entwickelt, um mit Microsoft QBasic und Microsoft QuickBASIC kompatibel zu sein. Sie müssen 7-Zip oder ein ähnliches Dienstprogramm installiert haben, um es zu extrahieren. +[Section.0410] +Description = QB64 è un compilatore auto ospitante per Microsoft Windows, Linux e Mac OS X, progettato per essere compatibile con Microsoft QuickBasic. Necessita di 7-Zip o uno strumento simile per essere estratto. + [Section.0415] Description = QB64 to kompilator BASIC zdolny do kompilacji własnego kodu źródłowego. Działa w systemach Windows, Linux i Mac OS X. Jest kompatybilny z Microsoft QBasic i QuickBASIC. Wymaga programu archiwizującego do wypakowania. diff --git a/base/applications/rapps/rapps/qmmp.txt b/base/applications/rapps/rapps/qmmp.txt index a666c7261c6..96bba2adfc7 100644 --- a/base/applications/rapps/rapps/qmmp.txt +++ b/base/applications/rapps/rapps/qmmp.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] @@ -15,6 +15,9 @@ CDPath = none [Section.0407] Description = Qmmp ist ein Audio-Player, der mit Hilfe der Qt Bibliothek geschrieben wurde. Die Benutzeroberfläche ist ähnlich zu WinAMP oder XMMS. Alternative Benutzeroberflächen sind ebenfalls verfügbar. +[Section.0410] +Description = Qmmp è un lettore multimediale, scritto con l'aiuto della libreria Qt. L'interfaccia grafica è simile a WinAMP o XMMS. Interfaccie utenti alternative sono disponibili. + [Section.0415] Description = Gmmp to odtwarzacz audio, napisany z pomocą biblioteki Qt. Interfejs podobny jest do Winampa lub XMMS. Dostępnme są także dodatkowe skórki. diff --git a/base/applications/rapps/rapps/remood.txt b/base/applications/rapps/rapps/remood.txt index 8a5f1d530d1..0b2053c5427 100644 --- a/base/applications/rapps/rapps/remood.txt +++ b/base/applications/rapps/rapps/remood.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = ReMooD @@ -14,6 +14,9 @@ CDPath = none [Section.0407] Description = ReMooD ist ein Port des Doom Legacy Sources. Es versucht das klassische Legacy Erfahrung zusammen mit neuen Features und mehr Stabilität zu bieten. +[Section.0410] +Description = ReMooD è un porting sorgente di Doom Legacy. Punta a provedere la classica esperienza ereditaria con nuove funzionalità e maggiore stabilità. + [Section.040a] Description = ReMood es un port de Doom Legacy. Su fin es proporcionar la clásica experiencia anterior con nuevas características y mayor estabilidad. diff --git a/base/applications/rapps/rapps/reshack.txt b/base/applications/rapps/rapps/reshack.txt index 18e22d6455c..02fdce2faa2 100644 --- a/base/applications/rapps/rapps/reshack.txt +++ b/base/applications/rapps/rapps/reshack.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] @@ -15,6 +15,9 @@ CDPath = none [Section.0407] Description = Resource Hacker ist ein Freeware-Tool zum anzeigen, ändern, umbenennen, hinzufügen, löschen und extrahieren von Ressourcen in 32-Bit & 64-Bit-Windows Anwendungen und Ressourcen-Dateien (*. Res). +[Section.0410] +Description = Resource Hacker, è uno strumento freewere per vedere, modificare, rinominare, aggiungere, rimuovere e estrarre risorse in eseguibili Windows 32 e 64 bit e file di risorse (*.res). + [Section.0415] Description = Resource Hacker to darmowe narzędzie do podglądu, modyfikacji, zmiany nazw, dodawania, kasowania i wypakowywania zasobów w plikach wykonywalnych 32bit i 64bit, oraz w plikach zasobów (*.res). diff --git a/base/applications/rapps/rapps/rocks.txt b/base/applications/rapps/rapps/rocks.txt index 5e8f0b29462..b17b5290fd0 100644 --- a/base/applications/rapps/rapps/rocks.txt +++ b/base/applications/rapps/rapps/rocks.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] @@ -15,6 +15,9 @@ CDPath = none [Section.0407] Description = Arcade-Style Spiel für UNIX, Mac OS X, Windows und DOS in der Tradition von: "Boulder Dash" (C64), "Emerald Mine" (Amiga), "Supaplex" (Amiga / PC), "Sokoban" (PC). Sie benötigen ein ZIP-Programm, um es zu installieren. +[Section.0410] +Description = Gioco in stile arcade per UNIX, Mac OS X, Windows e DOS nella tradizione di: "Boulder Dash" (C64), "Emerald Mine" (Amiga), "Supaplex" (Amiga/PC), "Sokoban" (PC). Necessita di un programma di decompressione di archivi ZIP per essere installato. + Section.0415] Description = Gra typu Arcade dla UNIX, Mac OS X, Windows i DOS. Bazująca na "Boulder Dash" (C64), "Emerald Mine" (Amiga), "Supaplex" (Amiga/PC), "Sokoban" (PC). Aby zainstalować te grę, potrzebny jest program archiwizujący np. 7-Zip. diff --git a/base/applications/rapps/rapps/rosbe.txt b/base/applications/rapps/rapps/rosbe.txt index 56098d8d9d6..bbdd3ebb224 100644 --- a/base/applications/rapps/rapps/rosbe.txt +++ b/base/applications/rapps/rapps/rosbe.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = ReactOS Build Environment diff --git a/base/applications/rapps/rapps/rosbeamd64.txt b/base/applications/rapps/rapps/rosbeamd64.txt index d2cb1c9a5fd..f51d300d064 100644 --- a/base/applications/rapps/rapps/rosbeamd64.txt +++ b/base/applications/rapps/rapps/rosbeamd64.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = ReactOS Build Environment AMD64 Addon diff --git a/base/applications/rapps/rapps/rosbearm.txt b/base/applications/rapps/rapps/rosbearm.txt index 258000ada33..1990dea2ed2 100644 --- a/base/applications/rapps/rapps/rosbearm.txt +++ b/base/applications/rapps/rapps/rosbearm.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = ReactOS Build Environment ARM Addon diff --git a/base/applications/rapps/rapps/sambatng.txt b/base/applications/rapps/rapps/sambatng.txt index b004377749c..0b586ea2c6c 100644 --- a/base/applications/rapps/rapps/sambatng.txt +++ b/base/applications/rapps/rapps/sambatng.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Samba TNG @@ -22,7 +22,7 @@ Description = Cet outil vous permet d'accéder à vos répertoire/imprimantes pa Size = 2,13 Mo [Section.0410] -Description = Questo strumento consente di accedere alle cartelle condivise di Windows / stampanti con ReactOS. +Description = Questo strumento consente di accedere alle cartelle/stampanti condivise di Windows con ReactOS. [Section.0413] Description = Maakt het mogelijk om Windows gedeelde printers te gebruiken met ReactOS. diff --git a/base/applications/rapps/rapps/sbforvmware.txt b/base/applications/rapps/rapps/sbforvmware.txt index 4d610352543..2e184062f53 100644 --- a/base/applications/rapps/rapps/sbforvmware.txt +++ b/base/applications/rapps/rapps/sbforvmware.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = SoundBlaster Driver for VMWare @@ -34,7 +34,7 @@ Size = 2,22 Mo [Section.0410] Name = Driver SoundBlaster per VMWare Licence = Sconosciuta -Description = Unzip nella cartella "ReactOS" e riavviare ReactOS. +Description = Estrarre nella cartella "ReactOS" e riavviare ReactOS due volte. [Section.0413] Name = SoundBlaster Driver voor VMWare diff --git a/base/applications/rapps/rapps/scite.txt b/base/applications/rapps/rapps/scite.txt index 52300c0fb42..208bcb833fa 100644 --- a/base/applications/rapps/rapps/scite.txt +++ b/base/applications/rapps/rapps/scite.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = SciTE @@ -22,7 +22,7 @@ Description = SciTE est un éditeur de texte basé sur SCIntilla. Originelement Size = 730 ko [Section.0410] -Description = SciTE è un editor di testo basato scintilla. Originariamente costruito per dimostrare Scintilla, è cresciuto fino a essere un editor generalmente utile con strutture per la creazione e l'esecuzione di programmi. +Description = SciTE è un editor di testo basato su scintilla. Originariamente costruito per dimostrare Scintilla, è cresciuto fino a essere un editor generalmente utile con strutture per la creazione e l'esecuzione di programmi. [Section.0413] Description = SciTE is een tekstbewerker gebaseerd op SCIntilla. Origineel bedoeld om Scontilla te demonstreren, is uitgegroeid tot een handige editor met mogelijkheden voor ontwerken en uitvoeren van programma's. diff --git a/base/applications/rapps/rapps/scummvm.txt b/base/applications/rapps/rapps/scummvm.txt index c976de62309..c6df83307e6 100644 --- a/base/applications/rapps/rapps/scummvm.txt +++ b/base/applications/rapps/rapps/scummvm.txt @@ -1,10 +1,10 @@ -; UTF-8 +; UTF-8 [Section] Name = ScummVM Version = 1.6.0 Licence = GPL -Description = Sam and Max, Day of the Tentacle, etc on ReactOS. +Description = Software that reproduce the working of graphical engine for videogames (Sam and Max, Day of the Tentacle, etc) on ReactOS. Size = 6.28 MB Category = 4 URLSite = http://scummvm.org/ @@ -22,7 +22,7 @@ Description = Sam and Max, Day of the Tentacle, etc sur ReactOS. Size = 6,28 Mo [Section.0410] -Description = Software che riproduce il funzionamento di motori grafici per videogiochi(Sam and Max, Day of the Tentacle, etc) su ReactOS. +Description = Software che riproduce il funzionamento di motori grafici per videogiochi (Sam and Max, Day of the Tentacle, etc) su ReactOS. [Section.0413] Description = Sam and Max, Day of the Tentacle, enz. op ReactOS. diff --git a/base/applications/rapps/rapps/sdl_mixer.txt b/base/applications/rapps/rapps/sdl_mixer.txt index 4837a287d1e..236b3dc5095 100644 --- a/base/applications/rapps/rapps/sdl_mixer.txt +++ b/base/applications/rapps/rapps/sdl_mixer.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Simple Direct Media Layer (SDL) Mixer diff --git a/base/applications/rapps/rapps/sdl_runtime.txt b/base/applications/rapps/rapps/sdl_runtime.txt index 0412ae5d9ed..fa77781a246 100644 --- a/base/applications/rapps/rapps/sdl_runtime.txt +++ b/base/applications/rapps/rapps/sdl_runtime.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Simple Direct Media Layer (SDL) Runtime diff --git a/base/applications/rapps/rapps/seamonkey.txt b/base/applications/rapps/rapps/seamonkey.txt index 4355489b8e7..7e978dbe1f8 100644 --- a/base/applications/rapps/rapps/seamonkey.txt +++ b/base/applications/rapps/rapps/seamonkey.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Mozilla SeaMonkey @@ -27,7 +27,7 @@ Size = 24,06 Mo URLDownload = http://ftp.mozilla.org/pub/mozilla.org/seamonkey/releases/2.25/win32/fr/SeaMonkey%20Setup%202.25.exe [Section.0410] -Description = Mozilla Suite è vivo. Questo è l'unico e solo Browser, Mail, Chat, e Composer di cui avrete mai bisogno... +Description = Mozilla Suite è vivo. Questo è l'unico pachetto che include Browser, Mail, Chat, e Composer di cui avrete mai bisogno... Size = 23.71 MB URLDownload = http://ftp.mozilla.org/pub/mozilla.org/seamonkey/releases/2.25/win32/it/SeaMonkey%20Setup%202.25.exe diff --git a/base/applications/rapps/rapps/smplayer.txt b/base/applications/rapps/rapps/smplayer.txt index b203cb6dad1..ca7683d142e 100644 --- a/base/applications/rapps/rapps/smplayer.txt +++ b/base/applications/rapps/rapps/smplayer.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = SMPlayer diff --git a/base/applications/rapps/rapps/snoopy.txt b/base/applications/rapps/rapps/snoopy.txt index 8ae0a8a6eab..ad350ef230c 100644 --- a/base/applications/rapps/rapps/snoopy.txt +++ b/base/applications/rapps/rapps/snoopy.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Snoopy @@ -14,6 +14,9 @@ CDPath = none [Section.0407] Description = Das Original C64 Snoopy Remake. +[Section.0410] +Description = Il remake del gioco Snoopy per Commodore 64. + [Section.041f] Licence = Ücretsiz Description = Özgün C64 Snoppy'nın yeniden yapılmışı. diff --git a/base/applications/rapps/rapps/stamina.txt b/base/applications/rapps/rapps/stamina.txt index e2c97693eec..0ff51a0f879 100644 --- a/base/applications/rapps/rapps/stamina.txt +++ b/base/applications/rapps/rapps/stamina.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] @@ -13,6 +13,9 @@ CDPath = none [Section.0407] Description = Ein freies Schreiblernprogramm. +[Section.0410] +Description = Tutore di scrittura gratuita. + [Section.0415] Description = Darmowy program do nauki pisania na klawiaturze. diff --git a/base/applications/rapps/rapps/steam.txt b/base/applications/rapps/rapps/steam.txt index 61894754cc3..9197a95b539 100644 --- a/base/applications/rapps/rapps/steam.txt +++ b/base/applications/rapps/rapps/steam.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = STEAM diff --git a/base/applications/rapps/rapps/sumatrapdf.txt b/base/applications/rapps/rapps/sumatrapdf.txt index af1fd201847..a4c3a8aa13e 100644 --- a/base/applications/rapps/rapps/sumatrapdf.txt +++ b/base/applications/rapps/rapps/sumatrapdf.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = SumatraPDF @@ -22,7 +22,7 @@ Description = Sumatra PDF est un lecteur PDF léger, libre et open-source. Size = 4,0 Mo [Section.0410] -Description = Sumatra PDF è un visualizzatore di file PDF. E' molto leggero ed è open source. +Description = Sumatra PDF è un visualizzatore di file PDF, leggero e open source. [Section.0413] Description = Sumatra PDF is een slanke, gratis, open-bron PDF lezer. diff --git a/base/applications/rapps/rapps/summerbound.txt b/base/applications/rapps/rapps/summerbound.txt index e17a8d4c813..e45c2c9fba8 100644 --- a/base/applications/rapps/rapps/summerbound.txt +++ b/base/applications/rapps/rapps/summerbound.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Summer Bound @@ -14,6 +14,9 @@ CDPath = none [Section.0407] Description = Ein Spiel, ähnlich zu Frozen Fruits. +[Section.0410] +Description = Un gioco simile a Frozen Fuits + [Section.041f] Licence = Ücretsiz Description = Frozen Fruits'e benzeyen bir oyun. diff --git a/base/applications/rapps/rapps/superdxb.txt b/base/applications/rapps/rapps/superdxb.txt index 370b20b2b0d..bd0151d8bce 100644 --- a/base/applications/rapps/rapps/superdxb.txt +++ b/base/applications/rapps/rapps/superdxb.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] Name = Super DX-Ball @@ -14,6 +14,9 @@ CDPath = none [Section.0407] Description = Super DX-Ball ist ein lebendiges und buntes Brick-Breaking-Spiel. +[Section.0410] +Description = Super DX-Ball è un gioco spacca blocchi vibrante e colorato + [Section.0415] Description = Super DX-Ball - pełna koloru i animacji gra polegająca na zbijaniu klocków. diff --git a/base/applications/rapps/rapps/superfinder.txt b/base/applications/rapps/rapps/superfinder.txt index 96829073322..9695da8b2f4 100644 --- a/base/applications/rapps/rapps/superfinder.txt +++ b/base/applications/rapps/rapps/superfinder.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Super Finder XT diff --git a/base/applications/rapps/rapps/supertux.txt b/base/applications/rapps/rapps/supertux.txt index 6f6cfac8db5..20dd10d9b38 100644 --- a/base/applications/rapps/rapps/supertux.txt +++ b/base/applications/rapps/rapps/supertux.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ; PL translation by wojo664 [Section] Name = SuperTux @@ -15,7 +15,7 @@ CDPath = none Description = SuperTux ist ein zweidimensionales, freies, Open Source Plattformspiel. [Section.0410] -Description = SuperTux è un gioco open-source a 2D. +Description = SuperTux è un gioco open-source gratuito in 2D. [Section.0415] Description = SuperTux to darmowa dwu wymiarowa gra platformowa OpenSource. diff --git a/base/applications/rapps/rapps/tahoma.txt b/base/applications/rapps/rapps/tahoma.txt index 73d8134515a..e40f3a14a97 100644 --- a/base/applications/rapps/rapps/tahoma.txt +++ b/base/applications/rapps/rapps/tahoma.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Microsoft Tahoma Font diff --git a/base/applications/rapps/rapps/thunderbird.txt b/base/applications/rapps/rapps/thunderbird.txt index a25ed479ffb..427b78a8ac9 100644 --- a/base/applications/rapps/rapps/thunderbird.txt +++ b/base/applications/rapps/rapps/thunderbird.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Mozilla Thunderbird 24 @@ -30,7 +30,7 @@ URLSite = https://www.mozilla.org/fr/thunderbird/ URLDownload = http://ftp.mozilla.org/pub/mozilla.org/thunderbird/releases/24.4.0/win32/fr/Thunderbird%20Setup%2024.4.0.exe [Section.0410] -Description = Il più popolare e il migliore Clients mail gratuito. +Description = Il più popolare e il migliore Client mail gratuito. Size = 20.91 MB URLSite = https://www.mozilla.org/it/thunderbird/ URLDownload = http://ftp.mozilla.org/pub/mozilla.org/thunderbird/releases/24.4.0/win32/it/Thunderbird%20Setup%2024.4.0.exe diff --git a/base/applications/rapps/rapps/thunderbird3.txt b/base/applications/rapps/rapps/thunderbird3.txt index 201a4bf2826..ffc3bce18fd 100644 --- a/base/applications/rapps/rapps/thunderbird3.txt +++ b/base/applications/rapps/rapps/thunderbird3.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Mozilla Thunderbird @@ -30,7 +30,7 @@ URLSite = https://www.mozilla.org/fr/thunderbird/ URLDownload = http://ftp.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.20/win32/fr/Thunderbird%20Setup%203.1.20.exe [Section.0410] -Description = Il più popolare e il migliore Clients mail gratuito. +Description = Il più popolare e il migliore Client mail gratuito. Size = 8.88 MB URLSite = https://www.mozilla.org/it/thunderbird/ URLDownload = http://ftp.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.20/win32/it/Thunderbird%20Setup%203.1.20.exe diff --git a/base/applications/rapps/rapps/tileworld.txt b/base/applications/rapps/rapps/tileworld.txt index dd3011cdbb1..4aa47a2da7a 100644 --- a/base/applications/rapps/rapps/tileworld.txt +++ b/base/applications/rapps/rapps/tileworld.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Tile World diff --git a/base/applications/rapps/rapps/totalcommander.txt b/base/applications/rapps/rapps/totalcommander.txt index 0503119ca76..ca17f0ac6cc 100644 --- a/base/applications/rapps/rapps/totalcommander.txt +++ b/base/applications/rapps/rapps/totalcommander.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Total Commander diff --git a/base/applications/rapps/rapps/tuxpaint.txt b/base/applications/rapps/rapps/tuxpaint.txt index de7bc9b11d0..9a23c5034bd 100644 --- a/base/applications/rapps/rapps/tuxpaint.txt +++ b/base/applications/rapps/rapps/tuxpaint.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = TuxPaint diff --git a/base/applications/rapps/rapps/ultravnc.txt b/base/applications/rapps/rapps/ultravnc.txt index 3a9954b4b96..06e225f312b 100644 --- a/base/applications/rapps/rapps/ultravnc.txt +++ b/base/applications/rapps/rapps/ultravnc.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = UltraVNC @@ -22,7 +22,7 @@ Description = Client/serveur VNC open source. Size = 3,27 Mo [Section.0410] -Description = Client/serveur VNC open source. +Description = Client/server VNC open source. [Section.0413] Description = Open-bron VNC afnemer/aanbieder. diff --git a/base/applications/rapps/rapps/utorrent.txt b/base/applications/rapps/rapps/utorrent.txt index 3a3cb8baf2c..6a4bcc1a21a 100644 --- a/base/applications/rapps/rapps/utorrent.txt +++ b/base/applications/rapps/rapps/utorrent.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = µTorrent diff --git a/base/applications/rapps/rapps/vb5run.txt b/base/applications/rapps/rapps/vb5run.txt index cfdc4712208..b4813f9a136 100644 --- a/base/applications/rapps/rapps/vb5run.txt +++ b/base/applications/rapps/rapps/vb5run.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Microsoft Visual Basic 5 Runtime diff --git a/base/applications/rapps/rapps/vb6run.txt b/base/applications/rapps/rapps/vb6run.txt index 1ae706e6d56..1c48f22e06f 100644 --- a/base/applications/rapps/rapps/vb6run.txt +++ b/base/applications/rapps/rapps/vb6run.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Microsoft Visual Basic 6 Runtime diff --git a/base/applications/rapps/rapps/vc2005sp1run.txt b/base/applications/rapps/rapps/vc2005sp1run.txt index 58693a9430a..c5c773a5a86 100644 --- a/base/applications/rapps/rapps/vc2005sp1run.txt +++ b/base/applications/rapps/rapps/vc2005sp1run.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Microsoft Visual C++ 2005 SP1 Redistributable Package diff --git a/base/applications/rapps/rapps/vc2008sp1run.txt b/base/applications/rapps/rapps/vc2008sp1run.txt index 74c0f3bf4ce..1920ff12472 100644 --- a/base/applications/rapps/rapps/vc2008sp1run.txt +++ b/base/applications/rapps/rapps/vc2008sp1run.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Microsoft Visual C++ 2008 SP1 Redistributable Package diff --git a/base/applications/rapps/rapps/vc2010run.txt b/base/applications/rapps/rapps/vc2010run.txt index e944533ec75..99c699761e0 100644 --- a/base/applications/rapps/rapps/vc2010run.txt +++ b/base/applications/rapps/rapps/vc2010run.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Microsoft Visual C++ 2010 Redistributable Package diff --git a/base/applications/rapps/rapps/vc6run.txt b/base/applications/rapps/rapps/vc6run.txt index 1e580af953c..9085eb47563 100644 --- a/base/applications/rapps/rapps/vc6run.txt +++ b/base/applications/rapps/rapps/vc6run.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Microsoft Visual C++ 6 Redistributable Package diff --git a/base/applications/rapps/rapps/vlc.txt b/base/applications/rapps/rapps/vlc.txt index 6faef05b095..6aeca7556a6 100644 --- a/base/applications/rapps/rapps/vlc.txt +++ b/base/applications/rapps/rapps/vlc.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = VLC media player diff --git a/base/applications/rapps/rapps/winboard.txt b/base/applications/rapps/rapps/winboard.txt index bdc18892789..483140c9c02 100644 --- a/base/applications/rapps/rapps/winboard.txt +++ b/base/applications/rapps/rapps/winboard.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = WinBoard diff --git a/base/applications/rapps/rapps/wme9.txt b/base/applications/rapps/rapps/wme9.txt index 96a0becc5d8..a6723407167 100644 --- a/base/applications/rapps/rapps/wme9.txt +++ b/base/applications/rapps/rapps/wme9.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Windows Media Encoder 9 diff --git a/base/applications/rapps/rapps/wordview.txt b/base/applications/rapps/rapps/wordview.txt index 7d3884e8bba..c2c46eeb8b7 100644 --- a/base/applications/rapps/rapps/wordview.txt +++ b/base/applications/rapps/rapps/wordview.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 [Section] Name = Microsoft Word Viewer diff --git a/base/applications/rapps/rapps/zaz.txt b/base/applications/rapps/rapps/zaz.txt index 12604c87972..ce7ff58e402 100644 --- a/base/applications/rapps/rapps/zaz.txt +++ b/base/applications/rapps/rapps/zaz.txt @@ -1,4 +1,4 @@ -; UTF-8 +; UTF-8 ;PL translation by wojo664 [Section] @@ -16,7 +16,7 @@ CDPath = none Description = Zaz ist ein freies Arcade Action Puzzle Spiel, ein wenig wie Frozen Bubble. [Section.0410] -Description = Zaz è un puzzle game gratuito, simile a Frozen Bubble. +Description = Zaz è un gioco arcade puzzle gratuito per computer, in parte simile a Frozen Bubble. [Section.0415] Description = Zaz to darmowa gra logiczno-zręcznościowa, trochę podobna do gry Frozen Bubble diff --git a/base/applications/regedit/lang/tr-TR.rc b/base/applications/regedit/lang/tr-TR.rc index b24e5566779..03cfb35bb51 100644 --- a/base/applications/regedit/lang/tr-TR.rc +++ b/base/applications/regedit/lang/tr-TR.rc @@ -293,7 +293,7 @@ BEGIN ID_REGISTRY_DISCONNECTNETWORKREGISTRY "Uzaktaki bir bilgisayarın Değer Defteri'sine olan bağlantıyı keser." ID_REGISTRY_PRINT "Değer Defteri'nin tümünü ya da bir bölümünü yazdırır." /* ID_HELP_HELPTOPICS "Değer Defteri Düzenleyicisi Yardımı'nı açar." */ - ID_HELP_ABOUT "İzlenceyle ilgili bilgi görüntüler." + ID_HELP_ABOUT "İzlenceyle ilgili bilgi, sürüm numarası ve telif hakkı görüntüler." END STRINGTABLE @@ -320,18 +320,18 @@ BEGIN IDS_UNSUPPORTED_TYPE "Bu türdeki dizinler değiştirilemiyor: %ld" IDS_TOO_BIG_VALUE "Değer çok büyük: %ld" IDS_MULTI_SZ_EMPTY_STRING "REG_MULTI_SZ veri türü boş dizgi içeremez.\nBoş dizgiler dizelgeden silinmiştir." - IDS_QUERY_DELETE_KEY_ONE "Bu dizini silmeyi doğruluyor musunuz?" - IDS_QUERY_DELETE_KEY_MORE "Bu dizinleri silmeyi doğruluyor musunuz?" + IDS_QUERY_DELETE_KEY_ONE "Bu dizini silmek istemeyi doğruluyor musunuz?" + IDS_QUERY_DELETE_KEY_MORE "Bu dizinleri silmek istemeyi doğruluyor musunuz?" IDS_QUERY_DELETE_KEY_CONFIRM "Dizin Silme Doğrulaması" - IDS_QUERY_DELETE_ONE "Bu değeri silmeyi doğruluyor musunuz?" - IDS_QUERY_DELETE_MORE "Bu değerleri silmeyi doğruluyor musunuz?" + IDS_QUERY_DELETE_ONE "Bu değeri silmek istemeyi doğruluyor musunuz?" + IDS_QUERY_DELETE_MORE "Bu değerleri silmek istemeyi doğruluyor musunuz?" IDS_QUERY_DELETE_CONFIRM "Değer Silme Doğrulaması" IDS_ERR_DELVAL_CAPTION "Değerler Silinmesi Yanlışlığı" IDS_ERR_DELETEVALUE "Tüm belirtilmiş değerler silinemiyor." IDS_ERR_RENVAL_CAPTION "Değer Adı Değiştirilmesi Yanlışlığı" IDS_ERR_RENVAL_TOEMPTY "Adı değiştirilemiyor: %s. Belirtilen değer adı boş. Başka bir ad yazıp yeniden deneyiniz." IDS_QUERY_IMPORT_HIVE_CAPTION "Dizin Yenileme Doğrulaması" - IDS_QUERY_IMPORT_HIVE_MSG "Bir dizin seçili dizinle yenilenecektir.\nBu dizinin tüm alt dizinleri ve değerleri silinecektir.\nEylemi sürdürmek istiyor musunuz?" + IDS_QUERY_IMPORT_HIVE_MSG "Bir dizin seçili dizinle yenilenecektir.\nBu dizinin tüm alt dizinleri ve değerleri silinecektir.\nİşlemi sürdürmek istiyor musunuz?" IDS_NEW_KEY "%d. Yeni Dizin" IDS_NEW_VALUE "%d. Yeni Değer" END @@ -397,7 +397,7 @@ END STRINGTABLE BEGIN IDS_IMPORT_PROMPT "Bilgi ekleme, yanlışlıkla değerleri değiştirebilir ya da silebilir ve bileşenlerin doğru çalışmasını engelleyebilir.\nEğer ""%s"" içindeki bilginin kaynağına güvenmiyorsanız onu Değer Defteri'ne eklemeyiniz.\n\nSürdürmek istediğinizi doğruluyor musunuz?" - IDS_IMPORT_OK "%s içinde bulunan dizinler ve değerler Değer Defteri'ne başarıyla eklendi." + IDS_IMPORT_OK """%s"" içinde bulunan dizinler ve değerler Değer Defteri'ne başarıyla eklendi." IDS_IMPORT_ERROR """%s"" alınamıyor: Kütüğü açmada yanlışlık. Bir disk yanlışlığı, bir kütük dizgesi yanlışlığı ya da kütüğün olmaması olabilir." IDS_EXPORT_ERROR """%s"" verilemiyor: Kütüğü oluşturmada ya da kütüğe yazmada yanlışlık. Bir disk yanlışlığı ya da bir kütük dizgesi yanlışlığı olabilir." END @@ -541,6 +541,6 @@ END *STRINGTABLE *BEGIN * ID_HELP_HELPTOPICS "Değer Defteri Düzenleyicisi Yardımı'nı açar." - * ID_HELP_ABOUT "İzlenceyle ilgili bilgi görüntüler." + * ID_HELP_ABOUT "İzlenceyle ilgili bilgi, sürüm numarası ve telif hakkı görüntüler." *END */ diff --git a/base/applications/sndvol32/lang/tr-TR.rc b/base/applications/sndvol32/lang/tr-TR.rc index 81ca9ed6a30..b12348b583a 100644 --- a/base/applications/sndvol32/lang/tr-TR.rc +++ b/base/applications/sndvol32/lang/tr-TR.rc @@ -35,7 +35,7 @@ BEGIN GROUPBOX "Ses Düzeyi Düzenlenecekler", -1, 7, 25, 211, 77 PUSHBUTTON "&Çalma", IDC_PLAYBACK, 13, 43, 47, 8, BS_AUTORADIOBUTTON PUSHBUTTON "K&aydetme", IDC_RECORDING, 13, 61, 47, 8, BS_AUTORADIOBUTTON - PUSHBUTTON "&Diğer:", IDC_OTHER, 13, 80, 42, 8, BS_AUTORADIOBUTTON | WS_DISABLED + PUSHBUTTON "&Başka:", IDC_OTHER, 13, 80, 42, 8, BS_AUTORADIOBUTTON | WS_DISABLED COMBOBOX IDC_LINE, 55, 80, 155, 50, CBS_DROPDOWNLIST | WS_TABSTOP | WS_DISABLED LTEXT "Aşağıdaki ses düzeyi denetimlerini göster:", IDC_LABELCONTROLS, 7, 109, 162, 8 CONTROL "", IDC_CONTROLS, "SysListView32", LVS_REPORT | LVS_NOCOLUMNHEADER | WS_TABSTOP | WS_BORDER, 7, 122, 211, 96 diff --git a/base/applications/taskmgr/lang/tr-TR.rc b/base/applications/taskmgr/lang/tr-TR.rc index c0715aaf2e7..93329ebe90f 100644 --- a/base/applications/taskmgr/lang/tr-TR.rc +++ b/base/applications/taskmgr/lang/tr-TR.rc @@ -277,11 +277,11 @@ FONT 8, "MS Shell Dlg" BEGIN DEFPUSHBUTTON "Tamam", IDOK, 84, 178, 50, 14 PUSHBUTTON "İptal", IDCANCEL, 138, 178, 50, 14 - LTEXT "Bu seçenekler, ""İşlemci"" sekmesindeki dikeçlerin hangisinin görüntülenip görüntülenmeyeceğini belirler.", IDC_STATIC, 7, 7, 181, 17 + LTEXT "Görev Yöneticisi'nin İşlemler sayfasında gözükecek dikeçleri seçiniz.", IDC_STATIC, 7, 7, 181, 17 CONTROL "Yansıma Adı", IDC_IMAGENAME, "Button", BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP, 7, 28, 56, 10 CONTROL "PID (İşlem Tanımlayıcı)", IDC_PID, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 39, 88, 10 CONTROL "CPU Kullanımı", IDC_CPUUSAGE, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 50, 53, 10 - CONTROL "CPU Çalışma Süresi", IDC_CPUTIME, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 61, 48, 10 + CONTROL "CPU Süresi", IDC_CPUTIME, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 61, 48, 10 CONTROL "Bellek Kullanımı", IDC_MEMORYUSAGE, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 72, 63, 10 CONTROL "Bellek Kullanım Aralığı", IDC_MEMORYUSAGEDELTA, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 83, 82, 10 CONTROL "En Yüksek Bellek Kullanımı", IDC_PEAKMEMORYUSAGE, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 94, 82, 10 @@ -295,14 +295,14 @@ BEGIN CONTROL "Farazî Bellek Boyutu", IDC_VIRTUALMEMORYSIZE, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 39, 77, 10 CONTROL "Sayfalanmış Havuz", IDC_PAGEDPOOL, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 50, 53, 10 CONTROL "Sayfalanmamış Havuz", IDC_NONPAGEDPOOL, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 61, 67, 10 - CONTROL "Öncelik", IDC_BASEPRIORITY, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 72, 55, 10 + CONTROL "Birinci Öncelik", IDC_BASEPRIORITY, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 72, 55, 10 CONTROL "İşleçler", IDC_HANDLECOUNT, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 83, 59, 10 CONTROL "İş Parçacıkları", IDC_THREADCOUNT, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 94, 59, 10 CONTROL "GDI Nesneleri", IDC_GDIOBJECTS, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 105, 55, 10 CONTROL "G/Ç Yazma", IDC_IOWRITES, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 116, 49, 10 CONTROL "G/Ç Yazma Çokluları", IDC_IOWRITEBYTES, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 127, 65, 10 - CONTROL "G/Ç Diğer", IDC_IOOTHER, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 138, 46, 10 - CONTROL "G/Ç Diğer Çoklular", IDC_IOOTHERBYTES, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 149, 65, 10 + CONTROL "G/Ç Başka", IDC_IOOTHER, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 138, 46, 10 + CONTROL "G/Ç Başka Çoklular", IDC_IOOTHERBYTES, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 107, 149, 65, 10 END /* String Tables */ @@ -311,64 +311,64 @@ STRINGTABLE BEGIN IDS_APP_TITLE "Görev Yöneticisi" IDC_TASKMGR "Görev Yöneticisi" - IDS_IDLE_PROCESS "Çalışmayan İşlemci Yüzdesi İşlemi" + IDS_IDLE_PROCESS "Dizge Boşta İşlemi" END STRINGTABLE BEGIN - ID_FILE_NEW "Yeni görev çalıştırır." - ID_OPTIONS_ALWAYSONTOP "Görev Yöneticisi'ni diğer pencerelerin üstünde tutar." - ID_OPTIONS_MINIMIZEONUSE "Geçiş yapılırken Görev Yöneticisi'ni simge durumuna küçültür." + ID_FILE_NEW "Yeni bir izlence çalıştırır." + ID_OPTIONS_ALWAYSONTOP "Simge durumuna küçültülmeden Görev Yöneticisi başka tüm pencerelerin önünde durur." + ID_OPTIONS_MINIMIZEONUSE "Geçme işlemi uygulanırken Görev Yöneticisi simge durumuna küçültülür." ID_OPTIONS_HIDEWHENMINIMIZED "Görev Yöneticisi simge durumuna küçültüldüğünde Görev Yöneticisi'ni gizler." - ID_VIEW_REFRESH "Görev Yöneticisi'ndeki bilgileri yeniler." - ID_VIEW_LARGE "Görevleri büyük simgelerle gösterir." - ID_VIEW_SMALL "Görevleri küçük simgelerle gösterir." - ID_VIEW_DETAILS "Görevleri küçük simgelerle, ayrıntılı olarak gösterir." - ID_VIEW_UPDATESPEED_HIGH "Her yarım sâniyede bir Görev Yöneticisi'ndeki bilgileri yeniler." - ID_VIEW_UPDATESPEED_NORMAL "Her iki sâniyede bir Görev Yöneticisi'ndeki bilgileri yeniler." - ID_VIEW_UPDATESPEED_LOW "Her dört sâniyede bir Görev Yöneticisi'ndeki bilgileri yeniler." + ID_VIEW_REFRESH "Yenileme Hızı ayârını önemsemeden Görev Yöneticisi'ni şimdi yenilemeye zorlar." + ID_VIEW_LARGE "Görevleri büyük simgeler kullanarak gösterir." + ID_VIEW_SMALL "Görevleri küçük simgeler kullanarak gösterir." + ID_VIEW_DETAILS "Her bir görev için bilgi görüntüler." + ID_VIEW_UPDATESPEED_HIGH "Her sâniyede iki kez görünümü yeniler." + ID_VIEW_UPDATESPEED_NORMAL "Her iki sâniyede bir görünümü yeniler." + ID_VIEW_UPDATESPEED_LOW "Her dört sâniyede bir görünümü yeniler." END STRINGTABLE BEGIN - ID_VIEW_UPDATESPEED_PAUSED "Görev Yöneticisi'ndeki bilgilerin kendiliğinden yenilenmesini durdurur." - ID_WINDOWS_TILEHORIZONTALLY "Masaüstündeki pencereleri yatay olarak sıralar." - ID_WINDOWS_TILEVERTICALLY "Masaüstündeki pencereleri dikey olarak sıralar." + ID_VIEW_UPDATESPEED_PAUSED "Kendiliğinden yenilemez." + ID_WINDOWS_TILEHORIZONTALLY "Masaüstünde pencereleri yatay olarak döşer." + ID_WINDOWS_TILEVERTICALLY "Masaüstünde pencereleri dikey olarak döşer." ID_WINDOWS_MINIMIZE "Pencereleri simge durumuna küçültür." - ID_WINDOWS_MAXIMIZE "Pencereleri her bir pencerenin görüntülüğü kaplayacağı şekilde büyütür." - ID_WINDOWS_CASCADE "Pencereleri masaüstünde çapraz olarak sıralar." - ID_WINDOWS_BRINGTOFRONT "Pencereyi öne getirir ancak o pencereye geçiş yapmaz." - ID_HELP_TOPICS "Görev Yöneticisi ile ilgili yardım konularını görüntüler." - ID_HELP_ABOUT "Görev Yöneticisi ile ilgili bilgi görüntüler." - ID_FILE_EXIT "Görev Yöneticisi'nden çıkar." - ID_OPTIONS_SHOW16BITTASKS "Farazî DOS Makinesi (ntvdm.exe) altında çalışan 16 bitlik uygulamaları da görüntüler." - ID_VIEW_SELECTCOLUMNS """İşlemler"" sekmesinde hangi dikeçlerin görüntülenip görüntülenmeyeceğini belirler." - ID_VIEW_SHOWKERNELTIMES "İşlemci çizgelerinde çekirdek zamanlarını gösterir." - ID_VIEW_CPUHISTORY_ONEGRAPHALL "Toplam CPU kullanımını tek çizgede gösterir." - ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU "Her CPU'nun kullanımını ayrı çizgelerde gösterir." - ID_APPLICATION_PAGE_SWITCHTO "Seçilen görevi öne getirip o göreve odaklatır." + ID_WINDOWS_MAXIMIZE "Pencereleri büyütür." + ID_WINDOWS_CASCADE "Masaüstünde pencereleri çapraz olarak basamaklar." + ID_WINDOWS_BRINGTOFRONT "Pencereyi öne getirir ancak ona geçmez." + ID_HELP_TOPICS "Görev Yöneticisi yardım konularını görüntüler." + ID_HELP_ABOUT "İzlenceyle ilgili bilgi, sürüm numarası ve telif hakkı görüntüler." + ID_FILE_EXIT "Görev Yöneticisi uygulamasından çıkar." + ID_OPTIONS_SHOW16BITTASKS "İlişkili ntvdm.exe altındaki 16 bitlik görevleri gösterir." + ID_VIEW_SELECTCOLUMNS "İşlemler sayfasında hangi dikeçlerin görünür olacağını seçer." + ID_VIEW_SHOWKERNELTIMES "Başarım çizgelerinde çekirdek sürelerini görüntüler." + ID_VIEW_CPUHISTORY_ONEGRAPHALL "Bir bayağı geçmiş çizgesi toplam CPU kullanımını gösterir." + ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU "Her bir CPU'nun kendi geçmiş çizgesi vardır." + ID_APPLICATION_PAGE_SWITCHTO "Bir görevi ön plana getirir, o göreve odaklatır." END STRINGTABLE BEGIN - ID_ENDTASK "Seçili görevi sonlandırmaya çalışır." - ID_GOTOPROCESS "Seçili görevin işlemine gider." - ID_RESTORE "Görev Yöneticisi'ni gizli olmaktan çıkarır." - ID_PROCESS_PAGE_ENDPROCESS "Seçili işlemi sonlandırır." - ID_PROCESS_PAGE_ENDPROCESSTREE "Seçili işlemi ve bu işlemin bağlı olduğu tüm işlemleri sonlandırır." - ID_PROCESS_PAGE_DEBUG "Seçili işleme bir yanlışlık ayıklayıcı bağlar." - ID_PROCESS_PAGE_SETAFFINITY "Seçili işlemin hangi CPU'larla yürütüleceğini belirler." - ID_PROCESS_PAGE_SETPRIORITY_REALTIME "Seçili işlemin öncelik sırasını EŞ ZAMANLI yapar." - ID_PROCESS_PAGE_SETPRIORITY_HIGH "Seçili işlemin öncelik sırasını YÜKSEK yapar." - ID_PROCESS_PAGE_SETPRIORITY_ABOVENORMAL "Seçili işlemin öncelik sırasını ORTA-YÜKSEK yapar." - ID_PROCESS_PAGE_SETPRIORITY_NORMAL "Seçili işlemin öncelik sırasını ORTA yapar." - ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL "Seçili işlemin öncelik sırasını ORTA-DÜŞÜK yapar." - ID_PROCESS_PAGE_SETPRIORITY_LOW "Seçili işlemin öncelik sırasını DÜŞÜK yapar." + ID_ENDTASK "Seçilen görevleri sonlandırmayı bildirir." + ID_GOTOPROCESS "Seçilen görevin işlemine odaklatır." + ID_RESTORE "Görev Yöneticisi'ni gizli durumdan döndürür." + ID_PROCESS_PAGE_ENDPROCESS "İşlemi dizgeden siler." + ID_PROCESS_PAGE_ENDPROCESSTREE "Bu işlemi ve tüm astlarını bu dizgeden sonlandırır." + ID_PROCESS_PAGE_DEBUG "Bu işleme yanlışlık ayıklayıcı bağlar." + ID_PROCESS_PAGE_SETAFFINITY "İşleme hangi CPU'ların üzerinde çalışmasına izin verileceğini denetler." + ID_PROCESS_PAGE_SETPRIORITY_REALTIME "İşlemi EŞ ZAMANLI öncelik sınıfına getirir." + ID_PROCESS_PAGE_SETPRIORITY_HIGH "İşlemi YÜKSEK öncelik sınıfına getirir." + ID_PROCESS_PAGE_SETPRIORITY_ABOVENORMAL "İşlemi DÜZGÜLÜ ÜSTÜ öncelik sınıfına getirir." + ID_PROCESS_PAGE_SETPRIORITY_NORMAL "İşlemi DÜZGÜLÜ öncelik sınıfına getirir." + ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL "İşlemi DÜZGÜLÜ ALTI öncelik sınıfına getirir." + ID_PROCESS_PAGE_SETPRIORITY_LOW "İşlemi DÜŞÜK öncelik sınıfına getirir." END STRINGTABLE BEGIN - IDS_TAB_APPS "Görevler" + IDS_TAB_APPS "Uygulamalar" IDS_TAB_PROCESSES "İşlemler" IDS_TAB_PERFORMANCE "Başarım" IDS_TAB_TASK "Görev" @@ -378,7 +378,7 @@ BEGIN IDS_TAB_USERNAME "Kullanıcı Adı" IDS_TAB_SESSIONID "Oturum Kimliği" IDS_TAB_CPU "CPU Kullanımı" - IDS_TAB_CPUTIME "CPU Çalışma Süresi" + IDS_TAB_CPUTIME "CPU Süresi" IDS_TAB_MEMUSAGE "Bellek Kullanımı" IDS_TAB_PEAKMEMUSAGE "En Yüksek Bellek Kullanımı" IDS_TAB_MEMDELTA "Bellek Kullanım Aralığı" @@ -387,43 +387,43 @@ BEGIN IDS_TAB_VMSIZE "Farazî Bellek Boyutu" IDS_TAB_PAGEDPOOL "Sayfalanmış Havuz" IDS_TAB_NPPOOL "Sayfalanmamış Havuz" - IDS_TAB_BASEPRI "Öncelik" + IDS_TAB_BASEPRI "Birinci Öncelik" IDS_TAB_HANDLES "İşleçler" IDS_TAB_THREADS "İş Parçacıkları" IDS_TAB_USERPBJECTS "Kullanıcı Nesneleri" IDS_TAB_GDIOBJECTS "GDI Nesneleri" IDS_TAB_IOREADS "G/Ç Okuma" IDS_TAB_IOWRITES "G/Ç Yazma" - IDS_TAB_IOOTHER "G/Ç Diğer" + IDS_TAB_IOOTHER "G/Ç Başka" IDS_TAB_IOREADBYTES "G/Ç Okuma Çokluları" IDS_TAB_IOWRITESBYTES "G/Ç Yazma Çokluları" - IDS_TAB_IOOTHERBYTES "G/Ç Diğer Çoklular" + IDS_TAB_IOOTHERBYTES "G/Ç Başka Çoklular" IDS_MENU_SELECTCOLUMNS "&Dikeçleri Seç..." IDS_MENU_16BITTASK "&16 Bitlik Görevleri Göster" IDS_MENU_WINDOWS "&Pencereler" IDS_MENU_LARGEICONS "&Büyük Simgeler" IDS_MENU_SMALLICONS "&Küçük Simgeler" IDS_MENU_DETAILS "&Ayrıntılar" - IDS_MENU_ONEGRAPHALLCPUS "&Tüm CPU'lar İçin Aynı Çizge" - IDS_MENU_ONEGRAPHPERCPU "&Her CPU'ya Birer Çizge" + IDS_MENU_ONEGRAPHALLCPUS "&Tek Çizge, Tüm CPU'lar" + IDS_MENU_ONEGRAPHPERCPU "&CPU Başına Bir Çizge" IDS_MENU_CPUHISTORY "&CPU Geçmişi" - IDS_MENU_SHOWKERNELTIMES "&Çekirdek Zamanlarını Göster" + IDS_MENU_SHOWKERNELTIMES "&Çekirdek Sürelerini Göster" IDS_CREATENEWTASK "Yeni Görev Oluşturma" - IDS_CREATENEWTASK_DESC "Çalıştırılacak görevin konumunu yazınız:" - IDS_MSG_ACCESSPROCESSAFF "CPU'larla ilişkisi erişilemez veyâ değiştirilemez." - IDS_MSG_PROCESSONEPRO "Herhangi bir işlem, en az bir CPU ile ilişkili olmalıdır." - IDS_MSG_INVALIDOPTION "Geçersiz seçenek." - IDS_MSG_UNABLEDEBUGPROCESS "Yanlışlık ayıklama işlemi yapılamaz." - IDS_MSG_WARNINGDEBUG "UYARI: Bu işlemde yanlışlık ayıklama, veri yitimine neden olabilir.\nBu işleme bir yanlışlık ayıklayıcı bağlamayı doğruluyor musunuz?" - IDS_MSG_TASKMGRWARNING "Uyarı" - IDS_MSG_WARNINGTERMINATING "UYARI: Bir işlemin sonlandırılması, dizge\nkararsızlığı veyâ veri yitimi gibi istenmeyen durumlara neden olabilir. Bu\nişlemi sonlandırmayı doğruluyor musunuz?" - IDS_MSG_UNABLETERMINATEPRO "İşlem sonlandırma yapılamaz." - IDS_MSG_UNABLECHANGEPRIORITY "İşlemci önceliği değiştirilemez." - IDS_MSG_WARNINGCHANGEPRIORITY "UYARI: İşlemci önceliğinin değiştirilmesi, dizge\nkararsızlığı gibi istenmeyen durumlara neden olabilir. Bu işlemin\nişlemci önceliğini değiştirmeyi doğruluyor musunuz?" + IDS_CREATENEWTASK_DESC "Bir izlencenin, bir dizinin, bir belgenin veyâ bir Umûmî Ağ kaynağının adını yazınız, Görev Yöneticisi onu sizin için açacaktır." + IDS_MSG_ACCESSPROCESSAFF "İşlemci İlişkisinin Erişilememesi veyâ Ayarlanamaması" + IDS_MSG_PROCESSONEPRO "İşlem en azından bir işlemciyle ilişkisi olmalıdır." + IDS_MSG_INVALIDOPTION "Geçersiz Seçenek" + IDS_MSG_UNABLEDEBUGPROCESS "Yanlışlık Ayıklama İşleminin Yapılamaması" + IDS_MSG_WARNINGDEBUG "UYARI: Bu işlemde yanlışlık ayıklama veri yitimiyle sonuçlanabilir.\nYanlışlık ayıklayıcı bağlamak istediğinizi doğruluyor musunuz?" + IDS_MSG_TASKMGRWARNING "Görev Yöneticisi Uyarısı" + IDS_MSG_WARNINGTERMINATING "UYARI: Bir işlemin sonlandırılması, veri\nyitimi ve dizge kararsızlığını içeren istenmeyen sonuçlara neden\nolabilir. İşlem sonlandırılmadan önce durumunu veyâ verisini\nkaydetme fırsatı verilmeyecektir. İşlemi\nsonlandırmak istediğinizi doğruluyor musunuz?" + IDS_MSG_UNABLETERMINATEPRO "İşlem Sonlandırmanın Yapılamaması" + IDS_MSG_UNABLECHANGEPRIORITY "Önceliğin Değiştirilememesi" + IDS_MSG_WARNINGCHANGEPRIORITY "UYARI: Bu işlemin öncelik sınıfının değiştirilmesi, dizge\nkararsızlığını içeren istenmeyen sonuçlara neden olabilir. Öncelik \nsınıfını değiştirmek istediğinizi doğruluyor musunuz?" IDS_MSG_TRAYICONCPUUSAGE "CPU Kullanımı: %%%d" IDS_STATUS_MEMUSAGE "Bellek Kullanımı: %d KB / %d KB" IDS_STATUS_CPUUSAGE "CPU Kullanımı: %%%3d" - IDS_STATUS_PROCESSES "İşlem Sayısı: %d" + IDS_STATUS_PROCESSES "İşlem: %d" IDS_Not_Responding "Yanıt Vermiyor" IDS_Running "Çalışıyor" END diff --git a/base/setup/reactos/lang/tr-TR.rc b/base/setup/reactos/lang/tr-TR.rc index b7860ff9ced..0468cd7c2f8 100644 --- a/base/setup/reactos/lang/tr-TR.rc +++ b/base/setup/reactos/lang/tr-TR.rc @@ -7,9 +7,9 @@ STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYS CAPTION "ReactOS Kur" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "ReactOS Kur'a Hoşgeldiniz.", IDC_STARTTITLE, 115, 8, 195, 24 - LTEXT "Daha bu CD'den ReactOS'u doğrudan kuramazsınız. Bu CD'den ReactOS'u kurmak için bilgisayarınızı yeniden başlatınız.", IDC_STATIC, 115, 40, 195, 100 - LTEXT "Kur'dan çıkmak için ""İptal"" düğmesine tıklayınız.", IDC_STATIC, 115, 169, 195, 17 + LTEXT "ReactOS Kur Büyücüsü'ne Hoşgeldiniz", IDC_STARTTITLE, 115, 8, 195, 24 + LTEXT "Daha bu CD'den ReactOS'u doğrudan kuramazsınız. Lütfen ReactOS'u kurmak için bu CD'den bilgisayarınızı yeniden başlatınız.", IDC_STATIC, 115, 40, 195, 100 + LTEXT "Kur'dan çıkmak için İptal'e tıklayınız.", IDC_STATIC, 115, 169, 195, 17 END IDD_LANGSELPAGE DIALOGEX 0, 0, 317, 193 @@ -20,9 +20,9 @@ BEGIN CONTROL "IDB_LOGO", IDB_ROSLOGO, "Static", WS_CHILD | WS_VISIBLE | SS_OWNERDRAW, 18, 0, 290, 99 CONTROL "Kurulum Dili:", IDC_STATIC, "Static", WS_CHILD | WS_VISIBLE | WS_GROUP | SS_RIGHT, 20, 109, 106, 11 CONTROL "", IDC_LANGUAGES, "ComboBox", WS_VSCROLL | WS_TABSTOP | CBS_DROPDOWNLIST, 132, 107, 176, 142 - CONTROL "Düğme Takımı Düzeni:", IDC_STATIC, "Static", WS_CHILD | WS_VISIBLE | WS_GROUP | SS_RIGHT, 20, 142, 106, 11 + CONTROL "Düğme Takımı Giriş Yöntemi:", IDC_STATIC, "Static", WS_CHILD | WS_VISIBLE | WS_GROUP | SS_RIGHT, 20, 142, 106, 11 CONTROL "", IDC_KEYLAYOUT, "ComboBox", WS_VSCROLL | WS_TABSTOP | CBS_DROPDOWNLIST, 132, 141, 176, 81 - LTEXT "Kurulum türünü seçmek için ""İleri >"" düğmesine tıklayınız.", IDC_STATIC, 10, 180, 297, 10 + LTEXT "Kurulum türünü seçmek için İleri'ye tıklayınız.", IDC_STATIC, 10, 180, 297, 10 END IDD_TYPEPAGE DIALOGEX 0, 0, 317, 193 @@ -32,8 +32,8 @@ FONT 8, "MS Shell Dlg" BEGIN CONTROL "Kurulum Türü", IDC_STATIC, "Button", BS_GROUPBOX, 10, 0, 297, 172 CONTROL "ReactOS'u Yükleme", IDC_INSTALL, "Button", BS_AUTORADIOBUTTON | WS_TABSTOP, 20, 15, 277, 10 - CONTROL "ReactOS'u Onarma ya da Yükseltme", IDC_SETUP, "Button", BS_AUTORADIOBUTTON | WS_TABSTOP | WS_DISABLED, 20, 30, 277, 10 - LTEXT "Aygıt seçeneklerini seçmek için ""İleri >"" düğmesine tıklayınız.", IDC_STATIC, 10, 180, 297, 10 + CONTROL "Kurulu ReactOS'u Onarma ya da Yükseltme", IDC_SETUP, "Button", BS_AUTORADIOBUTTON | WS_TABSTOP | WS_DISABLED, 20, 30, 277, 10 + LTEXT "Aygıtları kurmak için İleri'ye tıklayınız.", IDC_STATIC, 10, 180, 297, 10 END IDD_DEVICEPAGE DIALOGEX 0, 0, 317, 193 @@ -41,14 +41,14 @@ STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYS CAPTION "ReactOS Kur" FONT 8, "MS Shell Dlg" BEGIN - CONTROL "Aygıt Seçenekleri", IDC_STATIC, "Button", BS_GROUPBOX, 10, 0, 297, 172 - LTEXT "Bilgisayar Türü:", IDC_STATIC, 20, 15, 80, 10 + CONTROL "Aygıt Ayarları", IDC_STATIC, "Button", BS_GROUPBOX, 10, 0, 297, 172 + LTEXT "Bilgisayar:", IDC_STATIC, 20, 15, 80, 10 CONTROL "", IDC_COMPUTER, "ComboBox", WS_VSCROLL | WS_TABSTOP | CBS_DROPDOWNLIST, 100, 15, 180, 80 - LTEXT "Görüntü Ayarları:", IDC_STATIC, 20, 35, 80, 10 + LTEXT "Görüntü:", IDC_STATIC, 20, 35, 80, 10 CONTROL "", IDC_DISPLAY, "ComboBox", WS_VSCROLL | WS_TABSTOP | CBS_DROPDOWNLIST, 100, 35, 180, 80 - LTEXT "Düğme Takımı Türü:", IDC_STATIC, 20, 55, 80, 10 + LTEXT "Düğme Takımı:", IDC_STATIC, 20, 55, 80, 10 CONTROL "", IDC_KEYBOARD, "ComboBox", WS_VSCROLL | WS_TABSTOP | CBS_DROPDOWNLIST, 100, 55, 180, 80 - LTEXT "Kurulum yapılacak bölümü seçmek için ""İleri >"" düğmesine tıklayınız.", IDC_STATIC, 10, 180, 277, 20 + LTEXT "Kurulum aygıtını kurmak için İleri'ye tıklayınız.", IDC_STATIC, 10, 180, 277, 20 END IDD_DRIVEPAGE DIALOGEX 0, 0, 317, 193 @@ -56,13 +56,13 @@ STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYS CAPTION "ReactOS Kur" FONT 8, "MS Shell Dlg" BEGIN - CONTROL "ReactOS'un Kurulacağı Bölüm", IDC_STATIC, "Button", BS_GROUPBOX, 10, 1, 298, 176 + CONTROL "ReactOS Kurulumu İçin Bölümlendirme", IDC_STATIC, "Button", BS_GROUPBOX, 10, 1, 298, 176 LISTBOX IDC_PARTITION, 20, 12, 278, 142, LBS_HASSTRINGS | WS_VSCROLL PUSHBUTTON "&Oluştur...", IDC_PARTCREATE, 20, 155, 50, 15 PUSHBUTTON "&Sil", IDC_PARTDELETE, 76, 155, 50, 15 PUSHBUTTON "S&ürücü", IDC_DEVICEDRIVER, 162, 155, 50, 15, WS_DISABLED PUSHBUTTON "G&elişmiş Seçenekler...", IDC_PARTMOREOPTS, 218, 155, 80, 15 - LTEXT "Kurulum özetini görmek için ""İleri >"" düğmesine tıklayınız.", IDC_STATIC, 10, 180, 277, 20 + LTEXT "Kurulum özetini gözden geçirmek için İleri'ye tıklayınız.", IDC_STATIC, 10, 180, 277, 20 END IDD_PARTITION DIALOGEX 0, 0, 145, 90 @@ -71,7 +71,7 @@ CAPTION "Bölüm Oluşturma" FONT 8, "MS Shell Dlg" BEGIN CONTROL "", IDC_UPDOWN1, "msctls_updown32", WS_VISIBLE, 104, 22, 9, 13 - CONTROL "Bölüm Oluşturma", IDC_STATIC, "Button", BS_GROUPBOX, 7, 5, 129, 57 + CONTROL "Bölüm Oluşturma ve Biçimlendirme", IDC_STATIC, "Button", BS_GROUPBOX, 7, 5, 129, 57 LTEXT "Büyüklük:", IDC_STATIC, 13, 24, 27, 9 EDITTEXT IDC_PARTSIZE, 52, 23, 53, 13, WS_VISIBLE | WS_TABSTOP LTEXT "GB", IDC_UNIT, 117, 24, 14, 9 @@ -83,15 +83,15 @@ END IDD_BOOTOPTIONS DIALOGEX 0, 0, 305, 116 STYLE WS_VISIBLE | WS_CAPTION -CAPTION "Gelişmiş Seçenekler" +CAPTION "Gelişmiş Bölümlendirme Seçenekleri" FONT 8, "MS Shell Dlg" BEGIN CONTROL "Kurulum Dizini", IDC_STATIC, "Button", BS_GROUPBOX, 4, 1, 298, 30 EDITTEXT IDC_PATH, 10, 11, 278, 13, WS_VISIBLE - CONTROL "Önyükleyici Kurulumu", IDC_STATIC, "Button", BS_GROUPBOX, 4, 36, 298, 52 - CONTROL "Önyükleyici, diskin MBR'sine ve VBR'sine kurulsun.", IDC_INSTFREELDR, "Button", BS_AUTORADIOBUTTON | WS_TABSTOP, 10, 46, 278, 11 - CONTROL "Önyükleyici, diskin yalnızca VBR'sine kurulsun.", IDC_INSTVBRONLY, "Button", BS_AUTORADIOBUTTON | WS_TABSTOP, 10, 57, 278, 11 - CONTROL "Önyükleyici kurulmasın.", IDC_NOINSTFREELDR, "Button", BS_AUTORADIOBUTTON | WS_TABSTOP | WS_DISABLED, 10, 68, 278, 11 + CONTROL "Ön Yükleyici Kurulumu", IDC_STATIC, "Button", BS_GROUPBOX, 4, 36, 298, 52 + CONTROL "Ön yükleyiciyi diskin üzerine kur. (MBR ve VBR)", IDC_INSTFREELDR, "Button", BS_AUTORADIOBUTTON | WS_TABSTOP, 10, 46, 278, 11 + CONTROL "Ön yükleyiciyi diskin üzerine kur. (Yalnızca VBR)", IDC_INSTVBRONLY, "Button", BS_AUTORADIOBUTTON | WS_TABSTOP, 10, 57, 278, 11 + CONTROL "Ön yükleyici kurulumu yok.", IDC_NOINSTFREELDR, "Button", BS_AUTORADIOBUTTON | WS_TABSTOP | WS_DISABLED, 10, 68, 278, 11 PUSHBUTTON "Tamam", IDOK, 180, 94, 50, 15, WS_TABSTOP | WS_VISIBLE PUSHBUTTON "İptal", IDCANCEL, 240, 94, 50, 15, WS_TABSTOP | WS_VISIBLE END @@ -102,7 +102,7 @@ CAPTION "ReactOS Kur" FONT 8, "MS Shell Dlg" BEGIN CONTROL "Kurulum Özeti", IDC_ACTION, "Button", BS_GROUPBOX, 10, 0, 297, 172 - LTEXT "Kurulumu başlatmak için ""İleri >"" düğmesine tıklayınız.", IDC_STATIC, 10, 180, 277, 20 + LTEXT "Kurulumu işlemini başlatmak için İleri'ye tıklayınız.", IDC_STATIC, 10, 180, 277, 20 END IDD_PROCESSPAGE DIALOGEX 0, 0, 317, 193 @@ -110,7 +110,7 @@ STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYS CAPTION "ReactOS Kur" FONT 8, "MS Shell Dlg" BEGIN - CONTROL "Kurulum Süreci", IDC_ACTION, "Button", BS_GROUPBOX, 10, 0, 297, 172 + CONTROL "Kurulum İşlemi", IDC_ACTION, "Button", BS_GROUPBOX, 10, 0, 297, 172 LTEXT "Kütükler yükleniyor...", IDC_ACTIVITY, 20, 50, 277, 10 LTEXT "sınama.txt", IDC_ITEM, 30, 80, 257, 10 CONTROL "", IDC_PROCESSPROGRESS, "msctls_progress32", PBS_SMOOTH | WS_CHILD | WS_VISIBLE | WS_BORDER, 20, 120, 277, 8 @@ -118,32 +118,32 @@ END IDD_RESTARTPAGE DIALOGEX 0, 0, 317, 193 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "ReactOS Kur" +CAPTION "ReactOS Kurulumunun Bitirilmesi" FONT 8, "MS Shell Dlg" BEGIN CONTROL "ReactOS Kurulumunun İlk Aşaması Bitmesi", IDC_FINISHTITLE, "Button", BS_GROUPBOX, 10, 0, 297, 172 - LTEXT "ReactOS kurulumunun ilk aşaması bitti.", IDC_STATIC, 20, 50, 277, 10 - LTEXT """Bitir"" düğmesine bastığınızda bilgisayarınız yeniden başlatılacak.", IDC_STATIC, 20, 80, 277, 10 + LTEXT "ReactOS kurulumunun ilk aşamasını başarılı bir şekilde bitirdiniz.", IDC_STATIC, 20, 50, 277, 10 + LTEXT "Bitir'e tıkladığınızda bilgisayarınız yeniden başlatılacaktır.", IDC_STATIC, 20, 80, 277, 10 CONTROL "", IDC_RESTART_PROGRESS, "msctls_progress32", PBS_SMOOTH | WS_CHILD | WS_VISIBLE | WS_BORDER, 20, 120, 277, 8 - LTEXT "Eğer bilgisayarınızda takılı bir CD varsa onu çıkarttığınızdan sonra ""Bitir"" düğmesine tıklayınız.", IDC_STATIC, 10, 180, 297, 20 + LTEXT "Eğer bir sürücüde bir CD varsa onu çıkartınız. Sonra, bilgisayarınızı yeniden başlatmak için Bitir'e tıklayınız.", IDC_STATIC, 10, 180, 297, 20 END STRINGTABLE BEGIN IDS_LANGTITLE "Dil Seçimi" - IDS_LANGSUBTITLE "Kurulum ve dizge dilini seçiniz." + IDS_LANGSUBTITLE "Kurulum ve son dizge dilini seçiniz." IDS_TYPETITLE "ReactOS Kur'a Hoşgeldiniz" IDS_TYPESUBTITLE "Kurulum türünü seçiniz." - IDS_DEVICETITLE "Aygıt Seçeneklerinin Seçilmesi" - IDS_DEVICESUBTITLE "Görüntü ayarlarını ve düğme takımı türünü seçiniz." - IDS_DRIVETITLE "Kurulum Yapılacak Bölümün Seçilmesi" - IDS_DRIVESUBTITLE "Kurulum yapılacak bölümü, kurulum dizinini ve önyükleyici seçeneklerini seçiniz." + IDS_DEVICETITLE "Ana Aygıtların Kurulumu" + IDS_DEVICESUBTITLE "Görüntü ve düğme takımı ayarlarını yapınız." + IDS_DRIVETITLE "Kurulum Bölümünün ve Dizge Dizininin Anıklanması" + IDS_DRIVESUBTITLE "Kurulum bölümünü, dizge dizinini ve ön yükleyiciyi anıklayınız." IDS_PROCESSTITLE "Bölümün Biçimlendirilmesi, Kütüklerin Çoğaltılması ve Önyükleyicinin Kurulması" - IDS_PROCESSSUBTITLE "Bölüm biçimlendiriliyor, kütükler çoğaltılıyor ve önyükleyici kuruluyor." - IDS_RESTARTTITLE "Kurulumun İlk Aşamasının Bitmesi" - IDS_RESTARTSUBTITLE "Kurulumun ilk aşaması bitti. İkincisine geçmek için bilgisayarı yeniden başlatınız." + IDS_PROCESSSUBTITLE "Bölüm oluşturuluyor ve biçimlendiriliyor, kütükler çoğaltılıyor, ön yükleyici kuruluyor ve anıklanıyor." + IDS_RESTARTTITLE "Kurulumun İlk Aşaması Bitti" + IDS_RESTARTSUBTITLE "Kurulumun ilk aşaması bitirildi, ikinci aşamayla sürdürmek için yeniden başlatınız." IDS_SUMMARYTITLE "Kurulum Özeti" - IDS_SUMMARYSUBTITLE "Kurulumdan önce, dizelgelenen kurulum seçeneklerini gözden geçiriniz." - IDS_ABORTSETUP "ReactOS kurulumu bitmedi. Eğer Kur'dan çıkarsanız, ReactOS'u kurmak için Kur'u yeniden çalıştırabilirsiniz. Çıkmayı doğruluyor musunuz?" + IDS_SUMMARYSUBTITLE "Kurulumdan aygıtına uygulanmadan önce gözden geçirmek için dizelgelenen kurulum seçenekleri." + IDS_ABORTSETUP "ReactOS bilgisayarınıza tümüyle kurulmadı. Eğer şimdi Kur'dan çıkarsanız, ReactOS'u kurmak için Kur'u yeniden çalıştırmayı isteybilirsiniz. Gerçekten çıkılsın mı?" IDS_ABORTSETUP2 "Kurulum iptal edilsin mi?" END diff --git a/base/setup/reactos/reactos.rc b/base/setup/reactos/reactos.rc index 84b31a1a4fa..3fb5b36b4b5 100644 --- a/base/setup/reactos/reactos.rc +++ b/base/setup/reactos/reactos.rc @@ -78,12 +78,12 @@ IDB_ROSLOGO BITMAP "res/rosbitmap.bmp" #ifdef LANGUAGE_SK_SK #include "lang/sk-SK.rc" #endif -#ifdef LANGUAGE_TR_TR - #include "lang/tr-TR.rc" -#endif #ifdef LANGUAGE_SQ_AL #include "lang/sq-AL.rc" #endif +#ifdef LANGUAGE_TR_TR + #include "lang/tr-TR.rc" +#endif #ifdef LANGUAGE_UK_UA #include "lang/uk-UA.rc" #endif diff --git a/base/setup/usetup/bootsup.c b/base/setup/usetup/bootsup.c index 9865e265ab3..74d5ad3ffff 100644 --- a/base/setup/usetup/bootsup.c +++ b/base/setup/usetup/bootsup.c @@ -87,7 +87,8 @@ extern PPARTLIST PartitionList; static VOID -CreateCommonFreeLoaderSections(PINICACHE IniCache) +CreateCommonFreeLoaderSections( + PINICACHE IniCache) { PINICACHESECTION IniSection; @@ -1178,7 +1179,6 @@ InstallMbrBootCodeToDisk( return Status; } - /* Allocate buffer for new bootsector */ NewBootSector = (PPARTITION_SECTOR)RtlAllocateHeap(ProcessHeap, 0, @@ -1275,9 +1275,11 @@ InstallMbrBootCodeToDisk( return Status; } + NTSTATUS -InstallFat12BootCodeToFloppy(PWSTR SrcPath, - PWSTR RootPath) +InstallFat12BootCodeToFloppy( + PWSTR SrcPath, + PWSTR RootPath) { OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; @@ -1286,21 +1288,21 @@ InstallFat12BootCodeToFloppy(PWSTR SrcPath, NTSTATUS Status; PFAT_BOOTSECTOR OrigBootSector; PFAT_BOOTSECTOR NewBootSector; - + /* Allocate buffer for original bootsector */ OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE); if (OrigBootSector == NULL) return STATUS_INSUFFICIENT_RESOURCES; - + /* Read current boot sector into buffer */ RtlInitUnicodeString(&Name, RootPath); - + InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_CASE_INSENSITIVE, NULL, NULL); - + Status = NtOpenFile(&FileHandle, GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, @@ -1312,7 +1314,7 @@ InstallFat12BootCodeToFloppy(PWSTR SrcPath, RtlFreeHeap(ProcessHeap, 0, OrigBootSector); return Status; } - + Status = NtReadFile(FileHandle, NULL, NULL, @@ -1328,8 +1330,7 @@ InstallFat12BootCodeToFloppy(PWSTR SrcPath, RtlFreeHeap(ProcessHeap, 0, OrigBootSector); return Status; } - - + /* Allocate buffer for new bootsector */ NewBootSector = RtlAllocateHeap(ProcessHeap, 0, @@ -1339,16 +1340,16 @@ InstallFat12BootCodeToFloppy(PWSTR SrcPath, RtlFreeHeap(ProcessHeap, 0, OrigBootSector); return STATUS_INSUFFICIENT_RESOURCES; } - + /* Read new bootsector from SrcPath */ RtlInitUnicodeString(&Name, SrcPath); - + InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_CASE_INSENSITIVE, NULL, NULL); - + Status = NtOpenFile(&FileHandle, GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, @@ -1361,7 +1362,7 @@ InstallFat12BootCodeToFloppy(PWSTR SrcPath, RtlFreeHeap(ProcessHeap, 0, NewBootSector); return Status; } - + Status = NtReadFile(FileHandle, NULL, NULL, @@ -1378,25 +1379,25 @@ InstallFat12BootCodeToFloppy(PWSTR SrcPath, RtlFreeHeap(ProcessHeap, 0, NewBootSector); return Status; } - + /* Adjust bootsector (copy a part of the FAT16 BPB) */ memcpy(&NewBootSector->OemName, &OrigBootSector->OemName, FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) - FIELD_OFFSET(FAT_BOOTSECTOR, OemName)); - + /* Free the original boot sector */ RtlFreeHeap(ProcessHeap, 0, OrigBootSector); - + /* Write new bootsector to RootPath */ RtlInitUnicodeString(&Name, RootPath); - + InitializeObjectAttributes(&ObjectAttributes, &Name, 0, NULL, NULL); - + Status = NtOpenFile(&FileHandle, GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, @@ -1409,7 +1410,7 @@ InstallFat12BootCodeToFloppy(PWSTR SrcPath, RtlFreeHeap(ProcessHeap, 0, NewBootSector); return Status; } - + #if 0 FilePosition.QuadPart = 0; #endif @@ -1423,10 +1424,10 @@ InstallFat12BootCodeToFloppy(PWSTR SrcPath, NULL, NULL); NtClose(FileHandle); - + /* Free the new boot sector */ RtlFreeHeap(ProcessHeap, 0, NewBootSector); - + return Status; } @@ -1487,7 +1488,6 @@ InstallFat16BootCodeToDisk( return Status; } - /* Allocate buffer for new bootsector */ NewBootSector = RtlAllocateHeap(ProcessHeap, 0, @@ -2001,6 +2001,7 @@ UpdateBootIni( return Status; } + BOOLEAN CheckInstallFatBootcodeToPartition( PUNICODE_STRING SystemRootPath) @@ -2339,6 +2340,7 @@ InstallFatBootcodeToPartition( #endif } + NTSTATUS InstallVBRToPartition( PUNICODE_STRING SystemRootPath, @@ -2373,7 +2375,7 @@ InstallFatBootcodeToFloppy( WCHAR SrcPath[MAX_PATH]; WCHAR DstPath[MAX_PATH]; NTSTATUS Status; - + /* Format the floppy first */ Status = VfatFormat(&FloppyDevice, FMIFS_FLOPPY, diff --git a/base/setup/usetup/bootsup.h b/base/setup/usetup/bootsup.h index 33b983a0228..6322bae6405 100644 --- a/base/setup/usetup/bootsup.h +++ b/base/setup/usetup/bootsup.h @@ -27,65 +27,79 @@ #pragma once NTSTATUS -CreateFreeLoaderIniForDos(PWCHAR IniPath, - PWCHAR ArcPath); +CreateFreeLoaderIniForDos( + PWCHAR IniPath, + PWCHAR ArcPath); NTSTATUS -CreateFreeLoaderIniForReactos(PWCHAR IniPath, - PWCHAR ArcPath); +CreateFreeLoaderIniForReactos( + PWCHAR IniPath, + PWCHAR ArcPath); NTSTATUS -UpdateFreeLoaderIni(PWCHAR IniPath, - PWCHAR ArcPath); +UpdateFreeLoaderIni( + PWCHAR IniPath, + PWCHAR ArcPath); NTSTATUS -SaveCurrentBootSector(PWSTR RootPath, - PWSTR DstPath); +SaveCurrentBootSector( + PWSTR RootPath, + PWSTR DstPath); NTSTATUS -InstallFat16BootCodeToFile(PWSTR SrcPath, - PWSTR DstPath, - PWSTR RootPath); +InstallFat16BootCodeToFile( + PWSTR SrcPath, + PWSTR DstPath, + PWSTR RootPath); NTSTATUS -InstallFat32BootCodeToFile(PWSTR SrcPath, - PWSTR DstPath, - PWSTR RootPath); +InstallFat32BootCodeToFile( + PWSTR SrcPath, + PWSTR DstPath, + PWSTR RootPath); NTSTATUS -InstallMbrBootCodeToDisk (PWSTR SrcPath, - PWSTR RootPath); +InstallMbrBootCodeToDisk( + PWSTR SrcPath, + PWSTR RootPath); NTSTATUS -InstallFat16BootCodeToDisk(PWSTR SrcPath, - PWSTR RootPath); +InstallFat16BootCodeToDisk( + PWSTR SrcPath, + PWSTR RootPath); NTSTATUS -InstallFat32BootCodeToDisk(PWSTR SrcPath, - PWSTR RootPath); +InstallFat32BootCodeToDisk( + PWSTR SrcPath, + PWSTR RootPath); NTSTATUS -UpdateBootIni(PWSTR BootIniPath, - PWSTR EntryName, - PWSTR EntryValue); +UpdateBootIni( + PWSTR BootIniPath, + PWSTR EntryName, + PWSTR EntryValue); BOOLEAN -CheckInstallFatBootcodeToPartition(PUNICODE_STRING SystemRootPath); +CheckInstallFatBootcodeToPartition( + PUNICODE_STRING SystemRootPath); NTSTATUS -InstallFatBootcodeToPartition(PUNICODE_STRING SystemRootPath, - PUNICODE_STRING SourceRootPath, - PUNICODE_STRING DestinationArcPath, - UCHAR PartitionType); +InstallFatBootcodeToPartition( + PUNICODE_STRING SystemRootPath, + PUNICODE_STRING SourceRootPath, + PUNICODE_STRING DestinationArcPath, + UCHAR PartitionType); NTSTATUS -InstallVBRToPartition(PUNICODE_STRING SystemRootPath, - PUNICODE_STRING SourceRootPath, - PUNICODE_STRING DestinationArcPath, - UCHAR PartitionType); +InstallVBRToPartition( + PUNICODE_STRING SystemRootPath, + PUNICODE_STRING SourceRootPath, + PUNICODE_STRING DestinationArcPath, + UCHAR PartitionType); NTSTATUS -InstallFatBootcodeToFloppy(PUNICODE_STRING SourceRootPath, - PUNICODE_STRING DestinationArcPath); +InstallFatBootcodeToFloppy( + PUNICODE_STRING SourceRootPath, + PUNICODE_STRING DestinationArcPath); /* EOF */ diff --git a/base/setup/usetup/chkdsk.c b/base/setup/usetup/chkdsk.c index 03054bcaf7b..2c5522c462e 100644 --- a/base/setup/usetup/chkdsk.c +++ b/base/setup/usetup/chkdsk.c @@ -34,7 +34,9 @@ static PPROGRESSBAR ChkdskProgressBar = NULL; /* FUNCTIONS ****************************************************************/ -static BOOLEAN NTAPI +static +BOOLEAN +NTAPI ChkdskCallback( IN CALLBACKCOMMAND Command, IN ULONG Modifier, @@ -50,6 +52,7 @@ ChkdskCallback( return TRUE; } + NTSTATUS ChkdskPartition( IN PUNICODE_STRING DriveRoot, diff --git a/base/setup/usetup/drivesup.c b/base/setup/usetup/drivesup.c index a910e9302ef..b5734302885 100644 --- a/base/setup/usetup/drivesup.c +++ b/base/setup/usetup/drivesup.c @@ -34,66 +34,66 @@ /* FUNCTIONS ****************************************************************/ NTSTATUS -GetSourcePaths(PUNICODE_STRING SourcePath, - PUNICODE_STRING SourceRootPath, - PUNICODE_STRING SourceRootDir) +GetSourcePaths( + PUNICODE_STRING SourcePath, + PUNICODE_STRING SourceRootPath, + PUNICODE_STRING SourceRootDir) { - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING LinkName; - UNICODE_STRING SourceName; - WCHAR SourceBuffer[MAX_PATH] = {L'\0'}; - HANDLE Handle; - NTSTATUS Status; - ULONG Length; - PWCHAR Ptr; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING LinkName; + UNICODE_STRING SourceName; + WCHAR SourceBuffer[MAX_PATH] = {L'\0'}; + HANDLE Handle; + NTSTATUS Status; + ULONG Length; + PWCHAR Ptr; - RtlInitUnicodeString(&LinkName, - L"\\SystemRoot"); + RtlInitUnicodeString(&LinkName, + L"\\SystemRoot"); - InitializeObjectAttributes(&ObjectAttributes, - &LinkName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); + InitializeObjectAttributes(&ObjectAttributes, + &LinkName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); - Status = NtOpenSymbolicLinkObject(&Handle, - SYMBOLIC_LINK_ALL_ACCESS, - &ObjectAttributes); - if (!NT_SUCCESS(Status)) - return(Status); + Status = NtOpenSymbolicLinkObject(&Handle, + SYMBOLIC_LINK_ALL_ACCESS, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + return Status; - SourceName.Length = 0; - SourceName.MaximumLength = MAX_PATH * sizeof(WCHAR); - SourceName.Buffer = SourceBuffer; + SourceName.Length = 0; + SourceName.MaximumLength = MAX_PATH * sizeof(WCHAR); + SourceName.Buffer = SourceBuffer; - Status = NtQuerySymbolicLinkObject(Handle, - &SourceName, - &Length); - NtClose(Handle); + Status = NtQuerySymbolicLinkObject(Handle, + &SourceName, + &Length); + NtClose(Handle); - if (NT_SUCCESS(Status)) + if (NT_SUCCESS(Status)) { - RtlCreateUnicodeString(SourcePath, - SourceName.Buffer); + RtlCreateUnicodeString(SourcePath, + SourceName.Buffer); - /* strip trailing directory */ - Ptr = wcsrchr(SourceName.Buffer, L'\\'); - if (Ptr) - { - RtlCreateUnicodeString(SourceRootDir, Ptr); - *Ptr = 0; - } - else - RtlCreateUnicodeString(SourceRootDir, L""); + /* strip trailing directory */ + Ptr = wcsrchr(SourceName.Buffer, L'\\'); + if (Ptr) + { + RtlCreateUnicodeString(SourceRootDir, Ptr); + *Ptr = 0; + } + else + RtlCreateUnicodeString(SourceRootDir, L""); - RtlCreateUnicodeString(SourceRootPath, - SourceName.Buffer); + RtlCreateUnicodeString(SourceRootPath, + SourceName.Buffer); } - NtClose(Handle); + NtClose(Handle); - return(STATUS_SUCCESS); + return STATUS_SUCCESS; } - /* EOF */ diff --git a/base/setup/usetup/drivesup.h b/base/setup/usetup/drivesup.h index 37c918cf964..3d595b9a052 100644 --- a/base/setup/usetup/drivesup.h +++ b/base/setup/usetup/drivesup.h @@ -27,8 +27,9 @@ #pragma once NTSTATUS -GetSourcePaths(PUNICODE_STRING SourcePath, - PUNICODE_STRING SourceRootPath, - PUNICODE_STRING SourceRootDir); +GetSourcePaths( + PUNICODE_STRING SourcePath, + PUNICODE_STRING SourceRootPath, + PUNICODE_STRING SourceRootDir); /* EOF */ diff --git a/base/setup/usetup/filequeue.c b/base/setup/usetup/filequeue.c index ce0b1449640..4f1bc3b33c6 100644 --- a/base/setup/usetup/filequeue.c +++ b/base/setup/usetup/filequeue.c @@ -35,407 +35,425 @@ typedef struct _QUEUEENTRY { - struct _QUEUEENTRY *Prev; - struct _QUEUEENTRY *Next; - - PWSTR SourceCabinet; /* May be NULL if file is not in a cabinet */ - PWSTR SourceRootPath; - PWSTR SourcePath; - PWSTR SourceFilename; - PWSTR TargetDirectory; - PWSTR TargetFilename; + struct _QUEUEENTRY *Prev; + struct _QUEUEENTRY *Next; + PWSTR SourceCabinet; /* May be NULL if file is not in a cabinet */ + PWSTR SourceRootPath; + PWSTR SourcePath; + PWSTR SourceFilename; + PWSTR TargetDirectory; + PWSTR TargetFilename; } QUEUEENTRY, *PQUEUEENTRY; typedef struct _FILEQUEUEHEADER { - PQUEUEENTRY CopyHead; - PQUEUEENTRY CopyTail; - ULONG CopyCount; + PQUEUEENTRY CopyHead; + PQUEUEENTRY CopyTail; + ULONG CopyCount; } FILEQUEUEHEADER, *PFILEQUEUEHEADER; /* FUNCTIONS ****************************************************************/ -HSPFILEQ WINAPI +HSPFILEQ +WINAPI SetupOpenFileQueue(VOID) { - PFILEQUEUEHEADER QueueHeader; + PFILEQUEUEHEADER QueueHeader; - /* Allocate queue header */ - QueueHeader = (PFILEQUEUEHEADER)RtlAllocateHeap(ProcessHeap, - 0, - sizeof(FILEQUEUEHEADER)); - if (QueueHeader == NULL) - return(NULL); + /* Allocate queue header */ + QueueHeader = (PFILEQUEUEHEADER)RtlAllocateHeap(ProcessHeap, + 0, + sizeof(FILEQUEUEHEADER)); + if (QueueHeader == NULL) + return NULL; - /* Initialize queue header */ - RtlZeroMemory(QueueHeader, - sizeof(FILEQUEUEHEADER)); + /* Initialize queue header */ + RtlZeroMemory(QueueHeader, + sizeof(FILEQUEUEHEADER)); - - return((HSPFILEQ)QueueHeader); + return (HSPFILEQ)QueueHeader; } -VOID WINAPI -SetupCloseFileQueue(HSPFILEQ QueueHandle) +VOID +WINAPI +SetupCloseFileQueue( + HSPFILEQ QueueHandle) { - PFILEQUEUEHEADER QueueHeader; - PQUEUEENTRY Entry; + PFILEQUEUEHEADER QueueHeader; + PQUEUEENTRY Entry; - if (QueueHandle == NULL) - return; + if (QueueHandle == NULL) + return; - QueueHeader = (PFILEQUEUEHEADER)QueueHandle; + QueueHeader = (PFILEQUEUEHEADER)QueueHandle; - /* Delete copy queue */ - Entry = QueueHeader->CopyHead; - while (Entry != NULL) + /* Delete copy queue */ + Entry = QueueHeader->CopyHead; + while (Entry != NULL) { - /* Delete all strings */ - if (Entry->SourceCabinet != NULL) - RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet); - if (Entry->SourceRootPath != NULL) - RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath); - if (Entry->SourcePath != NULL) - RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath); - if (Entry->SourceFilename != NULL) - RtlFreeHeap(ProcessHeap, 0, Entry->SourceFilename); - if (Entry->TargetDirectory != NULL) - RtlFreeHeap(ProcessHeap, 0, Entry->TargetDirectory); - if (Entry->TargetFilename != NULL) - RtlFreeHeap(ProcessHeap, 0, Entry->TargetFilename); + /* Delete all strings */ + if (Entry->SourceCabinet != NULL) + RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet); - /* Unlink current queue entry */ - if (Entry->Next != NULL) - { - QueueHeader->CopyHead = Entry->Next; - QueueHeader->CopyHead->Prev = NULL; - } - else - { - QueueHeader->CopyHead = NULL; - QueueHeader->CopyTail = NULL; - } + if (Entry->SourceRootPath != NULL) + RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath); - /* Delete queue entry */ - RtlFreeHeap(ProcessHeap, 0, Entry); + if (Entry->SourcePath != NULL) + RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath); - /* Get next queue entry */ - Entry = QueueHeader->CopyHead; + if (Entry->SourceFilename != NULL) + RtlFreeHeap(ProcessHeap, 0, Entry->SourceFilename); + + if (Entry->TargetDirectory != NULL) + RtlFreeHeap(ProcessHeap, 0, Entry->TargetDirectory); + + if (Entry->TargetFilename != NULL) + RtlFreeHeap(ProcessHeap, 0, Entry->TargetFilename); + + /* Unlink current queue entry */ + if (Entry->Next != NULL) + { + QueueHeader->CopyHead = Entry->Next; + QueueHeader->CopyHead->Prev = NULL; + } + else + { + QueueHeader->CopyHead = NULL; + QueueHeader->CopyTail = NULL; + } + + /* Delete queue entry */ + RtlFreeHeap(ProcessHeap, 0, Entry); + + /* Get next queue entry */ + Entry = QueueHeader->CopyHead; } - /* Delete queue header */ - RtlFreeHeap(ProcessHeap, - 0, - QueueHeader); + /* Delete queue header */ + RtlFreeHeap(ProcessHeap, 0, QueueHeader); } BOOL -SetupQueueCopy(HSPFILEQ QueueHandle, - PCWSTR SourceCabinet, - PCWSTR SourceRootPath, - PCWSTR SourcePath, - PCWSTR SourceFilename, - PCWSTR TargetDirectory, - PCWSTR TargetFilename) +SetupQueueCopy( + HSPFILEQ QueueHandle, + PCWSTR SourceCabinet, + PCWSTR SourceRootPath, + PCWSTR SourcePath, + PCWSTR SourceFilename, + PCWSTR TargetDirectory, + PCWSTR TargetFilename) { - PFILEQUEUEHEADER QueueHeader; - PQUEUEENTRY Entry; - ULONG Length; + PFILEQUEUEHEADER QueueHeader; + PQUEUEENTRY Entry; + ULONG Length; - /* SourceCabinet may be NULL */ - if (QueueHandle == NULL || - SourceRootPath == NULL || - SourceFilename == NULL || - TargetDirectory == NULL) - return(FALSE); + /* SourceCabinet may be NULL */ + if (QueueHandle == NULL || + SourceRootPath == NULL || + SourceFilename == NULL || + TargetDirectory == NULL) + return FALSE; - QueueHeader = (PFILEQUEUEHEADER)QueueHandle; + QueueHeader = (PFILEQUEUEHEADER)QueueHandle; - /* Allocate new queue entry */ - Entry = (PQUEUEENTRY)RtlAllocateHeap(ProcessHeap, - 0, - sizeof(QUEUEENTRY)); - if (Entry == NULL) - return(FALSE); + /* Allocate new queue entry */ + Entry = (PQUEUEENTRY)RtlAllocateHeap(ProcessHeap, + 0, + sizeof(QUEUEENTRY)); + if (Entry == NULL) + return FALSE; - RtlZeroMemory(Entry, - sizeof(QUEUEENTRY)); + RtlZeroMemory(Entry, + sizeof(QUEUEENTRY)); - /* Copy source cabinet if available */ - if (SourceCabinet != NULL) + /* Copy source cabinet if available */ + if (SourceCabinet != NULL) { - Length = wcslen(SourceCabinet); - Entry->SourceCabinet = (WCHAR*) RtlAllocateHeap(ProcessHeap, - 0, - (Length + 1) * sizeof(WCHAR)); - if (Entry->SourceCabinet == NULL) - { + Length = wcslen(SourceCabinet); + Entry->SourceCabinet = (WCHAR*)RtlAllocateHeap(ProcessHeap, + 0, + (Length + 1) * sizeof(WCHAR)); + if (Entry->SourceCabinet == NULL) + { + RtlFreeHeap(ProcessHeap, 0, Entry); + return FALSE; + } + + wcsncpy(Entry->SourceCabinet, SourceCabinet, Length); + Entry->SourceCabinet[Length] = (WCHAR)0; + } + else + { + Entry->SourceCabinet = NULL; + } + + /* Copy source root path */ + Length = wcslen(SourceRootPath); + Entry->SourceRootPath = (WCHAR*)RtlAllocateHeap(ProcessHeap, + 0, + (Length + 1) * sizeof(WCHAR)); + if (Entry->SourceRootPath == NULL) + { + if (Entry->SourceCabinet != NULL) + { + RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet); + } + RtlFreeHeap(ProcessHeap, 0, Entry); - return(FALSE); - } - wcsncpy(Entry->SourceCabinet, SourceCabinet, Length); - Entry->SourceCabinet[Length] = (WCHAR)0; - } - else - { - Entry->SourceCabinet = NULL; + return FALSE; } - /* Copy source root path */ - Length = wcslen(SourceRootPath); - Entry->SourceRootPath = (WCHAR*) RtlAllocateHeap(ProcessHeap, - 0, - (Length + 1) * sizeof(WCHAR)); - if (Entry->SourceRootPath == NULL) - { - if (Entry->SourceCabinet != NULL) - { - RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet); - } - RtlFreeHeap(ProcessHeap, 0, Entry); - return(FALSE); - } - wcsncpy(Entry->SourceRootPath, SourceRootPath, Length); - Entry->SourceRootPath[Length] = (WCHAR)0; + wcsncpy(Entry->SourceRootPath, SourceRootPath, Length); + Entry->SourceRootPath[Length] = (WCHAR)0; - /* Copy source path */ - if (SourcePath != NULL) - { - Length = wcslen(SourcePath); - Entry->SourcePath = (WCHAR*) RtlAllocateHeap(ProcessHeap, - 0, - (Length + 1) * sizeof(WCHAR)); - if (Entry->SourcePath == NULL) + /* Copy source path */ + if (SourcePath != NULL) { - if (Entry->SourceCabinet != NULL) + Length = wcslen(SourcePath); + Entry->SourcePath = (WCHAR*)RtlAllocateHeap(ProcessHeap, + 0, + (Length + 1) * sizeof(WCHAR)); + if (Entry->SourcePath == NULL) { - RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet); + if (Entry->SourceCabinet != NULL) + { + RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet); + } + + RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath); + RtlFreeHeap(ProcessHeap, 0, Entry); + return FALSE; } - RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath); - RtlFreeHeap(ProcessHeap, 0, Entry); - return(FALSE); + + wcsncpy(Entry->SourcePath, SourcePath, Length); + Entry->SourcePath[Length] = (WCHAR)0; } - wcsncpy(Entry->SourcePath, SourcePath, Length); - Entry->SourcePath[Length] = (WCHAR)0; - } - /* Copy source file name */ - Length = wcslen(SourceFilename); - Entry->SourceFilename = (WCHAR*) RtlAllocateHeap(ProcessHeap, - 0, - (Length + 1) * sizeof(WCHAR)); - if (Entry->SourceFilename == NULL) - { - if (Entry->SourceCabinet != NULL) - { - RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet); - } - RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath); - RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath); - RtlFreeHeap(ProcessHeap, 0, Entry); - return(FALSE); - } - wcsncpy(Entry->SourceFilename, SourceFilename, Length); - Entry->SourceFilename[Length] = (WCHAR)0; - - /* Copy target directory */ - Length = wcslen(TargetDirectory); - if (TargetDirectory[Length] == '\\') - Length--; - Entry->TargetDirectory = (WCHAR*) RtlAllocateHeap(ProcessHeap, - 0, - (Length + 1) * sizeof(WCHAR)); - if (Entry->TargetDirectory == NULL) - { - if (Entry->SourceCabinet != NULL) - { - RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet); - } - RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath); - RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath); - RtlFreeHeap(ProcessHeap, 0, Entry->SourceFilename); - RtlFreeHeap(ProcessHeap, 0, Entry); - return(FALSE); - } - wcsncpy(Entry->TargetDirectory, TargetDirectory, Length); - Entry->TargetDirectory[Length] = (WCHAR)0; - - /* Copy optional target filename */ - if (TargetFilename != NULL) - { - Length = wcslen(TargetFilename); - Entry->TargetFilename = (WCHAR*) RtlAllocateHeap(ProcessHeap, - 0, - (Length + 1) * sizeof(WCHAR)); - if (Entry->TargetFilename == NULL) + /* Copy source file name */ + Length = wcslen(SourceFilename); + Entry->SourceFilename = (WCHAR*)RtlAllocateHeap(ProcessHeap, + 0, + (Length + 1) * sizeof(WCHAR)); + if (Entry->SourceFilename == NULL) { - if (Entry->SourceCabinet != NULL) + if (Entry->SourceCabinet != NULL) { - RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet); + RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet); } - RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath); - RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath); - RtlFreeHeap(ProcessHeap, 0, Entry->SourceFilename); - RtlFreeHeap(ProcessHeap, 0, Entry->TargetDirectory); - RtlFreeHeap(ProcessHeap, 0, Entry); - return(FALSE); + + RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath); + RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath); + RtlFreeHeap(ProcessHeap, 0, Entry); + return FALSE; } - wcsncpy(Entry->TargetFilename, TargetFilename, Length); - Entry->TargetFilename[Length] = (WCHAR)0; - } - /* Append queue entry */ - if (QueueHeader->CopyHead == NULL) // && QueueHeader->CopyTail == NULL) - { - Entry->Prev = NULL; - Entry->Next = NULL; - QueueHeader->CopyHead = Entry; - QueueHeader->CopyTail = Entry; - } - else - { - Entry->Prev = QueueHeader->CopyTail; - Entry->Next = NULL; - QueueHeader->CopyTail->Next = Entry; - QueueHeader->CopyTail = Entry; - } - QueueHeader->CopyCount++; + wcsncpy(Entry->SourceFilename, SourceFilename, Length); + Entry->SourceFilename[Length] = (WCHAR)0; - return(TRUE); + /* Copy target directory */ + Length = wcslen(TargetDirectory); + if (TargetDirectory[Length] == '\\') + Length--; + Entry->TargetDirectory = (WCHAR*)RtlAllocateHeap(ProcessHeap, + 0, + (Length + 1) * sizeof(WCHAR)); + if (Entry->TargetDirectory == NULL) + { + if (Entry->SourceCabinet != NULL) + { + RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet); + } + + RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath); + RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath); + RtlFreeHeap(ProcessHeap, 0, Entry->SourceFilename); + RtlFreeHeap(ProcessHeap, 0, Entry); + return FALSE; + } + + wcsncpy(Entry->TargetDirectory, TargetDirectory, Length); + Entry->TargetDirectory[Length] = (WCHAR)0; + + /* Copy optional target filename */ + if (TargetFilename != NULL) + { + Length = wcslen(TargetFilename); + Entry->TargetFilename = (WCHAR*)RtlAllocateHeap(ProcessHeap, + 0, + (Length + 1) * sizeof(WCHAR)); + if (Entry->TargetFilename == NULL) + { + if (Entry->SourceCabinet != NULL) + { + RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet); + } + + RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath); + RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath); + RtlFreeHeap(ProcessHeap, 0, Entry->SourceFilename); + RtlFreeHeap(ProcessHeap, 0, Entry->TargetDirectory); + RtlFreeHeap(ProcessHeap, 0, Entry); + return FALSE; + } + + wcsncpy(Entry->TargetFilename, TargetFilename, Length); + Entry->TargetFilename[Length] = (WCHAR)0; + } + + /* Append queue entry */ + if (QueueHeader->CopyHead == NULL) // && QueueHeader->CopyTail == NULL) + { + Entry->Prev = NULL; + Entry->Next = NULL; + QueueHeader->CopyHead = Entry; + QueueHeader->CopyTail = Entry; + } + else + { + Entry->Prev = QueueHeader->CopyTail; + Entry->Next = NULL; + QueueHeader->CopyTail->Next = Entry; + QueueHeader->CopyTail = Entry; + } + + QueueHeader->CopyCount++; + + return TRUE; } -BOOL WINAPI -SetupCommitFileQueueW(HWND Owner, - HSPFILEQ QueueHandle, - PSP_FILE_CALLBACK_W MsgHandler, - PVOID Context) +BOOL +WINAPI +SetupCommitFileQueueW( + HWND Owner, + HSPFILEQ QueueHandle, + PSP_FILE_CALLBACK_W MsgHandler, + PVOID Context) { - WCHAR CabinetName[MAX_PATH]; - PFILEQUEUEHEADER QueueHeader; - PQUEUEENTRY Entry; - NTSTATUS Status; - PCWSTR TargetRootPath, TargetPath; + WCHAR CabinetName[MAX_PATH]; + PFILEQUEUEHEADER QueueHeader; + PQUEUEENTRY Entry; + NTSTATUS Status; + PCWSTR TargetRootPath, TargetPath; - WCHAR FileSrcPath[MAX_PATH]; - WCHAR FileDstPath[MAX_PATH]; + WCHAR FileSrcPath[MAX_PATH]; + WCHAR FileDstPath[MAX_PATH]; - TargetRootPath = ((PCOPYCONTEXT)Context)->DestinationRootPath; - TargetPath = ((PCOPYCONTEXT)Context)->InstallPath; + TargetRootPath = ((PCOPYCONTEXT)Context)->DestinationRootPath; + TargetPath = ((PCOPYCONTEXT)Context)->InstallPath; - if (QueueHandle == NULL) - return(FALSE); + if (QueueHandle == NULL) + return FALSE; - QueueHeader = (PFILEQUEUEHEADER)QueueHandle; - - MsgHandler(Context, - SPFILENOTIFY_STARTQUEUE, - 0, - 0); - - MsgHandler(Context, - SPFILENOTIFY_STARTSUBQUEUE, - FILEOP_COPY, - QueueHeader->CopyCount); - - /* Commit copy queue */ - Entry = QueueHeader->CopyHead; - while (Entry != NULL) - { - wcscpy(FileSrcPath, Entry->SourceRootPath); - if (Entry->SourcePath != NULL) - wcscat(FileSrcPath, Entry->SourcePath); - wcscat(FileSrcPath, L"\\"); - wcscat(FileSrcPath, Entry->SourceFilename); - - /* Build the full target path */ - wcscpy(FileDstPath, TargetRootPath); - if (Entry->TargetDirectory[0] == L'\\') - { - wcscat(FileDstPath, Entry->TargetDirectory); - } - else - { - if (TargetPath != NULL) - { - if (TargetPath[0] != L'\\') - wcscat(FileDstPath, L"\\"); - wcscat(FileDstPath, TargetPath); - } - wcscat(FileDstPath, L"\\"); - wcscat(FileDstPath, Entry->TargetDirectory); - } - - /* Use only the destination path if the file is in a cabinet */ - if (Entry->SourceCabinet == NULL) - { - wcscat(FileDstPath, L"\\"); - if (Entry->TargetFilename != NULL) - wcscat(FileDstPath, Entry->TargetFilename); - else - wcscat(FileDstPath, Entry->SourceFilename); - } - - /* FIXME: Do it! */ - DPRINT("'%S' ==> '%S'\n", - FileSrcPath, - FileDstPath); + QueueHeader = (PFILEQUEUEHEADER)QueueHandle; MsgHandler(Context, - SPFILENOTIFY_STARTCOPY, - (UINT_PTR)Entry->SourceFilename, - FILEOP_COPY); + SPFILENOTIFY_STARTQUEUE, + 0, + 0); - if (Entry->SourceCabinet != NULL) - { - /* Extract the file */ - wcscpy(CabinetName, Entry->SourceRootPath); + MsgHandler(Context, + SPFILENOTIFY_STARTSUBQUEUE, + FILEOP_COPY, + QueueHeader->CopyCount); + + /* Commit copy queue */ + Entry = QueueHeader->CopyHead; + while (Entry != NULL) + { + wcscpy(FileSrcPath, Entry->SourceRootPath); if (Entry->SourcePath != NULL) - wcscat(CabinetName, Entry->SourcePath); - wcscat(CabinetName, L"\\"); - wcscat(CabinetName, Entry->SourceCabinet); - Status = SetupExtractFile(CabinetName, Entry->SourceFilename, FileDstPath); - } - else - { - /* Copy the file */ - Status = SetupCopyFile(FileSrcPath, FileDstPath); - } - if (!NT_SUCCESS(Status)) - { - MsgHandler(Context, - SPFILENOTIFY_COPYERROR, - (UINT_PTR)Entry->SourceFilename, - FILEOP_COPY); + wcscat(FileSrcPath, Entry->SourcePath); + wcscat(FileSrcPath, L"\\"); + wcscat(FileSrcPath, Entry->SourceFilename); - } - else - { - MsgHandler(Context, - SPFILENOTIFY_ENDCOPY, - (UINT_PTR)Entry->SourceFilename, - FILEOP_COPY); + /* Build the full target path */ + wcscpy(FileDstPath, TargetRootPath); + if (Entry->TargetDirectory[0] == L'\\') + { + wcscat(FileDstPath, Entry->TargetDirectory); + } + else + { + if (TargetPath != NULL) + { + if (TargetPath[0] != L'\\') + wcscat(FileDstPath, L"\\"); + wcscat(FileDstPath, TargetPath); + } + + wcscat(FileDstPath, L"\\"); + wcscat(FileDstPath, Entry->TargetDirectory); + } + + /* Use only the destination path if the file is in a cabinet */ + if (Entry->SourceCabinet == NULL) + { + wcscat(FileDstPath, L"\\"); + if (Entry->TargetFilename != NULL) + wcscat(FileDstPath, Entry->TargetFilename); + else + wcscat(FileDstPath, Entry->SourceFilename); + } + + /* FIXME: Do it! */ + DPRINT("'%S' ==> '%S'\n", FileSrcPath, FileDstPath); + + MsgHandler(Context, + SPFILENOTIFY_STARTCOPY, + (UINT_PTR)Entry->SourceFilename, + FILEOP_COPY); + + if (Entry->SourceCabinet != NULL) + { + /* Extract the file */ + wcscpy(CabinetName, Entry->SourceRootPath); + if (Entry->SourcePath != NULL) + wcscat(CabinetName, Entry->SourcePath); + wcscat(CabinetName, L"\\"); + wcscat(CabinetName, Entry->SourceCabinet); + Status = SetupExtractFile(CabinetName, Entry->SourceFilename, FileDstPath); + } + else + { + /* Copy the file */ + Status = SetupCopyFile(FileSrcPath, FileDstPath); + } + + if (!NT_SUCCESS(Status)) + { + MsgHandler(Context, + SPFILENOTIFY_COPYERROR, + (UINT_PTR)Entry->SourceFilename, + FILEOP_COPY); + } + else + { + MsgHandler(Context, + SPFILENOTIFY_ENDCOPY, + (UINT_PTR)Entry->SourceFilename, + FILEOP_COPY); + } + + Entry = Entry->Next; } - Entry = Entry->Next; - } + MsgHandler(Context, + SPFILENOTIFY_ENDSUBQUEUE, + FILEOP_COPY, + 0); - MsgHandler(Context, - SPFILENOTIFY_ENDSUBQUEUE, - FILEOP_COPY, - 0); + MsgHandler(Context, + SPFILENOTIFY_ENDQUEUE, + 0, + 0); - MsgHandler(Context, - SPFILENOTIFY_ENDQUEUE, - 0, - 0); - - return(TRUE); + return TRUE; } /* EOF */ diff --git a/base/setup/usetup/filequeue.h b/base/setup/usetup/filequeue.h index 7dc8587d548..17ebe04fe0e 100644 --- a/base/setup/usetup/filequeue.h +++ b/base/setup/usetup/filequeue.h @@ -51,55 +51,62 @@ typedef PVOID HSPFILEQ; -typedef UINT (CALLBACK* PSP_FILE_CALLBACK_W)(PVOID Context, - UINT Notification, - UINT_PTR Param1, - UINT_PTR Param2); +typedef UINT (CALLBACK* PSP_FILE_CALLBACK_W)( + PVOID Context, + UINT Notification, + UINT_PTR Param1, + UINT_PTR Param2); typedef struct _COPYCONTEXT { - LPCWSTR DestinationRootPath; /* Not owned by this structure */ - LPCWSTR InstallPath; /* Not owned by this structure */ - ULONG TotalOperations; - ULONG CompletedOperations; - PPROGRESSBAR ProgressBar; - PPROGRESSBAR MemoryBars[4]; + LPCWSTR DestinationRootPath; /* Not owned by this structure */ + LPCWSTR InstallPath; /* Not owned by this structure */ + ULONG TotalOperations; + ULONG CompletedOperations; + PPROGRESSBAR ProgressBar; + PPROGRESSBAR MemoryBars[4]; } COPYCONTEXT, *PCOPYCONTEXT; /* FUNCTIONS ****************************************************************/ -HSPFILEQ WINAPI +HSPFILEQ +WINAPI SetupOpenFileQueue(VOID); -VOID WINAPI +VOID +WINAPI SetupCloseFileQueue( - IN HSPFILEQ QueueHandle); - -BOOL WINAPI -SetupQueueCopyWNew( - IN HSPFILEQ QueueHandle, - IN PCWSTR SourceRootPath, - IN PCWSTR SourcePath, - IN PCWSTR SourceFileName, - IN PCWSTR SourceDescription, - IN PCWSTR SourceTagFile, - IN PCWSTR TargetDirectory, - IN PCWSTR TargetFileName, - IN DWORD CopyStyle); + IN HSPFILEQ QueueHandle); BOOL -SetupQueueCopy(HSPFILEQ QueueHandle, - PCWSTR SourceCabinet, - PCWSTR SourceRootPath, - PCWSTR SourcePath, - PCWSTR SourceFilename, - PCWSTR TargetDirectory, - PCWSTR TargetFilename); +WINAPI +SetupQueueCopyWNew( + IN HSPFILEQ QueueHandle, + IN PCWSTR SourceRootPath, + IN PCWSTR SourcePath, + IN PCWSTR SourceFileName, + IN PCWSTR SourceDescription, + IN PCWSTR SourceTagFile, + IN PCWSTR TargetDirectory, + IN PCWSTR TargetFileName, + IN DWORD CopyStyle); -BOOL WINAPI -SetupCommitFileQueueW(HWND Owner, - HSPFILEQ QueueHandle, - PSP_FILE_CALLBACK_W MsgHandler, - PVOID Context); +BOOL +SetupQueueCopy( + HSPFILEQ QueueHandle, + PCWSTR SourceCabinet, + PCWSTR SourceRootPath, + PCWSTR SourcePath, + PCWSTR SourceFilename, + PCWSTR TargetDirectory, + PCWSTR TargetFilename); + +BOOL +WINAPI +SetupCommitFileQueueW( + HWND Owner, + HSPFILEQ QueueHandle, + PSP_FILE_CALLBACK_W MsgHandler, + PVOID Context); /* EOF */ diff --git a/base/setup/usetup/filesup.c b/base/setup/usetup/filesup.c index 290208857a2..eaabc3d479f 100644 --- a/base/setup/usetup/filesup.c +++ b/base/setup/usetup/filesup.c @@ -38,358 +38,373 @@ static WCHAR CurrentCabinetName[MAX_PATH]; static CAB_SEARCH Search; NTSTATUS -SetupCreateDirectory(PWCHAR DirectoryName) +SetupCreateDirectory( + PWCHAR DirectoryName) { - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - UNICODE_STRING PathName; - HANDLE DirectoryHandle; - NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING PathName; + HANDLE DirectoryHandle; + NTSTATUS Status; - RtlCreateUnicodeString(&PathName, - DirectoryName); - if (PathName.Length > sizeof(WCHAR) && - PathName.Buffer[PathName.Length / sizeof(WCHAR) - 2] == L'\\' && - PathName.Buffer[PathName.Length / sizeof(WCHAR) - 1] == L'.') + RtlCreateUnicodeString(&PathName, + DirectoryName); + if (PathName.Length > sizeof(WCHAR) && + PathName.Buffer[PathName.Length / sizeof(WCHAR) - 2] == L'\\' && + PathName.Buffer[PathName.Length / sizeof(WCHAR) - 1] == L'.') { - PathName.Length -= sizeof(WCHAR); - PathName.Buffer[PathName.Length / sizeof(WCHAR)] = 0; + PathName.Length -= sizeof(WCHAR); + PathName.Buffer[PathName.Length / sizeof(WCHAR)] = 0; } - if (PathName.Length > sizeof(WCHAR) && - PathName.Buffer[PathName.Length / sizeof(WCHAR) - 1] == L'\\') + if (PathName.Length > sizeof(WCHAR) && + PathName.Buffer[PathName.Length / sizeof(WCHAR) - 1] == L'\\') { - PathName.Length -= sizeof(WCHAR); - PathName.Buffer[PathName.Length / sizeof(WCHAR)] = 0; - } - - InitializeObjectAttributes(&ObjectAttributes, - &PathName, - OBJ_CASE_INSENSITIVE | OBJ_INHERIT, - NULL, - NULL); - - Status = NtCreateFile(&DirectoryHandle, - DIRECTORY_ALL_ACCESS, - &ObjectAttributes, - &IoStatusBlock, - NULL, - FILE_ATTRIBUTE_DIRECTORY, - FILE_SHARE_READ | FILE_SHARE_WRITE, - FILE_OPEN_IF, - FILE_DIRECTORY_FILE, - NULL, - 0); - if (NT_SUCCESS(Status)) - { - NtClose(DirectoryHandle); + PathName.Length -= sizeof(WCHAR); + PathName.Buffer[PathName.Length / sizeof(WCHAR)] = 0; } - RtlFreeUnicodeString(&PathName); + InitializeObjectAttributes(&ObjectAttributes, + &PathName, + OBJ_CASE_INSENSITIVE | OBJ_INHERIT, + NULL, + NULL); - return(Status); + Status = NtCreateFile(&DirectoryHandle, + DIRECTORY_ALL_ACCESS, + &ObjectAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_DIRECTORY, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN_IF, + FILE_DIRECTORY_FILE, + NULL, + 0); + if (NT_SUCCESS(Status)) + { + NtClose(DirectoryHandle); + } + + RtlFreeUnicodeString(&PathName); + + return Status; } NTSTATUS -SetupCopyFile(PWCHAR SourceFileName, - PWCHAR DestinationFileName) +SetupCopyFile( + PWCHAR SourceFileName, + PWCHAR DestinationFileName) { - OBJECT_ATTRIBUTES ObjectAttributes; - HANDLE FileHandleSource; - HANDLE FileHandleDest; - static IO_STATUS_BLOCK IoStatusBlock; - FILE_STANDARD_INFORMATION FileStandard; - FILE_BASIC_INFORMATION FileBasic; - ULONG RegionSize; - UNICODE_STRING FileName; - NTSTATUS Status; - PVOID SourceFileMap = 0; - HANDLE SourceFileSection; - SIZE_T SourceSectionSize = 0; - LARGE_INTEGER ByteOffset; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE FileHandleSource; + HANDLE FileHandleDest; + static IO_STATUS_BLOCK IoStatusBlock; + FILE_STANDARD_INFORMATION FileStandard; + FILE_BASIC_INFORMATION FileBasic; + ULONG RegionSize; + UNICODE_STRING FileName; + NTSTATUS Status; + PVOID SourceFileMap = 0; + HANDLE SourceFileSection; + SIZE_T SourceSectionSize = 0; + LARGE_INTEGER ByteOffset; #ifdef __REACTOS__ - RtlInitUnicodeString(&FileName, - SourceFileName); + RtlInitUnicodeString(&FileName, + SourceFileName); - InitializeObjectAttributes(&ObjectAttributes, - &FileName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); + InitializeObjectAttributes(&ObjectAttributes, + &FileName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); - Status = NtOpenFile(&FileHandleSource, - GENERIC_READ, - &ObjectAttributes, - &IoStatusBlock, - FILE_SHARE_READ, - FILE_SEQUENTIAL_ONLY); - if(!NT_SUCCESS(Status)) + Status = NtOpenFile(&FileHandleSource, + GENERIC_READ, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_READ, + FILE_SEQUENTIAL_ONLY); + if (!NT_SUCCESS(Status)) { - DPRINT1("NtOpenFile failed: %x, %wZ\n", Status, &FileName); - goto done; + DPRINT1("NtOpenFile failed: %x, %wZ\n", Status, &FileName); + goto done; } #else - FileHandleSource = CreateFileW(SourceFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - if (FileHandleSource == INVALID_HANDLE_VALUE) - { - Status = STATUS_UNSUCCESSFUL; - goto done; - } + FileHandleSource = CreateFileW(SourceFileName, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + 0, + NULL); + if (FileHandleSource == INVALID_HANDLE_VALUE) + { + Status = STATUS_UNSUCCESSFUL; + goto done; + } #endif - Status = NtQueryInformationFile(FileHandleSource, - &IoStatusBlock, - &FileStandard, - sizeof(FILE_STANDARD_INFORMATION), - FileStandardInformation); - if(!NT_SUCCESS(Status)) + Status = NtQueryInformationFile(FileHandleSource, + &IoStatusBlock, + &FileStandard, + sizeof(FILE_STANDARD_INFORMATION), + FileStandardInformation); + if (!NT_SUCCESS(Status)) { - DPRINT1("NtQueryInformationFile failed: %x\n", Status); - goto closesrc; - } - Status = NtQueryInformationFile(FileHandleSource, - &IoStatusBlock,&FileBasic, - sizeof(FILE_BASIC_INFORMATION), - FileBasicInformation); - if(!NT_SUCCESS(Status)) - { - DPRINT1("NtQueryInformationFile failed: %x\n", Status); - goto closesrc; + DPRINT1("NtQueryInformationFile failed: %x\n", Status); + goto closesrc; } - Status = NtCreateSection( &SourceFileSection, - SECTION_MAP_READ, - NULL, - NULL, - PAGE_READONLY, - SEC_COMMIT, - FileHandleSource); - if(!NT_SUCCESS(Status)) + Status = NtQueryInformationFile(FileHandleSource, + &IoStatusBlock,&FileBasic, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtQueryInformationFile failed: %x\n", Status); + goto closesrc; + } + + Status = NtCreateSection(&SourceFileSection, + SECTION_MAP_READ, + NULL, + NULL, + PAGE_READONLY, + SEC_COMMIT, + FileHandleSource); + if (!NT_SUCCESS(Status)) { DPRINT1("NtCreateSection failed: %x, %S\n", Status, SourceFileName); goto closesrc; } - Status = NtMapViewOfSection( SourceFileSection, - NtCurrentProcess(), - &SourceFileMap, - 0, - 0, - NULL, - &SourceSectionSize, - ViewUnmap, - 0, - PAGE_READONLY ); - if(!NT_SUCCESS(Status)) + Status = NtMapViewOfSection(SourceFileSection, + NtCurrentProcess(), + &SourceFileMap, + 0, + 0, + NULL, + &SourceSectionSize, + ViewUnmap, + 0, + PAGE_READONLY ); + if (!NT_SUCCESS(Status)) { - DPRINT1("NtMapViewOfSection failed: %x, %S\n", Status, SourceFileName); - goto closesrcsec; + DPRINT1("NtMapViewOfSection failed: %x, %S\n", Status, SourceFileName); + goto closesrcsec; } - RtlInitUnicodeString(&FileName, - DestinationFileName); + RtlInitUnicodeString(&FileName, + DestinationFileName); - InitializeObjectAttributes(&ObjectAttributes, - &FileName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); + InitializeObjectAttributes(&ObjectAttributes, + &FileName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); - Status = NtCreateFile(&FileHandleDest, - GENERIC_WRITE | SYNCHRONIZE, - &ObjectAttributes, - &IoStatusBlock, - NULL, - FILE_ATTRIBUTE_NORMAL, - 0, - FILE_OVERWRITE_IF, - FILE_NO_INTERMEDIATE_BUFFERING | - FILE_SEQUENTIAL_ONLY | - FILE_SYNCHRONOUS_IO_NONALERT, - NULL, - 0); - if(!NT_SUCCESS(Status)) + Status = NtCreateFile(&FileHandleDest, + GENERIC_WRITE | SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + 0, + FILE_OVERWRITE_IF, + FILE_NO_INTERMEDIATE_BUFFERING | + FILE_SEQUENTIAL_ONLY | + FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + if (!NT_SUCCESS(Status)) { - DPRINT1("NtCreateFile failed: %x\n", Status); - goto unmapsrcsec; + DPRINT1("NtCreateFile failed: %x\n", Status); + goto unmapsrcsec; } - RegionSize = (ULONG)PAGE_ROUND_UP(FileStandard.EndOfFile.u.LowPart); - IoStatusBlock.Status = 0; - ByteOffset.QuadPart = 0; - Status = NtWriteFile(FileHandleDest, - NULL, - NULL, - NULL, - &IoStatusBlock, - SourceFileMap, - RegionSize, - &ByteOffset, - NULL); - if(!NT_SUCCESS(Status)) + RegionSize = (ULONG)PAGE_ROUND_UP(FileStandard.EndOfFile.u.LowPart); + IoStatusBlock.Status = 0; + ByteOffset.QuadPart = 0; + Status = NtWriteFile(FileHandleDest, + NULL, + NULL, + NULL, + &IoStatusBlock, + SourceFileMap, + RegionSize, + &ByteOffset, + NULL); + if (!NT_SUCCESS(Status)) { - DPRINT1("NtWriteFile failed: %x:%x, iosb: %p src: %p, size: %x\n", Status, IoStatusBlock.Status, &IoStatusBlock, SourceFileMap, RegionSize); - goto closedest; - } - /* Copy file date/time from source file */ - Status = NtSetInformationFile(FileHandleDest, - &IoStatusBlock, - &FileBasic, - sizeof(FILE_BASIC_INFORMATION), - FileBasicInformation); - if(!NT_SUCCESS(Status)) - { - DPRINT1("NtSetInformationFile failed: %x\n", Status); - goto closedest; + DPRINT1("NtWriteFile failed: %x:%x, iosb: %p src: %p, size: %x\n", Status, IoStatusBlock.Status, &IoStatusBlock, SourceFileMap, RegionSize); + goto closedest; } - /* shorten the file back to it's real size after completing the write */ - Status = NtSetInformationFile(FileHandleDest, - &IoStatusBlock, - &FileStandard.EndOfFile, - sizeof(FILE_END_OF_FILE_INFORMATION), - FileEndOfFileInformation); - - if(!NT_SUCCESS(Status)) + /* Copy file date/time from source file */ + Status = NtSetInformationFile(FileHandleDest, + &IoStatusBlock, + &FileBasic, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + if (!NT_SUCCESS(Status)) { - DPRINT1("NtSetInformationFile failed: %x\n", Status); + DPRINT1("NtSetInformationFile failed: %x\n", Status); + goto closedest; } - closedest: - NtClose(FileHandleDest); - unmapsrcsec: - NtUnmapViewOfSection( NtCurrentProcess(), SourceFileMap ); - closesrcsec: - NtClose(SourceFileSection); - closesrc: - NtClose(FileHandleSource); - done: - return(Status); + /* shorten the file back to it's real size after completing the write */ + Status = NtSetInformationFile(FileHandleDest, + &IoStatusBlock, + &FileStandard.EndOfFile, + sizeof(FILE_END_OF_FILE_INFORMATION), + FileEndOfFileInformation); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtSetInformationFile failed: %x\n", Status); + } + +closedest: + NtClose(FileHandleDest); + +unmapsrcsec: + NtUnmapViewOfSection(NtCurrentProcess(), SourceFileMap); + +closesrcsec: + NtClose(SourceFileSection); + +closesrc: + NtClose(FileHandleSource); + +done: + return Status; } #ifdef __REACTOS__ NTSTATUS -SetupExtractFile(PWCHAR CabinetFileName, - PWCHAR SourceFileName, - PWCHAR DestinationPathName) +SetupExtractFile( + PWCHAR CabinetFileName, + PWCHAR SourceFileName, + PWCHAR DestinationPathName) { - ULONG CabStatus; + ULONG CabStatus; - DPRINT("SetupExtractFile(CabinetFileName %S, SourceFileName %S, DestinationPathName %S)\n", - CabinetFileName, SourceFileName, DestinationPathName); + DPRINT("SetupExtractFile(CabinetFileName %S, SourceFileName %S, DestinationPathName %S)\n", + CabinetFileName, SourceFileName, DestinationPathName); - if (HasCurrentCabinet) + if (HasCurrentCabinet) { - DPRINT("CurrentCabinetName: %S\n", CurrentCabinetName); + DPRINT("CurrentCabinetName: %S\n", CurrentCabinetName); } - if ((HasCurrentCabinet) && (wcscmp(CabinetFileName, CurrentCabinetName) == 0)) + if ((HasCurrentCabinet) && (wcscmp(CabinetFileName, CurrentCabinetName) == 0)) { - DPRINT("Using same cabinet as last time\n"); + DPRINT("Using same cabinet as last time\n"); - /* Use our last location because the files should be sequential */ - CabStatus = CabinetFindNextFileSequential(SourceFileName, &Search); - if (CabStatus != CAB_STATUS_SUCCESS) - { - DPRINT("Sequential miss on file: %S\n", SourceFileName); - - /* Looks like we got unlucky */ - CabStatus = CabinetFindFirst(SourceFileName, &Search); - } - } - else - { - DPRINT("Using new cabinet\n"); - - if (HasCurrentCabinet) + /* Use our last location because the files should be sequential */ + CabStatus = CabinetFindNextFileSequential(SourceFileName, &Search); + if (CabStatus != CAB_STATUS_SUCCESS) { - CabinetCleanup(); + DPRINT("Sequential miss on file: %S\n", SourceFileName); + + /* Looks like we got unlucky */ + CabStatus = CabinetFindFirst(SourceFileName, &Search); + } + } + else + { + DPRINT("Using new cabinet\n"); + + if (HasCurrentCabinet) + { + CabinetCleanup(); } - wcscpy(CurrentCabinetName, CabinetFileName); + wcscpy(CurrentCabinetName, CabinetFileName); - CabinetInitialize(); - CabinetSetEventHandlers(NULL, NULL, NULL); - CabinetSetCabinetName(CabinetFileName); + CabinetInitialize(); + CabinetSetEventHandlers(NULL, NULL, NULL); + CabinetSetCabinetName(CabinetFileName); - CabStatus = CabinetOpen(); - if (CabStatus == CAB_STATUS_SUCCESS) + CabStatus = CabinetOpen(); + if (CabStatus == CAB_STATUS_SUCCESS) { - DPRINT("Opened cabinet %S\n", CabinetGetCabinetName()); - HasCurrentCabinet = TRUE; + DPRINT("Opened cabinet %S\n", CabinetGetCabinetName()); + HasCurrentCabinet = TRUE; } - else + else { - DPRINT("Cannot open cabinet (%d)\n", CabStatus); - return STATUS_UNSUCCESSFUL; + DPRINT("Cannot open cabinet (%d)\n", CabStatus); + return STATUS_UNSUCCESSFUL; } - - /* We have to start at the beginning here */ - CabStatus = CabinetFindFirst(SourceFileName, &Search); + + /* We have to start at the beginning here */ + CabStatus = CabinetFindFirst(SourceFileName, &Search); } - - if (CabStatus != CAB_STATUS_SUCCESS) - { - DPRINT1("Unable to find '%S' in cabinet '%S'\n", SourceFileName, CabinetGetCabinetName()); - return STATUS_UNSUCCESSFUL; - } - CabinetSetDestinationPath(DestinationPathName); - CabStatus = CabinetExtractFile(&Search); - if (CabStatus != CAB_STATUS_SUCCESS) + if (CabStatus != CAB_STATUS_SUCCESS) { - DPRINT("Cannot extract file %S (%d)\n", SourceFileName, CabStatus); - return STATUS_UNSUCCESSFUL; + DPRINT1("Unable to find '%S' in cabinet '%S'\n", SourceFileName, CabinetGetCabinetName()); + return STATUS_UNSUCCESSFUL; } - return STATUS_SUCCESS; + CabinetSetDestinationPath(DestinationPathName); + CabStatus = CabinetExtractFile(&Search); + if (CabStatus != CAB_STATUS_SUCCESS) + { + DPRINT("Cannot extract file %S (%d)\n", SourceFileName, CabStatus); + return STATUS_UNSUCCESSFUL; + } + + return STATUS_SUCCESS; } #endif BOOLEAN -DoesFileExist(PWSTR PathName, - PWSTR FileName) +DoesFileExist( + PWSTR PathName, + PWSTR FileName) { - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - UNICODE_STRING Name; - WCHAR FullName[MAX_PATH]; - HANDLE FileHandle; - NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING Name; + WCHAR FullName[MAX_PATH]; + HANDLE FileHandle; + NTSTATUS Status; - wcscpy(FullName, PathName); - if (FileName != NULL) + wcscpy(FullName, PathName); + if (FileName != NULL) { - if (FileName[0] != L'\\') - wcscat(FullName, L"\\"); - wcscat(FullName, FileName); + if (FileName[0] != L'\\') + wcscat(FullName, L"\\"); + wcscat(FullName, FileName); } - RtlInitUnicodeString(&Name, - FullName); + RtlInitUnicodeString(&Name, + FullName); - InitializeObjectAttributes(&ObjectAttributes, - &Name, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); + InitializeObjectAttributes(&ObjectAttributes, + &Name, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); - Status = NtOpenFile(&FileHandle, - GENERIC_READ | SYNCHRONIZE, - &ObjectAttributes, - &IoStatusBlock, - 0, - FILE_SYNCHRONOUS_IO_NONALERT); - if (!NT_SUCCESS(Status)) + Status = NtOpenFile(&FileHandle, + GENERIC_READ | SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + 0, + FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS(Status)) { - return(FALSE); + return FALSE; } - NtClose(FileHandle); + NtClose(FileHandle); - return(TRUE); + return TRUE; } /* EOF */ diff --git a/base/setup/usetup/filesup.h b/base/setup/usetup/filesup.h index a1d45cb9417..5522321fbd7 100644 --- a/base/setup/usetup/filesup.h +++ b/base/setup/usetup/filesup.h @@ -27,19 +27,23 @@ #pragma once NTSTATUS -SetupCreateDirectory(PWCHAR DirectoryName); +SetupCreateDirectory( + PWCHAR DirectoryName); NTSTATUS -SetupCopyFile(PWCHAR SourceFileName, - PWCHAR DestinationFileName); +SetupCopyFile( + PWCHAR SourceFileName, + PWCHAR DestinationFileName); NTSTATUS -SetupExtractFile(PWCHAR CabinetFileName, - PWCHAR SourceFileName, - PWCHAR DestinationFileName); +SetupExtractFile( + PWCHAR CabinetFileName, + PWCHAR SourceFileName, + PWCHAR DestinationFileName); BOOLEAN -DoesFileExist(PWSTR PathName, - PWSTR FileName); +DoesFileExist( + PWSTR PathName, + PWSTR FileName); /* EOF */ diff --git a/base/setup/usetup/format.c b/base/setup/usetup/format.c index 00f437420b3..dd2ee166e5e 100644 --- a/base/setup/usetup/format.c +++ b/base/setup/usetup/format.c @@ -34,7 +34,9 @@ static PPROGRESSBAR FormatProgressBar = NULL; /* FUNCTIONS ****************************************************************/ -static BOOLEAN NTAPI +static +BOOLEAN +NTAPI FormatCallback( IN CALLBACKCOMMAND Command, IN ULONG Modifier, @@ -82,6 +84,7 @@ FormatCallback( return TRUE; } + NTSTATUS FormatPartition( IN PUNICODE_STRING DriveRoot, diff --git a/base/setup/usetup/fslist.c b/base/setup/usetup/fslist.c index 93db77c6da1..85045a83c1e 100644 --- a/base/setup/usetup/fslist.c +++ b/base/setup/usetup/fslist.c @@ -65,6 +65,7 @@ FS_AddProvider( InsertTailList(&List->ListHead, &Item->ListEntry); } + PFILE_SYSTEM_LIST CreateFileSystemList( IN SHORT Left, @@ -111,6 +112,7 @@ CreateFileSystemList( return List; } + VOID DestroyFileSystemList( IN PFILE_SYSTEM_LIST List) @@ -131,6 +133,7 @@ DestroyFileSystemList( RtlFreeHeap(ProcessHeap, 0, List); } + VOID DrawFileSystemList( IN PFILE_SYSTEM_LIST List) @@ -183,6 +186,7 @@ DrawFileSystemList( } } + VOID ScrollDownFileSystemList( IN PFILE_SYSTEM_LIST List) @@ -194,6 +198,7 @@ ScrollDownFileSystemList( } } + VOID ScrollUpFileSystemList( IN PFILE_SYSTEM_LIST List) diff --git a/base/setup/usetup/fslist.h b/base/setup/usetup/fslist.h index 1c84024eeec..6b28e29073e 100644 --- a/base/setup/usetup/fslist.h +++ b/base/setup/usetup/fslist.h @@ -30,34 +30,34 @@ typedef struct _FILE_SYSTEM_ITEM { - LIST_ENTRY ListEntry; - LPCWSTR FileSystem; /* Not owned by the item */ - FORMATEX FormatFunc; - CHKDSKEX ChkdskFunc; - BOOLEAN QuickFormat; + LIST_ENTRY ListEntry; + LPCWSTR FileSystem; /* Not owned by the item */ + FORMATEX FormatFunc; + CHKDSKEX ChkdskFunc; + BOOLEAN QuickFormat; } FILE_SYSTEM_ITEM, *PFILE_SYSTEM_ITEM; typedef struct _FILE_SYSTEM_LIST { - SHORT Left; - SHORT Top; - PFILE_SYSTEM_ITEM Selected; - LIST_ENTRY ListHead; /* List of FILE_SYSTEM_ITEM */ + SHORT Left; + SHORT Top; + PFILE_SYSTEM_ITEM Selected; + LIST_ENTRY ListHead; /* List of FILE_SYSTEM_ITEM */ } FILE_SYSTEM_LIST, *PFILE_SYSTEM_LIST; VOID FS_AddProvider( - IN OUT PFILE_SYSTEM_LIST List, - IN LPCWSTR FileSystem, - IN FORMATEX FormatFunc, - IN CHKDSKEX ChkdskFunc); + IN OUT PFILE_SYSTEM_LIST List, + IN LPCWSTR FileSystem, + IN FORMATEX FormatFunc, + IN CHKDSKEX ChkdskFunc); PFILE_SYSTEM_LIST CreateFileSystemList( - IN SHORT Left, - IN SHORT Top, - IN BOOLEAN ForceFormat, - IN LPCWSTR ForceFileSystem); + IN SHORT Left, + IN SHORT Top, + IN BOOLEAN ForceFormat, + IN LPCWSTR ForceFileSystem); VOID DestroyFileSystemList( diff --git a/base/setup/usetup/genlist.c b/base/setup/usetup/genlist.c index 9073ca3880c..6e5a736b4a8 100644 --- a/base/setup/usetup/genlist.c +++ b/base/setup/usetup/genlist.c @@ -84,8 +84,9 @@ CreateGenericList(VOID) VOID -DestroyGenericList(PGENERIC_LIST List, - BOOLEAN FreeUserData) +DestroyGenericList( + PGENERIC_LIST List, + BOOLEAN FreeUserData) { PGENERIC_LIST_ENTRY ListEntry; PLIST_ENTRY Entry; @@ -110,10 +111,11 @@ DestroyGenericList(PGENERIC_LIST List, BOOLEAN -AppendGenericListEntry(PGENERIC_LIST List, - PCHAR Text, - PVOID UserData, - BOOLEAN Current) +AppendGenericListEntry( + PGENERIC_LIST List, + PCHAR Text, + PVOID UserData, + BOOLEAN Current) { PGENERIC_LIST_ENTRY Entry; @@ -139,8 +141,10 @@ AppendGenericListEntry(PGENERIC_LIST List, } -static VOID -DrawListFrame(PGENERIC_LIST GenericList) +static +VOID +DrawListFrame( + PGENERIC_LIST GenericList) { COORD coPos; DWORD Written; @@ -221,8 +225,10 @@ DrawListFrame(PGENERIC_LIST GenericList) } -static VOID -DrawListEntries(PGENERIC_LIST GenericList) +static +VOID +DrawListEntries( + PGENERIC_LIST GenericList) { PGENERIC_LIST_ENTRY ListEntry; PLIST_ENTRY Entry; @@ -286,8 +292,11 @@ DrawListEntries(PGENERIC_LIST GenericList) } } -static VOID -DrawScrollBarGenericList(PGENERIC_LIST GenericList) + +static +VOID +DrawScrollBarGenericList( + PGENERIC_LIST GenericList) { COORD coPos; DWORD Written; @@ -331,12 +340,14 @@ DrawScrollBarGenericList(PGENERIC_LIST GenericList) } } + VOID -DrawGenericList(PGENERIC_LIST List, - SHORT Left, - SHORT Top, - SHORT Right, - SHORT Bottom) +DrawGenericList( + PGENERIC_LIST List, + SHORT Left, + SHORT Top, + SHORT Right, + SHORT Bottom) { List->FirstShown = List->ListHead.Flink; List->Left = Left; @@ -353,8 +364,10 @@ DrawGenericList(PGENERIC_LIST List, DrawScrollBarGenericList(List); } + VOID -ScrollPageDownGenericList (PGENERIC_LIST List) +ScrollPageDownGenericList( + PGENERIC_LIST List) { SHORT i; @@ -374,8 +387,10 @@ ScrollPageDownGenericList (PGENERIC_LIST List) List->Redraw = TRUE; } + VOID -ScrollPageUpGenericList (PGENERIC_LIST List) +ScrollPageUpGenericList( + PGENERIC_LIST List) { SHORT i; @@ -395,8 +410,10 @@ ScrollPageUpGenericList (PGENERIC_LIST List) List->Redraw = TRUE; } + VOID -ScrollDownGenericList (PGENERIC_LIST List) +ScrollDownGenericList( + PGENERIC_LIST List) { PLIST_ENTRY Entry; @@ -423,7 +440,9 @@ ScrollDownGenericList (PGENERIC_LIST List) VOID -ScrollToPositionGenericList (PGENERIC_LIST List, ULONG uIndex) +ScrollToPositionGenericList( + PGENERIC_LIST List, + ULONG uIndex) { PLIST_ENTRY Entry; ULONG uCount = 0; @@ -456,7 +475,8 @@ ScrollToPositionGenericList (PGENERIC_LIST List, ULONG uIndex) VOID -ScrollUpGenericList (PGENERIC_LIST List) +ScrollUpGenericList( + PGENERIC_LIST List) { PLIST_ENTRY Entry; @@ -483,7 +503,8 @@ ScrollUpGenericList (PGENERIC_LIST List) VOID -RedrawGenericList(PGENERIC_LIST List) +RedrawGenericList( + PGENERIC_LIST List) { if (List->CurrentEntry == NULL) return; @@ -497,7 +518,9 @@ RedrawGenericList(PGENERIC_LIST List) VOID -SetCurrentListEntry(PGENERIC_LIST List, PGENERIC_LIST_ENTRY Entry) +SetCurrentListEntry( + PGENERIC_LIST List, + PGENERIC_LIST_ENTRY Entry) { if (Entry->List != List) return; @@ -506,14 +529,16 @@ SetCurrentListEntry(PGENERIC_LIST List, PGENERIC_LIST_ENTRY Entry) PGENERIC_LIST_ENTRY -GetCurrentListEntry(PGENERIC_LIST List) +GetCurrentListEntry( + PGENERIC_LIST List) { return List->CurrentEntry; } PGENERIC_LIST_ENTRY -GetFirstListEntry(PGENERIC_LIST List) +GetFirstListEntry( + PGENERIC_LIST List) { PLIST_ENTRY Entry = List->ListHead.Flink; @@ -524,7 +549,8 @@ GetFirstListEntry(PGENERIC_LIST List) PGENERIC_LIST_ENTRY -GetNextListEntry(PGENERIC_LIST_ENTRY Entry) +GetNextListEntry( + PGENERIC_LIST_ENTRY Entry) { PLIST_ENTRY Next = Entry->Entry.Flink; @@ -535,21 +561,25 @@ GetNextListEntry(PGENERIC_LIST_ENTRY Entry) PVOID -GetListEntryUserData(PGENERIC_LIST_ENTRY List) +GetListEntryUserData( + PGENERIC_LIST_ENTRY List) { return List->UserData; } LPCSTR -GetListEntryText(PGENERIC_LIST_ENTRY List) +GetListEntryText( + PGENERIC_LIST_ENTRY List) { return List->Text; } VOID -GenericListKeyPress (PGENERIC_LIST GenericList, CHAR AsciChar) +GenericListKeyPress( + PGENERIC_LIST GenericList, + CHAR AsciChar) { PGENERIC_LIST_ENTRY ListEntry; PGENERIC_LIST_ENTRY OldListEntry; @@ -609,14 +639,16 @@ End: VOID -SaveGenericListState(PGENERIC_LIST List) +SaveGenericListState( + PGENERIC_LIST List) { List->BackupEntry = List->CurrentEntry; } VOID -RestoreGenericListState(PGENERIC_LIST List) +RestoreGenericListState( + PGENERIC_LIST List) { List->CurrentEntry = List->BackupEntry; } diff --git a/base/setup/usetup/genlist.h b/base/setup/usetup/genlist.h index 8b09a5eaf58..bfe9020e877 100644 --- a/base/setup/usetup/genlist.h +++ b/base/setup/usetup/genlist.h @@ -35,68 +35,90 @@ PGENERIC_LIST CreateGenericList(VOID); VOID -DestroyGenericList(PGENERIC_LIST List, - BOOLEAN FreeUserData); +DestroyGenericList( + PGENERIC_LIST List, + BOOLEAN FreeUserData); BOOLEAN -AppendGenericListEntry(PGENERIC_LIST List, - PCHAR Text, - PVOID UserData, - BOOLEAN Current); +AppendGenericListEntry( + PGENERIC_LIST List, + PCHAR Text, + PVOID UserData, + BOOLEAN Current); VOID -DrawGenericList(PGENERIC_LIST List, - SHORT Left, - SHORT Top, - SHORT Right, - SHORT Bottom); +DrawGenericList( + PGENERIC_LIST List, + SHORT Left, + SHORT Top, + SHORT Right, + SHORT Bottom); VOID -DrawScrollBarGenericLis(PGENERIC_LIST List); +DrawScrollBarGenericLis( + PGENERIC_LIST List); VOID -ScrollDownGenericList(PGENERIC_LIST List); +ScrollDownGenericList( + PGENERIC_LIST List); VOID -ScrollUpGenericList(PGENERIC_LIST List); +ScrollUpGenericList( + PGENERIC_LIST List); VOID -ScrollPageDownGenericList(PGENERIC_LIST List); +ScrollPageDownGenericList( + PGENERIC_LIST List); VOID -ScrollPageUpGenericList(PGENERIC_LIST List); +ScrollPageUpGenericList( + PGENERIC_LIST List); VOID -ScrollToPositionGenericList (PGENERIC_LIST List, ULONG uIndex); +ScrollToPositionGenericList( + PGENERIC_LIST List, + ULONG uIndex); VOID -RedrawGenericList(PGENERIC_LIST List); +RedrawGenericList( + PGENERIC_LIST List); VOID -SetCurrentListEntry(PGENERIC_LIST List, PGENERIC_LIST_ENTRY Entry); +SetCurrentListEntry( + PGENERIC_LIST List, + PGENERIC_LIST_ENTRY Entry); PGENERIC_LIST_ENTRY -GetCurrentListEntry(PGENERIC_LIST List); +GetCurrentListEntry( + PGENERIC_LIST List); PGENERIC_LIST_ENTRY -GetFirstListEntry(PGENERIC_LIST List); +GetFirstListEntry( + PGENERIC_LIST List); PGENERIC_LIST_ENTRY -GetNextListEntry(PGENERIC_LIST_ENTRY Entry); +GetNextListEntry( + PGENERIC_LIST_ENTRY Entry); PVOID -GetListEntryUserData(PGENERIC_LIST_ENTRY List); +GetListEntryUserData( + PGENERIC_LIST_ENTRY List); LPCSTR -GetListEntryText(PGENERIC_LIST_ENTRY List); +GetListEntryText( + PGENERIC_LIST_ENTRY List); VOID -SaveGenericListState(PGENERIC_LIST List); +SaveGenericListState( + PGENERIC_LIST List); VOID -RestoreGenericListState(PGENERIC_LIST List); +RestoreGenericListState( + PGENERIC_LIST List); VOID -GenericListKeyPress (PGENERIC_LIST List, CHAR AsciChar); +GenericListKeyPress( + PGENERIC_LIST List, + CHAR AsciChar); /* EOF */ diff --git a/base/setup/usetup/host.h b/base/setup/usetup/host.h index 14a3a51fb48..6d8a84bfdb3 100644 --- a/base/setup/usetup/host.h +++ b/base/setup/usetup/host.h @@ -15,19 +15,17 @@ #endif BOOLEAN -HOST_InitConsole( - VOID); +HOST_InitConsole(VOID); BOOLEAN -HOST_InitMemory( - VOID); +HOST_InitMemory(VOID); BOOLEAN HOST_CreateFileSystemList( - IN PFILE_SYSTEM_LIST List); + IN PFILE_SYSTEM_LIST List); BOOLEAN HOST_FormatPartition( - IN PFILE_SYSTEM_ITEM FileSystem, - IN PCUNICODE_STRING DriveRoot, - IN PFMIFSCALLBACK Callback); + IN PFILE_SYSTEM_ITEM FileSystem, + IN PCUNICODE_STRING DriveRoot, + IN PFMIFSCALLBACK Callback); diff --git a/base/setup/usetup/inffile.c b/base/setup/usetup/inffile.c index e2ea1b4f0c1..1eb6d66f1f5 100644 --- a/base/setup/usetup/inffile.c +++ b/base/setup/usetup/inffile.c @@ -35,173 +35,179 @@ #ifdef __REACTOS__ -BOOL WINAPI +BOOL +WINAPI InfpFindFirstLineW( - IN HINF InfHandle, - IN PCWSTR Section, - IN PCWSTR Key, - IN OUT PINFCONTEXT Context) + IN HINF InfHandle, + IN PCWSTR Section, + IN PCWSTR Key, + IN OUT PINFCONTEXT Context) { - PINFCONTEXT pContext; - BOOL ret; + PINFCONTEXT pContext; + BOOL ret; - ret = InfFindFirstLine(InfHandle, Section, Key, &pContext); - if (!ret) - return FALSE; + ret = InfFindFirstLine(InfHandle, Section, Key, &pContext); + if (!ret) + return FALSE; - memcpy(Context, pContext, sizeof(INFCONTEXT)); - InfFreeContext(pContext); - return TRUE; + memcpy(Context, pContext, sizeof(INFCONTEXT)); + InfFreeContext(pContext); + return TRUE; } -HINF WINAPI + +HINF +WINAPI InfpOpenInfFileW( - IN PCWSTR FileName, - IN PCWSTR InfClass, - IN DWORD InfStyle, - IN LCID LocaleId, - OUT PUINT ErrorLine) + IN PCWSTR FileName, + IN PCWSTR InfClass, + IN DWORD InfStyle, + IN LCID LocaleId, + OUT PUINT ErrorLine) { - HINF hInf = NULL; - UNICODE_STRING FileNameU; - ULONG ErrorLineUL; - NTSTATUS Status; + HINF hInf = NULL; + UNICODE_STRING FileNameU; + ULONG ErrorLineUL; + NTSTATUS Status; - RtlInitUnicodeString(&FileNameU, FileName); - Status = InfOpenFile( - &hInf, - &FileNameU, - LANGIDFROMLCID(LocaleId), - &ErrorLineUL); - *ErrorLine = (UINT)ErrorLineUL; - if (!NT_SUCCESS(Status)) - return INVALID_HANDLE_VALUE; + RtlInitUnicodeString(&FileNameU, FileName); + Status = InfOpenFile(&hInf, + &FileNameU, + LANGIDFROMLCID(LocaleId), + &ErrorLineUL); + *ErrorLine = (UINT)ErrorLineUL; + if (!NT_SUCCESS(Status)) + return INVALID_HANDLE_VALUE; - return hInf; + return hInf; } - #endif /* __REACTOS__ */ + BOOLEAN INF_GetData( - IN PINFCONTEXT Context, - OUT PWCHAR *Key, - OUT PWCHAR *Data) + IN PINFCONTEXT Context, + OUT PWCHAR *Key, + OUT PWCHAR *Data) { #ifdef __REACTOS__ - return InfGetData(Context, Key, Data); + return InfGetData(Context, Key, Data); #else - static PWCHAR pLastCallData[4] = { NULL, NULL, NULL, NULL }; - static DWORD currentIndex = 0; - DWORD dwSize, i; - BOOL ret; + static PWCHAR pLastCallData[4] = { NULL, NULL, NULL, NULL }; + static DWORD currentIndex = 0; + DWORD dwSize, i; + BOOL ret; - currentIndex ^= 2; + currentIndex ^= 2; - if (Key) *Key = NULL; - if (Data) *Data = NULL; + if (Key) + *Key = NULL; - if (SetupGetFieldCount(Context) != 1) - return FALSE; + if (Data) + *Data = NULL; - for (i = 0; i <= 1; i++) - { - ret = SetupGetStringFieldW( - Context, - i, - NULL, - 0, - &dwSize); - if (!ret) - return FALSE; - HeapFree(GetProcessHeap(), 0, pLastCallData[i + currentIndex]); - pLastCallData[i + currentIndex] = HeapAlloc(GetProcessHeap(), 0, dwSize * sizeof(WCHAR)); - ret = SetupGetStringFieldW( - Context, - i, - pLastCallData[i + currentIndex], - dwSize, - NULL); - if (!ret) - return FALSE; - } + if (SetupGetFieldCount(Context) != 1) + return FALSE; - if (Key) - *Key = pLastCallData[0 + currentIndex]; - if (Data) - *Data = pLastCallData[1 + currentIndex]; - return TRUE; + for (i = 0; i <= 1; i++) + { + ret = SetupGetStringFieldW(Context, + i, + NULL, + 0, + &dwSize); + if (!ret) + return FALSE; + + HeapFree(GetProcessHeap(), 0, pLastCallData[i + currentIndex]); + pLastCallData[i + currentIndex] = HeapAlloc(GetProcessHeap(), 0, dwSize * sizeof(WCHAR)); + ret = SetupGetStringFieldW(Context, + i, + pLastCallData[i + currentIndex], + dwSize, + NULL); + if (!ret) + return FALSE; + } + + if (Key) + *Key = pLastCallData[0 + currentIndex]; + + if (Data) + *Data = pLastCallData[1 + currentIndex]; + + return TRUE; #endif /* !__REACTOS__ */ } + BOOLEAN INF_GetDataField( - IN PINFCONTEXT Context, - IN ULONG FieldIndex, - OUT PWCHAR *Data) + IN PINFCONTEXT Context, + IN ULONG FieldIndex, + OUT PWCHAR *Data) { #ifdef __REACTOS__ - return InfGetDataField(Context, FieldIndex, Data); + return InfGetDataField(Context, FieldIndex, Data); #else - static PWCHAR pLastCallsData[] = { NULL, NULL, NULL }; - static DWORD NextIndex = 0; - DWORD dwSize; - BOOL ret; + static PWCHAR pLastCallsData[] = { NULL, NULL, NULL }; + static DWORD NextIndex = 0; + DWORD dwSize; + BOOL ret; - *Data = NULL; + *Data = NULL; - ret = SetupGetStringFieldW( - Context, - FieldIndex, - NULL, - 0, - &dwSize); - if (!ret) - return FALSE; - HeapFree(GetProcessHeap(), 0, pLastCallsData[NextIndex]); - pLastCallsData[NextIndex] = HeapAlloc(GetProcessHeap(), 0, dwSize * sizeof(WCHAR)); - ret = SetupGetStringFieldW( - Context, - FieldIndex, - pLastCallsData[NextIndex], - dwSize, - NULL); - if (!ret) - return FALSE; + ret = SetupGetStringFieldW(Context, + FieldIndex, + NULL, + 0, + &dwSize); + if (!ret) + return FALSE; - *Data = pLastCallsData[NextIndex]; - NextIndex = (NextIndex + 1) % (sizeof(pLastCallsData) / sizeof(pLastCallsData[0])); - return TRUE; + HeapFree(GetProcessHeap(), 0, pLastCallsData[NextIndex]); + pLastCallsData[NextIndex] = HeapAlloc(GetProcessHeap(), 0, dwSize * sizeof(WCHAR)); + ret = SetupGetStringFieldW(Context, + FieldIndex, + pLastCallsData[NextIndex], + dwSize, + NULL); + if (!ret) + return FALSE; + + *Data = pLastCallsData[NextIndex]; + NextIndex = (NextIndex + 1) % (sizeof(pLastCallsData) / sizeof(pLastCallsData[0])); + return TRUE; #endif /* !__REACTOS__ */ } + HINF WINAPI INF_OpenBufferedFileA( - IN PSTR FileBuffer, - IN ULONG FileSize, - IN PCSTR InfClass, - IN DWORD InfStyle, - IN LCID LocaleId, - OUT PUINT ErrorLine) + IN PSTR FileBuffer, + IN ULONG FileSize, + IN PCSTR InfClass, + IN DWORD InfStyle, + IN LCID LocaleId, + OUT PUINT ErrorLine) { #ifdef __REACTOS__ - HINF hInf = NULL; - ULONG ErrorLineUL; - NTSTATUS Status; + HINF hInf = NULL; + ULONG ErrorLineUL; + NTSTATUS Status; - Status = InfOpenBufferedFile( - &hInf, - FileBuffer, - FileSize, - LANGIDFROMLCID(LocaleId), - &ErrorLineUL); - *ErrorLine = (UINT)ErrorLineUL; - if (!NT_SUCCESS(Status)) - return INVALID_HANDLE_VALUE; + Status = InfOpenBufferedFile(&hInf, + FileBuffer, + FileSize, + LANGIDFROMLCID(LocaleId), + &ErrorLineUL); + *ErrorLine = (UINT)ErrorLineUL; + if (!NT_SUCCESS(Status)) + return INVALID_HANDLE_VALUE; - return hInf; + return hInf; #else - return INVALID_HANDLE_VALUE; + return INVALID_HANDLE_VALUE; #endif /* !__REACTOS__ */ } diff --git a/base/setup/usetup/inffile.h b/base/setup/usetup/inffile.h index ba0e45a0fd1..83133f99b00 100644 --- a/base/setup/usetup/inffile.h +++ b/base/setup/usetup/inffile.h @@ -45,47 +45,49 @@ * Delete it once we don't use inflib anymore */ typedef struct _INFCONTEXT { - PVOID Inf; - PVOID Section; - PVOID Line; + PVOID Inf; + PVOID Section; + PVOID Line; } INFCONTEXT; -BOOL WINAPI +BOOL +WINAPI InfpFindFirstLineW( - IN HINF InfHandle, - IN PCWSTR Section, - IN PCWSTR Key, - IN OUT PINFCONTEXT Context); + IN HINF InfHandle, + IN PCWSTR Section, + IN PCWSTR Key, + IN OUT PINFCONTEXT Context); -HINF WINAPI +HINF +WINAPI InfpOpenInfFileW( - IN PCWSTR FileName, - IN PCWSTR InfClass, - IN DWORD InfStyle, - IN LCID LocaleId, - OUT PUINT ErrorLine); + IN PCWSTR FileName, + IN PCWSTR InfClass, + IN DWORD InfStyle, + IN LCID LocaleId, + OUT PUINT ErrorLine); #endif /* __REACTOS__ */ BOOLEAN INF_GetData( - IN PINFCONTEXT Context, - OUT PWCHAR *Key, - OUT PWCHAR *Data); + IN PINFCONTEXT Context, + OUT PWCHAR *Key, + OUT PWCHAR *Data); BOOLEAN INF_GetDataField( - IN PINFCONTEXT Context, - IN ULONG FieldIndex, - OUT PWCHAR *Data); + IN PINFCONTEXT Context, + IN ULONG FieldIndex, + OUT PWCHAR *Data); HINF WINAPI INF_OpenBufferedFileA( - IN PSTR FileBuffer, - IN ULONG FileSize, - IN PCSTR InfClass, - IN DWORD InfStyle, - IN LCID LocaleId, - OUT PUINT ErrorLine); + IN PSTR FileBuffer, + IN ULONG FileSize, + IN PCSTR InfClass, + IN DWORD InfStyle, + IN LCID LocaleId, + OUT PUINT ErrorLine); /* EOF */ diff --git a/base/setup/usetup/inicache.c b/base/setup/usetup/inicache.c index fa40dc1c165..0b8dff594d3 100644 --- a/base/setup/usetup/inicache.c +++ b/base/setup/usetup/inicache.c @@ -34,1154 +34,1143 @@ /* PRIVATE FUNCTIONS ********************************************************/ -static PINICACHEKEY -IniCacheFreeKey(PINICACHEKEY Key) +static +PINICACHEKEY +IniCacheFreeKey( + PINICACHEKEY Key) { - PINICACHEKEY Next; + PINICACHEKEY Next; - if (Key == NULL) + if (Key == NULL) { - return(NULL); + return NULL; } - Next = Key->Next; - if (Key->Name != NULL) + Next = Key->Next; + if (Key->Name != NULL) { - RtlFreeHeap(ProcessHeap, - 0, - Key->Name); - Key->Name = NULL; + RtlFreeHeap(ProcessHeap, 0, Key->Name); + Key->Name = NULL; } - if (Key->Data != NULL) + if (Key->Data != NULL) { - RtlFreeHeap(ProcessHeap, - 0, - Key->Data); - Key->Data = NULL; + RtlFreeHeap(ProcessHeap, 0, Key->Data); + Key->Data = NULL; } - RtlFreeHeap(ProcessHeap, - 0, - Key); + RtlFreeHeap(ProcessHeap, 0, Key); - return(Next); + return Next; } -static PINICACHESECTION -IniCacheFreeSection(PINICACHESECTION Section) +static +PINICACHESECTION +IniCacheFreeSection( + PINICACHESECTION Section) { - PINICACHESECTION Next; + PINICACHESECTION Next; - if (Section == NULL) + if (Section == NULL) { - return(NULL); + return NULL; } - Next = Section->Next; - while (Section->FirstKey != NULL) + Next = Section->Next; + while (Section->FirstKey != NULL) { - Section->FirstKey = IniCacheFreeKey(Section->FirstKey); + Section->FirstKey = IniCacheFreeKey(Section->FirstKey); } - Section->LastKey = NULL; + Section->LastKey = NULL; - if (Section->Name != NULL) + if (Section->Name != NULL) { - RtlFreeHeap(ProcessHeap, - 0, - Section->Name); - Section->Name = NULL; + RtlFreeHeap(ProcessHeap, 0, Section->Name); + Section->Name = NULL; } - RtlFreeHeap(ProcessHeap, - 0, - Section); + RtlFreeHeap(ProcessHeap, 0, Section); - return(Next); + return Next; } -static PINICACHEKEY -IniCacheFindKey(PINICACHESECTION Section, - PWCHAR Name, - ULONG NameLength) +static +PINICACHEKEY +IniCacheFindKey( + PINICACHESECTION Section, + PWCHAR Name, + ULONG NameLength) { - PINICACHEKEY Key; + PINICACHEKEY Key; - Key = Section->FirstKey; - while (Key != NULL) + Key = Section->FirstKey; + while (Key != NULL) { - if (NameLength == wcslen(Key->Name)) - { - if (_wcsnicmp(Key->Name, Name, NameLength) == 0) - break; - } + if (NameLength == wcslen(Key->Name)) + { + if (_wcsnicmp(Key->Name, Name, NameLength) == 0) + break; + } - Key = Key->Next; + Key = Key->Next; } - return(Key); + return Key; } -static PINICACHEKEY -IniCacheAddKey(PINICACHESECTION Section, - PCHAR Name, - ULONG NameLength, - PCHAR Data, - ULONG DataLength) +static +PINICACHEKEY +IniCacheAddKey( + PINICACHESECTION Section, + PCHAR Name, + ULONG NameLength, + PCHAR Data, + ULONG DataLength) { - PINICACHEKEY Key; - ULONG i; + PINICACHEKEY Key; + ULONG i; - Key = NULL; + Key = NULL; - if (Section == NULL || - Name == NULL || - NameLength == 0 || - Data == NULL || - DataLength == 0) + if (Section == NULL || + Name == NULL || + NameLength == 0 || + Data == NULL || + DataLength == 0) { - DPRINT("Invalid parameter\n"); - return(NULL); + DPRINT("Invalid parameter\n"); + return NULL; } - Key = (PINICACHEKEY)RtlAllocateHeap(ProcessHeap, - 0, - sizeof(INICACHEKEY)); - if (Key == NULL) + Key = (PINICACHEKEY)RtlAllocateHeap(ProcessHeap, + 0, + sizeof(INICACHEKEY)); + if (Key == NULL) { - DPRINT("RtlAllocateHeap() failed\n"); - return(NULL); + DPRINT("RtlAllocateHeap() failed\n"); + return NULL; } - RtlZeroMemory(Key, - sizeof(INICACHEKEY)); + RtlZeroMemory(Key, + sizeof(INICACHEKEY)); - - Key->Name = (WCHAR*) RtlAllocateHeap(ProcessHeap, - 0, - (NameLength + 1) * sizeof(WCHAR)); - if (Key->Name == NULL) + Key->Name = (WCHAR*)RtlAllocateHeap(ProcessHeap, + 0, + (NameLength + 1) * sizeof(WCHAR)); + if (Key->Name == NULL) { - DPRINT("RtlAllocateHeap() failed\n"); - RtlFreeHeap(ProcessHeap, - 0, - Key); - return(NULL); + DPRINT("RtlAllocateHeap() failed\n"); + RtlFreeHeap(ProcessHeap, 0, Key); + return NULL; } - /* Copy value name */ - for (i = 0; i < NameLength; i++) + /* Copy value name */ + for (i = 0; i < NameLength; i++) { - Key->Name[i] = (WCHAR)Name[i]; + Key->Name[i] = (WCHAR)Name[i]; } - Key->Name[NameLength] = 0; + Key->Name[NameLength] = 0; - - Key->Data = (WCHAR*) RtlAllocateHeap(ProcessHeap, - 0, - (DataLength + 1) * sizeof(WCHAR)); - if (Key->Data == NULL) + Key->Data = (WCHAR*)RtlAllocateHeap(ProcessHeap, + 0, + (DataLength + 1) * sizeof(WCHAR)); + if (Key->Data == NULL) { - DPRINT("RtlAllocateHeap() failed\n"); - RtlFreeHeap(ProcessHeap, - 0, - Key->Name); - RtlFreeHeap(ProcessHeap, - 0, - Key); - return(NULL); + DPRINT("RtlAllocateHeap() failed\n"); + RtlFreeHeap(ProcessHeap, 0, Key->Name); + RtlFreeHeap(ProcessHeap, 0, Key); + return NULL; } - /* Copy value data */ - for (i = 0; i < DataLength; i++) + /* Copy value data */ + for (i = 0; i < DataLength; i++) { - Key->Data[i] = (WCHAR)Data[i]; + Key->Data[i] = (WCHAR)Data[i]; } - Key->Data[DataLength] = 0; + Key->Data[DataLength] = 0; - if (Section->FirstKey == NULL) + if (Section->FirstKey == NULL) { - Section->FirstKey = Key; - Section->LastKey = Key; + Section->FirstKey = Key; + Section->LastKey = Key; } - else + else { - Section->LastKey->Next = Key; - Key->Prev = Section->LastKey; - Section->LastKey = Key; + Section->LastKey->Next = Key; + Key->Prev = Section->LastKey; + Section->LastKey = Key; } - return(Key); + return Key; } + #if 0 -static PINICACHESECTION -IniCacheFindSection(PINICACHE Cache, - PWCHAR Name, - ULONG NameLength) +static +PINICACHESECTION +IniCacheFindSection( + PINICACHE Cache, + PWCHAR Name, + ULONG NameLength) { - PINICACHESECTION Section = NULL; + PINICACHESECTION Section = NULL; - if (Cache == NULL || Name == NULL || NameLength == 0) + if (Cache == NULL || Name == NULL || NameLength == 0) { - return(NULL); + return NULL; } - Section = Cache->FirstSection; + Section = Cache->FirstSection; - /* iterate through list of sections */ - while (Section != NULL) + /* iterate through list of sections */ + while (Section != NULL) { - if (NameLength == wcslen(Section->Name)) - { - /* are the contents the same too? */ - if (_wcsnicmp(Section->Name, Name, NameLength) == 0) - break; - } + if (NameLength == wcslen(Section->Name)) + { + /* are the contents the same too? */ + if (_wcsnicmp(Section->Name, Name, NameLength) == 0) + break; + } - /* get the next section*/ - Section = Section->Next; + /* get the next section*/ + Section = Section->Next; } - return(Section); + return Section; } #endif -static PINICACHESECTION -IniCacheAddSection(PINICACHE Cache, - PCHAR Name, - ULONG NameLength) + +static +PINICACHESECTION +IniCacheAddSection( + PINICACHE Cache, + PCHAR Name, + ULONG NameLength) { - PINICACHESECTION Section = NULL; - ULONG i; + PINICACHESECTION Section = NULL; + ULONG i; - if (Cache == NULL || Name == NULL || NameLength == 0) + if (Cache == NULL || Name == NULL || NameLength == 0) { - DPRINT("Invalid parameter\n"); - return(NULL); + DPRINT("Invalid parameter\n"); + return NULL; } - Section = (PINICACHESECTION)RtlAllocateHeap(ProcessHeap, - 0, - sizeof(INICACHESECTION)); - if (Section == NULL) + Section = (PINICACHESECTION)RtlAllocateHeap(ProcessHeap, + 0, + sizeof(INICACHESECTION)); + if (Section == NULL) { - DPRINT("RtlAllocateHeap() failed\n"); - return(NULL); - } - RtlZeroMemory(Section, - sizeof(INICACHESECTION)); - - /* Allocate and initialize section name */ - Section->Name = (WCHAR*) RtlAllocateHeap(ProcessHeap, - 0, - (NameLength + 1) * sizeof(WCHAR)); - if (Section->Name == NULL) - { - DPRINT("RtlAllocateHeap() failed\n"); - RtlFreeHeap(ProcessHeap, - 0, - Section); - return(NULL); + DPRINT("RtlAllocateHeap() failed\n"); + return NULL; } - /* Copy section name */ - for (i = 0; i < NameLength; i++) - { - Section->Name[i] = (WCHAR)Name[i]; - } - Section->Name[NameLength] = 0; + RtlZeroMemory(Section, sizeof(INICACHESECTION)); - /* Append section */ - if (Cache->FirstSection == NULL) + /* Allocate and initialize section name */ + Section->Name = (WCHAR*)RtlAllocateHeap(ProcessHeap, + 0, + (NameLength + 1) * sizeof(WCHAR)); + if (Section->Name == NULL) { - Cache->FirstSection = Section; - Cache->LastSection = Section; - } - else - { - Cache->LastSection->Next = Section; - Section->Prev = Cache->LastSection; - Cache->LastSection = Section; + DPRINT("RtlAllocateHeap() failed\n"); + RtlFreeHeap(ProcessHeap, 0, Section); + return NULL; } - return(Section); + /* Copy section name */ + for (i = 0; i < NameLength; i++) + { + Section->Name[i] = (WCHAR)Name[i]; + } + Section->Name[NameLength] = 0; + + /* Append section */ + if (Cache->FirstSection == NULL) + { + Cache->FirstSection = Section; + Cache->LastSection = Section; + } + else + { + Cache->LastSection->Next = Section; + Section->Prev = Cache->LastSection; + Cache->LastSection = Section; + } + + return Section; } -static PCHAR -IniCacheSkipWhitespace(PCHAR Ptr) +static +PCHAR +IniCacheSkipWhitespace( + PCHAR Ptr) { - while (*Ptr != 0 && isspace(*Ptr)) - Ptr++; + while (*Ptr != 0 && isspace(*Ptr)) + Ptr++; - return((*Ptr == 0) ? NULL : Ptr); + return (*Ptr == 0) ? NULL : Ptr; } -static PCHAR -IniCacheSkipToNextSection(PCHAR Ptr) +static +PCHAR +IniCacheSkipToNextSection( + PCHAR Ptr) { - while (*Ptr != 0 && *Ptr != '[') + while (*Ptr != 0 && *Ptr != '[') { - while (*Ptr != 0 && *Ptr != L'\n') - { - Ptr++; - } - Ptr++; + while (*Ptr != 0 && *Ptr != L'\n') + { + Ptr++; + } + + Ptr++; } - return((*Ptr == 0) ? NULL : Ptr); + return (*Ptr == 0) ? NULL : Ptr; } -static PCHAR -IniCacheGetSectionName(PCHAR Ptr, - PCHAR *NamePtr, - PULONG NameSize) +static +PCHAR +IniCacheGetSectionName( + PCHAR Ptr, + PCHAR *NamePtr, + PULONG NameSize) { - ULONG Size = 0; - CHAR Name[256]; + ULONG Size = 0; + CHAR Name[256]; - *NamePtr = NULL; - *NameSize = 0; - - /* skip whitespace */ - while (*Ptr != 0 && isspace(*Ptr)) - { - Ptr++; - } - - *NamePtr = Ptr; - - while (*Ptr != 0 && *Ptr != ']') - { - Size++; - Ptr++; - } - - Ptr++; - - while (*Ptr != 0 && *Ptr != L'\n') - { - Ptr++; - } - Ptr++; - - *NameSize = Size; - - strncpy(Name, *NamePtr, Size); - Name[Size] = 0; - - DPRINT("SectionName: '%s'\n", Name); - - return(Ptr); -} - - -static PCHAR -IniCacheGetKeyName(PCHAR Ptr, - PCHAR *NamePtr, - PULONG NameSize) -{ - ULONG Size = 0; - - *NamePtr = NULL; - *NameSize = 0; - - while(Ptr && *Ptr) - { *NamePtr = NULL; *NameSize = 0; - Size = 0; - /* skip whitespace and empty lines */ - while (isspace(*Ptr) || *Ptr == '\n' || *Ptr == '\r') + /* skip whitespace */ + while (*Ptr != 0 && isspace(*Ptr)) { - Ptr++; - } - if (*Ptr == 0) - { - continue; + Ptr++; } *NamePtr = Ptr; - while (*Ptr != 0 && !isspace(*Ptr) && *Ptr != '=' && *Ptr != ';') + while (*Ptr != 0 && *Ptr != ']') { - Size++; - Ptr++; + Size++; + Ptr++; } - if (*Ptr == ';') + Ptr++; + + while (*Ptr != 0 && *Ptr != L'\n') { - while (*Ptr != 0 && *Ptr != '\r' && *Ptr != '\n') - { - Ptr++; - } + Ptr++; + } + Ptr++; + + *NameSize = Size; + + strncpy(Name, *NamePtr, Size); + Name[Size] = 0; + + DPRINT("SectionName: '%s'\n", Name); + + return Ptr; +} + + +static +PCHAR +IniCacheGetKeyName( + PCHAR Ptr, + PCHAR *NamePtr, + PULONG NameSize) +{ + ULONG Size = 0; + + *NamePtr = NULL; + *NameSize = 0; + + while(Ptr && *Ptr) + { + *NamePtr = NULL; + *NameSize = 0; + Size = 0; + + /* skip whitespace and empty lines */ + while (isspace(*Ptr) || *Ptr == '\n' || *Ptr == '\r') + { + Ptr++; + } + if (*Ptr == 0) + { + continue; + } + + *NamePtr = Ptr; + + while (*Ptr != 0 && !isspace(*Ptr) && *Ptr != '=' && *Ptr != ';') + { + Size++; + Ptr++; + } + if (*Ptr == ';') + { + while (*Ptr != 0 && *Ptr != '\r' && *Ptr != '\n') + { + Ptr++; + } + } + else + { + *NameSize = Size; + break; + } + } + + return Ptr; +} + + +static +PCHAR +IniCacheGetKeyValue( + PCHAR Ptr, + PCHAR *DataPtr, + PULONG DataSize, + BOOLEAN String) +{ + ULONG Size = 0; + + *DataPtr = NULL; + *DataSize = 0; + + /* Skip whitespace */ + while (*Ptr != 0 && isspace(*Ptr)) + { + Ptr++; + } + + /* Check and skip '=' */ + if (*Ptr != '=') + { + return NULL; + } + Ptr++; + + /* Skip whitespace */ + while (*Ptr != 0 && isspace(*Ptr)) + { + Ptr++; + } + + if (*Ptr == '"' && String) + { + Ptr++; + + /* Get data */ + *DataPtr = Ptr; + while (*Ptr != '"') + { + Ptr++; + Size++; + } + Ptr++; + + while (*Ptr && *Ptr != '\r' && *Ptr != '\n') + { + Ptr++; + } } else { - *NameSize = Size; - break; + /* Get data */ + *DataPtr = Ptr; + while (*Ptr != 0 && *Ptr != '\r' && *Ptr != ';') + { + Ptr++; + Size++; + } } - } - return(Ptr); + /* Skip to next line */ + if (*Ptr == '\r') + Ptr++; + if (*Ptr == '\n') + Ptr++; + + *DataSize = Size; + + return Ptr; } -static PCHAR -IniCacheGetKeyValue(PCHAR Ptr, - PCHAR *DataPtr, - PULONG DataSize, - BOOLEAN String) -{ - ULONG Size = 0; - - *DataPtr = NULL; - *DataSize = 0; - - /* Skip whitespace */ - while (*Ptr != 0 && isspace(*Ptr)) - { - Ptr++; - } - - /* Check and skip '=' */ - if (*Ptr != '=') - { - return(NULL); - } - Ptr++; - - /* Skip whitespace */ - while (*Ptr != 0 && isspace(*Ptr)) - { - Ptr++; - } - - if (*Ptr == '"' && String) - { - Ptr++; - - /* Get data */ - *DataPtr = Ptr; - while (*Ptr != '"') - { - Ptr++; - Size++; - } - Ptr++; - while (*Ptr && *Ptr != '\r' && *Ptr != '\n') - { - Ptr++; - } - } - else - { - /* Get data */ - *DataPtr = Ptr; - while (*Ptr != 0 && *Ptr != '\r' && *Ptr != ';') - { - Ptr++; - Size++; - } - } - - /* Skip to next line */ - if (*Ptr == '\r') - Ptr++; - if (*Ptr == '\n') - Ptr++; - - *DataSize = Size; - - return(Ptr); -} - - - - /* PUBLIC FUNCTIONS *********************************************************/ NTSTATUS -IniCacheLoad(PINICACHE *Cache, - PUNICODE_STRING FileName, - BOOLEAN String) +IniCacheLoad( + PINICACHE *Cache, + PUNICODE_STRING FileName, + BOOLEAN String) { - OBJECT_ATTRIBUTES ObjectAttributes; - FILE_STANDARD_INFORMATION FileInfo; - IO_STATUS_BLOCK IoStatusBlock; - HANDLE FileHandle; - NTSTATUS Status; - PCHAR FileBuffer; - ULONG FileLength; - PCHAR Ptr; - LARGE_INTEGER FileOffset; + OBJECT_ATTRIBUTES ObjectAttributes; + FILE_STANDARD_INFORMATION FileInfo; + IO_STATUS_BLOCK IoStatusBlock; + HANDLE FileHandle; + NTSTATUS Status; + PCHAR FileBuffer; + ULONG FileLength; + PCHAR Ptr; + LARGE_INTEGER FileOffset; - PINICACHESECTION Section; - PINICACHEKEY Key; + PINICACHESECTION Section; + PINICACHEKEY Key; - PCHAR SectionName; - ULONG SectionNameSize; + PCHAR SectionName; + ULONG SectionNameSize; - PCHAR KeyName; - ULONG KeyNameSize; + PCHAR KeyName; + ULONG KeyNameSize; - PCHAR KeyValue; - ULONG KeyValueSize; + PCHAR KeyValue; + ULONG KeyValueSize; - *Cache = NULL; + *Cache = NULL; - /* Open ini file */ - InitializeObjectAttributes(&ObjectAttributes, - FileName, - 0, - NULL, - NULL); + /* Open ini file */ + InitializeObjectAttributes(&ObjectAttributes, + FileName, + 0, + NULL, + NULL); - Status = NtOpenFile(&FileHandle, - GENERIC_READ | SYNCHRONIZE, - &ObjectAttributes, - &IoStatusBlock, - FILE_SHARE_READ, - FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE); - if (!NT_SUCCESS(Status)) + Status = NtOpenFile(&FileHandle, + GENERIC_READ | SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_READ, + FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE); + if (!NT_SUCCESS(Status)) { - DPRINT("NtOpenFile() failed (Status %lx)\n", Status); - return(Status); + DPRINT("NtOpenFile() failed (Status %lx)\n", Status); + return Status; } - DPRINT("NtOpenFile() successful\n"); + DPRINT("NtOpenFile() successful\n"); - /* Query file size */ - Status = NtQueryInformationFile(FileHandle, - &IoStatusBlock, - &FileInfo, - sizeof(FILE_STANDARD_INFORMATION), - FileStandardInformation); - if (!NT_SUCCESS(Status)) + /* Query file size */ + Status = NtQueryInformationFile(FileHandle, + &IoStatusBlock, + &FileInfo, + sizeof(FILE_STANDARD_INFORMATION), + FileStandardInformation); + if (!NT_SUCCESS(Status)) { - DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status); - NtClose(FileHandle); - return(Status); + DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status); + NtClose(FileHandle); + return Status; } - FileLength = FileInfo.EndOfFile.u.LowPart; + FileLength = FileInfo.EndOfFile.u.LowPart; - DPRINT("File size: %lu\n", FileLength); + DPRINT("File size: %lu\n", FileLength); - /* Allocate file buffer */ - FileBuffer = (CHAR*) RtlAllocateHeap(ProcessHeap, - 0, - FileLength + 1); - if (FileBuffer == NULL) + /* Allocate file buffer */ + FileBuffer = (CHAR*)RtlAllocateHeap(ProcessHeap, + 0, + FileLength + 1); + if (FileBuffer == NULL) { - DPRINT1("RtlAllocateHeap() failed\n"); - NtClose(FileHandle); - return(STATUS_INSUFFICIENT_RESOURCES); + DPRINT1("RtlAllocateHeap() failed\n"); + NtClose(FileHandle); + return STATUS_INSUFFICIENT_RESOURCES; } - /* Read file */ - FileOffset.QuadPart = 0ULL; - Status = NtReadFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - FileBuffer, - FileLength, - &FileOffset, - NULL); + /* Read file */ + FileOffset.QuadPart = 0ULL; + Status = NtReadFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + FileBuffer, + FileLength, + &FileOffset, + NULL); - /* Append string terminator */ - FileBuffer[FileLength] = 0; + /* Append string terminator */ + FileBuffer[FileLength] = 0; - NtClose(FileHandle); + NtClose(FileHandle); - if (!NT_SUCCESS(Status)) + if (!NT_SUCCESS(Status)) { - DPRINT("NtReadFile() failed (Status %lx)\n", Status); - RtlFreeHeap(ProcessHeap, - 0, - FileBuffer); - return(Status); + DPRINT("NtReadFile() failed (Status %lx)\n", Status); + RtlFreeHeap(ProcessHeap, 0, FileBuffer); + return Status; } - - /* Allocate inicache header */ - *Cache = (PINICACHE)RtlAllocateHeap(ProcessHeap, - 0, - sizeof(INICACHE)); - if (*Cache == NULL) + /* Allocate inicache header */ + *Cache = (PINICACHE)RtlAllocateHeap(ProcessHeap, + 0, + sizeof(INICACHE)); + if (*Cache == NULL) { - DPRINT("RtlAllocateHeap() failed\n"); - return(STATUS_INSUFFICIENT_RESOURCES); + DPRINT("RtlAllocateHeap() failed\n"); + return STATUS_INSUFFICIENT_RESOURCES; } - /* Initialize inicache header */ - RtlZeroMemory(*Cache, - sizeof(INICACHE)); + /* Initialize inicache header */ + RtlZeroMemory(*Cache, sizeof(INICACHE)); - /* Parse ini file */ - Section = NULL; - Ptr = FileBuffer; - while (Ptr != NULL && *Ptr != 0) + /* Parse ini file */ + Section = NULL; + Ptr = FileBuffer; + while (Ptr != NULL && *Ptr != 0) { - Ptr = IniCacheSkipWhitespace(Ptr); - if (Ptr == NULL) - continue; + Ptr = IniCacheSkipWhitespace(Ptr); + if (Ptr == NULL) + continue; - if (*Ptr == '[') - { - Section = NULL; - Ptr++; + if (*Ptr == '[') + { + Section = NULL; + Ptr++; - Ptr = IniCacheGetSectionName(Ptr, - &SectionName, - &SectionNameSize); + Ptr = IniCacheGetSectionName(Ptr, + &SectionName, + &SectionNameSize); - DPRINT1("[%.*s]\n", SectionNameSize, SectionName); + DPRINT1("[%.*s]\n", SectionNameSize, SectionName); - Section = IniCacheAddSection(*Cache, - SectionName, - SectionNameSize); - if (Section == NULL) - { - DPRINT("IniCacheAddSection() failed\n"); - Ptr = IniCacheSkipToNextSection(Ptr); - continue; - } - } - else - { - if (Section == NULL) - { - Ptr = IniCacheSkipToNextSection(Ptr); - continue; - } + Section = IniCacheAddSection(*Cache, + SectionName, + SectionNameSize); + if (Section == NULL) + { + DPRINT("IniCacheAddSection() failed\n"); + Ptr = IniCacheSkipToNextSection(Ptr); + continue; + } + } + else + { + if (Section == NULL) + { + Ptr = IniCacheSkipToNextSection(Ptr); + continue; + } - Ptr = IniCacheGetKeyName(Ptr, - &KeyName, - &KeyNameSize); + Ptr = IniCacheGetKeyName(Ptr, + &KeyName, + &KeyNameSize); - Ptr = IniCacheGetKeyValue(Ptr, - &KeyValue, - &KeyValueSize, - String); + Ptr = IniCacheGetKeyValue(Ptr, + &KeyValue, + &KeyValueSize, + String); - DPRINT1("'%.*s' = '%.*s'\n", KeyNameSize, KeyName, KeyValueSize, KeyValue); + DPRINT1("'%.*s' = '%.*s'\n", KeyNameSize, KeyName, KeyValueSize, KeyValue); - Key = IniCacheAddKey(Section, - KeyName, - KeyNameSize, - KeyValue, - KeyValueSize); - if (Key == NULL) - { - DPRINT("IniCacheAddKey() failed\n"); - } - } + Key = IniCacheAddKey(Section, + KeyName, + KeyNameSize, + KeyValue, + KeyValueSize); + if (Key == NULL) + { + DPRINT("IniCacheAddKey() failed\n"); + } + } } - /* Free file buffer */ - RtlFreeHeap(ProcessHeap, - 0, - FileBuffer); + /* Free file buffer */ + RtlFreeHeap(ProcessHeap, 0, FileBuffer); - return(Status); + return Status; } VOID -IniCacheDestroy(PINICACHE Cache) +IniCacheDestroy( + PINICACHE Cache) { - if (Cache == NULL) + if (Cache == NULL) { - return; + return; } - while (Cache->FirstSection != NULL) + while (Cache->FirstSection != NULL) { - Cache->FirstSection = IniCacheFreeSection(Cache->FirstSection); + Cache->FirstSection = IniCacheFreeSection(Cache->FirstSection); } - Cache->LastSection = NULL; + Cache->LastSection = NULL; - RtlFreeHeap(ProcessHeap, - 0, - Cache); + RtlFreeHeap(ProcessHeap, 0, Cache); } PINICACHESECTION -IniCacheGetSection(PINICACHE Cache, - PWCHAR Name) +IniCacheGetSection( + PINICACHE Cache, + PWCHAR Name) { - PINICACHESECTION Section = NULL; + PINICACHESECTION Section = NULL; - if (Cache == NULL || Name == NULL) + if (Cache == NULL || Name == NULL) { - DPRINT("Invalid parameter\n"); - return(NULL); + DPRINT("Invalid parameter\n"); + return NULL; } - /* Iterate through list of sections */ - Section = Cache->FirstSection; - while (Section != NULL) + /* Iterate through list of sections */ + Section = Cache->FirstSection; + while (Section != NULL) { - DPRINT("Comparing '%S' and '%S'\n", Section->Name, Name); + DPRINT("Comparing '%S' and '%S'\n", Section->Name, Name); - /* Are the section names the same? */ - if (_wcsicmp(Section->Name, Name) == 0) - return(Section); + /* Are the section names the same? */ + if (_wcsicmp(Section->Name, Name) == 0) + return Section; - /* Get the next section */ - Section = Section->Next; + /* Get the next section */ + Section = Section->Next; } - DPRINT("Section not found\n"); + DPRINT("Section not found\n"); - return(NULL); + return NULL; } NTSTATUS -IniCacheGetKey(PINICACHESECTION Section, - PWCHAR KeyName, - PWCHAR *KeyData) +IniCacheGetKey( + PINICACHESECTION Section, + PWCHAR KeyName, + PWCHAR *KeyData) { - PINICACHEKEY Key; + PINICACHEKEY Key; - if (Section == NULL || KeyName == NULL || KeyData == NULL) + if (Section == NULL || KeyName == NULL || KeyData == NULL) { - DPRINT("Invalid parameter\n"); - return(STATUS_INVALID_PARAMETER); + DPRINT("Invalid parameter\n"); + return STATUS_INVALID_PARAMETER; } - *KeyData = NULL; + *KeyData = NULL; - Key = IniCacheFindKey(Section, KeyName, wcslen(KeyName)); - if (Key == NULL) + Key = IniCacheFindKey(Section, KeyName, wcslen(KeyName)); + if (Key == NULL) { - return(STATUS_INVALID_PARAMETER); + return STATUS_INVALID_PARAMETER; } - *KeyData = Key->Data; + *KeyData = Key->Data; - return(STATUS_SUCCESS); + return STATUS_SUCCESS; } PINICACHEITERATOR -IniCacheFindFirstValue(PINICACHESECTION Section, - PWCHAR *KeyName, - PWCHAR *KeyData) +IniCacheFindFirstValue( + PINICACHESECTION Section, + PWCHAR *KeyName, + PWCHAR *KeyData) { - PINICACHEITERATOR Iterator; - PINICACHEKEY Key; + PINICACHEITERATOR Iterator; + PINICACHEKEY Key; - if (Section == NULL || KeyName == NULL || KeyData == NULL) + if (Section == NULL || KeyName == NULL || KeyData == NULL) { - DPRINT("Invalid parameter\n"); - return(NULL); + DPRINT("Invalid parameter\n"); + return NULL; } - Key = Section->FirstKey; - if (Key == NULL) + Key = Section->FirstKey; + if (Key == NULL) { - DPRINT("Invalid parameter\n"); - return(NULL); + DPRINT("Invalid parameter\n"); + return NULL; } - *KeyName = Key->Name; - *KeyData = Key->Data; + *KeyName = Key->Name; + *KeyData = Key->Data; - Iterator = (PINICACHEITERATOR)RtlAllocateHeap(ProcessHeap, - 0, - sizeof(INICACHEITERATOR)); - if (Iterator == NULL) + Iterator = (PINICACHEITERATOR)RtlAllocateHeap(ProcessHeap, + 0, + sizeof(INICACHEITERATOR)); + if (Iterator == NULL) { - DPRINT("RtlAllocateHeap() failed\n"); - return(NULL); + DPRINT("RtlAllocateHeap() failed\n"); + return NULL; } - Iterator->Section = Section; - Iterator->Key = Key; + Iterator->Section = Section; + Iterator->Key = Key; - return(Iterator); + return Iterator; } BOOLEAN -IniCacheFindNextValue(PINICACHEITERATOR Iterator, - PWCHAR *KeyName, - PWCHAR *KeyData) +IniCacheFindNextValue( + PINICACHEITERATOR Iterator, + PWCHAR *KeyName, + PWCHAR *KeyData) { - PINICACHEKEY Key; + PINICACHEKEY Key; - if (Iterator == NULL || KeyName == NULL || KeyData == NULL) + if (Iterator == NULL || KeyName == NULL || KeyData == NULL) { - DPRINT("Invalid parameter\n"); - return(FALSE); + DPRINT("Invalid parameter\n"); + return FALSE; } - Key = Iterator->Key->Next; - if (Key == NULL) + Key = Iterator->Key->Next; + if (Key == NULL) { - DPRINT("No more entries\n"); - return(FALSE); + DPRINT("No more entries\n"); + return FALSE; } - *KeyName = Key->Name; - *KeyData = Key->Data; + *KeyName = Key->Name; + *KeyData = Key->Data; - Iterator->Key = Key; + Iterator->Key = Key; - return(TRUE); + return TRUE; } VOID -IniCacheFindClose(PINICACHEITERATOR Iterator) +IniCacheFindClose( + PINICACHEITERATOR Iterator) { - if (Iterator == NULL) - return; + if (Iterator == NULL) + return; - RtlFreeHeap(ProcessHeap, - 0, - Iterator); + RtlFreeHeap(ProcessHeap, 0, Iterator); } PINICACHEKEY -IniCacheInsertKey(PINICACHESECTION Section, - PINICACHEKEY AnchorKey, - INSERTATION_TYPE InsertationType, - PWCHAR Name, - PWCHAR Data) +IniCacheInsertKey( + PINICACHESECTION Section, + PINICACHEKEY AnchorKey, + INSERTATION_TYPE InsertationType, + PWCHAR Name, + PWCHAR Data) { - PINICACHEKEY Key; + PINICACHEKEY Key; - Key = NULL; + Key = NULL; - if (Section == NULL || - Name == NULL || - *Name == 0 || - Data == NULL || - *Data == 0) + if (Section == NULL || + Name == NULL || + *Name == 0 || + Data == NULL || + *Data == 0) { - DPRINT("Invalid parameter\n"); - return(NULL); + DPRINT("Invalid parameter\n"); + return NULL; } - /* Allocate key buffer */ - Key = (PINICACHEKEY)RtlAllocateHeap(ProcessHeap, - 0, - sizeof(INICACHEKEY)); - if (Key == NULL) + /* Allocate key buffer */ + Key = (PINICACHEKEY)RtlAllocateHeap(ProcessHeap, + 0, + sizeof(INICACHEKEY)); + if (Key == NULL) { - DPRINT("RtlAllocateHeap() failed\n"); - return(NULL); - } - RtlZeroMemory(Key, - sizeof(INICACHEKEY)); - - /* Allocate name buffer */ - Key->Name = (WCHAR*) RtlAllocateHeap(ProcessHeap, - 0, - (wcslen(Name) + 1) * sizeof(WCHAR)); - if (Key->Name == NULL) - { - DPRINT("RtlAllocateHeap() failed\n"); - RtlFreeHeap(ProcessHeap, - 0, - Key); - return(NULL); + DPRINT("RtlAllocateHeap() failed\n"); + return NULL; } - /* Copy value name */ - wcscpy(Key->Name, Name); + RtlZeroMemory(Key, sizeof(INICACHEKEY)); - /* Allocate data buffer */ - Key->Data = (WCHAR*) RtlAllocateHeap(ProcessHeap, - 0, - (wcslen(Data) + 1) * sizeof(WCHAR)); - if (Key->Data == NULL) + /* Allocate name buffer */ + Key->Name = (WCHAR*)RtlAllocateHeap(ProcessHeap, + 0, + (wcslen(Name) + 1) * sizeof(WCHAR)); + if (Key->Name == NULL) { - DPRINT("RtlAllocateHeap() failed\n"); - RtlFreeHeap(ProcessHeap, - 0, - Key->Name); - RtlFreeHeap(ProcessHeap, - 0, - Key); - return(NULL); + DPRINT("RtlAllocateHeap() failed\n"); + RtlFreeHeap(ProcessHeap, 0, Key); + return NULL; } - /* Copy value data */ - wcscpy(Key->Data, Data); + /* Copy value name */ + wcscpy(Key->Name, Name); - /* Insert key into section */ - if (Section->FirstKey == NULL) + /* Allocate data buffer */ + Key->Data = (WCHAR*)RtlAllocateHeap(ProcessHeap, + 0, + (wcslen(Data) + 1) * sizeof(WCHAR)); + if (Key->Data == NULL) { - Section->FirstKey = Key; - Section->LastKey = Key; - } - else if ((InsertationType == INSERT_FIRST) || - ((InsertationType == INSERT_BEFORE) && ((AnchorKey == NULL) || (AnchorKey == Section->FirstKey)))) - { - /* Insert at the head of the list */ - Section->FirstKey->Prev = Key; - Key->Next = Section->FirstKey; - Section->FirstKey = Key; - } - else if ((InsertationType == INSERT_BEFORE) && (AnchorKey != NULL)) - { - /* Insert before the anchor key */ - Key->Next = AnchorKey; - Key->Prev = AnchorKey->Prev; - AnchorKey->Prev->Next = Key; - AnchorKey->Prev = Key; - } - else if ((InsertationType == INSERT_LAST) || - ((InsertationType == INSERT_AFTER) && ((AnchorKey == NULL) || (AnchorKey == Section->LastKey)))) - { - Section->LastKey->Next = Key; - Key->Prev = Section->LastKey; - Section->LastKey = Key; - } - else if ((InsertationType == INSERT_AFTER) && (AnchorKey != NULL)) - { - /* Insert before the anchor key */ - Key->Next = AnchorKey->Next; - Key->Prev = AnchorKey; - AnchorKey->Next->Prev = Key; - AnchorKey->Next = Key; + DPRINT("RtlAllocateHeap() failed\n"); + RtlFreeHeap(ProcessHeap, 0, Key->Name); + RtlFreeHeap(ProcessHeap, 0, Key); + return NULL; } - return(Key); + /* Copy value data */ + wcscpy(Key->Data, Data); + + /* Insert key into section */ + if (Section->FirstKey == NULL) + { + Section->FirstKey = Key; + Section->LastKey = Key; + } + else if ((InsertationType == INSERT_FIRST) || + ((InsertationType == INSERT_BEFORE) && ((AnchorKey == NULL) || (AnchorKey == Section->FirstKey)))) + { + /* Insert at the head of the list */ + Section->FirstKey->Prev = Key; + Key->Next = Section->FirstKey; + Section->FirstKey = Key; + } + else if ((InsertationType == INSERT_BEFORE) && (AnchorKey != NULL)) + { + /* Insert before the anchor key */ + Key->Next = AnchorKey; + Key->Prev = AnchorKey->Prev; + AnchorKey->Prev->Next = Key; + AnchorKey->Prev = Key; + } + else if ((InsertationType == INSERT_LAST) || + ((InsertationType == INSERT_AFTER) && ((AnchorKey == NULL) || (AnchorKey == Section->LastKey)))) + { + Section->LastKey->Next = Key; + Key->Prev = Section->LastKey; + Section->LastKey = Key; + } + else if ((InsertationType == INSERT_AFTER) && (AnchorKey != NULL)) + { + /* Insert after the anchor key */ + Key->Next = AnchorKey->Next; + Key->Prev = AnchorKey; + AnchorKey->Next->Prev = Key; + AnchorKey->Next = Key; + } + + return Key; } PINICACHE IniCacheCreate(VOID) { - PINICACHE Cache; + PINICACHE Cache; - /* Allocate inicache header */ - Cache = (PINICACHE)RtlAllocateHeap(ProcessHeap, - 0, - sizeof(INICACHE)); - if (Cache == NULL) + /* Allocate inicache header */ + Cache = (PINICACHE)RtlAllocateHeap(ProcessHeap, + 0, + sizeof(INICACHE)); + if (Cache == NULL) { - DPRINT("RtlAllocateHeap() failed\n"); - return(NULL); + DPRINT("RtlAllocateHeap() failed\n"); + return NULL; } - /* Initialize inicache header */ - RtlZeroMemory(Cache, - sizeof(INICACHE)); + /* Initialize inicache header */ + RtlZeroMemory(Cache, sizeof(INICACHE)); - return(Cache); + return Cache; } NTSTATUS -IniCacheSave(PINICACHE Cache, - PWCHAR FileName) +IniCacheSave( + PINICACHE Cache, + PWCHAR FileName) { - UNICODE_STRING Name; - PINICACHESECTION Section; - PINICACHEKEY Key; - ULONG BufferSize; - PCHAR Buffer; - PCHAR Ptr; - ULONG Len; - NTSTATUS Status; + UNICODE_STRING Name; + PINICACHESECTION Section; + PINICACHEKEY Key; + ULONG BufferSize; + PCHAR Buffer; + PCHAR Ptr; + ULONG Len; + NTSTATUS Status; - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - LARGE_INTEGER Offset; - HANDLE FileHandle; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + LARGE_INTEGER Offset; + HANDLE FileHandle; - /* Calculate required buffer size */ - BufferSize = 0; - Section = Cache->FirstSection; - while (Section != NULL) + /* Calculate required buffer size */ + BufferSize = 0; + Section = Cache->FirstSection; + while (Section != NULL) { - BufferSize += (Section->Name ? wcslen(Section->Name) : 0) - + 4; /* "[]\r\n" */ + BufferSize += (Section->Name ? wcslen(Section->Name) : 0) + + 4; /* "[]\r\n" */ - Key = Section->FirstKey; - while (Key != NULL) - { - BufferSize += wcslen(Key->Name) - + (Key->Data ? wcslen(Key->Data) : 0) - + 3; /* "=\r\n" */ - Key = Key->Next; - } + Key = Section->FirstKey; + while (Key != NULL) + { + BufferSize += wcslen(Key->Name) + + (Key->Data ? wcslen(Key->Data) : 0) + + 3; /* "=\r\n" */ + Key = Key->Next; + } - Section = Section->Next; - if (Section != NULL) - BufferSize += 2; /* extra "\r\n" at end of each section */ + Section = Section->Next; + if (Section != NULL) + BufferSize += 2; /* extra "\r\n" at end of each section */ } - BufferSize++; /* Null-terminator */ + BufferSize++; /* Null-terminator */ - DPRINT("BufferSize: %lu\n", BufferSize); + DPRINT("BufferSize: %lu\n", BufferSize); - /* Allocate file buffer */ - Buffer = (CHAR*) RtlAllocateHeap(ProcessHeap, - 0, - BufferSize); - if (Buffer == NULL) + /* Allocate file buffer */ + Buffer = (CHAR*)RtlAllocateHeap(ProcessHeap, + 0, + BufferSize); + if (Buffer == NULL) { - DPRINT1("RtlAllocateHeap() failed\n"); - return(STATUS_INSUFFICIENT_RESOURCES); - } - RtlZeroMemory(Buffer, BufferSize); - - /* Fill file buffer */ - Ptr = Buffer; - Section = Cache->FirstSection; - while (Section != NULL) - { - Len = sprintf(Ptr, "[%S]\r\n", Section->Name); - Ptr += Len; - - Key = Section->FirstKey; - while (Key != NULL) - { - Len = sprintf(Ptr, "%S=%S\r\n", Key->Name, Key->Data); - Ptr += Len; - Key = Key->Next; - } - - Section = Section->Next; - if (Section != NULL) - { - Len = sprintf(Ptr, "\r\n"); - Ptr += Len; - } + DPRINT1("RtlAllocateHeap() failed\n"); + return STATUS_INSUFFICIENT_RESOURCES; } - /* Create ini file */ - RtlInitUnicodeString(&Name, - FileName); + RtlZeroMemory(Buffer, BufferSize); - InitializeObjectAttributes(&ObjectAttributes, - &Name, - 0, - NULL, - NULL); - - Status = NtCreateFile(&FileHandle, - GENERIC_WRITE | SYNCHRONIZE, - &ObjectAttributes, - &IoStatusBlock, - NULL, - FILE_ATTRIBUTE_NORMAL, - 0, - FILE_SUPERSEDE, - FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY, - NULL, - 0); - if (!NT_SUCCESS(Status)) + /* Fill file buffer */ + Ptr = Buffer; + Section = Cache->FirstSection; + while (Section != NULL) { - DPRINT("NtCreateFile() failed (Status %lx)\n", Status); - RtlFreeHeap(ProcessHeap, - 0, - Buffer); - return(Status); + Len = sprintf(Ptr, "[%S]\r\n", Section->Name); + Ptr += Len; + + Key = Section->FirstKey; + while (Key != NULL) + { + Len = sprintf(Ptr, "%S=%S\r\n", Key->Name, Key->Data); + Ptr += Len; + Key = Key->Next; + } + + Section = Section->Next; + if (Section != NULL) + { + Len = sprintf(Ptr, "\r\n"); + Ptr += Len; + } } - Offset.QuadPart = 0LL; - Status = NtWriteFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - Buffer, - BufferSize, - &Offset, - NULL); - if (!NT_SUCCESS(Status)) + /* Create ini file */ + RtlInitUnicodeString(&Name, + FileName); + + InitializeObjectAttributes(&ObjectAttributes, + &Name, + 0, + NULL, + NULL); + + Status = NtCreateFile(&FileHandle, + GENERIC_WRITE | SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + 0, + FILE_SUPERSEDE, + FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY, + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtCreateFile() failed (Status %lx)\n", Status); + RtlFreeHeap(ProcessHeap, 0, Buffer); + return Status; + } + + Offset.QuadPart = 0LL; + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + Buffer, + BufferSize, + &Offset, + NULL); + if (!NT_SUCCESS(Status)) { DPRINT("NtWriteFile() failed (Status %lx)\n", Status); NtClose(FileHandle); - RtlFreeHeap(ProcessHeap, - 0, - Buffer); - return(Status); + RtlFreeHeap(ProcessHeap, 0, Buffer); + return Status; } - NtClose(FileHandle); + NtClose(FileHandle); - RtlFreeHeap(ProcessHeap, - 0, - Buffer); + RtlFreeHeap(ProcessHeap, 0, Buffer); - return(STATUS_SUCCESS); + return STATUS_SUCCESS; } PINICACHESECTION -IniCacheAppendSection(PINICACHE Cache, - PWCHAR Name) +IniCacheAppendSection( + PINICACHE Cache, + PWCHAR Name) { - PINICACHESECTION Section = NULL; + PINICACHESECTION Section = NULL; - if (Cache == NULL || Name == NULL || *Name == 0) + if (Cache == NULL || Name == NULL || *Name == 0) { - DPRINT("Invalid parameter\n"); - return(NULL); + DPRINT("Invalid parameter\n"); + return NULL; } - Section = (PINICACHESECTION)RtlAllocateHeap(ProcessHeap, - 0, - sizeof(INICACHESECTION)); - if (Section == NULL) + Section = (PINICACHESECTION)RtlAllocateHeap(ProcessHeap, + 0, + sizeof(INICACHESECTION)); + if (Section == NULL) { - DPRINT("RtlAllocateHeap() failed\n"); - return(NULL); - } - RtlZeroMemory(Section, - sizeof(INICACHESECTION)); - - /* Allocate and initialize section name */ - Section->Name = (WCHAR*) RtlAllocateHeap(ProcessHeap, - 0, - (wcslen(Name) + 1) * sizeof(WCHAR)); - if (Section->Name == NULL) - { - DPRINT("RtlAllocateHeap() failed\n"); - RtlFreeHeap(ProcessHeap, - 0, - Section); - return(NULL); + DPRINT("RtlAllocateHeap() failed\n"); + return NULL; } - /* Copy section name */ - wcscpy(Section->Name, Name); + RtlZeroMemory(Section, sizeof(INICACHESECTION)); - /* Append section */ - if (Cache->FirstSection == NULL) + /* Allocate and initialize section name */ + Section->Name = (WCHAR*)RtlAllocateHeap(ProcessHeap, + 0, + (wcslen(Name) + 1) * sizeof(WCHAR)); + if (Section->Name == NULL) { - Cache->FirstSection = Section; - Cache->LastSection = Section; - } - else - { - Cache->LastSection->Next = Section; - Section->Prev = Cache->LastSection; - Cache->LastSection = Section; + DPRINT("RtlAllocateHeap() failed\n"); + RtlFreeHeap(ProcessHeap, 0, Section); + return NULL; } - return(Section); + /* Copy section name */ + wcscpy(Section->Name, Name); + + /* Append section */ + if (Cache->FirstSection == NULL) + { + Cache->FirstSection = Section; + Cache->LastSection = Section; + } + else + { + Cache->LastSection->Next = Section; + Section->Prev = Cache->LastSection; + Cache->LastSection = Section; + } + + return Section; } /* EOF */ diff --git a/base/setup/usetup/inicache.h b/base/setup/usetup/inicache.h index bd7dd33510c..4da4c117f36 100644 --- a/base/setup/usetup/inicache.h +++ b/base/setup/usetup/inicache.h @@ -29,99 +29,107 @@ typedef struct _INICACHEKEY { - PWCHAR Name; - PWCHAR Data; + PWCHAR Name; + PWCHAR Data; - struct _INICACHEKEY *Next; - struct _INICACHEKEY *Prev; + struct _INICACHEKEY *Next; + struct _INICACHEKEY *Prev; } INICACHEKEY, *PINICACHEKEY; typedef struct _INICACHESECTION { - PWCHAR Name; + PWCHAR Name; - PINICACHEKEY FirstKey; - PINICACHEKEY LastKey; + PINICACHEKEY FirstKey; + PINICACHEKEY LastKey; - struct _INICACHESECTION *Next; - struct _INICACHESECTION *Prev; + struct _INICACHESECTION *Next; + struct _INICACHESECTION *Prev; } INICACHESECTION, *PINICACHESECTION; typedef struct _INICACHE { - PINICACHESECTION FirstSection; - PINICACHESECTION LastSection; + PINICACHESECTION FirstSection; + PINICACHESECTION LastSection; } INICACHE, *PINICACHE; typedef struct _PINICACHEITERATOR { - PINICACHESECTION Section; - PINICACHEKEY Key; + PINICACHESECTION Section; + PINICACHEKEY Key; } INICACHEITERATOR, *PINICACHEITERATOR; typedef enum { - INSERT_FIRST, - INSERT_BEFORE, - INSERT_AFTER, - INSERT_LAST + INSERT_FIRST, + INSERT_BEFORE, + INSERT_AFTER, + INSERT_LAST } INSERTATION_TYPE; /* FUNCTIONS ****************************************************************/ NTSTATUS -IniCacheLoad(PINICACHE *Cache, - PUNICODE_STRING FileName, - BOOLEAN String); +IniCacheLoad( + PINICACHE *Cache, + PUNICODE_STRING FileName, + BOOLEAN String); VOID -IniCacheDestroy(PINICACHE Cache); +IniCacheDestroy( + PINICACHE Cache); PINICACHESECTION -IniCacheGetSection(PINICACHE Cache, - PWCHAR Name); +IniCacheGetSection( + PINICACHE Cache, + PWCHAR Name); NTSTATUS -IniCacheGetKey(PINICACHESECTION Section, - PWCHAR KeyName, - PWCHAR *KeyData); - - +IniCacheGetKey( + PINICACHESECTION Section, + PWCHAR KeyName, + PWCHAR *KeyData); PINICACHEITERATOR -IniCacheFindFirstValue(PINICACHESECTION Section, - PWCHAR *KeyName, - PWCHAR *KeyData); +IniCacheFindFirstValue( + PINICACHESECTION Section, + PWCHAR *KeyName, + PWCHAR *KeyData); BOOLEAN -IniCacheFindNextValue(PINICACHEITERATOR Iterator, - PWCHAR *KeyName, - PWCHAR *KeyData); +IniCacheFindNextValue( + PINICACHEITERATOR Iterator, + PWCHAR *KeyName, + PWCHAR *KeyData); VOID -IniCacheFindClose(PINICACHEITERATOR Iterator); +IniCacheFindClose( + PINICACHEITERATOR Iterator); PINICACHEKEY -IniCacheInsertKey(PINICACHESECTION Section, - PINICACHEKEY AnchorKey, - INSERTATION_TYPE InsertationType, - PWCHAR Name, - PWCHAR Data); +IniCacheInsertKey( + PINICACHESECTION Section, + PINICACHEKEY AnchorKey, + INSERTATION_TYPE InsertationType, + PWCHAR Name, + PWCHAR Data); PINICACHE IniCacheCreate(VOID); NTSTATUS -IniCacheSave(PINICACHE Cache, - PWCHAR FileName); +IniCacheSave( + PINICACHE Cache, + PWCHAR FileName); PINICACHESECTION -IniCacheAppendSection(PINICACHE Cache, - PWCHAR Name); +IniCacheAppendSection( + PINICACHE Cache, + PWCHAR Name); /* EOF */ diff --git a/base/setup/usetup/mui.c b/base/setup/usetup/mui.c index 71a6250feb9..1ebcf4a31b4 100644 --- a/base/setup/usetup/mui.c +++ b/base/setup/usetup/mui.c @@ -63,8 +63,10 @@ FindLanguageIndex(VOID) return 0; } + BOOLEAN -IsLanguageAvailable(PWCHAR LanguageId) +IsLanguageAvailable( + PWCHAR LanguageId) { ULONG lngIndex = 0; @@ -82,7 +84,8 @@ IsLanguageAvailable(PWCHAR LanguageId) static const MUI_ENTRY * -FindMUIEntriesOfPage(IN ULONG PageNumber) +FindMUIEntriesOfPage( + IN ULONG PageNumber) { ULONG muiIndex = 0; ULONG lngIndex; @@ -102,6 +105,7 @@ FindMUIEntriesOfPage(IN ULONG PageNumber) return NULL; } + static const MUI_ERROR * FindMUIErrorEntries(VOID) @@ -110,6 +114,7 @@ FindMUIErrorEntries(VOID) return LanguageList[lngIndex].MuiErrors; } + static const MUI_STRING * FindMUIStringEntries(VOID) @@ -118,6 +123,7 @@ FindMUIStringEntries(VOID) return LanguageList[lngIndex].MuiStrings; } + LPCWSTR MUIDefaultKeyboardLayout(VOID) { @@ -125,6 +131,7 @@ MUIDefaultKeyboardLayout(VOID) return LanguageList[lngIndex].MuiLayouts[0].LayoutID; } + PWCHAR MUIGetGeoID(VOID) { @@ -132,6 +139,7 @@ MUIGetGeoID(VOID) return LanguageList[lngIndex].GeoID; } + const MUI_LAYOUTS * MUIGetLayoutsList(VOID) { @@ -139,8 +147,10 @@ MUIGetLayoutsList(VOID) return LanguageList[lngIndex].MuiLayouts; } + VOID -MUIClearPage(IN ULONG page) +MUIClearPage( + IN ULONG page) { const MUI_ENTRY * entry; int index; @@ -167,8 +177,10 @@ MUIClearPage(IN ULONG page) while (entry[index].Buffer != NULL); } + VOID -MUIDisplayPage(IN ULONG page) +MUIDisplayPage( + IN ULONG page) { const MUI_ENTRY * entry; int index; @@ -196,8 +208,12 @@ MUIDisplayPage(IN ULONG page) while (entry[index].Buffer != NULL); } + VOID -MUIDisplayError(IN ULONG ErrorNum, OUT PINPUT_RECORD Ir, IN ULONG WaitEvent) +MUIDisplayError( + IN ULONG ErrorNum, + OUT PINPUT_RECORD Ir, + IN ULONG WaitEvent) { const MUI_ERROR * entry; @@ -227,8 +243,10 @@ MUIDisplayError(IN ULONG ErrorNum, OUT PINPUT_RECORD Ir, IN ULONG WaitEvent) WaitEvent); } + LPSTR -MUIGetString(ULONG Number) +MUIGetString( + ULONG Number) { ULONG i; const MUI_STRING * entry; @@ -249,15 +267,20 @@ MUIGetString(ULONG Number) sprintf(szErr, "Error: failed find string id %lu for language index %lu\n", Number, FindLanguageIndex()); PopupError(szErr, - NULL, - NULL, - POPUP_WAIT_NONE); + NULL, + NULL, + POPUP_WAIT_NONE); return ""; } -static BOOLEAN -AddHotkeySettings(IN LPCWSTR Hotkey, IN LPCWSTR LangHotkey, IN LPCWSTR LayoutHotkey) + +static +BOOLEAN +AddHotkeySettings( + IN LPCWSTR Hotkey, + IN LPCWSTR LangHotkey, + IN LPCWSTR LayoutHotkey) { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING KeyName; @@ -340,8 +363,10 @@ AddHotkeySettings(IN LPCWSTR Hotkey, IN LPCWSTR LangHotkey, IN LPCWSTR LayoutHot return TRUE; } + BOOLEAN -AddKbLayoutsToRegistry(IN const MUI_LAYOUTS * MuiLayouts) +AddKbLayoutsToRegistry( + IN const MUI_LAYOUTS *MuiLayouts) { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING KeyName; @@ -509,10 +534,12 @@ AddKbLayoutsToRegistry(IN const MUI_LAYOUTS * MuiLayouts) return TRUE; } + BOOLEAN AddKeyboardLayouts(VOID) { ULONG lngIndex = 0; + do { if (_wcsicmp(LanguageList[lngIndex].LanguageID , SelectedLanguageId) == 0) @@ -527,8 +554,13 @@ AddKeyboardLayouts(VOID) return FALSE; } -static BOOLEAN -AddCodepageToRegistry(IN LPCWSTR ACPage, IN LPCWSTR OEMCPage, IN LPCWSTR MACCPage) + +static +BOOLEAN +AddCodepageToRegistry( + IN LPCWSTR ACPage, + IN LPCWSTR OEMCPage, + IN LPCWSTR MACCPage) { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING KeyName; @@ -603,8 +635,11 @@ AddCodepageToRegistry(IN LPCWSTR ACPage, IN LPCWSTR OEMCPage, IN LPCWSTR MACCPag return TRUE; } -static BOOLEAN -AddFontsSettingsToRegistry(IN const MUI_SUBFONT * MuiSubFonts) + +static +BOOLEAN +AddFontsSettingsToRegistry( + IN const MUI_SUBFONT * MuiSubFonts) { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING KeyName; @@ -654,6 +689,7 @@ AddFontsSettingsToRegistry(IN const MUI_SUBFONT * MuiSubFonts) return TRUE; } + BOOLEAN AddCodePage(VOID) { @@ -682,6 +718,7 @@ AddCodePage(VOID) return FALSE; } + VOID SetConsoleCodePage(VOID) { diff --git a/base/setup/usetup/mui.h b/base/setup/usetup/mui.h index f8074efd312..bf35835f792 100644 --- a/base/setup/usetup/mui.h +++ b/base/setup/usetup/mui.h @@ -54,16 +54,22 @@ typedef struct } MUI_LANGUAGE; BOOLEAN -IsLanguageAvailable(PWCHAR LanguageId); +IsLanguageAvailable( + PWCHAR LanguageId); VOID -MUIDisplayPage (ULONG PageNumber); +MUIDisplayPage( + ULONG PageNumber); VOID -MUIClearPage (ULONG PageNumber); +MUIClearPage( + ULONG PageNumber); VOID -MUIDisplayError (ULONG ErrorNum, PINPUT_RECORD Ir, ULONG WaitEvent); +MUIDisplayError( + ULONG ErrorNum, + PINPUT_RECORD Ir, + ULONG WaitEvent); LPCWSTR MUIDefaultKeyboardLayout(VOID); @@ -75,7 +81,8 @@ const MUI_LAYOUTS * MUIGetLayoutsList(VOID); BOOLEAN -AddKbLayoutsToRegistry(IN const MUI_LAYOUTS * MuiLayouts); +AddKbLayoutsToRegistry( + IN const MUI_LAYOUTS *MuiLayouts); BOOLEAN AddCodePage(VOID); @@ -87,7 +94,8 @@ VOID SetConsoleCodePage(VOID); LPSTR -MUIGetString(ULONG Number); +MUIGetString( + ULONG Number); #define STRING_PLEASEWAIT 1 #define STRING_INSTALLCREATEPARTITION 2 diff --git a/base/setup/usetup/muilanguages.h b/base/setup/usetup/muilanguages.h index a27f9ba7924..c2c4ea04895 100644 --- a/base/setup/usetup/muilanguages.h +++ b/base/setup/usetup/muilanguages.h @@ -409,424 +409,424 @@ const MUI_LANGUAGE LanguageList[] = { /* Lang ID, ANSI CP, OEM CP, MAC CP, Language Name, GeoID page strgs,error strings, other strings, fonts, kb layouts */ #ifdef LANGUAGE_AF_ZA - {L"00000436", L"1252", L"850", L"10000", L"Afrikaans", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, afZALayouts }, + {L"00000436", L"1252", L"850", L"10000", L"Afrikaans", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, afZALayouts }, #endif #ifdef LANGUAGE_SQ_AL {L"0000041C", L"1250", L"852", L"10029", L"Albanian (Albania)", L"355", sqALPages, sqALErrorEntries, sqALStrings, LatinFonts, sqALLayouts }, #endif #ifdef LANGUAGE_AR_SA - {L"00000401", L"1256", L"720", L"10004", L"Arabic (Saudi Arabia)", L"966", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arSALayouts }, + {L"00000401", L"1256", L"720", L"10004", L"Arabic (Saudi Arabia)", L"966", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arSALayouts }, #endif #ifdef LANGUAGE_AR_IQ - {L"00000801", L"1256", L"720", L"10004", L"Arabic (Iraq)", L"964", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arIQLayouts }, + {L"00000801", L"1256", L"720", L"10004", L"Arabic (Iraq)", L"964", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arIQLayouts }, #endif #ifdef LANGUAGE_AR_EG - {L"00000C01", L"1256", L"720", L"10004", L"Arabic (Egypt)", L"20", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arEGLayouts }, + {L"00000C01", L"1256", L"720", L"10004", L"Arabic (Egypt)", L"20", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arEGLayouts }, #endif #ifdef LANGUAGE_AR_LY - {L"00001001", L"1256", L"720", L"10004", L"Arabic (Libya)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arLYLayouts }, + {L"00001001", L"1256", L"720", L"10004", L"Arabic (Libya)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arLYLayouts }, #endif #ifdef LANGUAGE_AR_DZ - {L"00001401", L"1256", L"720", L"10004", L"Arabic (Algeria)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arDZLayouts }, + {L"00001401", L"1256", L"720", L"10004", L"Arabic (Algeria)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arDZLayouts }, #endif #ifdef LANGUAGE_AR_MA - {L"00001801", L"1256", L"720", L"10004", L"Arabic (Morocco)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arMALayouts }, + {L"00001801", L"1256", L"720", L"10004", L"Arabic (Morocco)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arMALayouts }, #endif #ifdef LANGUAGE_AR_TN - {L"00001C01", L"1256", L"720", L"10004", L"Arabic (Tunisia)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arTNLayouts }, + {L"00001C01", L"1256", L"720", L"10004", L"Arabic (Tunisia)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arTNLayouts }, #endif #ifdef LANGUAGE_AR_OM - {L"00002001", L"1256", L"720", L"10004", L"Arabic (Oman)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arOMLayouts }, + {L"00002001", L"1256", L"720", L"10004", L"Arabic (Oman)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arOMLayouts }, #endif #ifdef LANGUAGE_AR_YE - {L"00002401", L"1256", L"720", L"10004", L"Arabic (Yemen)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arYELayouts }, + {L"00002401", L"1256", L"720", L"10004", L"Arabic (Yemen)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arYELayouts }, #endif #ifdef LANGUAGE_AR_SY - {L"00002801", L"1256", L"720", L"10004", L"Arabic (Syria)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arSYLayouts }, + {L"00002801", L"1256", L"720", L"10004", L"Arabic (Syria)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arSYLayouts }, #endif #ifdef LANGUAGE_AR_JO - {L"00002C01", L"1256", L"720", L"10004", L"Arabic (Jordan)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arJOLayouts }, + {L"00002C01", L"1256", L"720", L"10004", L"Arabic (Jordan)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arJOLayouts }, #endif #ifdef LANGUAGE_AR_LB - {L"00003001", L"1256", L"720", L"10004", L"Arabic (Lebanon)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arLBLayouts }, + {L"00003001", L"1256", L"720", L"10004", L"Arabic (Lebanon)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arLBLayouts }, #endif #ifdef LANGUAGE_AR_KW - {L"00003401", L"1256", L"720", L"10004", L"Arabic (Kuwait)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arKWLayouts }, + {L"00003401", L"1256", L"720", L"10004", L"Arabic (Kuwait)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arKWLayouts }, #endif #ifdef LANGUAGE_AR_AE - {L"00003801", L"1256", L"720", L"10004", L"Arabic (U.A.E.)", L"971", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arAELayouts }, + {L"00003801", L"1256", L"720", L"10004", L"Arabic (U.A.E.)", L"971", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arAELayouts }, #endif #ifdef LANGUAGE_AR_BH - {L"00003C01", L"1256", L"720", L"10004", L"Arabic (Bahrain)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arBHLayouts }, + {L"00003C01", L"1256", L"720", L"10004", L"Arabic (Bahrain)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arBHLayouts }, #endif #ifdef LANGUAGE_AR_QA - {L"00004001", L"1256", L"720", L"10004", L"Arabic (Qatar)", L"974", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arQALayouts }, + {L"00004001", L"1256", L"720", L"10004", L"Arabic (Qatar)", L"974", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, arQALayouts }, #endif #ifdef LANGUAGE_HY_AM - {L"0000042B", L"0", L"1", L"2", L"Armenian", L"374", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, hyAMLayouts }, + {L"0000042B", L"0", L"1", L"2", L"Armenian", L"374", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, hyAMLayouts }, #endif #ifdef LANGUAGE_AZ_AZ - {L"0000082C", L"1251", L"866", L"10007", L"Azeri (Cyrillic)", L"1", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, azAZLayouts }, + {L"0000082C", L"1251", L"866", L"10007", L"Azeri (Cyrillic)", L"1", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, azAZLayouts }, #endif #ifdef LANGUAGE_AZ_AZ - {L"0000042C", L"1254", L"857", L"10081", L"Azeri (Latin)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, azAZLayouts }, + {L"0000042C", L"1254", L"857", L"10081", L"Azeri (Latin)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, azAZLayouts }, #endif #ifdef LANGUAGE_EU_ES - {L"0000042D", L"1252", L"850", L"10000", L"Basque", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, euESLayouts }, + {L"0000042D", L"1252", L"850", L"10000", L"Basque", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, euESLayouts }, #endif #ifdef LANGUAGE_BE_BY - {L"00000423", L"1251", L"866", L"10007", L"Belarusian", L"1", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, beBYLayouts }, + {L"00000423", L"1251", L"866", L"10007", L"Belarusian", L"1", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, beBYLayouts }, #endif #ifdef LANGUAGE_BG_BG - {L"00000402", L"1251", L"866", L"10007", L"Bulgarian", L"359", bgBGPages, bgBGErrorEntries, bgBGStrings, CyrillicFonts, bgBGLayouts }, + {L"00000402", L"1251", L"866", L"10007", L"Bulgarian", L"359", bgBGPages, bgBGErrorEntries, bgBGStrings, CyrillicFonts, bgBGLayouts }, #endif #ifdef LANGUAGE_MY_MM - {L"00000455", L"0", L"1", L"2", L"Burmese", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, myMMLayouts }, + {L"00000455", L"0", L"1", L"2", L"Burmese", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, myMMLayouts }, #endif #ifdef LANGUAGE_CA_ES - {L"00000403", L"1252", L"850", L"10000", L"Catalan", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, caESLayouts }, + {L"00000403", L"1252", L"850", L"10000", L"Catalan", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, caESLayouts }, #endif #ifdef LANGUAGE_ZH_TW - {L"00000404", L"950", L"950", L"10008", L"Chinese (Taiwan)", L"886", enUSPages, enUSErrorEntries, enUSStrings, CJKFonts, zhTWLayouts }, + {L"00000404", L"950", L"950", L"10008", L"Chinese (Taiwan)", L"886", enUSPages, enUSErrorEntries, enUSStrings, CJKFonts, zhTWLayouts }, #endif #ifdef LANGUAGE_ZH_CN - {L"00000804", L"936", L"936", L"10008", L"Chinese (PRC)", L"86", enUSPages, enUSErrorEntries, enUSStrings, CJKFonts, zhCNLayouts }, + {L"00000804", L"936", L"936", L"10008", L"Chinese (PRC)", L"86", enUSPages, enUSErrorEntries, enUSStrings, CJKFonts, zhCNLayouts }, #endif #ifdef LANGUAGE_ZH_HK - {L"00000C04", L"950", L"950", L"10008", L"Chinese (Hong Kong S.A.R.)", L"1", enUSPages, enUSErrorEntries, enUSStrings, CJKFonts, zhHKLayouts }, + {L"00000C04", L"950", L"950", L"10008", L"Chinese (Hong Kong S.A.R.)", L"1", enUSPages, enUSErrorEntries, enUSStrings, CJKFonts, zhHKLayouts }, #endif #ifdef LANGUAGE_ZH_SG - {L"00001004", L"936", L"936", L"10008", L"Chinese (Singapore)", L"1", enUSPages, enUSErrorEntries, enUSStrings, CJKFonts, zhSGLayouts }, + {L"00001004", L"936", L"936", L"10008", L"Chinese (Singapore)", L"1", enUSPages, enUSErrorEntries, enUSStrings, CJKFonts, zhSGLayouts }, #endif #ifdef LANGUAGE_ZH_MO - {L"00001404", L"950", L"950", L"10002", L"Chinese (Macau S.A.R.)", L"1", enUSPages, enUSErrorEntries, enUSStrings, CJKFonts, zhMOLayouts }, + {L"00001404", L"950", L"950", L"10002", L"Chinese (Macau S.A.R.)", L"1", enUSPages, enUSErrorEntries, enUSStrings, CJKFonts, zhMOLayouts }, #endif #ifdef LANGUAGE_HR_HR - {L"0000041A", L"1250", L"852", L"10029", L"Croatian", L"385", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, hrHRLayouts }, + {L"0000041A", L"1250", L"852", L"10029", L"Croatian", L"385", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, hrHRLayouts }, #endif #ifdef LANGUAGE_CS_CZ - {L"00000405", L"1250", L"852", L"10029", L"Czech", L"420", csCZPages, csCZErrorEntries, csCZStrings, LatinFonts, csCZLayouts }, + {L"00000405", L"1250", L"852", L"10029", L"Czech", L"420", csCZPages, csCZErrorEntries, csCZStrings, LatinFonts, csCZLayouts }, #endif #ifdef LANGUAGE_DA_DK - {L"00000406", L"1252", L"850", L"10000", L"Danish", L"45", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, daDKLayouts }, + {L"00000406", L"1252", L"850", L"10000", L"Danish", L"45", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, daDKLayouts }, #endif #ifdef LANGUAGE_DV_MV - {L"00000465", L"0", L"1", L"2", L"Dhivehi (Maldives)", L"960", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, dvMVLayouts }, + {L"00000465", L"0", L"1", L"2", L"Dhivehi (Maldives)", L"960", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, dvMVLayouts }, #endif #ifdef LANGUAGE_NL_NL - {L"00000413", L"1252", L"850", L"10000", L"Dutch (Netherlands)", L"31", nlNLPages, nlNLErrorEntries, nlNLStrings, LatinFonts, nlNLLayouts }, + {L"00000413", L"1252", L"850", L"10000", L"Dutch (Netherlands)", L"31", nlNLPages, nlNLErrorEntries, nlNLStrings, LatinFonts, nlNLLayouts }, #endif #ifdef LANGUAGE_NL_BE - {L"00000813", L"1252", L"850", L"10000", L"Dutch (Belgium)", L"32", nlNLPages, nlNLErrorEntries, nlNLStrings, LatinFonts, nlBELayouts }, + {L"00000813", L"1252", L"850", L"10000", L"Dutch (Belgium)", L"32", nlNLPages, nlNLErrorEntries, nlNLStrings, LatinFonts, nlBELayouts }, #endif #ifdef LANGUAGE_EN_US - {L"00000409", L"1252", L"437", L"10000", L"English (United States)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enUSLayouts }, + {L"00000409", L"1252", L"437", L"10000", L"English (United States)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enUSLayouts }, #endif #ifdef LANGUAGE_EN_GB - {L"00000809", L"1252", L"850", L"10000", L"English (United Kingdom)", L"44", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enGBLayouts }, + {L"00000809", L"1252", L"850", L"10000", L"English (United Kingdom)", L"44", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enGBLayouts }, #endif #ifdef LANGUAGE_EN_AU - {L"00000C09", L"1252", L"850", L"10000", L"English (Australia)", L"61", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enAULayouts }, + {L"00000C09", L"1252", L"850", L"10000", L"English (Australia)", L"61", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enAULayouts }, #endif #ifdef LANGUAGE_EN_CA - {L"00001009", L"1252", L"850", L"10000", L"English (Canada)", L"107", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enCALayouts }, + {L"00001009", L"1252", L"850", L"10000", L"English (Canada)", L"107", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enCALayouts }, #endif #ifdef LANGUAGE_EN_NZ - {L"00001409", L"1252", L"850", L"10000", L"English (New Zealand)", L"64", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enNZLayouts }, + {L"00001409", L"1252", L"850", L"10000", L"English (New Zealand)", L"64", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enNZLayouts }, #endif #ifdef LANGUAGE_EN_IE - {L"00001809", L"1252", L"850", L"10000", L"English (Ireland)", L"353", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enIELayouts }, + {L"00001809", L"1252", L"850", L"10000", L"English (Ireland)", L"353", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enIELayouts }, #endif #ifdef LANGUAGE_EN_ZA - {L"00001C09", L"1252", L"437", L"10000", L"English (South Africa)", L"27", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enZALayouts }, + {L"00001C09", L"1252", L"437", L"10000", L"English (South Africa)", L"27", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enZALayouts }, #endif #ifdef LANGUAGE_EN_JM - {L"00002009", L"1252", L"850", L"10000", L"English (Jamaica)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enJMLayouts }, + {L"00002009", L"1252", L"850", L"10000", L"English (Jamaica)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enJMLayouts }, #endif #ifdef LANGUAGE_EN_CB - {L"00002409", L"1252", L"850", L"10000", L"English (Caribbean)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enCBLayouts }, + {L"00002409", L"1252", L"850", L"10000", L"English (Caribbean)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enCBLayouts }, #endif #ifdef LANGUAGE_EN_BZ - {L"00002809", L"1252", L"850", L"10000", L"English (Belize)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enBZLayouts }, + {L"00002809", L"1252", L"850", L"10000", L"English (Belize)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enBZLayouts }, #endif #ifdef LANGUAGE_EN_TT - {L"00002C09", L"1252", L"850", L"10000", L"English (Trinidad)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enTTLayouts }, + {L"00002C09", L"1252", L"850", L"10000", L"English (Trinidad)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enTTLayouts }, #endif #ifdef LANGUAGE_EN_ZW - {L"00003009", L"1252", L"437", L"10000", L"English (Zimbabwe)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enZWLayouts }, + {L"00003009", L"1252", L"437", L"10000", L"English (Zimbabwe)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enZWLayouts }, #endif #ifdef LANGUAGE_EN_PH - {L"00003409", L"1252", L"437", L"10000", L"English (Philippines)", L"63", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enPHLayouts }, + {L"00003409", L"1252", L"437", L"10000", L"English (Philippines)", L"63", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, enPHLayouts }, #endif #ifdef LANGUAGE_EO_AA - {L"0000048F", L"1252", L"437", L"10000", L"Esperanto", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, eoAALayouts }, + {L"0000048F", L"1252", L"437", L"10000", L"Esperanto", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, eoAALayouts }, #endif #ifdef LANGUAGE_ET_EE - {L"00000425", L"1252", L"775", L"10029", L"Estonian", L"372", etEEPages, etEEErrorEntries, etEEStrings, LatinFonts, etEELayouts }, + {L"00000425", L"1252", L"775", L"10029", L"Estonian", L"372", etEEPages, etEEErrorEntries, etEEStrings, LatinFonts, etEELayouts }, #endif #ifdef LANGUAGE_FO_FO - {L"00000438", L"1252", L"850", L"10079", L"Faeroese", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, foFOLayouts }, + {L"00000438", L"1252", L"850", L"10079", L"Faeroese", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, foFOLayouts }, #endif #ifdef LANGUAGE_FA_IR - {L"00000429", L"1256", L"720", L"10004", L"Farsi", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, faIRLayouts }, + {L"00000429", L"1256", L"720", L"10004", L"Farsi", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, faIRLayouts }, #endif #ifdef LANGUAGE_FI_FI - {L"0000040B", L"1252", L"850", L"10000", L"Finnish", L"358", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, fiFILayouts }, + {L"0000040B", L"1252", L"850", L"10000", L"Finnish", L"358", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, fiFILayouts }, #endif #ifdef LANGUAGE_FR_CA - {L"00000C0C", L"1252", L"850", L"10000", L"French (Canada)", L"107", frFRPages, frFRErrorEntries, frFRStrings, LatinFonts, frCALayouts }, + {L"00000C0C", L"1252", L"850", L"10000", L"French (Canada)", L"107", frFRPages, frFRErrorEntries, frFRStrings, LatinFonts, frCALayouts }, #endif #ifdef LANGUAGE_FR_FR - {L"0000040C", L"1252", L"850", L"10000", L"French (France)", L"33", frFRPages, frFRErrorEntries, frFRStrings, LatinFonts, frFRLayouts }, + {L"0000040C", L"1252", L"850", L"10000", L"French (France)", L"33", frFRPages, frFRErrorEntries, frFRStrings, LatinFonts, frFRLayouts }, #endif #ifdef LANGUAGE_FR_BE - {L"0000080C", L"1252", L"850", L"10000", L"French (Belgium)", L"32", frFRPages, frFRErrorEntries, frFRStrings, LatinFonts, frBELayouts }, + {L"0000080C", L"1252", L"850", L"10000", L"French (Belgium)", L"32", frFRPages, frFRErrorEntries, frFRStrings, LatinFonts, frBELayouts }, #endif #ifdef LANGUAGE_FR_CH - {L"0000100C", L"1252", L"850", L"10000", L"French (Switzerland)", L"41", frFRPages, frFRErrorEntries, frFRStrings, LatinFonts, frCHLayouts }, + {L"0000100C", L"1252", L"850", L"10000", L"French (Switzerland)", L"41", frFRPages, frFRErrorEntries, frFRStrings, LatinFonts, frCHLayouts }, #endif #ifdef LANGUAGE_FR_LU - {L"0000140C", L"1252", L"850", L"10000", L"French (Luxembourg)", L"352", frFRPages, frFRErrorEntries, frFRStrings, LatinFonts, frLULayouts }, + {L"0000140C", L"1252", L"850", L"10000", L"French (Luxembourg)", L"352", frFRPages, frFRErrorEntries, frFRStrings, LatinFonts, frLULayouts }, #endif #ifdef LANGUAGE_FR_MC - {L"0000180C", L"1252", L"850", L"10000", L"French (Monaco)", L"1", frFRPages, frFRErrorEntries, frFRStrings, LatinFonts, frMCLayouts }, + {L"0000180C", L"1252", L"850", L"10000", L"French (Monaco)", L"1", frFRPages, frFRErrorEntries, frFRStrings, LatinFonts, frMCLayouts }, #endif #ifdef LANGUAGE_GL_ES - {L"00000456", L"1252", L"850", L"10000", L"Galician (Spain)", L"34", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, glESLayouts }, + {L"00000456", L"1252", L"850", L"10000", L"Galician (Spain)", L"34", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, glESLayouts }, #endif #ifdef LANGUAGE_KA_GE - {L"00000437", L"0", L"1", L"2", L"Georgian", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, kaGELayouts }, + {L"00000437", L"0", L"1", L"2", L"Georgian", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, kaGELayouts }, #endif #ifdef LANGUAGE_DE_DE - {L"00000407", L"1252", L"850", L"10000", L"German (Germany)", L"49", deDEPages, deDEErrorEntries, deDEStrings, LatinFonts, deDELayouts }, + {L"00000407", L"1252", L"850", L"10000", L"German (Germany)", L"49", deDEPages, deDEErrorEntries, deDEStrings, LatinFonts, deDELayouts }, #endif #ifdef LANGUAGE_DE_CH - {L"00000807", L"1252", L"850", L"10000", L"German (Switzerland)", L"41", deDEPages, deDEErrorEntries, deDEStrings, LatinFonts, deCHLayouts }, + {L"00000807", L"1252", L"850", L"10000", L"German (Switzerland)", L"41", deDEPages, deDEErrorEntries, deDEStrings, LatinFonts, deCHLayouts }, #endif #ifdef LANGUAGE_DE_AT - {L"00000C07", L"1252", L"850", L"10000", L"German (Austria)", L"43", deDEPages, deDEErrorEntries, deDEStrings, LatinFonts, deATLayouts }, + {L"00000C07", L"1252", L"850", L"10000", L"German (Austria)", L"43", deDEPages, deDEErrorEntries, deDEStrings, LatinFonts, deATLayouts }, #endif #ifdef LANGUAGE_DE_LU - {L"00001007", L"1252", L"850", L"10000", L"German (Luxembourg)", L"352", deDEPages, deDEErrorEntries, deDEStrings, LatinFonts, deLULayouts }, + {L"00001007", L"1252", L"850", L"10000", L"German (Luxembourg)", L"352", deDEPages, deDEErrorEntries, deDEStrings, LatinFonts, deLULayouts }, #endif #ifdef LANGUAGE_DE_LI - {L"00001407", L"1252", L"850", L"10000", L"German (Liechtenstein)", L"423", deDEPages, deDEErrorEntries, deDEStrings, LatinFonts, deLILayouts }, + {L"00001407", L"1252", L"850", L"10000", L"German (Liechtenstein)", L"423", deDEPages, deDEErrorEntries, deDEStrings, LatinFonts, deLILayouts }, #endif #ifdef LANGUAGE_EL_GR - {L"00000408", L"1253", L"737", L"10006", L"Greek", L"30", elGRPages, elGRErrorEntries, elGRStrings, GreekFonts, elGRLayouts }, + {L"00000408", L"1253", L"737", L"10006", L"Greek", L"30", elGRPages, elGRErrorEntries, elGRStrings, GreekFonts, elGRLayouts }, #endif #ifdef LANGUAGE_GU_IN - {L"00000447", L"0", L"1", L"2", L"Gujarati (India)", L"91", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, guINLayouts }, + {L"00000447", L"0", L"1", L"2", L"Gujarati (India)", L"91", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, guINLayouts }, #endif #ifdef LANGUAGE_HE_IL - {L"0000040D", L"1255", L"862", L"10005", L"Hebrew", L"1", heILPages, heILErrorEntries, heILStrings, HebrewFonts, heILLayouts }, + {L"0000040D", L"1255", L"862", L"10005", L"Hebrew", L"1", heILPages, heILErrorEntries, heILStrings, HebrewFonts, heILLayouts }, #endif #ifdef LANGUAGE_HI_IN - {L"00000439", L"1252", L"437", L"10000", L"Hindi", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, hiINLayouts }, + {L"00000439", L"1252", L"437", L"10000", L"Hindi", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, hiINLayouts }, #endif #ifdef LANGUAGE_HU_HU - {L"0000040E", L"1250", L"852", L"10029", L"Hungarian", L"36", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, huHULayouts }, + {L"0000040E", L"1250", L"852", L"10029", L"Hungarian", L"36", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, huHULayouts }, #endif #ifdef LANGUAGE_IS_IS - {L"0000040F", L"1252", L"850", L"10079", L"Icelandic", L"354", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, isISLayouts }, + {L"0000040F", L"1252", L"850", L"10079", L"Icelandic", L"354", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, isISLayouts }, #endif #ifdef LANGUAGE_ID_ID - {L"00000421", L"1252", L"850", L"10079", L"Indonesian", L"62", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, idIDLayouts }, + {L"00000421", L"1252", L"850", L"10079", L"Indonesian", L"62", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, idIDLayouts }, #endif #ifdef LANGUAGE_IT_IT - {L"00000410", L"1252", L"850", L"10000", L"Italian (Italy)", L"39", itITPages, itITErrorEntries, itITStrings, LatinFonts, itITLayouts }, + {L"00000410", L"1252", L"850", L"10000", L"Italian (Italy)", L"39", itITPages, itITErrorEntries, itITStrings, LatinFonts, itITLayouts }, #endif #ifdef LANGUAGE_IT_CH - {L"00000810", L"1252", L"850", L"10000", L"Italian (Switzerland)", L"41", itITPages, itITErrorEntries, itITStrings, LatinFonts, itCHLayouts }, + {L"00000810", L"1252", L"850", L"10000", L"Italian (Switzerland)", L"41", itITPages, itITErrorEntries, itITStrings, LatinFonts, itCHLayouts }, #endif #ifdef LANGUAGE_JA_JP - {L"00000411", L"932", L"932", L"10001", L"Japanese", L"81", jaJPPages, jaJPErrorEntries, jaJPStrings, CJKFonts, jaJPLayouts }, + {L"00000411", L"932", L"932", L"10001", L"Japanese", L"81", jaJPPages, jaJPErrorEntries, jaJPStrings, CJKFonts, jaJPLayouts }, #endif #ifdef LANGUAGE_KN_IN - {L"0000044B", L"1252", L"437", L"10079", L"Kannada (India)", L"91", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, knINLayouts }, + {L"0000044B", L"1252", L"437", L"10079", L"Kannada (India)", L"91", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, knINLayouts }, #endif #ifdef LANGUAGE_KK_KZ - {L"0000043F", L"1251", L"866", L"10007", L"Kazakh", L"705", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, kkKZLayouts }, + {L"0000043F", L"1251", L"866", L"10007", L"Kazakh", L"705", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, kkKZLayouts }, #endif #ifdef LANGUAGE_KOK_IN - {L"00000457", L"0", L"437", L"2", L"Konkani", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, kokINLayouts}, + {L"00000457", L"0", L"437", L"2", L"Konkani", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, kokINLayouts}, #endif #ifdef LANGUAGE_KO_KR - {L"00000412", L"949", L"949", L"10003", L"Korean", L"1", enUSPages, enUSErrorEntries, enUSStrings, CJKFonts, koKRLayouts }, + {L"00000412", L"949", L"949", L"10003", L"Korean", L"1", enUSPages, enUSErrorEntries, enUSStrings, CJKFonts, koKRLayouts }, #endif #ifdef LANGUAGE_KY_KG - {L"00000440", L"1251", L"866", L"10007", L"Kyrgyz (Kyrgyzstan)", L"1", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, kyKGLayouts }, + {L"00000440", L"1251", L"866", L"10007", L"Kyrgyz (Kyrgyzstan)", L"1", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, kyKGLayouts }, #endif #ifdef LANGUAGE_LV_LV - {L"00000426", L"1257", L"775", L"10029", L"Latvian", L"371", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, lvLVLayouts }, + {L"00000426", L"1257", L"775", L"10029", L"Latvian", L"371", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, lvLVLayouts }, #endif #ifdef LANGUAGE_LT_LT - {L"00000427", L"1257", L"775", L"10029", L"Lithuanian", L"370", ltLTPages, ltLTErrorEntries, ltLTStrings, LatinFonts, ltLTLayouts }, + {L"00000427", L"1257", L"775", L"10029", L"Lithuanian", L"370", ltLTPages, ltLTErrorEntries, ltLTStrings, LatinFonts, ltLTLayouts }, #endif #ifdef LANGUAGE_MK_MK - {L"0000042F", L"1251", L"866", L"10007", L"FYRO Macedonian", L"1", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, mkMKLayouts }, + {L"0000042F", L"1251", L"866", L"10007", L"FYRO Macedonian", L"1", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, mkMKLayouts }, #endif #ifdef LANGUAGE_MS_BN - {L"0000083E", L"1252", L"850", L"10000", L"Malay (Brunei Darussalam)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, msBNLayouts }, + {L"0000083E", L"1252", L"850", L"10000", L"Malay (Brunei Darussalam)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, msBNLayouts }, #endif #ifdef LANGUAGE_MS_MY - {L"0000043E", L"1252", L"850", L"10000", L"Malay (Malaysia)", L"60", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, msMYLayouts }, + {L"0000043E", L"1252", L"850", L"10000", L"Malay (Malaysia)", L"60", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, msMYLayouts }, #endif #ifdef LANGUAGE_MR_IN - {L"0000044E", L"0", L"1", L"2", L"Marathi", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, mrINLayouts }, + {L"0000044E", L"0", L"1", L"2", L"Marathi", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, mrINLayouts }, #endif #ifdef LANGUAGE_MN_MN - {L"00000450", L"1251", L"866", L"10007", L"Mongolian (Mongolia)", L"976", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, mnMNLayouts }, + {L"00000450", L"1251", L"866", L"10007", L"Mongolian (Mongolia)", L"976", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, mnMNLayouts }, #endif #ifdef LANGUAGE_NB_NO - {L"00000414", L"1252", L"850", L"10000", L"Norwegian (Bokmal)", L"47", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, nbNOLayouts }, + {L"00000414", L"1252", L"850", L"10000", L"Norwegian (Bokmal)", L"47", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, nbNOLayouts }, #endif #ifdef LANGUAGE_NN_NO - {L"00000814", L"1252", L"850", L"10000", L"Norwegian (Nynorsk)", L"47", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, nnNOLayouts }, + {L"00000814", L"1252", L"850", L"10000", L"Norwegian (Nynorsk)", L"47", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, nnNOLayouts }, #endif #ifdef LANGUAGE_PL_PL - {L"00000415", L"1250", L"852", L"10029", L"Polish", L"48", plPLPages, plPLErrorEntries, plPLStrings, LatinFonts, plPLLayouts }, + {L"00000415", L"1250", L"852", L"10029", L"Polish", L"48", plPLPages, plPLErrorEntries, plPLStrings, LatinFonts, plPLLayouts }, #endif #ifdef LANGUAGE_PT_PT - {L"00000816", L"1252", L"850", L"10000", L"Portuguese (Portugal)", L"351", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, ptPTLayouts }, + {L"00000816", L"1252", L"850", L"10000", L"Portuguese (Portugal)", L"351", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, ptPTLayouts }, #endif #ifdef LANGUAGE_PT_BR - {L"00000416", L"1252", L"850", L"10000", L"Portuguese (Brazil)", L"55", ptBRPages, ptBRErrorEntries, ptBRStrings, LatinFonts, ptBRLayouts }, + {L"00000416", L"1252", L"850", L"10000", L"Portuguese (Brazil)", L"55", ptBRPages, ptBRErrorEntries, ptBRStrings, LatinFonts, ptBRLayouts }, #endif #ifdef LANGUAGE_PA_IN - {L"00000446", L"0", L"1", L"2", L"Punjabi (India)", L"91", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, paINLayouts }, + {L"00000446", L"0", L"1", L"2", L"Punjabi (India)", L"91", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, paINLayouts }, #endif #ifdef LANGUAGE_RO_RO - {L"00000418", L"1250", L"852", L"10029", L"Romanian", L"40", roROPages, roROErrorEntries, roROStrings, LatinFonts, roROLayouts }, + {L"00000418", L"1250", L"852", L"10029", L"Romanian", L"40", roROPages, roROErrorEntries, roROStrings, LatinFonts, roROLayouts }, #endif #ifdef LANGUAGE_RM_CH - {L"00000417", L"1252", L"850", L"10000", L"Romansh", L"41", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, rmCHLayouts }, + {L"00000417", L"1252", L"850", L"10000", L"Romansh", L"41", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, rmCHLayouts }, #endif #ifdef LANGUAGE_RU_RU - {L"00000419", L"1251", L"866", L"10007", L"Russian", L"7", ruRUPages, ruRUErrorEntries, ruRUStrings, CyrillicFonts, ruRULayouts }, + {L"00000419", L"1251", L"866", L"10007", L"Russian", L"7", ruRUPages, ruRUErrorEntries, ruRUStrings, CyrillicFonts, ruRULayouts }, #endif #ifdef LANGUAGE_SA_IN - {L"0000044F", L"0", L"1", L"2", L"Sanskrit", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, saINLayouts }, + {L"0000044F", L"0", L"1", L"2", L"Sanskrit", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, saINLayouts }, #endif #ifdef LANGUAGE_SR_SP - {L"00000C1A", L"1251", L"855", L"10007", L"Serbian (Cyrillic)", L"1", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, srSPLayouts }, + {L"00000C1A", L"1251", L"855", L"10007", L"Serbian (Cyrillic)", L"1", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, srSPLayouts }, #endif #ifdef LANGUAGE_SR_SP - {L"0000081A", L"1250", L"852", L"10029", L"Serbian (Latin)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, srSPLayouts }, + {L"0000081A", L"1250", L"852", L"10029", L"Serbian (Latin)", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, srSPLayouts }, #endif #ifdef LANGUAGE_SK_SK - {L"0000041B", L"1250", L"852", L"10029", L"Slovak", L"421", skSKPages, skSKErrorEntries, skSKStrings, LatinFonts, skSKLayouts }, + {L"0000041B", L"1250", L"852", L"10029", L"Slovak", L"421", skSKPages, skSKErrorEntries, skSKStrings, LatinFonts, skSKLayouts }, #endif #ifdef LANGUAGE_SL_SI - {L"00000424", L"1250", L"852", L"10029", L"Slovenian", L"386", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, slSILayouts }, + {L"00000424", L"1250", L"852", L"10029", L"Slovenian", L"386", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, slSILayouts }, #endif #ifdef LANGUAGE_ES_ES - {L"0000040A", L"1252", L"850", L"10000", L"Spanish (Traditional Sort)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esESLayouts }, + {L"0000040A", L"1252", L"850", L"10000", L"Spanish (Traditional Sort)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esESLayouts }, #endif #ifdef LANGUAGE_ES_MX - {L"0000080A", L"1252", L"850", L"10000", L"Spanish (Mexico)", L"52", esESPages, esESErrorEntries, esESStrings, LatinFonts, esMXLayouts }, + {L"0000080A", L"1252", L"850", L"10000", L"Spanish (Mexico)", L"52", esESPages, esESErrorEntries, esESStrings, LatinFonts, esMXLayouts }, #endif #ifdef LANGUAGE_ES_ES - {L"00000C0A", L"1252", L"850", L"10000", L"Spanish (International Sort)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esESLayouts }, + {L"00000C0A", L"1252", L"850", L"10000", L"Spanish (International Sort)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esESLayouts }, #endif #ifdef LANGUAGE_ES_GT - {L"0000100A", L"1252", L"850", L"10000", L"Spanish (Guatemala)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esGTLayouts }, + {L"0000100A", L"1252", L"850", L"10000", L"Spanish (Guatemala)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esGTLayouts }, #endif #ifdef LANGUAGE_ES_CR - {L"0000140A", L"1252", L"850", L"10000", L"Spanish (Costa Rica)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esCRLayouts }, + {L"0000140A", L"1252", L"850", L"10000", L"Spanish (Costa Rica)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esCRLayouts }, #endif #ifdef LANGUAGE_ES_PA - {L"0000180A", L"1252", L"850", L"10000", L"Spanish (Panama)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esPALayouts }, + {L"0000180A", L"1252", L"850", L"10000", L"Spanish (Panama)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esPALayouts }, #endif #ifdef LANGUAGE_ES_DO - {L"00001C0A", L"1252", L"850", L"10000", L"Spanish (Dominican Republic)", L"110", esESPages, esESErrorEntries, esESStrings, LatinFonts, esDOLayouts }, + {L"00001C0A", L"1252", L"850", L"10000", L"Spanish (Dominican Republic)", L"110", esESPages, esESErrorEntries, esESStrings, LatinFonts, esDOLayouts }, #endif #ifdef LANGUAGE_ES_VE - {L"0000200A", L"1252", L"850", L"10000", L"Spanish (Venezuela)", L"58", esESPages, esESErrorEntries, esESStrings, LatinFonts, esVELayouts }, + {L"0000200A", L"1252", L"850", L"10000", L"Spanish (Venezuela)", L"58", esESPages, esESErrorEntries, esESStrings, LatinFonts, esVELayouts }, #endif #ifdef LANGUAGE_ES_CO - {L"0000240A", L"1252", L"850", L"10000", L"Spanish (Colombia)", L"57", esESPages, esESErrorEntries, esESStrings, LatinFonts, esCOLayouts }, + {L"0000240A", L"1252", L"850", L"10000", L"Spanish (Colombia)", L"57", esESPages, esESErrorEntries, esESStrings, LatinFonts, esCOLayouts }, #endif #ifdef LANGUAGE_ES_PE - {L"0000280A", L"1252", L"850", L"10000", L"Spanish (Peru)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esPELayouts }, + {L"0000280A", L"1252", L"850", L"10000", L"Spanish (Peru)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esPELayouts }, #endif #ifdef LANGUAGE_ES_AR - {L"00002C0A", L"1252", L"850", L"10000", L"Spanish (Argentina)", L"54", esESPages, esESErrorEntries, esESStrings, LatinFonts, esARLayouts }, + {L"00002C0A", L"1252", L"850", L"10000", L"Spanish (Argentina)", L"54", esESPages, esESErrorEntries, esESStrings, LatinFonts, esARLayouts }, #endif #ifdef LANGUAGE_ES_EC - {L"0000300A", L"1252", L"850", L"10000", L"Spanish (Ecuador)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esECLayouts }, + {L"0000300A", L"1252", L"850", L"10000", L"Spanish (Ecuador)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esECLayouts }, #endif #ifdef LANGUAGE_ES_CL - {L"0000340A", L"1252", L"850", L"10000", L"Spanish (Chile)", L"56", esESPages, esESErrorEntries, esESStrings, LatinFonts, esCLLayouts }, + {L"0000340A", L"1252", L"850", L"10000", L"Spanish (Chile)", L"56", esESPages, esESErrorEntries, esESStrings, LatinFonts, esCLLayouts }, #endif #ifdef LANGUAGE_ES_UY - {L"0000380A", L"1252", L"850", L"10000", L"Spanish (Uruguay)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esUYLayouts }, + {L"0000380A", L"1252", L"850", L"10000", L"Spanish (Uruguay)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esUYLayouts }, #endif #ifdef LANGUAGE_ES_PY - {L"00003C0A", L"1252", L"850", L"10000", L"Spanish (Paraguay)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esPYLayouts }, + {L"00003C0A", L"1252", L"850", L"10000", L"Spanish (Paraguay)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esPYLayouts }, #endif #ifdef LANGUAGE_ES_BO - {L"0000400A", L"1252", L"850", L"10000", L"Spanish (Bolivia)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esBOLayouts }, + {L"0000400A", L"1252", L"850", L"10000", L"Spanish (Bolivia)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esBOLayouts }, #endif #ifdef LANGUAGE_ES_SV - {L"0000440A", L"1252", L"850", L"10000", L"Spanish (El Salvador)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esSVLayouts }, + {L"0000440A", L"1252", L"850", L"10000", L"Spanish (El Salvador)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esSVLayouts }, #endif #ifdef LANGUAGE_ES_HN - {L"0000480A", L"1252", L"850", L"10000", L"Spanish (Honduras)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esHNLayouts }, + {L"0000480A", L"1252", L"850", L"10000", L"Spanish (Honduras)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esHNLayouts }, #endif #ifdef LANGUAGE_ES_NI - {L"00004C0A", L"1252", L"850", L"10000", L"Spanish (Nicaragua)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esNILayouts }, + {L"00004C0A", L"1252", L"850", L"10000", L"Spanish (Nicaragua)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esNILayouts }, #endif #ifdef LANGUAGE_ES_PR - {L"0000500A", L"1252", L"850", L"10000", L"Spanish (Puerto Rico)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esPRLayouts }, + {L"0000500A", L"1252", L"850", L"10000", L"Spanish (Puerto Rico)", L"1", esESPages, esESErrorEntries, esESStrings, LatinFonts, esPRLayouts }, #endif #ifdef LANGUAGE_SW_KE - {L"00000441", L"1252", L"437", L"10000", L"Swahili", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, swKELayouts }, + {L"00000441", L"1252", L"437", L"10000", L"Swahili", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, swKELayouts }, #endif #ifdef LANGUAGE_SV_SE - {L"0000041D", L"1252", L"850", L"10000", L"Swedish", L"46", svSEPages, svSEErrorEntries, svSEStrings, LatinFonts, svSELayouts }, + {L"0000041D", L"1252", L"850", L"10000", L"Swedish", L"46", svSEPages, svSEErrorEntries, svSEStrings, LatinFonts, svSELayouts }, #endif #ifdef LANGUAGE_SV_FI - {L"0000081D", L"1252", L"850", L"10000", L"Swedish (Finland)", L"358", svSEPages, svSEErrorEntries, svSEStrings, LatinFonts, svFILayouts }, + {L"0000081D", L"1252", L"850", L"10000", L"Swedish (Finland)", L"358", svSEPages, svSEErrorEntries, svSEStrings, LatinFonts, svFILayouts }, #endif #ifdef LANGUAGE_SYR_SY - {L"0000045A", L"0", L"1", L"2", L"Syriac (Syria)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, syrSYLayouts}, + {L"0000045A", L"0", L"1", L"2", L"Syriac (Syria)", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, syrSYLayouts}, #endif #ifdef LANGUAGE_TA_IN - {L"00000449", L"0", L"1", L"2", L"Tamil", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, taINLayouts }, + {L"00000449", L"0", L"1", L"2", L"Tamil", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, taINLayouts }, #endif #ifdef LANGUAGE_TT_TA - {L"00000444", L"1251", L"866", L"10007", L"Tatar", L"1", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, ttTALayouts }, + {L"00000444", L"1251", L"866", L"10007", L"Tatar", L"1", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, ttTALayouts }, #endif #ifdef LANGUAGE_TE_IN - {L"0000044A", L"0", L"1", L"2", L"Telugu (India)", L"91", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, teINLayouts }, + {L"0000044A", L"0", L"1", L"2", L"Telugu (India)", L"91", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, teINLayouts }, #endif #ifdef LANGUAGE_TH_TH - {L"0000041E", L"874", L"874", L"10021", L"Thai", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, thTHLayouts }, + {L"0000041E", L"874", L"874", L"10021", L"Thai", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, thTHLayouts }, #endif #ifdef LANGUAGE_TR_TR - {L"0000041F", L"1254", L"857", L"10081", L"Turkish", L"90", trTRPages, trTRErrorEntries, trTRStrings, LatinFonts, trTRLayouts }, + {L"0000041F", L"1254", L"857", L"10081", L"Turkish", L"90", trTRPages, trTRErrorEntries, trTRStrings, LatinFonts, trTRLayouts }, #endif #ifdef LANGUAGE_UK_UA - {L"00000422", L"1251", L"866", L"10017", L"Ukrainian", L"380", ukUAPages, ukUAErrorEntries, ukUAStrings, CyrillicFonts, ukUALayouts }, + {L"00000422", L"1251", L"866", L"10017", L"Ukrainian", L"380", ukUAPages, ukUAErrorEntries, ukUAStrings, CyrillicFonts, ukUALayouts }, #endif #ifdef LANGUAGE_UR_PK - {L"00000420", L"1256", L"720", L"10004", L"Urdu", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, urPKLayouts }, + {L"00000420", L"1256", L"720", L"10004", L"Urdu", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, urPKLayouts }, #endif #ifdef LANGUAGE_UZ_UZ - {L"00000443", L"1254", L"857", L"10029", L"Uzbek (Latin)", L"998", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, uzUZLayouts }, + {L"00000443", L"1254", L"857", L"10029", L"Uzbek (Latin)", L"998", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, uzUZLayouts }, #endif #ifdef LANGUAGE_UZ_UZ - {L"00000843", L"1251", L"866", L"10007", L"Uzbek (Cyrillic)", L"998", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, uzUZLayouts }, + {L"00000843", L"1251", L"866", L"10007", L"Uzbek (Cyrillic)", L"998", enUSPages, enUSErrorEntries, enUSStrings, CyrillicFonts, uzUZLayouts }, #endif #ifdef LANGUAGE_VI_VN - {L"0000042A", L"1258", L"1258",L"10000", L"Vietnamese", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, viVNLayouts }, + {L"0000042A", L"1258", L"1258",L"10000", L"Vietnamese", L"1", enUSPages, enUSErrorEntries, enUSStrings, UnicodeFonts, viVNLayouts }, #endif #ifdef LANGUAGE_WA_BE - {L"00000490", L"1252", L"850", L"10000", L"Walon", L"32", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, waBELayouts }, + {L"00000490", L"1252", L"850", L"10000", L"Walon", L"32", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, waBELayouts }, #endif #ifdef LANGUAGE_ZU_ZU - {L"00000435", L"1252", L"850", L"10000", L"Zulu", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, zuZULayouts }, + {L"00000435", L"1252", L"850", L"10000", L"Zulu", L"1", enUSPages, enUSErrorEntries, enUSStrings, LatinFonts, zuZULayouts }, #endif - {NULL, NULL, NULL, NULL, NULL, NULL} + {NULL, NULL, NULL, NULL, NULL, NULL} }; diff --git a/base/setup/usetup/progress.c b/base/setup/usetup/progress.c index 55433819877..d41c9f07a2b 100644 --- a/base/setup/usetup/progress.c +++ b/base/setup/usetup/progress.c @@ -9,362 +9,372 @@ /* FUNCTIONS ****************************************************************/ -static VOID -DrawBorder(PPROGRESSBAR Bar) +static +VOID +DrawBorder( + PPROGRESSBAR Bar) { - COORD coPos; - DWORD Written; - SHORT i; + COORD coPos; + DWORD Written; + SHORT i; - /* draw upper left corner */ - coPos.X = Bar->Left; - coPos.Y = Bar->Top + 1; - FillConsoleOutputCharacterA(StdOutput, - 0xDA, // '+', - 1, - coPos, - &Written); + /* draw upper left corner */ + coPos.X = Bar->Left; + coPos.Y = Bar->Top + 1; + FillConsoleOutputCharacterA(StdOutput, + 0xDA, // '+', + 1, + coPos, + &Written); - /* draw upper edge */ - coPos.X = Bar->Left + 1; - coPos.Y = Bar->Top + 1; - FillConsoleOutputCharacterA(StdOutput, - 0xC4, // '-', - Bar->Right - Bar->Left - 1, - coPos, - &Written); + /* draw upper edge */ + coPos.X = Bar->Left + 1; + coPos.Y = Bar->Top + 1; + FillConsoleOutputCharacterA(StdOutput, + 0xC4, // '-', + Bar->Right - Bar->Left - 1, + coPos, + &Written); - /* draw upper right corner */ - coPos.X = Bar->Right; - coPos.Y = Bar->Top + 1; - FillConsoleOutputCharacterA(StdOutput, - 0xBF, // '+', - 1, - coPos, - &Written); + /* draw upper right corner */ + coPos.X = Bar->Right; + coPos.Y = Bar->Top + 1; + FillConsoleOutputCharacterA(StdOutput, + 0xBF, // '+', + 1, + coPos, + &Written); - /* draw left and right edge */ - for (i = Bar->Top + 2; i < Bar->Bottom; i++) + /* draw left and right edge */ + for (i = Bar->Top + 2; i < Bar->Bottom; i++) { - coPos.X = Bar->Left; - coPos.Y = i; - FillConsoleOutputCharacterA(StdOutput, - 0xB3, // '|', - 1, - coPos, - &Written); + coPos.X = Bar->Left; + coPos.Y = i; + FillConsoleOutputCharacterA(StdOutput, + 0xB3, // '|', + 1, + coPos, + &Written); - coPos.X = Bar->Right; - FillConsoleOutputCharacterA(StdOutput, - 0xB3, //'|', - 1, - coPos, - &Written); + coPos.X = Bar->Right; + FillConsoleOutputCharacterA(StdOutput, + 0xB3, //'|', + 1, + coPos, + &Written); } - /* draw lower left corner */ - coPos.X = Bar->Left; - coPos.Y = Bar->Bottom; - FillConsoleOutputCharacterA(StdOutput, - 0xC0, // '+', - 1, - coPos, - &Written); + /* draw lower left corner */ + coPos.X = Bar->Left; + coPos.Y = Bar->Bottom; + FillConsoleOutputCharacterA(StdOutput, + 0xC0, // '+', + 1, + coPos, + &Written); - /* draw lower edge */ - coPos.X = Bar->Left + 1; - coPos.Y = Bar->Bottom; - FillConsoleOutputCharacterA(StdOutput, - 0xC4, // '-', - Bar->Right - Bar->Left - 1, - coPos, - &Written); + /* draw lower edge */ + coPos.X = Bar->Left + 1; + coPos.Y = Bar->Bottom; + FillConsoleOutputCharacterA(StdOutput, + 0xC4, // '-', + Bar->Right - Bar->Left - 1, + coPos, + &Written); - /* draw lower right corner */ - coPos.X = Bar->Right; - coPos.Y = Bar->Bottom; - FillConsoleOutputCharacterA(StdOutput, - 0xD9, // '+', - 1, - coPos, - &Written); + /* draw lower right corner */ + coPos.X = Bar->Right; + coPos.Y = Bar->Bottom; + FillConsoleOutputCharacterA(StdOutput, + 0xD9, // '+', + 1, + coPos, + &Written); } -static VOID -DrawThickBorder(PPROGRESSBAR Bar) + +static +VOID +DrawThickBorder( + PPROGRESSBAR Bar) { - COORD coPos; - DWORD Written; - SHORT i; + COORD coPos; + DWORD Written; + SHORT i; - /* draw upper left corner */ - coPos.X = Bar->Left; - coPos.Y = Bar->Top + 1; - FillConsoleOutputCharacterA(StdOutput, - 0xC9, // '+', - 1, - coPos, - &Written); + /* draw upper left corner */ + coPos.X = Bar->Left; + coPos.Y = Bar->Top + 1; + FillConsoleOutputCharacterA(StdOutput, + 0xC9, // '+', + 1, + coPos, + &Written); - /* draw upper edge */ - coPos.X = Bar->Left + 1; - coPos.Y = Bar->Top + 1; - FillConsoleOutputCharacterA(StdOutput, - 0xCD, // '-', - Bar->Right - Bar->Left - 1, - coPos, - &Written); + /* draw upper edge */ + coPos.X = Bar->Left + 1; + coPos.Y = Bar->Top + 1; + FillConsoleOutputCharacterA(StdOutput, + 0xCD, // '-', + Bar->Right - Bar->Left - 1, + coPos, + &Written); - /* draw upper right corner */ - coPos.X = Bar->Right; - coPos.Y = Bar->Top + 1; - FillConsoleOutputCharacterA(StdOutput, - 0xBB, // '+', - 1, - coPos, - &Written); + /* draw upper right corner */ + coPos.X = Bar->Right; + coPos.Y = Bar->Top + 1; + FillConsoleOutputCharacterA(StdOutput, + 0xBB, // '+', + 1, + coPos, + &Written); - /* draw left and right edge */ - for (i = Bar->Top + 2; i < Bar->Bottom; i++) + /* draw left and right edge */ + for (i = Bar->Top + 2; i < Bar->Bottom; i++) { - coPos.X = Bar->Left; - coPos.Y = i; - FillConsoleOutputCharacterA(StdOutput, - 0xBA, // '|', - 1, - coPos, - &Written); + coPos.X = Bar->Left; + coPos.Y = i; + FillConsoleOutputCharacterA(StdOutput, + 0xBA, // '|', + 1, + coPos, + &Written); - coPos.X = Bar->Right; - FillConsoleOutputCharacterA(StdOutput, - 0xBA, //'|', - 1, - coPos, - &Written); + coPos.X = Bar->Right; + FillConsoleOutputCharacterA(StdOutput, + 0xBA, //'|', + 1, + coPos, + &Written); } - /* draw lower left corner */ - coPos.X = Bar->Left; - coPos.Y = Bar->Bottom; - FillConsoleOutputCharacterA(StdOutput, - 0xC8, // '+', - 1, - coPos, - &Written); + /* draw lower left corner */ + coPos.X = Bar->Left; + coPos.Y = Bar->Bottom; + FillConsoleOutputCharacterA(StdOutput, + 0xC8, // '+', + 1, + coPos, + &Written); - /* draw lower edge */ - coPos.X = Bar->Left + 1; - coPos.Y = Bar->Bottom; - FillConsoleOutputCharacterA(StdOutput, - 0xCD, // '-', - Bar->Right - Bar->Left - 1, - coPos, - &Written); + /* draw lower edge */ + coPos.X = Bar->Left + 1; + coPos.Y = Bar->Bottom; + FillConsoleOutputCharacterA(StdOutput, + 0xCD, // '-', + Bar->Right - Bar->Left - 1, + coPos, + &Written); - /* draw lower right corner */ - coPos.X = Bar->Right; - coPos.Y = Bar->Bottom; - FillConsoleOutputCharacterA(StdOutput, - 0xBC, // '+', - 1, - coPos, - &Written); + /* draw lower right corner */ + coPos.X = Bar->Right; + coPos.Y = Bar->Bottom; + FillConsoleOutputCharacterA(StdOutput, + 0xBC, // '+', + 1, + coPos, + &Written); } -static VOID -DrawProgressBar(PPROGRESSBAR Bar) + +static +VOID +DrawProgressBar( + PPROGRESSBAR Bar) { - CHAR TextBuffer[8]; - COORD coPos; - DWORD Written; - PROGRESSBAR BarBorder = *Bar; + CHAR TextBuffer[8]; + COORD coPos; + DWORD Written; + PROGRESSBAR BarBorder = *Bar; - /* Print percentage */ - sprintf(TextBuffer, "%-3lu%%", Bar->Percent); + /* Print percentage */ + sprintf(TextBuffer, "%-3lu%%", Bar->Percent); - coPos.X = Bar->Left + (Bar->Width - 2) / 2; - coPos.Y = Bar->Top; - WriteConsoleOutputCharacterA(StdOutput, - TextBuffer, - 4, - coPos, - &Written); + coPos.X = Bar->Left + (Bar->Width - 2) / 2; + coPos.Y = Bar->Top; + WriteConsoleOutputCharacterA(StdOutput, + TextBuffer, + 4, + coPos, + &Written); - /* Draw the progress bar border */ - DrawBorder(Bar); + /* Draw the progress bar border */ + DrawBorder(Bar); - /* Write Text Associated with Bar */ - CONSOLE_SetTextXY(Bar->TextTop, Bar->TextRight, Bar->Text); + /* Write Text Associated with Bar */ + CONSOLE_SetTextXY(Bar->TextTop, Bar->TextRight, Bar->Text); - /* Draw the progress bar "border" border */ - if (Bar->Double) - { - BarBorder.Top -= 5; - BarBorder.Bottom += 2; - BarBorder.Right += 5; - BarBorder.Left -= 5; - DrawThickBorder(&BarBorder); - } - - /* Draw the bar */ - coPos.X = Bar->Left + 1; - for (coPos.Y = Bar->Top + 2; coPos.Y <= Bar->Bottom - 1; coPos.Y++) + /* Draw the progress bar "border" border */ + if (Bar->Double) { - FillConsoleOutputAttribute(StdOutput, - FOREGROUND_YELLOW | BACKGROUND_BLUE, - Bar->Width - 2, - coPos, - &Written); - - FillConsoleOutputCharacterA(StdOutput, - ' ', - Bar->Width - 2, - coPos, - &Written); + BarBorder.Top -= 5; + BarBorder.Bottom += 2; + BarBorder.Right += 5; + BarBorder.Left -= 5; + DrawThickBorder(&BarBorder); } -} + /* Draw the bar */ + coPos.X = Bar->Left + 1; + for (coPos.Y = Bar->Top + 2; coPos.Y <= Bar->Bottom - 1; coPos.Y++) + { + FillConsoleOutputAttribute(StdOutput, + FOREGROUND_YELLOW | BACKGROUND_BLUE, + Bar->Width - 2, + coPos, + &Written); + FillConsoleOutputCharacterA(StdOutput, + ' ', + Bar->Width - 2, + coPos, + &Written); + } +} PPROGRESSBAR -CreateProgressBar(SHORT Left, - SHORT Top, - SHORT Right, - SHORT Bottom, - SHORT TextTop, - SHORT TextRight, - IN BOOLEAN DoubleEdge, - char* Text) +CreateProgressBar( + SHORT Left, + SHORT Top, + SHORT Right, + SHORT Bottom, + SHORT TextTop, + SHORT TextRight, + IN BOOLEAN DoubleEdge, + CHAR *Text) { - PPROGRESSBAR Bar; + PPROGRESSBAR Bar; - Bar = (PPROGRESSBAR)RtlAllocateHeap(ProcessHeap, - 0, - sizeof(PROGRESSBAR)); - if (Bar == NULL) - return(NULL); + Bar = (PPROGRESSBAR)RtlAllocateHeap(ProcessHeap, + 0, + sizeof(PROGRESSBAR)); + if (Bar == NULL) + return NULL; - Bar->Left = Left; - Bar->Top = Top; - Bar->Right = Right; - Bar->Bottom = Bottom; - Bar->TextTop = TextTop; - Bar->TextRight = TextRight; - Bar->Double = DoubleEdge; - Bar->Text = Text; + Bar->Left = Left; + Bar->Top = Top; + Bar->Right = Right; + Bar->Bottom = Bottom; + Bar->TextTop = TextTop; + Bar->TextRight = TextRight; + Bar->Double = DoubleEdge; + Bar->Text = Text; - Bar->Width = Bar->Right - Bar->Left + 1; + Bar->Width = Bar->Right - Bar->Left + 1; - Bar->Percent = 0; - Bar->Pos = 0; + Bar->Percent = 0; + Bar->Pos = 0; - Bar->StepCount = 0; - Bar->CurrentStep = 0; + Bar->StepCount = 0; + Bar->CurrentStep = 0; - DrawProgressBar(Bar); + DrawProgressBar(Bar); - return(Bar); + return Bar; } VOID -DestroyProgressBar(PPROGRESSBAR Bar) +DestroyProgressBar( + PPROGRESSBAR Bar) { - RtlFreeHeap(ProcessHeap, - 0, - Bar); -} - -VOID -ProgressSetStepCount(PPROGRESSBAR Bar, - ULONG StepCount) -{ - Bar->CurrentStep = 0; - Bar->StepCount = StepCount; - - DrawProgressBar(Bar); + RtlFreeHeap(ProcessHeap, 0, Bar); } VOID -ProgressNextStep(PPROGRESSBAR Bar) +ProgressSetStepCount( + PPROGRESSBAR Bar, + ULONG StepCount) { - ProgressSetStep(Bar, Bar->CurrentStep + 1); + Bar->CurrentStep = 0; + Bar->StepCount = StepCount; + + DrawProgressBar(Bar); } VOID -ProgressSetStep (PPROGRESSBAR Bar, - ULONG Step) +ProgressNextStep( + PPROGRESSBAR Bar) { - CHAR TextBuffer[8]; - COORD coPos; - DWORD Written; - ULONG NewPercent; - ULONG NewPos; + ProgressSetStep(Bar, Bar->CurrentStep + 1); +} - if (Step > Bar->StepCount) - return; - Bar->CurrentStep = Step; +VOID +ProgressSetStep( + PPROGRESSBAR Bar, + ULONG Step) +{ + CHAR TextBuffer[8]; + COORD coPos; + DWORD Written; + ULONG NewPercent; + ULONG NewPos; - /* Calculate new percentage */ - NewPercent = (ULONG)(((100.0 * (float)Bar->CurrentStep) / (float)Bar->StepCount) + 0.5); + if (Step > Bar->StepCount) + return; - /* Redraw precentage if changed */ - if (Bar->Percent != NewPercent) + Bar->CurrentStep = Step; + + /* Calculate new percentage */ + NewPercent = (ULONG)(((100.0 * (float)Bar->CurrentStep) / (float)Bar->StepCount) + 0.5); + + /* Redraw precentage if changed */ + if (Bar->Percent != NewPercent) { - Bar->Percent = NewPercent; + Bar->Percent = NewPercent; - sprintf(TextBuffer, "%-3lu%%", Bar->Percent); + sprintf(TextBuffer, "%-3lu%%", Bar->Percent); - coPos.X = Bar->Left + (Bar->Width - 2) / 2; - coPos.Y = Bar->Top; - WriteConsoleOutputCharacterA(StdOutput, - TextBuffer, - 4, - coPos, - &Written); + coPos.X = Bar->Left + (Bar->Width - 2) / 2; + coPos.Y = Bar->Top; + WriteConsoleOutputCharacterA(StdOutput, + TextBuffer, + 4, + coPos, + &Written); } - /* Calculate bar position */ - NewPos = (ULONG)((((float)(Bar->Width - 2) * 2.0 * (float)Bar->CurrentStep) / (float)Bar->StepCount) + 0.5); + /* Calculate bar position */ + NewPos = (ULONG)((((float)(Bar->Width - 2) * 2.0 * (float)Bar->CurrentStep) / (float)Bar->StepCount) + 0.5); - /* Redraw bar if changed */ - if (Bar->Pos != NewPos) + /* Redraw bar if changed */ + if (Bar->Pos != NewPos) { - Bar->Pos = NewPos; + Bar->Pos = NewPos; - for (coPos.Y = Bar->Top + 2; coPos.Y <= Bar->Bottom - 1; coPos.Y++) - { - coPos.X = Bar->Left + 1; - FillConsoleOutputCharacterA(StdOutput, - 0xDB, - Bar->Pos / 2, - coPos, - &Written); - coPos.X += Bar->Pos/2; + for (coPos.Y = Bar->Top + 2; coPos.Y <= Bar->Bottom - 1; coPos.Y++) + { + coPos.X = Bar->Left + 1; + FillConsoleOutputCharacterA(StdOutput, + 0xDB, + Bar->Pos / 2, + coPos, + &Written); + coPos.X += Bar->Pos/2; - if (NewPos & 1) - { - FillConsoleOutputCharacterA(StdOutput, - 0xDD, - 1, - coPos, - &Written); - coPos.X++; - } + if (NewPos & 1) + { + FillConsoleOutputCharacterA(StdOutput, + 0xDD, + 1, + coPos, + &Written); + coPos.X++; + } - if (coPos.X <= Bar->Right - 1) - { - FillConsoleOutputCharacterA(StdOutput, - ' ', - Bar->Right - coPos.X, - coPos, - &Written); - } - } + if (coPos.X <= Bar->Right - 1) + { + FillConsoleOutputCharacterA(StdOutput, + ' ', + Bar->Right - coPos.X, + coPos, + &Written); + } + } } } diff --git a/base/setup/usetup/progress.h b/base/setup/usetup/progress.h index 948501c3d62..4e486048400 100644 --- a/base/setup/usetup/progress.h +++ b/base/setup/usetup/progress.h @@ -28,49 +28,54 @@ typedef struct _PROGRESS { - SHORT Left; - SHORT Top; - SHORT Right; - SHORT Bottom; - SHORT TextTop; - SHORT TextRight; + SHORT Left; + SHORT Top; + SHORT Right; + SHORT Bottom; + SHORT TextTop; + SHORT TextRight; - SHORT Width; + SHORT Width; - ULONG Percent; - SHORT Pos; + ULONG Percent; + SHORT Pos; - ULONG StepCount; - ULONG CurrentStep; + ULONG StepCount; + ULONG CurrentStep; - BOOLEAN Double; - CHAR *Text; + BOOLEAN Double; + CHAR *Text; } PROGRESSBAR, *PPROGRESSBAR; /* FUNCTIONS ****************************************************************/ PPROGRESSBAR -CreateProgressBar(SHORT Left, - SHORT Top, - SHORT Right, - SHORT Bottom, - SHORT TextTop, - SHORT TextRight, - BOOLEAN DoubleEdge, - char* Text); +CreateProgressBar( + SHORT Left, + SHORT Top, + SHORT Right, + SHORT Bottom, + SHORT TextTop, + SHORT TextRight, + BOOLEAN DoubleEdge, + CHAR *Text); VOID -DestroyProgressBar(PPROGRESSBAR Bar); +DestroyProgressBar( + PPROGRESSBAR Bar); VOID -ProgressSetStepCount(PPROGRESSBAR Bar, - ULONG StepCount); +ProgressSetStepCount( + PPROGRESSBAR Bar, + ULONG StepCount); VOID -ProgressNextStep(PPROGRESSBAR Bar); +ProgressNextStep( + PPROGRESSBAR Bar); VOID -ProgressSetStep (PPROGRESSBAR Bar, - ULONG Step); +ProgressSetStep( + PPROGRESSBAR Bar, + ULONG Step); /* EOF */ diff --git a/base/setup/usetup/registry.c b/base/setup/usetup/registry.c index 493a17a4a83..032c5d961b9 100644 --- a/base/setup/usetup/registry.c +++ b/base/setup/usetup/registry.c @@ -63,47 +63,49 @@ typedef struct _REG_DISK_MOUNT_INFO { - ULONG Signature; - LARGE_INTEGER StartingOffset; + ULONG Signature; + LARGE_INTEGER StartingOffset; } REG_DISK_MOUNT_INFO, *PREG_DISK_MOUNT_INFO; #include /* FUNCTIONS ****************************************************************/ -static BOOLEAN -GetRootKey (PWCHAR Name) +static +BOOLEAN +GetRootKey( + PWCHAR Name) { - if (!_wcsicmp (Name, L"HKCR")) + if (!_wcsicmp (Name, L"HKCR")) { - wcscpy (Name, L"\\Registry\\Machine\\SOFTWARE\\Classes\\"); - return TRUE; + wcscpy (Name, L"\\Registry\\Machine\\SOFTWARE\\Classes\\"); + return TRUE; } - if (!_wcsicmp (Name, L"HKCU")) + if (!_wcsicmp (Name, L"HKCU")) { - wcscpy (Name, L"\\Registry\\User\\.DEFAULT\\"); - return TRUE; + wcscpy (Name, L"\\Registry\\User\\.DEFAULT\\"); + return TRUE; } - if (!_wcsicmp (Name, L"HKLM")) + if (!_wcsicmp (Name, L"HKLM")) { - wcscpy (Name, L"\\Registry\\Machine\\"); - return TRUE; + wcscpy (Name, L"\\Registry\\Machine\\"); + return TRUE; } - if (!_wcsicmp (Name, L"HKU")) + if (!_wcsicmp (Name, L"HKU")) { - wcscpy (Name, L"\\Registry\\User\\"); - return TRUE; + wcscpy (Name, L"\\Registry\\User\\"); + return TRUE; } #if 0 - if (!_wcsicmp (Name, L"HKR")) - return FALSE; + if (!_wcsicmp (Name, L"HKR")) + return FALSE; #endif - return FALSE; + return FALSE; } @@ -500,7 +502,7 @@ CreateNestedKey (PHANDLE KeyHandle, * Called once for each AddReg and DelReg entry in a given section. */ static BOOLEAN -registry_callback (HINF hInf, PCWSTR Section, BOOLEAN Delete) +registry_callback(HINF hInf, PCWSTR Section, BOOLEAN Delete) { OBJECT_ATTRIBUTES ObjectAttributes; WCHAR Buffer[MAX_INF_STRING_LENGTH]; @@ -624,148 +626,154 @@ registry_callback (HINF hInf, PCWSTR Section, BOOLEAN Delete) BOOLEAN -ImportRegistryFile(PWSTR Filename, - PWSTR Section, - LCID LocaleId, - BOOLEAN Delete) +ImportRegistryFile( + PWSTR Filename, + PWSTR Section, + LCID LocaleId, + BOOLEAN Delete) { - WCHAR FileNameBuffer[MAX_PATH]; - HINF hInf; - UINT ErrorLine; + WCHAR FileNameBuffer[MAX_PATH]; + HINF hInf; + UINT ErrorLine; - /* Load inf file from install media. */ - wcscpy(FileNameBuffer, SourcePath.Buffer); - wcscat(FileNameBuffer, L"\\"); - wcscat(FileNameBuffer, Filename); + /* Load inf file from install media. */ + wcscpy(FileNameBuffer, SourcePath.Buffer); + wcscat(FileNameBuffer, L"\\"); + wcscat(FileNameBuffer, Filename); - hInf = SetupOpenInfFileW( - FileNameBuffer, - NULL, - INF_STYLE_WIN4, - LocaleId, - &ErrorLine); - if (hInf == INVALID_HANDLE_VALUE) + hInf = SetupOpenInfFileW(FileNameBuffer, + NULL, + INF_STYLE_WIN4, + LocaleId, + &ErrorLine); + if (hInf == INVALID_HANDLE_VALUE) { - DPRINT1("SetupOpenInfFile() failed\n"); - return FALSE; + DPRINT1("SetupOpenInfFile() failed\n"); + return FALSE; } - if (!registry_callback (hInf, L"AddReg", FALSE)) + if (!registry_callback(hInf, L"AddReg", FALSE)) { - DPRINT1("registry_callback() failed\n"); + DPRINT1("registry_callback() failed\n"); } - if (!registry_callback (hInf, L"AddReg.NT" Architecture, FALSE)) + if (!registry_callback(hInf, L"AddReg.NT" Architecture, FALSE)) { - DPRINT1("registry_callback() failed\n"); + DPRINT1("registry_callback() failed\n"); } - InfCloseFile (hInf); + InfCloseFile(hInf); - return TRUE; + return TRUE; } BOOLEAN -SetInstallPathValue(PUNICODE_STRING InstallPath) +SetInstallPathValue( + PUNICODE_STRING InstallPath) { - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\HARDWARE"); - UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"InstallPath"); - HANDLE KeyHandle; - NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\HARDWARE"); + UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"InstallPath"); + HANDLE KeyHandle; + NTSTATUS Status; - /* Create the 'secret' InstallPath key */ - InitializeObjectAttributes (&ObjectAttributes, - &KeyName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - Status = NtOpenKey (&KeyHandle, - KEY_ALL_ACCESS, - &ObjectAttributes); - if (!NT_SUCCESS(Status)) + /* Create the 'secret' InstallPath key */ + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = NtOpenKey(&KeyHandle, + KEY_ALL_ACCESS, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) { - DPRINT1("NtOpenKey() failed (Status %lx)\n", Status); - return FALSE; + DPRINT1("NtOpenKey() failed (Status %lx)\n", Status); + return FALSE; } - Status = NtSetValueKey (KeyHandle, - &ValueName, - 0, - REG_SZ, - (PVOID)InstallPath->Buffer, - InstallPath->Length + sizeof(WCHAR)); - NtClose(KeyHandle); - if (!NT_SUCCESS(Status)) - { - DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status); - return FALSE; - } - - return TRUE; -} - -BOOLEAN -SetMountedDeviceValue(CHAR Letter, ULONG Signature, LARGE_INTEGER StartingOffset) -{ - OBJECT_ATTRIBUTES ObjectAttributes; - WCHAR ValueNameBuffer[16]; - UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\MountedDevices"); - UNICODE_STRING ValueName; - REG_DISK_MOUNT_INFO MountInfo; - NTSTATUS Status; - HANDLE KeyHandle; - - swprintf(ValueNameBuffer, L"\\DosDevices\\%C:", Letter); - RtlInitUnicodeString(&ValueName, ValueNameBuffer); - - InitializeObjectAttributes (&ObjectAttributes, - &KeyName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - Status = NtOpenKey (&KeyHandle, - KEY_ALL_ACCESS, - &ObjectAttributes); - if (!NT_SUCCESS(Status)) - { - Status = NtCreateKey(&KeyHandle, - KEY_ALL_ACCESS, - &ObjectAttributes, + Status = NtSetValueKey(KeyHandle, + &ValueName, 0, - NULL, - REG_OPTION_NON_VOLATILE, - NULL); - } - - if (!NT_SUCCESS(Status)) + REG_SZ, + (PVOID)InstallPath->Buffer, + InstallPath->Length + sizeof(WCHAR)); + NtClose(KeyHandle); + if (!NT_SUCCESS(Status)) { - DPRINT1("NtCreateKey() failed (Status %lx)\n", Status); - return FALSE; + DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status); + return FALSE; } - MountInfo.Signature = Signature; - MountInfo.StartingOffset = StartingOffset; - Status = NtSetValueKey (KeyHandle, - &ValueName, - 0, - REG_BINARY, - (PVOID)&MountInfo, - sizeof(MountInfo)); - NtClose(KeyHandle); - if (!NT_SUCCESS(Status)) + return TRUE; +} + + +BOOLEAN +SetMountedDeviceValue( + CHAR Letter, + ULONG Signature, + LARGE_INTEGER StartingOffset) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + WCHAR ValueNameBuffer[16]; + UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\MountedDevices"); + UNICODE_STRING ValueName; + REG_DISK_MOUNT_INFO MountInfo; + NTSTATUS Status; + HANDLE KeyHandle; + + swprintf(ValueNameBuffer, L"\\DosDevices\\%C:", Letter); + RtlInitUnicodeString(&ValueName, ValueNameBuffer); + + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = NtOpenKey(&KeyHandle, + KEY_ALL_ACCESS, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) { - DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status); - return FALSE; + Status = NtCreateKey(&KeyHandle, + KEY_ALL_ACCESS, + &ObjectAttributes, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + NULL); } - return TRUE; + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtCreateKey() failed (Status %lx)\n", Status); + return FALSE; + } + + MountInfo.Signature = Signature; + MountInfo.StartingOffset = StartingOffset; + Status = NtSetValueKey(KeyHandle, + &ValueName, + 0, + REG_BINARY, + (PVOID)&MountInfo, + sizeof(MountInfo)); + NtClose(KeyHandle); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status); + return FALSE; + } + + return TRUE; } VOID -SetDefaultPagefile(WCHAR Drive) +SetDefaultPagefile( + WCHAR Drive) { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management"); diff --git a/base/setup/usetup/registry.h b/base/setup/usetup/registry.h index 2b23cd8d33d..de02b0eb5d8 100644 --- a/base/setup/usetup/registry.h +++ b/base/setup/usetup/registry.h @@ -27,18 +27,24 @@ #pragma once BOOLEAN -ImportRegistryFile(PWSTR Filename, - PWSTR Section, - LCID LocaleId, - BOOLEAN Delete); +ImportRegistryFile( + PWSTR Filename, + PWSTR Section, + LCID LocaleId, + BOOLEAN Delete); BOOLEAN -SetInstallPathValue(PUNICODE_STRING InstallPath); +SetInstallPathValue( + PUNICODE_STRING InstallPath); BOOLEAN -SetMountedDeviceValue(CHAR Letter, ULONG Signature, LARGE_INTEGER StartingOffset); +SetMountedDeviceValue( + CHAR Letter, + ULONG Signature, + LARGE_INTEGER StartingOffset); VOID -SetDefaultPagefile(WCHAR Drive); +SetDefaultPagefile( + WCHAR Drive); /* EOF */ diff --git a/base/setup/usetup/settings.c b/base/setup/usetup/settings.c index 7dcb3291da1..03461671742 100644 --- a/base/setup/usetup/settings.c +++ b/base/setup/usetup/settings.c @@ -31,34 +31,45 @@ #define NDEBUG #include +/* GLOBALS ******************************************************************/ + +ULONG DefaultLanguageIndex = 0; + /* FUNCTIONS ****************************************************************/ -static BOOLEAN +static +BOOLEAN IsAcpiComputer(VOID) { - UNICODE_STRING MultiKeyPathU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"); - UNICODE_STRING IdentifierU = RTL_CONSTANT_STRING(L"Identifier"); - UNICODE_STRING AcpiBiosIdentifier = RTL_CONSTANT_STRING(L"ACPI BIOS"); - OBJECT_ATTRIBUTES ObjectAttributes; - PKEY_BASIC_INFORMATION pDeviceInformation = NULL; - ULONG DeviceInfoLength = sizeof(KEY_BASIC_INFORMATION) + 50 * sizeof(WCHAR); - PKEY_VALUE_PARTIAL_INFORMATION pValueInformation = NULL; - ULONG ValueInfoLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 50 * sizeof(WCHAR); - ULONG RequiredSize; - ULONG IndexDevice = 0; - UNICODE_STRING DeviceName, ValueName; - HANDLE hDevicesKey = NULL; - HANDLE hDeviceKey = NULL; - NTSTATUS Status; - BOOLEAN ret = FALSE; + UNICODE_STRING MultiKeyPathU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"); + UNICODE_STRING IdentifierU = RTL_CONSTANT_STRING(L"Identifier"); + UNICODE_STRING AcpiBiosIdentifier = RTL_CONSTANT_STRING(L"ACPI BIOS"); + OBJECT_ATTRIBUTES ObjectAttributes; + PKEY_BASIC_INFORMATION pDeviceInformation = NULL; + ULONG DeviceInfoLength = sizeof(KEY_BASIC_INFORMATION) + 50 * sizeof(WCHAR); + PKEY_VALUE_PARTIAL_INFORMATION pValueInformation = NULL; + ULONG ValueInfoLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 50 * sizeof(WCHAR); + ULONG RequiredSize; + ULONG IndexDevice = 0; + UNICODE_STRING DeviceName, ValueName; + HANDLE hDevicesKey = NULL; + HANDLE hDeviceKey = NULL; + NTSTATUS Status; + BOOLEAN ret = FALSE; - InitializeObjectAttributes(&ObjectAttributes, &MultiKeyPathU, OBJ_CASE_INSENSITIVE, NULL, NULL); - Status = NtOpenKey(&hDevicesKey, KEY_ENUMERATE_SUB_KEYS, &ObjectAttributes); - if (!NT_SUCCESS(Status)) - { - DPRINT("NtOpenKey() failed with status 0x%08lx\n", Status); - goto cleanup; - } + InitializeObjectAttributes(&ObjectAttributes, + &MultiKeyPathU, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = NtOpenKey(&hDevicesKey, + KEY_ENUMERATE_SUB_KEYS, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtOpenKey() failed with status 0x%08lx\n", Status); + goto cleanup; + } pDeviceInformation = RtlAllocateHeap(RtlGetProcessHeap(), 0, DeviceInfoLength); if (!pDeviceInformation) @@ -170,9 +181,11 @@ cleanup: } -static BOOLEAN -GetComputerIdentifier(PWSTR Identifier, - ULONG IdentifierLength) +static +BOOLEAN +GetComputerIdentifier( + PWSTR Identifier, + ULONG IdentifierLength) { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING KeyName; @@ -212,14 +225,12 @@ GetComputerIdentifier(PWSTR Identifier, } /* Get number of subkeys */ - Status = NtQueryKey( - ProcessorsKey, - KeyFullInformation, - pFullInfo, - Size, - &Size); + Status = NtQueryKey(ProcessorsKey, + KeyFullInformation, + pFullInfo, + Size, + &Size); NtClose(ProcessorsKey); - if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) { DPRINT("NtQueryKey() failed (Status 0x%lx)\n", Status); @@ -276,7 +287,8 @@ GetComputerIdentifier(PWSTR Identifier, PGENERIC_LIST -CreateComputerTypeList(HINF InfFile) +CreateComputerTypeList( + HINF InfFile) { CHAR Buffer[128]; PGENERIC_LIST List; @@ -364,8 +376,10 @@ CreateComputerTypeList(HINF InfFile) } -static BOOLEAN -GetDisplayIdentifier(PWSTR Identifier, +static +BOOLEAN +GetDisplayIdentifier( + PWSTR Identifier, ULONG IdentifierLength) { OBJECT_ATTRIBUTES ObjectAttributes; @@ -530,7 +544,8 @@ GetDisplayIdentifier(PWSTR Identifier, PGENERIC_LIST -CreateDisplayDriverList(HINF InfFile) +CreateDisplayDriverList( + HINF InfFile) { CHAR Buffer[128]; PGENERIC_LIST List; @@ -630,8 +645,12 @@ CreateDisplayDriverList(HINF InfFile) return List; } + BOOLEAN -ProcessComputerFiles(HINF InfFile, PGENERIC_LIST List, PWCHAR* AdditionalSectionName) +ProcessComputerFiles( + HINF InfFile, + PGENERIC_LIST List, + PWCHAR *AdditionalSectionName) { PGENERIC_LIST_ENTRY Entry; static WCHAR SectionName[128]; @@ -654,7 +673,9 @@ ProcessComputerFiles(HINF InfFile, PGENERIC_LIST List, PWCHAR* AdditionalSection BOOLEAN -ProcessDisplayRegistry(HINF InfFile, PGENERIC_LIST List) +ProcessDisplayRegistry( + HINF InfFile, + PGENERIC_LIST List) { PGENERIC_LIST_ENTRY Entry; INFCONTEXT Context; @@ -692,12 +713,11 @@ ProcessDisplayRegistry(HINF InfFile, PGENERIC_LIST List) StartValue = 1; Status = RtlWriteRegistryValue(RTL_REGISTRY_SERVICES, - ServiceName, - L"Start", - REG_DWORD, - &StartValue, - sizeof(ULONG)); - + ServiceName, + L"Start", + REG_DWORD, + &StartValue, + sizeof(ULONG)); if (!NT_SUCCESS(Status)) { DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status); @@ -715,11 +735,11 @@ ProcessDisplayRegistry(HINF InfFile, PGENERIC_LIST List) Width = wcstoul(Buffer, NULL, 10); Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE, - RegPath, - L"DefaultSettings.XResolution", - REG_DWORD, - &Width, - sizeof(ULONG)); + RegPath, + L"DefaultSettings.XResolution", + REG_DWORD, + &Width, + sizeof(ULONG)); if (!NT_SUCCESS(Status)) { DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status); @@ -734,11 +754,11 @@ ProcessDisplayRegistry(HINF InfFile, PGENERIC_LIST List) Height = wcstoul(Buffer, 0, 0); Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE, - RegPath, - L"DefaultSettings.YResolution", - REG_DWORD, - &Height, - sizeof(ULONG)); + RegPath, + L"DefaultSettings.YResolution", + REG_DWORD, + &Height, + sizeof(ULONG)); if (!NT_SUCCESS(Status)) { DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status); @@ -753,11 +773,11 @@ ProcessDisplayRegistry(HINF InfFile, PGENERIC_LIST List) Bpp = wcstoul(Buffer, 0, 0); Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE, - RegPath, - L"DefaultSettings.BitsPerPel", - REG_DWORD, - &Bpp, - sizeof(ULONG)); + RegPath, + L"DefaultSettings.BitsPerPel", + REG_DWORD, + &Bpp, + sizeof(ULONG)); if (!NT_SUCCESS(Status)) { DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status); @@ -771,7 +791,8 @@ ProcessDisplayRegistry(HINF InfFile, PGENERIC_LIST List) BOOLEAN -ProcessLocaleRegistry(PGENERIC_LIST List) +ProcessLocaleRegistry( + PGENERIC_LIST List) { PGENERIC_LIST_ENTRY Entry; PWCHAR LanguageId; @@ -807,7 +828,6 @@ ProcessLocaleRegistry(PGENERIC_LIST List) Status = NtOpenKey(&KeyHandle, KEY_SET_VALUE, &ObjectAttributes); - if (!NT_SUCCESS(Status)) { DPRINT1("NtOpenKey() failed (Status %lx)\n", Status); @@ -851,7 +871,8 @@ ProcessLocaleRegistry(PGENERIC_LIST List) PGENERIC_LIST -CreateKeyboardDriverList(HINF InfFile) +CreateKeyboardDriverList( + HINF InfFile) { CHAR Buffer[128]; PGENERIC_LIST List; @@ -879,9 +900,9 @@ CreateKeyboardDriverList(HINF InfFile) break; } - UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap, - 0, - (wcslen(KeyName) + 1) * sizeof(WCHAR)); + UserData = (WCHAR*)RtlAllocateHeap(ProcessHeap, + 0, + (wcslen(KeyName) + 1) * sizeof(WCHAR)); if (UserData == NULL) { /* FIXME: Handle error! */ @@ -896,7 +917,6 @@ CreateKeyboardDriverList(HINF InfFile) return List; } -ULONG DefaultLanguageIndex = 0; ULONG GetDefaultLanguageIndex(VOID) @@ -904,8 +924,11 @@ GetDefaultLanguageIndex(VOID) return DefaultLanguageIndex; } + PGENERIC_LIST -CreateLanguageList(HINF InfFile, WCHAR * DefaultLanguage) +CreateLanguageList( + HINF InfFile, + WCHAR *DefaultLanguage) { CHAR Buffer[128]; PGENERIC_LIST List; @@ -980,8 +1003,11 @@ CreateLanguageList(HINF InfFile, WCHAR * DefaultLanguage) return List; } + PGENERIC_LIST -CreateKeyboardLayoutList(HINF InfFile, WCHAR * DefaultKBLayout) +CreateKeyboardLayoutList( + HINF InfFile, + WCHAR *DefaultKBLayout) { CHAR Buffer[128]; PGENERIC_LIST List; @@ -1028,10 +1054,9 @@ CreateKeyboardLayoutList(HINF InfFile, WCHAR * DefaultKBLayout) if (_wcsicmp(LayoutsList[uIndex].LayoutID, KeyName) == 0) { - UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap, - 0, - (wcslen(KeyName) + 1) * sizeof(WCHAR)); - + UserData = (WCHAR*)RtlAllocateHeap(ProcessHeap, + 0, + (wcslen(KeyName) + 1) * sizeof(WCHAR)); if (UserData == NULL) { /* FIXME: Handle error! */ @@ -1067,8 +1092,10 @@ CreateKeyboardLayoutList(HINF InfFile, WCHAR * DefaultKBLayout) return List; } + BOOLEAN -ProcessKeyboardLayoutRegistry(PGENERIC_LIST List) +ProcessKeyboardLayoutRegistry( + PGENERIC_LIST List) { PGENERIC_LIST_ENTRY Entry; PWCHAR LayoutId; @@ -1117,14 +1144,17 @@ ProcessKeyboardLayoutRegistry(PGENERIC_LIST List) #if 0 BOOLEAN -ProcessKeyboardLayoutFiles(PGENERIC_LIST List) +ProcessKeyboardLayoutFiles( + PGENERIC_LIST List) { return TRUE; } #endif + BOOLEAN -SetGeoID(PWCHAR Id) +SetGeoID( + PWCHAR Id) { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING KeyName; @@ -1133,6 +1163,7 @@ SetGeoID(PWCHAR Id) WCHAR szKeyName[] = L"\\Registry\\User\\.DEFAULT\\Control Panel\\International\\Geo"; WCHAR szValueName[] = L"Nation"; NTSTATUS Status; + RtlInitUnicodeString(&KeyName, szKeyName); InitializeObjectAttributes(&ObjectAttributes, @@ -1143,24 +1174,25 @@ SetGeoID(PWCHAR Id) Status = NtOpenKey(&KeyHandle, KEY_SET_VALUE, - &ObjectAttributes); + &ObjectAttributes); if(!NT_SUCCESS(Status)) { DPRINT1("NtOpenKey() failed (Status %lx)\n", Status); return FALSE; } + RtlInitUnicodeString(&ValueName, szValueName); Status = NtSetValueKey(KeyHandle, - &ValueName, - 0, - REG_SZ, - (PVOID)Id, - (wcslen(Id) + 1) * sizeof(WCHAR)); + &ValueName, + 0, + REG_SZ, + (PVOID)Id, + (wcslen(Id) + 1) * sizeof(WCHAR)); NtClose(KeyHandle); if (!NT_SUCCESS(Status)) { - DPRINT1("NtSetValueKey() failed (Status = %lx)\n", Status); - return FALSE; + DPRINT1("NtSetValueKey() failed (Status = %lx)\n", Status); + return FALSE; } return TRUE; diff --git a/base/setup/usetup/settings.h b/base/setup/usetup/settings.h index fb8cd3cdd1e..528247419b6 100644 --- a/base/setup/usetup/settings.h +++ b/base/setup/usetup/settings.h @@ -27,42 +27,55 @@ #pragma once PGENERIC_LIST -CreateComputerTypeList(HINF InfFile); +CreateComputerTypeList( + HINF InfFile); PGENERIC_LIST -CreateDisplayDriverList(HINF InfFile); +CreateDisplayDriverList( + HINF InfFile); BOOLEAN -ProcessComputerFiles(HINF InfFile, - PGENERIC_LIST List, - PWCHAR* AdditionalSectionName); +ProcessComputerFiles( + HINF InfFile, + PGENERIC_LIST List, + PWCHAR *AdditionalSectionName); BOOLEAN -ProcessDisplayRegistry(HINF InfFile, - PGENERIC_LIST List); +ProcessDisplayRegistry( + HINF InfFile, + PGENERIC_LIST List); PGENERIC_LIST -CreateKeyboardDriverList(HINF InfFile); +CreateKeyboardDriverList( + HINF InfFile); PGENERIC_LIST -CreateKeyboardLayoutList(HINF InfFile, WCHAR *DefaultKBLayout); +CreateKeyboardLayoutList( + HINF InfFile, + WCHAR *DefaultKBLayout); -PGENERIC_LIST -CreateLanguageList(HINF InfFile, WCHAR * DefaultLanguage); +PGENERIC_LIST +CreateLanguageList( + HINF InfFile, + WCHAR *DefaultLanguage); ULONG GetDefaultLanguageIndex(VOID); BOOLEAN -ProcessLocaleRegistry(PGENERIC_LIST List); +ProcessLocaleRegistry( + PGENERIC_LIST List); BOOLEAN -ProcessKeyboardLayoutRegistry(PGENERIC_LIST List); +ProcessKeyboardLayoutRegistry( + PGENERIC_LIST List); BOOLEAN -ProcessKeyboardLayoutFiles(PGENERIC_LIST List); +ProcessKeyboardLayoutFiles( + PGENERIC_LIST List); BOOLEAN -SetGeoID(PWCHAR Id); +SetGeoID( + PWCHAR Id); /* EOF */ diff --git a/base/setup/usetup/usetup.h b/base/setup/usetup/usetup.h index 2dfb99ba469..dd88ca8103b 100644 --- a/base/setup/usetup/usetup.h +++ b/base/setup/usetup/usetup.h @@ -113,43 +113,43 @@ extern BOOLEAN InfGetStringField(PINFCONTEXT Context, #define _PAGE_NUMBER_DEFINED typedef enum _PAGE_NUMBER { - START_PAGE, - LANGUAGE_PAGE, - INTRO_PAGE, - LICENSE_PAGE, - INSTALL_INTRO_PAGE, + START_PAGE, + LANGUAGE_PAGE, + INTRO_PAGE, + LICENSE_PAGE, + INSTALL_INTRO_PAGE, -// SCSI_CONTROLLER_PAGE, +// SCSI_CONTROLLER_PAGE, - DEVICE_SETTINGS_PAGE, - COMPUTER_SETTINGS_PAGE, - DISPLAY_SETTINGS_PAGE, - KEYBOARD_SETTINGS_PAGE, - LAYOUT_SETTINGS_PAGE, + DEVICE_SETTINGS_PAGE, + COMPUTER_SETTINGS_PAGE, + DISPLAY_SETTINGS_PAGE, + KEYBOARD_SETTINGS_PAGE, + LAYOUT_SETTINGS_PAGE, - SELECT_PARTITION_PAGE, - CREATE_PARTITION_PAGE, - DELETE_PARTITION_PAGE, + SELECT_PARTITION_PAGE, + CREATE_PARTITION_PAGE, + DELETE_PARTITION_PAGE, - SELECT_FILE_SYSTEM_PAGE, - FORMAT_PARTITION_PAGE, - CHECK_FILE_SYSTEM_PAGE, + SELECT_FILE_SYSTEM_PAGE, + FORMAT_PARTITION_PAGE, + CHECK_FILE_SYSTEM_PAGE, - PREPARE_COPY_PAGE, - INSTALL_DIRECTORY_PAGE, - FILE_COPY_PAGE, - REGISTRY_PAGE, - BOOT_LOADER_PAGE, - BOOT_LOADER_FLOPPY_PAGE, - BOOT_LOADER_HARDDISK_MBR_PAGE, - BOOT_LOADER_HARDDISK_VBR_PAGE, + PREPARE_COPY_PAGE, + INSTALL_DIRECTORY_PAGE, + FILE_COPY_PAGE, + REGISTRY_PAGE, + BOOT_LOADER_PAGE, + BOOT_LOADER_FLOPPY_PAGE, + BOOT_LOADER_HARDDISK_MBR_PAGE, + BOOT_LOADER_HARDDISK_VBR_PAGE, - REPAIR_INTRO_PAGE, + REPAIR_INTRO_PAGE, - SUCCESS_PAGE, - QUIT_PAGE, - FLUSH_PAGE, - REBOOT_PAGE, /* virtual page */ + SUCCESS_PAGE, + QUIT_PAGE, + FLUSH_PAGE, + REBOOT_PAGE, /* virtual page */ } PAGE_NUMBER, *PPAGE_NUMBER; #endif diff --git a/base/setup/vmwinst/lang/tr-TR.rc b/base/setup/vmwinst/lang/tr-TR.rc index 9a1528d50a3..657dcb770fd 100644 --- a/base/setup/vmwinst/lang/tr-TR.rc +++ b/base/setup/vmwinst/lang/tr-TR.rc @@ -4,24 +4,24 @@ LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT IDD_WELCOMEPAGE DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Görüntülük Sürücüsü Kurulumu" +CAPTION "Vidyo Sürücüsü Kurulumu" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN - LTEXT "ReactOS Kur, VMWare(r)'de çalıştığını algıladı.", -1, 117, 8, 140, 24 - LTEXT "VMware(r) SVGA sürücüsünü kurmak için ""İleri"" düğmesine tıklayınız. Eğer sürücüyü kurmak istemiyorsanız ""İptal"" düğmesine tıklayınız.", -1, 117, 140, 140, 24 + LTEXT "ReactOS Kur, sizin ReactOS'u VMWare(r)'de çalıştırdığınızı algıladı.", -1, 117, 8, 140, 24 + LTEXT "Eğer VMware(r) SVGA sürücüsünü kurmayı istiyorsanız ""İleri""ye tıklayınız, yoksa ""İptal""e tıklayınız.", -1, 117, 140, 140, 24 END IDD_INSERT_VMWARE_TOOLS DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Görüntülük Sürücüsü Kurulumu" +CAPTION "Vidyo Sürücüsü Kurulumu" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN - LTEXT "ReactOS Kur, VMware(r) SVGA sürücüsüyle birlikte gelmez.\n\nBu yüzden, VMWare(r)'de bulunan ""Install VMware tools..."" seçeneğine tıklayınız.\n\n\nİşlemi sürdürmek için ""İleri"" düğmesine, sürücünün kurulumunu atlamak için ""İptal"" düğmesine tıklayınız.", -1, 25, 25, 225, 85 + LTEXT "ReactOS Kur, VMware(r) SVGA sürücüsüyle gelmez.\n\nBu yüzden VMWare(r) seçke çubuğunuzdaki ""VM""ye gidiniz ve ""Install VMware tools...""u seçiniz.\n\n\nSürdürmek için ""İleri""ye ya da SVGA sürücüsünün kurulumunu atlamak için ""İptal""e tıklayınız.", -1, 25, 25, 225, 85 END IDD_INSTALLING_VMWARE_TOOLS DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Görüntülük Sürücüsü Kurulumu" +CAPTION "Vidyo Sürücüsü Kurulumu" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN LTEXT "{STATUS}", IDC_INSTALLINGSTATUS, 25, 68, 225, 8 @@ -30,10 +30,10 @@ END IDD_CONFIG DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Görüntülük Sürücüsü Kurulumu" +CAPTION "Vidyo Sürücüsü Kurulumu" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN - LTEXT "VMware(r) SVGA sürücüsü, başarılı bir şekilde kuruldu. Aşağıdaki çözünürlüklerden birini seçiniz:", -1, 25, 5, 225, 20 + LTEXT "VMware(r) SVGA sürücüsü, başarılı bir şekilde kuruldu. Lütfen gözde görüntülük çözünürlüğünüzü seçiniz:", -1, 25, 5, 225, 20 PUSHBUTTON "640x480", 1120, 25, 30, 65, 15, BS_AUTORADIOBUTTON PUSHBUTTON "800x600", 1400, 25, 45, 65, 15, BS_AUTORADIOBUTTON PUSHBUTTON "1024x768", 1792, 25, 60, 65, 15, BS_AUTORADIOBUTTON @@ -45,89 +45,89 @@ BEGIN PUSHBUTTON "1792x1344", 3136, 195, 30, 65, 15, BS_AUTORADIOBUTTON PUSHBUTTON "1856x1392", 3248, 195, 45, 65, 15, BS_AUTORADIOBUTTON PUSHBUTTON "1920x1440", 3360, 195, 60, 50, 15, BS_AUTORADIOBUTTON - LTEXT "Aşağıdaki derinliklerden birini seçiniz:", -1, 25, 93, 225, 12 + LTEXT "Lütfen gözde renk derinliğinizi seçiniz:", -1, 25, 93, 225, 12 COMBOBOX IDC_COLORQUALITY, 25, 105, 75, 80, CBS_DROPDOWNLIST | WS_TABSTOP END IDD_INSTALLATION_FAILED DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Görüntülük Sürücüsü Kurulumu" +CAPTION "Vidyo Sürücüsü Kurulumu" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN - LTEXT "ReactOS Kur, VMware(r) SVGA sürücüsünü kuramadı.\n\n\nReactOS kurulumunu sürdürmek için ""Bitir"" düğmesine tıklayınız.", -1, 25, 25, 225, 85 + LTEXT "ReactOS Kur, VMware(r) SVGA sürücüsünü kuramadı.\n\n\nKurulum işlemini sürdürmek için ""Bitir""e tıklayınız.", -1, 25, 25, 225, 85 END IDD_CHOOSEACTION DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Görüntülük Sürücüsü Kurulumu" +CAPTION "Vidyo Sürücüsü Kurulumu" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN - LTEXT "VMware(r) SVGA sürücüsü, daha önceden kurulmuş.\n\nNe yapmak istediğinizi seçiniz:", -1, 25, 5, 225, 30 - PUSHBUTTON "Görüntülük Ayarlarını Yapılandırmak", IDC_CONFIGSETTINGS, 25, 40, 200, 15, BS_AUTORADIOBUTTON - PUSHBUTTON "Başka Bir Görüntülük Sürücüsü Kurmak", IDC_USEOTHERDRIVER, 25, 55, 200, 15, BS_AUTORADIOBUTTON - PUSHBUTTON "VMware(r) SVGA Sürücüsünü Kaldırmak", IDC_UNINSTALL, 25, 70, 200, 15, BS_AUTORADIOBUTTON - LTEXT "Sürdürmek için ""İleri"" düğmesine, çıkmak için ""İptal"" düğmesine tıklayınız.", -1, 25, 93, 225, 19 + LTEXT "VMware(r) SVGA sürücüsü önceden kurulmuş.\n\nLütfen ne yapmak istediğinizi seçiniz:", -1, 25, 5, 225, 30 + PUSHBUTTON "Görüntülük Ayarlarını Yapılandırma", IDC_CONFIGSETTINGS, 25, 40, 200, 15, BS_AUTORADIOBUTTON + PUSHBUTTON "Başka Bir Çizge Sürücüsü Kurma", IDC_USEOTHERDRIVER, 25, 55, 200, 15, BS_AUTORADIOBUTTON + PUSHBUTTON "VMware(r) SVGA Sürücüsünü Kaldırma", IDC_UNINSTALL, 25, 70, 200, 15, BS_AUTORADIOBUTTON + LTEXT "Sürdürmek için ""İleri""ye ya da büyücüden çıkmak için ""İptal""e tıklayınız.", -1, 25, 93, 225, 19 END IDD_SELECTDRIVER DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Görüntülük Sürücüsü Kurulumu" +CAPTION "Vidyo Sürücüsü Kurulumu" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN - LTEXT "Kullanmak istediğiniz görüntülük sürücüsünü seçiniz:", -1, 25, 25, 225, 15 + LTEXT "Lütfen kullanmak istediğiniz çizge sürücüsünü seçiniz:", -1, 25, 25, 225, 15 PUSHBUTTON "ReactOS VGA Sürücüsü", IDC_VGA, 25, 40, 225, 15, BS_AUTORADIOBUTTON PUSHBUTTON "ReactOS VBE Sürücüsü (SVGA)", IDC_VBE, 25, 55, 225, 15, BS_AUTORADIOBUTTON - LTEXT "İşlemi bitirmek için ""Bitir"" düğmesine, hiçbir değişiklik yapmadan çıkmak için ""İptal"" düğmesine tıklayınız.", -1, 25, 93, 225, 20 + LTEXT "İşlemi bitirmek için ""Bitir""e ya da değişiklik yapmadan kurulumdan çıkmak için ""İptal""e tıklayınız.", -1, 25, 93, 225, 20 END IDD_DOUNINSTALL DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Görüntülük Sürücüsü Kurulumu" +CAPTION "Vidyo Sürücüsü Kurulumu" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN - LTEXT "ReactOS Kur, VMware(r) SVGA sürücüsünü kaldırmak üzere.\n\n\nKaldırmayı bitirmek için ""Bitir"" düğmesine, hiçbir değişiklik yapılmadan çıkmak için ""İptal"" düğmesine tıklayınız.", -1, 25, 25, 225, 85 + LTEXT "ReactOS Kur, VMware(r) SVGA sürücünüzü kaldırmak üzere.\n\n\nSürücüyü kaldırmak için ""Bitir""e ya da onu olduğu gibi bırakmak için ""İptal""e tıklayınız.", -1, 25, 25, 225, 85 END STRINGTABLE BEGIN IDS_WIZARD_NAME "VMware(r) algılandı." - IDS_FAILEDTOLOCATEDRIVERS "ReactOS Kur, gerekli kütükleri bulamadı.\nVMWare(r) Araç CD'sini bağladığınızı doğrulayınız." - IDS_FAILEDTOCOPYFILES "ReactOS Kur, gerekli kütükleri çoğaltamadı.\nVMWare(r) Araç CD'sini bağladığınızı doğrulayınız.\n" - IDS_FAILEDTOACTIVATEDRIVER "VMware(r) SVGA sürücüsünün etkinleştirilmesi başarısız oldu." - IDS_FAILEDTOSELVGADRIVER "ReactOS VGA sürücüsünün etkinleştirilmesi başarısız oldu." - IDS_FAILEDTOSELVBEDRIVER "ReactOS VBE sürücüsünün etkinleştirilmesi başarısız oldu." - IDS_UNINSTNOTICE "VMware(r) SVGA sürücüsünün kütükleri silinmedi.\nOnları, dizgeyi yeniden başlatma sonrasında siliniz." - IDS_FAILEDTOADDREGENTRIES "VMware(r) SVGA sürücüsünün değerleri oluşturulamadı." + IDS_FAILEDTOLOCATEDRIVERS "ReactOS Kur gerekli kütükleri bulamadı.\nVMWare(r) Araç CD-ROM'unun takılı olduğundan emin olunuz." + IDS_FAILEDTOCOPYFILES "ReactOS Kur gerekli kütükleri çoğaltamadı.\nVMWare(r) Araç CD-ROM'unun takılı olduğundan emin olunuz.\n" + IDS_FAILEDTOACTIVATEDRIVER "VMware(r) SVGA sürücüsünü etkinleştirme başarısız oldu." + IDS_FAILEDTOSELVGADRIVER "ReactOS VGA sürücüsünü etkinleştirme başarısız oldu." + IDS_FAILEDTOSELVBEDRIVER "ReactOS VBE sürücüsünü etkinleştirme başarısız oldu." + IDS_UNINSTNOTICE "VMware(r) SVGA sürücüsünün kütükleri daha silinmedi.\nLütfen onları bir yeniden başlatmadan sonra elle siliniz." + IDS_FAILEDTOADDREGENTRIES "VMware(r) SVGA sürücüsü için değer defteri girdilerinin oluşturulması başarısız oldu." END STRINGTABLE BEGIN - 10001 "Düşük (8 İkillik)" - 10002 "Orta (16 İkillik)" - 10003 "Yüksek (32 İkillik)" + 10001 "En Düşük (Her Noktada 8 Bit)" + 10002 "Orta (Her Noktada 16 Bit)" + 10003 "En Yüksek (Her Noktada 32 Bit)" END STRINGTABLE BEGIN - IDS_SEARCHINGFORCDROM "VMWare(r) Araç CD'si aranıyor..." + IDS_SEARCHINGFORCDROM "VMWare(r) Araç CD-ROM'u aranıyor..." IDS_COPYINGFILES "Kütükler çoğaltılıyor..." IDS_ENABLINGDRIVER "VMware(r) SVGA sürücüsü etkinleştiriliyor..." END STRINGTABLE BEGIN - IDD_INSERT_VMWARE_TOOLSTITLE "VMware(r) SVGA Sürücüsünün Kurulumu" - IDD_INSERT_VMWARE_TOOLSSUBTITLE "VMWare(r) Araç CD'sini bağlayınız." - IDD_INSTALLING_VMWARE_TOOLSTITLE "VMware(r) SVGA Sürücüsünün Kurulumu" - IDD_INSTALLING_VMWARE_TOOLSSUBTITLE "VMware(r) SVGA sürücüsünü bulunuz ve çoğaltınız." - IDD_CONFIGTITLE "VMware(r) SVGA Sürücüsünün Kurulumu" - IDD_CONFIGSUBTITLE "Çözünürlüklerden birini seçiniz." - IDD_INSTALLATION_FAILEDTITLE "VMware(r) SVGA Sürücüsünün Kurulumu" + IDD_INSERT_VMWARE_TOOLSTITLE "VMware(r) SVGA Sürücüsünün Kurulum Büyücüsü" + IDD_INSERT_VMWARE_TOOLSSUBTITLE "Lütfen VMWare(r) Araç CD-ROM'unu takınız." + IDD_INSTALLING_VMWARE_TOOLSTITLE "VMware(r) SVGA Sürücüsünün Kurulum Büyücüsü" + IDD_INSTALLING_VMWARE_TOOLSSUBTITLE "VMware(r) SVGA sürücüsünü arayınız ve çoğaltınız." + IDD_CONFIGTITLE "VMware(r) SVGA Sürücüsünün Kurulum Büyücüsü" + IDD_CONFIGSUBTITLE "Gözde görüntülük çözünürlüğünüzü seçiniz." + IDD_INSTALLATION_FAILEDTITLE "VMware(r) SVGA Sürücüsünün Kurulum Büyücüsü" IDD_INSTALLATION_FAILEDSUBTITLE "VMware(r) SVGA sürücüsünün kurulumu başarısız oldu." - IDD_CHOOSEACTIONTITLE "VMware(r) SVGA Sürücüsünün Kurulumu" + IDD_CHOOSEACTIONTITLE "VMware(r) SVGA Sürücüsünün Kurulum Büyücüsü" IDD_CHOOSEACTIONSUBTITLE "Ne yapmak istediğinizi seçiniz." - IDD_SELECTDRIVERTITLE "VMware(r) SVGA Sürücüsünün Kurulumu" + IDD_SELECTDRIVERTITLE "VMware(r) SVGA Sürücüsünün Kurulum Büyücüsü" IDD_SELECTDRIVERSUBTITLE "Bir sürücü seçiniz." - IDD_DOUNINSTALLTITLE "VMware(r) SVGA Sürücüsünün Kurulumu" + IDD_DOUNINSTALLTITLE "VMware(r) SVGA Sürücüsünün Kurulum Büyücüsü" IDD_DOUNINSTALLSUBTITLE "Sürücüyü kaldırınız." END diff --git a/base/setup/vmwinst/vmwinst.rc b/base/setup/vmwinst/vmwinst.rc index 6ff883b4f9a..835aa28e736 100644 --- a/base/setup/vmwinst/vmwinst.rc +++ b/base/setup/vmwinst/vmwinst.rc @@ -77,12 +77,12 @@ IDB_HEADER BITMAP "resources/header.bmp" #ifdef LANGUAGE_SK_SK #include "lang/sk-SK.rc" #endif -#ifdef LANGUAGE_SV_SE - #include "lang/sv-SE.rc" -#endif #ifdef LANGUAGE_SQ_AL #include "lang/sq-AL.rc" #endif +#ifdef LANGUAGE_SV_SE + #include "lang/sv-SE.rc" +#endif #ifdef LANGUAGE_TR_TR #include "lang/tr-TR.rc" #endif diff --git a/base/setup/welcome/lang/tr-TR.rc b/base/setup/welcome/lang/tr-TR.rc index d91b20872ea..78802c65f12 100644 --- a/base/setup/welcome/lang/tr-TR.rc +++ b/base/setup/welcome/lang/tr-TR.rc @@ -7,10 +7,10 @@ LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT /* Default settings */ STRINGTABLE BEGIN - IDS_APPTITLE "ReactOS - Hoşgeldiniz Uygulaması" - IDS_DEFAULTTOPICTITLE "ReactOS - Hoşgeldiniz Uygulaması" - IDS_DEFAULTTOPICDESC "React İşletim Dizgesi'ne hoşgeldiniz.\n\nFârenizi, soldaki herhangi bir seçeneğe götürebilirsiniz." -// IDS_CHECKTEXT "Bir sonraki sefere bu pencereyi göster." + IDS_APPTITLE "ReactOS - Hoşgeldiniz" + IDS_DEFAULTTOPICTITLE "ReactOS" + IDS_DEFAULTTOPICDESC "React İşletim Dizgesi'ne hoşgeldiniz.\n\nSolda bir konuya tıklayınız." +// IDS_CHECKTEXT "Bu iletiyi yine göster." // IDS_CLOSETEXT "Çıkış" END @@ -18,7 +18,7 @@ END STRINGTABLE BEGIN IDS_TOPICBUTTON0 "ReactOS'u Kur" - IDS_TOPICBUTTON1 "CD'nin İçini Araştır" + IDS_TOPICBUTTON1 "Bu CD'yi Araştır" IDS_TOPICBUTTON2 "Çıkış" // IDS_TOPICBUTTON3 "Empty Topic 3" // IDS_TOPICBUTTON4 "Empty Topic 4" @@ -33,7 +33,7 @@ END STRINGTABLE BEGIN IDS_TOPICTITLE0 "ReactOS'u Kur" - IDS_TOPICTITLE1 "CD'nin İçini Araştır" + IDS_TOPICTITLE1 "Bu CD'yi Araştır" IDS_TOPICTITLE2 "Çıkış" // IDS_TOPICTITLE3 "Empty Topic Title 3" // IDS_TOPICTITLE4 "Empty Topic Title 4" @@ -47,9 +47,9 @@ END /* Topic descriptions */ STRINGTABLE BEGIN - IDS_TOPICDESC0 "Bu seçenek ile bilgisayarınıza ReactOS yükleyebilir ya da bilgisayarınızda var olan bir ReactOS yüklemesini yükseltebilirsiniz." - IDS_TOPICDESC1 "CD'deki kütükleri gösterir." - IDS_TOPICDESC2 "Bu uygulamadan çıkar." + IDS_TOPICDESC0 "Bilgisayarınıza yeni bir ReactOS yükleyiniz ya da var olan bir yüklemeyi yükseltiniz." + IDS_TOPICDESC1 "CD'yi araştır." + IDS_TOPICDESC2 "Bu uygulamadan çıkmak için tıklayınız." // IDS_TOPICDESC3 "Topic description 3.\n\nDescribe topic 3 here." // IDS_TOPICDESC4 "Topic description 4.\n\nDescribe topic 4 here." // IDS_TOPICDESC5 "Topic description 5.\n\nDescribe topic 5 here." diff --git a/base/setup/welcome/welcome.rc b/base/setup/welcome/welcome.rc index 655fcf2b344..2391afe02b8 100644 --- a/base/setup/welcome/welcome.rc +++ b/base/setup/welcome/welcome.rc @@ -116,6 +116,9 @@ END #ifdef LANGUAGE_SK_SK #include "lang/sk-SK.rc" #endif +#ifdef LANGUAGE_SQ_AL + #include "lang/sq-AL.rc" +#endif #ifdef LANGUAGE_SV_SE #include "lang/sv-SE.rc" #endif @@ -125,9 +128,6 @@ END #ifdef LANGUAGE_TR_TR #include "lang/tr-TR.rc" #endif -#ifdef LANGUAGE_SQ_AL - #include "lang/sq-AL.rc" -#endif #ifdef LANGUAGE_UK_UA #include "lang/uk-UA.rc" #endif diff --git a/base/shell/cmd/copy.c b/base/shell/cmd/copy.c index a5f896d17dd..c5c127f573b 100644 --- a/base/shell/cmd/copy.c +++ b/base/shell/cmd/copy.c @@ -200,7 +200,7 @@ copy(TCHAR source[MAX_PATH], } /* A page-aligned buffer usually give more speed */ - buffer = (LPBYTE)VirtualAlloc(NULL, BUFF_SIZE, MEM_COMMIT, PAGE_READWRITE); + buffer = VirtualAlloc(NULL, BUFF_SIZE, MEM_COMMIT, PAGE_READWRITE); if (buffer == NULL) { CloseHandle (hFileDest); diff --git a/base/shell/cmd/replace.c b/base/shell/cmd/replace.c index 4b139c82e5a..864e3fb6e24 100644 --- a/base/shell/cmd/replace.c +++ b/base/shell/cmd/replace.c @@ -160,7 +160,7 @@ INT replace(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], DWORD dwFlags, BOOL *d } /* Get buffer for the copy process */ - buffer = (LPBYTE)VirtualAlloc(NULL, BUFF_SIZE, MEM_COMMIT, PAGE_READWRITE); + buffer = VirtualAlloc(NULL, BUFF_SIZE, MEM_COMMIT, PAGE_READWRITE); if (buffer == NULL) { CloseHandle (hFileDest); @@ -188,7 +188,7 @@ INT replace(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], DWORD dwFlags, BOOL *d if (dwWritten != dwRead || CheckCtrlBreak(BREAK_INPUT)) { ConOutResPuts(STRING_COPY_ERROR3); - cmd_free (buffer); + VirtualFree (buffer, 0, MEM_RELEASE); CloseHandle (hFileDest); CloseHandle (hFileSrc); nErrorLevel = 1; diff --git a/base/shell/explorer-new/lang/tr-TR.rc b/base/shell/explorer-new/lang/tr-TR.rc index 5258caec0b5..95ea9523ca6 100644 --- a/base/shell/explorer-new/lang/tr-TR.rc +++ b/base/shell/explorer-new/lang/tr-TR.rc @@ -11,8 +11,8 @@ BEGIN MENUITEM "&Bildirimleri Husûsileştir...", ID_SHELL_CMD_CUST_NOTIF MENUITEM SEPARATOR MENUITEM "&Pencereleri Basamakla", ID_SHELL_CMD_CASCADE_WND - MENUITEM "P&encereleri Üst Üste Sırala", ID_SHELL_CMD_TILE_WND_H - MENUITEM "Pe&ncereleri Yan Yana Sırala", ID_SHELL_CMD_TILE_WND_V + MENUITEM "P&encereleri Yatay Olarak Döşe", ID_SHELL_CMD_TILE_WND_H + MENUITEM "Pe&ncereleri Dikey Olarak Döşe", ID_SHELL_CMD_TILE_WND_V MENUITEM "&Masaüstünü Göster", ID_SHELL_CMD_SHOW_DESKTOP MENUITEM "&Geri Al", ID_SHELL_CMD_UNDO_ACTION MENUITEM SEPARATOR @@ -28,11 +28,11 @@ BEGIN POPUP "" BEGIN MENUITEM "", -1, MFT_SEPARATOR - POPUP "&Yazılımlar", IDM_PROGRAMS + POPUP "&İzlenceler", IDM_PROGRAMS BEGIN MENUITEM "(Boş)", -1, MFT_STRING, MFS_GRAYED END - POPUP "Y&er İmleri", IDM_FAVORITES + POPUP "&Yer İmleri", IDM_FAVORITES BEGIN MENUITEM "(Boş)", -1, MFT_STRING, MFS_GRAYED END @@ -56,11 +56,11 @@ BEGIN MENUITEM "Yar&dım ve Destek", IDM_HELPANDSUPPORT, MFT_STRING, MFS_ENABLED MENUITEM "&Çalıştır...", IDM_RUN, MFT_STRING, MFS_ENABLED MENUITEM "", 450, MFT_SEPARATOR, MFS_ENABLED - MENUITEM "E&şle", IDM_SYNCHRONIZE, MFT_STRING, MFS_ENABLED - MENUITEM "&Oturumu Kapat %s...", IDM_LOGOFF, MFT_STRING, MFS_ENABLED + MENUITEM "&Eşle", IDM_SYNCHRONIZE, MFT_STRING, MFS_ENABLED + MENUITEM "&Oturumu Kapat: %s...", IDM_LOGOFF, MFT_STRING, MFS_ENABLED MENUITEM "Ba&ğlantıyı Kes...", IDM_DISCONNECT, MFT_STRING, MFS_ENABLED MENUITEM "B&ilgisayarı Ayır", IDM_UNDOCKCOMPUTER, MFT_STRING, MFS_ENABLED - MENUITEM "Bi&lgisayarı Kapat...", IDM_SHUTDOWN, MFT_STRING, MFS_ENABLED + MENUITEM "&Kapat...", IDM_SHUTDOWN, MFT_STRING, MFS_ENABLED END END @@ -69,7 +69,7 @@ STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPT CAPTION "Görev Çubuğu" FONT 8, "MS Shell Dlg", 0, 0, 0x1 BEGIN - GROUPBOX "Görev Çubuğunun Görünümü", IDC_STATIC, 6, 6, 240, 104 + GROUPBOX "Görev Çubuğu Görünümü", IDC_STATIC, 6, 6, 240, 104 CONTROL "", IDC_TASKBARPROP_TASKBARBITMAP, "Static", SS_BITMAP | SS_SUNKEN, 13, 18, 224, 21 AUTOCHECKBOX "&Görev Çubuğunu Kilitle", IDC_TASKBARPROP_LOCK, 13, 45, 200, 10 AUTOCHECKBOX "G&örev Çubuğunu Kendiliğinden Gizle", IDC_TASKBARPROP_HIDE, 13, 58, 200, 10 @@ -83,15 +83,15 @@ STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPT CAPTION "Başlat Seçkesi" FONT 8, "MS Shell Dlg", 0, 0, 0x1 BEGIN - AUTORADIOBUTTON "&Gelişmiş Başlat Seçkesi", IDC_TASKBARPROP_STARTMENU, 7, 7, 105, 10 - LTEXT "Gelişmiş Başlat Seçkesi; dizinlere, sık kullanılan yazılımlara ve aramaya kolayca ulaşmanıza olanak sağlar.", IDC_STATIC, 20, 17, 150, 24, WS_DISABLED + AUTORADIOBUTTON "&Başlat Seçkesi", IDC_TASKBARPROP_STARTMENU, 7, 7, 105, 10 + LTEXT "Bu seçke türü; size dizinlerinize, sık kullanılan izlencelere ve aramaya kolay erişim verir.", IDC_STATIC, 20, 17, 150, 24, WS_DISABLED PUSHBUTTON "&Husûsileştir...", IDC_TASKBARPROP_STARTMENUCUST, 192, 4, 53, 14, WS_DISABLED - AUTORADIOBUTTON "&Eski Başlat Seçkesi", IDC_TASKBARPROP_STARTMENUCLASSIC, 7, 47, 105, 10, WS_DISABLED - LTEXT "Eski Başlat Seçkesi, eski görünüm ve eski işlevliği sağlar.", -1, 20, 57, 150, 24, WS_DISABLED + AUTORADIOBUTTON "&Geleneklik Başlat Seçkesi", IDC_TASKBARPROP_STARTMENUCLASSIC, 7, 47, 105, 10, WS_DISABLED + LTEXT "Bu seçke türü, size geleneklik görünümü ve geleneklik işlevliliği sağlar.", -1, 20, 57, 150, 24, WS_DISABLED PUSHBUTTON "H&usûsileştir...", IDC_TASKBARPROP_STARTMENUCLASSICCUST, 192, 44, 53, 14, WS_DISABLED GROUPBOX "Gizlilik", IDC_STATIC, 7, 100, 238, 42 - AUTOCHECKBOX "&Son Kullanılan Kütüklerin Dizelgesini Sakla ve Görüntüle", IDC_TASKBARPROP_RECENTFILES, 14, 114, 224, 10, WS_DISABLED - AUTOCHECKBOX "S&on Kullanılan Yazılımların Dizelgesini Sakla ve Görüntüle", IDC_TASKBARPROP_RECENTFOLDERS, 14, 128, 224, 10, WS_DISABLED + AUTOCHECKBOX "&Son Zamanlarda Açılan Kütüklerin Bir Dizelgesini Sakla ve Görüntüle", IDC_TASKBARPROP_RECENTFILES, 14, 114, 224, 10, WS_DISABLED + AUTOCHECKBOX "S&on Zamanlarda Açılan Yazılımların Bir Dizelgesini Sakla ve Görüntüle", IDC_TASKBARPROP_RECENTFOLDERS, 14, 128, 224, 10, WS_DISABLED END IDD_TASKBARPROP_NOTIFICATION DIALOGEX 0, 0, 252, 218 @@ -101,13 +101,13 @@ FONT 8, "MS Shell Dlg", 0, 0, 0x1 BEGIN CONTROL "", IDC_TASKBARPROP_NOTIFICATIONBITMAP, "Static", SS_BITMAP | SS_SUNKEN,7, 6, 238, 21, WS_DISABLED GROUPBOX "Simgeler", IDC_STATIC, 6, 33, 240, 58, WS_DISABLED - LTEXT "Yakın zamanda kullanmadığınız simgeleri gizleyerek bildirim alanının şişmesini önleyebilirsiniz.", IDC_STATIC, 13, 48, 223, 16, WS_DISABLED + LTEXT "Son zamanlarda tıklamadığınız simgeleri gizleyerek bildirim alanını düzenli tutabilirsiniz.", IDC_STATIC, 13, 48, 223, 16, WS_DISABLED AUTOCHECKBOX "E&dilgin Simgeleri Gizle", IDC_TASKBARPROP_HIDEICONS, 13, 70, 125, 10, WS_DISABLED PUSHBUTTON "&Husûsileştir...", IDC_TASKBARPROP_ICONCUST, 188, 70, 50, 14, WS_DISABLED GROUPBOX "Dizge Simgeleri", IDC_STATIC, 6, 97, 240, 84, WS_DISABLED - LTEXT "Sürekli görüntülenecek dizge simgelerini seçiniz:", IDC_STATIC, 13, 112, 223, 16, WS_DISABLED + LTEXT "Sürekli göstermek için dizge simgelerini seçiniz:", IDC_STATIC, 13, 112, 223, 16, WS_DISABLED AUTOCHECKBOX "&Saat", IDC_TASKBARPROP_CLOCK, 13, 126, 200, 10, WS_DISABLED - AUTOCHECKBOX "S&es Ayârı", IDC_TASKBARPROP_VOLUME, 13, 139, 200, 10, WS_DISABLED + AUTOCHECKBOX "S&es Düzeyi", IDC_TASKBARPROP_VOLUME, 13, 139, 200, 10, WS_DISABLED AUTOCHECKBOX "&Ağ", IDC_TASKBARPROP_NETWORK, 13, 152, 200, 10, WS_DISABLED AUTOCHECKBOX "&Güç", IDC_TASKBARPROP_POWER, 13, 164, 200, 10, WS_DISABLED END @@ -117,7 +117,7 @@ STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPT CAPTION "Araç Çubukları" FONT 8, "MS Shell Dlg", 0, 0, 0x1 BEGIN - LTEXT "Görev çubuğuna hangi araç çubuklarının ekleneceğini seçebilirsiniz:", IDC_STATIC, 7, 7, 223, 12, WS_DISABLED + LTEXT "Görev çubuğuna eklemek için araç çubuklarını seçiniz:", IDC_STATIC, 7, 7, 223, 12, WS_DISABLED CONTROL "", IDC_TASKBARPROP_DESKBANDLIST, "SysTreeView32", WS_BORDER | WS_TABSTOP | WS_DISABLED, 7, 20, 236, 160, WS_EX_CLIENTEDGE END @@ -137,7 +137,7 @@ BEGIN IDS_PROPERTIES "&Husûsiyetler" IDS_OPEN_ALL_USERS "&Tüm Kullanıcılar'da Aç" IDS_EXPLORE_ALL_USERS "T&üm Kullanıcılar'da Araştır" - IDS_STARTUP_ERROR "Dizge, gerekli değerlerin, bozuk olduğundan ya da olmadığından Gezgin'i başlatamadı." + IDS_STARTUP_ERROR "Dizge, değer defterinin, bozuk ya da olmadığından gezgini başlatamadı." END STRINGTABLE diff --git a/base/shell/explorer/explorer-cz.rc b/base/shell/explorer/explorer-cz.rc index e06138465d6..c2027c3d8ae 100644 --- a/base/shell/explorer/explorer-cz.rc +++ b/base/shell/explorer/explorer-cz.rc @@ -8,38 +8,38 @@ BEGIN BEGIN MENUITEM "&Spustit...", ID_EXECUTE MENUITEM SEPARATOR - MENUITEM "&Ukonit", ID_FILE_EXIT + MENUITEM "&Ukončit", ID_FILE_EXIT END - POPUP "&Zobrazen" + POPUP "&Zobrazení" BEGIN - MENUITEM "Panel &nstroj", ID_VIEW_TOOL_BAR + MENUITEM "Panel &nástrojů", ID_VIEW_TOOL_BAR MENUITEM "Panel &extra", ID_VIEW_EXTRA_BAR - MENUITEM "L&ita disk", ID_VIEW_DRIVE_BAR - MENUITEM "&Bon panel", ID_VIEW_SIDE_BAR - MENUITEM "&Stavov dek", ID_VIEW_STATUSBAR + MENUITEM "L&išta disků", ID_VIEW_DRIVE_BAR + MENUITEM "&Boční panel", ID_VIEW_SIDE_BAR + MENUITEM "&Stavový řádek", ID_VIEW_STATUSBAR MENUITEM SEPARATOR MENUITEM "&Aktualizovat\tF5", ID_REFRESH - MENUITEM "&Cel obrazovka\tCtrl+Shift+S", ID_VIEW_FULLSCREEN + MENUITEM "&Celá obrazovka\tCtrl+Shift+S", ID_VIEW_FULLSCREEN MENUITEM "SDI", ID_VIEW_SDI END POPUP "&Okno" BEGIN - MENUITEM "&Nov Okno", ID_WINDOW_NEW - MENUITEM "&Kaskdovat\tShift+F5", ID_WINDOW_CASCADE - MENUITEM "&Uspodat vodorovn", ID_WINDOW_TILE_HORZ - MENUITEM "U&spodat svisle\tShift+F4", ID_WINDOW_TILE_VERT - MENUITEM "Us&podat automaticky", ID_WINDOW_AUTOSORT - MENUITEM "Usp&odat symboly", ID_WINDOW_ARRANGE + MENUITEM "&Nové Okno", ID_WINDOW_NEW + MENUITEM "&Kaskádovat\tShift+F5", ID_WINDOW_CASCADE + MENUITEM "&Uspořádat vodorovně", ID_WINDOW_TILE_HORZ + MENUITEM "U&spořádat svisle\tShift+F4", ID_WINDOW_TILE_VERT + MENUITEM "Us&pořádat automaticky", ID_WINDOW_AUTOSORT + MENUITEM "Usp&ořádat symboly", ID_WINDOW_ARRANGE END - POPUP "&Nstroje" + POPUP "&Nástroje" BEGIN - MENUITEM "&Monosti", ID_TOOLS_OPTIONS + MENUITEM "&Možnosti", ID_TOOLS_OPTIONS END - POPUP "N&povda" + POPUP "Ná&pověda" BEGIN - MENUITEM "&Przkumnk &FAQ", ID_EXPLORER_FAQ - MENUITEM "O P&rzkumnku", ID_ABOUT_EXPLORER - MENUITEM "&O operanm systmu", ID_ABOUT_WINDOWS + MENUITEM "&Průzkumník &FAQ", ID_EXPLORER_FAQ + MENUITEM "O P&růzkumníku", ID_ABOUT_EXPLORER + MENUITEM "&O operačním systému", ID_ABOUT_WINDOWS END END @@ -47,10 +47,10 @@ IDM_DESKTOPBAR MENU BEGIN POPUP "" BEGIN - MENUITEM "&Nastaven", ID_DESKTOPBAR_SETTINGS - MENUITEM "&Sprvce loh", ID_TASKMGR + MENUITEM "&Nastavení", ID_DESKTOPBAR_SETTINGS + MENUITEM "&Správce úloh", ID_TASKMGR MENUITEM SEPARATOR - MENUITEM "&O Przkumnku", ID_ABOUT_EXPLORER + MENUITEM "&O Průzkumníku", ID_ABOUT_EXPLORER END END @@ -58,7 +58,7 @@ IDM_VOLUME MENU BEGIN POPUP "" BEGIN - MENUITEM "&Otevt ovldn hlasitosti", ID_TRAY_VOLUME + MENUITEM "&Otevřít ovládání hlasitosti", ID_TRAY_VOLUME MENUITEM "&Upravit vlastnosti zvuku", ID_VOLUME_PROPERTIES END END @@ -67,12 +67,12 @@ IDM_NOTIFYAREA MENU BEGIN POPUP "" BEGIN - MENUITEM "&Zobrazit skryt ikony", ID_SHOW_HIDDEN_ICONS - MENUITEM "Z&obrazit ikonu tlatka", ID_SHOW_ICON_BUTTON - MENUITEM "&Nastavit upozornn", ID_CONFIG_NOTIFYAREA - MENUITEM "N&astavit datum a as", ID_CONFIG_TIME + MENUITEM "&Zobrazit skryté ikony", ID_SHOW_HIDDEN_ICONS + MENUITEM "Z&obrazit ikonu tlačítka", ID_SHOW_ICON_BUTTON + MENUITEM "&Nastavit upozornění", ID_CONFIG_NOTIFYAREA + MENUITEM "N&astavit datum a čas", ID_CONFIG_TIME MENUITEM SEPARATOR - MENUITEM "&O Przkumnku", ID_ABOUT_EXPLORER + MENUITEM "&O Průzkumníku", ID_ABOUT_EXPLORER END END @@ -82,27 +82,27 @@ BEGIN BEGIN MENUITEM "&Spustit...", ID_EXECUTE MENUITEM SEPARATOR - MENUITEM "&Ukonit", ID_FILE_EXIT + MENUITEM "&Ukončit", ID_FILE_EXIT END - POPUP "&Zobrazen" + POPUP "&Zobrazení" BEGIN - MENUITEM "Panel &nstroj", ID_VIEW_TOOL_BAR - MENUITEM "&Bon panel", ID_VIEW_SIDE_BAR, GRAYED - MENUITEM "&Stavov dek", ID_VIEW_STATUSBAR + MENUITEM "Panel &nástrojů", ID_VIEW_TOOL_BAR + MENUITEM "&Boční panel", ID_VIEW_SIDE_BAR, GRAYED + MENUITEM "&Stavový řádek", ID_VIEW_STATUSBAR MENUITEM SEPARATOR MENUITEM "&Aktualizovat\tF5", ID_REFRESH - MENUITEM "Cel obrazovka\tCtrl+Shift+S", ID_VIEW_FULLSCREEN + MENUITEM "Celá obrazovka\tCtrl+Shift+S", ID_VIEW_FULLSCREEN MENUITEM "&MDI", ID_VIEW_MDI END - POPUP "&Nstroje" + POPUP "&Nástroje" BEGIN - MENUITEM "&Nastaven", ID_TOOLS_OPTIONS + MENUITEM "&Nastavení", ID_TOOLS_OPTIONS END - POPUP "N&povda" + POPUP "Ná&pověda" BEGIN - MENUITEM "Przkumnk &FAQ", ID_EXPLORER_FAQ - MENUITEM "O &Przkumnku", ID_ABOUT_EXPLORER - MENUITEM "O &Operanm systmu", ID_ABOUT_WINDOWS + MENUITEM "Průzkumník &FAQ", ID_EXPLORER_FAQ + MENUITEM "O &Průzkumníku", ID_ABOUT_EXPLORER + MENUITEM "O &Operačním systému", ID_ABOUT_WINDOWS END END @@ -114,18 +114,18 @@ CAPTION "Spustit" FONT 8, "MS Shell Dlg" BEGIN CONTROL "", 101, "Static", SS_SIMPLE | SS_NOPREFIX, 3, 6, 162, 10 - CONTROL "&Pkaz:", -1, "Static", SS_LEFTNOWORDWRAP | WS_GROUP, 3, 18, 60, 10 + CONTROL "&Příkaz:", -1, "Static", SS_LEFTNOWORDWRAP | WS_GROUP, 3, 18, 60, 10 EDITTEXT 201, 3, 29, 134, 12, ES_AUTOHSCROLL CONTROL "Jako &symbol", 214, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 3, 45, 71, 12 DEFPUSHBUTTON "&Spustit", 1, 158, 6, 47, 14 PUSHBUTTON "&Storno", 2, 158, 23, 47, 14 - PUSHBUTTON "N&povda", 254, 158, 43, 47, 14 + PUSHBUTTON "Ná&pověda", 254, 158, 43, 47, 14 END IDD_SEARCH_PROGRAM DIALOGEX 0, 0, 200, 65 STYLE DS_SHELLFONT | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME EXSTYLE WS_EX_APPWINDOW -CAPTION "Hledat program v nabdce Start" +CAPTION "Hledat program v nabídce Start" FONT 8, "MS Shell Dlg", 0, 0, 0x1 BEGIN LTEXT "&Filtr:", IDC_STATIC, 7, 9, 18, 8 @@ -140,7 +140,7 @@ STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION CAPTION "Vlastnosti plochy" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Prosm zvolte si zpsob zarovnn ikon:", IDC_STATIC, 7, 7, 166, 8 + LTEXT "Prosím zvolte si způsob zarovnání ikon:", IDC_STATIC, 7, 7, 166, 8 CONTROL "vlevo/n. d.", IDC_ICON_ALIGN_0, "Button", BS_OWNERDRAW | BS_BOTTOM | WS_TABSTOP, 7, 25, 46, 44 CONTROL "vlevo/n. p.", IDC_ICON_ALIGN_1, "Button", BS_OWNERDRAW | BS_BOTTOM | WS_TABSTOP, 57, 25, 46, 44 CONTROL "vpravo/n. l.", IDC_ICON_ALIGN_2, "Button", BS_OWNERDRAW | BS_BOTTOM | WS_TABSTOP, 110, 25, 46, 44 @@ -158,17 +158,17 @@ END IDD_DESKBAR_TASKBAR DIALOGEX 0, 0, 210, 194 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Vlastnosti panelu loh" +CAPTION "Vlastnosti panelu úloh" FONT 8, "MS Shell Dlg" BEGIN - CONTROL "&Zobrazit as", ID_SHOW_CLOCK, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 152, 52, 10 - CONTROL "&Skrt neaktivn ikony", ID_HIDE_INACTIVE_ICONS, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 174, 111, 10 - PUSHBUTTON "&Upozornn...", ID_CONFIG_NOTIFYAREA, 153, 173, 50, 14 + CONTROL "&Zobrazit čas", ID_SHOW_CLOCK, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 152, 52, 10 + CONTROL "&Skrýt neaktivní ikony", ID_HIDE_INACTIVE_ICONS, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 174, 111, 10 + PUSHBUTTON "&Upozornění...", ID_CONFIG_NOTIFYAREA, 153, 173, 50, 14 END IDD_DESKBAR_STARTMENU DIALOGEX 0, 0, 210, 194 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Vlastnosti nabdky Start" +CAPTION "Vlastnosti nabídky Start" FONT 8, "MS Shell Dlg" BEGIN END @@ -176,24 +176,24 @@ END IDD_NOTIFYAREA DIALOGEX 0, 0, 208, 174 STYLE DS_SHELLFONT | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME EXSTYLE WS_EX_APPWINDOW -CAPTION "Nastaven ikon v oblasti upozorovn" +CAPTION "Nastavení ikon v oblasti upozorňování" FONT 8, "MS Shell Dlg", 0, 0, 0x1 BEGIN CONTROL "Tree1", IDC_NOTIFY_ICONS, "SysTreeView32", TVS_HASLINES | TVS_SHOWSELALWAYS | WS_BORDER | WS_TABSTOP, 7, 7, 194, 31 LTEXT "&Text popisku:", IDC_LABEL1, 7, 44, 40, 8 EDITTEXT IDC_NOTIFY_TOOLTIP, 58, 42, 143, 14, ES_AUTOHSCROLL - LTEXT "&Nzev okna:", IDC_LABEL2, 7, 63, 44, 8 + LTEXT "&Název okna:", IDC_LABEL2, 7, 63, 44, 8 EDITTEXT IDC_NOTIFY_TITLE, 58, 60, 143, 14, ES_AUTOHSCROLL LTEXT "&Cesta:", IDC_LABEL3, 7, 81, 80, 8 EDITTEXT IDC_NOTIFY_MODULE, 58, 78, 143, 14, ES_AUTOHSCROLL - GROUPBOX "&Zobrazen", IDC_LABEL4, 7, 96, 157, 28 + GROUPBOX "&Zobrazení", IDC_LABEL4, 7, 96, 157, 28 CONTROL "z&obrazit", IDC_NOTIFY_SHOW, "Button", BS_AUTORADIOBUTTON | WS_TABSTOP, 15, 108, 45, 10 - CONTROL "&skrt", IDC_NOTIFY_HIDE, "Button", BS_AUTORADIOBUTTON, 66, 108, 29, 10 + CONTROL "&skrýt", IDC_NOTIFY_HIDE, "Button", BS_AUTORADIOBUTTON, 66, 108, 29, 10 CONTROL "&automaticky", IDC_NOTIFY_AUTOHIDE, "Button", BS_AUTORADIOBUTTON, 104, 108, 55, 10 ICON "", IDC_PICTURE, 173, 101, 21, 20 - LTEXT "&Posledn zmna:", IDC_LABEL6, 7, 132, 60, 8 + LTEXT "&Poslední změna:", IDC_LABEL6, 7, 132, 60, 8 EDITTEXT IDC_LAST_CHANGE, 59, 129, 105, 14, ES_AUTOHSCROLL | ES_READONLY - CONTROL "zob&razit skryt", ID_SHOW_HIDDEN_ICONS, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 158, 57, 10 + CONTROL "zob&razit skryté", ID_SHOW_HIDDEN_ICONS, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 158, 57, 10 DEFPUSHBUTTON "&OK", IDOK, 91, 153, 50, 14, WS_GROUP PUSHBUTTON "&Storno", IDCANCEL, 151, 153, 50, 14 END @@ -201,26 +201,26 @@ END IDD_MDI_SDI DIALOGEX 0, 0, 194, 157 STYLE DS_SHELLFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_APPWINDOW -CAPTION "Volba MDI / SDI mdu" +CAPTION "Volba MDI / SDI módu" FONT 8, "MS Shell Dlg", 0, 0, 0x1 BEGIN - LTEXT "Prosm zvolte si Vmi upednostovan zpsob zobrazen oken Przkumnka:", IDC_STATIC, 7, 7, 160, 8 - CONTROL "&MDI (Mnoho dokumentov interface)", IDC_MDI, "Button", BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP, 7, 31, 125, 10 - CONTROL "&SDI (Jedno dokumentov interface)", IDC_SDI, "Button", BS_AUTORADIOBUTTON, 7, 62, 125, 10 + LTEXT "Prosím zvolte si Vámi upřednostňovaný způsob zobrazení oken Průzkumníka:", IDC_STATIC, 7, 7, 160, 8 + CONTROL "&MDI (Mnoho dokumentový interface)", IDC_MDI, "Button", BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP, 7, 31, 125, 10 + CONTROL "&SDI (Jedno dokumentový interface)", IDC_SDI, "Button", BS_AUTORADIOBUTTON, 7, 62, 125, 10 CONTROL 170, IDC_STATIC, "Static", SS_BITMAP, 145, 23, 15, 13 CONTROL 171, IDC_STATIC, "Static", SS_BITMAP, 145, 57, 15, 13 - CONTROL "&Otevrat sloky v novm okn", IDC_SEPARATE_SUBFOLDERS, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 90, 135, 10 - LTEXT "Toto nastaven bude pouito jako vchoz pro vechna okna Przkumnka.", IDC_STATIC, 7, 111, 174, 22 + CONTROL "&Otevírat složky v novém okně", IDC_SEPARATE_SUBFOLDERS, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 90, 135, 10 + LTEXT "Toto nastavení bude použito jako výchozí pro všechna okna Průzkumníka.", IDC_STATIC, 7, 111, 174, 22 DEFPUSHBUTTON "&OK", IDOK, 29, 136, 50, 14, WS_GROUP PUSHBUTTON "&Storno", IDCANCEL, 106, 136, 50, 14 END IDD_ABOUT_EXPLORER DIALOGEX 0, 0, 199, 106 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "O ReactOS Przkumnku" +CAPTION "O ReactOS Průzkumníku" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "ReactOS Przkumnk", IDC_ROS_EXPLORER, 91, 13, 104, 11 + LTEXT "ReactOS Průzkumník", IDC_ROS_EXPLORER, 91, 13, 104, 11 LTEXT "V 0.9", IDC_VERSION_TXT, 91, 27, 104, 8 LTEXT "(c) 2003-2005 Martin Fuchs", IDC_STATIC, 91, 42, 104, 8 LTEXT "", IDC_WIN_VERSION, 91, 58, 98, 22 @@ -232,61 +232,61 @@ END STRINGTABLE BEGIN - IDS_TITLE "ReactOS Przkumnk" + IDS_TITLE "ReactOS Průzkumník" IDS_START "Start" - IDS_LOGOFF "Odhlsit se..." + IDS_LOGOFF "Odhlásit se..." IDS_SHUTDOWN "Vypnout..." IDS_RESTART "Restartovat..." IDS_LAUNCH "Spustit..." - IDS_START_HELP "Npovda" + IDS_START_HELP "Nápověda" IDS_SEARCH_FILES "Hledat" IDS_DOCUMENTS "Dokumenty" - IDS_FAVORITES "Oblben" + IDS_FAVORITES "Oblíbené" IDS_PROGRAMS "Programy" - IDS_SETTINGS "Nastaven" + IDS_SETTINGS "Nastavení" IDS_EXPLORE "Prozkoumat" - IDS_EMPTY "(Przdn)" - IDS_RECENT "Nedvn dokumenty" - IDS_ADMIN "Systmov nstroje" + IDS_EMPTY "(Prázdné)" + IDS_RECENT "Nedávné dokumenty" + IDS_ADMIN "Systémové nástroje" END STRINGTABLE BEGIN - IDS_STARTMENU "Nabdka Start" - IDS_MINIMIZE_ALL "minimalizovat vechna okna" + IDS_STARTMENU "Nabídka Start" + IDS_MINIMIZE_ALL "minimalizovat všechna okna" IDS_DESKTOP_NUM "Plocha %d" IDS_VOLUME "Hlasitost" - IDS_ITEMS_CUR "souasn poloky" - IDS_ITEMS_CONFIGURED "nastaven" - IDS_ITEMS_VISIBLE "viditeln" - IDS_ITEMS_HIDDEN "skryt" + IDS_ITEMS_CUR "současné položky" + IDS_ITEMS_CONFIGURED "nastavení" + IDS_ITEMS_VISIBLE "viditelné" + IDS_ITEMS_HIDDEN "skryté" IDS_NOTIFY_SHOW "zobrazit" - IDS_NOTIFY_HIDE "skrt" - IDS_NOTIFY_AUTOHIDE "skrvat automaticky" - IDS_SHOW_HIDDEN_ICONS "Zobrazit skryt ikony" - IDS_HIDE_ICONS "Skrt ikony" - IDS_TERMINATE "Ukonit ReactOS Przkumnka" + IDS_NOTIFY_HIDE "skrýt" + IDS_NOTIFY_AUTOHIDE "skrývat automaticky" + IDS_SHOW_HIDDEN_ICONS "Zobrazit skryté ikony" + IDS_HIDE_ICONS "Skrýt ikony" + IDS_TERMINATE "Ukončit ReactOS Průzkumníka" END STRINGTABLE BEGIN - IDS_NETWORK "S" - IDS_CONNECTIONS "Sov spojen" + IDS_NETWORK "Síť" + IDS_CONNECTIONS "Síťové spojení" IDS_DRIVES "Disky" - IDS_SEARCH_COMPUTER "Hledat pota" - IDS_SETTINGS_MENU "Nastaven" - IDS_CONTROL_PANEL "Ovldac panel" - IDS_PRINTERS "Tiskrny" - IDS_BROWSE "Prohlet soubory" + IDS_SEARCH_COMPUTER "Hledat počítač" + IDS_SETTINGS_MENU "Nastavení" + IDS_CONTROL_PANEL "Ovládací panel" + IDS_PRINTERS "Tiskárny" + IDS_BROWSE "Prohlížet soubory" IDS_SEARCH_PRG "Hledat programy" - IDS_ALL_USERS "Vichni uivatel\\" + IDS_ALL_USERS "Všichni uživatelé\\" IDS_SEARCH "Hledat" - IDS_ABOUT_EXPLORER "&O Przkumnku" - IDS_LAUNCH_MANY_PROGRAMS "Bylo vybrno vce program.\nPejete si je spustit vechny?" - IDS_DESKTOPBAR_SETTINGS "Nastaven plochy" + IDS_ABOUT_EXPLORER "&O Průzkumníku" + IDS_LAUNCH_MANY_PROGRAMS "Bylo vybráno více programů.\nPřejete si je spustit všechny?" + IDS_DESKTOPBAR_SETTINGS "Nastavení plochy" IDS_DESKTOP "Plocha" - IDS_TASKBAR "Panel loh" - IDS_NAMECOLUMN "Nzev" + IDS_TASKBAR "Panel úloh" + IDS_NAMECOLUMN "Název" IDS_PATHCOLUMN "Cesta" IDS_MENUCOLUMN "Menu path" END diff --git a/base/shell/explorer/explorer.rc b/base/shell/explorer/explorer.rc index 53d232b2a31..13882b18369 100644 --- a/base/shell/explorer/explorer.rc +++ b/base/shell/explorer/explorer.rc @@ -27,19 +27,19 @@ IDB_SDI BITMAP "res/sdi.bmp" /* Accelerators */ -IDA_EXPLORER ACCELERATORS +IDA_EXPLORER ACCELERATORS BEGIN "S", ID_VIEW_FULLSCREEN, VIRTKEY, SHIFT, CONTROL, NOINVERT VK_F5, ID_REFRESH, VIRTKEY, NOINVERT "X", ID_FILE_EXIT, VIRTKEY, ALT, NOINVERT END -IDA_SEARCH_PROGRAM ACCELERATORS +IDA_SEARCH_PROGRAM ACCELERATORS BEGIN VK_F5, ID_REFRESH, VIRTKEY, NOINVERT END -IDA_TRAYNOTIFY ACCELERATORS +IDA_TRAYNOTIFY ACCELERATORS BEGIN VK_F5, ID_REFRESH, VIRTKEY, NOINVERT END @@ -112,9 +112,6 @@ CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "explorer.exe.manifest" #ifdef LANGUAGE_BG_BG #include "explorer-bg.rc" #endif -#ifdef LANGUAGE_CS_CZ - #include "explorer-cz.rc" -#endif #ifdef LANGUAGE_DE_DE #include "explorer-de.rc" #endif @@ -164,6 +161,9 @@ CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "explorer.exe.manifest" /* UTF-8 */ #pragma code_page(65001) +#ifdef LANGUAGE_CS_CZ + #include "explorer-cz.rc" +#endif #ifdef LANGUAGE_HE_IL #include "explorer-he.rc" #endif diff --git a/base/system/rundll32/lang/tr-TR.rc b/base/system/rundll32/lang/tr-TR.rc index 65b747ef844..e33c668bc4e 100644 --- a/base/system/rundll32/lang/tr-TR.rc +++ b/base/system/rundll32/lang/tr-TR.rc @@ -3,6 +3,6 @@ LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT STRINGTABLE BEGIN - IDS_DllNotLoaded """%s"" kitaplığı yüklenemedi." - IDS_MissingEntry "%s giriş noktası %s içinde bulunamadı." + IDS_DllNotLoaded "LoadLibrary, ""%s"" kitaplığını yüklemede başarısız oldu." + IDS_MissingEntry "%s içinde %s giriş noktası eksik." END diff --git a/base/system/rundll32/rundll32.rc b/base/system/rundll32/rundll32.rc index 3a4b4de56d4..19f7703d58a 100644 --- a/base/system/rundll32/rundll32.rc +++ b/base/system/rundll32/rundll32.rc @@ -67,15 +67,15 @@ #ifdef LANGUAGE_SK_SK #include "lang/sk-SK.rc" #endif +#ifdef LANGUAGE_SQ_AL + #include "lang/sq-AL.rc" +#endif #ifdef LANGUAGE_TH_TH #include "lang/th-TH.rc" #endif #ifdef LANGUAGE_TR_TR #include "lang/tr-TR.rc" #endif -#ifdef LANGUAGE_SQ_AL - #include "lang/sq-AL.rc" -#endif #ifdef LANGUAGE_UK_UA #include "lang/uk-UA.rc" #endif diff --git a/base/system/runonce/lang/tr-TR.rc b/base/system/runonce/lang/tr-TR.rc index 1e629c8c447..76de1eab405 100644 --- a/base/system/runonce/lang/tr-TR.rc +++ b/base/system/runonce/lang/tr-TR.rc @@ -7,7 +7,7 @@ STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYS CAPTION "ReactOS Kur" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "ReactOS, şimdi aşağıdaki ayarlamaları yapıyor:", -1, 38, 8, 196, 18 + LTEXT "ReactOS şimdi aşağıdaki öğeleri kuruyor:", -1, 38, 8, 196, 18 LISTBOX IDC_COMP_LIST, 36, 32, 197, 131, LBS_OWNERDRAWVARIABLE | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP ICON IDI_ICON, -1, 5, 6, 21, 20 END diff --git a/base/system/runonce/runonce.rc b/base/system/runonce/runonce.rc index 5ed0a8f69c6..3ca6be68c51 100644 --- a/base/system/runonce/runonce.rc +++ b/base/system/runonce/runonce.rc @@ -48,12 +48,12 @@ IDI_ICON ICON "res/icon.ico" #ifdef LANGUAGE_SK_SK #include "lang/sk-SK.rc" #endif -#ifdef LANGUAGE_TR_TR - #include "lang/tr-TR.rc" -#endif #ifdef LANGUAGE_SQ_AL #include "lang/sq-AL.rc" #endif +#ifdef LANGUAGE_TR_TR + #include "lang/tr-TR.rc" +#endif #ifdef LANGUAGE_UK_UA #include "lang/uk-UA.rc" #endif diff --git a/base/system/userinit/lang/tr-TR.rc b/base/system/userinit/lang/tr-TR.rc index c7d2d068ff4..870c00f1342 100644 --- a/base/system/userinit/lang/tr-TR.rc +++ b/base/system/userinit/lang/tr-TR.rc @@ -4,5 +4,5 @@ LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT STRINGTABLE BEGIN - STRING_USERINIT_FAIL "Userinit, kabuğu başlatamadı!\n" + STRING_USERINIT_FAIL "Userinit, kabuğu başlatmada başarısız oldu!\n" END diff --git a/base/system/userinit/userinit.rc b/base/system/userinit/userinit.rc index 20f5fa53937..5b573e5c3ad 100644 --- a/base/system/userinit/userinit.rc +++ b/base/system/userinit/userinit.rc @@ -70,6 +70,9 @@ #ifdef LANGUAGE_SK_SK #include "lang/sk-SK.rc" #endif +#ifdef LANGUAGE_SQ_AL + #include "lang/sq-AL.rc" +#endif #ifdef LANGUAGE_SV_SE #include "lang/sv-SE.rc" #endif @@ -79,9 +82,6 @@ #ifdef LANGUAGE_TR_TR #include "lang/tr-TR.rc" #endif -#ifdef LANGUAGE_SQ_AL - #include "lang/sq-AL.rc" -#endif #ifdef LANGUAGE_UK_UA #include "lang/uk-UA.rc" #endif diff --git a/base/system/winlogon/lang/tr-TR.rc b/base/system/winlogon/lang/tr-TR.rc index 8ea502ef894..b919dcb19c5 100644 --- a/base/system/winlogon/lang/tr-TR.rc +++ b/base/system/winlogon/lang/tr-TR.rc @@ -7,7 +7,7 @@ STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPT CAPTION "Bilgisayarı Kapat" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Şimdi bilgisayarınızı kapatabilirsiniz.", IDC_SHUTDOWNCOMPUTER, 31, 13, 132, 8 + LTEXT "Şimdi bilgisayarınızı kapatmak güvenlidir.", IDC_SHUTDOWNCOMPUTER, 31, 13, 132, 8 ICON IDI_WINLOGON, IDC_SHTDOWNICON, 6, 7, 18, 20 DEFPUSHBUTTON "&Yeniden Başlat", IDC_BTNSHTDOWNCOMPUTER, 62, 32, 40, 14 END @@ -17,8 +17,8 @@ STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPT CAPTION "Kullanıcı Arayüzü Yanlışlığı" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Oturum Açma Kullanıcı Arayüzü DLL'si (%s) yüklenemedi.", IDC_GINALOADFAILED, 39, 16, 156, 24 - LTEXT "DLL'nin yenilenmesi için dizge yöneticinize başvurunuz.", IDC_GINALOADFAILEDCONTACT, 39, 53, 151, 25 + LTEXT "Oturum Açma Kullanıcı Arayüzü %s DLL'si yüklemede başarısız oldu.", IDC_GINALOADFAILED, 39, 16, 156, 24 + LTEXT "DLL'yi yenisiyle değiştirmek veyâ özgün DLL'yi onarmak için dizge yöneticinize başvurunuz.", IDC_GINALOADFAILEDCONTACT, 39, 53, 151, 25 DEFPUSHBUTTON "&Yeniden Başlat", 1, 80, 91, 68, 14 END @@ -26,21 +26,21 @@ STRINGTABLE BEGIN IDS_PREPARENETWORKCONNECTIONS "Ağ Bağlantıları Anıklanıyor..." IDS_APPLYINGCOMPUTERSETTINGS "Bilgisayar Ayarları Uygulanıyor..." - IDS_RUNNINGSTARTUPSCRIPTS "Bilgisayarı Açma Betikleri Çalıştırılıyor..." - IDS_RUNNINGSHUTDOWNSCRIPTS "Bilgisayarı Kapama Betikleri Çalıştırılıyor..." - IDS_APPLYINGYOURPERSONALSETTINGS "Kullanıcı Ayarlarınız Uygulanıyor..." + IDS_RUNNINGSTARTUPSCRIPTS "Açılış Betikleri Çalıştırılıyor..." + IDS_RUNNINGSHUTDOWNSCRIPTS "Kapanış Betikleri Çalıştırılıyor..." + IDS_APPLYINGYOURPERSONALSETTINGS "Şahsî Ayarlarınız Uygulanıyor..." IDS_RUNNINGLOGOFFSCRIPTS "Oturum Kapama Betikleri Çalıştırılıyor..." IDS_RUNNINGLOGONSCRIPTS "Oturum Açma Betikleri Çalıştırılıyor..." - IDS_LOADINGYOURPERSONALSETTINGS "Kullanıcı Ayarlarınız Yükleniyor..." + IDS_LOADINGYOURPERSONALSETTINGS "Şahsî Ayarlarınız Yükleniyor..." IDS_CLOSINGNETWORKCONNECTIONS "Ağ Bağlantıları Kapatılıyor..." IDS_REACTOSISSHUTTINGDOWN "ReactOS Kapatılıyor..." - IDS_PREPARETOSTANDBY "Uyku Kipine Geçiliyor..." - IDS_PREPARETOHIBERNATE "Anıkta Beklemeye Geçiliyor..." + IDS_PREPARETOSTANDBY "Beklemeye Anıklanıyor..." + IDS_PREPARETOHIBERNATE "Anıkta Beklemeye Anıklanıyor..." IDS_SAVEYOURSETTINGS "Ayarlarınız Kaydediliyor..." IDS_REACTOSISSTARTINGUP "ReactOS Başlatılıyor..." END STRINGTABLE BEGIN - IDS_FAILEDACTIVATEUSERSHELL "Winlogon, kullanıcı kabuğunu etkinleştiremedi." + IDS_FAILEDACTIVATEUSERSHELL "Winlogon, kullanıcı kabuğunu etkinleştirmede başarısız oldu." END diff --git a/base/system/winlogon/winlogon.rc b/base/system/winlogon/winlogon.rc index 1a68945b555..d3c4747160c 100644 --- a/base/system/winlogon/winlogon.rc +++ b/base/system/winlogon/winlogon.rc @@ -74,18 +74,18 @@ IDI_WINLOGON ICON "resources/winlogon.ico" #ifdef LANGUAGE_RU_RU #include "lang/ru-RU.rc" #endif -#ifdef LANGUAGE_SV_SE - #include "lang/sv-SE.rc" -#endif #ifdef LANGUAGE_SK_SK #include "lang/sk-SK.rc" #endif -#ifdef LANGUAGE_TR_TR - #include "lang/tr-TR.rc" -#endif #ifdef LANGUAGE_SQ_AL #include "lang/sq-AL.rc" #endif +#ifdef LANGUAGE_SV_SE + #include "lang/sv-SE.rc" +#endif +#ifdef LANGUAGE_TR_TR + #include "lang/tr-TR.rc" +#endif #ifdef LANGUAGE_UK_UA #include "lang/uk-UA.rc" #endif diff --git a/cmake/msvc.cmake b/cmake/msvc.cmake index 18121baf88c..7d3cedd4522 100644 --- a/cmake/msvc.cmake +++ b/cmake/msvc.cmake @@ -56,7 +56,8 @@ add_compile_flags("/wd4290") # - C4163: 'identifier': not available as an intrinsic function # - C4229: modifiers on data are ignored # - C4700: uninitialized variable usage -add_compile_flags("/we4013 /we4020 /we4022 /we4047 /we4098 /we4113 /we4129 /we4163 /we4229 /we4700") +# - C4603: macro is not defined or definition is different after precompiled header use +add_compile_flags("/we4013 /we4020 /we4022 /we4047 /we4098 /we4113 /we4129 /we4163 /we4229 /we4700 /we4603") # Enable warnings above the default level, but don't treat them as errors: # - C4115: named type definition in parentheses diff --git a/dll/cpl/access/access.rc b/dll/cpl/access/access.rc index 614340b9540..3f9530afdfc 100644 --- a/dll/cpl/access/access.rc +++ b/dll/cpl/access/access.rc @@ -19,9 +19,6 @@ IDI_CPLACCESS ICON "resources/applet.ico" #ifdef LANGUAGE_BG_BG #include "lang/bg-BG.rc" #endif -#ifdef LANGUAGE_CS_CZ - #include "lang/cs-CZ.rc" -#endif #ifdef LANGUAGE_DE_DE #include "lang/de-DE.rc" #endif @@ -62,6 +59,9 @@ IDI_CPLACCESS ICON "resources/applet.ico" /* UTF-8 */ #pragma code_page(65001) +#ifdef LANGUAGE_CS_CZ + #include "lang/cs-CZ.rc" +#endif #ifdef LANGUAGE_HE_IL #include "lang/he-IL.rc" #endif diff --git a/dll/cpl/access/lang/cs-CZ.rc b/dll/cpl/access/lang/cs-CZ.rc index a7c5147cc66..0b29558454b 100644 --- a/dll/cpl/access/lang/cs-CZ.rc +++ b/dll/cpl/access/lang/cs-CZ.rc @@ -2,25 +2,25 @@ LANGUAGE LANG_CZECH, SUBLANG_DEFAULT IDD_PROPPAGEKEYBOARD DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Klvesnice" +CAPTION "Klávesnice" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN - GROUPBOX "Jednm prstem", -1, PROPSHEETPADDING(1), LABELLINE(1), PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(6) + PROPSHEETPADDING(1) - LTEXT "Tuto funkci pouijte, pokud chcete pouvat Shift, Ctrl nebo Alt stisknutm pouze jedn klvesy najednou.", + GROUPBOX "Jedním prstem", -1, PROPSHEETPADDING(1), LABELLINE(1), PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(6) + PROPSHEETPADDING(1) + LTEXT "Tuto funkci použijte, pokud chcete používat Shift, Ctrl nebo Alt stisknutím pouze jedné klávesy najednou.", -1, PROPSHEETPADDING(2), LABELLINE(2), PROPSHEETWIDTH - PROPSHEETPADDING(4), LABELLINE(3) - AUTOCHECKBOX "Pouvat funkci &Jednm prstem", IDC_STICKY_BOX, PROPSHEETPADDING(2), LABELLINE(5) + 2, PROPSHEETWIDTH - PROPSHEETPADDING(20), 14 - PUSHBUTTON "&Nastaven", IDC_STICKY_BUTTON, PROPSHEETWIDTH - PROPSHEETPADDING(17), LABELLINE(5) + 2, PROPSHEETPADDING(15), 14 - GROUPBOX "Filtrovn klves", -1, PROPSHEETPADDING(1), LABELLINE(8) + 5, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(7) + 2 - LTEXT "Pouijte funkci Filtrovn klves, pokud chcete, aby ReactOS ignoroval nhodn nebo opakovan stisknut klves.", + AUTOCHECKBOX "Používat funkci &Jedním prstem", IDC_STICKY_BOX, PROPSHEETPADDING(2), LABELLINE(5) + 2, PROPSHEETWIDTH - PROPSHEETPADDING(20), 14 + PUSHBUTTON "&Nastavení", IDC_STICKY_BUTTON, PROPSHEETWIDTH - PROPSHEETPADDING(17), LABELLINE(5) + 2, PROPSHEETPADDING(15), 14 + GROUPBOX "Filtrování kláves", -1, PROPSHEETPADDING(1), LABELLINE(8) + 5, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(7) + 2 + LTEXT "Použijte funkci Filtrování kláves, pokud chcete, aby ReactOS ignoroval náhodná nebo opakovaná stisknutí kláves.", -1, PROPSHEETPADDING(2), LABELLINE(10) - 3, PROPSHEETWIDTH - PROPSHEETPADDING(4), LABELLINE(3) - AUTOCHECKBOX "Pouvat funkci &Filtrovn klves", IDC_FILTER_BOX, PROPSHEETPADDING(2), LABELLINE(13) + 2, PROPSHEETWIDTH - PROPSHEETPADDING(20), 14 - PUSHBUTTON "N&astaven", IDC_FILTER_BUTTON, PROPSHEETWIDTH - PROPSHEETPADDING(17), LABELLINE(13) + 2, PROPSHEETPADDING(15), 14 - GROUPBOX "Ozvuen klves", -1, PROPSHEETPADDING(1), LABELLINE(16) + 3, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(6) + PROPSHEETPADDING(1) - LTEXT "Pouijte funkci Ozvuen klves, chcete-li bt upozornni na stisk klves Caps Lock, Num Lock a Scroll Lock zvukovm signlem.", + AUTOCHECKBOX "Používat funkci &Filtrování kláves", IDC_FILTER_BOX, PROPSHEETPADDING(2), LABELLINE(13) + 2, PROPSHEETWIDTH - PROPSHEETPADDING(20), 14 + PUSHBUTTON "N&astavení", IDC_FILTER_BUTTON, PROPSHEETWIDTH - PROPSHEETPADDING(17), LABELLINE(13) + 2, PROPSHEETPADDING(15), 14 + GROUPBOX "Ozvučení kláves", -1, PROPSHEETPADDING(1), LABELLINE(16) + 3, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(6) + PROPSHEETPADDING(1) + LTEXT "Použijte funkci Ozvučení kláves, chcete-li být upozorněni na stisk kláves Caps Lock, Num Lock a Scroll Lock zvukovým signálem.", -1, PROPSHEETPADDING(2), LABELLINE(18) - 3, PROPSHEETWIDTH - PROPSHEETPADDING(4), LABELLINE(2) + 6 - AUTOCHECKBOX "Pouvat funkci O&zvuen klves", IDC_TOGGLE_BOX, PROPSHEETPADDING(2), LABELLINE(20) + 4, PROPSHEETWIDTH - PROPSHEETPADDING(20), 14 - PUSHBUTTON "Na&staven", IDC_TOGGLE_BUTTON, PROPSHEETWIDTH - PROPSHEETPADDING(17), LABELLINE(20) + 4, PROPSHEETPADDING(15), 14 - AUTOCHECKBOX "&V programech zobrazovat dodatenou npovdu ke klvesm.", IDC_KEYBOARD_EXTRA, + AUTOCHECKBOX "Používat funkci O&zvučení kláves", IDC_TOGGLE_BOX, PROPSHEETPADDING(2), LABELLINE(20) + 4, PROPSHEETWIDTH - PROPSHEETPADDING(20), 14 + PUSHBUTTON "Na&stavení", IDC_TOGGLE_BUTTON, PROPSHEETWIDTH - PROPSHEETPADDING(17), LABELLINE(20) + 4, PROPSHEETPADDING(15), 14 + AUTOCHECKBOX "&V programech zobrazovat dodatečnou nápovědu ke klávesám.", IDC_KEYBOARD_EXTRA, PROPSHEETPADDING(1), LABELLINE(23) + 3, PROPSHEETWIDTH - PROPSHEETPADDING(2), 14 END @@ -30,28 +30,28 @@ CAPTION "Zvuk" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN GROUPBOX "Funkce Popis zvuku", -1, PROPSHEETPADDING(1), LABELLINE(1), PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(10) + PROPSHEETPADDING(1) - LTEXT "Pouijte funkci Zobrazen zvuku, pokud chcete aby ReactOS vizuln upozoroval na kad zvuk vydan systmem.", + LTEXT "Použijte funkci Zobrazení zvuku, pokud chcete aby ReactOS vizuálně upozorňoval na každý zvuk vydaný systémem.", -1, PROPSHEETPADDING(2), LABELLINE(2), PROPSHEETWIDTH - PROPSHEETPADDING(4), LABELLINE(3) - AUTOCHECKBOX "&Pouvat funkci Popis zvuku", IDC_SENTRY_BOX, PROPSHEETPADDING(2), LABELLINE(5) + 2, PROPSHEETPADDING(20), 14 + AUTOCHECKBOX "&Používat funkci Popis zvuku", IDC_SENTRY_BOX, PROPSHEETPADDING(2), LABELLINE(5) + 2, PROPSHEETPADDING(20), 14 LTEXT "Use the following warning:", IDC_SENTRY_TEXT, PROPSHEETPADDING(2), LABELLINE(8) - 2, PROPSHEETWIDTH - PROPSHEETPADDING(4), LABELLINE(1) COMBOBOX IDC_SENTRY_COMBO, PROPSHEETPADDING(2), LABELLINE(9), PROPSHEETWIDTH - PROPSHEETPADDING(4), LABELLINE(6), CBS_DROPDOWNLIST | WS_VSCROLL | WS_VISIBLE | WS_TABSTOP - GROUPBOX "Funkce Zobrazen zvuku", -1, PROPSHEETPADDING(1), LABELLINE(12) + 5, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(7) + 2 - LTEXT "Pouijte Zobrazen zvuku, aby programy zobrazovaly textov popis zrove se zvukem.", + GROUPBOX "Funkce Zobrazení zvuku", -1, PROPSHEETPADDING(1), LABELLINE(12) + 5, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(7) + 2 + LTEXT "Použijte Zobrazení zvuku, aby programy zobrazovaly textový popis zároveň se zvukem.", -1, PROPSHEETPADDING(2), LABELLINE(14) - 3, PROPSHEETWIDTH - PROPSHEETPADDING(4), LABELLINE(3) - AUTOCHECKBOX "Pouvat funkci &Zobrazen zvuku", IDC_SSHOW_BOX, PROPSHEETPADDING(2), LABELLINE(16) + 2, PROPSHEETWIDTH - PROPSHEETPADDING(4), 14 + AUTOCHECKBOX "Používat funkci &Zobrazení zvuku", IDC_SSHOW_BOX, PROPSHEETPADDING(2), LABELLINE(16) + 2, PROPSHEETWIDTH - PROPSHEETPADDING(4), 14 END IDD_PROPPAGEDISPLAY DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Zobrazen" +CAPTION "Zobrazení" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN - GROUPBOX "Funkce Vysok kontrast", -1, PROPSHEETPADDING(1), LABELLINE(1), PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(6) + PROPSHEETPADDING(1) - LTEXT "Vyberte tuto monost pokud chcete, aby Reactos pouval barvy a psma uren pro snadnou itelnost.", + GROUPBOX "Funkce Vysoký kontrast", -1, PROPSHEETPADDING(1), LABELLINE(1), PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(6) + PROPSHEETPADDING(1) + LTEXT "Vyberte tuto možnost pokud chcete, aby Reactos používal barvy a písma určené pro snadnou čitelnost.", -1, PROPSHEETPADDING(2), LABELLINE(2), PROPSHEETWIDTH - PROPSHEETPADDING(4), LABELLINE(3) - AUTOCHECKBOX "&Pout funkci Vysok kontrast", IDC_CONTRAST_BOX, PROPSHEETPADDING(2), LABELLINE(5) + 2, PROPSHEETWIDTH - PROPSHEETPADDING(20), 14 - PUSHBUTTON "&Nastaven", IDC_CONTRAST_BUTTON, PROPSHEETWIDTH - PROPSHEETPADDING(17), LABELLINE(5) + 2, PROPSHEETPADDING(15), 14 + AUTOCHECKBOX "&Použít funkci Vysoký kontrast", IDC_CONTRAST_BOX, PROPSHEETPADDING(2), LABELLINE(5) + 2, PROPSHEETWIDTH - PROPSHEETPADDING(20), 14 + PUSHBUTTON "&Nastavení", IDC_CONTRAST_BUTTON, PROPSHEETWIDTH - PROPSHEETPADDING(17), LABELLINE(5) + 2, PROPSHEETPADDING(15), 14 GROUPBOX "Cursor options", -1, PROPSHEETPADDING(1), LABELLINE(8) + 5, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(13) LTEXT "Use the track bars to modify the blinking speed of the cursor and its width.", -1, PROPSHEETPADDING(2), LABELLINE(9) + 5, PROPSHEETWIDTH - PROPSHEETPADDING(4), LABELLINE(2) @@ -70,40 +70,40 @@ END IDD_PROPPAGEMOUSE DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "My" +CAPTION "Myš" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN - GROUPBOX "Funkce My klvesnic", -1, PROPSHEETPADDING(1), LABELLINE(1), PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(6) + PROPSHEETPADDING(1) - LTEXT "Vyberte tuto monost, pokud chcete ovldat my pomoc ipek na numerick klvesnici.", + GROUPBOX "Funkce Myš klávesnicí", -1, PROPSHEETPADDING(1), LABELLINE(1), PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(6) + PROPSHEETPADDING(1) + LTEXT "Vyberte tuto možnost, pokud chcete ovládat myš pomocí šipek na numerické klávesnici.", -1, PROPSHEETPADDING(2), LABELLINE(2), PROPSHEETWIDTH - PROPSHEETPADDING(4), LABELLINE(3) - AUTOCHECKBOX "Pout funkci &My klvesnic", IDC_MOUSE_BOX, PROPSHEETPADDING(2), LABELLINE(5) + 2, PROPSHEETWIDTH - PROPSHEETPADDING(20), 14 - PUSHBUTTON "&Nastaven", IDC_MOUSE_BUTTON, PROPSHEETWIDTH - PROPSHEETPADDING(17), LABELLINE(5) + 2, PROPSHEETPADDING(15), 14 + AUTOCHECKBOX "Použít funkci &Myš klávesnicí", IDC_MOUSE_BOX, PROPSHEETPADDING(2), LABELLINE(5) + 2, PROPSHEETWIDTH - PROPSHEETPADDING(20), 14 + PUSHBUTTON "&Nastavení", IDC_MOUSE_BUTTON, PROPSHEETWIDTH - PROPSHEETPADDING(17), LABELLINE(5) + 2, PROPSHEETPADDING(15), 14 END IDD_PROPPAGEGENERAL DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Obecn" +CAPTION "Obecné" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN - GROUPBOX "Automatick vypnut", -1, PROPSHEETPADDING(1), LABELLINE(1), PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(5) - AUTOCHECKBOX "Vypnout &funkce usnadnn po neinnosti del ne:", + GROUPBOX "Automatické vypnutí", -1, PROPSHEETPADDING(1), LABELLINE(1), PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(5) + AUTOCHECKBOX "Vypnout &funkce usnadnění po nečinnosti delší než:", IDC_RESET_BOX, PROPSHEETPADDING(2), LABELLINE(2) - 2, PROPSHEETWIDTH - PROPSHEETPADDING(4), 14 COMBOBOX IDC_RESET_COMBO, PROPSHEETPADDING(4), LABELLINE(4), PROPSHEETPADDING(10), LABELLINE(5), CBS_DROPDOWNLIST | WS_VSCROLL | WS_VISIBLE | WS_TABSTOP - GROUPBOX "Upozornn", -1, PROPSHEETPADDING(1), LABELLINE(7) - 2, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(5) - AUTOCHECKBOX "Pi zapnut funkce zobrazit upozornn.", IDC_NOTIFICATION_MESSAGE, + GROUPBOX "Upozornění", -1, PROPSHEETPADDING(1), LABELLINE(7) - 2, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(5) + AUTOCHECKBOX "Při zapnutí funkce zobrazit upozornění.", IDC_NOTIFICATION_MESSAGE, PROPSHEETPADDING(2), LABELLINE(8) - 2, PROPSHEETWIDTH - PROPSHEETPADDING(4), 14 - AUTOCHECKBOX "Upozornit na zapnut nebo vypnut funkce usnadnn zvukem.", IDC_NOTIFICATION_SOUND, + AUTOCHECKBOX "Upozornit na zapnutí nebo vypnutí funkce usnadnění zvukem.", IDC_NOTIFICATION_SOUND, PROPSHEETPADDING(2), LABELLINE(10) - 2, PROPSHEETWIDTH - PROPSHEETPADDING(4), 14 GROUPBOX "Funkce SerialKey", -1, PROPSHEETPADDING(1), LABELLINE(13) - 4, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(5) - LTEXT "Funkce SerialKey Vm umon alternativn pstup k funkcm myi a klvesnice.", + LTEXT "Funkce SerialKey Vám umožní alternativní přístup k funkcím myši a klávesnice.", -1, PROPSHEETPADDING(2), LABELLINE(14) - 4, PROPSHEETWIDTH - PROPSHEETPADDING(4), LABELLINE(2) - AUTOCHECKBOX "Pout funkci &SerialKey", IDC_SERIAL_BOX, PROPSHEETPADDING(2), LABELLINE(16) - 4, PROPSHEETWIDTH - PROPSHEETPADDING(20), 14 - PUSHBUTTON "Na&staven", IDC_SERIAL_BUTTON, PROPSHEETWIDTH - PROPSHEETPADDING(17), LABELLINE(16) - 4, PROPSHEETPADDING(15), 14 - GROUPBOX "Monosti sprvy", -1, PROPSHEETPADDING(1), LABELLINE(19) - 4, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(5) - AUTOCHECKBOX "Pout &nastaven pi pihlen.", IDC_ADMIN_LOGON_BOX, + AUTOCHECKBOX "Použít funkci &SerialKey", IDC_SERIAL_BOX, PROPSHEETPADDING(2), LABELLINE(16) - 4, PROPSHEETWIDTH - PROPSHEETPADDING(20), 14 + PUSHBUTTON "Na&stavení", IDC_SERIAL_BUTTON, PROPSHEETWIDTH - PROPSHEETPADDING(17), LABELLINE(16) - 4, PROPSHEETPADDING(15), 14 + GROUPBOX "Možnosti správy", -1, PROPSHEETPADDING(1), LABELLINE(19) - 4, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(5) + AUTOCHECKBOX "Použít &nastavení při přihlášení.", IDC_ADMIN_LOGON_BOX, PROPSHEETPADDING(2), LABELLINE(20) - 4, PROPSHEETWIDTH - PROPSHEETPADDING(4), 14 - AUTOCHECKBOX "Po&ut nastaven jako vchoz pro nov uivatele.", IDC_ADMIN_USERS_BOX, + AUTOCHECKBOX "Po&užít nastavení jako výchozí pro nové uživatele.", IDC_ADMIN_USERS_BOX, PROPSHEETPADDING(2), LABELLINE(22) - 4, PROPSHEETWIDTH - PROPSHEETPADDING(4), 14 END @@ -280,8 +280,8 @@ END STRINGTABLE BEGIN - IDS_CPLSYSTEMNAME "Monosti usnadnn" - IDS_CPLSYSTEMDESCRIPTION "Uprav monosti usnadnn pro tento pota." + IDS_CPLSYSTEMNAME "Možnosti usnadnění" + IDS_CPLSYSTEMDESCRIPTION "Upraví možnosti usnadnění pro tento počítač." IDS_SENTRY_NONE "[None]" IDS_SENTRY_TITLE "Flash the titlebar" IDS_SENTRY_WINDOW "Flash the active window" diff --git a/dll/cpl/hdwwiz/hdwwiz.rc b/dll/cpl/hdwwiz/hdwwiz.rc index 48d3922190e..ad82b37eaf2 100644 --- a/dll/cpl/hdwwiz/hdwwiz.rc +++ b/dll/cpl/hdwwiz/hdwwiz.rc @@ -25,9 +25,6 @@ IDB_HEADER BITMAP "resources/header.bmp" #ifdef LANGUAGE_BG_BG #include "lang/bg-BG.rc" #endif -#ifdef LANGUAGE_CS_CZ - #include "lang/cs-CZ.rc" -#endif #ifdef LANGUAGE_DE_DE #include "lang/de-DE.rc" #endif @@ -80,6 +77,9 @@ IDB_HEADER BITMAP "resources/header.bmp" /* UTF-8 */ #pragma code_page(65001) +#ifdef LANGUAGE_CS_CZ + #include "lang/cs-CZ.rc" +#endif #ifdef LANGUAGE_HE_IL #include "lang/he-IL.rc" #endif diff --git a/dll/cpl/hdwwiz/lang/cs-CZ.rc b/dll/cpl/hdwwiz/lang/cs-CZ.rc index b2680d1b72d..c0b30f246b6 100644 --- a/dll/cpl/hdwwiz/lang/cs-CZ.rc +++ b/dll/cpl/hdwwiz/lang/cs-CZ.rc @@ -1,27 +1,27 @@ /* FILE: dll/cpl/hdwwiz/lang/cs-CZ.rc * TRANSLATOR: Radek Liska aka Black_Fox (radekliska at gmail dot com) - * UPDATED: 2009-02-03 + * UPDATED: 2014-04-25 */ LANGUAGE LANG_CZECH, SUBLANG_DEFAULT IDD_STARTPAGE DIALOG 0, 0, 317, 186 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Prvodce pidnm hardwaru" +CAPTION "Průvodce přidáním hardwaru" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Vtejte v Prvodci pidnm hardwaru", IDC_FINISHTITLE, 114, 8, 203, 24 - LTEXT "Tento prvodce vm pome:", -1, 114, 40, 182, 8 - LTEXT "1) Nainstalovat software pro podporu hardwaru pidanho do potae.", -1, 121, 56, 184, 16 - LTEXT "2) Vyeit problmy, kter mete s vam hardwarem mt.", -1, 121, 78, 185, 16 + LTEXT "Vítejte v Průvodci přidáním hardwaru", IDC_FINISHTITLE, 114, 8, 203, 24 + LTEXT "Tento průvodce vám pomůže:", -1, 114, 40, 182, 8 + LTEXT "1) Nainstalovat software pro podporu hardwaru přidaného do počítače.", -1, 121, 56, 184, 16 + LTEXT "2) Vyřešit problémy, které můžete s vaším hardwarem mít.", -1, 121, 78, 185, 16 ICON IDI_WARNINGICON, IDC_WARNINGICON, 124, 109, 20, 20 - LTEXT "Pokud bylo k hardwaru pibaleno instalan CD, doporuuje se ukonit tohoto prvodce klepnutm na tlatko Storno a pout k instalaci hardwaru toto CD.", 503, 150, 106, 155, 50 - LTEXT "Pokraujte klepnutm na tlatko Dal.", -1, 114, 166, 193, 8 + LTEXT "Pokud bylo k hardwaru přibaleno instalační CD, doporučuje se ukončit tohoto průvodce klepnutím na tlačítko Storno a použít k instalaci hardwaru toto CD.", 503, 150, 106, 155, 50 + LTEXT "Pokračujte klepnutím na tlačítko Další.", -1, 114, 166, 193, 8 END IDD_SEARCHPAGE DIALOG 0, 0, 317, 143 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Prvodce pidnm hardwaru" +CAPTION "Průvodce přidáním hardwaru" FONT 8, "MS Shell Dlg" BEGIN LTEXT "", IDC_STATUSTEXT, 21, 8, 275, 32 @@ -30,63 +30,63 @@ END IDD_ISCONNECTEDPAGE DIALOG 0, 0, 317, 143 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Prvodce pidnm hardwaru" +CAPTION "Průvodce přidáním hardwaru" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Byl ji tento hardware pipojen k tomuto potai?", -1, 20, 11, 275, 8 - AUTORADIOBUTTON "&Ano, ji byl pipojen", IDC_CONNECTED, 29, 23, 266, 8, WS_GROUP - AUTORADIOBUTTON "&Ne, jet nebyl pidn", IDC_NOTCONNECTED, 29, 35, 266, 8 + LTEXT "Byl již tento hardware připojen k tomuto počítači?", -1, 20, 11, 275, 8 + AUTORADIOBUTTON "&Ano, již byl připojen", IDC_CONNECTED, 29, 23, 266, 8, WS_GROUP + AUTORADIOBUTTON "&Ne, ještě nebyl přidán", IDC_NOTCONNECTED, 29, 35, 266, 8 END IDD_PROBELISTPAGE DIALOG 0, 0, 317, 143 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Prvodce pidnm hardwaru" +CAPTION "Průvodce přidáním hardwaru" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Vyberte nainstalovan zazen ze seznamu ne, pot lze klepnutm na tlatko Dal zkontrolovat jeho vlastnosti nebo zjistit een monch problm.", -1, 21, 8, 275, 22 - LTEXT "Klepnutm na ""Pidat nov zazen."" pidte hardware, kter se v tomto seznamu nenachz.", -1, 21, 32, 275, 24 - LTEXT "Nai&nstalovan hardware:", -1, 21, 62, 140, 8 + LTEXT "Vyberte nainstalované zařízení ze seznamu níže, poté lze klepnutím na tlačítko Další zkontrolovat jeho vlastnosti nebo zjistit řešení možných problémů.", -1, 21, 8, 275, 22 + LTEXT "Klepnutím na ""Přidat nové zařízení."" přidáte hardware, který se v tomto seznamu nenachází.", -1, 21, 32, 275, 24 + LTEXT "Nai&nstalovaný hardware:", -1, 21, 62, 140, 8 CONTROL "", IDC_PROBELIST, "SysListView32", WS_BORDER | WS_GROUP | WS_TABSTOP | LVS_REPORT | LVS_NOSORTHEADER | LVS_SINGLESEL | LVS_SHAREIMAGELISTS | LVS_NOCOLUMNHEADER, 21, 72, 275, 66 END IDD_SELECTWAYPAGE DIALOG 0, 0, 317, 143 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Prvodce pidnm hardwaru" +CAPTION "Průvodce přidáním hardwaru" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Prvodce me vyhledat dal hardware a automaticky ho nainstalovat, nebo jej mete vybrat ze seznamu, pokud vte o kter model se jedn.", -1, 21, 8, 280, 24 - LTEXT "Co m prvodce udlat?", -1, 23, 40, 275, 8 - AUTORADIOBUTTON "&Vyhledat a automaticky nainstalovat hardware (doporueno)", IDC_AUTOINSTALL, 30, 55, 266, 8, WS_GROUP | NOT WS_TABSTOP - AUTORADIOBUTTON "Nainstalovat hardware, kter si &run zvolm ze seznamu (pokroil)", IDC_MANUALLYINST, 30, 70, 266, 8, NOT WS_TABSTOP + LTEXT "Průvodce může vyhledat další hardware a automaticky ho nainstalovat, nebo jej můžete vybrat ze seznamu, pokud víte o který model se jedná.", -1, 21, 8, 280, 24 + LTEXT "Co má průvodce udělat?", -1, 23, 40, 275, 8 + AUTORADIOBUTTON "&Vyhledat a automaticky nainstalovat hardware (doporučeno)", IDC_AUTOINSTALL, 30, 55, 266, 8, WS_GROUP | NOT WS_TABSTOP + AUTORADIOBUTTON "Nainstalovat hardware, který si &ručně zvolím ze seznamu (pokročilé)", IDC_MANUALLYINST, 30, 70, 266, 8, NOT WS_TABSTOP END IDD_DETECTEDHWPAGE DIALOG 0, 0, 317, 143 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Prvodce pidnm hardwaru" +CAPTION "Průvodce přidáním hardwaru" FONT 8, "MS Shell Dlg" BEGIN LTEXT "", IDC_STATUSTEXT, 21, 9, 275, 40 - LTEXT "Detekovan hardware:", IDC_DETECTEDHWTEXT, 21, 53, 176, 8 + LTEXT "Detekovaný hardware:", IDC_DETECTEDHWTEXT, 21, 53, 176, 8 CONTROL "", IDC_DETECTEDHWLIST, "SysListView32", WS_BORDER | WS_GROUP | WS_TABSTOP | LVS_REPORT | LVS_NOSORTHEADER | LVS_SINGLESEL | LVS_SHAREIMAGELISTS | LVS_NOCOLUMNHEADER, 21, 65, 275, 70 END IDD_HWTYPESPAGE DIALOG 0, 0, 317, 143 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Prvodce pidnm hardwaru" +CAPTION "Průvodce přidáním hardwaru" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Pokud nevidte vmi hledan typ hardwaru, klepnte na Zobrazit vechna zazen.", IDC_STATUSTEXT, 21, 9, 275, 18 - LTEXT "Bn typy &hardwaru:", IDC_HWTYPESTEXT, 21, 31, 180, 8 + LTEXT "Pokud nevidíte vámi hledaný typ hardwaru, klepněte na Zobrazit všechna zařízení.", IDC_STATUSTEXT, 21, 9, 275, 18 + LTEXT "Běžné typy &hardwaru:", IDC_HWTYPESTEXT, 21, 31, 180, 8 CONTROL "", IDC_HWTYPESLIST, "SysListView32", WS_BORDER | WS_GROUP | WS_TABSTOP | LVS_REPORT | LVS_NOSORTHEADER | LVS_SINGLESEL | LVS_SHAREIMAGELISTS | LVS_NOCOLUMNHEADER, 21, 42, 275, 92 END IDD_PROGRESSPAGE DIALOG 0, 0, 317, 143 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Prvodce pidnm hardwaru" +CAPTION "Průvodce přidáním hardwaru" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Vyhledvn hardwaru me trvat nkolik minut.", -1, 21, 8, 275, 15 - LTEXT "Celkov postup:", IDC_TPROGRESSTEXT, 21, 25, 275, 8 + LTEXT "Vyhledávání hardwaru může trvat několik minut.", -1, 21, 8, 275, 15 + LTEXT "Celkový postup:", IDC_TPROGRESSTEXT, 21, 25, 275, 8 CONTROL "", IDC_TPROGRESSBAR, "msctls_progress32", 0, 21, 37, 275, 14 LTEXT "", IDC_PROGRESSTEXT, 58, 58, 200, 8, SS_NOPREFIX CONTROL "", IDC_PROGRESSBAR, "msctls_progress32", 0, 58, 70, 200, 8 @@ -94,59 +94,59 @@ END IDD_FINISHPAGE DIALOG 0, 0, 317, 186 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Prvodce pidnm hardwaru" +CAPTION "Průvodce přidáním hardwaru" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Dokonen Prvodce pidnm hardwaru", IDC_FINISHTITLE, 114, 8, 203, 24 - LTEXT "Prvodce pidnm hardwaru byl spn dokonen.", -1, 114, 32, 193, 19 + LTEXT "Dokončení Průvodce přidáním hardwaru", IDC_FINISHTITLE, 114, 8, 203, 24 + LTEXT "Průvodce přidáním hardwaru byl úspěšně dokončen.", -1, 114, 32, 193, 19 LTEXT "", IDC_STATUSTEXT, 114, 70, 193, 92 - LTEXT "Klepnutm na Dokonit uzavete prvodce.", -1, 114, 166, 132, 8 + LTEXT "Klepnutím na Dokončit uzavřete průvodce.", -1, 114, 166, 132, 8 END IDD_ISFOUNDPAGE DIALOG 0, 0, 317, 186 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Prvodce pidnm hardwaru" +CAPTION "Průvodce přidáním hardwaru" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Dokonen Prvodce pidnm hardwaru", IDC_FINISHTITLE, 114, 8, 203, 24 - LTEXT "Prvodce nael nsledujc hardware pipojen k tomuto potai:", -1, 114, 32, 193, 19 - LTEXT "Klepnutm na Dokonit uzavete prvodce.", -1, 114, 166, 132, 8 + LTEXT "Dokončení Průvodce přidáním hardwaru", IDC_FINISHTITLE, 114, 8, 203, 24 + LTEXT "Průvodce našel následující hardware připojený k tomuto počítači:", -1, 114, 32, 193, 19 + LTEXT "Klepnutím na Dokončit uzavřete průvodce.", -1, 114, 166, 132, 8 CONTROL "", IDC_FOUNDHARDWARELIST, "SysListView32", WS_BORDER | WS_GROUP | WS_TABSTOP | LVS_REPORT | LVS_NOSORTHEADER | LVS_SINGLESEL | LVS_SHAREIMAGELISTS, 114, 56, 193, 78 END IDD_HWSTATUSPAGE DIALOG 0, 0, 317, 186 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Prvodce pidnm hardwaru" +CAPTION "Průvodce přidáním hardwaru" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Dokonen Prvodce pidnm hardwaru", IDC_FINISHTITLE, 114, 8, 195, 28 - LTEXT "Souasn stav zvolenho hardwaru:", -1, 114, 40, 193, 19 + LTEXT "Dokončení Průvodce přidáním hardwaru", IDC_FINISHTITLE, 114, 8, 195, 28 + LTEXT "Současný stav zvoleného hardwaru:", -1, 114, 40, 193, 19 EDITTEXT IDC_HWSTATUSEDIT, 114, 60, 193, 70, ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | WS_VSCROLL | NOT WS_TABSTOP - LTEXT "Klepnutm na Dokonit lze zat eit mon problmy.", -1, 114, 136, 193, 16 - LTEXT "Klepnutm na Storno ukonte prvodce.", IDC_STATUSTEXT, 114, 166, 132, 8 + LTEXT "Klepnutím na Dokončit lze začít řešit možné problémy.", -1, 114, 136, 193, 16 + LTEXT "Klepnutím na Storno ukončíte průvodce.", IDC_STATUSTEXT, 114, 166, 132, 8 END IDD_NOTCONNECTEDPAGE DIALOG 0, 0, 317, 186 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Prvodce pidnm hardwaru" +CAPTION "Průvodce přidáním hardwaru" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Nelze pokraovat v Prvodci pidnm hardwaru", IDC_FINISHTITLE, 114, 8, 203, 28 - LTEXT "Pokraovat lze po pipojen hardwaru k potai.", -1, 114, 40, 193, 16 - AUTOCHECKBOX "Vypnou&t pota po klepnut na tlatko Dokonit, aby mohl bt hardware pipojen.", IDC_TURNOFFCHECKBOX, 114, 64, 203, 20, BS_TOP | BS_MULTILINE - LTEXT "Ve vtin ppad ReactOS automaticky nainstaluje hardware po jeho pipojen. Pokud jej ReactOS nenajde, lze tohoto prvodce znovu spustit a nainstalovat podprn software.", -1, 114, 98, 193, 32 - LTEXT "Klepnutm na tlatko Dokonit ukonte prvodce.", IDC_STATUSTEXT, 114, 166, 193, 8 + LTEXT "Nelze pokračovat v Průvodci přidáním hardwaru", IDC_FINISHTITLE, 114, 8, 203, 28 + LTEXT "Pokračovat lze po připojení hardwaru k počítači.", -1, 114, 40, 193, 16 + AUTOCHECKBOX "Vypnou&t počítač po klepnutí na tlačítko Dokončit, aby mohl být hardware připojen.", IDC_TURNOFFCHECKBOX, 114, 64, 203, 20, BS_TOP | BS_MULTILINE + LTEXT "Ve většině případů ReactOS automaticky nainstaluje hardware po jeho připojení. Pokud jej ReactOS nenajde, lze tohoto průvodce znovu spustit a nainstalovat podpůrný software.", -1, 114, 98, 193, 32 + LTEXT "Klepnutím na tlačítko Dokončit ukončíte průvodce.", IDC_STATUSTEXT, 114, 166, 193, 8 END STRINGTABLE BEGIN - IDS_CPLNAME "Pidat hardware" - IDS_CPLDESCRIPTION "Pid hardware do tohoto potae." - IDS_SEARCHTITLE "ekejte, prosm, prvodce hled..." - IDS_SEARCHTEXT "Tento prvodce hled hardware, kter byl nedvno pipojen k tomuto potai, ale jet nebyl nainstalovn." - IDS_ISCONNECTED "Je hardware pipojen?" - IDS_PROBELISTTITLE "Nsledujc hardware ji je nainstalovn na tomto potai" - IDS_ADDNEWDEVICE "Pidat nov hardwarov zazen" - IDS_SELECTWAYTITLE "Prvodce vm me pomoci nainstalovat jin hardware" - IDS_HDTYPESTITLE "Ze seznamu ne zvolte typ instalovanho hardwaru" + IDS_CPLNAME "Přidat hardware" + IDS_CPLDESCRIPTION "Přidá hardware do tohoto počítače." + IDS_SEARCHTITLE "Čekejte, prosím, průvodce hledá..." + IDS_SEARCHTEXT "Tento průvodce hledá hardware, který byl nedávno připojen k tomuto počítači, ale ještě nebyl nainstalován." + IDS_ISCONNECTED "Je hardware připojen?" + IDS_PROBELISTTITLE "Následující hardware již je nainstalován na tomto počítači" + IDS_ADDNEWDEVICE "Přidat nové hardwarové zařízení" + IDS_SELECTWAYTITLE "Průvodce vám může pomoci nainstalovat jiný hardware" + IDS_HDTYPESTITLE "Ze seznamu níže zvolte typ instalovaného hardwaru" END diff --git a/dll/cpl/inetcpl/inetcpl.rc b/dll/cpl/inetcpl/inetcpl.rc index b509fceb789..c44f7c627b8 100644 --- a/dll/cpl/inetcpl/inetcpl.rc +++ b/dll/cpl/inetcpl/inetcpl.rc @@ -27,6 +27,9 @@ #include +#ifdef LANGUAGE_CS_CZ + #include "lang/cs-CZ.rc" +#endif #ifdef LANGUAGE_DE_DE #include "lang/de-DE.rc" #endif diff --git a/dll/cpl/inetcpl/lang/cs-CZ.rc b/dll/cpl/inetcpl/lang/cs-CZ.rc new file mode 100644 index 00000000000..66847279e1a --- /dev/null +++ b/dll/cpl/inetcpl/lang/cs-CZ.rc @@ -0,0 +1,99 @@ +/* FILE: dll/cpl/inetcpl/lang/cs-CZ.rc + * TRANSLATOR: Radek Liska aka Black_Fox (radekliska at gmail dot com) + * UPDATED: 2014-04-21 + */ + + /* UTF-8 */ + #pragma code_page(65001) + + LANGUAGE LANG_CZECH, SUBLANG_DEFAULT + +/* "General" propsheet */ +IDD_GENERAL DIALOG 0, 0, 320, 220 +STYLE WS_CAPTION | WS_CHILD | WS_DISABLED +FONT 8, "MS Shell Dlg" +CAPTION "Obecné" +BEGIN + + GROUPBOX " Domovská stránka ", IDC_STATIC, 4, 4, 312, 52 + LTEXT "Zvolená adresa bude uložena jako domovská stránka.", + IDC_STATIC, 58, 10, 252, 10 + EDITTEXT IDC_HOME_EDIT, 58, 22, 252, 12, WS_VISIBLE | ES_AUTOHSCROLL + PUSHBUTTON "&Aktuální stránka", IDC_HOME_CURRENT, 58, 36, 80, 14 + PUSHBUTTON "&Výchozí stránka", IDC_HOME_DEFAULT, 144, 36, 80, 14 + PUSHBUTTON "&Prázdná stránka", IDC_HOME_BLANK, 230, 36, 80, 14 + GROUPBOX " Historie prohlížení ", IDC_STATIC, 4, 60, 312, 46 + LTEXT "Lze smazat stránky v mezipaměti, cookies a další data.", + IDC_STATIC, 58, 72, 252, 10 + PUSHBUTTON "Smazat &soubory...", IDC_HISTORY_DELETE, 144, 86, 80, 14 + PUSHBUTTON "&Nastavení...", IDC_HISTORY_SETTINGS, 230, 86, 80, 14 + +END + +/* "Delete browsing history" dialog */ +IDD_DELETE_HISTORY DIALOG 0, 0, 250, 250 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +FONT 8, "MS Shell Dlg" +CAPTION "Smazat historii prohlížení" +BEGIN + + AUTOCHECKBOX "Dočasné internetové soubory\nUložené kopie webových stránek, obrázků a certifikátů.", + IDC_DELETE_TEMP_FILES, 10, 8, 230, 30, BS_TOP | BS_MULTILINE + AUTOCHECKBOX "Cookies\nSoubory uložené na počítači webovými stránkami, ve kterých jsou uložené například uživatelské předvolby nebo přihlašovací údaje.", + IDC_DELETE_COOKIES, 10, 38, 230, 30, BS_TOP | BS_MULTILINE + AUTOCHECKBOX "Historie\nSeznam navštívených webových stránek.", + IDC_DELETE_HISTORY, 10, 68, 230, 30, BS_TOP | BS_MULTILINE + AUTOCHECKBOX "Data formulářů\nUživatelská jména a další údaje, které byly zadány do formulářů.", + IDC_DELETE_FORM_DATA, 10, 98, 230, 30, BS_TOP | BS_MULTILINE + AUTOCHECKBOX "Hesla\nUložená hesla, která byla zadána do formulářů.", + IDC_DELETE_PASSWORDS, 10, 128, 230, 30, BS_TOP | BS_MULTILINE + DEFPUSHBUTTON "Storno", IDCANCEL, 185, 230, 60, 15, WS_GROUP + PUSHBUTTON "Smazat", IDOK, 120, 230, 60, 15, WS_GROUP + +END + +/* "Security" propsheet */ +IDD_SECURITY DIALOG 0, 0, 320, 220 +STYLE WS_CAPTION | WS_CHILD | WS_DISABLED +FONT 8, "MS Shell Dlg" +CAPTION "Zabezpečení" +BEGIN + + CONTROL "Listview", IDC_SEC_LISTVIEW, "SysListView32", + LVS_ICON | LVS_ALIGNLEFT | LVS_AUTOARRANGE | LVS_SINGLESEL | LVS_SHOWSELALWAYS | WS_BORDER | WS_VSCROLL, + 4, 4, 312, 58 + LTEXT "", IDC_SEC_ZONE_INFO, 4, 68, 312, 20 + GROUPBOX "", IDC_SEC_GROUP, 4, 88, 312, 126 + CONTROL "trackbar", IDC_SEC_TRACKBAR, "msctls_trackbar32", + TBS_VERT | TBS_AUTOTICKS | TBS_BOTH | TBS_REVERSED, 8, 98, 32, 100 + LTEXT "", IDC_SEC_LEVEL, 48, 102, 180, 12 + LTEXT "", IDC_SEC_LEVEL_INFO, 48, 114, 260, 80 +END + +/* "Content" propsheet */ +IDD_CONTENT DIALOG 0, 0, 320, 220 +STYLE WS_CAPTION | WS_CHILD | WS_DISABLED +FONT 8, "MS Shell Dlg" +CAPTION "Obsah" +BEGIN + + GROUPBOX " Certifikáty ", IDC_STATIC, 4, 4, 312, 50 + LTEXT "Certifikáty slouží k osobní identifikaci a k identifikaci certifikačních autorit a vydavatelů.", + IDC_STATIC, 58, 14, 252, 18 + PUSHBUTTON "Certifikáty...", IDC_CERT, 146, 34, 80, 14 + PUSHBUTTON "Vydavatelé...", IDC_CERT_PUBLISHER, 230, 34, 80, 14 + +END + +STRINGTABLE +BEGIN + IDS_CPL_NAME "Nastavení Internetu" + IDS_CPL_INFO "Konfigurovat Internetový prohlížeč Wine a související nastavení" + IDS_SEC_SETTINGS "Nastavení zabezpečení pro zónu: " + IDS_SEC_LEVEL0 "Vlastní" + IDS_SEC_LEVEL1 "Velmi nízké" + IDS_SEC_LEVEL2 "Nízké" + IDS_SEC_LEVEL3 "Střední" + IDS_SEC_LEVEL4 "Zvýšené" + IDS_SEC_LEVEL5 "Vysoké" +END diff --git a/dll/cpl/joy/joy.rc b/dll/cpl/joy/joy.rc index 0536869cad3..7637ab013d2 100644 --- a/dll/cpl/joy/joy.rc +++ b/dll/cpl/joy/joy.rc @@ -18,9 +18,6 @@ IDI_CPLSYSTEM ICON "resources/applet.ico" #ifdef LANGUAGE_BG_BG #include "lang/bg-BG.rc" #endif -#ifdef LANGUAGE_CS_CZ - #include "lang/cs-CZ.rc" -#endif #ifdef LANGUAGE_DE_DE #include "lang/de-DE.rc" #endif @@ -55,6 +52,9 @@ IDI_CPLSYSTEM ICON "resources/applet.ico" /* UTF-8 */ #pragma code_page(65001) +#ifdef LANGUAGE_CS_CZ + #include "lang/cs-CZ.rc" +#endif #ifdef LANGUAGE_HE_IL #include "lang/he-IL.rc" #endif diff --git a/dll/cpl/joy/lang/cs-CZ.rc b/dll/cpl/joy/lang/cs-CZ.rc index 603132d3464..c737c3d3daa 100644 --- a/dll/cpl/joy/lang/cs-CZ.rc +++ b/dll/cpl/joy/lang/cs-CZ.rc @@ -1,6 +1,6 @@ /* FILE: dll/cpl/joy/lang/cs-CZ.rc * TRANSLATOR: Radek Liska aka Black_Fox (radekliska at gmail dot com) - * UPDATED: 2009-01-10 + * UPDATED: 2014-04-25 */ LANGUAGE LANG_CZECH, SUBLANG_DEFAULT @@ -8,35 +8,35 @@ LANGUAGE LANG_CZECH, SUBLANG_DEFAULT IDD_PROPPAGEMAIN DIALOGEX 0, 0, 252, 205 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUPWINDOW | WS_CAPTION EXSTYLE WS_EX_CONTEXTHELP -CAPTION "Hern ovladae" +CAPTION "Herní ovladače" FONT 8, "MS Shell Dlg" BEGIN ICON IDI_CPLSYSTEM, -1, 7, 7, 20, 20 - LTEXT "Tato nastaven pomhaj konfigurovat hern ovladae nainstalovan na tomto potai.", -1, 33, 7, 214, 20, NOT WS_GROUP - GROUPBOX "Nai&nstalovan hern ovladae", -1, 7, 34, 238, 117 + LTEXT "Tato nastavení pomáhají konfigurovat herní ovladače nainstalované na tomto počítači.", -1, 33, 7, 214, 20, NOT WS_GROUP + GROUPBOX "Nai&nstalované herní ovladače", -1, 7, 34, 238, 117 CONTROL "List1", IDC_CONTROLLER_LIST, "SysListView32", WS_BORDER | WS_GROUP | WS_TABSTOP | 0x0000808D, 14, 44, 224, 80 - PUSHBUTTON "&Pidat...", IDC_ADD_BUTTON, 35, 129, 65, 14 + PUSHBUTTON "&Přidat...", IDC_ADD_BUTTON, 35, 129, 65, 14 PUSHBUTTON "&Odebrat", IDC_REMOVE_BUTTON, 104, 129, 65, 14, WS_DISABLED PUSHBUTTON "&Vlastnosti", IDC_PROPERTIES_BUTTON, 173, 129, 65, 14, WS_DISABLED - PUSHBUTTON "&Rozen...", IDC_ADVANCED_BUTTON, 111, 157, 65, 14 - PUSHBUTTON "&een problm...", IDC_TROUBLESHOOT_BUTTON, 180, 157, 65, 14 + PUSHBUTTON "&Rozšířené...", IDC_ADVANCED_BUTTON, 111, 157, 65, 14 + PUSHBUTTON "Ř&ešení problémů...", IDC_TROUBLESHOOT_BUTTON, 180, 157, 65, 14 PUSHBUTTON "OK", IDOK, 195, 185, 50, 14 END IDD_ADD DIALOGEX 0, 0, 265, 200 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_CAPTION EXSTYLE WS_EX_CONTEXTHELP -CAPTION "Pidat hern ovlada" +CAPTION "Přidat herní ovladač" FONT 8, "MS Shell Dlg" BEGIN ICON IDI_CPLSYSTEM, -1, 8, 7, 20, 20 - LTEXT "Vyberte hern ovlada ze seznamu ne, pot kliknte na tlatko OK. Pokud se v ovlada v seznamu nenachz, kliknte na tlatko Vlastn.", -1, 35, 7, 210, 33 - LTEXT "&Hern ovladae:", -1, 8, 45, 126, 8 + LTEXT "Vyberte herní ovladač ze seznamu níže, poté klikněte na tlačítko OK. Pokud se váš ovladač v seznamu nenachází, klikněte na tlačítko Vlastní.", -1, 35, 7, 210, 33 + LTEXT "&Herní ovladače:", -1, 8, 45, 126, 8 LISTBOX IDC_GAME_CONTROLLERS_LIST, 7, 55, 251, 57, LBS_STANDARD | LBS_NOINTEGRALHEIGHT | LBS_WANTKEYBOARDINPUT | WS_HSCROLL | WS_TABSTOP - AUTOCHECKBOX "&Zapnout kormidlo a pedly", IDC_ENABLE_RUDDERS_CHECKBOX, 7, 114, 100, 10, WS_GROUP + AUTOCHECKBOX "&Zapnout kormidlo a pedály", IDC_ENABLE_RUDDERS_CHECKBOX, 7, 114, 100, 10, WS_GROUP LTEXT "&Port:", -1, 7, 134, 38, 8, NOT WS_VISIBLE COMBOBOX IDC_GAME_PORT_COMBO, 7, 147, 140, 50, CBS_DROPDOWNLIST | CBS_SORT | NOT WS_VISIBLE | WS_VSCROLL - PUSHBUTTON "&Vlastn...", IDC_CUSTOM_BUTTON, 208, 147, 50, 14 + PUSHBUTTON "&Vlastní...", IDC_CUSTOM_BUTTON, 208, 147, 50, 14 CONTROL "", -25525, "STATIC", SS_ETCHEDHORZ, 7, 170, 251, 1 DEFPUSHBUTTON "OK", IDOK, 155, 179, 50, 14 PUSHBUTTON "Storno", IDCANCEL, 208, 179, 50, 14 @@ -45,22 +45,22 @@ END IDD_CUSTOM DIALOGEX 0, 0, 265, 183, 0 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_CAPTION EXSTYLE WS_EX_CONTEXTHELP -CAPTION "Vlastn hern ovlada" +CAPTION "Vlastní herní ovladač" FONT 8, "MS Shell Dlg" BEGIN - GROUPBOX "Zvltn charakteristiky", -1, 7, 7, 245, 52 + GROUPBOX "Zvláštní charakteristiky", -1, 7, 7, 245, 52 AUTORADIOBUTTON "&Joystick", IDC_JOYSTICK_RADIO, 17, 23, 55, 10 - AUTORADIOBUTTON "&Leteck dc pka nebo kormidlo", IDC_FLIGHT_YOKE_RADIO, 147, 23, 89, 10 + AUTORADIOBUTTON "&Letecká řídící páka nebo kormidlo", IDC_FLIGHT_YOKE_RADIO, 147, 23, 89, 10 AUTORADIOBUTTON "&Gamepad", IDC_GAME_PAD_RADIO, 17, 40, 65, 10 - AUTORADIOBUTTON "zen &auta", IDC_RACE_CAR_RADIO, 147, 40, 93, 10 + AUTORADIOBUTTON "Řízení &auta", IDC_RACE_CAR_RADIO, 147, 40, 93, 10 GROUPBOX "&Osy", -1, 7, 67, 116, 44, WS_GROUP COMBOBOX IDC_AXES_COMBO, 37, 79, 48, 50, CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL - AUTORADIOBUTTON "Kormidlo/Pedly", IDC_RUDDER_PEDALS_RADIO, 14, 97, 63, 10, NOT WS_VISIBLE + AUTORADIOBUTTON "Kormidlo/Pedály", IDC_RUDDER_PEDALS_RADIO, 14, 97, 63, 10, NOT WS_VISIBLE AUTORADIOBUTTON "Osa Z", IDC_Z_AXIS_RADIO, 81, 97, 35, 10, NOT WS_VISIBLE - GROUPBOX "&Tlatka", -1, 137, 67, 116, 44 + GROUPBOX "&Tlačítka", -1, 137, 67, 116, 44 COMBOBOX IDC_BUTTONS_COMBO, 178, 79, 48, 50, CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL, WS_EX_CLIENTEDGE - AUTOCHECKBOX "Obsahuje zen zo&rnho hlu", IDC_INC_POINT_CHECKBOX, 7, 123, 115, 10 - LTEXT "Nzev hernho &ovladae:", -1, 7, 139, 200, 9 + AUTOCHECKBOX "Obsahuje řízení zo&rného úhlu", IDC_INC_POINT_CHECKBOX, 7, 123, 115, 10 + LTEXT "Název herního &ovladače:", -1, 7, 139, 200, 9 EDITTEXT IDC_CONTROLLER_NAME_EDIT, 7, 150, 116, 15, ES_AUTOHSCROLL, WS_EX_CLIENTEDGE | WS_EX_STATICEDGE DEFPUSHBUTTON "OK", IDOK, 137, 150, 50, 14 PUSHBUTTON "Storno", IDCANCEL, 203, 150, 50, 14 @@ -69,21 +69,21 @@ END IDD_ADVANCED DIALOGEX 0, 0, 220, 86 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUPWINDOW | WS_CAPTION EXSTYLE WS_EX_CONTEXTHELP -CAPTION "Rozen nastaven" +CAPTION "Rozšířené nastavení" FONT 8, "MS Shell Dlg" BEGIN ICON IDI_CPLSYSTEM, -1, 7, 24, 20, 20 DEFPUSHBUTTON "OK", IDOK, 106, 65, 50, 14 PUSHBUTTON "Storno", IDCANCEL, 163, 65, 50, 14 - LTEXT "Vyberte zazen, kter chcete pouvat se starmi programy.", -1, 7, 7, 208, 10 - LTEXT "&Preferovan zazen:", -1, 34, 24, 70, 10 + LTEXT "Vyberte zařízení, které chcete používat se staršími programy.", -1, 7, 7, 208, 10 + LTEXT "&Preferované zařízení:", -1, 34, 24, 70, 10 COMBOBOX IDC_PREFERRED_DEV_COMBO, 34, 38, 179, 75, CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL END STRINGTABLE BEGIN - IDS_CPLSYSTEMNAME "Hern ovladae" - IDS_CPLSYSTEMDESCRIPTION "Pidat, odebrat a konfigurovat hern ovladae jako napklad joysticky nebo gamepady." - IDS_CONTROLLER "Ovlada" + IDS_CPLSYSTEMNAME "Herní ovladače" + IDS_CPLSYSTEMDESCRIPTION "Přidat, odebrat a konfigurovat herní ovladače jako například joysticky nebo gamepady." + IDS_CONTROLLER "Ovladač" IDS_STATUS "Stav" END diff --git a/dll/cpl/mmsys/lang/cs-CZ.rc b/dll/cpl/mmsys/lang/cs-CZ.rc index e0207108160..364fb40c3e1 100644 --- a/dll/cpl/mmsys/lang/cs-CZ.rc +++ b/dll/cpl/mmsys/lang/cs-CZ.rc @@ -1,6 +1,6 @@ /* FILE: dll/cpl/mmsys/lang/cs-CZ.rc * TRANSLATOR: Radek Liska aka Black_Fox (radekliska at gmail dot com) - * UPDATED: 2009-02-02 + * UPDATED: 2014-04-25 */ LANGUAGE LANG_CZECH, SUBLANG_DEFAULT @@ -12,19 +12,19 @@ FONT 8, "MS Shell Dlg" BEGIN ICON IDI_CPLICON, IDI_CPLICON, 8, 5, 32, 32 LTEXT "", IDC_DEVICE_NAME, 40, 10, 194, 36 - GROUPBOX "Hlasitost zazen", -1, 7, 30, 230, 100 + GROUPBOX "Hlasitost zařízení", -1, 7, 30, 230, 100 CONTROL "", IDC_MUTE_ICON, "Static", SS_ICON | WS_VISIBLE, 17, 45, 32, 32 CONTROL "", IDC_VOLUME_TRACKBAR, "msctls_trackbar32", TBS_AUTOTICKS | TBS_ENABLESELRANGE | TBS_BOTTOM | TBS_HORZ | WS_TABSTOP, 65, 45, 140, 14 - LTEXT "Nzk", -1, 62, 66, 30, 17 - LTEXT "Vysok", -1, 195, 66, 30, 17 + LTEXT "Nízká", -1, 62, 66, 30, 17 + LTEXT "Vysoká", -1, 195, 66, 30, 17 CHECKBOX "&Ztlumit", IDC_MUTE_CHECKBOX, 50, 78, 140, 10 - CHECKBOX "Umstit &ikonu hlasitosti na panel loh", IDC_ICON_IN_TASKBAR, 50, 92, 140, 10 - PUSHBUTTON "&Upesnit...", IDC_ADVANCED_BTN, 150, 105, 75, 15 - GROUPBOX "Nastaven reproduktor", IDC_SPEAKER_SET_BTN, 7, 140, 230, 80 + CHECKBOX "Umístit &ikonu hlasitosti na panel úloh", IDC_ICON_IN_TASKBAR, 50, 92, 140, 10 + PUSHBUTTON "&Upřesnit...", IDC_ADVANCED_BTN, 150, 105, 75, 15 + GROUPBOX "Nastavení reproduktorů", IDC_SPEAKER_SET_BTN, 7, 140, 230, 80 CONTROL "", IDC_SPEAKIMG, "Static", SS_OWNERDRAW, 4, 160, 70, 70 - LTEXT "Nastaven ne lze pout ke zmnn hlasitosti jednotlivch reproduktor a dalch nastaven.", -1, 70, 155, 150, 36 - PUSHBUTTON "&Hlasitost reproduktor...", IDC_SPEAKER_VOL_BTN, 70, 195, 75, 15 - PUSHBUTTON "U&pesnit...", IDC_ADVANCED2_BTN, 150, 195, 75, 15 + LTEXT "Nastavení níže lze použít ke změnění hlasitosti jednotlivých reproduktorů a dalších nastavení.", -1, 70, 155, 150, 36 + PUSHBUTTON "&Hlasitost reproduktorů...", IDC_SPEAKER_VOL_BTN, 70, 195, 75, 15 + PUSHBUTTON "U&přesnit...", IDC_ADVANCED2_BTN, 150, 195, 75, 15 END IDD_SOUNDS DIALOGEX 0, 0, 246, 228 @@ -32,18 +32,18 @@ STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION CAPTION "Zvuky" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Zvukov schma je soubor zvuk, kter jsou pehrvny pi udlostech v systmu ReactOS a programech. Lze zvolit existujc schma nebo uloit jin, upraven.", -1, 8, 7, 230, 40 - LTEXT "Zvukov s&chma:", -1, 8, 42, 150, 17 + LTEXT "Zvukové schéma je soubor zvuků, které jsou přehrávány při událostech v systému ReactOS a programech. Lze zvolit existující schéma nebo uložit jiné, upravené.", -1, 8, 7, 230, 40 + LTEXT "Zvukové s&chéma:", -1, 8, 42, 150, 17 COMBOBOX IDC_SOUND_SCHEME, 8, 53, 230, 46, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "&Uloit jako...", IDC_SAVEAS_BTN, 134, 70, 50, 15 + PUSHBUTTON "&Uložit jako...", IDC_SAVEAS_BTN, 134, 70, 50, 15 PUSHBUTTON "&Smazat", IDC_DELETE_BTN, 188, 70, 50, 15 - LTEXT "Zvuky lze mnit kliknutm na programovou udlost v nsledujcm seznamu a vybrnm zvuku, kter m bt pehrn. Zmny lze uloit jako nov zvukov schma.", -1, 8, 90, 230, 40 - LTEXT "&Udlosti program:", -1, 8, 118, 150, 17 + LTEXT "Zvuky lze měnit kliknutím na programovou událost v následujícím seznamu a vybráním zvuku, který má být přehrán. Změny lze uložit jako nové zvukové schéma.", -1, 8, 90, 230, 40 + LTEXT "&Události programů:", -1, 8, 118, 150, 17 CONTROL "", IDC_SCHEME_LIST, "SysListView32", LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | WS_BORDER | WS_TABSTOP, 8, 130, 230, 60, WS_EX_CLIENTEDGE LTEXT "&Zvuky:", IDC_TEXT_SOUND, 8, 194, 80, 17, WS_DISABLED COMBOBOX IDC_SOUND_LIST, 8, 205, 155, 146, CBS_DROPDOWNLIST | CBS_DISABLENOSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP | WS_DISABLED PUSHBUTTON "", IDC_PLAY_SOUND, 168, 205, 15, 15, WS_DISABLED | BS_ICON - PUSHBUTTON "&Prochzet...", IDC_BROWSE_SOUND, 188, 205, 50, 15, WS_DISABLED + PUSHBUTTON "&Procházet...", IDC_BROWSE_SOUND, 188, 205, 50, 15, WS_DISABLED END IDD_AUDIO DIALOGEX 0, 0, 246, 228 @@ -51,25 +51,25 @@ STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION CAPTION "Zvuk" FONT 8, "MS Shell Dlg" BEGIN - GROUPBOX "Pehrvn zvuku", -1, 7, 7, 230, 60 + GROUPBOX "Přehrávání zvuku", -1, 7, 7, 230, 60 ICON IDI_CPLICON, IDI_CPLICON, 15, 20, 32, 32 - LTEXT "&Vchoz zazen:", -1, 50, 20, 80, 17 + LTEXT "&Výchozí zařízení:", -1, 50, 20, 80, 17 COMBOBOX IDC_DEVICE_PLAY_LIST, 50, 30, 180, 46, CBS_DROPDOWNLIST PUSHBUTTON "&Hlasitost...", IDC_VOLUME1_BTN, 85, 47, 70, 15 - PUSHBUTTON "&Upesnit...", IDC_ADV2_BTN, 160, 47, 70, 15 - GROUPBOX "Zznam zvuku", -1, 7, 75, 230, 60 + PUSHBUTTON "&Upřesnit...", IDC_ADV2_BTN, 160, 47, 70, 15 + GROUPBOX "Záznam zvuku", -1, 7, 75, 230, 60 ICON IDI_MICROPHONE_ICON, IDI_MICROPHONE_ICON, 15, 88, 32, 32 - LTEXT "V&choz zazen:", -1, 50, 88, 80, 17 + LTEXT "Vý&chozí zařízení:", -1, 50, 88, 80, 17 COMBOBOX IDC_DEVICE_REC_LIST, 50, 98, 180, 46, CBS_DROPDOWNLIST PUSHBUTTON "H&lasitost...", IDC_VOLUME2_BTN, 85, 115, 70, 15 - PUSHBUTTON "U&pesnit...", IDC_ADV1_BTN, 160, 115, 70, 15 - GROUPBOX "Pehrvn MIDI hudby", -1, 7, 145, 230, 60 + PUSHBUTTON "U&přesnit...", IDC_ADV1_BTN, 160, 115, 70, 15 + GROUPBOX "Přehrávání MIDI hudby", -1, 7, 145, 230, 60 ICON IDI_MIDICON, IDI_MIDICON, 15, 158, 32, 32 - LTEXT "Vcho&z zazen:", -1, 50, 158, 80, 17 + LTEXT "Výcho&zí zařízení:", -1, 50, 158, 80, 17 COMBOBOX IDC_DEVICE_MIDI_LIST, 50, 168, 180, 46, CBS_DROPDOWNLIST PUSHBUTTON "Hl&asitost...", IDC_VOLUME3_BTN, 85, 185, 70, 15 PUSHBUTTON "&O produktu...", IDC_ADV3_BTN, 160, 185, 70, 15 - CHECKBOX "Pouva&t jen vchoz zazen", IDC_DEFAULT_DEV_CHECKBOX, 7, 212, 140, 10 + CHECKBOX "Používa&t jen výchozí zařízení", IDC_DEFAULT_DEV_CHECKBOX, 7, 212, 140, 10 END IDD_VOICE DIALOGEX 0, 0, 246, 228 @@ -77,19 +77,19 @@ STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION CAPTION "Hlas" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Tato nastaven ovlivuj hlasitost a rozen volby pro pehrvn hlasu a zvolen zznamov zazen.", -1, 8, 7, 230, 40 - GROUPBOX "Pehrvn hlasu", -1, 7, 37, 230, 60 + LTEXT "Tato nastavení ovlivňují hlasitost a rozšířené volby pro přehrávání hlasu a zvolené záznamové zařízení.", -1, 8, 7, 230, 40 + GROUPBOX "Přehrávání hlasu", -1, 7, 37, 230, 60 ICON IDI_CPLICON, IDI_CPLICON, 15, 50, 32, 32 - LTEXT "&Vchoz zazen:", -1, 50, 50, 80, 17 + LTEXT "&Výchozí zařízení:", -1, 50, 50, 80, 17 COMBOBOX IDC_DEVICE_VOICE_LIST, 50, 60, 180, 46, CBS_DROPDOWNLIST PUSHBUTTON "&Hlasitost...", IDC_VOLUME4_BTN, 85, 77, 70, 15 - PUSHBUTTON "&Upesnit...", IDC_ADV4_BTN, 160, 77, 70, 15 - GROUPBOX "Zznam hlasu", -1, 7, 105, 230, 60 + PUSHBUTTON "&Upřesnit...", IDC_ADV4_BTN, 160, 77, 70, 15 + GROUPBOX "Záznam hlasu", -1, 7, 105, 230, 60 ICON IDI_MICROPHONE_ICON, IDI_MICROPHONE_ICON, 15, 118, 32, 32 - LTEXT "V&choz zazen:", -1, 50, 118, 80, 17 + LTEXT "Vý&chozí zařízení:", -1, 50, 118, 80, 17 COMBOBOX IDC_DEVICE_VOICE_REC_LIST, 50, 128, 180, 46, CBS_DROPDOWNLIST PUSHBUTTON "H&lasitost...", IDC_VOLUME5_BTN, 85, 145, 70, 15 - PUSHBUTTON "U&pesnit...", IDC_ADV5_BTN, 160, 145, 70, 15 + PUSHBUTTON "U&přesnit...", IDC_ADV5_BTN, 160, 145, 70, 15 PUSHBUTTON "&Otestovat hardware...", IDC_TEST_HARDWARE, 160, 175, 70, 15 END @@ -102,10 +102,10 @@ END IDD_SAVE_SCHEME_AS DIALOG 9, 23, 225, 54 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CONTEXTHELP | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION -CAPTION "Uloit schma jako" +CAPTION "Uložit schéma jako" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "&Uloit toto zvukov schma jako:", -1, 7, 7, 212, 9 + LTEXT "&Uložit toto zvukové schéma jako:", -1, 7, 7, 212, 9 EDITTEXT 8960, 7, 17, 211, 14, ES_AUTOHSCROLL DEFPUSHBUTTON "OK", IDOK, 93, 36, 60, 14 PUSHBUTTON "Storno", IDCANCEL, 157, 36, 60, 14 @@ -117,156 +117,156 @@ CAPTION "Reproduktory" FONT 8, "MS Shell Dlg" BEGIN ICON 4379, -1, 7, 8, 20, 20 - LTEXT "Zvolte rozmstn reproduktor, kter nejvce odpovd souasnmu.", -1, 36, 8, 215, 27 + LTEXT "Zvolte rozmístění reproduktorů, které nejvíce odpovídá současnému.", -1, 36, 8, 215, 27 CONTROL 110, 5376, "STATIC", SS_BITMAP | SS_CENTERIMAGE, 37, 40, 209, 112, WS_EX_TRANSPARENT - LTEXT "&Rozmstn reproduktor:", 8502, 53, 169, 55, 10 + LTEXT "&Rozmístění reproduktorů:", 8502, 53, 169, 55, 10 COMBOBOX 5401, 52, 182, 170, 200, CBS_DROPDOWNLIST | WS_VSCROLL | NOT WS_TABSTOP END IDD_PERFORMANCE1 DIALOG 0, 0, 257, 218 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Vkon" +CAPTION "Výkon" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Tato nastaven ovlivuj, jak systm ReactOS pehrv zvuk. Mohou pomoci pi een problm se zvukem.", 8492, 34, 7, 218, 23 - GROUPBOX "Pehrvn zvuku", 8494, 7, 32, 243, 152 + LTEXT "Tato nastavení ovlivňují, jak systém ReactOS přehrává zvuk. Mohou pomoci při řešení problémů se zvukem.", 8492, 34, 7, 218, 23 + GROUPBOX "Přehrávání zvuku", 8494, 7, 32, 243, 152 ICON 4379, 8512, 8, 8, 20, 20 - LTEXT "&Hardwarov akcelerace:", 8495, 13, 56, 111, 14 + LTEXT "&Hardwarová akcelerace:", 8495, 13, 56, 111, 14 CONTROL "Slider1", 5395, "MSCTLS_TRACKBAR32", WS_GROUP | WS_TABSTOP | 0x00000401, 150, 54, 62, 18 - LTEXT "&Kvalita pevodu vzorkovn:", 8496, 13, 123, 103, 14 + LTEXT "&Kvalita převodu vzorkování:", 8496, 13, 123, 103, 14 CONTROL "Slider1", 5396, "MSCTLS_TRACKBAR32", WS_TABSTOP | 0x00000401, 150, 121, 62, 18 - PUSHBUTTON "&Obnovit vchoz", 5400, 7, 191, 110, 14 - LTEXT "dn", 8497, 128, 56, 21, 10 - LTEXT "Pln", 8498, 214, 56, 21, 9 - LTEXT "Dobr", 8499, 128, 123, 21, 10 - LTEXT "Nejlep", 8500, 214, 123, 23, 9 - LTEXT "Tento string popisuje hardwarov nastaven pro zachytvac zazen", 5399, 13, 145, 227, 21 - LTEXT "Tento string popisuje hardwarov nastaven pro vykreslovac zazen", 5398, 13, 78, 227, 22 + PUSHBUTTON "&Obnovit výchozí", 5400, 7, 191, 110, 14 + LTEXT "Žádná", 8497, 128, 56, 21, 10 + LTEXT "Plná", 8498, 214, 56, 21, 9 + LTEXT "Dobrá", 8499, 128, 123, 21, 10 + LTEXT "Nejlepší", 8500, 214, 123, 23, 9 + LTEXT "Tento string popisuje hardwarové nastavení pro zachytávací zařízení", 5399, 13, 145, 227, 21 + LTEXT "Tento string popisuje hardwarové nastavení pro vykreslovací zařízení", 5398, 13, 78, 227, 22 END IDD_PERFORMANCE2 DIALOG 0, 0, 257, 218 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Vkon" +CAPTION "Výkon" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Tato nastaven ovlivuj, jak systm ReactOS zaznamenv zvuk. Mohou pomoci pi een problm se zvukem.", 8492, 34, 7, 217, 20 - GROUPBOX "Zznam zvuku", 8494, 7, 29, 242, 122 + LTEXT "Tato nastavení ovlivňují, jak systém ReactOS zaznamenává zvuk. Mohou pomoci při řešení problémů se zvukem.", 8492, 34, 7, 217, 20 + GROUPBOX "Záznam zvuku", 8494, 7, 29, 242, 122 ICON 4380, 8512, 8, 7, 20, 20 - LTEXT "&Hardwarov akcelerace:", 8495, 13, 46, 103, 17 + LTEXT "&Hardwarová akcelerace:", 8495, 13, 46, 103, 17 CONTROL "Slider1", 5395, "MSCTLS_TRACKBAR32", WS_GROUP | WS_TABSTOP | 0x00000401, 150, 43, 62, 18 - LTEXT "&Kvalita pevodu vzorkovn:", 8496, 13, 103, 103, 17 + LTEXT "&Kvalita převodu vzorkování:", 8496, 13, 103, 103, 17 CONTROL "Slider1", 5396, "MSCTLS_TRACKBAR32", WS_TABSTOP | 0x00000401, 150, 101, 62, 18 - PUSHBUTTON "&Obnovit vchoz", 5400, 9, 158, 110, 14 - LTEXT "dn", 8497, 125, 46, 24, 10 - LTEXT "Pln", 8498, 217, 46, 19, 9 - LTEXT "Dobr", 8499, 125, 103, 24, 10 - LTEXT "Nejlep", 8500, 217, 103, 19, 9 - LTEXT "Tento string popisuje hardwarov nastaven pro zachytvac zazen", 5399, 13, 125, 222, 21 - LTEXT "Tento string popisuje hardwarov nastaven pro vykreslovac zazen", 5398, 13, 68, 218, 24 + PUSHBUTTON "&Obnovit výchozí", 5400, 9, 158, 110, 14 + LTEXT "Žádná", 8497, 125, 46, 24, 10 + LTEXT "Plná", 8498, 217, 46, 19, 9 + LTEXT "Dobrá", 8499, 125, 103, 24, 10 + LTEXT "Nejlepší", 8500, 217, 103, 19, 9 + LTEXT "Tento string popisuje hardwarové nastavení pro zachytávací zařízení", 5399, 13, 125, 222, 21 + LTEXT "Tento string popisuje hardwarové nastavení pro vykreslovací zařízení", 5398, 13, 68, 218, 24 END IDD_SETUP1 DIALOG 0, 0, 227, 206 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION -CAPTION "Nastaven" +CAPTION "Nastavení" FONT 8, "MS Shell Dlg" BEGIN GROUPBOX "ReactOS zvuk", 10243, 7, 5, 213, 192 ICON 4393, 10241, 26, 26, 20, 20 - LTEXT "Tento pota neme pehrvat zvuk, protoe sluba zvuku systmu ReactOS nen sputna.", 10245, 60, 25, 150, 40 + LTEXT "Tento počítač nemůže přehrávat zvuk, protože služba zvuku systému ReactOS není spuštěna.", 10245, 60, 25, 150, 40 AUTOCHECKBOX "&Spustit ReactOS zvuk", 10253, 60, 68, 150, 9 - LTEXT "Poznmky", 10246, 58, 87, 150, 11 - LTEXT "1. Pro sputn tto sluby je teba bt sprvcem potae. Pokud nejste pihleni jako sprvce, bude vydno jmno a heslo sprvce.", 10247, 60, 100, 150, 40 - LTEXT "2. Po sputn ReactOS zvuku bude teba restartovat pota.", 10248, 60, 140, 150, 40 + LTEXT "Poznámky", 10246, 58, 87, 150, 11 + LTEXT "1. Pro spuštění této služby je třeba být správcem počítače. Pokud nejste přihlášeni jako správce, bude vyžádáno jméno a heslo správce.", 10247, 60, 100, 150, 40 + LTEXT "2. Po spuštění ReactOS zvuku bude třeba restartovat počítač.", 10248, 60, 140, 150, 40 END IDD_MULTICHANNEL DIALOG 0, 0, 227, 218 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION -CAPTION "Vcekanlov zvuk" +CAPTION "Vícekanálový zvuk" FONT 8, "MS Shell Dlg" BEGIN LTEXT "Tady bude popis.", 9506, 8, 4, 212, 24 - LTEXT "Nzk", 9473, 65, 31, 14, 8 + LTEXT "Nízká", 9473, 65, 31, 14, 8 LTEXT "", 9472, 5, 31, 55, 8 CONTROL "Slider1", 9475, "MSCTLS_TRACKBAR32", WS_TABSTOP | 0x00000401, 87, 29, 108, 17 - LTEXT "Vysok", 9474, 202, 31, 17, 8 - LTEXT "Nzk", 9477, 65, 50, 14, 8 + LTEXT "Vysoká", 9474, 202, 31, 17, 8 + LTEXT "Nízká", 9477, 65, 50, 14, 8 LTEXT "", 9476, 5, 50, 55, 8 CONTROL "Slider1", 9479, "MSCTLS_TRACKBAR32", WS_TABSTOP | 0x00000401, 87, 48, 108, 17 - LTEXT "Vysok", 9478, 202, 50, 17, 8 - LTEXT "Nzk", 9481, 65, 69, 14, 8 + LTEXT "Vysoká", 9478, 202, 50, 17, 8 + LTEXT "Nízká", 9481, 65, 69, 14, 8 LTEXT "", 9480, 5, 69, 55, 8 CONTROL "Slider1", 9483, "MSCTLS_TRACKBAR32", WS_TABSTOP | 0x00000401, 87, 67, 108, 17 - LTEXT "Vysok", 9482, 202, 69, 17, 8 - LTEXT "Nzk", 9485, 65, 88, 14, 8 + LTEXT "Vysoká", 9482, 202, 69, 17, 8 + LTEXT "Nízká", 9485, 65, 88, 14, 8 LTEXT "", 9484, 5, 88, 55, 8 CONTROL "Slider1", 9487, "MSCTLS_TRACKBAR32", WS_TABSTOP | 0x00000401, 87, 86, 108, 17 - LTEXT "Vysok", 9486, 202, 88, 17, 8 - LTEXT "Nzk", 9489, 65, 107, 14, 8 + LTEXT "Vysoká", 9486, 202, 88, 17, 8 + LTEXT "Nízká", 9489, 65, 107, 14, 8 LTEXT "", 9488, 5, 107, 55, 8 CONTROL "Slider1", 9491, "MSCTLS_TRACKBAR32", WS_TABSTOP | 0x00000401, 87, 105, 108, 17 - LTEXT "Vysok", 9490, 202, 107, 17, 8 - LTEXT "Nzk", 9493, 65, 126, 14, 8 + LTEXT "Vysoká", 9490, 202, 107, 17, 8 + LTEXT "Nízká", 9493, 65, 126, 14, 8 LTEXT "", 9492, 5, 126, 55, 8 CONTROL "Slider1", 9495, "MSCTLS_TRACKBAR32", WS_TABSTOP | 0x00000401, 87, 124, 108, 17 - LTEXT "Vysok", 9494, 202, 126, 17, 8 - LTEXT "Nzk", 9497, 65, 145, 14, 8 + LTEXT "Vysoká", 9494, 202, 126, 17, 8 + LTEXT "Nízká", 9497, 65, 145, 14, 8 LTEXT "", 9496, 5, 145, 55, 8 CONTROL "Slider1", 9499, "MSCTLS_TRACKBAR32", WS_TABSTOP | 0x00000401, 87, 143, 108, 17 - LTEXT "Vysok", 9498, 202, 145, 17, 8 - LTEXT "Nzk", 9501, 65, 164, 14, 8 + LTEXT "Vysoká", 9498, 202, 145, 17, 8 + LTEXT "Nízká", 9501, 65, 164, 14, 8 LTEXT "", 9500, 5, 164, 55, 8 CONTROL "Slider1", 9503, "MSCTLS_TRACKBAR32", WS_TABSTOP | 0x00000401, 87, 162, 108, 17 - LTEXT "Vysok", 9502, 202, 164, 17, 8 - AUTOCHECKBOX "&Pohybovat vemi posuvnky najednou", 9504, 5, 185, 216, 9 - PUSHBUTTON "&Obnovit vchoz", 9505, 110, 199, 110, 14 + LTEXT "Vysoká", 9502, 202, 164, 17, 8 + AUTOCHECKBOX "&Pohybovat všemi posuvníky najednou", 9504, 5, 185, 216, 9 + PUSHBUTTON "&Obnovit výchozí", 9505, 110, 199, 110, 14 END IDD_SETUP2 DIALOG 0, 0, 227, 206 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION -CAPTION "Nastaven" +CAPTION "Nastavení" FONT 8, "MS Shell Dlg" BEGIN GROUPBOX "ReactOS zvuk", 10259, 7, 5, 213, 192 ICON 4394, 10257, 25, 25, 20, 20 - LTEXT "Sluba zvuku systmu ReactOS je nyn sputna. Zvuk nicmn nemus fungovat sprvn, dokud nebude systm ReactOS restartovn. Pokud chcete restartovat nyn, nejdve ulote svou prci a ukonete vechny sputn programy.", 10261, 60, 25, 150, 50 - LTEXT "Klepnutm na tlatko OK restartujete systm ReactOS.", 10262, 60, 75, 150, 20 - LTEXT "Pokud klepnete na tlatko Storno, bude teba pota restartovat pozdji, aby ReactOS zvuk fungoval sprvn.", 10263, 60, 100, 150, 40 + LTEXT "Služba zvuku systému ReactOS je nyní spuštěna. Zvuk nicméně nemusí fungovat správně, dokud nebude systém ReactOS restartován. Pokud chcete restartovat nyní, nejdříve uložte svou práci a ukončete všechny spuštěné programy.", 10261, 60, 25, 150, 50 + LTEXT "Klepnutím na tlačítko OK restartujete systém ReactOS.", 10262, 60, 75, 150, 20 + LTEXT "Pokud klepnete na tlačítko Storno, bude třeba počítač restartovat později, aby ReactOS zvuk fungoval správně.", 10263, 60, 100, 150, 40 END STRINGTABLE BEGIN - IDS_CPLNAME "Zvuky a zvukov zazen" - IDS_CPLDESCRIPTION "Uprav zvukov schma Vaeho potae, nebo nastav reproduktory a nahrvac zazen." - IDS_NO_SOUND "(Nen)" + IDS_CPLNAME "Zvuky a zvuková zařízení" + IDS_CPLDESCRIPTION "Upraví zvukové schéma Vašeho počítače, nebo nastaví reproduktory a nahrávací zařízení." + IDS_NO_SOUND "(Není)" IDS_NO_DEVICES "No Devices" 5825 "Chyba programu" - 5826 "Ukonen programu" - 5827 "Varovn pi kritickm stavu baterie" - 5828 "Pipojen zazen" - 5829 "Odpojen zazen" - 5830 "Nezdaen pipojen zazen" - 5831 "Vysypn koe" - 5832 "Varovn pi nzkm stavu baterie" + 5826 "Ukončení programu" + 5827 "Varování při kritickém stavu baterie" + 5828 "Připojení zařízení" + 5829 "Odpojení zařízení" + 5830 "Nezdařené připojení zařízení" + 5831 "Vysypání koše" + 5832 "Varování při nízkém stavu baterie" 5833 "Maximalizace" - 5834 "Vyvoln pkazu z nabdky" - 5835 "Vyvoln nabdky" + 5834 "Vyvolání příkazu z nabídky" + 5835 "Vyvolání nabídky" 5836 "Minimalizace" - 5837 "Oznmen o nov pot" - 5838 "Zahjen navigace" - 5839 "Sputn programu" - 5840 "Dokonen tisku" - 5841 "Obnoven z maximalizace" - 5842 "Obnoven z minimalizace" - 5843 "Hvzdika" - 5844 "Vchoz nastaven zvuku" - 5845 "Vstraha" - 5846 "Ukonen systmu ReactOS" - 5847 "Kritick zastaven" - 5848 "Systmov oznmen" - 5849 "Otzka" - 5850 "Sputn systmu ReactOS" - 5851 "Oteven nabdky Start" - 5852 "Odhlen od systmu ReactOS" - 5853 "Pihlen k systmu ReactOS" + 5837 "Oznámení o nové poště" + 5838 "Zahájení navigace" + 5839 "Spuštění programu" + 5840 "Dokončení tisku" + 5841 "Obnovení z maximalizace" + 5842 "Obnovení z minimalizace" + 5843 "Hvězdička" + 5844 "Výchozí nastavení zvuku" + 5845 "Výstraha" + 5846 "Ukončení systému ReactOS" + 5847 "Kritické zastavení" + 5848 "Systémová oznámení" + 5849 "Otázka" + 5850 "Spuštění systému ReactOS" + 5851 "Otevření nabídky Start" + 5852 "Odhlášení od systému ReactOS" + 5853 "Přihlášení k systému ReactOS" 5854 "ReactOS Explorer" END diff --git a/dll/cpl/mmsys/mmsys.rc b/dll/cpl/mmsys/mmsys.rc index b8992f7d09e..0d2cc8833f0 100644 --- a/dll/cpl/mmsys/mmsys.rc +++ b/dll/cpl/mmsys/mmsys.rc @@ -66,9 +66,6 @@ IDB_SPEAKIMG BITMAP "resources/speaker.bmp" #ifdef LANGUAGE_BG_BG #include "lang/bg-BG.rc" #endif -#ifdef LANGUAGE_CS_CZ - #include "lang/cs-CZ.rc" -#endif #ifdef LANGUAGE_DE_DE #include "lang/de-DE.rc" #endif @@ -112,6 +109,9 @@ IDB_SPEAKIMG BITMAP "resources/speaker.bmp" /* UTF-8 */ #pragma code_page(65001) +#ifdef LANGUAGE_CS_CZ + #include "lang/cs-CZ.rc" +#endif #ifdef LANGUAGE_HE_IL #include "lang/he-IL.rc" #endif diff --git a/dll/cpl/powercfg/lang/cs-CZ.rc b/dll/cpl/powercfg/lang/cs-CZ.rc index 52afc5b3bc1..5b747dcb77d 100644 --- a/dll/cpl/powercfg/lang/cs-CZ.rc +++ b/dll/cpl/powercfg/lang/cs-CZ.rc @@ -2,142 +2,142 @@ LANGUAGE LANG_CZECH, SUBLANG_DEFAULT IDD_PROPPAGEPOWERSHEMES DIALOGEX 0, 0, 252, 237 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Schmata napjen" +CAPTION "Schémata napájení" FONT 8, "MS Shell Dlg" BEGIN ICON IDI_ACDC, IDI_ACDC, 7, 7, 28, 22 - LTEXT "Vyberte napjec schma, kter se nejvce hod pro tento pota. Vechny zmny nastaven se ulo do vybranho schmatu.", -1, 37, 6, 209, 36 - GROUPBOX "&Schma napjen", -1, 6, 43, 240, 50 + LTEXT "Vyberte napájecí schéma, které se nejvíce hodí pro tento počítač. Všechny změny nastavení se uloží do vybraného schématu.", -1, 37, 6, 209, 36 + GROUPBOX "&Schéma napájení", -1, 6, 43, 240, 50 COMBOBOX IDC_ENERGYLIST, 14, 54, 224, 92, CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | WS_VSCROLL - PUSHBUTTON "&Uloit jako...", IDC_SAVEAS_BTN, 109, 72, 70, 14, WS_DISABLED + PUSHBUTTON "&Uložit jako...", IDC_SAVEAS_BTN, 109, 72, 70, 14, WS_DISABLED PUSHBUTTON "&Odstranit", IDC_DELETE_BTN, 183, 72, 55, 14, WS_DISABLED - GROUPBOX "Neznm", IDC_GRPDETAIL, 6, 95, 240, 136 - LTEXT "Pokud je pota:", IDC_SAT, 12, 109, 60, 12 - LTEXT "Pipojen", IDC_SAC, 123, 110, 45, 15 + GROUPBOX "Neznámý", IDC_GRPDETAIL, 6, 95, 240, 136 + LTEXT "Pokud je počítač:", IDC_SAT, 12, 109, 60, 12 + LTEXT "Připojen", IDC_SAC, 123, 110, 45, 15 ICON IDI_AC, IDC_IAC, 97, 108, 21, 20 LTEXT "Funguje na baterie", IDC_SDC, 195, 110, 45, 15 ICON IDI_DC, IDC_IDC, 170, 108, 21, 20 LTEXT "Vypnout &monitor:", IDC_MONITOR, 13, 148, 84, 10 COMBOBOX IDC_MONITORACLIST, 100, 145, 65, 150, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_MONITORDCLIST, 173, 145, 65, 150, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "Vypnout pevn &disky:", IDC_DISK, 13, 171, 84, 10 + LTEXT "Vypnout pevné &disky:", IDC_DISK, 13, 171, 84, 10 COMBOBOX IDC_DISKACLIST, 100, 167, 65, 150, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_DISKDCLIST, 173, 167, 65, 150, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "sporn &reim:", IDC_STANDBY, 13, 191, 84, 10 + LTEXT "Úsporný &režim:", IDC_STANDBY, 13, 191, 84, 10 COMBOBOX IDC_STANDBYACLIST, 100, 188, 65, 150, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_STANDBYDCLIST, 173, 188, 65, 150, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "&Reim spnku:", IDC_HYBERNATE, 13, 212, 84, 10 + LTEXT "&Režim spánku:", IDC_HYBERNATE, 13, 212, 84, 10 COMBOBOX IDC_HYBERNATEACLIST, 100, 209, 65, 150, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_HYBERNATEDCLIST, 173, 209, 65, 150, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP END IDD_PROPPAGEALARMS DIALOGEX 0, 0, 252, 237 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Varovn" +CAPTION "Varování" FONT 8, "MS Shell Dlg" BEGIN - GROUPBOX "Varovn o nzkm stavu baterie", -1, 10, 15, 235, 95 - CONTROL "Aktivovat &varovn o nzkm stavu baterie, kdy rove nabit doshne:", IDC_ALARM1, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 15, 17, 190, 15 - LTEXT "neznm", IDC_ALARMVALUE1, 209, 20, 33, 10 + GROUPBOX "Varování o nízkém stavu baterie", -1, 10, 15, 235, 95 + CONTROL "Aktivovat &varování o nízkém stavu baterie, když úroveň nabití dosáhne:", IDC_ALARM1, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 15, 17, 190, 15 + LTEXT "neznámá", IDC_ALARMVALUE1, 209, 20, 33, 10 LTEXT "0%", -1, 28, 43, 15, 10 CONTROL "Slider1", IDC_ALARMBAR1, "msctls_trackbar32", TBS_HORZ | TBS_AUTOTICKS | WS_TABSTOP, 42, 45, 170, 15 LTEXT "100%", -1, 214, 43, 25, 10 - PUSHBUTTON "&Akce pi varovn...", -1, 17, 69, 70, 14, WS_DISABLED - LTEXT "Oznmen:", -1, 95, 71, 57, 10 - LTEXT "Neznm", IDC_ALARMMSG1, 154, 71, 84, 10 + PUSHBUTTON "&Akce při varování...", -1, 17, 69, 70, 14, WS_DISABLED + LTEXT "Oznámení:", -1, 95, 71, 57, 10 + LTEXT "Neznámé", IDC_ALARMMSG1, 154, 71, 84, 10 LTEXT "Akce:", -1, 95, 83, 55, 10 - LTEXT "Neznm", IDC_ALARMAKTION1, 154, 83, 84, 10 + LTEXT "Neznámá", IDC_ALARMAKTION1, 154, 83, 84, 10 LTEXT "Spustit program:", -1, 95, 95, 55, 10 - LTEXT "Neznm", IDC_ALARMPROG1, 154, 95, 84, 10 - GROUPBOX "Varovn o kritickm stavu baterie", -1, 6, 120, 239, 106 - CONTROL "Aktivovat varovn o &kritickm stavu baterie, kdy rove nabit doshne:", IDC_ALARM2, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 15, 131, 180, 15 - LTEXT "neznm", IDC_ALARMVALUE2, 209, 133, 33, 10 + LTEXT "Neznámý", IDC_ALARMPROG1, 154, 95, 84, 10 + GROUPBOX "Varování o kritickém stavu baterie", -1, 6, 120, 239, 106 + CONTROL "Aktivovat varování o &kritickém stavu baterie, když úroveň nabití dosáhne:", IDC_ALARM2, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 15, 131, 180, 15 + LTEXT "neznámá", IDC_ALARMVALUE2, 209, 133, 33, 10 LTEXT "0%", -1, 28, 154, 15, 10 CONTROL "Slider1", IDC_ALARMBAR2, "msctls_trackbar32", TBS_HORZ | TBS_AUTOTICKS | WS_TABSTOP, 42, 158, 170, 15 LTEXT "100%", -1, 214, 154, 25, 10 - PUSHBUTTON "Akce &pi varovn...", -1, 17, 183, 70, 14, WS_DISABLED - LTEXT "Oznmen:", -1, 95, 185, 50, 10 - LTEXT "Neznm", IDC_ALARMMSG2, 154, 185, 84, 10 + PUSHBUTTON "Akce &při varování...", -1, 17, 183, 70, 14, WS_DISABLED + LTEXT "Oznámení:", -1, 95, 185, 50, 10 + LTEXT "Neznámé", IDC_ALARMMSG2, 154, 185, 84, 10 LTEXT "Akce:", -1, 95, 198, 45, 10 - LTEXT "Neznm", IDC_ALARMAKTION2, 154, 198, 84, 10 + LTEXT "Neznámá", IDC_ALARMAKTION2, 154, 198, 84, 10 LTEXT "Spustit program:", -1, 95, 211, 50, 10 - LTEXT "Neznm", IDC_ALARMPROG2, 154, 211, 84, 10 + LTEXT "Neznámý", IDC_ALARMPROG2, 154, 211, 84, 10 END IDD_PROPPAGEADVANCED DIALOGEX 0, 0, 252, 237 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Upesnit" +CAPTION "Upřesnit" FONT 8, "MS Shell Dlg" BEGIN ICON IDI_ACDC, IDI_ACDC, 7, 7, 20, 20 - LTEXT "Vyberte, kter nastaven snen spoteby chcete pout.", -1, 37, 6, 207, 20 - GROUPBOX "Monosti", -1, 6, 30, 240, 65 - CONTROL "Vdy zobrazovat &ikonu na hlavnm panelu", IDC_SYSTRAYBATTERYMETER, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 17, 43, 220, 10 - CONTROL "Dotzat se na &heslo pi pechodu z spornho reimu", IDC_PASSWORDLOGON, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 17, 60, 220, 10 - CONTROL "&Snit jas displeje pi chodu na baterie.", IDC_VIDEODIMDISPLAY, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 17, 78, 220, 10 - GROUPBOX "Tlatka napjen", -1, 6, 101, 240, 127 - LTEXT "&Pi sklopen displeje penosnho potae:", IDC_SLIDCLOSE, 15, 115, 222, 10 + LTEXT "Vyberte, které nastavení snížené spotřeby chcete použít.", -1, 37, 6, 207, 20 + GROUPBOX "Možnosti", -1, 6, 30, 240, 65 + CONTROL "Vždy zobrazovat &ikonu na hlavním panelu", IDC_SYSTRAYBATTERYMETER, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 17, 43, 220, 10 + CONTROL "Dotázat se na &heslo při přechodu z úsporného režimu", IDC_PASSWORDLOGON, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 17, 60, 220, 10 + CONTROL "&Snížit jas displeje při chodu na baterie.", IDC_VIDEODIMDISPLAY, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 17, 78, 220, 10 + GROUPBOX "Tlačítka napájení", -1, 6, 101, 240, 127 + LTEXT "&Při sklopení displeje přenosného počítače:", IDC_SLIDCLOSE, 15, 115, 222, 10 COMBOBOX IDC_LIDCLOSE, 15, 127, 220, 90, CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP - LTEXT "Pi stisknut tlatka &napjen:", IDC_SPOWERBUTTON, 15, 153, 222, 10 + LTEXT "Při stisknutí tlačítka &napájení:", IDC_SPOWERBUTTON, 15, 153, 222, 10 COMBOBOX IDC_POWERBUTTON, 15, 165, 220, 90, CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP - LTEXT "Pi stisknut tlatka reimu &spnku:", IDC_SSLEEPBUTTON, 15, 191, 222, 10 + LTEXT "Při stisknutí tlačítka režimu &spánku:", IDC_SSLEEPBUTTON, 15, 191, 222, 10 COMBOBOX IDC_SLEEPBUTTON, 15, 203, 220, 90, CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP END IDD_PROPPAGEHIBERNATE DIALOGEX 0, 0, 252, 237 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Reim spnku" +CAPTION "Režim spánku" FONT 8, "MS Shell Dlg" BEGIN ICON IDI_HIBERNATE, IDI_HIBERNATE, 7, 7, 20, 20 - LTEXT "Pokud V pota pejde do reimu spnku, ulo obsah sv pamti na pevn disk a vypne se. Po optovnm sputn se vrt do pvodnho stavu.", -1, 37, 6, 210, 35 - GROUPBOX "Reim spnku", -1, 6, 41, 240, 32 - CONTROL "Zapnout funkci reim &spnku", IDC_HIBERNATEFILE, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 17, 55, 210, 10 - GROUPBOX "Msto na disku potebn pro reim spnku", -1, 6, 80, 240, 76 - LTEXT "Voln msto:", -1, 15, 95, 140, 10 - LTEXT "Neznm", IDC_FREESPACE, 160, 95, 80, 10 - LTEXT "Potebn msto na disku:", -1, 15, 115, 140, 10 - LTEXT "Neznm", IDC_SPACEFORHIBERNATEFILE, 160, 115, 80, 10 - LTEXT "Pro funkci reim spnku muste uvolnit msto na disku. ", IDC_TOLESSFREESPACE, 15, 135, 224, 20 + LTEXT "Pokud Váš počítač přejde do režimu spánku, uloží obsah své paměti na pevný disk a vypne se. Po opětovném spuštění se vrátí do původního stavu.", -1, 37, 6, 210, 35 + GROUPBOX "Režim spánku", -1, 6, 41, 240, 32 + CONTROL "Zapnout funkci režim &spánku", IDC_HIBERNATEFILE, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 17, 55, 210, 10 + GROUPBOX "Místo na disku potřebné pro režim spánku", -1, 6, 80, 240, 76 + LTEXT "Volné místo:", -1, 15, 95, 140, 10 + LTEXT "Neznámé", IDC_FREESPACE, 160, 95, 80, 10 + LTEXT "Potřebné místo na disku:", -1, 15, 115, 140, 10 + LTEXT "Neznámé", IDC_SPACEFORHIBERNATEFILE, 160, 115, 80, 10 + LTEXT "Pro funkci režim spánku musíte uvolnit místo na disku. ", IDC_TOLESSFREESPACE, 15, 135, 224, 20 END STRINGTABLE BEGIN - IDS_CPLNAME_1 "Monosti napjen" - IDS_CPLDESCRIPTION_1 "Nastav monosti napjen a eten energi pro tento pota." + IDS_CPLNAME_1 "Možnosti napájení" + IDS_CPLDESCRIPTION_1 "Nastaví možnosti napájení a šetření energií pro tento počítač." IDS_PROCENT "%i%%" IDS_SOUND "Zvuk" IDS_TEXT "Text" - IDS_CONFIG1 "Nastaven pro schma napjen %1" - IDS_CONFIG2 "Pokroil nastaven pro %1" - IDS_SIZEBYTS "%i byt" + IDS_CONFIG1 "Nastavení pro schéma napájení %1" + IDS_CONFIG2 "Pokročilá nastavení pro %1" + IDS_SIZEBYTS "%i bytů" IDS_SIZEMB "%i MB" - IDS_NOACTION "Nedlat nic" - IDS_PowerActionNone1 "dn akce" - IDS_PowerActionUnknown "Neznm" - IDS_PowerActionSleep "sporn reim" - IDS_PowerActionHibernate "Reim spnku" + IDS_NOACTION "Nedělat nic" + IDS_PowerActionNone1 "Žádná akce" + IDS_PowerActionUnknown "Neznámý" + IDS_PowerActionSleep "Úsporný režim" + IDS_PowerActionHibernate "Režim spánku" IDS_PowerActionShutdown "Vypnout" IDS_PowerActionRestart "Restartovat" - IDS_PowerActionShutdownOff "Vypnout a odpojit napjen" - IDS_PowerActionWarmEject "Zeptat se na poadovanou akci" - IDS_PowerActionNone2 "Nen" - IDS_TIMEOUT1 "Po 1 minut" - IDS_TIMEOUT2 "Po 2 minutch" - IDS_TIMEOUT3 "Po 3 minutch" - IDS_TIMEOUT4 "Po 5 minutch" - IDS_TIMEOUT5 "Po 10 minutch" - IDS_TIMEOUT6 "Po 15 minutch" - IDS_TIMEOUT7 "Po 20 minutch" - IDS_TIMEOUT8 "Po 25 minutch" - IDS_TIMEOUT9 "Po 30 minutch" - IDS_TIMEOUT10 "Po 45 minutch" - IDS_TIMEOUT11 "Po 1 hodin" - IDS_TIMEOUT12 "Po 2 hodinch" - IDS_TIMEOUT13 "Po 3 hodinch" - IDS_TIMEOUT14 "Po 4 hodinch" - IDS_TIMEOUT15 "Po 5 hodinch" + IDS_PowerActionShutdownOff "Vypnout a odpojit napájení" + IDS_PowerActionWarmEject "Zeptat se na požadovanou akci" + IDS_PowerActionNone2 "Není" + IDS_TIMEOUT1 "Po 1 minutě" + IDS_TIMEOUT2 "Po 2 minutách" + IDS_TIMEOUT3 "Po 3 minutách" + IDS_TIMEOUT4 "Po 5 minutách" + IDS_TIMEOUT5 "Po 10 minutách" + IDS_TIMEOUT6 "Po 15 minutách" + IDS_TIMEOUT7 "Po 20 minutách" + IDS_TIMEOUT8 "Po 25 minutách" + IDS_TIMEOUT9 "Po 30 minutách" + IDS_TIMEOUT10 "Po 45 minutách" + IDS_TIMEOUT11 "Po 1 hodině" + IDS_TIMEOUT12 "Po 2 hodinách" + IDS_TIMEOUT13 "Po 3 hodinách" + IDS_TIMEOUT14 "Po 4 hodinách" + IDS_TIMEOUT15 "Po 5 hodinách" IDS_TIMEOUT16 "Nikdy" - IDS_DEL_SCHEME "Opravdu si pejete smazat toto schma napjen?" - IDS_DEL_SCHEME_TITLE "Smazat schma" + IDS_DEL_SCHEME "Opravdu si přejete smazat toto schéma napájení?" + IDS_DEL_SCHEME_TITLE "Smazat schéma" END diff --git a/dll/cpl/powercfg/powercfg.rc b/dll/cpl/powercfg/powercfg.rc index 944667529f0..0a1e3ea2c9d 100644 --- a/dll/cpl/powercfg/powercfg.rc +++ b/dll/cpl/powercfg/powercfg.rc @@ -23,9 +23,6 @@ IDI_HIBERNATE ICON "resources/hibernate.ico" #ifdef LANGUAGE_BG_BG #include "lang/bg-BG.rc" #endif -#ifdef LANGUAGE_CS_CZ - #include "lang/cs-CZ.rc" -#endif #ifdef LANGUAGE_DE_DE #include "lang/de-DE.rc" #endif @@ -72,6 +69,9 @@ IDI_HIBERNATE ICON "resources/hibernate.ico" /* UTF-8 */ #pragma code_page(65001) +#ifdef LANGUAGE_CS_CZ + #include "lang/cs-CZ.rc" +#endif #ifdef LANGUAGE_HE_IL #include "lang/he-IL.rc" #endif diff --git a/dll/cpl/timedate/lang/cs-CZ.rc b/dll/cpl/timedate/lang/cs-CZ.rc index d747d5a2674..eb347436365 100644 --- a/dll/cpl/timedate/lang/cs-CZ.rc +++ b/dll/cpl/timedate/lang/cs-CZ.rc @@ -2,7 +2,7 @@ LANGUAGE LANG_CZECH, SUBLANG_DEFAULT IDD_DATETIMEPAGE DIALOGEX 0, 0, 252, 146 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Datum && as" +CAPTION "Datum && Čas" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN GROUPBOX "&Datum", -1, 4, 2, 122, 125 @@ -11,7 +11,7 @@ BEGIN CONTROL "", IDC_YEAR, UPDOWN_CLASS, UDS_SETBUDDYINT | UDS_NOTHOUSANDS | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | WS_BORDER | WS_GROUP, 120, 17, 50, 12 CONTROL "", IDC_MONTHCALENDAR, "MonthCalWnd", WS_CHILD | WS_VISIBLE | WS_TABSTOP, 11, 37, 108, 80, WS_EX_CLIENTEDGE - GROUPBOX "&as", -1, 132, 2, 113, 125 + GROUPBOX "&Čas", -1, 132, 2, 113, 125 CONTROL "", IDC_TIMEPICKER, "SysDateTimePick32", DTS_TIMEFORMAT | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 144, 105, 90, 12 LTEXT "", IDC_TIMEZONE, 6, 132, 242, 11 CONTROL "", IDC_CLOCKWND, "ClockWndClass", WS_CHILD | WS_VISIBLE, 138, 12, 102, 89 @@ -19,39 +19,39 @@ END IDD_TIMEZONEPAGE DIALOGEX 0, 0, 252, 146 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "asov psmo" +CAPTION "Časové pásmo" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN COMBOBOX IDC_TIMEZONELIST, 5, 4, 241, 136, CBS_DROPDOWNLIST | WS_VSCROLL | WS_VISIBLE | WS_TABSTOP CONTROL "", IDC_WORLD_BACKGROUND, "Static", SS_OWNERDRAW, 5, 20, 240, 110, WS_EX_STATICEDGE - AUTOCHECKBOX "Provdt zmnu na letn as a zpt automaticky", + AUTOCHECKBOX "Provádět změnu na letní čas a zpět automaticky", IDC_AUTODAYLIGHT, 6, 132, 242, 11, WS_VISIBLE | WS_GROUP | WS_TABSTOP END IDD_INETTIMEPAGE DIALOGEX 0, 0, 252, 146 STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "as v Internetu" +CAPTION "Čas v Internetu" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN COMBOBOX IDC_SERVERLIST, 65, 22, 117, 136, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - AUTOCHECKBOX "Automaticky synchronizovat as s asovm serverem v Internetu", + AUTOCHECKBOX "Automaticky synchronizovat čas s časovým serverem v Internetu", IDC_AUTOSYNC, 11, 7, 241, 10, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP LTEXT "Server:", IDC_SERVERTEXT, 34, 22, 28, 13 PUSHBUTTON "Aktualizovat", IDC_UPDATEBUTTON, 187, 22, 49, 14 LTEXT "", IDC_SUCSYNC, 16, 54, 214, 23 LTEXT "", IDC_NEXTSYNC, 12, 96, 137, 12 - LTEXT "Synchronizace me probhnout pouze v ppad, e je pota pipojen k sti Internet.", -1, 12, 114, 225, 25 + LTEXT "Synchronizace může proběhnout pouze v případě, že je počítač připojen k síti Internet.", -1, 12, 114, 225, 25 END STRINGTABLE BEGIN - IDS_CPLNAME "Datum/as" - IDS_CPLDESCRIPTION "Nastavuje datum, as a zmny asovho psma." - IDS_TIMEZONETEXT "Aktuln asov psmo: %s" - IDS_TIMEZONEINVALID "Neplatn" - IDS_TIMEZONEUNKNOWN "Neznm" - IDS_INETTIMESUCSYNC "as byl spn synchronizovn z %s %s v %s" - IDS_INETTIMENEXTSYNC "Dal synchronizace: %s v %s" - IDS_INETTIMESYNCING "Prosm ekejte, zatmco systm ReactOS synchronizuje as s %s" - IDS_INETTIMEERROR "Pi synchronizaci asu s %s nastala chyba" + IDS_CPLNAME "Datum/Čas" + IDS_CPLDESCRIPTION "Nastavuje datum, čas a změny časového pásma." + IDS_TIMEZONETEXT "Aktuální časové pásmo: %s" + IDS_TIMEZONEINVALID "Neplatné" + IDS_TIMEZONEUNKNOWN "Neznámé" + IDS_INETTIMESUCSYNC "Čas byl úspěšně synchronizován z %s %s v %s" + IDS_INETTIMENEXTSYNC "Další synchronizace: %s v %s" + IDS_INETTIMESYNCING "Prosím čekejte, zatímco systém ReactOS synchronizuje čas s %s" + IDS_INETTIMEERROR "Při synchronizaci času s %s nastala chyba" END diff --git a/dll/cpl/timedate/timedate.rc b/dll/cpl/timedate/timedate.rc index 701c66f0897..34df4980078 100644 --- a/dll/cpl/timedate/timedate.rc +++ b/dll/cpl/timedate/timedate.rc @@ -20,9 +20,6 @@ IDC_WORLD BITMAP "resources/world.bmp" #ifdef LANGUAGE_BG_BG #include "lang/bg-BG.rc" #endif -#ifdef LANGUAGE_CS_CZ - #include "lang/cs-CZ.rc" -#endif #ifdef LANGUAGE_DA_DK #include "lang/da-DK.rc" #endif @@ -78,6 +75,9 @@ IDC_WORLD BITMAP "resources/world.bmp" /* UTF-8 */ #pragma code_page(65001) +#ifdef LANGUAGE_CS_CZ + #include "lang/cs-CZ.rc" +#endif #ifdef LANGUAGE_HE_IL #include "lang/he-IL.rc" #endif diff --git a/dll/cpl/usrmgr/lang/cs-CZ.rc b/dll/cpl/usrmgr/lang/cs-CZ.rc new file mode 100644 index 00000000000..96d2228182f --- /dev/null +++ b/dll/cpl/usrmgr/lang/cs-CZ.rc @@ -0,0 +1,218 @@ +/* FILE: dll/cpl/usrmgr/lang/cs-CZ.rc + * TRANSLATOR: Radek Liska aka Black_Fox (radekliska at gmail dot com) + * UPDATED: 2014-04-21 + */ + + LANGUAGE LANG_CZECH, SUBLANG_DEFAULT + +/* Dialogs */ + +IDD_USERS DIALOGEX 0, 0, 252, 223 +STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Uživatelé" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "", IDC_USERS_LIST, "SysListView32", LVS_REPORT | LVS_EDITLABELS | LVS_SINGLESEL | + LVS_SHOWSELALWAYS | LVS_SORTASCENDING | WS_BORDER | WS_TABSTOP, 7, 7, 238, 85, WS_EX_CLIENTEDGE + PUSHBUTTON "&Přidat...", IDC_USERS_ADD, 87, 98, 50, 14 + PUSHBUTTON "&Odebrat", IDC_USERS_REMOVE, 141, 98, 50, 14 + PUSHBUTTON "&Vlastnosti", IDC_USERS_PROPERTIES, 195, 98, 50, 14 + AUTOCHECKBOX "Vyžadovat uživatelské jméno a heslo při spuštění sytému.", IDC_USERS_STARTUP_REQUIRE, 10, 118, 200, 14, WS_DISABLED + PUSHBUTTON "Reset Password", IDC_USERS_RESET, 165, 200, 80, 14, WS_DISABLED +END + +IDD_GROUPS DIALOGEX 0, 0, 252, 223 +STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Skupiny" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "", IDC_GROUPS_LIST, "SysListView32", LVS_REPORT | LVS_EDITLABELS | LVS_SINGLESEL | + LVS_SHOWSELALWAYS | LVS_SORTASCENDING | WS_BORDER | WS_TABSTOP, 7, 7, 238, 85, WS_EX_CLIENTEDGE + PUSHBUTTON "&Přidat...", IDC_GROUPS_ADD, 87, 98, 50, 14 + PUSHBUTTON "&Odebrat", IDC_GROUPS_REMOVE, 141, 98, 50, 14 + PUSHBUTTON "&Vlastnosti", IDC_GROUPS_PROPERTIES, 195, 98, 50, 14 +END + +IDD_EXTRA DIALOGEX 0, 0, 252, 223 +STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Další" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "Tady zatím nic není", IDC_STATIC, 66, 90, 112, 8 +END + +IDD_USER_GENERAL DIALOGEX 0, 0, 252, 223 +STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Obecné" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "", IDC_USER_GENERAL_NAME, 7, 12, 112, 8 + LTEXT "Celé jméno:", -1, 7, 46, 63, 8 + EDITTEXT IDC_USER_GENERAL_FULL_NAME, 77, 43, 168, 13, ES_AUTOHSCROLL + LTEXT "Popis:", -1, 7, 64, 63, 8 + EDITTEXT IDC_USER_GENERAL_DESCRIPTION, 77, 61, 168, 13, ES_AUTOHSCROLL + AUTOCHECKBOX "Uživatel musí změnit heslo po prvním přihlášení", IDC_USER_GENERAL_FORCE_CHANGE, 7, 82, 210, 10 + AUTOCHECKBOX "Uživatel nemůže měnit heslo", IDC_USER_GENERAL_CANNOT_CHANGE, 7, 95, 210, 10 + AUTOCHECKBOX "Platnost hesla je neomezená", IDC_USER_GENERAL_NEVER_EXPIRES, 7, 108, 210, 10 + AUTOCHECKBOX "Účet je vypnutý", IDC_USER_GENERAL_DISABLED, 7, 121, 210, 10 + AUTOCHECKBOX "Účet je zamčený", IDC_USER_GENERAL_LOCKED, 7, 134, 210, 10 +END + +IDD_USER_MEMBERSHIP DIALOGEX 0, 0, 252, 223 +STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Členství" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "Člen:", -1, 7, 7, 56, 8 + CONTROL "", IDC_USER_MEMBERSHIP_LIST, "SysListView32", LVS_REPORT | LVS_NOCOLUMNHEADER | + LVS_SORTASCENDING | WS_BORDER | WS_TABSTOP, 7, 18, 238, 173, WS_EX_CLIENTEDGE + PUSHBUTTON "Přidat...", IDC_USER_MEMBERSHIP_ADD, 7, 197, 50, 14 + PUSHBUTTON "Odebrat", IDC_USER_MEMBERSHIP_REMOVE, 61, 197, 50, 14, WS_DISABLED +END + +IDD_USER_PROFILE DIALOGEX 0, 0, 252, 223 +STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Profil" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Uživatelský profil", -1, 7, 7, 238, 54 + LTEXT "Cesta k profilu:", -1, 16, 22, 55, 8 + EDITTEXT IDC_USER_PROFILE_PATH, 78, 19, 160, 13, ES_AUTOHSCROLL + LTEXT "Přihlašovací skript:", -1, 16, 40, 55, 8 + EDITTEXT IDC_USER_PROFILE_SCRIPT, 78, 37, 160, 13, ES_AUTOHSCROLL + GROUPBOX "Domovský adresář", -1, 7, 68, 238, 54 + AUTORADIOBUTTON "Místní cesta:", IDC_USER_PROFILE_LOCAL, 16, 83, 60, 10 + AUTORADIOBUTTON "Připojit:", IDC_USER_PROFILE_REMOTE, 16, 100, 60, 10 + EDITTEXT IDC_USER_PROFILE_LOCAL_PATH, 78, 81, 160, 13, ES_AUTOHSCROLL + COMBOBOX IDC_USER_PROFILE_DRIVE, 78, 99, 26, 160, CBS_DROPDOWNLIST | CBS_SORT | + WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL + LTEXT "k:", -1, 112, 101, 12, 8 + EDITTEXT IDC_USER_PROFILE_REMOTE_PATH, 130, 99, 108, 13, ES_AUTOHSCROLL +END + +IDD_GROUP_GENERAL DIALOGEX 0, 0, 252, 223 +STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Obecné" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "", IDC_GROUP_GENERAL_NAME, 7, 12, 112, 8 + LTEXT "Popis:", -1, 7, 45, 46, 8 + EDITTEXT IDC_GROUP_GENERAL_DESCRIPTION, 65, 42, 180, 13, ES_AUTOHSCROLL + LTEXT "Členové:", -1, 7, 63, 45, 8 + CONTROL "", IDC_GROUP_GENERAL_MEMBERS, "SysListView32", LVS_REPORT | LVS_NOCOLUMNHEADER | + LVS_SHOWSELALWAYS | LVS_SORTASCENDING | WS_BORDER | WS_TABSTOP, 7, 74, 238, 117, WS_EX_CLIENTEDGE + PUSHBUTTON "Přidat...", IDC_GROUP_GENERAL_ADD, 7, 197, 50, 14 + PUSHBUTTON "Odebrat", IDC_GROUP_GENERAL_REMOVE, 61, 197, 50, 14, WS_DISABLED +END + +IDD_CHANGE_PASSWORD DIALOGEX 0, 0, 267, 74 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_SHELLFONT +CAPTION "Změna hesla" +FONT 8, "MS Shell Dlg" +BEGIN + EDITTEXT IDC_EDIT_PASSWORD1, 107, 7, 153, 14, ES_AUTOHSCROLL | ES_PASSWORD + RTEXT "Nové heslo:", -1, 7, 10, 96, 8 + EDITTEXT IDC_EDIT_PASSWORD2, 107, 25, 153, 14, ES_AUTOHSCROLL | ES_PASSWORD + RTEXT "Nové heslo znovu:", -1, 7, 28, 96, 8 + DEFPUSHBUTTON "OK", IDOK, 156, 53, 50, 14 + PUSHBUTTON "Storno", IDCANCEL, 210, 53, 50, 14 +END + +IDD_USER_NEW DIALOGEX 0, 0, 267, 200 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_SHELLFONT +CAPTION "Nový uživatel" +FONT 8, "MS Shell Dlg" +BEGIN + EDITTEXT IDC_USER_NEW_NAME, 107, 7, 153, 14, ES_AUTOHSCROLL + RTEXT "Uživatelské jméno:", -1, 7, 10, 96, 8 + EDITTEXT IDC_USER_NEW_FULL_NAME, 107, 25, 153, 14, ES_AUTOHSCROLL + RTEXT "Celé jméno uživatele:", -1, 7, 28, 96, 8 + EDITTEXT IDC_USER_NEW_DESCRIPTION, 107, 43, 153, 14, ES_AUTOHSCROLL + RTEXT "Popis:", -1, 7, 46, 96, 8 + EDITTEXT IDC_USER_NEW_PASSWORD1, 107, 67, 153, 14, ES_AUTOHSCROLL | ES_PASSWORD + RTEXT "Heslo:", -1, 7, 70, 96, 8 + EDITTEXT IDC_USER_NEW_PASSWORD2, 107, 85, 153, 14, ES_AUTOHSCROLL | ES_PASSWORD + RTEXT "Heslo znovu:", -1, 7, 88, 96, 8 + AUTOCHECKBOX "Uživatel musí změnit heslo po prvním přihlášení", IDC_USER_NEW_FORCE_CHANGE, 7, 109, 200, 10 + AUTOCHECKBOX "Uživatel nemůže měnit heslo", IDC_USER_NEW_CANNOT_CHANGE, 7, 123, 200, 10, WS_DISABLED + AUTOCHECKBOX "Platnost hesla je neomezená", IDC_USER_NEW_NEVER_EXPIRES, 7, 137, 200, 10, WS_DISABLED + AUTOCHECKBOX "Účet je vypnutý", IDC_USER_NEW_DISABLED, 7, 151, 200, 10 + DEFPUSHBUTTON "OK", IDOK, 156, 179, 50, 14, WS_DISABLED + PUSHBUTTON "Storno", IDCANCEL, 210, 179, 50, 14 +END + +IDD_GROUP_NEW DIALOGEX 0, 0, 267, 74 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_SHELLFONT +CAPTION "Nová skupina" +FONT 8, "MS Shell Dlg" +BEGIN + EDITTEXT IDC_GROUP_NEW_NAME, 107, 7, 153, 14, ES_AUTOHSCROLL + RTEXT "Jméno skupiny:", -1, 7, 10, 96, 8 + EDITTEXT IDC_GROUP_NEW_DESCRIPTION, 107, 25, 153, 14, ES_AUTOHSCROLL + RTEXT "Popis:", -1, 7, 28, 96, 8 + DEFPUSHBUTTON "OK", IDOK, 156, 53, 50, 14, WS_DISABLED + PUSHBUTTON "Storno", IDCANCEL, 210, 53, 50, 14 +END + +IDD_USER_ADD_MEMBERSHIP DIALOGEX 0, 0, 252, 223 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_SHELLFONT +CAPTION "Členství ve skupině" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "Člen:", -1, 7, 7, 56, 8 + CONTROL "", IDC_USER_ADD_MEMBERSHIP_LIST, "SysListView32", LVS_REPORT | LVS_SHOWSELALWAYS | + LVS_SORTASCENDING | WS_BORDER | WS_TABSTOP, 7, 18, 238, 173, WS_EX_CLIENTEDGE + DEFPUSHBUTTON "OK", IDOK, 141, 197, 50, 14 + PUSHBUTTON "Storno", IDCANCEL, 195, 197, 50, 14 +END + +/* Menus */ + +IDM_POPUP_GROUP MENU +BEGIN + POPUP "" + BEGIN + MENUITEM "Nová skupina...", IDM_GROUP_NEW + END + POPUP "" + BEGIN + MENUITEM "Přidat člena", IDM_GROUP_ADD_MEMBER, GRAYED + MENUITEM SEPARATOR + MENUITEM "Odstranit", IDM_GROUP_DELETE + MENUITEM "Přejmenovat", IDM_GROUP_RENAME + MENUITEM SEPARATOR + MENUITEM "Vlastnosti", IDM_GROUP_PROPERTIES + END +END + +IDM_POPUP_USER MENU +BEGIN + POPUP "" + BEGIN + MENUITEM "Nový uživatel...", IDM_USER_NEW + END + POPUP "" + BEGIN + MENUITEM "Změnit heslo", IDM_USER_CHANGE_PASSWORD + MENUITEM SEPARATOR + MENUITEM "Odstranit", IDM_USER_DELETE + MENUITEM "Přejmenovat", IDM_USER_RENAME + MENUITEM SEPARATOR + MENUITEM "Vlastnosti", IDM_USER_PROPERTIES + END +END + +/* Strings */ + +STRINGTABLE +BEGIN + IDS_CPLNAME "Uživatelské účty" + IDS_CPLDESCRIPTION "Spravuje uživatele a skupiny." +END + +STRINGTABLE +BEGIN + IDS_NAME "Jméno" + IDS_FULLNAME "Celé jméno" + IDS_DESCRIPTION "Popis" +END diff --git a/dll/cpl/usrmgr/usrmgr.rc b/dll/cpl/usrmgr/usrmgr.rc index 0fe2763b982..2cecdc45a77 100644 --- a/dll/cpl/usrmgr/usrmgr.rc +++ b/dll/cpl/usrmgr/usrmgr.rc @@ -37,6 +37,9 @@ IDI_GROUP ICON "resources/group.ico" /* UTF-8 */ #pragma code_page(65001) +#ifdef LANGUAGE_CS_CZ + #include "lang/cs-CZ.rc" +#endif #ifdef LANGUAGE_PL_PL #include "lang/pl-PL.rc" #endif diff --git a/dll/directx/wine/msdmo/dmoreg.c b/dll/directx/wine/msdmo/dmoreg.c index 48968b37798..84c1ed93a38 100644 --- a/dll/directx/wine/msdmo/dmoreg.c +++ b/dll/directx/wine/msdmo/dmoreg.c @@ -607,9 +607,9 @@ static HRESULT WINAPI IEnumDMO_fnNext( hres = RegQueryValueExW(hkey, NULL, NULL, NULL, (LPBYTE) szValue, &len); if (ERROR_SUCCESS == hres) { - Names[count] = HeapAlloc(GetProcessHeap(), 0, strlenW(szValue) + 1); + Names[count] = HeapAlloc(GetProcessHeap(), 0, (strlenW(szValue) + 1) * sizeof(WCHAR)); if (Names[count]) - strcmpW(Names[count], szValue); + strcpyW(Names[count], szValue); } wsprintfW(szGuidKey,szToGuidFmt,szNextKey); CLSIDFromString(szGuidKey, &pCLSID[count]); diff --git a/dll/directx/wine/quartz/avisplit.c b/dll/directx/wine/quartz/avisplit.c index f3c8ddce968..f651cf78167 100644 --- a/dll/directx/wine/quartz/avisplit.c +++ b/dll/directx/wine/quartz/avisplit.c @@ -803,7 +803,7 @@ static HRESULT AVISplitter_ProcessStreamList(AVISplitterImpl * This, const BYTE TRACE("dwChunkId: %.4s\n", (const char *)&pIndex->dwChunkId); if (pIndex->dwReserved[0]) TRACE("dwReserved[0]: %u\n", pIndex->dwReserved[0]); - if (pIndex->dwReserved[2]) + if (pIndex->dwReserved[1]) TRACE("dwReserved[1]: %u\n", pIndex->dwReserved[1]); if (pIndex->dwReserved[2]) TRACE("dwReserved[2]: %u\n", pIndex->dwReserved[2]); diff --git a/dll/ntdll/CMakeLists.txt b/dll/ntdll/CMakeLists.txt index afa15fd2c24..d99009315ac 100644 --- a/dll/ntdll/CMakeLists.txt +++ b/dll/ntdll/CMakeLists.txt @@ -40,6 +40,7 @@ add_library(ntdll SHARED ${SOURCE} ${ntdll_asm} def/ntdll.rc + ${CMAKE_CURRENT_BINARY_DIR}/ntdll_stubs.c ${CMAKE_CURRENT_BINARY_DIR}/ntdll.def) set_module_type(ntdll win32dll HOTPATCHABLE ENTRYPOINT 0) diff --git a/dll/ntdll/csr/capture.c b/dll/ntdll/csr/capture.c index d22644b5992..0a779eca9f9 100644 --- a/dll/ntdll/csr/capture.c +++ b/dll/ntdll/csr/capture.c @@ -101,6 +101,9 @@ CsrAllocateCaptureBuffer(IN ULONG ArgumentCount, /* Align it to a 4-byte boundary */ BufferSize = (BufferSize + 3) & ~3; + /* Add the size of the alignment padding for each argument */ + BufferSize += ArgumentCount * 3; + /* Allocate memory from the port heap */ CaptureBuffer = RtlAllocateHeap(CsrPortHeap, HEAP_ZERO_MEMORY, BufferSize); if (CaptureBuffer == NULL) return NULL; diff --git a/dll/ntdll/def/ntdll.spec b/dll/ntdll/def/ntdll.spec index 4ed630d4604..c649d574d51 100644 --- a/dll/ntdll/def/ntdll.spec +++ b/dll/ntdll/def/ntdll.spec @@ -175,7 +175,7 @@ @ stdcall NtGetCurrentProcessorNumber() ; 5.2 and higher @ stdcall NtGetDevicePowerState(ptr ptr) @ stdcall NtGetPlugPlayEvent(long long ptr long) -;@ stdcall NtGetTickCount() +@ stdcall NtGetTickCount() RtlGetTickCount @ stdcall NtGetWriteWatch(long long ptr long ptr ptr ptr) @ stdcall NtImpersonateAnonymousToken(ptr) @ stdcall NtImpersonateClientOfPort(ptr ptr) @@ -1051,7 +1051,7 @@ @ stdcall ZwGetCurrentProcessorNumber() @ stdcall ZwGetDevicePowerState(ptr ptr) @ stdcall ZwGetPlugPlayEvent(long long ptr long) -;@ stdcall ZwGetTickCount() NtGetTickCount +@ stdcall ZwGetTickCount() RtlGetTickCount @ stdcall ZwGetWriteWatch(long long ptr long ptr ptr ptr) NtGetWriteWatch @ stdcall ZwImpersonateAnonymousToken(ptr) @ stdcall ZwImpersonateClientOfPort(ptr ptr) NtImpersonateClientOfPort diff --git a/dll/ntdll/rtl/libsupp.c b/dll/ntdll/rtl/libsupp.c index 9ceb2b0bda2..69d58f36f89 100644 --- a/dll/ntdll/rtl/libsupp.c +++ b/dll/ntdll/rtl/libsupp.c @@ -613,4 +613,32 @@ RtlpSafeCopyMemory( return STATUS_SUCCESS; } +/* FIXME: code duplication with kernel32/client/time.c */ +ULONG +NTAPI +RtlGetTickCount(VOID) +{ + ULARGE_INTEGER TickCount; + +#ifdef _WIN64 + TickCount.QuadPart = *((volatile ULONG64*)&SharedUserData->TickCount); +#else + while (TRUE) + { + TickCount.HighPart = (ULONG)SharedUserData->TickCount.High1Time; + TickCount.LowPart = SharedUserData->TickCount.LowPart; + + if (TickCount.HighPart == (ULONG)SharedUserData->TickCount.High2Time) + break; + + YieldProcessor(); + } +#endif + + return (ULONG)((UInt32x32To64(TickCount.LowPart, + SharedUserData->TickCountMultiplier) >> 24) + + UInt32x32To64((TickCount.HighPart << 8) & 0xFFFFFFFF, + SharedUserData->TickCountMultiplier)); +} + /* EOF */ diff --git a/dll/win32/atl/CMakeLists.txt b/dll/win32/atl/CMakeLists.txt index 1d7d6bbc536..580e31c495b 100644 --- a/dll/win32/atl/CMakeLists.txt +++ b/dll/win32/atl/CMakeLists.txt @@ -23,6 +23,5 @@ add_library(atl SHARED ${SOURCE} rsrc.rc) set_module_type(atl win32dll) target_link_libraries(atl uuid wine) add_importlibs(atl oleaut32 ole32 user32 gdi32 advapi32 msvcrt kernel32 ntdll) -add_dependencies(atl atl_atliface_header) add_pch(atl precomp.h SOURCE) add_cd_file(TARGET atl DESTINATION reactos/system32 FOR all) diff --git a/dll/win32/comctl32/treeview.c b/dll/win32/comctl32/treeview.c index ec60708de55..73e5ca0a3c9 100644 --- a/dll/win32/comctl32/treeview.c +++ b/dll/win32/comctl32/treeview.c @@ -5242,6 +5242,10 @@ TREEVIEW_KeyDown(TREEVIEW_INFO *infoPtr, WPARAM wParam) newSelection = TREEVIEW_GetNextListItem(infoPtr, prevItem); break; + case VK_RETURN: + TREEVIEW_SendSimpleNotify(infoPtr, NM_RETURN); + break; + case VK_HOME: newSelection = infoPtr->root->firstChild; break; diff --git a/dll/win32/icmp/icmp_main.c b/dll/win32/icmp/icmp_main.c index 8257c1156b1..187b310f0a6 100644 --- a/dll/win32/icmp/icmp_main.c +++ b/dll/win32/icmp/icmp_main.c @@ -179,6 +179,7 @@ HANDLE WINAPI IcmpCreateFile(VOID) icp=HeapAlloc(GetProcessHeap(), 0, sizeof(*icp)); if (icp==NULL) { + closesocket(sid); SetLastError(IP_NO_RESOURCES); return INVALID_HANDLE_VALUE; } diff --git a/dll/win32/ieframe/shelluihelper.c b/dll/win32/ieframe/shelluihelper.c index f5141659906..5399cd56bb2 100644 --- a/dll/win32/ieframe/shelluihelper.c +++ b/dll/win32/ieframe/shelluihelper.c @@ -41,7 +41,7 @@ static HRESULT WINAPI ShellUIHelper2_QueryInterface(IShellUIHelper2 *iface, REFI }else if(IsEqualGUID(&IID_IShellUIHelper, riid)) { TRACE("(%p)->(IID_IShellUIHelper %p)\n", This, ppv); *ppv = &This->IShellUIHelper2_iface; - }else if(IsEqualGUID(&IID_IShellUIHelper, riid)) { + }else if(IsEqualGUID(&IID_IShellUIHelper2, riid)) { TRACE("(%p)->(IID_IShellUIHelper2 %p)\n", This, ppv); *ppv = &This->IShellUIHelper2_iface; }else { diff --git a/dll/win32/kernel32/client/proc.c b/dll/win32/kernel32/client/proc.c index 0f3bc305d03..84bcd6d2509 100644 --- a/dll/win32/kernel32/client/proc.c +++ b/dll/win32/kernel32/client/proc.c @@ -2301,7 +2301,7 @@ CreateProcessInternalW(IN HANDLE hUserToken, BOOLEAN InJob, SaferNeeded, UseLargePages, HavePrivilege; BOOLEAN QuerySection, SkipSaferAndAppCompat; CONTEXT Context; - BASE_API_MESSAGE CsrMsg; + BASE_API_MESSAGE CsrMsg[2]; PBASE_CREATE_PROCESS CreateProcessMsg; PCSR_CAPTURE_BUFFER CaptureBuffer; PVOID BaseAddress, PrivilegeState, RealTimePrivilegeState; @@ -2431,8 +2431,8 @@ CreateProcessInternalW(IN HANDLE hUserToken, IsWowApp = FALSE; /* Set message structures */ - CreateProcessMsg = &CsrMsg.Data.CreateProcessRequest; - CheckVdmMsg = &CsrMsg.Data.CheckVDMRequest; + CreateProcessMsg = &CsrMsg[0].Data.CreateProcessRequest; + CheckVdmMsg = &CsrMsg[1].Data.CheckVDMRequest; /* Clear the more complex structures by zeroing out their entire memory */ RtlZeroMemory(&Context, sizeof(Context)); @@ -3197,7 +3197,7 @@ StartScan: /* Pick which kind of WOW mode we want to run in */ VdmBinaryType = (dwCreationFlags & CREATE_SEPARATE_WOW_VDM) ? - BINARY_TYPE_WOW : BINARY_TYPE_SEPARATE_WOW; + BINARY_TYPE_SEPARATE_WOW : BINARY_TYPE_WOW; /* Get all the VDM settings and current status */ Status = BaseCheckVDM(VdmBinaryType, @@ -3205,7 +3205,7 @@ StartScan: lpCommandLine, lpCurrentDirectory, &VdmAnsiEnv, - &CsrMsg, + &CsrMsg[1], &VdmTask, dwCreationFlags, &StartupInfo, @@ -3342,7 +3342,7 @@ StartScan: lpCommandLine, lpCurrentDirectory, &VdmAnsiEnv, - &CsrMsg, + &CsrMsg[1], &VdmTask, dwCreationFlags, &StartupInfo, @@ -3966,6 +3966,8 @@ StartScan: &VdmWaitObject, VdmTask, VdmBinaryType); + + if (!Result) { /* Bail out on failure */ DPRINT1("Failed to update VDM with wait object\n"); @@ -4335,7 +4337,7 @@ StartScan: } /* We are finally ready to call CSRSS to tell it about our new process! */ - CsrClientCallServer((PCSR_API_MESSAGE)&CsrMsg, + CsrClientCallServer((PCSR_API_MESSAGE)&CsrMsg[0], CaptureBuffer, CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepCreateProcess), @@ -4349,12 +4351,12 @@ StartScan: } /* Check if CSRSS failed to accept ownership of the new Windows process */ - if (!NT_SUCCESS(CsrMsg.Status)) + if (!NT_SUCCESS(CsrMsg[0].Status)) { /* Terminate the process and enter failure path with the CSRSS status */ DPRINT1("Failed to tell csrss about new process\n"); - BaseSetLastNTError(CsrMsg.Status); - NtTerminateProcess(ProcessHandle, CsrMsg.Status); + BaseSetLastNTError(CsrMsg[0].Status); + NtTerminateProcess(ProcessHandle, CsrMsg[0].Status); Result = FALSE; goto Quickie; } diff --git a/dll/win32/kernel32/client/time.c b/dll/win32/kernel32/client/time.c index aee6d8ab169..abba55b6a90 100644 --- a/dll/win32/kernel32/client/time.c +++ b/dll/win32/kernel32/client/time.c @@ -446,6 +446,9 @@ GetTickCount(VOID) { ULARGE_INTEGER TickCount; +#ifdef _WIN64 + TickCount.QuadPart = *((volatile ULONG64*)&SharedUserData->TickCount); +#else while (TRUE) { TickCount.HighPart = (ULONG)SharedUserData->TickCount.High1Time; @@ -456,6 +459,7 @@ GetTickCount(VOID) YieldProcessor(); } +#endif return (ULONG)((UInt32x32To64(TickCount.LowPart, SharedUserData->TickCountMultiplier) >> 24) + diff --git a/dll/win32/kernel32/client/vdm.c b/dll/win32/kernel32/client/vdm.c index 3ff2c466168..c37a3cf3589 100644 --- a/dll/win32/kernel32/client/vdm.c +++ b/dll/win32/kernel32/client/vdm.c @@ -64,7 +64,7 @@ BaseIsDosApplication(IN PUNICODE_STRING PathName, return 0; } -BOOL +NTSTATUS WINAPI BaseCheckVDM(IN ULONG BinaryType, IN PCWCH ApplicationName, @@ -77,9 +77,354 @@ BaseCheckVDM(IN ULONG BinaryType, IN LPSTARTUPINFOW StartupInfo, IN HANDLE hUserToken OPTIONAL) { - /* This is not supported */ - UNIMPLEMENTED; - return FALSE; + NTSTATUS Status; + PBASE_CHECK_VDM CheckVdm = &ApiMessage->Data.CheckVDMRequest; + PCSR_CAPTURE_BUFFER CaptureBuffer; + PWCHAR CurrentDir = NULL; + PWCHAR ShortAppName = NULL; + PWCHAR ShortCurrentDir = NULL; + ULONG Length; + PCHAR AnsiCmdLine = NULL; + PCHAR AnsiAppName = NULL; + PCHAR AnsiCurDirectory = NULL; + PCHAR AnsiDesktop = NULL; + PCHAR AnsiTitle = NULL; + PCHAR AnsiReserved = NULL; + STARTUPINFOA AnsiStartupInfo; + ULONG NumStrings = 5; + + if (CurrentDirectory == NULL) + { + /* Allocate memory for the current directory path */ + Length = GetCurrentDirectoryW(0, NULL); + CurrentDir = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + Length * sizeof(WCHAR)); + if (CurrentDir == NULL) + { + Status = STATUS_NO_MEMORY; + goto Cleanup; + } + + /* Get the current directory */ + GetCurrentDirectoryW(Length, CurrentDir); + CurrentDirectory = CurrentDir; + } + + /* Calculate the size of the short application name */ + Length = GetShortPathNameW(ApplicationName, NULL, 0); + + /* Allocate memory for the short application name */ + ShortAppName = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + Length * sizeof(WCHAR)); + if (!ShortAppName) + { + Status = STATUS_NO_MEMORY; + goto Cleanup; + } + + /* Get the short application name */ + if (!GetShortPathNameW(ApplicationName, ShortAppName, Length)) + { + /* Try to determine which error occurred */ + switch (GetLastError()) + { + case ERROR_NOT_ENOUGH_MEMORY: + { + Status = STATUS_NO_MEMORY; + break; + } + + case ERROR_INVALID_PARAMETER: + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + default: + { + Status = STATUS_OBJECT_PATH_INVALID; + } + } + + goto Cleanup; + } + + /* Calculate the size of the short current directory path */ + Length = GetShortPathNameW(CurrentDirectory, NULL, 0); + + /* Allocate memory for the short current directory path */ + ShortCurrentDir = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + Length * sizeof(WCHAR)); + if (!ShortCurrentDir) + { + Status = STATUS_NO_MEMORY; + goto Cleanup; + } + + /* Get the short current directory path */ + if (!GetShortPathNameW(CurrentDirectory, ShortCurrentDir, Length)) + { + /* Try to determine which error occurred */ + switch (GetLastError()) + { + case ERROR_NOT_ENOUGH_MEMORY: + { + Status = STATUS_NO_MEMORY; + break; + } + + case ERROR_INVALID_PARAMETER: + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + default: + { + Status = STATUS_OBJECT_PATH_INVALID; + } + } + goto Cleanup; + } + + /* Setup the input parameters */ + CheckVdm->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + CheckVdm->BinaryType = BinaryType; + CheckVdm->CodePage = CP_ACP; + CheckVdm->dwCreationFlags = CreationFlags; + CheckVdm->CurDrive = CurrentDirectory[0] - L'A'; + CheckVdm->CmdLen = wcslen(CommandLine) + 1; + CheckVdm->AppLen = wcslen(ShortAppName) + 1; + CheckVdm->PifLen = 0; // TODO: PIF file support! + CheckVdm->CurDirectoryLen = wcslen(ShortCurrentDir) + 1; + CheckVdm->EnvLen = AnsiEnvironment->Length; + CheckVdm->DesktopLen = (StartupInfo->lpDesktop != NULL) ? (wcslen(StartupInfo->lpDesktop) + 1) : 0; + CheckVdm->TitleLen = (StartupInfo->lpTitle != NULL) ? (wcslen(StartupInfo->lpTitle) + 1) : 0; + CheckVdm->ReservedLen = (StartupInfo->lpReserved != NULL) ? (wcslen(StartupInfo->lpReserved) + 1) : 0; + + if (StartupInfo->dwFlags & STARTF_USESTDHANDLES) + { + /* Set the standard handles */ + CheckVdm->StdIn = StartupInfo->hStdInput; + CheckVdm->StdOut = StartupInfo->hStdOutput; + CheckVdm->StdErr = StartupInfo->hStdError; + } + + /* Allocate memory for the ANSI strings */ + AnsiCmdLine = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->CmdLen); + AnsiAppName = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->AppLen); + AnsiCurDirectory = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->CurDirectoryLen); + if (StartupInfo->lpDesktop) AnsiDesktop = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + CheckVdm->DesktopLen); + if (StartupInfo->lpTitle) AnsiTitle = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + CheckVdm->TitleLen); + if (StartupInfo->lpReserved) AnsiReserved = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + CheckVdm->ReservedLen); + + if (!AnsiCmdLine + || !AnsiAppName + || !AnsiCurDirectory + || (StartupInfo->lpDesktop && !AnsiDesktop) + || (StartupInfo->lpTitle && !AnsiTitle) + || (StartupInfo->lpReserved && !AnsiReserved)) + { + Status = STATUS_NO_MEMORY; + goto Cleanup; + } + + /* Convert the command line into an ANSI string */ + WideCharToMultiByte(CP_ACP, + 0, + CommandLine, + CheckVdm->CmdLen, + AnsiCmdLine, + CheckVdm->CmdLen, + NULL, + NULL); + + /* Convert the short application name into an ANSI string */ + WideCharToMultiByte(CP_ACP, + 0, + ShortAppName, + CheckVdm->AppLen, + AnsiAppName, + CheckVdm->AppLen, + NULL, + NULL); + + /* Convert the short current directory path into an ANSI string */ + WideCharToMultiByte(CP_ACP, + 0, + ShortCurrentDir, + CheckVdm->CurDirectoryLen, + AnsiCurDirectory, + CheckVdm->CurDirectoryLen, + NULL, + NULL); + + if (StartupInfo->lpDesktop) + { + /* Convert the desktop name into an ANSI string */ + WideCharToMultiByte(CP_ACP, + 0, + StartupInfo->lpDesktop, + CheckVdm->DesktopLen, + AnsiDesktop, + CheckVdm->DesktopLen, + NULL, + NULL); + NumStrings++; + } + + if (StartupInfo->lpTitle) + { + /* Convert the title into an ANSI string */ + WideCharToMultiByte(CP_ACP, + 0, + StartupInfo->lpTitle, + CheckVdm->TitleLen, + AnsiTitle, + CheckVdm->TitleLen, + NULL, + NULL); + NumStrings++; + } + + if (StartupInfo->lpReserved) + { + /* Convert the reserved value into an ANSI string */ + WideCharToMultiByte(CP_ACP, + 0, + StartupInfo->lpReserved, + CheckVdm->ReservedLen, + AnsiReserved, + CheckVdm->ReservedLen, + NULL, + NULL); + NumStrings++; + } + + /* Fill the ANSI startup info structure */ + RtlCopyMemory(&AnsiStartupInfo, StartupInfo, sizeof(STARTUPINFO)); + AnsiStartupInfo.lpReserved = AnsiReserved; + AnsiStartupInfo.lpDesktop = AnsiDesktop; + AnsiStartupInfo.lpTitle = AnsiTitle; + + /* Allocate the capture buffer */ + CaptureBuffer = CsrAllocateCaptureBuffer(NumStrings, + CheckVdm->CmdLen + + CheckVdm->AppLen + + CheckVdm->PifLen + + CheckVdm->CurDirectoryLen + + CheckVdm->DesktopLen + + CheckVdm->TitleLen + + CheckVdm->ReservedLen + + CheckVdm->EnvLen + + sizeof(STARTUPINFOA)); + if (CaptureBuffer == NULL) + { + Status = STATUS_NO_MEMORY; + goto Cleanup; + } + + /* Capture the command line */ + CsrCaptureMessageBuffer(CaptureBuffer, + AnsiCmdLine, + CheckVdm->CmdLen, + (PVOID*)&CheckVdm->CmdLine); + + /* Capture the application name */ + CsrCaptureMessageBuffer(CaptureBuffer, + AnsiAppName, + CheckVdm->AppLen, + (PVOID*)&CheckVdm->AppName); + + CheckVdm->PifFile = NULL; // TODO: PIF file support! + + /* Capture the current directory */ + CsrCaptureMessageBuffer(CaptureBuffer, + AnsiCurDirectory, + CheckVdm->CurDirectoryLen, + (PVOID*)&CheckVdm->CurDirectory); + + /* Capture the environment */ + CsrCaptureMessageBuffer(CaptureBuffer, + AnsiEnvironment->Buffer, + CheckVdm->EnvLen, + (PVOID*)&CheckVdm->Env); + + /* Capture the startup info structure */ + CsrCaptureMessageBuffer(CaptureBuffer, + &AnsiStartupInfo, + sizeof(STARTUPINFOA), + (PVOID*)&CheckVdm->StartupInfo); + + if (StartupInfo->lpDesktop) + { + /* Capture the desktop name */ + CsrCaptureMessageBuffer(CaptureBuffer, + AnsiDesktop, + CheckVdm->DesktopLen, + (PVOID*)&CheckVdm->Desktop); + } + else CheckVdm->Desktop = NULL; + + if (StartupInfo->lpTitle) + { + /* Capture the title */ + CsrCaptureMessageBuffer(CaptureBuffer, + AnsiTitle, + CheckVdm->TitleLen, + (PVOID*)&CheckVdm->Title); + } + else CheckVdm->Title = NULL; + + if (StartupInfo->lpReserved) + { + /* Capture the reserved parameter */ + CsrCaptureMessageBuffer(CaptureBuffer, + AnsiReserved, + CheckVdm->ReservedLen, + (PVOID*)&CheckVdm->Reserved); + } + else CheckVdm->Reserved = NULL; + + /* Send the message to CSRSS */ + Status = CsrClientCallServer((PCSR_API_MESSAGE)ApiMessage, + CaptureBuffer, + CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepCheckVDM), + sizeof(BASE_CHECK_VDM)); + + /* Write back the task ID */ + *iTask = CheckVdm->iTask; + +Cleanup: + + /* Free the ANSI strings */ + if (AnsiCmdLine) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiCmdLine); + if (AnsiAppName) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiAppName); + if (AnsiCurDirectory) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiCurDirectory); + if (AnsiDesktop) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiDesktop); + if (AnsiTitle) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiTitle); + if (AnsiReserved) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiReserved); + + /* Free the capture buffer */ + CsrFreeCaptureBuffer(CaptureBuffer); + + /* Free the short paths */ + if (ShortAppName) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortAppName); + if (ShortCurrentDir) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortCurrentDir); + + /* Free the current directory, if it was allocated here */ + if (CurrentDir) RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentDir); + + return Status; } BOOL @@ -89,10 +434,9 @@ BaseUpdateVDMEntry(IN ULONG UpdateIndex, IN ULONG IndexInfo, IN ULONG BinaryType) { -#if 0 // Unimplemented in BASESRV NTSTATUS Status; BASE_API_MESSAGE ApiMessage; - PBASE_UPDATE_VDM_ENTRY UpdateVdmEntry = &ApiMessage.Data.UpdateVdmEntry; + PBASE_UPDATE_VDM_ENTRY UpdateVdmEntry = &ApiMessage.Data.UpdateVDMEntryRequest; /* Check what update is being sent */ switch (UpdateIndex) @@ -155,7 +499,7 @@ BaseUpdateVDMEntry(IN ULONG UpdateIndex, /* Return it to the caller */ *WaitHandle = UpdateVdmEntry->WaitObjectForParent; } -#endif + /* We made it */ return TRUE; } @@ -165,11 +509,10 @@ WINAPI BaseCheckForVDM(IN HANDLE ProcessHandle, OUT LPDWORD ExitCode) { -#if 0 // Unimplemented in BASESRV NTSTATUS Status; EVENT_BASIC_INFORMATION EventBasicInfo; BASE_API_MESSAGE ApiMessage; - PBASE_GET_VDM_EXIT_CODE GetVdmExitCode = &ApiMessage.Data.GetVdmExitCode; + PBASE_GET_VDM_EXIT_CODE GetVdmExitCode = &ApiMessage.Data.GetVDMExitCodeRequest; /* It's VDM if the process is actually a wait handle (an event) */ Status = NtQueryEvent(ProcessHandle, @@ -192,7 +535,6 @@ BaseCheckForVDM(IN HANDLE ProcessHandle, /* Get the exit code from the reply */ *ExitCode = GetVdmExitCode->ExitCode; -#endif return TRUE; } @@ -335,7 +677,7 @@ BaseCreateVDMEnvironment(IN PWCHAR lpEnvironment, if (!lpEnvironment) { /* Nope, create one */ - Status = RtlCreateEnvironment(TRUE, (PWCHAR*)&Environment); + Status = RtlCreateEnvironment(TRUE, &Environment); if (!NT_SUCCESS(Status)) goto Quickie; } else @@ -376,6 +718,7 @@ BaseCreateVDMEnvironment(IN PWCHAR lpEnvironment, p = NewEnvironment; /* FIXME: Code here */ + DPRINT1("BaseCreateVDMEnvironment is half-plemented!\n"); /* Terminate it */ *p++ = UNICODE_NULL; @@ -574,7 +917,7 @@ InternalGetBinaryType(HANDLE hFile) return BINARY_PE_EXE32; } - if(!memcmp(magic, "NE", 1)) + if(!memcmp(magic, "NE", 2)) { /* This is a Windows executable (NE) header. This can * mean either a 16-bit OS/2 or a 16-bit Windows or even a @@ -755,46 +1098,399 @@ CmdBatNotification ( } /* - * @unimplemented + * @implemented */ -DWORD +VOID WINAPI -ExitVDM ( - DWORD Unknown0, - DWORD Unknown1 - ) +ExitVDM(BOOL IsWow, ULONG iWowTask) { - STUB; - return 0; + BASE_API_MESSAGE ApiMessage; + PBASE_EXIT_VDM ExitVdm = &ApiMessage.Data.ExitVDMRequest; + + /* Setup the input parameters */ + ExitVdm->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + ExitVdm->iWowTask = IsWow ? iWowTask : 0; /* Always zero for DOS tasks */ + ExitVdm->WaitObjectForVDM = NULL; + + /* Call CSRSS */ + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + NULL, + CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepExitVDM), + sizeof(BASE_EXIT_VDM)); + + /* Close the returned wait object handle, if any */ + if (NT_SUCCESS(ApiMessage.Status) && (ExitVdm->WaitObjectForVDM != NULL)) + { + CloseHandle(ExitVdm->WaitObjectForVDM); + } +} + +/* + * @implemented + */ +BOOL +WINAPI +GetNextVDMCommand(PVDM_COMMAND_INFO CommandData) +{ + NTSTATUS Status; + BOOL Result = FALSE; + BASE_API_MESSAGE ApiMessage; + PBASE_GET_NEXT_VDM_COMMAND GetNextVdmCommand = &ApiMessage.Data.GetNextVDMCommandRequest; + PBASE_IS_FIRST_VDM IsFirstVdm = &ApiMessage.Data.IsFirstVDMRequest; + PBASE_SET_REENTER_COUNT SetReenterCount = &ApiMessage.Data.SetReenterCountRequest; + PCSR_CAPTURE_BUFFER CaptureBuffer = NULL; + ULONG NumStrings = 0; + + if (CommandData != NULL) + { + if (CommandData->VDMState & (VDM_NOT_LOADED | VDM_NOT_READY | VDM_READY)) + { + /* Clear the structure */ + ZeroMemory(GetNextVdmCommand, sizeof(*GetNextVdmCommand)); + + /* Setup the input parameters */ + GetNextVdmCommand->iTask = CommandData->TaskId; + GetNextVdmCommand->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + GetNextVdmCommand->CmdLen = CommandData->CmdLen; + GetNextVdmCommand->AppLen = CommandData->AppLen; + GetNextVdmCommand->PifLen = CommandData->PifLen; + GetNextVdmCommand->CurDirectoryLen = CommandData->CurDirectoryLen; + GetNextVdmCommand->EnvLen = CommandData->EnvLen; + GetNextVdmCommand->DesktopLen = CommandData->DesktopLen; + GetNextVdmCommand->TitleLen = CommandData->TitleLen; + GetNextVdmCommand->ReservedLen = CommandData->ReservedLen; + GetNextVdmCommand->VDMState = CommandData->VDMState; + + /* Count the number of strings */ + if (CommandData->CmdLen) NumStrings++; + if (CommandData->AppLen) NumStrings++; + if (CommandData->PifLen) NumStrings++; + if (CommandData->CurDirectoryLen) NumStrings++; + if (CommandData->EnvLen) NumStrings++; + if (CommandData->DesktopLen) NumStrings++; + if (CommandData->TitleLen) NumStrings++; + if (CommandData->ReservedLen) NumStrings++; + + /* Allocate the capture buffer */ + CaptureBuffer = CsrAllocateCaptureBuffer(NumStrings + 1, + GetNextVdmCommand->CmdLen + + GetNextVdmCommand->AppLen + + GetNextVdmCommand->PifLen + + GetNextVdmCommand->CurDirectoryLen + + GetNextVdmCommand->EnvLen + + GetNextVdmCommand->DesktopLen + + GetNextVdmCommand->TitleLen + + GetNextVdmCommand->ReservedLen + + sizeof(STARTUPINFOA)); + if (CaptureBuffer == NULL) + { + BaseSetLastNTError(STATUS_NO_MEMORY); + goto Cleanup; + } + + /* Allocate memory for the startup info */ + CsrAllocateMessagePointer(CaptureBuffer, + sizeof(STARTUPINFOA), + (PVOID*)&GetNextVdmCommand->StartupInfo); + + if (CommandData->CmdLen) + { + /* Allocate memory for the command line */ + CsrAllocateMessagePointer(CaptureBuffer, + CommandData->CmdLen, + (PVOID*)&GetNextVdmCommand->CmdLine); + } + + if (CommandData->AppLen) + { + /* Allocate memory for the application name */ + CsrAllocateMessagePointer(CaptureBuffer, + CommandData->AppLen, + (PVOID*)&GetNextVdmCommand->AppName); + } + + if (CommandData->PifLen) + { + /* Allocate memory for the PIF file name */ + CsrAllocateMessagePointer(CaptureBuffer, + CommandData->PifLen, + (PVOID*)&GetNextVdmCommand->PifFile); + } + + if (CommandData->CurDirectoryLen) + { + /* Allocate memory for the current directory */ + CsrAllocateMessagePointer(CaptureBuffer, + CommandData->CurDirectoryLen, + (PVOID*)&GetNextVdmCommand->CurDirectory); + } + + if (CommandData->EnvLen) + { + /* Allocate memory for the environment */ + CsrAllocateMessagePointer(CaptureBuffer, + CommandData->EnvLen, + (PVOID*)&GetNextVdmCommand->Env); + } + + if (CommandData->DesktopLen) + { + /* Allocate memory for the desktop name */ + CsrAllocateMessagePointer(CaptureBuffer, + CommandData->DesktopLen, + (PVOID*)&GetNextVdmCommand->Desktop); + } + + if (CommandData->TitleLen) + { + /* Allocate memory for the title */ + CsrAllocateMessagePointer(CaptureBuffer, + CommandData->TitleLen, + (PVOID*)&GetNextVdmCommand->Title); + } + + if (CommandData->ReservedLen) + { + /* Allocate memory for the reserved parameter */ + CsrAllocateMessagePointer(CaptureBuffer, + CommandData->ReservedLen, + (PVOID*)&GetNextVdmCommand->Reserved); + } + + do + { + /* Call CSRSS */ + Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + CaptureBuffer, + CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepGetNextVDMCommand), + sizeof(BASE_GET_NEXT_VDM_COMMAND)); + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + goto Cleanup; + } + + /* Did we receive an event handle? */ + if (GetNextVdmCommand->WaitObjectForVDM != NULL) + { + /* Wait for the event to become signaled and try again */ + Status = NtWaitForSingleObject(GetNextVdmCommand->WaitObjectForVDM, + FALSE, + NULL); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + goto Cleanup; + } + + /* Set the retry flag and clear the exit code */ + GetNextVdmCommand->VDMState |= VDM_FLAG_RETRY; + GetNextVdmCommand->ExitCode = 0; + } + } + while (GetNextVdmCommand->WaitObjectForVDM != NULL); + + /* Write back the standard handles */ + CommandData->StdIn = GetNextVdmCommand->StdIn; + CommandData->StdOut = GetNextVdmCommand->StdOut; + CommandData->StdErr = GetNextVdmCommand->StdErr; + + /* Write back the startup info */ + RtlMoveMemory(&CommandData->StartupInfo, + GetNextVdmCommand->StartupInfo, + sizeof(STARTUPINFOA)); + + if (CommandData->CmdLen) + { + /* Write back the command line */ + RtlMoveMemory(CommandData->CmdLine, + GetNextVdmCommand->CmdLine, + GetNextVdmCommand->CmdLen); + + /* Set the actual length */ + CommandData->CmdLen = GetNextVdmCommand->CmdLen; + } + + if (CommandData->AppLen) + { + /* Write back the application name */ + RtlMoveMemory(CommandData->AppName, + GetNextVdmCommand->AppName, + GetNextVdmCommand->AppLen); + + /* Set the actual length */ + CommandData->AppLen = GetNextVdmCommand->AppLen; + } + + if (CommandData->PifLen) + { + /* Write back the PIF file name */ + RtlMoveMemory(CommandData->PifFile, + GetNextVdmCommand->PifFile, + GetNextVdmCommand->PifLen); + + /* Set the actual length */ + CommandData->PifLen = GetNextVdmCommand->PifLen; + } + + if (CommandData->CurDirectoryLen) + { + /* Write back the current directory */ + RtlMoveMemory(CommandData->CurDirectory, + GetNextVdmCommand->CurDirectory, + GetNextVdmCommand->CurDirectoryLen); + + /* Set the actual length */ + CommandData->CurDirectoryLen = GetNextVdmCommand->CurDirectoryLen; + } + + if (CommandData->EnvLen) + { + /* Write back the environment */ + RtlMoveMemory(CommandData->Env, + GetNextVdmCommand->Env, + GetNextVdmCommand->EnvLen); + + /* Set the actual length */ + CommandData->EnvLen = GetNextVdmCommand->EnvLen; + } + + if (CommandData->DesktopLen) + { + /* Write back the desktop name */ + RtlMoveMemory(CommandData->Desktop, + GetNextVdmCommand->Desktop, + GetNextVdmCommand->DesktopLen); + + /* Set the actual length */ + CommandData->DesktopLen = GetNextVdmCommand->DesktopLen; + } + + if (CommandData->TitleLen) + { + /* Write back the title */ + RtlMoveMemory(CommandData->Title, + GetNextVdmCommand->Title, + GetNextVdmCommand->TitleLen); + + /* Set the actual length */ + CommandData->TitleLen = GetNextVdmCommand->TitleLen; + } + + if (CommandData->ReservedLen) + { + /* Write back the reserved parameter */ + RtlMoveMemory(CommandData->Reserved, + GetNextVdmCommand->Reserved, + GetNextVdmCommand->ReservedLen); + + /* Set the actual length */ + CommandData->ReservedLen = GetNextVdmCommand->ReservedLen; + } + + /* Write the remaining output parameters */ + CommandData->TaskId = GetNextVdmCommand->iTask; + CommandData->CreationFlags = GetNextVdmCommand->dwCreationFlags; + CommandData->CodePage = GetNextVdmCommand->CodePage; + CommandData->ExitCode = GetNextVdmCommand->ExitCode; + CommandData->CurrentDrive = GetNextVdmCommand->CurrentDrive; + CommandData->VDMState = GetNextVdmCommand->VDMState; + CommandData->ComingFromBat = GetNextVdmCommand->fComingFromBat; + + /* It was successful */ + Result = TRUE; + } + else if ((CommandData->VDMState == VDM_INC_REENTER_COUNT) + || (CommandData->VDMState == VDM_DEC_REENTER_COUNT)) + { + /* Setup the input parameters */ + SetReenterCount->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + SetReenterCount->fIncDec = CommandData->VDMState; + + /* Call CSRSS */ + Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + NULL, + CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepSetReenterCount), + sizeof(BASE_SET_REENTER_COUNT)); + BaseSetLastNTError(Status); + Result = NT_SUCCESS(Status); + } + else + { + BaseSetLastNTError(STATUS_INVALID_PARAMETER); + Result = FALSE; + } + } + else + { + /* Call CSRSS */ + Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + NULL, + CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepIsFirstVDM), + sizeof(BASE_IS_FIRST_VDM)); + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + goto Cleanup; + } + + /* Return TRUE if this is the first VDM */ + Result = IsFirstVdm->FirstVDM; + } + +Cleanup: + if (CaptureBuffer != NULL) CsrFreeCaptureBuffer(CaptureBuffer); + return Result; } /* - * @unimplemented + * @implemented */ DWORD WINAPI -GetNextVDMCommand ( - DWORD Unknown0 - ) +GetVDMCurrentDirectories(DWORD cchCurDirs, PCHAR lpszzCurDirs) { - STUB; - return 0; -} + BASE_API_MESSAGE ApiMessage; + PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest = &ApiMessage.Data.VDMCurrentDirsRequest; + PCSR_CAPTURE_BUFFER CaptureBuffer; + /* Allocate the capture buffer */ + CaptureBuffer = CsrAllocateCaptureBuffer(1, cchCurDirs); + if (CaptureBuffer == NULL) + { + BaseSetLastNTError(STATUS_NO_MEMORY); + return 0; + } -/* - * @unimplemented - */ -DWORD -WINAPI -GetVDMCurrentDirectories ( - DWORD Unknown0, - DWORD Unknown1 - ) -{ - STUB; - return 0; + /* Setup the input parameters */ + VDMCurrentDirsRequest->cchCurDirs = cchCurDirs; + CsrAllocateMessagePointer(CaptureBuffer, + cchCurDirs, + (PVOID*)&VDMCurrentDirsRequest->lpszzCurDirs); + + /* Call CSRSS */ + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + CaptureBuffer, + CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepGetVDMCurDirs), + sizeof(BASE_GETSET_VDM_CURDIRS)); + + /* Set the last error */ + BaseSetLastNTError(ApiMessage.Status); + + if (NT_SUCCESS(ApiMessage.Status)) + { + /* Copy the result */ + RtlMoveMemory(lpszzCurDirs, VDMCurrentDirsRequest->lpszzCurDirs, cchCurDirs); + } + + /* Free the capture buffer */ + CsrFreeCaptureBuffer(CaptureBuffer); + + /* Return the size if it was successful, or if the buffer was too small */ + return (NT_SUCCESS(ApiMessage.Status) || (ApiMessage.Status == STATUS_BUFFER_TOO_SMALL)) + ? VDMCurrentDirsRequest->cchCurDirs : 0; } @@ -851,17 +1547,44 @@ RegisterWowExec ( /* - * @unimplemented + * @implemented */ BOOL WINAPI -SetVDMCurrentDirectories ( - DWORD Unknown0, - DWORD Unknown1 - ) +SetVDMCurrentDirectories(DWORD cchCurDirs, PCHAR lpszzCurDirs) { - STUB; - return FALSE; + BASE_API_MESSAGE ApiMessage; + PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest = &ApiMessage.Data.VDMCurrentDirsRequest; + PCSR_CAPTURE_BUFFER CaptureBuffer; + + /* Allocate the capture buffer */ + CaptureBuffer = CsrAllocateCaptureBuffer(1, cchCurDirs); + if (CaptureBuffer == NULL) + { + BaseSetLastNTError(STATUS_NO_MEMORY); + return FALSE; + } + + /* Setup the input parameters */ + VDMCurrentDirsRequest->cchCurDirs = cchCurDirs; + CsrCaptureMessageBuffer(CaptureBuffer, + lpszzCurDirs, + cchCurDirs, + (PVOID*)&VDMCurrentDirsRequest->lpszzCurDirs); + + /* Call CSRSS */ + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + CaptureBuffer, + CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepSetVDMCurDirs), + sizeof(BASE_GETSET_VDM_CURDIRS)); + + /* Free the capture buffer */ + CsrFreeCaptureBuffer(CaptureBuffer); + + /* Set the last error */ + BaseSetLastNTError(ApiMessage.Status); + + return NT_SUCCESS(ApiMessage.Status) ? TRUE : FALSE; } /* @@ -882,12 +1605,15 @@ VDMConsoleOperation ( /* * @unimplemented */ -DWORD +BOOL WINAPI -VDMOperationStarted ( - DWORD Unknown0 - ) +VDMOperationStarted(IN ULONG Unknown0) { - STUB; - return 0; + DPRINT1("VDMOperationStarted(%d)\n", Unknown0); + + return + BaseUpdateVDMEntry(VdmEntryUpdateControlCHandler, + NULL, + 0, + Unknown0); } diff --git a/dll/win32/kernel32/include/vdm.h b/dll/win32/kernel32/include/vdm.h index 696597dfb5d..56e872683c3 100644 --- a/dll/win32/kernel32/include/vdm.h +++ b/dll/win32/kernel32/include/vdm.h @@ -8,42 +8,6 @@ #pragma once -/* CONSTANTS ******************************************************************/ - -typedef enum _VDM_ENTRY_CODE -{ - VdmEntryUndo, - VdmEntryUpdateProcess, - VdmEntryUpdateControlCHandler -} VDM_ENTRY_CODE; - -// -// Undo States -// -#define VDM_UNDO_PARTIAL 0x01 -#define VDM_UNDO_FULL 0x02 -#define VDM_UNDO_REUSE 0x04 -#define VDM_UNDO_COMPLETED 0x08 - -// -// Binary Types to share with VDM -// -#define BINARY_TYPE_EXE 0x01 -#define BINARY_TYPE_COM 0x02 -#define BINARY_TYPE_PIF 0x03 -#define BINARY_TYPE_DOS 0x10 -#define BINARY_TYPE_SEPARATE_WOW 0x20 -#define BINARY_TYPE_WOW 0x40 -#define BINARY_TYPE_WOW_EX 0x80 - -// -// VDM States -// -#define VDM_NOT_LOADED 0x01 -#define VDM_NOT_READY 0x02 -#define VDM_READY 0x04 - - /* FUNCTION PROTOTYPES ********************************************************/ BOOL @@ -87,7 +51,7 @@ BaseCheckForVDM( OUT LPDWORD ExitCode ); -BOOL +NTSTATUS WINAPI BaseCheckVDM( IN ULONG BinaryType, diff --git a/dll/win32/kernel32/k32.h b/dll/win32/kernel32/k32.h index e544b0c7eef..7228f83ed80 100644 --- a/dll/win32/kernel32/k32.h +++ b/dll/win32/kernel32/k32.h @@ -46,6 +46,7 @@ #include #include #include +#include /* DDK Driver Headers */ #include diff --git a/dll/win32/kernel32/wine/actctx.c b/dll/win32/kernel32/wine/actctx.c index 7eb91a90c4c..c1a73d16972 100644 --- a/dll/win32/kernel32/wine/actctx.c +++ b/dll/win32/kernel32/wine/actctx.c @@ -10,7 +10,7 @@ * Samuel Serapin */ -/* synched with wine 1.1.26 */ +/* Partly synched with Wine 1.7.17 */ #include @@ -178,11 +178,15 @@ BOOL WINAPI FindActCtxSectionGuid(DWORD dwFlags, const GUID* lpExtGuid, ULONG ulId, const GUID* lpSearchGuid, PACTCTX_SECTION_KEYED_DATA pInfo) { - FIXME("%08x %s %u %s %p\n", dwFlags, debugstr_guid(lpExtGuid), - ulId, debugstr_guid(lpSearchGuid), pInfo); - SetLastError( ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + NTSTATUS status; + + if ((status = RtlFindActivationContextSectionGuid(dwFlags, lpExtGuid, ulId, lpSearchGuid, pInfo))) + { + SetLastError(RtlNtStatusToDosError(status)); + return FALSE; + } + + return TRUE; } - /* EOF */ diff --git a/dll/win32/mshtml/CMakeLists.txt b/dll/win32/mshtml/CMakeLists.txt index d0de62d0140..012cd047b88 100644 --- a/dll/win32/mshtml/CMakeLists.txt +++ b/dll/win32/mshtml/CMakeLists.txt @@ -7,7 +7,7 @@ add_definitions( -DCOM_NO_WINDOWS_H) include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine) -add_idl_Headers(mshtml_nsiface_header nsiface.idl) +add_idl_headers(mshtml_nsiface_header nsiface.idl) spec2def(mshtml.dll mshtml.spec) list(APPEND SOURCE diff --git a/dll/win32/mshtml/msvc.S b/dll/win32/mshtml/msvc.S index 9d210be115f..90b65d8ab37 100644 --- a/dll/win32/mshtml/msvc.S +++ b/dll/win32/mshtml/msvc.S @@ -4,13 +4,23 @@ .code MACRO(DEFINE_WRAPPER_FUNC, n, off, x) +#ifdef _M_IX86 PUBLIC _wrapper_func_&n& _wrapper_func_&n&: -mov eax, [esp+4] -mov eax, [eax+4] -mov [esp+4], eax -mov eax, [eax] -jmp dword ptr [eax+off] + mov eax, [esp+4] + mov eax, [eax+4] + mov [esp+4], eax + mov eax, [eax] + jmp dword ptr [eax+off] +#elif defined(_M_AMD64) +PUBLIC wrapper_func_&n& +wrapper_func_&n&: + mov rcx, [rcx+4] + mov rax, [rcx] + jmp qword ptr [rax+off] +#else +#error Unimplemented +#endif ENDM DEFINE_WRAPPER_FUNC 3, 12, 24 diff --git a/dll/win32/msvcrt/msvcrt.spec b/dll/win32/msvcrt/msvcrt.spec index 1e5e0670fd1..8587c0d9e66 100644 --- a/dll/win32/msvcrt/msvcrt.spec +++ b/dll/win32/msvcrt/msvcrt.spec @@ -73,7 +73,7 @@ # @ cdecl ??_U@YAPAXIHPBDH@Z(long long str long) MSVCRT_operator_new_dbg @ cdecl -arch=win32 ??_V@YAXPAX@Z(ptr) MSVCRT_operator_delete @ cdecl -arch=win64 ??_V@YAXPEAX@Z(ptr) MSVCRT_operator_delete -@ cdecl -arch=win64 -norelay __uncaught_exception(ptr) +@ cdecl -norelay __uncaught_exception(ptr) @ cdecl -arch=win32 -norelay ?_query_new_handler@@YAP6AHI@ZXZ() MSVCRT__query_new_handler @ cdecl -arch=win64 -norelay ?_query_new_handler@@YAP6AH_K@ZXZ() MSVCRT__query_new_handler @ cdecl ?_query_new_mode@@YAHXZ() MSVCRT__query_new_mode @@ -256,7 +256,6 @@ @ cdecl __threadhandle() kernel32.GetCurrentThread @ cdecl __threadid() kernel32.GetCurrentThreadId @ cdecl __toascii(long) -@ cdecl __uncaught_exception() @ cdecl __unDName(ptr str long ptr ptr long) @ cdecl __unDNameEx(ptr str long ptr ptr ptr long) @ extern __unguarded_readlc_active diff --git a/dll/win32/rpcrt4/rpc_transport.c b/dll/win32/rpcrt4/rpc_transport.c index f60ea9f50d1..6608d8aedf2 100644 --- a/dll/win32/rpcrt4/rpc_transport.c +++ b/dll/win32/rpcrt4/rpc_transport.c @@ -307,7 +307,10 @@ static RPC_STATUS rpcrt4_ncacn_np_open(RpcConnection* Connection) { RpcConnection_np *npc = (RpcConnection_np *) Connection; static const char prefix[] = "\\\\"; - static const char local[] ="."; + static const char local[] = "."; + BOOL bUseLocalName = TRUE; + CHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1]; + DWORD bufLen = sizeof(ComputerName)/sizeof(ComputerName[0]); RPC_STATUS r; LPSTR pname; INT size; @@ -318,15 +321,39 @@ static RPC_STATUS rpcrt4_ncacn_np_open(RpcConnection* Connection) /* protseq=ncacn_np: named pipes */ size = strlen(prefix); + if (Connection->NetworkAddr == NULL || strlen(Connection->NetworkAddr) == 0) + { + bUseLocalName = TRUE; size += strlen(local); + } else - size += strlen(Connection->NetworkAddr); + { + if (GetComputerNameA(ComputerName, &bufLen)) + { + if (stricmp(ComputerName, Connection->NetworkAddr) == 0) + { + bUseLocalName = TRUE; + size += strlen(local); + } + else + { + bUseLocalName = FALSE; + size += strlen(Connection->NetworkAddr); + } + } + else + { + bUseLocalName = FALSE; + size += strlen(Connection->NetworkAddr); + } + } + size += strlen(Connection->Endpoint) + 1; pname = I_RpcAllocate(size); strcpy(pname, prefix); - if (Connection->NetworkAddr == NULL || strlen(Connection->NetworkAddr) == 0) + if (bUseLocalName) strcat(pname, local); else strcat(pname, Connection->NetworkAddr); diff --git a/dll/win32/rpcrt4/rpcrt4_ros.diff b/dll/win32/rpcrt4/rpcrt4_ros.diff index 36b824b02bc..098606b3610 100644 --- a/dll/win32/rpcrt4/rpcrt4_ros.diff +++ b/dll/win32/rpcrt4/rpcrt4_ros.diff @@ -1,40 +1,16 @@ -diff -prudN e:\Wine\dlls\rpcrt4/epm_towers.h e:\reactos\dll\win32\rpcrt4/epm_towers.h ---- e:\Wine\dlls\rpcrt4/epm_towers.h 2011-09-16 23:22:37.031828000 +0100 -+++ e:\reactos\dll\win32\rpcrt4/epm_towers.h 2013-01-25 14:13:03.257632500 +0100 -@@ -19,7 +19,7 @@ - * - */ +diff -prudN .\wine\dlls\rpcrt4/rpc_epmap.c .\reactos\dll\win32\rpcrt4/rpc_epmap.c +--- .\wine\dlls\rpcrt4/rpc_epmap.c 2014-05-09 03:43:55.965035900 +0200 ++++ .\reactos\dll\win32\rpcrt4/rpc_epmap.c 2013-12-27 18:11:56.421567500 +0100 +@@ -92,7 +80,7 @@ static BOOL start_rpcss(void) + lstrcatW( cmd, rpcss ); --#include "epm.h" -+#include + Wow64DisableWow64FsRedirection( &redir ); +- rslt = CreateProcessW( cmd, cmd, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &si, &pi ); ++ rslt = CreateProcessW( cmd, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ); + Wow64RevertWow64FsRedirection( redir ); - #define EPM_PROTOCOL_DNET_NSP 0x04 - #define EPM_PROTOCOL_OSI_TP4 0x05 -diff -prudN e:\Wine\dlls\rpcrt4/ndr_marshall.c e:\reactos\dll\win32\rpcrt4/ndr_marshall.c ---- e:\Wine\dlls\rpcrt4/ndr_marshall.c 2012-04-02 20:39:58.270363100 +0100 -+++ e:\reactos\dll\win32\rpcrt4/ndr_marshall.c 2013-12-06 20:04:02.897835300 +0100 -@@ -1211,7 +1211,7 @@ static unsigned char * EmbeddedPointerMa - unsigned char *bufptr = bufbase + *(const SHORT*)&info[2]; - unsigned char *saved_memory = pStubMsg->Memory; - -- pStubMsg->Memory = pMemory; -+ pStubMsg->Memory = membase; - PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4); - pStubMsg->Memory = saved_memory; - } -@@ -1365,7 +1365,7 @@ static void EmbeddedPointerBufferSize(PM - unsigned char *memptr = membase + *(const SHORT*)&info[0]; - unsigned char *saved_memory = pStubMsg->Memory; - -- pStubMsg->Memory = pMemory; -+ pStubMsg->Memory = membase; - PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4); - pStubMsg->Memory = saved_memory; - } -diff -prudN e:\Wine\dlls\rpcrt4/rpc_epmap.c e:\reactos\dll\win32\rpcrt4/rpc_epmap.c ---- e:\Wine\dlls\rpcrt4/rpc_epmap.c 2013-03-02 14:18:00.736492500 +0100 -+++ e:\reactos\dll\win32\rpcrt4/rpc_epmap.c 2013-12-06 20:28:21.361553600 +0100 -@@ -162,7 +169,7 @@ static RPC_STATUS get_epm_handle_server( + if (rslt) +@@ -162,7 +150,7 @@ static RPC_STATUS get_epm_handle_server( static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *__eptr) { @@ -43,10 +19,10 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_epmap.c e:\reactos\dll\win32\rpcrt4/rpc_epma { case EXCEPTION_ACCESS_VIOLATION: case EXCEPTION_ILLEGAL_INSTRUCTION: -diff -prudN e:\Wine\dlls\rpcrt4/rpc_server.c e:\reactos\dll\win32\rpcrt4/rpc_server.c ---- e:\Wine\dlls\rpcrt4/rpc_server.c 2012-12-09 09:57:02.680308600 +0100 -+++ e:\reactos\dll\win32\rpcrt4/rpc_server.c 2013-12-06 23:50:04.564226300 +0100 -@@ -1075,8 +1077,10 @@ void RPCRT4_destroy_all_protseqs(void) +diff -prudN .\wine\dlls\rpcrt4/rpc_server.c .\reactos\dll\win32\rpcrt4/rpc_server.c +--- .\wine\dlls\rpcrt4/rpc_server.c 2014-05-09 03:43:55.973036400 +0200 ++++ .\reactos\dll\win32\rpcrt4/rpc_server.c 2013-12-27 18:11:56.780368100 +0100 +@@ -1075,8 +1053,10 @@ void RPCRT4_destroy_all_protseqs(void) EnterCriticalSection(&server_cs); LIST_FOR_EACH_ENTRY_SAFE(cps, cursor2, &protseqs, RpcServerProtseq, entry) { @@ -57,10 +33,10 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_server.c e:\reactos\dll\win32\rpcrt4/rpc_ser destroy_serverprotoseq(cps); } LeaveCriticalSection(&server_cs); -diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_transport.c ---- e:\Wine\dlls\rpcrt4/rpc_transport.c 2013-12-06 20:10:59.302378700 +0100 -+++ e:\reactos\dll\win32\rpcrt4/rpc_transport.c 2013-12-06 23:39:38.664465200 +0100 -@@ -111,31 +115,41 @@ typedef struct _RpcConnection_np +diff -prudN .\wine\dlls\rpcrt4/rpc_transport.c .\reactos\dll\win32\rpcrt4/rpc_transport.c +--- .\wine\dlls\rpcrt4/rpc_transport.c 2014-05-09 03:43:55.977036600 +0200 ++++ .\reactos\dll\win32\rpcrt4/rpc_transport.c 2014-05-09 03:10:59.250551600 +0200 +@@ -113,31 +91,41 @@ typedef struct _RpcConnection_np { RpcConnection common; HANDLE pipe; @@ -109,26 +85,20 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_ case ERROR_NO_DATA_DETECTED: /* client has disconnected, retry */ DisconnectNamedPipe( npc->pipe ); -@@ -148,28 +162,12 @@ static DWORD CALLBACK listen_thread(void +@@ -150,6 +138,7 @@ static DWORD CALLBACK listen_thread(void } } --static RPC_STATUS rpcrt4_conn_listen_pipe(RpcConnection_np *npc) --{ -- if (npc->listening) -- return RPC_S_OK; -- -- npc->listening = TRUE; -- npc->listen_thread = CreateThread(NULL, 0, listen_thread, npc, 0, NULL); -- if (!npc->listen_thread) -- { -- npc->listening = FALSE; -- ERR("Couldn't create listen thread (error was %d)\n", GetLastError()); -- return RPC_S_OUT_OF_RESOURCES; -- } -- return RPC_S_OK; --} -- ++#ifndef __REACTOS__ + static RPC_STATUS rpcrt4_conn_listen_pipe(RpcConnection_np *npc) + { + if (npc->listening) +@@ -165,13 +154,14 @@ static RPC_STATUS rpcrt4_conn_listen_pip + } + return RPC_S_OK; + } ++#endif + static RPC_STATUS rpcrt4_conn_create_pipe(RpcConnection *Connection, LPCSTR pname) { RpcConnection_np *npc = (RpcConnection_np *) Connection; @@ -139,7 +109,7 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, PIPE_UNLIMITED_INSTANCES, RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, 5000, NULL); -@@ -181,6 +179,9 @@ static RPC_STATUS rpcrt4_conn_create_pip +@@ -183,6 +173,9 @@ static RPC_STATUS rpcrt4_conn_create_pip return RPC_S_CANT_CREATE_ENDPOINT; } @@ -149,7 +119,7 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_ /* Note: we don't call ConnectNamedPipe here because it must be done in the * server thread as the thread must be alertable */ return RPC_S_OK; -@@ -227,6 +228,9 @@ static RPC_STATUS rpcrt4_conn_open_pipe( +@@ -229,6 +222,9 @@ static RPC_STATUS rpcrt4_conn_open_pipe( if (err == ERROR_PIPE_BUSY) { TRACE("connection failed, error=%x\n", err); return RPC_S_SERVER_TOO_BUSY; @@ -159,7 +129,7 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_ } if (!wait || !WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) { err = GetLastError(); -@@ -236,9 +240,11 @@ static RPC_STATUS rpcrt4_conn_open_pipe( +@@ -238,9 +234,11 @@ static RPC_STATUS rpcrt4_conn_open_pipe( } /* success */ @@ -171,13 +141,16 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_ npc->pipe = pipe; return RPC_S_OK; -@@ -306,18 +312,32 @@ static RPC_STATUS rpcrt4_protseq_ncalrpc +@@ -308,18 +306,59 @@ static RPC_STATUS rpcrt4_protseq_ncalrpc static RPC_STATUS rpcrt4_ncacn_np_open(RpcConnection* Connection) { RpcConnection_np *npc = (RpcConnection_np *) Connection; - static const char prefix[] = "\\\\."; + static const char prefix[] = "\\\\"; -+ static const char local[] ="."; ++ static const char local[] = "."; ++ BOOL bUseLocalName = TRUE; ++ CHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1]; ++ DWORD bufLen = sizeof(ComputerName)/sizeof(ComputerName[0]); RPC_STATUS r; LPSTR pname; + INT size; @@ -191,15 +164,39 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_ - strcat(strcpy(pname, prefix), Connection->Endpoint); - r = rpcrt4_conn_open_pipe(Connection, pname, FALSE); + size = strlen(prefix); ++ + if (Connection->NetworkAddr == NULL || strlen(Connection->NetworkAddr) == 0) ++ { ++ bUseLocalName = TRUE; + size += strlen(local); ++ } + else -+ size += strlen(Connection->NetworkAddr); ++ { ++ if (GetComputerNameA(ComputerName, &bufLen)) ++ { ++ if (stricmp(ComputerName, Connection->NetworkAddr) == 0) ++ { ++ bUseLocalName = TRUE; ++ size += strlen(local); ++ } ++ else ++ { ++ bUseLocalName = FALSE; ++ size += strlen(Connection->NetworkAddr); ++ } ++ } ++ else ++ { ++ bUseLocalName = FALSE; ++ size += strlen(Connection->NetworkAddr); ++ } ++ } ++ + size += strlen(Connection->Endpoint) + 1; + + pname = I_RpcAllocate(size); + strcpy(pname, prefix); -+ if (Connection->NetworkAddr == NULL || strlen(Connection->NetworkAddr) == 0) ++ if (bUseLocalName) + strcat(pname, local); + else + strcat(pname, Connection->NetworkAddr); @@ -208,7 +205,7 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_ I_RpcFree(pname); return r; -@@ -366,9 +386,9 @@ static void rpcrt4_conn_np_handoff(RpcCo +@@ -368,9 +407,9 @@ static void rpcrt4_conn_np_handoff(RpcCo * to the child, then reopen the server binding to continue listening */ new_npc->pipe = old_npc->pipe; @@ -220,7 +217,7 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_ old_npc->listening = FALSE; } -@@ -413,11 +433,17 @@ static int rpcrt4_conn_np_read(RpcConnec +@@ -415,11 +454,17 @@ static int rpcrt4_conn_np_read(RpcConnec char *buf = buffer; BOOL ret = TRUE; unsigned int bytes_left = count; @@ -239,7 +236,7 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_ if (!ret && GetLastError() == ERROR_MORE_DATA) ret = TRUE; if (!ret || !bytes_read) -@@ -425,6 +451,7 @@ static int rpcrt4_conn_np_read(RpcConnec +@@ -427,6 +472,7 @@ static int rpcrt4_conn_np_read(RpcConnec bytes_left -= bytes_read; buf += bytes_read; } @@ -247,7 +244,7 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_ return ret ? count : -1; } -@@ -435,16 +462,23 @@ static int rpcrt4_conn_np_write(RpcConne +@@ -437,16 +483,23 @@ static int rpcrt4_conn_np_write(RpcConne const char *buf = buffer; BOOL ret = TRUE; unsigned int bytes_left = count; @@ -272,7 +269,7 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_ return ret ? count : -1; } -@@ -456,9 +490,9 @@ static int rpcrt4_conn_np_close(RpcConne +@@ -458,9 +511,9 @@ static int rpcrt4_conn_np_close(RpcConne CloseHandle(npc->pipe); npc->pipe = 0; } @@ -285,7 +282,7 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_ } return 0; } -@@ -662,7 +696,7 @@ static void *rpcrt4_protseq_np_get_wait_ +@@ -664,7 +717,7 @@ static void *rpcrt4_protseq_np_get_wait_ conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common); while (conn) { rpcrt4_conn_listen_pipe(conn); @@ -294,7 +291,7 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_ (*count)++; conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common); } -@@ -683,7 +717,7 @@ static void *rpcrt4_protseq_np_get_wait_ +@@ -685,7 +738,7 @@ static void *rpcrt4_protseq_np_get_wait_ *count = 1; conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common); while (conn) { @@ -303,7 +300,7 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_ (*count)++; conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common); } -@@ -730,18 +764,12 @@ static int rpcrt4_protseq_np_wait_for_ne +@@ -732,18 +785,12 @@ static int rpcrt4_protseq_np_wait_for_ne EnterCriticalSection(&protseq->cs); conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common); while (conn) { @@ -324,9 +321,9 @@ diff -prudN e:\Wine\dlls\rpcrt4/rpc_transport.c e:\reactos\dll\win32\rpcrt4/rpc_ else ERR("failed to locate connection for handle %p\n", b_handle); LeaveCriticalSection(&protseq->cs); -diff -prudN e:\Wine\dlls\rpcrt4/rpcrt4.spec e:\reactos\dll\win32\rpcrt4/rpcrt4.spec ---- e:\Wine\dlls\rpcrt4/rpcrt4.spec 2012-09-09 19:47:53.677232900 +0100 -+++ e:\reactos\dll\win32\rpcrt4/rpcrt4.spec 2013-12-06 20:29:09.804227500 +0100 +diff -prudN .\wine\dlls\rpcrt4/rpcrt4.spec .\reactos\dll\win32\rpcrt4/rpcrt4.spec +--- .\wine\dlls\rpcrt4/rpcrt4.spec 2014-05-09 03:43:55.911032800 +0200 ++++ .\reactos\dll\win32\rpcrt4/rpcrt4.spec 2013-12-07 15:35:15.331527800 +0100 @@ -266,7 +266,7 @@ @ stdcall NdrRangeUnmarshall(ptr ptr ptr long) @ stub NdrRpcSmClientAllocate diff --git a/dll/win32/setupapi/CMakeLists.txt b/dll/win32/setupapi/CMakeLists.txt index 3d1af9fe4ca..5f0c7365c4a 100644 --- a/dll/win32/setupapi/CMakeLists.txt +++ b/dll/win32/setupapi/CMakeLists.txt @@ -40,7 +40,7 @@ add_library(setupapi SHARED set_module_type(setupapi win32dll UNICODE) target_link_libraries(setupapi uuid wine ${PSEH_LIB}) -add_delay_importlibs(setupapi shell32) +add_delay_importlibs(setupapi shell32 wintrust) add_importlibs(setupapi msvcrt diff --git a/dll/win32/setupapi/install.c b/dll/win32/setupapi/install.c index 533820b8064..6bc03bee219 100644 --- a/dll/win32/setupapi/install.c +++ b/dll/win32/setupapi/install.c @@ -2173,6 +2173,7 @@ BOOL WINAPI SetupCopyOEMInfA( PWSTR DestinationInfFileNameW = NULL; PWSTR DestinationInfFileNameComponentW = NULL; BOOL ret = FALSE; + DWORD size; TRACE("%s %s 0x%lx 0x%lx %p 0%lu %p %p\n", SourceInfFileName, OEMSourceMediaLocation, OEMSourceMediaType, @@ -2204,11 +2205,14 @@ BOOL WINAPI SetupCopyOEMInfA( CopyStyle, DestinationInfFileNameW, DestinationInfFileNameSize, - RequiredSize, + &size, DestinationInfFileNameComponent ? &DestinationInfFileNameComponentW : NULL); if (!ret) + { + if (RequiredSize) *RequiredSize = size; goto cleanup; - + } + if (DestinationInfFileNameSize != 0) { if (WideCharToMultiByte(CP_ACP, 0, DestinationInfFileNameW, -1, diff --git a/dll/win32/setupapi/misc.c b/dll/win32/setupapi/misc.c index cca5891450e..138dcae87d5 100644 --- a/dll/win32/setupapi/misc.c +++ b/dll/win32/setupapi/misc.c @@ -1217,6 +1217,34 @@ DWORD WINAPI InstallCatalog( LPCSTR catalog, LPCSTR basename, LPSTR fullname ) return 0; } +/*********************************************************************** + * pSetupInstallCatalog (SETUPAPI.@) + */ +DWORD WINAPI pSetupInstallCatalog( LPCWSTR catalog, LPCWSTR basename, LPWSTR fullname ) +{ + HCATADMIN admin; + HCATINFO cat; + + TRACE ("%s, %s, %p\n", debugstr_w(catalog), debugstr_w(basename), fullname); + + if (!CryptCATAdminAcquireContext(&admin,NULL,0)) + return GetLastError(); + + if (!(cat = CryptCATAdminAddCatalog( admin, (PWSTR)catalog, (PWSTR)basename, 0 ))) + { + DWORD rc = GetLastError(); + CryptCATAdminReleaseContext(admin, 0); + return rc; + } + CryptCATAdminReleaseCatalogContext(admin, cat, 0); + CryptCATAdminReleaseContext(admin,0); + + if (fullname) + FIXME("not returning full installed catalog path\n"); + + return NO_ERROR; +} + static UINT detect_compression_type( LPCWSTR file ) { DWORD size; @@ -1536,26 +1564,29 @@ static DWORD decompress_file_lz( LPCWSTR source, LPCWSTR target ) return ret; } +struct callback_context +{ + BOOL has_extracted; + LPCWSTR target; +}; + static UINT CALLBACK decompress_or_copy_callback( PVOID context, UINT notification, UINT_PTR param1, UINT_PTR param2 ) { + struct callback_context *context_info = context; FILE_IN_CABINET_INFO_W *info = (FILE_IN_CABINET_INFO_W *)param1; switch (notification) { case SPFILENOTIFY_FILEINCABINET: { - LPCWSTR filename, targetname = context; - WCHAR *p; + if (context_info->has_extracted) + return FILEOP_ABORT; - if ((p = strrchrW( targetname, '\\' ))) filename = p + 1; - else filename = targetname; - - if (!lstrcmpiW( filename, info->NameInCabinet )) - { - strcpyW( info->FullTargetName, targetname ); - return FILEOP_DOIT; - } - return FILEOP_SKIP; + TRACE("Requesting extraction of cabinet file %s\n", + wine_dbgstr_w(info->NameInCabinet)); + strcpyW( info->FullTargetName, context_info->target ); + context_info->has_extracted = TRUE; + return FILEOP_DOIT; } default: return NO_ERROR; } @@ -1563,9 +1594,10 @@ static UINT CALLBACK decompress_or_copy_callback( PVOID context, UINT notificati static DWORD decompress_file_cab( LPCWSTR source, LPCWSTR target ) { + struct callback_context context = {0, target}; BOOL ret; - ret = SetupIterateCabinetW( source, 0, decompress_or_copy_callback, (PVOID)target ); + ret = SetupIterateCabinetW( source, 0, decompress_or_copy_callback, &context ); if (ret) return ERROR_SUCCESS; else return GetLastError(); @@ -1578,7 +1610,7 @@ static DWORD decompress_file_cab( LPCWSTR source, LPCWSTR target ) */ DWORD WINAPI SetupDecompressOrCopyFileA( PCSTR source, PCSTR target, PUINT type ) { - DWORD ret = FALSE; + DWORD ret = 0; WCHAR *sourceW = NULL, *targetW = NULL; if (source && !(sourceW = pSetupMultiByteToUnicode( source, CP_ACP ))) return FALSE; diff --git a/dll/win32/setupapi/setupapi.spec b/dll/win32/setupapi/setupapi.spec index 81f2125f8ac..2a6ad8d47e0 100644 --- a/dll/win32/setupapi/setupapi.spec +++ b/dll/win32/setupapi/setupapi.spec @@ -562,7 +562,7 @@ @ stub pSetupHandleFailedVerification @ stub pSetupInfCacheBuild @ stub pSetupInfIsFromOemLocation -@ stub pSetupInstallCatalog +@ stdcall pSetupInstallCatalog(wstr wstr ptr) @ stub pSetupInstallStopEx @ stdcall pSetupIsGuidNull(ptr) @ stub pSetupIsLocalSystem diff --git a/dll/win32/setupapi/setupapi_private.h b/dll/win32/setupapi/setupapi_private.h index 53db948def9..80a818a66bf 100644 --- a/dll/win32/setupapi/setupapi_private.h +++ b/dll/win32/setupapi/setupapi_private.h @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include #include #define NTOS_MODE_USER diff --git a/dll/win32/shell32/folders/cpanel.cpp b/dll/win32/shell32/folders/cpanel.cpp index 47ec5b670c3..cf0c9cf448d 100644 --- a/dll/win32/shell32/folders/cpanel.cpp +++ b/dll/win32/shell32/folders/cpanel.cpp @@ -852,9 +852,14 @@ HRESULT WINAPI CControlPanelFolder::ExecuteFromIdList(LPCITEMIDLIST pidl) } /* Build control panel applet cmd - Note: we passes applet name to Control_RunDLL to distinguish between applets in one .cpl file */ + Note: we pass the applet name to Control_RunDLL to distinguish between multiple applets in one .cpl file */ WCHAR wszCmd[2*MAX_PATH]; - StringCbPrintfW(wszCmd, sizeof(wszCmd), L"rundll32 shell32.dll,Control_RunDLL \"%hs\",\"%hs\"", pCPanel->szName, pCPanel->szName + pCPanel->offsDispName); + WCHAR wszAppletName[MAX_PATH]; + + if(!MultiByteToWideChar(CP_ACP, 0, pCPanel->szName + pCPanel->offsDispName, -1, wszAppletName, MAX_PATH)) + return E_FAIL; + + StringCbPrintfW(wszCmd, sizeof(wszCmd), L"rundll32 shell32.dll,Control_RunDLL \"%hs\",\"%ls\"", pCPanel->szName, wszAppletName); /* Start the applet */ TRACE("Run cpl %ls\n", wszCmd); diff --git a/dll/win32/shell32/lang/cs-CZ.rc b/dll/win32/shell32/lang/cs-CZ.rc index d653e611a86..b3f7b9336cd 100644 --- a/dll/win32/shell32/lang/cs-CZ.rc +++ b/dll/win32/shell32/lang/cs-CZ.rc @@ -1,6 +1,6 @@ /* FILE: dll/win32/shell32/lang/cs-CZ.rc * TRANSLATOR: Radek Liska aka Black_Fox (radekliska at gmail dot com) - * UPDATED: 2013-06-01 + * UPDATED: 2014-04-25 * THANKS TO: navaraf, who translated major part of this file */ @@ -764,7 +764,7 @@ BEGIN IDS_SYS_FILE "Systémový soubor" IDS_OPEN_VERB "Otevřít" - IDS_EXPLORE_VERB "Explore" + IDS_EXPLORE_VERB "Prozkoumat" IDS_RUNAS_VERB "Spustit jako " IDS_EDIT_VERB "Upravit" IDS_FIND_VERB "Najít" diff --git a/dll/win32/shell32/shlexec.cpp b/dll/win32/shell32/shlexec.cpp index 8e022a1a2d7..b1614e38b5d 100644 --- a/dll/win32/shell32/shlexec.cpp +++ b/dll/win32/shell32/shlexec.cpp @@ -450,16 +450,14 @@ static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait, startup.cb = sizeof(STARTUPINFOW); startup.dwFlags = STARTF_USESHOWWINDOW; startup.wShowWindow = psei->nShow; + dwCreationFlags = CREATE_UNICODE_ENVIRONMENT; + if (psei->fMask & SEE_MASK_NO_CONSOLE) + dwCreationFlags |= CREATE_NEW_CONSOLE; startup.lpTitle = (LPWSTR)(psei->fMask & (SEE_MASK_HASLINKNAME | SEE_MASK_HASTITLE) ? psei->lpClass : NULL); if (psei->fMask & SEE_MASK_HASLINKNAME) startup.dwFlags |= STARTF_TITLEISLINKNAME; - dwCreationFlags = CREATE_UNICODE_ENVIRONMENT; - - if (psei->fMask & SEE_MASK_NO_CONSOLE) - dwCreationFlags |= CREATE_NEW_CONSOLE; - if (CreateProcessW(NULL, (LPWSTR)lpCmd, NULL, NULL, FALSE, dwCreationFlags, env, lpDirectory, &startup, &info)) { @@ -703,7 +701,13 @@ static UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOpera lpFile = xlpFile; /* Hey, isn't this value ignored? Why make this call? Shouldn't we return here? --dank*/ } - + else if (lpPath && SearchPathW(NULL, lpFile, wszExe, sizeof(xlpFile)/sizeof(WCHAR), xlpFile, NULL)) + { + TRACE("SearchPathW returned non-zero\n"); + lpFile = xlpFile; + /* The file was found in one of the directories in the system-wide search path */ + } + attribs = GetFileAttributesW(lpFile); if (attribs != INVALID_FILE_ATTRIBUTES && (attribs & FILE_ATTRIBUTE_DIRECTORY)) { diff --git a/dll/win32/shlwapi/path.c b/dll/win32/shlwapi/path.c index 46eb8d93279..c0589ac9780 100644 --- a/dll/win32/shlwapi/path.c +++ b/dll/win32/shlwapi/path.c @@ -3515,7 +3515,7 @@ BOOL WINAPI PathRelativePathToW(LPWSTR lpszPath, LPCWSTR lpszFrom, DWORD dwAttrF if(!(dwAttrFrom & FILE_ATTRIBUTE_DIRECTORY)) PathRemoveFileSpecW(szFrom); - if(!(dwAttrFrom & FILE_ATTRIBUTE_DIRECTORY)) + if(!(dwAttrTo & FILE_ATTRIBUTE_DIRECTORY)) PathRemoveFileSpecW(szTo); /* Paths can only be relative if they have a common root */ diff --git a/dll/win32/syssetup/lang/cs-CZ.rc b/dll/win32/syssetup/lang/cs-CZ.rc index f94b9705d0e..f9eb3a794ea 100644 --- a/dll/win32/syssetup/lang/cs-CZ.rc +++ b/dll/win32/syssetup/lang/cs-CZ.rc @@ -1,6 +1,6 @@ /* FILE: dll/win32/syssetup/lang/cs-CZ.rc * TRANSLATOR: Radek Liska aka Black_Fox (radekliska at gmail dot com) - * UPDATED: 2009-08-02 + * UPDATED: 2014-04-21 * THANKS TO: Filip Navara and Kamil Hornicek, who translated major part of this file */ @@ -12,7 +12,7 @@ CAPTION "ReactOS Instalátor" FONT 8, "MS Shell Dlg" BEGIN LTEXT "Vítejte v průvodci instalace systému ReactOS.", IDC_WELCOMETITLE, 115, 9, 189, 31 - LTEXT "Tento průvodce nainstaluje systém ReactOS na Váš počítač. Průvodce potřebuje získat některé informace o Vás a Vašem počítači aby mohl systém správně nastavit.", IDC_STATIC, 115, 50, 189, 100 + LTEXT "Tento průvodce nainstaluje systém ReactOS na Váš počítač. Průvodce potřebuje získat některé informace o Vás a Vašem počítači, aby mohl systém správně nastavit.", IDC_STATIC, 115, 50, 189, 100 LTEXT "Kliknutím na Další pokračujte v instalaci.", IDC_STATIC, 115, 160, 189, 31 END @@ -155,7 +155,7 @@ BEGIN IDS_TIMEOUT "Vypršel časový limit registrace" IDS_REASON_UNKNOWN "" /* - * ATTENTION: + * ATTENTION: * If you translate the administator account name, keep IDS_ADMINISTRATOR_NAME and * samsrv.dll:IDS_USER_ADMINISTRATOR_NAME synchronized. * Also check the IDD_COMPUTERPAGE dialog. diff --git a/drivers/base/kdcom/kdserial.c b/drivers/base/kdcom/kdserial.c index 2837900a299..bb37a3d9228 100644 --- a/drivers/base/kdcom/kdserial.c +++ b/drivers/base/kdcom/kdserial.c @@ -38,7 +38,7 @@ KdpSendBuffer( * \brief Receives data from the KD port and fills a buffer. * \param Buffer Pointer to a buffer that receives the data. * \param Size Size of data to receive in bytes. - * \return KDP_PACKET_RECEIVED if successful. + * \return KDP_PACKET_RECEIVED if successful. * KDP_PACKET_TIMEOUT if the receice timed out. */ KDP_STATUS @@ -69,7 +69,7 @@ KdpReceiveBuffer( * \name KdpReceivePacketLeader * \brief Receives a packet leadr from the KD port. * \param PacketLeader Pointer to an ULONG that receives the packet leader. - * \return KDP_PACKET_RECEIVED if successful. + * \return KDP_PACKET_RECEIVED if successful. * KDP_PACKET_TIMEOUT if the receive timed out. * KDP_PACKET_RESEND if a breakin byte was detected. */ @@ -141,7 +141,7 @@ KdpReceivePacketLeader( while (Index < 4); /* Enable the debugger */ - KdDebuggerNotPresent = FALSE; + KD_DEBUGGER_NOT_PRESENT = FALSE; SharedUserData->KdDebuggerEnabled |= 0x00000002; /* Return the received packet leader */ diff --git a/drivers/bus/acpi/compbatt/compmisc.c b/drivers/bus/acpi/compbatt/compmisc.c index f34aa9af0c2..337c521835c 100644 --- a/drivers/bus/acpi/compbatt/compmisc.c +++ b/drivers/bus/acpi/compbatt/compmisc.c @@ -14,7 +14,7 @@ NTSTATUS NTAPI -BatteryIoctl(IN ULONG IoControlCode, +BatteryIoctl(IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, @@ -50,11 +50,11 @@ BatteryIoctl(IN ULONG IoControlCode, KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); Status = IoStatusBlock.Status; } - + /* Print failure */ if (!(NT_SUCCESS(Status)) && (CompBattDebug & 8)) DbgPrint("BatteryIoctl: Irp failed - %x\n", Status); - + /* Done */ if (CompBattDebug & 0x100) DbgPrint("CompBatt: EXITING BatteryIoctl\n"); } @@ -64,7 +64,7 @@ BatteryIoctl(IN ULONG IoControlCode, if (CompBattDebug & 8) DbgPrint("BatteryIoctl: couldn't create Irp\n"); Status = STATUS_INSUFFICIENT_RESOURCES; } - + /* Return status */ return Status; } @@ -82,7 +82,7 @@ CompBattGetDeviceObjectPointer(IN PUNICODE_STRING DeviceName, PFILE_OBJECT LocalFileObject; HANDLE DeviceHandle; PAGED_CODE(); - + /* Open a file object handle to the device */ InitializeObjectAttributes(&ObjectAttributes, DeviceName, 0, NULL, NULL); Status = ZwCreateFile(&DeviceHandle, @@ -101,7 +101,7 @@ CompBattGetDeviceObjectPointer(IN PUNICODE_STRING DeviceName, /* Reference the file object */ Status = ObReferenceObjectByHandle(DeviceHandle, 0, - IoFileObjectType, + *IoFileObjectType, KernelMode, (PVOID)&LocalFileObject, NULL); @@ -111,11 +111,11 @@ CompBattGetDeviceObjectPointer(IN PUNICODE_STRING DeviceName, *FileObject = LocalFileObject; *DeviceObject = IoGetRelatedDeviceObject(LocalFileObject); } - + /* Close the handle */ ZwClose(DeviceHandle); } - + /* Return status */ return Status; } diff --git a/drivers/crypto/ksecdd/random.c b/drivers/crypto/ksecdd/random.c index 392ad0f70ca..1d1168a8776 100644 --- a/drivers/crypto/ksecdd/random.c +++ b/drivers/crypto/ksecdd/random.c @@ -31,11 +31,13 @@ KsecGenRandom( PVOID Buffer, SIZE_T Length) { + LARGE_INTEGER TickCount; ULONG i, RandomValue; PULONG P; /* Try to generate a more random seed */ - KsecRandomSeed ^= _rotl(KeTickCount.LowPart, (KsecRandomSeed % 23)); + KeQueryTickCount(&TickCount); + KsecRandomSeed ^= _rotl(TickCount.LowPart, (KsecRandomSeed % 23)); P = Buffer; for (i = 0; i < Length / sizeof(ULONG); i++) @@ -94,7 +96,7 @@ KsecGatherEntropyData( PTEB Teb; PPEB Peb; PWSTR String; - ULONG ReturnLength; + SIZE_T ReturnLength; NTSTATUS Status; /* Query some generic values */ @@ -125,7 +127,7 @@ KsecGatherEntropyData( /* Update the MD4 context from the environment data */ MD4Update(&Md4Context, (PUCHAR)Peb->ProcessParameters->Environment, - (PUCHAR)String - (PUCHAR)Peb->ProcessParameters->Environment); + (ULONG)((PUCHAR)String - (PUCHAR)Peb->ProcessParameters->Environment)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { diff --git a/drivers/filters/mountmgr/device.c b/drivers/filters/mountmgr/device.c index c86df7a5426..4ee8096c7e6 100644 --- a/drivers/filters/mountmgr/device.c +++ b/drivers/filters/mountmgr/device.c @@ -1552,7 +1552,7 @@ MountMgrVolumeMountPointChanged(IN PDEVICE_EXTENSION DeviceExtension, } /* Reference it */ - Status = ObReferenceObjectByHandle(Handle, 0, IoFileObjectType, KernelMode, (PVOID *)&FileObject, NULL); + Status = ObReferenceObjectByHandle(Handle, 0, *IoFileObjectType, KernelMode, (PVOID *)&FileObject, NULL); if (!NT_SUCCESS(Status)) { goto Cleanup; diff --git a/drivers/ksfilter/ks/api.c b/drivers/ksfilter/ks/api.c index 26aa2cf8025..575a5a4bc73 100644 --- a/drivers/ksfilter/ks/api.c +++ b/drivers/ksfilter/ks/api.c @@ -1140,7 +1140,7 @@ KsSynchronousIoControlDevice( if (Status) { /* store bytes returned */ - *BytesReturned = IoStatusBlock.Information; + *BytesReturned = (ULONG)IoStatusBlock.Information; /* return status */ return IoStatusBlock.Status; } @@ -1181,7 +1181,7 @@ KsSynchronousIoControlDevice( Status = IoStatusBlock.Status; } - *BytesReturned = IoStatusBlock.Information; + *BytesReturned = (ULONG)IoStatusBlock.Information; return Status; } @@ -1716,8 +1716,8 @@ KsCompletePendingRequest( return; } - /* FIXME - * delete object / device header + /* FIXME + * delete object / device header * remove dead pin / filter instance */ UNIMPLEMENTED @@ -1782,7 +1782,7 @@ KspDeviceSetGetBusData( Status = IoCallDriver(DeviceObject, Irp); /* is the request still pending */ - if (Status == STATUS_PENDING) + if (Status == STATUS_PENDING) { /* have a nap */ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); @@ -1887,7 +1887,7 @@ KsGetNextSibling( /* get the basic header */ BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER)); - ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory || + ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory || BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin); return (PVOID)BasicHeader->Next.Pin; @@ -2128,7 +2128,7 @@ KspMergePropertySet( PKSPROPERTY_ITEM PropertyItem, CurrentPropertyItem; NTSTATUS Status; - // max properties + // max properties PropertyCount = PropertySetA->PropertiesCount + PropertySetB->PropertiesCount; // allocate items @@ -2518,7 +2518,7 @@ KsRegisterAggregatedClientUnknown( PKSBASIC_HEADER BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER)); /* sanity check */ - ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory || + ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory || BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin); if (BasicHeader->ClientAggregate) diff --git a/drivers/ksfilter/ks/event.c b/drivers/ksfilter/ks/event.c index f851957c19e..96f01464760 100644 --- a/drivers/ksfilter/ks/event.c +++ b/drivers/ksfilter/ks/event.c @@ -87,7 +87,7 @@ NTSTATUS KspEnableEvent( IN PIRP Irp, IN ULONG EventSetsCount, - IN PKSEVENT_SET EventSet, + IN const KSEVENT_SET* EventSet, IN OUT PLIST_ENTRY EventsList OPTIONAL, IN KSEVENTS_LOCKTYPE EventsFlags OPTIONAL, IN PVOID EventsLock OPTIONAL, @@ -99,7 +99,7 @@ KspEnableEvent( KSEVENT Event; PKSEVENT_ITEM EventItem, FoundEventItem; PKSEVENTDATA EventData; - PKSEVENT_SET FoundEventSet; + const KSEVENT_SET *FoundEventSet; PKSEVENT_ENTRY EventEntry; ULONG Index, SubIndex, Size; PVOID Object; @@ -234,7 +234,7 @@ KspEnableEvent( if (EventData->NotificationType == KSEVENTF_SEMAPHORE_HANDLE) { /* get semaphore object handle */ - Status = ObReferenceObjectByHandle(EventData->SemaphoreHandle.Semaphore, SEMAPHORE_MODIFY_STATE, ExSemaphoreObjectType, Irp->RequestorMode, &Object, NULL); + Status = ObReferenceObjectByHandle(EventData->SemaphoreHandle.Semaphore, SEMAPHORE_MODIFY_STATE, *ExSemaphoreObjectType, Irp->RequestorMode, &Object, NULL); if (!NT_SUCCESS(Status)) { @@ -245,7 +245,7 @@ KspEnableEvent( else if (EventData->NotificationType == KSEVENTF_EVENT_HANDLE) { /* get event object handle */ - Status = ObReferenceObjectByHandle(EventData->EventHandle.Event, EVENT_MODIFY_STATE, ExEventObjectType, Irp->RequestorMode, &Object, NULL); + Status = ObReferenceObjectByHandle(EventData->EventHandle.Event, EVENT_MODIFY_STATE, *ExEventObjectType, Irp->RequestorMode, &Object, NULL); if (!NT_SUCCESS(Status)) { @@ -270,7 +270,7 @@ KspEnableEvent( /* invalid type requested */ return STATUS_INVALID_PARAMETER; } - } + } /* calculate request size */ @@ -398,18 +398,19 @@ KsEnableEvent( /* @implemented */ +_IRQL_requires_max_(PASSIVE_LEVEL) KSDDKAPI NTSTATUS NTAPI KsEnableEventWithAllocator( - IN PIRP Irp, - IN ULONG EventSetsCount, - IN PKSEVENT_SET EventSet, - IN OUT PLIST_ENTRY EventsList OPTIONAL, - IN KSEVENTS_LOCKTYPE EventsFlags OPTIONAL, - IN PVOID EventsLock OPTIONAL, - IN PFNKSALLOCATOR Allocator OPTIONAL, - IN ULONG EventItemSize OPTIONAL) + _In_ PIRP Irp, + _In_ ULONG EventSetsCount, + _In_reads_(EventSetsCount) const KSEVENT_SET* EventSet, + _Inout_opt_ PLIST_ENTRY EventsList, + _In_opt_ KSEVENTS_LOCKTYPE EventsFlags, + _In_opt_ PVOID EventsLock, + _In_opt_ PFNKSALLOCATOR Allocator, + _In_opt_ ULONG EventItemSize) { return KspEnableEvent(Irp, EventSetsCount, EventSet, EventsList, EventsFlags, EventsLock, Allocator, EventItemSize); } diff --git a/drivers/ksfilter/ks/ksfunc.h b/drivers/ksfilter/ks/ksfunc.h index 83d57b2bef8..8a930dde136 100644 --- a/drivers/ksfilter/ks/ksfunc.h +++ b/drivers/ksfilter/ks/ksfunc.h @@ -175,7 +175,7 @@ NTSTATUS KspEnableEvent( IN PIRP Irp, IN ULONG EventSetsCount, - IN PKSEVENT_SET EventSet, + IN const KSEVENT_SET* EventSet, IN OUT PLIST_ENTRY EventsList OPTIONAL, IN KSEVENTS_LOCKTYPE EventsFlags OPTIONAL, IN PVOID EventsLock OPTIONAL, diff --git a/drivers/ksfilter/ks/methods.c b/drivers/ksfilter/ks/methods.c index 65b49c60373..e58a6ff0a81 100644 --- a/drivers/ksfilter/ks/methods.c +++ b/drivers/ksfilter/ks/methods.c @@ -147,7 +147,7 @@ KspMethodHandlerWithAllocator( if (Allocator) { /* allocate the requested amount */ - Status = Allocator(Irp, Irp->IoStatus.Information, FALSE); + Status = Allocator(Irp, (ULONG)Irp->IoStatus.Information, FALSE); /* check if the block was allocated */ if (!NT_SUCCESS(Status)) @@ -189,13 +189,14 @@ KspMethodHandlerWithAllocator( /* @implemented */ +_IRQL_requires_max_(PASSIVE_LEVEL) KSDDKAPI NTSTATUS NTAPI KsMethodHandler( - IN PIRP Irp, - IN ULONG MethodSetsCount, - IN PKSMETHOD_SET MethodSet) + _In_ PIRP Irp, + _In_ ULONG MethodSetsCount, + _In_reads_(MethodSetsCount) const KSMETHOD_SET* MethodSet) { return KspMethodHandlerWithAllocator(Irp, MethodSetsCount, MethodSet, NULL, 0); } @@ -203,15 +204,16 @@ KsMethodHandler( /* @implemented */ +_IRQL_requires_max_(PASSIVE_LEVEL) KSDDKAPI NTSTATUS NTAPI KsMethodHandlerWithAllocator( - IN PIRP Irp, - IN ULONG MethodSetsCount, - IN PKSMETHOD_SET MethodSet, - IN PFNKSALLOCATOR Allocator OPTIONAL, - IN ULONG MethodItemSize OPTIONAL) + _In_ PIRP Irp, + _In_ ULONG MethodSetsCount, + _In_reads_(MethodSetsCount) const KSMETHOD_SET* MethodSet, + _In_opt_ PFNKSALLOCATOR Allocator, + _In_opt_ ULONG MethodItemSize) { return KspMethodHandlerWithAllocator(Irp, MethodSetsCount, MethodSet, Allocator, MethodItemSize); } diff --git a/drivers/ksfilter/ks/misc.c b/drivers/ksfilter/ks/misc.c index 1aa2b7dcbdc..9ad2cc57883 100644 --- a/drivers/ksfilter/ks/misc.c +++ b/drivers/ksfilter/ks/misc.c @@ -103,7 +103,7 @@ KspCopyCreateRequest( OUT PVOID * Result) { PIO_STACK_LOCATION IoStack; - ULONG ObjectLength, ParametersLength; + SIZE_T ObjectLength, ParametersLength; PVOID Buffer; /* get current irp stack */ @@ -129,7 +129,7 @@ KspCopyCreateRequest( /* store result */ *Result = Buffer; - *Size = ParametersLength; + *Size = (ULONG)ParametersLength; return STATUS_SUCCESS; } @@ -199,7 +199,7 @@ KsGetOuterUnknown( PKSBASIC_HEADER BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER)); /* sanity check */ - ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory || + ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory || BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin); /* return objects outer unknown */ diff --git a/drivers/ksfilter/ks/pin.c b/drivers/ksfilter/ks/pin.c index 0865b3b7b8c..2226223c90c 100644 --- a/drivers/ksfilter/ks/pin.c +++ b/drivers/ksfilter/ks/pin.c @@ -193,7 +193,7 @@ IKsPin_PinMasterClock( { Mode = ExGetPreviousMode(); - Status = ObReferenceObjectByHandle(*Handle, SYNCHRONIZE | DIRECTORY_QUERY, IoFileObjectType, Mode, (PVOID*)&FileObject, NULL); + Status = ObReferenceObjectByHandle(*Handle, SYNCHRONIZE | DIRECTORY_QUERY, *IoFileObjectType, Mode, (PVOID*)&FileObject, NULL); DPRINT("IKsPin_PinMasterClock ObReferenceObjectByHandle %lx\n", Status); if (NT_SUCCESS(Status)) @@ -2221,7 +2221,7 @@ IKsPin_DispatchCreateClock( pResolution = &Resolution; } - Status = KsAllocateDefaultClockEx(&This->DefaultClock, + Status = KsAllocateDefaultClockEx(&This->DefaultClock, (PVOID)&This->Pin, (PFNKSSETTIMER)This->Pin.Descriptor->Dispatch->Clock->SetTimer, (PFNKSCANCELTIMER)This->Pin.Descriptor->Dispatch->Clock->CancelTimer, @@ -2265,7 +2265,7 @@ IKsPin_DispatchCreateNode( return STATUS_NOT_IMPLEMENTED; } -static KSDISPATCH_TABLE PinDispatchTable = +static KSDISPATCH_TABLE PinDispatchTable = { IKsPin_DispatchDeviceIoControl, KsDispatchInvalidDeviceRequest, @@ -2329,10 +2329,10 @@ KspCreatePin( DPRINT("KspCreatePin Index %lu FileAlignment %lx\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].FileAlignment); DPRINT("KspCreatePin Index %lu MemoryTypeWeight %lx\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].MemoryTypeWeight); DPRINT("KspCreatePin Index %lu PhysicalRange MinFrameSize %lu MaxFrameSize %lu Stepping %lu\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].PhysicalRange.MinFrameSize, - Descriptor->AllocatorFraming->FramingItem[Index].PhysicalRange.MaxFrameSize, + Descriptor->AllocatorFraming->FramingItem[Index].PhysicalRange.MaxFrameSize, Descriptor->AllocatorFraming->FramingItem[Index].PhysicalRange.Stepping); - DPRINT("KspCreatePin Index %lu FramingRange MinFrameSize %lu MaxFrameSize %lu Stepping %lu InPlaceWeight %lu NotInPlaceWeight %lu\n", + DPRINT("KspCreatePin Index %lu FramingRange MinFrameSize %lu MaxFrameSize %lu Stepping %lu InPlaceWeight %lu NotInPlaceWeight %lu\n", Index, Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.Range.MinFrameSize, Descriptor->AllocatorFraming->FramingItem[Index].FramingRange.Range.MaxFrameSize, diff --git a/drivers/ksfilter/ks/property.c b/drivers/ksfilter/ks/property.c index 7d6a29b704c..029043574a1 100644 --- a/drivers/ksfilter/ks/property.c +++ b/drivers/ksfilter/ks/property.c @@ -300,7 +300,7 @@ KspPropertyHandler( if (Allocator) { /* allocate the requested amount */ - Status = Allocator(Irp, Irp->IoStatus.Information, FALSE); + Status = Allocator(Irp, (ULONG)Irp->IoStatus.Information, FALSE); /* check if the block was allocated */ if (!NT_SUCCESS(Status)) @@ -364,15 +364,16 @@ KsPropertyHandler( /* @implemented */ +_IRQL_requires_max_(PASSIVE_LEVEL) KSDDKAPI NTSTATUS NTAPI KsPropertyHandlerWithAllocator( - IN PIRP Irp, - IN ULONG PropertySetsCount, - IN PKSPROPERTY_SET PropertySet, - IN PFNKSALLOCATOR Allocator OPTIONAL, - IN ULONG PropertyItemSize OPTIONAL) + _In_ PIRP Irp, + _In_ ULONG PropertySetsCount, + _In_reads_(PropertySetsCount) const KSPROPERTY_SET* PropertySet, + _In_opt_ PFNKSALLOCATOR Allocator, + _In_opt_ ULONG PropertyItemSize) { return KspPropertyHandler(Irp, PropertySetsCount, PropertySet, Allocator, PropertyItemSize); } diff --git a/drivers/ksfilter/ks/swenum.c b/drivers/ksfilter/ks/swenum.c index 0b76c8562a4..93dbb41274f 100644 --- a/drivers/ksfilter/ks/swenum.c +++ b/drivers/ksfilter/ks/swenum.c @@ -329,7 +329,7 @@ KspCreateDeviceReference( IN LPWSTR ReferenceString) { LPWSTR DeviceName; - ULONG Length; + SIZE_T Length; PLIST_ENTRY Entry; PBUS_DEVICE_ENTRY DeviceEntry = NULL; /* GCC warning */ BOOLEAN ItemExists = FALSE; @@ -523,7 +523,7 @@ KspBusQueryReferenceString( IN OUT PWCHAR *String) { LPWSTR Name; - ULONG Length; + SIZE_T Length; PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)Context; /* sanity checks */ @@ -665,7 +665,7 @@ KspDoReparseForIrp( PIRP Irp, PBUS_DEVICE_ENTRY DeviceEntry) { - ULONG Length; + SIZE_T Length; LPWSTR Buffer; PIO_STACK_LOCATION IoStack; @@ -885,7 +885,7 @@ KspQueryId( PBUS_DEVICE_ENTRY DeviceEntry; PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; LPWSTR Name; - ULONG Length; + SIZE_T Length; /* get current irp stack location */ IoStack = IoGetCurrentIrpStackLocation(Irp); @@ -972,7 +972,7 @@ KspInstallInterface( IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, IN PSWENUM_INSTALL_INTERFACE InstallInterface) { - ULONG Length, Index; + SIZE_T Length, Index; UNICODE_STRING DeviceString, InterfaceString, ReferenceString; HANDLE hKey, hDeviceKey, hInterfaceKey, hReferenceKey; NTSTATUS Status; @@ -1369,7 +1369,7 @@ KsGetBusEnumIdentifier( PDEV_EXTENSION DeviceExtension; PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; PIO_STACK_LOCATION IoStack; - ULONG Length; + SIZE_T Length; NTSTATUS Status; LPWSTR Buffer; @@ -1489,7 +1489,7 @@ KsCreateBusEnumObject( IN REFGUID InterfaceGuid OPTIONAL, IN PWCHAR ServiceRelativePath OPTIONAL) { - ULONG Length; + SIZE_T Length; NTSTATUS Status = STATUS_SUCCESS; UNICODE_STRING ServiceKeyPath = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\"); PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; diff --git a/drivers/ksfilter/ks/topology.c b/drivers/ksfilter/ks/topology.c index c6dc1b77718..2785a9b871b 100644 --- a/drivers/ksfilter/ks/topology.c +++ b/drivers/ksfilter/ks/topology.c @@ -28,7 +28,7 @@ KspCreateObjectType( /* calculate request length */ Name.Length = 0; - Name.MaximumLength = wcslen(ObjectType) * sizeof(WCHAR) + CreateParametersSize + 1 * sizeof(WCHAR); + Name.MaximumLength = (USHORT)(wcslen(ObjectType) * sizeof(WCHAR) + CreateParametersSize + 1 * sizeof(WCHAR)); Name.MaximumLength += sizeof(WCHAR); /* acquire request buffer */ Name.Buffer = AllocateItem(NonPagedPool, Name.MaximumLength); @@ -39,7 +39,7 @@ KspCreateObjectType( return STATUS_INSUFFICIENT_RESOURCES; } - /* build a request which looks like {ObjectClass}\CreateParameters + /* build a request which looks like {ObjectClass}\CreateParameters * For pins the parent is the reference string used in registration * For clocks it is full path for pin\{ClockGuid}\ClockCreateParams */ diff --git a/drivers/network/afd/afd/bind.c b/drivers/network/afd/afd/bind.c index 5bc13bf51a9..21a64fe53f1 100644 --- a/drivers/network/afd/afd/bind.c +++ b/drivers/network/afd/afd/bind.c @@ -105,7 +105,7 @@ AfdBindSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, 0, NULL, MAXIMUM_ALLOWED, - IoFileObjectType, + *IoFileObjectType, Irp->RequestorMode, &UserHandle); if (NT_SUCCESS(Status)) diff --git a/drivers/network/afd/afd/select.c b/drivers/network/afd/afd/select.c index 66b8ac846ca..2e30ca3ba2b 100644 --- a/drivers/network/afd/afd/select.c +++ b/drivers/network/afd/afd/select.c @@ -289,7 +289,7 @@ AfdEventSelect( PDEVICE_OBJECT DeviceObject, PIRP Irp, Status = ObReferenceObjectByHandle( (PVOID)EventSelectInfo-> EventObject, EVENT_ALL_ACCESS, - ExEventObjectType, + *ExEventObjectType, UserMode, (PVOID *)&FCB->EventSelect, NULL ); @@ -346,7 +346,7 @@ AfdEnumEvents( PDEVICE_OBJECT DeviceObject, PIRP Irp, Status = ObReferenceObjectByHandle(EnumReq->Event, EVENT_ALL_ACCESS, - ExEventObjectType, + *ExEventObjectType, UserMode, (PVOID *)&UserEvent, NULL); diff --git a/drivers/network/afd/afd/tdi.c b/drivers/network/afd/afd/tdi.c index 60040e16d39..a36a09dc841 100644 --- a/drivers/network/afd/afd/tdi.c +++ b/drivers/network/afd/afd/tdi.c @@ -144,7 +144,7 @@ static NTSTATUS TdiOpenDevice( if (NT_SUCCESS(Status)) { Status = ObReferenceObjectByHandle(*Handle, /* Handle to open file */ GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, /* Access mode */ - IoFileObjectType, /* Object type */ + *IoFileObjectType, /* Object type */ KernelMode, /* Access mode */ (PVOID*)Object, /* Pointer to object */ NULL); /* Handle information */ diff --git a/drivers/network/tcpip/tcpip/dispatch.c b/drivers/network/tcpip/tcpip/dispatch.c index 94d127db46b..69ed6bf2bf6 100644 --- a/drivers/network/tcpip/tcpip/dispatch.c +++ b/drivers/network/tcpip/tcpip/dispatch.c @@ -173,7 +173,7 @@ VOID NTAPI DispCancelRequest( case TDI_CONNECT: DequeuedIrp = TCPRemoveIRP(TranContext->Handle.ConnectionContext, Irp); break; - + case TDI_DISCONNECT: Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext; @@ -303,7 +303,7 @@ NTSTATUS DispTdiAssociateAddress( Status = ObReferenceObjectByHandle( Parameters->AddressHandle, 0, - IoFileObjectType, + *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); @@ -511,7 +511,7 @@ NTSTATUS DispTdiDisconnect( Status = STATUS_INVALID_PARAMETER; goto done; } - + Status = DispPrepareIrpForCancel (TranContext->Handle.ConnectionContext, Irp, @@ -716,7 +716,7 @@ NTSTATUS DispTdiQueryInformation( case TDI_CONNECTION_FILE: Endpoint = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext; - + Address->TAAddressCount = 1; Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP; Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP; @@ -761,12 +761,12 @@ NTSTATUS DispTdiQueryInformation( case TDI_QUERY_MAX_DATAGRAM_INFO: { PTDI_MAX_DATAGRAM_INFO MaxDatagramInfo; - + if (MmGetMdlByteCount(Irp->MdlAddress) < sizeof(*MaxDatagramInfo)) { TI_DbgPrint(MID_TRACE, ("MDL buffer too small.\n")); return STATUS_BUFFER_TOO_SMALL; } - + MaxDatagramInfo = (PTDI_MAX_DATAGRAM_INFO) MmGetSystemAddressForMdl(Irp->MdlAddress); @@ -1560,7 +1560,7 @@ NTSTATUS DispTdiSetIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) { IF->Netmask.Type = IP_ADDRESS_V4; IF->Netmask.Address.IPv4Address = IpAddrChange->Netmask; - + IF->Broadcast.Type = IP_ADDRESS_V4; IF->Broadcast.Address.IPv4Address = IF->Unicast.Address.IPv4Address | diff --git a/drivers/storage/floppy/floppy.c b/drivers/storage/floppy/floppy.c index 740fd9e18e4..ea4a2be1fa1 100644 --- a/drivers/storage/floppy/floppy.c +++ b/drivers/storage/floppy/floppy.c @@ -761,9 +761,9 @@ InitController(PCONTROLLER_INFO ControllerInfo) HeadLoadTime = SPECIFY_HLT_500K; HeadUnloadTime = SPECIFY_HUT_500K; StepRateTime = SPECIFY_SRT_500K; - + INFO_(FLOPPY, "InitController: setting data rate\n"); - + /* Set data rate */ if(HwSetDataRate(ControllerInfo, DRSR_DSEL_500KBPS) != STATUS_SUCCESS) { @@ -1176,7 +1176,7 @@ DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) return STATUS_INSUFFICIENT_RESOURCES; } - if(ObReferenceObjectByHandle(ThreadHandle, STANDARD_RIGHTS_ALL, PsThreadType, KernelMode, &QueueThreadObject, NULL) != STATUS_SUCCESS) + if(ObReferenceObjectByHandle(ThreadHandle, STANDARD_RIGHTS_ALL, *PsThreadType, KernelMode, &QueueThreadObject, NULL) != STATUS_SUCCESS) { WARN_(FLOPPY, "Unable to reference returned thread handle; failing init\n"); return STATUS_UNSUCCESSFUL; diff --git a/drivers/wdm/audio/legacy/wdmaud/control.c b/drivers/wdm/audio/legacy/wdmaud/control.c index 1b6a90d355e..89d85fd1618 100644 --- a/drivers/wdm/audio/legacy/wdmaud/control.c +++ b/drivers/wdm/audio/legacy/wdmaud/control.c @@ -97,7 +97,7 @@ WdmAudControlDeviceState( DPRINT("WdmAudControlDeviceState\n"); - Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); + Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo->hDevice, DeviceInfo->DeviceType); @@ -197,7 +197,7 @@ WdmAudFrameSize( NTSTATUS Status; /* Get sysaudio pin file object */ - Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); + Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Invalid buffer handle %p\n", DeviceInfo->hDevice); @@ -290,7 +290,7 @@ WdmAudResetStream( DPRINT("WdmAudResetStream\n"); - Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); + Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo->hDevice, DeviceInfo->DeviceType); @@ -528,7 +528,7 @@ WdmAudReadWrite( ASSERT(DeviceInfo); /* now get sysaudio file object */ - Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); + Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Invalid pin handle %p\n", DeviceInfo->hDevice); diff --git a/drivers/wdm/audio/legacy/wdmaud/deviface.c b/drivers/wdm/audio/legacy/wdmaud/deviface.c index 4363a03b1c3..477ac30fc0b 100644 --- a/drivers/wdm/audio/legacy/wdmaud/deviface.c +++ b/drivers/wdm/audio/legacy/wdmaud/deviface.c @@ -165,7 +165,7 @@ WdmAudOpenSysAudioDevices( } /* get the file object */ - Status = ObReferenceObjectByHandle(hSysAudio, FILE_READ_DATA | FILE_WRITE_DATA, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); + Status = ObReferenceObjectByHandle(hSysAudio, FILE_READ_DATA | FILE_WRITE_DATA, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to reference FileObject %x\n", Status); @@ -200,7 +200,7 @@ WdmAudRegisterDeviceInterface( } /* failed to register device interface - * create a symbolic link instead + * create a symbolic link instead */ DeviceExtension->DeviceInterfaceSupport = FALSE; diff --git a/drivers/wdm/audio/legacy/wdmaud/mmixer.c b/drivers/wdm/audio/legacy/wdmaud/mmixer.c index 6642447d73a..deafa02aa40 100644 --- a/drivers/wdm/audio/legacy/wdmaud/mmixer.c +++ b/drivers/wdm/audio/legacy/wdmaud/mmixer.c @@ -202,7 +202,7 @@ Control( PFILE_OBJECT FileObject; /* get file object */ - Status = ObReferenceObjectByHandle(hMixer, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); + Status = ObReferenceObjectByHandle(hMixer, GENERIC_READ | GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { DPRINT("failed to reference %p with %lx\n", hMixer, Status); @@ -420,7 +420,7 @@ WdmAudControlOpenMixer( if (DeviceInfo->u.hNotifyEvent) { - Status = ObReferenceObjectByHandle(DeviceInfo->u.hNotifyEvent, EVENT_MODIFY_STATE, ExEventObjectType, UserMode, (LPVOID*)&EventObject, NULL); + Status = ObReferenceObjectByHandle(DeviceInfo->u.hNotifyEvent, EVENT_MODIFY_STATE, *ExEventObjectType, UserMode, (LPVOID*)&EventObject, NULL); if (!NT_SUCCESS(Status)) { diff --git a/drivers/wdm/audio/legacy/wdmaud/sup.c b/drivers/wdm/audio/legacy/wdmaud/sup.c index c7c33a53005..f19178980d8 100644 --- a/drivers/wdm/audio/legacy/wdmaud/sup.c +++ b/drivers/wdm/audio/legacy/wdmaud/sup.c @@ -420,7 +420,7 @@ OpenDevice( if (FileObject) { - Status = ObReferenceObjectByHandle(hDevice, FILE_READ_DATA | FILE_WRITE_DATA, IoFileObjectType, KernelMode, (PVOID*)FileObject, NULL); + Status = ObReferenceObjectByHandle(hDevice, FILE_READ_DATA | FILE_WRITE_DATA, *IoFileObjectType, KernelMode, (PVOID*)FileObject, NULL); if (!NT_SUCCESS(Status)) { diff --git a/drivers/wdm/audio/sysaudio/deviface.c b/drivers/wdm/audio/sysaudio/deviface.c index 8db29770753..5e5bb098092 100644 --- a/drivers/wdm/audio/sysaudio/deviface.c +++ b/drivers/wdm/audio/sysaudio/deviface.c @@ -50,7 +50,7 @@ OpenDevice( return Status; } - Status = ObReferenceObjectByHandle(NodeHandle, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); + Status = ObReferenceObjectByHandle(NodeHandle, GENERIC_READ | GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { ZwClose(NodeHandle); diff --git a/drivers/wdm/audio/sysaudio/pin.c b/drivers/wdm/audio/sysaudio/pin.c index f0c7f444214..1b688aac936 100644 --- a/drivers/wdm/audio/sysaudio/pin.c +++ b/drivers/wdm/audio/sysaudio/pin.c @@ -35,7 +35,7 @@ Pin_fnDeviceIoControl( ASSERT(Context); /* acquire real pin file object */ - Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); + Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { Irp->IoStatus.Information = 0; @@ -94,7 +94,7 @@ Pin_fnWrite( } /* acquire real pin file object */ - Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); + Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("failed\n"); @@ -235,8 +235,8 @@ CreateMixerPinAndSetFormat( } Status = ObReferenceObjectByHandle(PinHandle, - GENERIC_READ | GENERIC_WRITE, - IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); + GENERIC_READ | GENERIC_WRITE, + *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { diff --git a/drivers/wmi/CMakeLists.txt b/drivers/wmi/CMakeLists.txt index 2fb593b2893..35f19842bab 100644 --- a/drivers/wmi/CMakeLists.txt +++ b/drivers/wmi/CMakeLists.txt @@ -12,4 +12,4 @@ set_module_type(wmilib kernelmodedriver ENTRYPOINT 0) add_importlibs(wmilib ntoskrnl) -add_cd_file(TARGET wmilib DESTINATION reactos/system32/drivers FOR all) +add_cd_file(TARGET wmilib DESTINATION reactos/system32/drivers NO_CAB FOR all) diff --git a/include/ddk/isvbop.h b/include/ddk/isvbop.h new file mode 100644 index 00000000000..088e9e6dcda --- /dev/null +++ b/include/ddk/isvbop.h @@ -0,0 +1,51 @@ +/* + * isvbop.h + * + * Windows NT Device Driver Kit + * + * This file is part of the ReactOS DDK package. + * + * Contributors: + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +/* + * The corresponding ASM header of this file is isvbop.inc. + */ + +#pragma once + +/* BOP Identifiers */ +#define BOP_3RDPARTY 0x58 // 3rd-party VDD BOP +#define BOP_UNSIMULATE 0xFE // Stop execution + +#if defined(__GNUC__) + +#define RegisterModule() __asm__(".byte 0xC4, 0xC4, %c0, 0" : : "i"(BOP_3RDPARTY)) +#define UnRegisterModule() __asm__(".byte 0xC4, 0xC4, %c0, 1" : : "i"(BOP_3RDPARTY)) +#define DispatchCall() __asm__(".byte 0xC4, 0xC4, %c0, 2" : : "i"(BOP_3RDPARTY)) +#define VDDUnSimulate16() __asm__(".byte 0xC4, 0xC4, %c0" : : "i"(BOP_UNSIMULATE)) + +#elif defined(_MSC_VER) + +#define RegisterModule() _asm _emit 0xC4 _asm _emit 0xC4 _asm _emit BOP_3RDPARTY _asm _emit 0 +#define UnRegisterModule() _asm _emit 0xC4 _asm _emit 0xC4 _asm _emit BOP_3RDPARTY _asm _emit 1 +#define DispatchCall() _asm _emit 0xC4 _asm _emit 0xC4 _asm _emit BOP_3RDPARTY _asm _emit 2 +#define VDDUnSimulate16() _asm _emit 0xC4 _asm _emit 0xC4 _asm _emit BOP_UNSIMULATE + +#else +#error Unknown compiler for inline assembler +#endif + +/* EOF */ diff --git a/include/ddk/isvbop.inc b/include/ddk/isvbop.inc new file mode 100644 index 00000000000..7a13b4bc27a --- /dev/null +++ b/include/ddk/isvbop.inc @@ -0,0 +1,49 @@ +/* + * isvbop.inc + * + * Windows NT Device Driver Kit + * + * This file is part of the ReactOS DDK package. + * + * Contributors: + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +/* + * This is the corresponding ASM header for isvbop.h. + * Please refer to isvbop.h for information about these interfaces. + */ + +#include + +BOP_3RDPARTY = HEX(58) +BOP_UNSIMULATE = HEX(FE) + +MACRO(RegisterModule) + .byte HEX(C4), HEX(C4), BOP_3RDPARTY, 0 +ENDM + +MACRO(UnRegisterModule) + .byte HEX(C4), HEX(C4), BOP_3RDPARTY, 1 +ENDM + +MACRO(DispatchCall) + .byte HEX(C4), HEX(C4), BOP_3RDPARTY, 2 +ENDM + +MACRO(VDDUnSimulate16) + .byte HEX(C4), HEX(C4), BOP_UNSIMULATE +ENDM + +/* EOF */ diff --git a/include/ddk/nt_vdd.h b/include/ddk/nt_vdd.h new file mode 100644 index 00000000000..b4b6c7df67d --- /dev/null +++ b/include/ddk/nt_vdd.h @@ -0,0 +1,161 @@ +/* + * nt_vdd.h + * + * Windows NT Device Driver Kit + * + * This file is part of the ReactOS DDK package. + * + * Contributors: + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#pragma once + +#define _NT_VDD + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * VDM Control + */ + +VOID +WINAPI +VDDSimulate16(VOID); + +VOID +WINAPI +VDDTerminateVDM(VOID); + + +/* + * I/O Port services + */ + +typedef VOID (*PFNVDD_INB) (WORD iport, PBYTE data); +typedef VOID (*PFNVDD_INW) (WORD iport, PWORD data); +typedef VOID (*PFNVDD_INSB) (WORD iport, PBYTE data, WORD count); +typedef VOID (*PFNVDD_INSW) (WORD iport, PWORD data, WORD count); +typedef VOID (*PFNVDD_OUTB) (WORD iport, BYTE data); +typedef VOID (*PFNVDD_OUTW) (WORD iport, WORD data); +typedef VOID (*PFNVDD_OUTSB) (WORD iport, PBYTE data, WORD count); +typedef VOID (*PFNVDD_OUTSW) (WORD iport, PWORD data, WORD count); + +typedef struct _VDD_IO_HANDLERS +{ + PFNVDD_INB inb_handler; + PFNVDD_INW inw_handler; + PFNVDD_INSB insb_handler; + PFNVDD_INSW insw_handler; + PFNVDD_OUTB outb_handler; + PFNVDD_OUTW outw_handler; + PFNVDD_OUTSB outsb_handler; + PFNVDD_OUTSW outsw_handler; +} VDD_IO_HANDLERS, *PVDD_IO_HANDLERS; + +typedef struct _VDD_IO_PORTRANGE +{ + WORD First; + WORD Last; +} VDD_IO_PORTRANGE, *PVDD_IO_PORTRANGE; + +BOOL +WINAPI +VDDInstallIOHook +( + HANDLE hVdd, + WORD cPortRange, + PVDD_IO_PORTRANGE pPortRange, + PVDD_IO_HANDLERS IOhandler +); + +VOID +WINAPI +VDDDeInstallIOHook +( + HANDLE hVdd, + WORD cPortRange, + PVDD_IO_PORTRANGE pPortRange +); + + +/* + * Memory services + */ + +typedef enum +{ + VDM_V86, + VDM_PM +} VDM_MODE; + +#ifndef MSW_PE +#define MSW_PE 0x0001 +#endif + +#define getMODE() ((getMSW() & MSW_PE) ? VDM_PM : VDM_V86) + +PBYTE +WINAPI +Sim32pGetVDMPointer +( + IN ULONG Address, + IN BOOLEAN ProtectedMode +); + +PBYTE +WINAPI +MGetVdmPointer +( + IN ULONG Address, + IN ULONG Size, + IN BOOLEAN ProtectedMode +); + +PVOID +WINAPI +VdmMapFlat +( + IN USHORT Segment, + IN ULONG Offset, + IN VDM_MODE Mode +); + +BOOL +WINAPI +VdmFlushCache +( + IN USHORT Segment, + IN ULONG Offset, + IN ULONG Size, + IN VDM_MODE Mode +); + +BOOL +WINAPI +VdmUnmapFlat +( + IN USHORT Segment, + IN ULONG Offset, + IN PVOID Buffer, + IN VDM_MODE Mode +); + +#ifdef __cplusplus +} +#endif + +/* EOF */ diff --git a/include/ddk/ntddk.h b/include/ddk/ntddk.h index b8e4e03d995..8cf5a48f28a 100644 --- a/include/ddk/ntddk.h +++ b/include/ddk/ntddk.h @@ -1666,14 +1666,12 @@ typedef struct { #endif } HAL_DISPATCH, *PHAL_DISPATCH; -/* GCC/MSVC and WDK compatible declaration */ -extern NTKERNELAPI HAL_DISPATCH HalDispatchTable; - -#if defined(_NTOSKRNL_) || defined(_BLDR_) +#ifdef _NTSYSTEM_ +extern HAL_DISPATCH HalDispatchTable; #define HALDISPATCH (&HalDispatchTable) #else -/* This is a WDK compatibility definition */ -#define HalDispatchTable (&HalDispatchTable) +extern PHAL_DISPATCH HalDispatchTable; +__CREATE_NTOS_DATA_IMPORT_ALIAS(HalDispatchTable) #define HALDISPATCH HalDispatchTable #endif diff --git a/include/ddk/ntifs.h b/include/ddk/ntifs.h index df190c10d0a..53b2d135915 100644 --- a/include/ddk/ntifs.h +++ b/include/ddk/ntifs.h @@ -4937,35 +4937,13 @@ FsRtlNotifyStreamFileObject( _In_ BOOLEAN SafeToRecurse); #endif /* (NTDDI_VERSION >= NTDDI_VISTA) */ -#define DO_VERIFY_VOLUME 0x00000002 -#define DO_BUFFERED_IO 0x00000004 -#define DO_EXCLUSIVE 0x00000008 -#define DO_DIRECT_IO 0x00000010 -#define DO_MAP_IO_BUFFER 0x00000020 -#define DO_DEVICE_HAS_NAME 0x00000040 -#define DO_DEVICE_INITIALIZING 0x00000080 -#define DO_SYSTEM_BOOT_PARTITION 0x00000100 -#define DO_LONG_TERM_REQUESTS 0x00000200 -#define DO_NEVER_LAST_DEVICE 0x00000400 -#define DO_SHUTDOWN_REGISTERED 0x00000800 -#define DO_BUS_ENUMERATED_DEVICE 0x00001000 -#define DO_POWER_PAGABLE 0x00002000 -#define DO_POWER_INRUSH 0x00004000 -#define DO_LOW_PRIORITY_FILESYSTEM 0x00010000 -#define DO_SUPPORTS_TRANSACTIONS 0x00040000 -#define DO_FORCE_NEITHER_IO 0x00080000 -#define DO_VOLUME_DEVICE_OBJECT 0x00100000 -#define DO_SYSTEM_SYSTEM_PARTITION 0x00200000 -#define DO_SYSTEM_CRITICAL_PARTITION 0x00400000 -#define DO_DISALLOW_EXECUTE 0x00800000 - -extern KSPIN_LOCK IoStatisticsLock; -extern ULONG IoReadOperationCount; -extern ULONG IoWriteOperationCount; -extern ULONG IoOtherOperationCount; -extern LARGE_INTEGER IoReadTransferCount; -extern LARGE_INTEGER IoWriteTransferCount; -extern LARGE_INTEGER IoOtherTransferCount; +extern NTKERNELAPI KSPIN_LOCK IoStatisticsLock; +extern NTKERNELAPI ULONG IoReadOperationCount; +extern NTKERNELAPI ULONG IoWriteOperationCount; +extern NTKERNELAPI ULONG IoOtherOperationCount; +extern NTKERNELAPI LARGE_INTEGER IoReadTransferCount; +extern NTKERNELAPI LARGE_INTEGER IoWriteTransferCount; +extern NTKERNELAPI LARGE_INTEGER IoOtherTransferCount; #define IO_FILE_OBJECT_NON_PAGED_POOL_CHARGE 64 #define IO_FILE_OBJECT_PAGED_POOL_CHARGE 1024 @@ -5731,6 +5709,7 @@ SeLocateProcessImageName( ((PSECURITY_SUBJECT_CONTEXT) SubjectContext)->PrimaryToken ) extern NTKERNELAPI PSE_EXPORTS SeExports; + /****************************************************************************** * Process Manager Functions * ******************************************************************************/ @@ -8413,26 +8392,31 @@ FsRtlRemovePerFileObjectContext( (InterlockedDecrement((LONG volatile *)&((FL)->LockRequestsInProgress)));\ } -/* GCC compatible definition, MS one is retarded */ -extern NTKERNELAPI const UCHAR * const FsRtlLegalAnsiCharacterArray; -#define LEGAL_ANSI_CHARACTER_ARRAY FsRtlLegalAnsiCharacterArray +#ifdef _NTSYSTEM_ +extern const UCHAR * const FsRtlLegalAnsiCharacterArray; +#define LEGAL_ANSI_CHARACTER_ARRAY FsRtlLegalAnsiCharacterArray +#else +extern const UCHAR * const *FsRtlLegalAnsiCharacterArray; +__CREATE_NTOS_DATA_IMPORT_ALIAS(FsRtlLegalAnsiCharacterArray) +#define LEGAL_ANSI_CHARACTER_ARRAY (*FsRtlLegalAnsiCharacterArray) +#endif #define FsRtlIsAnsiCharacterWild(C) ( \ - FlagOn(FsRtlLegalAnsiCharacterArray[(UCHAR)(C)], FSRTL_WILD_CHARACTER ) \ + FlagOn(LEGAL_ANSI_CHARACTER_ARRAY[(UCHAR)(C)], FSRTL_WILD_CHARACTER ) \ ) #define FsRtlIsAnsiCharacterLegalFat(C, WILD) ( \ - FlagOn(FsRtlLegalAnsiCharacterArray[(UCHAR)(C)], (FSRTL_FAT_LEGAL) | \ + FlagOn(LEGAL_ANSI_CHARACTER_ARRAY[(UCHAR)(C)], (FSRTL_FAT_LEGAL) | \ ((WILD) ? FSRTL_WILD_CHARACTER : 0 )) \ ) #define FsRtlIsAnsiCharacterLegalHpfs(C, WILD) ( \ - FlagOn(FsRtlLegalAnsiCharacterArray[(UCHAR)(C)], (FSRTL_HPFS_LEGAL) | \ + FlagOn(LEGAL_ANSI_CHARACTER_ARRAY[(UCHAR)(C)], (FSRTL_HPFS_LEGAL) | \ ((WILD) ? FSRTL_WILD_CHARACTER : 0 )) \ ) #define FsRtlIsAnsiCharacterLegalNtfs(C, WILD) ( \ - FlagOn(FsRtlLegalAnsiCharacterArray[(UCHAR)(C)], (FSRTL_NTFS_LEGAL) | \ + FlagOn(LEGAL_ANSI_CHARACTER_ARRAY[(UCHAR)(C)], (FSRTL_NTFS_LEGAL) | \ ((WILD) ? FSRTL_WILD_CHARACTER : 0 )) \ ) @@ -8460,7 +8444,7 @@ extern NTKERNELAPI const UCHAR * const FsRtlLegalAnsiCharacterArray; #define FsRtlIsUnicodeCharacterWild(C) ( \ (((C) >= 0x40) ? \ FALSE : \ - FlagOn(FsRtlLegalAnsiCharacterArray[(C)], FSRTL_WILD_CHARACTER )) \ + FlagOn(LEGAL_ANSI_CHARACTER_ARRAY[(C)], FSRTL_WILD_CHARACTER )) \ ) #define FsRtlInitPerFileContext( _fc, _owner, _inst, _cb) \ @@ -8623,7 +8607,7 @@ typedef VOID (((PSECTION_OBJECT_POINTERS)(FO)->SectionObjectPointer)->SharedCacheMap != NULL) \ ) -extern ULONG CcFastMdlReadWait; +extern NTKERNELAPI ULONG CcFastMdlReadWait; #if (NTDDI_VERSION >= NTDDI_WIN2K) @@ -11005,13 +10989,14 @@ HalGetDmaAlignmentRequirement( #define HalGetDmaAlignmentRequirement() 1L #endif -extern NTKERNELAPI PUSHORT NlsOemLeadByteInfo; -#define NLS_OEM_LEAD_BYTE_INFO NlsOemLeadByteInfo - -#ifdef NLS_MB_CODE_PAGE_TAG -#undef NLS_MB_CODE_PAGE_TAG +#ifdef _NTSYSTEM_ +extern PUSHORT NlsOemLeadByteInfo; +#define NLS_OEM_LEAD_BYTE_INFO NlsOemLeadByteInfo +#else +extern PUSHORT *NlsOemLeadByteInfo; +__CREATE_NTOS_DATA_IMPORT_ALIAS(NlsOemLeadByteInfo) +#define NLS_OEM_LEAD_BYTE_INFO (*NlsOemLeadByteInfo) #endif -#define NLS_MB_CODE_PAGE_TAG NlsMbOemCodePageTag #if (NTDDI_VERSION >= NTDDI_VISTA) diff --git a/include/ddk/vddsvc.h b/include/ddk/vddsvc.h new file mode 100644 index 00000000000..451a2c444e9 --- /dev/null +++ b/include/ddk/vddsvc.h @@ -0,0 +1,254 @@ +/* + * vddsvc.h + * + * Windows NT Device Driver Kit + * + * This file is part of the ReactOS DDK package. + * + * Contributors: + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#pragma once + +#ifndef _NT_VDD +#include +#endif + +/* + * Interrupts services + */ +#define ICA_MASTER 0 +#define ICA_SLAVE 1 + +VOID +WINAPI +call_ica_hw_interrupt +( + INT ms, + BYTE line, + INT count +); + +#define VDDSimulateInterrupt(ms, line, count) \ + call_ica_hw_interrupt((ms), (line), (count)) // Windows specifies a count of 1 ... + + +/* + * Registers manipulation + */ +PVOID WINAPI getIntelRegistersPointer(VOID); + +#ifndef _M_MIPS + +ULONG WINAPI getEAX(VOID); +VOID WINAPI setEAX(ULONG); +USHORT WINAPI getAX(VOID); +VOID WINAPI setAX(USHORT); +UCHAR WINAPI getAH(VOID); +VOID WINAPI setAH(UCHAR); +UCHAR WINAPI getAL(VOID); +VOID WINAPI setAL(UCHAR); + +ULONG WINAPI getEBX(VOID); +VOID WINAPI setEBX(ULONG); +USHORT WINAPI getBX(VOID); +VOID WINAPI setBX(USHORT); +UCHAR WINAPI getBH(VOID); +VOID WINAPI setBH(UCHAR); +UCHAR WINAPI getBL(VOID); +VOID WINAPI setBL(UCHAR); + +ULONG WINAPI getECX(VOID); +VOID WINAPI setECX(ULONG); +USHORT WINAPI getCX(VOID); +VOID WINAPI setCX(USHORT); +UCHAR WINAPI getCH(VOID); +VOID WINAPI setCH(UCHAR); +UCHAR WINAPI getCL(VOID); +VOID WINAPI setCL(UCHAR); + +ULONG WINAPI getEDX(VOID); +VOID WINAPI setEDX(ULONG); +USHORT WINAPI getDX(VOID); +VOID WINAPI setDX(USHORT); +UCHAR WINAPI getDH(VOID); +VOID WINAPI setDH(UCHAR); +UCHAR WINAPI getDL(VOID); +VOID WINAPI setDL(UCHAR); + + + +ULONG WINAPI getESP(VOID); +VOID WINAPI setESP(ULONG); +USHORT WINAPI getSP(VOID); +VOID WINAPI setSP(USHORT); + +ULONG WINAPI getEBP(VOID); +VOID WINAPI setEBP(ULONG); +USHORT WINAPI getBP(VOID); +VOID WINAPI setBP(USHORT); + +ULONG WINAPI getESI(VOID); +VOID WINAPI setESI(ULONG); +USHORT WINAPI getSI(VOID); +VOID WINAPI setSI(USHORT); + +ULONG WINAPI getEDI(VOID); +VOID WINAPI setEDI(ULONG); +USHORT WINAPI getDI(VOID); +VOID WINAPI setDI(USHORT); + +ULONG WINAPI getEIP(VOID); +VOID WINAPI setEIP(ULONG); +USHORT WINAPI getIP(VOID); +VOID WINAPI setIP(USHORT); + +USHORT WINAPI getCS(VOID); +VOID WINAPI setCS(USHORT); +USHORT WINAPI getSS(VOID); +VOID WINAPI setSS(USHORT); +USHORT WINAPI getDS(VOID); +VOID WINAPI setDS(USHORT); +USHORT WINAPI getES(VOID); +VOID WINAPI setES(USHORT); +USHORT WINAPI getFS(VOID); +VOID WINAPI setFS(USHORT); +USHORT WINAPI getGS(VOID); +VOID WINAPI setGS(USHORT); + +ULONG WINAPI getCF(VOID); +VOID WINAPI setCF(ULONG); +ULONG WINAPI getPF(VOID); +VOID WINAPI setPF(ULONG); +ULONG WINAPI getAF(VOID); +VOID WINAPI setAF(ULONG); +ULONG WINAPI getZF(VOID); +VOID WINAPI setZF(ULONG); +ULONG WINAPI getSF(VOID); +VOID WINAPI setSF(ULONG); +ULONG WINAPI getIF(VOID); +VOID WINAPI setIF(ULONG); +ULONG WINAPI getDF(VOID); +VOID WINAPI setDF(ULONG); +ULONG WINAPI getOF(VOID); +VOID WINAPI setOF(ULONG); + +ULONG WINAPI getEFLAGS(VOID); +VOID WINAPI setEFLAGS(ULONG); + +USHORT WINAPI getMSW(VOID); +VOID WINAPI setMSW(USHORT); + +#else + +ULONG WINAPI c_getEAX(VOID); +VOID WINAPI c_setEAX(ULONG); +USHORT WINAPI c_getAX(VOID); +VOID WINAPI c_setAX(USHORT); +UCHAR WINAPI c_getAH(VOID); +VOID WINAPI c_setAH(UCHAR); +UCHAR WINAPI c_getAL(VOID); +VOID WINAPI c_setAL(UCHAR); + +ULONG WINAPI c_getEBX(VOID); +VOID WINAPI c_setEBX(ULONG); +USHORT WINAPI c_getBX(VOID); +VOID WINAPI c_setBX(USHORT); +UCHAR WINAPI c_getBH(VOID); +VOID WINAPI c_setBH(UCHAR); +UCHAR WINAPI c_getBL(VOID); +VOID WINAPI c_setBL(UCHAR); + +ULONG WINAPI c_getECX(VOID); +VOID WINAPI c_setECX(ULONG); +USHORT WINAPI c_getCX(VOID); +VOID WINAPI c_setCX(USHORT); +UCHAR WINAPI c_getCH(VOID); +VOID WINAPI c_setCH(UCHAR); +UCHAR WINAPI c_getCL(VOID); +VOID WINAPI c_setCL(UCHAR); + +ULONG WINAPI c_getEDX(VOID); +VOID WINAPI c_setEDX(ULONG); +USHORT WINAPI c_getDX(VOID); +VOID WINAPI c_setDX(USHORT); +UCHAR WINAPI c_getDH(VOID); +VOID WINAPI c_setDH(UCHAR); +UCHAR WINAPI c_getDL(VOID); +VOID WINAPI c_setDL(UCHAR); + + + +ULONG WINAPI c_getESP(VOID); +VOID WINAPI c_setESP(ULONG); +USHORT WINAPI c_getSP(VOID); +VOID WINAPI c_setSP(USHORT); + +ULONG WINAPI c_getEBP(VOID); +VOID WINAPI c_setEBP(ULONG); +USHORT WINAPI c_getBP(VOID); +VOID WINAPI c_setBP(USHORT); + +ULONG WINAPI c_getESI(VOID); +VOID WINAPI c_setESI(ULONG); +USHORT WINAPI c_getSI(VOID); +VOID WINAPI c_setSI(USHORT); + +ULONG WINAPI c_getEDI(VOID); +VOID WINAPI c_setEDI(ULONG); +USHORT WINAPI c_getDI(VOID); +VOID WINAPI c_setDI(USHORT); + +ULONG WINAPI c_getEIP(VOID); +VOID WINAPI c_setEIP(ULONG); +USHORT WINAPI c_getIP(VOID); +VOID WINAPI c_setIP(USHORT); + +USHORT WINAPI c_getCS(VOID); +VOID WINAPI c_setCS(USHORT); +USHORT WINAPI c_getSS(VOID); +VOID WINAPI c_setSS(USHORT); +USHORT WINAPI c_getDS(VOID); +VOID WINAPI c_setDS(USHORT); +USHORT WINAPI c_getES(VOID); +VOID WINAPI c_setES(USHORT); +USHORT WINAPI c_getFS(VOID); +VOID WINAPI c_setFS(USHORT); +USHORT WINAPI c_getGS(VOID); +VOID WINAPI c_setGS(USHORT); + +ULONG WINAPI c_getCF(VOID); +VOID WINAPI c_setCF(ULONG); +ULONG WINAPI c_getPF(VOID); +VOID WINAPI c_setPF(ULONG); +ULONG WINAPI c_getAF(VOID); +VOID WINAPI c_setAF(ULONG); +ULONG WINAPI c_getZF(VOID); +VOID WINAPI c_setZF(ULONG); +ULONG WINAPI c_getSF(VOID); +VOID WINAPI c_setSF(ULONG); +ULONG WINAPI c_getIF(VOID); +VOID WINAPI c_setIF(ULONG); +ULONG WINAPI c_getDF(VOID); +VOID WINAPI c_setDF(ULONG); +ULONG WINAPI c_getOF(VOID); +VOID WINAPI c_setOF(ULONG); + +USHORT WINAPI c_getMSW(VOID); +VOID WINAPI c_setMSW(USHORT); + +#endif + +/* EOF */ diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index 124e45b4012..8d040604b0c 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -82,10 +82,13 @@ extern "C" { #endif /* For ReactOS */ -#if !defined(_NTOSKRNL_) && !defined(_BLDR_) +#if !defined(_NTOSKRNL_) && !defined(_BLDR_) && !defined(_NTSYSTEM_) #define NTKERNELAPI DECLSPEC_IMPORT #else #define NTKERNELAPI +#ifndef _NTSYSTEM_ +#define _NTSYSTEM_ +#endif #endif #if defined(_X86_) && !defined(_NTHAL_) @@ -129,6 +132,29 @@ extern "C" { #define ALLOC_DATA_PRAGMA 1 #endif +#endif /* _MSC_VER */ + +/* These macros are used to create aliases for imported data. We need to do + this to have declarations that are compatible with MS DDK */ +#ifdef _M_IX86 +#define __SYMBOL(_Name) "_"#_Name +#define __IMPORTSYMBOL(_Name) "__imp__"#_Name +#define __IMPORTNAME(_Name) _imp__##_Name +#else +#define __SYMBOL(_Name) #_Name +#define __IMPORTSYMBOL(_Name) "__imp_"#_Name +#define __IMPORTNAME(_Name) __imp_##_Name +#endif +#ifdef _MSC_VER +#define __CREATE_NTOS_DATA_IMPORT_ALIAS(_Name) \ + __pragma(comment(linker, "/alternatename:"__SYMBOL(_Name) "=" __IMPORTSYMBOL(_Name))) +#else /* !_MSC_VER */ +#ifndef __STRINGIFY +#define __STRINGIFY(_exp) #_exp +#endif +#define _Pragma_redefine_extname(_Name, _Target) _Pragma(__STRINGIFY(redefine_extname _Name _Target)) +#define __CREATE_NTOS_DATA_IMPORT_ALIAS(_Name) \ + _Pragma_redefine_extname(_Name,__IMPORTNAME(_Name)) #endif #if defined(_WIN64) @@ -599,11 +625,19 @@ typedef struct _EXCEPTION_POINTERS { PCONTEXT ContextRecord; } EXCEPTION_POINTERS, *PEXCEPTION_POINTERS; -/* MS definition is broken! */ -extern BOOLEAN NTSYSAPI NlsMbCodePageTag; -extern BOOLEAN NTSYSAPI NlsMbOemCodePageTag; +#ifdef _NTSYSTEM_ +extern BOOLEAN NlsMbCodePageTag; #define NLS_MB_CODE_PAGE_TAG NlsMbCodePageTag +extern BOOLEAN NlsMbOemCodePageTag; #define NLS_MB_OEM_CODE_PAGE_TAG NlsMbOemCodePageTag +#else +extern BOOLEAN *NlsMbCodePageTag; +__CREATE_NTOS_DATA_IMPORT_ALIAS(NlsMbCodePageTag) +#define NLS_MB_CODE_PAGE_TAG (*NlsMbCodePageTag) +extern BOOLEAN *NlsMbOemCodePageTag; +__CREATE_NTOS_DATA_IMPORT_ALIAS(NlsMbOemCodePageTag) +#define NLS_MB_OEM_CODE_PAGE_TAG (*NlsMbOemCodePageTag) +#endif #define SHORT_LEAST_SIGNIFICANT_BIT 0 #define SHORT_MOST_SIGNIFICANT_BIT 1 @@ -1673,6 +1707,7 @@ extern NTSYSAPI volatile CCHAR KeNumberProcessors; extern NTSYSAPI CCHAR KeNumberProcessors; #else extern PCCHAR KeNumberProcessors; +__CREATE_NTOS_DATA_IMPORT_ALIAS(KeNumberProcessors) #endif @@ -1824,8 +1859,11 @@ typedef enum _MM_SYSTEM_SIZE { MmLargeSystem } MM_SYSTEMSIZE; -extern NTKERNELAPI BOOLEAN Mm64BitPhysicalAddress; -extern PVOID MmBadPointer; +#ifndef _NTSYSTEM_ +extern PBOOLEAN Mm64BitPhysicalAddress; +__CREATE_NTOS_DATA_IMPORT_ALIAS(Mm64BitPhysicalAddress) +#endif +extern NTKERNELAPI PVOID MmBadPointer; /****************************************************************************** @@ -2098,7 +2136,7 @@ typedef struct _RESOURCE_PERFORMANCE_DATA { /* Global debug flag */ #if DEVL -extern ULONG NtGlobalFlag; +extern NTKERNELAPI ULONG NtGlobalFlag; #define IF_NTOS_DEBUG(FlagName) if (NtGlobalFlag & (FLG_##FlagName)) #else #define IF_NTOS_DEBUG(FlagName) if(FALSE) @@ -7857,6 +7895,7 @@ typedef struct _OBJECT_NAME_INFORMATION { } OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION; /* Exported object types */ +#ifdef _NTSYSTEM_ extern POBJECT_TYPE NTSYSAPI CmKeyObjectType; extern POBJECT_TYPE NTSYSAPI ExEventObjectType; extern POBJECT_TYPE NTSYSAPI ExSemaphoreObjectType; @@ -7864,6 +7903,30 @@ extern POBJECT_TYPE NTSYSAPI IoFileObjectType; extern POBJECT_TYPE NTSYSAPI PsThreadType; extern POBJECT_TYPE NTSYSAPI SeTokenObjectType; extern POBJECT_TYPE NTSYSAPI PsProcessType; +#else +extern POBJECT_TYPE *CmKeyObjectType; +extern POBJECT_TYPE *IoFileObjectType; +extern POBJECT_TYPE *ExEventObjectType; +extern POBJECT_TYPE *ExSemaphoreObjectType; +extern POBJECT_TYPE *TmTransactionManagerObjectType; +extern POBJECT_TYPE *TmResourceManagerObjectType; +extern POBJECT_TYPE *TmEnlistmentObjectType; +extern POBJECT_TYPE *TmTransactionObjectType; +extern POBJECT_TYPE *PsProcessType; +extern POBJECT_TYPE *PsThreadType; +extern POBJECT_TYPE *SeTokenObjectType; +__CREATE_NTOS_DATA_IMPORT_ALIAS(CmKeyObjectType) +__CREATE_NTOS_DATA_IMPORT_ALIAS(IoFileObjectType) +__CREATE_NTOS_DATA_IMPORT_ALIAS(ExEventObjectType) +__CREATE_NTOS_DATA_IMPORT_ALIAS(ExSemaphoreObjectType) +__CREATE_NTOS_DATA_IMPORT_ALIAS(TmTransactionManagerObjectType) +__CREATE_NTOS_DATA_IMPORT_ALIAS(TmResourceManagerObjectType) +__CREATE_NTOS_DATA_IMPORT_ALIAS(TmEnlistmentObjectType) +__CREATE_NTOS_DATA_IMPORT_ALIAS(TmTransactionObjectType) +__CREATE_NTOS_DATA_IMPORT_ALIAS(PsProcessType) +__CREATE_NTOS_DATA_IMPORT_ALIAS(PsThreadType) +__CREATE_NTOS_DATA_IMPORT_ALIAS(SeTokenObjectType) +#endif /****************************************************************************** @@ -8339,7 +8402,7 @@ KeRestoreFloatingPointState(PVOID FloatingState) #define HIGH_LEVEL 15 #define KI_USER_SHARED_DATA ((ULONG_PTR)(KADDRESS_BASE + 0xFFFE0000)) -extern volatile LARGE_INTEGER KeTickCount; +extern NTKERNELAPI volatile LARGE_INTEGER KeTickCount; #define PAUSE_PROCESSOR __yield(); @@ -15770,27 +15833,18 @@ DbgSetDebugPrintCallback( #endif /* !DBG */ -#if defined(__GNUC__) - -extern NTKERNELAPI BOOLEAN KdDebuggerNotPresent; -extern NTKERNELAPI BOOLEAN KdDebuggerEnabled; -#define KD_DEBUGGER_ENABLED KdDebuggerEnabled -#define KD_DEBUGGER_NOT_PRESENT KdDebuggerNotPresent - -#elif defined(_NTDDK_) || defined(_NTIFS_) || defined(_NTHAL_) || defined(_WDMDDK_) || defined(_NTOSP_) - -extern NTKERNELAPI PBOOLEAN KdDebuggerNotPresent; -extern NTKERNELAPI PBOOLEAN KdDebuggerEnabled; -#define KD_DEBUGGER_ENABLED *KdDebuggerEnabled -#define KD_DEBUGGER_NOT_PRESENT *KdDebuggerNotPresent - -#else - -extern BOOLEAN KdDebuggerNotPresent; +#ifdef _NTSYSTEM_ extern BOOLEAN KdDebuggerEnabled; #define KD_DEBUGGER_ENABLED KdDebuggerEnabled +extern BOOLEAN KdDebuggerNotPresent; #define KD_DEBUGGER_NOT_PRESENT KdDebuggerNotPresent - +#else +extern BOOLEAN *KdDebuggerEnabled; +__CREATE_NTOS_DATA_IMPORT_ALIAS(KdDebuggerEnabled) +#define KD_DEBUGGER_ENABLED (*KdDebuggerEnabled) +extern BOOLEAN *KdDebuggerNotPresent; +__CREATE_NTOS_DATA_IMPORT_ALIAS(KdDebuggerNotPresent) +#define KD_DEBUGGER_NOT_PRESENT (*KdDebuggerNotPresent) #endif #if (NTDDI_VERSION >= NTDDI_WIN2K) diff --git a/include/ndk/rtlfuncs.h b/include/ndk/rtlfuncs.h index c0a205c473f..b38a982197a 100644 --- a/include/ndk/rtlfuncs.h +++ b/include/ndk/rtlfuncs.h @@ -3654,7 +3654,7 @@ RtlFindActivationContextSectionString( _In_ ULONG dwFlags, _In_ const GUID *ExtensionGuid, _In_ ULONG SectionType, - _In_ PUNICODE_STRING SectionName, + _In_ const UNICODE_STRING *SectionName, _Inout_ PVOID ReturnedData ); @@ -4419,6 +4419,17 @@ RtlCloneMemoryStream( #endif // NTOS_MODE_USER +NTSYSAPI +NTSTATUS +NTAPI +RtlFindActivationContextSectionGuid( + ULONG flags, + const GUID *extguid, + ULONG section_kind, + const GUID *guid, + void *ptr +); + #ifdef __cplusplus } #endif diff --git a/include/psdk/ks.h b/include/psdk/ks.h index eb5d2f5b2d6..3ae6e9a3f23 100644 --- a/include/psdk/ks.h +++ b/include/psdk/ks.h @@ -3525,7 +3525,7 @@ NTAPI KsMethodHandler( _In_ PIRP Irp, _In_ ULONG MethodSetsCount, - _In_reads_(MethodSetsCount) const PKSMETHOD_SET MethodSet); + _In_reads_(MethodSetsCount) const KSMETHOD_SET* MethodSet); _IRQL_requires_max_(PASSIVE_LEVEL) KSDDKAPI @@ -3534,7 +3534,7 @@ NTAPI KsMethodHandlerWithAllocator( _In_ PIRP Irp, _In_ ULONG MethodSetsCount, - _In_reads_(MethodSetsCount) const PKSMETHOD_SET MethodSet, + _In_reads_(MethodSetsCount) const KSMETHOD_SET* MethodSet, _In_opt_ PFNKSALLOCATOR Allocator, _In_opt_ ULONG MethodItemSize); @@ -3576,7 +3576,7 @@ NTAPI KsPropertyHandlerWithAllocator( _In_ PIRP Irp, _In_ ULONG PropertySetsCount, - _In_reads_(PropertySetsCount) const PKSPROPERTY_SET PropertySet, + _In_reads_(PropertySetsCount) const KSPROPERTY_SET* PropertySet, _In_opt_ PFNKSALLOCATOR Allocator, _In_opt_ ULONG PropertyItemSize); @@ -3659,7 +3659,7 @@ NTAPI KsEnableEventWithAllocator( _In_ PIRP Irp, _In_ ULONG EventSetsCount, - _In_reads_(EventSetsCount) const PKSEVENT_SET EventSet, + _In_reads_(EventSetsCount) const KSEVENT_SET* EventSet, _Inout_opt_ PLIST_ENTRY EventsList, _In_opt_ KSEVENTS_LOCKTYPE EventsFlags, _In_opt_ PVOID EventsLock, @@ -4819,7 +4819,7 @@ DEFINE_GUID(IID_IKsControl, 0x28F54685L, 0x06FD, 0x11D2, 0xB2, 0x7A, 0x00, 0xA0, DECLARE_INTERFACE_(IKsControl,IUnknown) { - STDMETHOD_(NTSTATUS, QueryInterface)( THIS_ + STDMETHOD_(NTSTATUS, QueryInterface)( THIS_ REFIID InterfaceId, PVOID* Interface)PURE; diff --git a/include/reactos/libs/fast486/fast486.h b/include/reactos/libs/fast486/fast486.h new file mode 100644 index 00000000000..339ecb6a77e --- /dev/null +++ b/include/reactos/libs/fast486/fast486.h @@ -0,0 +1,562 @@ +/* + * Fast486 386/486 CPU Emulation Library + * fast486.h + * + * Copyright (C) 2013 Aleksandar Andrejevic + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _FAST486_H_ +#define _FAST486_H_ + +#pragma once + +/* DEFINES ********************************************************************/ + +#ifndef FASTCALL +#define FASTCALL __fastcall +#endif + +#define FAST486_NUM_GEN_REGS 8 +#define FAST486_NUM_SEG_REGS 6 +#define FAST486_NUM_CTRL_REGS 3 +#define FAST486_NUM_DBG_REGS 6 +#define FAST486_NUM_FPU_REGS 8 + +#define FAST486_CR0_PE (1 << 0) +#define FAST486_CR0_MP (1 << 1) +#define FAST486_CR0_EM (1 << 2) +#define FAST486_CR0_TS (1 << 3) +#define FAST486_CR0_ET (1 << 4) +#define FAST486_CR0_NE (1 << 5) +#define FAST486_CR0_WP (1 << 16) +#define FAST486_CR0_AM (1 << 18) +#define FAST486_CR0_NW (1 << 29) +#define FAST486_CR0_CD (1 << 30) +#define FAST486_CR0_PG (1 << 31) + +#define FAST486_DR4_B0 (1 << 0) +#define FAST486_DR4_B1 (1 << 1) +#define FAST486_DR4_B2 (1 << 2) +#define FAST486_DR4_B3 (1 << 3) +#define FAST486_DR4_BD (1 << 13) +#define FAST486_DR4_BS (1 << 14) +#define FAST486_DR4_BT (1 << 15) + +#define FAST486_DR5_L0 (1 << 0) +#define FAST486_DR5_G0 (1 << 1) +#define FAST486_DR5_L1 (1 << 2) +#define FAST486_DR5_G1 (1 << 3) +#define FAST486_DR5_L2 (1 << 4) +#define FAST486_DR5_G2 (1 << 5) +#define FAST486_DR5_L3 (1 << 6) +#define FAST486_DR5_G3 (1 << 7) +#define FAST486_DR5_LE (1 << 8) +#define FAST486_DR5_GE (1 << 9) +#define FAST486_DR5_GD (1 << 13) + +#define FAST486_DBG_BREAK_EXEC 0 +#define FAST486_DBG_BREAK_WRITE 1 +#define FAST486_DBG_BREAK_READWRITE 3 + +#define FAST486_DR4_RESERVED 0xFFFF1FF0 +#define FAST486_DR5_RESERVED 0x0000DC00 + +#define FAST486_IDT_TASK_GATE 0x5 +#define FAST486_IDT_INT_GATE 0x6 +#define FAST486_IDT_TRAP_GATE 0x7 +#define FAST486_IDT_INT_GATE_32 0xE +#define FAST486_IDT_TRAP_GATE_32 0xF + +#define FAST486_LDT_SIGNATURE 0x02 +#define FAST486_TSS_SIGNATURE 0x09 + +#define FAST486_PREFIX_SEG (1 << 0) +#define FAST486_PREFIX_OPSIZE (1 << 1) +#define FAST486_PREFIX_ADSIZE (1 << 2) +#define FAST486_PREFIX_LOCK (1 << 3) +#define FAST486_PREFIX_REPNZ (1 << 4) +#define FAST486_PREFIX_REP (1 << 5) + +struct _FAST486_STATE; +typedef struct _FAST486_STATE FAST486_STATE, *PFAST486_STATE; + +typedef enum _FAST486_GEN_REGS +{ + FAST486_REG_EAX, + FAST486_REG_ECX, + FAST486_REG_EDX, + FAST486_REG_EBX, + FAST486_REG_ESP, + FAST486_REG_EBP, + FAST486_REG_ESI, + FAST486_REG_EDI +} FAST486_GEN_REGS, *PFAST486_GEN_REGS; + +typedef enum _FAST486_SEG_REGS +{ + FAST486_REG_ES, + FAST486_REG_CS, + FAST486_REG_SS, + FAST486_REG_DS, + FAST486_REG_FS, + FAST486_REG_GS +} FAST486_SEG_REGS, *PFAST486_SEG_REGS; + +typedef enum _FAST486_CTRL_REGS +{ + FAST486_REG_CR0 = 0, + FAST486_REG_CR2 = 1, + FAST486_REG_CR3 = 2, +} FAST486_CTRL_REGS, *PFAST486_CTRL_REGS; + +typedef enum _FAST486_DBG_REGS +{ + FAST486_REG_DR0 = 0, + FAST486_REG_DR1 = 1, + FAST486_REG_DR2 = 2, + FAST486_REG_DR3 = 3, + FAST486_REG_DR4 = 4, + FAST486_REG_DR5 = 5, + FAST486_REG_DR6 = 4, // alias to DR4 + FAST486_REG_DR7 = 5 // alias to DR5 +} FAST486_DBG_REGS, *PFAST486_DBG_REGS; + +typedef enum _FAST486_EXCEPTIONS +{ + FAST486_EXCEPTION_DE = 0x00, + FAST486_EXCEPTION_DB = 0x01, + FAST486_EXCEPTION_BP = 0x03, + FAST486_EXCEPTION_OF = 0x04, + FAST486_EXCEPTION_BR = 0x05, + FAST486_EXCEPTION_UD = 0x06, + FAST486_EXCEPTION_NM = 0x07, + FAST486_EXCEPTION_DF = 0x08, + FAST486_EXCEPTION_TS = 0x0A, + FAST486_EXCEPTION_NP = 0x0B, + FAST486_EXCEPTION_SS = 0x0C, + FAST486_EXCEPTION_GP = 0x0D, + FAST486_EXCEPTION_PF = 0x0E, + FAST486_EXCEPTION_MF = 0x10, + FAST486_EXCEPTION_AC = 0x11, + FAST486_EXCEPTION_MC = 0x12 +} FAST486_EXCEPTIONS, *PFAST486_EXCEPTIONS; + +typedef enum _FAST486_INT_STATUS +{ + FAST486_INT_NONE = 0, + FAST486_INT_EXECUTE = 1, + FAST486_INT_SIGNAL = 2 +} FAST486_INT_STATUS, *PFAST486_INT_STATUS; + +typedef +VOID +(NTAPI *FAST486_MEM_READ_PROC) +( + PFAST486_STATE State, + ULONG Address, + PVOID Buffer, + ULONG Size +); + +typedef +VOID +(NTAPI *FAST486_MEM_WRITE_PROC) +( + PFAST486_STATE State, + ULONG Address, + PVOID Buffer, + ULONG Size +); + +typedef +VOID +(NTAPI *FAST486_IO_READ_PROC) +( + PFAST486_STATE State, + ULONG Port, + PVOID Buffer, + ULONG DataCount, + UCHAR DataSize +); + +typedef +VOID +(NTAPI *FAST486_IO_WRITE_PROC) +( + PFAST486_STATE State, + ULONG Port, + PVOID Buffer, + ULONG DataCount, + UCHAR DataSize +); + +typedef +VOID +(NTAPI *FAST486_IDLE_PROC) +( + PFAST486_STATE State +); + +typedef +VOID +(NTAPI *FAST486_BOP_PROC) +( + PFAST486_STATE State, + UCHAR BopCode +); + +typedef +UCHAR +(NTAPI *FAST486_INT_ACK_PROC) +( + PFAST486_STATE State +); + +typedef union _FAST486_REG +{ + union + { + struct + { + UCHAR LowByte; + UCHAR HighByte; + }; + USHORT LowWord; + }; + ULONG Long; +} FAST486_REG, *PFAST486_REG; + +typedef struct _FAST486_SEG_REG +{ + USHORT Selector; + + /* Descriptor cache */ + ULONG Accessed : 1; + ULONG ReadWrite : 1; + ULONG DirConf : 1; + ULONG Executable : 1; + ULONG SystemType : 1; + ULONG Dpl : 2; + ULONG Present : 1; + ULONG Size : 1; + ULONG Limit; + ULONG Base; +} FAST486_SEG_REG, *PFAST486_SEG_REG; + +typedef struct +{ + USHORT Selector; + ULONG Base; + ULONG Limit; +} FAST486_LDT_REG; + +typedef struct +{ + USHORT Selector; + ULONG Base; + ULONG Limit; + BOOLEAN Busy; +} FAST486_TASK_REG, *PFAST486_TASK_REG; + +#pragma pack(push, 1) + +typedef struct +{ + ULONG Limit : 16; + ULONG Base : 16; + ULONG BaseMid : 8; + ULONG Accessed : 1; + ULONG ReadWrite : 1; + ULONG DirConf : 1; + ULONG Executable : 1; + ULONG SystemType : 1; + ULONG Dpl : 2; + ULONG Present : 1; + ULONG LimitHigh : 4; + ULONG Avl : 1; + ULONG Reserved : 1; + ULONG Size : 1; + ULONG Granularity : 1; + ULONG BaseHigh : 8; +} FAST486_GDT_ENTRY, *PFAST486_GDT_ENTRY; + +/* Verify the structure size */ +C_ASSERT(sizeof(FAST486_GDT_ENTRY) == sizeof(ULONGLONG)); + +typedef struct +{ + ULONG Limit : 16; + ULONG Base : 16; + ULONG BaseMid : 8; + ULONG Signature : 5; + ULONG Dpl : 2; + ULONG Present : 1; + ULONG LimitHigh : 4; + ULONG Avl : 1; + ULONG Reserved : 2; + ULONG Granularity : 1; + ULONG BaseHigh : 8; +} FAST486_SYSTEM_DESCRIPTOR, *PFAST486_SYSTEM_DESCRIPTOR; + +/* Verify the structure size */ +C_ASSERT(sizeof(FAST486_SYSTEM_DESCRIPTOR) == sizeof(ULONGLONG)); + +typedef struct +{ + ULONG Offset : 16; + ULONG Selector : 16; + ULONG ParamCount : 5; + ULONG Reserved : 3; + ULONG Type : 4; + ULONG SystemType : 1; + ULONG Dpl : 2; + ULONG Present : 1; + ULONG OffsetHigh : 16; +} FAST486_CALL_GATE, *PFAST486_CALL_GATE; + +/* Verify the structure size */ +C_ASSERT(sizeof(FAST486_CALL_GATE) == sizeof(ULONGLONG)); + +typedef struct +{ + ULONG Offset : 16; + ULONG Selector : 16; + ULONG Zero : 8; + ULONG Type : 4; + ULONG Storage : 1; + ULONG Dpl : 2; + ULONG Present : 1; + ULONG OffsetHigh : 16; +} FAST486_IDT_ENTRY, *PFAST486_IDT_ENTRY; + +/* Verify the structure size */ +C_ASSERT(sizeof(FAST486_IDT_ENTRY) == sizeof(ULONGLONG)); + +#pragma pack(pop) + +typedef struct _FAST486_TABLE_REG +{ + USHORT Size; + ULONG Address; +} FAST486_TABLE_REG, *PFAST486_TABLE_REG; + +typedef union _FAST486_FLAGS_REG +{ + USHORT LowWord; + ULONG Long; + + struct + { + ULONG Cf : 1; + ULONG AlwaysSet : 1; + ULONG Pf : 1; + ULONG Reserved0 : 1; + ULONG Af : 1; + ULONG Reserved1 : 1; + ULONG Zf : 1; + ULONG Sf : 1; + ULONG Tf : 1; + ULONG If : 1; + ULONG Df : 1; + ULONG Of : 1; + ULONG Iopl : 2; + ULONG Nt : 1; + ULONG Reserved2 : 1; + ULONG Rf : 1; + ULONG Vm : 1; + ULONG Ac : 1; + + // ULONG Reserved : 13; + }; +} FAST486_FLAGS_REG, *PFAST486_FLAGS_REG; + +typedef struct _FAST486_TSS +{ + ULONG Link; + ULONG Esp0; + ULONG Ss0; + ULONG Esp1; + ULONG Ss1; + ULONG Esp2; + ULONG Ss2; + ULONG Cr3; + ULONG Eip; + ULONG Eflags; + ULONG Eax; + ULONG Ecx; + ULONG Edx; + ULONG Ebx; + ULONG Esp; + ULONG Ebp; + ULONG Esi; + ULONG Edi; + ULONG Es; + ULONG Cs; + ULONG Ss; + ULONG Ds; + ULONG Fs; + ULONG Gs; + ULONG Ldtr; + ULONG IopbOffset; +} FAST486_TSS, *PFAST486_TSS; + +typedef struct _FAST486_FPU_DATA_REG +{ + ULONGLONG Mantissa; + USHORT Exponent; +} FAST486_FPU_DATA_REG, *PFAST486_FPU_DATA_REG; + +typedef union _FAST486_FPU_STATUS_REG +{ + USHORT Value; + + struct + { + ULONG Ie : 1; + ULONG De : 1; + ULONG Ze : 1; + ULONG Oe : 1; + ULONG Ue : 1; + ULONG Pe : 1; + ULONG Sf : 1; + ULONG Es : 1; + ULONG Code0 : 1; + ULONG Code1 : 1; + ULONG Code2 : 1; + ULONG Top : 3; + ULONG Code3 : 1; + ULONG Busy : 1; + }; +} FAST486_FPU_STATUS_REG, *PFAST486_FPU_STATUS_REG; + +typedef union _FAST486_FPU_CONTROL_REG +{ + USHORT Value; + + struct + { + ULONG Im : 1; + ULONG Dm : 1; + ULONG Zm : 1; + ULONG Om : 1; + ULONG Um : 1; + ULONG Pm : 1; + ULONG Reserved : 2; + ULONG Pc : 2; + ULONG Rc : 2; + ULONG Inf : 1; + // ULONG Reserved1 : 3; + }; +} FAST486_FPU_CONTROL_REG, *PFAST486_FPU_CONTROL_REG; + +struct _FAST486_STATE +{ + FAST486_MEM_READ_PROC MemReadCallback; + FAST486_MEM_WRITE_PROC MemWriteCallback; + FAST486_IO_READ_PROC IoReadCallback; + FAST486_IO_WRITE_PROC IoWriteCallback; + FAST486_IDLE_PROC IdleCallback; + FAST486_BOP_PROC BopCallback; + FAST486_INT_ACK_PROC IntAckCallback; + FAST486_REG GeneralRegs[FAST486_NUM_GEN_REGS]; + FAST486_SEG_REG SegmentRegs[FAST486_NUM_SEG_REGS]; + FAST486_REG InstPtr, SavedInstPtr; + FAST486_FLAGS_REG Flags; + FAST486_TABLE_REG Gdtr, Idtr; + FAST486_LDT_REG Ldtr; + FAST486_TASK_REG TaskReg; + UCHAR Cpl; + ULONG ControlRegisters[FAST486_NUM_CTRL_REGS]; + ULONG DebugRegisters[FAST486_NUM_DBG_REGS]; + ULONG ExceptionCount; + ULONG PrefixFlags; + FAST486_SEG_REGS SegmentOverride; + FAST486_INT_STATUS IntStatus; + UCHAR PendingIntNum; + PULONG Tlb; + FAST486_FPU_DATA_REG FpuRegisters[FAST486_NUM_FPU_REGS]; + FAST486_FPU_STATUS_REG FpuStatus; + FAST486_FPU_CONTROL_REG FpuControl; + USHORT FpuTag; +}; + +/* FUNCTIONS ******************************************************************/ + +VOID +NTAPI +Fast486Initialize(PFAST486_STATE State, + FAST486_MEM_READ_PROC MemReadCallback, + FAST486_MEM_WRITE_PROC MemWriteCallback, + FAST486_IO_READ_PROC IoReadCallback, + FAST486_IO_WRITE_PROC IoWriteCallback, + FAST486_IDLE_PROC IdleCallback, + FAST486_BOP_PROC BopCallback, + FAST486_INT_ACK_PROC IntAckCallback, + PULONG Tlb); + +VOID +NTAPI +Fast486Reset(PFAST486_STATE State); + +VOID +NTAPI +Fast486Continue(PFAST486_STATE State); + +VOID +NTAPI +Fast486StepInto(PFAST486_STATE State); + +VOID +NTAPI +Fast486StepOver(PFAST486_STATE State); + +VOID +NTAPI +Fast486StepOut(PFAST486_STATE State); + +VOID +NTAPI +Fast486DumpState(PFAST486_STATE State); + +VOID +NTAPI +Fast486Interrupt(PFAST486_STATE State, UCHAR Number); + +VOID +NTAPI +Fast486InterruptSignal(PFAST486_STATE State); + +VOID +NTAPI +Fast486ExecuteAt(PFAST486_STATE State, USHORT Segment, ULONG Offset); + +VOID +NTAPI +Fast486SetStack(PFAST486_STATE State, USHORT Segment, ULONG Offset); + +VOID +NTAPI +Fast486SetSegment +( + PFAST486_STATE State, + FAST486_SEG_REGS Segment, + USHORT Selector +); + +#endif // _FAST486_H_ + +/* EOF */ diff --git a/include/reactos/libs/pseh/pseh3.h b/include/reactos/libs/pseh/pseh3.h index 6aa15dd9c15..8337b41522a 100644 --- a/include/reactos/libs/pseh/pseh3.h +++ b/include/reactos/libs/pseh/pseh3.h @@ -120,7 +120,7 @@ void * __cdecl __attribute__((error("Can only be used inside an exception filter #define _SEH3$_EnforceFramePointer() asm volatile ("#\n" : : "m"(*(char*)__builtin_alloca(4)) : "%esp", "memory") /* CLANG doesn't have asm goto! */ -#define _SEH3$_ASM_GOTO(_Label, ...) +#define _SEH3$_ASM_GOTO(...) int __attribute__((regparm(3))) @@ -167,7 +167,7 @@ _SEH3$_RegisterTryLevelWithNonVolatiles( /* This will make GCC use ebp, even if it was disabled by -fomit-frame-pointer */ #define _SEH3$_EnforceFramePointer() asm volatile ("#\n" : : "m"(*(char*)__builtin_alloca(0)) : "%esp", "memory") -#define _SEH3$_ASM_GOTO(_Label, ...) asm goto ("#\n" : : : "memory", ## __VA_ARGS__ : _Label) +#define _SEH3$_ASM_GOTO(...) asm goto ("#\n" : : : "memory" : __VA_ARGS__) #ifdef __cplusplus #define _SEH3$_CALL_WRAPPER(_Function, _TrylevelFrame, _DataTable) \ @@ -177,7 +177,7 @@ _SEH3$_RegisterTryLevelWithNonVolatiles( : \ : "m" (*(_TrylevelFrame)), "m" (*(_DataTable)), "c"(__builtin_alloca(0)) \ : "eax", "edx", "memory" \ - : _SEH3$_l_HandlerTarget, _SEH3$_l_FilterOrFinally) + : _SEH3$_l_BeforeTry, _SEH3$_l_HandlerTarget, _SEH3$_l_OnException, _SEH3$_l_BeforeFilterOrFinally, _SEH3$_l_FilterOrFinally) #else #define _SEH3$_CALL_WRAPPER(_Function, _TrylevelFrame, _DataTable) \ @@ -187,7 +187,7 @@ _SEH3$_RegisterTryLevelWithNonVolatiles( : \ : "m" (*(_TrylevelFrame)), "m" (*(_DataTable)) \ : "eax", "edx", "ecx", "memory" \ - : _SEH3$_l_HandlerTarget) + : _SEH3$_l_BeforeTry, _SEH3$_l_HandlerTarget, _SEH3$_l_OnException, _SEH3$_l_BeforeFilterOrFinally, _SEH3$_l_FilterOrFinally) #endif /* This is an asm wrapper around _SEH3$_RegisterFrame */ @@ -202,10 +202,8 @@ _SEH3$_RegisterTryLevelWithNonVolatiles( around into places that are never executed. */ #define _SEH3$_SCARE_GCC() \ void *plabel; \ - _SEH3$_ASM_GOTO(_SEH3$_l_BeforeTry); \ - _SEH3$_ASM_GOTO(_SEH3$_l_HandlerTarget); \ - _SEH3$_ASM_GOTO(_SEH3$_l_OnException); \ - asm volatile ("#" : "=a"(plabel) : "p"(&&_SEH3$_l_BeforeTry), "p"(&&_SEH3$_l_HandlerTarget), "p"(&&_SEH3$_l_OnException) \ + _SEH3$_ASM_GOTO(_SEH3$_l_BeforeTry, _SEH3$_l_HandlerTarget, _SEH3$_l_OnException, _SEH3$_l_BeforeFilterOrFinally, _SEH3$_l_FilterOrFinally); \ + asm volatile ("#" : "=a"(plabel) : "p"(&&_SEH3$_l_BeforeTry), "p"(&&_SEH3$_l_HandlerTarget), "p"(&&_SEH3$_l_OnException), "p"(&&_SEH3$_l_FilterOrFinally) \ : "ebx", "ecx", "edx", "esi", "edi", "flags", "memory" ); \ goto _SEH3$_l_OnException; diff --git a/include/reactos/subsys/win/vdm.h b/include/reactos/subsys/win/vdm.h new file mode 100644 index 00000000000..e493dcdc009 --- /dev/null +++ b/include/reactos/subsys/win/vdm.h @@ -0,0 +1,117 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Base API Server DLL + * FILE: include/reactos/subsys/win/vdm.h + * PURPOSE: Public definitions for the Virtual Dos Machine + * PROGRAMMERS: Aleksandar Andrejevic + * Alex Ionescu (alex.ionescu@reactos.org) + */ + +#ifndef _VDM_H +#define _VDM_H + +#pragma once + +/* CONSTANTS & TYPES **********************************************************/ + +typedef enum _VDM_ENTRY_CODE +{ + VdmEntryUndo, + VdmEntryUpdateProcess, + VdmEntryUpdateControlCHandler +} VDM_ENTRY_CODE; + +// +// Undo States +// +#define VDM_UNDO_PARTIAL 0x01 +#define VDM_UNDO_FULL 0x02 +#define VDM_UNDO_REUSE 0x04 +#define VDM_UNDO_COMPLETED 0x08 + +// +// Binary Types to share with VDM +// +#define BINARY_TYPE_EXE 0x01 +#define BINARY_TYPE_COM 0x02 +#define BINARY_TYPE_PIF 0x03 +#define BINARY_TYPE_DOS 0x10 +#define BINARY_TYPE_SEPARATE_WOW 0x20 +#define BINARY_TYPE_WOW 0x40 +#define BINARY_TYPE_WOW_EX 0x80 + +// +// VDM States +// +#define VDM_NOT_LOADED 0x01 +#define VDM_NOT_READY 0x02 +#define VDM_READY 0x04 + +// +// VDM Flags +// +#define VDM_FLAG_FIRST_TASK 0x01 +#define VDM_FLAG_WOW 0x02 +#define VDM_FLAG_DOS 0x04 +#define VDM_FLAG_RETRY 0x08 +#define VDM_INC_REENTER_COUNT 0x10 +#define VDM_DEC_REENTER_COUNT 0x20 +#define VDM_FLAG_NESTED_TASK 0x40 +#define VDM_FLAG_DONT_WAIT 0x80 +#define VDM_GET_FIRST_COMMAND 0x100 +#define VDM_GET_ENVIRONMENT 0x400 +#define VDM_FLAG_SEPARATE_WOW 0x800 +#define VDM_LIST_WOW_PROCESSES 0x1000 +#define VDM_LIST_WOW_TASKS 0x4000 +#define VDM_ADD_WOW_TASK 0x8000 + +typedef struct +{ + ULONG TaskId; + ULONG CreationFlags; + ULONG ExitCode; + ULONG CodePage; + HANDLE StdIn; + HANDLE StdOut; + HANDLE StdErr; + LPSTR CmdLine; + LPSTR AppName; + LPSTR PifFile; + LPSTR CurDirectory; + LPSTR Env; + ULONG EnvLen; + STARTUPINFOA StartupInfo; + LPSTR Desktop; + ULONG DesktopLen; + LPSTR Title; + ULONG TitleLen; + LPVOID Reserved; + ULONG ReservedLen; + USHORT CmdLen; + USHORT AppLen; + USHORT PifLen; + USHORT CurDirectoryLen; + USHORT VDMState; + USHORT CurrentDrive; + BOOLEAN ComingFromBat; +} VDM_COMMAND_INFO, *PVDM_COMMAND_INFO; + + +/* FUNCTION PROTOTYPES ********************************************************/ + +BOOL +WINAPI +GetNextVDMCommand( + IN OUT PVDM_COMMAND_INFO CommandData OPTIONAL +); + +VOID +WINAPI +ExitVDM( + IN BOOL IsWow, + IN ULONG iWowTask +); + +#endif // _VDM_H + +/* EOF */ diff --git a/include/reactos/wine/port.h b/include/reactos/wine/port.h index 7b42643de67..30d8e9e41b8 100644 --- a/include/reactos/wine/port.h +++ b/include/reactos/wine/port.h @@ -278,7 +278,7 @@ ssize_t pwrite( int fd, const void *buf, size_t count, off_t offset ); #endif /* HAVE_PWRITE */ #endif /* __REACTOS__ */ -#ifdef WIN32 +#ifdef _WIN32 #ifndef HAVE_SIGSETJMP # include typedef jmp_buf sigjmp_buf; @@ -343,9 +343,9 @@ extern int spawnvp(int mode, const char *cmdname, const char * const argv[]); #if defined(_MSC_VER) || (defined(__i386__) && defined(__GNUC__) && !defined(WINE_PORT_NO_INTERLOCKED)) #define interlocked_cmpxchg InterlockedCompareExchange -#define interlocked_cmpxchg_ptr InterlockedCompareExchangePtr +#define interlocked_cmpxchg_ptr InterlockedCompareExchangePointer #define interlocked_xchg InterlockedExchange -#define interlocked_xchg_ptr InterlockedExchangePtr +#define interlocked_xchg_ptr InterlockedExchangePointer #define interlocked_xchg_add InterlockedExchangeAdd diff --git a/include/xdk/ccfuncs.h b/include/xdk/ccfuncs.h index 9192381f5f4..5e998d89ed3 100644 --- a/include/xdk/ccfuncs.h +++ b/include/xdk/ccfuncs.h @@ -6,7 +6,7 @@ $if (_NTIFS_) (((PSECTION_OBJECT_POINTERS)(FO)->SectionObjectPointer)->SharedCacheMap != NULL) \ ) -extern ULONG CcFastMdlReadWait; +extern NTKERNELAPI ULONG CcFastMdlReadWait; #if (NTDDI_VERSION >= NTDDI_WIN2K) diff --git a/include/xdk/extypes.h b/include/xdk/extypes.h index ae252d375ed..548dceee203 100644 --- a/include/xdk/extypes.h +++ b/include/xdk/extypes.h @@ -271,7 +271,7 @@ typedef struct _RESOURCE_PERFORMANCE_DATA { /* Global debug flag */ #if DEVL -extern ULONG NtGlobalFlag; +extern NTKERNELAPI ULONG NtGlobalFlag; #define IF_NTOS_DEBUG(FlagName) if (NtGlobalFlag & (FLG_##FlagName)) #else #define IF_NTOS_DEBUG(FlagName) if(FALSE) diff --git a/include/xdk/fsrtlfuncs.h b/include/xdk/fsrtlfuncs.h index b98897c0bb8..24465b8e2ea 100644 --- a/include/xdk/fsrtlfuncs.h +++ b/include/xdk/fsrtlfuncs.h @@ -1580,26 +1580,31 @@ FsRtlRemovePerFileObjectContext( (InterlockedDecrement((LONG volatile *)&((FL)->LockRequestsInProgress)));\ } -/* GCC compatible definition, MS one is retarded */ -extern NTKERNELAPI const UCHAR * const FsRtlLegalAnsiCharacterArray; -#define LEGAL_ANSI_CHARACTER_ARRAY FsRtlLegalAnsiCharacterArray +#ifdef _NTSYSTEM_ +extern const UCHAR * const FsRtlLegalAnsiCharacterArray; +#define LEGAL_ANSI_CHARACTER_ARRAY FsRtlLegalAnsiCharacterArray +#else +extern const UCHAR * const *FsRtlLegalAnsiCharacterArray; +__CREATE_NTOS_DATA_IMPORT_ALIAS(FsRtlLegalAnsiCharacterArray) +#define LEGAL_ANSI_CHARACTER_ARRAY (*FsRtlLegalAnsiCharacterArray) +#endif #define FsRtlIsAnsiCharacterWild(C) ( \ - FlagOn(FsRtlLegalAnsiCharacterArray[(UCHAR)(C)], FSRTL_WILD_CHARACTER ) \ + FlagOn(LEGAL_ANSI_CHARACTER_ARRAY[(UCHAR)(C)], FSRTL_WILD_CHARACTER ) \ ) #define FsRtlIsAnsiCharacterLegalFat(C, WILD) ( \ - FlagOn(FsRtlLegalAnsiCharacterArray[(UCHAR)(C)], (FSRTL_FAT_LEGAL) | \ + FlagOn(LEGAL_ANSI_CHARACTER_ARRAY[(UCHAR)(C)], (FSRTL_FAT_LEGAL) | \ ((WILD) ? FSRTL_WILD_CHARACTER : 0 )) \ ) #define FsRtlIsAnsiCharacterLegalHpfs(C, WILD) ( \ - FlagOn(FsRtlLegalAnsiCharacterArray[(UCHAR)(C)], (FSRTL_HPFS_LEGAL) | \ + FlagOn(LEGAL_ANSI_CHARACTER_ARRAY[(UCHAR)(C)], (FSRTL_HPFS_LEGAL) | \ ((WILD) ? FSRTL_WILD_CHARACTER : 0 )) \ ) #define FsRtlIsAnsiCharacterLegalNtfs(C, WILD) ( \ - FlagOn(FsRtlLegalAnsiCharacterArray[(UCHAR)(C)], (FSRTL_NTFS_LEGAL) | \ + FlagOn(LEGAL_ANSI_CHARACTER_ARRAY[(UCHAR)(C)], (FSRTL_NTFS_LEGAL) | \ ((WILD) ? FSRTL_WILD_CHARACTER : 0 )) \ ) @@ -1627,7 +1632,7 @@ extern NTKERNELAPI const UCHAR * const FsRtlLegalAnsiCharacterArray; #define FsRtlIsUnicodeCharacterWild(C) ( \ (((C) >= 0x40) ? \ FALSE : \ - FlagOn(FsRtlLegalAnsiCharacterArray[(C)], FSRTL_WILD_CHARACTER )) \ + FlagOn(LEGAL_ANSI_CHARACTER_ARRAY[(C)], FSRTL_WILD_CHARACTER )) \ ) #define FsRtlInitPerFileContext( _fc, _owner, _inst, _cb) \ diff --git a/include/xdk/haltypes.h b/include/xdk/haltypes.h index 941daef32be..db308060e03 100644 --- a/include/xdk/haltypes.h +++ b/include/xdk/haltypes.h @@ -269,14 +269,12 @@ typedef struct { #endif } HAL_DISPATCH, *PHAL_DISPATCH; -/* GCC/MSVC and WDK compatible declaration */ -extern NTKERNELAPI HAL_DISPATCH HalDispatchTable; - -#if defined(_NTOSKRNL_) || defined(_BLDR_) +#ifdef _NTSYSTEM_ +extern HAL_DISPATCH HalDispatchTable; #define HALDISPATCH (&HalDispatchTable) #else -/* This is a WDK compatibility definition */ -#define HalDispatchTable (&HalDispatchTable) +extern PHAL_DISPATCH HalDispatchTable; +__CREATE_NTOS_DATA_IMPORT_ALIAS(HalDispatchTable) #define HALDISPATCH HalDispatchTable #endif diff --git a/include/xdk/ia64/ke.h b/include/xdk/ia64/ke.h index 2920636bf54..27ff06ad3f0 100644 --- a/include/xdk/ia64/ke.h +++ b/include/xdk/ia64/ke.h @@ -17,7 +17,7 @@ $if (_WDMDDK_) #define HIGH_LEVEL 15 #define KI_USER_SHARED_DATA ((ULONG_PTR)(KADDRESS_BASE + 0xFFFE0000)) -extern volatile LARGE_INTEGER KeTickCount; +extern NTKERNELAPI volatile LARGE_INTEGER KeTickCount; #define PAUSE_PROCESSOR __yield(); diff --git a/include/xdk/iotypes.h b/include/xdk/iotypes.h index 4b375154977..41954a5a121 100644 --- a/include/xdk/iotypes.h +++ b/include/xdk/iotypes.h @@ -7037,35 +7037,13 @@ FsRtlNotifyStreamFileObject( _In_ BOOLEAN SafeToRecurse); #endif /* (NTDDI_VERSION >= NTDDI_VISTA) */ -#define DO_VERIFY_VOLUME 0x00000002 -#define DO_BUFFERED_IO 0x00000004 -#define DO_EXCLUSIVE 0x00000008 -#define DO_DIRECT_IO 0x00000010 -#define DO_MAP_IO_BUFFER 0x00000020 -#define DO_DEVICE_HAS_NAME 0x00000040 -#define DO_DEVICE_INITIALIZING 0x00000080 -#define DO_SYSTEM_BOOT_PARTITION 0x00000100 -#define DO_LONG_TERM_REQUESTS 0x00000200 -#define DO_NEVER_LAST_DEVICE 0x00000400 -#define DO_SHUTDOWN_REGISTERED 0x00000800 -#define DO_BUS_ENUMERATED_DEVICE 0x00001000 -#define DO_POWER_PAGABLE 0x00002000 -#define DO_POWER_INRUSH 0x00004000 -#define DO_LOW_PRIORITY_FILESYSTEM 0x00010000 -#define DO_SUPPORTS_TRANSACTIONS 0x00040000 -#define DO_FORCE_NEITHER_IO 0x00080000 -#define DO_VOLUME_DEVICE_OBJECT 0x00100000 -#define DO_SYSTEM_SYSTEM_PARTITION 0x00200000 -#define DO_SYSTEM_CRITICAL_PARTITION 0x00400000 -#define DO_DISALLOW_EXECUTE 0x00800000 - -extern KSPIN_LOCK IoStatisticsLock; -extern ULONG IoReadOperationCount; -extern ULONG IoWriteOperationCount; -extern ULONG IoOtherOperationCount; -extern LARGE_INTEGER IoReadTransferCount; -extern LARGE_INTEGER IoWriteTransferCount; -extern LARGE_INTEGER IoOtherTransferCount; +extern NTKERNELAPI KSPIN_LOCK IoStatisticsLock; +extern NTKERNELAPI ULONG IoReadOperationCount; +extern NTKERNELAPI ULONG IoWriteOperationCount; +extern NTKERNELAPI ULONG IoOtherOperationCount; +extern NTKERNELAPI LARGE_INTEGER IoReadTransferCount; +extern NTKERNELAPI LARGE_INTEGER IoWriteTransferCount; +extern NTKERNELAPI LARGE_INTEGER IoOtherTransferCount; #define IO_FILE_OBJECT_NON_PAGED_POOL_CHARGE 64 #define IO_FILE_OBJECT_PAGED_POOL_CHARGE 1024 diff --git a/include/xdk/kdfuncs.h b/include/xdk/kdfuncs.h index e05c86500d8..b5e908ba35a 100644 --- a/include/xdk/kdfuncs.h +++ b/include/xdk/kdfuncs.h @@ -119,27 +119,18 @@ DbgSetDebugPrintCallback( #endif /* !DBG */ -#if defined(__GNUC__) - -extern NTKERNELAPI BOOLEAN KdDebuggerNotPresent; -extern NTKERNELAPI BOOLEAN KdDebuggerEnabled; -#define KD_DEBUGGER_ENABLED KdDebuggerEnabled -#define KD_DEBUGGER_NOT_PRESENT KdDebuggerNotPresent - -#elif defined(_NTDDK_) || defined(_NTIFS_) || defined(_NTHAL_) || defined(_WDMDDK_) || defined(_NTOSP_) - -extern NTKERNELAPI PBOOLEAN KdDebuggerNotPresent; -extern NTKERNELAPI PBOOLEAN KdDebuggerEnabled; -#define KD_DEBUGGER_ENABLED *KdDebuggerEnabled -#define KD_DEBUGGER_NOT_PRESENT *KdDebuggerNotPresent - -#else - -extern BOOLEAN KdDebuggerNotPresent; +#ifdef _NTSYSTEM_ extern BOOLEAN KdDebuggerEnabled; #define KD_DEBUGGER_ENABLED KdDebuggerEnabled +extern BOOLEAN KdDebuggerNotPresent; #define KD_DEBUGGER_NOT_PRESENT KdDebuggerNotPresent - +#else +extern BOOLEAN *KdDebuggerEnabled; +__CREATE_NTOS_DATA_IMPORT_ALIAS(KdDebuggerEnabled) +#define KD_DEBUGGER_ENABLED (*KdDebuggerEnabled) +extern BOOLEAN *KdDebuggerNotPresent; +__CREATE_NTOS_DATA_IMPORT_ALIAS(KdDebuggerNotPresent) +#define KD_DEBUGGER_NOT_PRESENT (*KdDebuggerNotPresent) #endif #if (NTDDI_VERSION >= NTDDI_WIN2K) diff --git a/include/xdk/ketypes.h b/include/xdk/ketypes.h index 1ef6473ba2e..7b14d0ae09b 100644 --- a/include/xdk/ketypes.h +++ b/include/xdk/ketypes.h @@ -987,6 +987,7 @@ extern NTSYSAPI volatile CCHAR KeNumberProcessors; extern NTSYSAPI CCHAR KeNumberProcessors; #else extern PCCHAR KeNumberProcessors; +__CREATE_NTOS_DATA_IMPORT_ALIAS(KeNumberProcessors) #endif $endif (_WDMDDK_) diff --git a/include/xdk/mmtypes.h b/include/xdk/mmtypes.h index 2b98aeef5ae..ae665cca59a 100644 --- a/include/xdk/mmtypes.h +++ b/include/xdk/mmtypes.h @@ -147,8 +147,11 @@ typedef enum _MM_SYSTEM_SIZE { MmLargeSystem } MM_SYSTEMSIZE; -extern NTKERNELAPI BOOLEAN Mm64BitPhysicalAddress; -extern PVOID MmBadPointer; +#ifndef _NTSYSTEM_ +extern PBOOLEAN Mm64BitPhysicalAddress; +__CREATE_NTOS_DATA_IMPORT_ALIAS(Mm64BitPhysicalAddress) +#endif +extern NTKERNELAPI PVOID MmBadPointer; $endif (_WDMDDK_) $if (_NTDDK_) diff --git a/include/xdk/ntifs.template.h b/include/xdk/ntifs.template.h index dfff253e59e..68957892ec6 100644 --- a/include/xdk/ntifs.template.h +++ b/include/xdk/ntifs.template.h @@ -1124,13 +1124,14 @@ HalGetDmaAlignmentRequirement( #define HalGetDmaAlignmentRequirement() 1L #endif -extern NTKERNELAPI PUSHORT NlsOemLeadByteInfo; -#define NLS_OEM_LEAD_BYTE_INFO NlsOemLeadByteInfo - -#ifdef NLS_MB_CODE_PAGE_TAG -#undef NLS_MB_CODE_PAGE_TAG +#ifdef _NTSYSTEM_ +extern PUSHORT NlsOemLeadByteInfo; +#define NLS_OEM_LEAD_BYTE_INFO NlsOemLeadByteInfo +#else +extern PUSHORT *NlsOemLeadByteInfo; +__CREATE_NTOS_DATA_IMPORT_ALIAS(NlsOemLeadByteInfo) +#define NLS_OEM_LEAD_BYTE_INFO (*NlsOemLeadByteInfo) #endif -#define NLS_MB_CODE_PAGE_TAG NlsMbOemCodePageTag #if (NTDDI_VERSION >= NTDDI_VISTA) diff --git a/include/xdk/obtypes.h b/include/xdk/obtypes.h index 7063ab1d1e3..482ab193979 100644 --- a/include/xdk/obtypes.h +++ b/include/xdk/obtypes.h @@ -125,6 +125,7 @@ typedef struct _OBJECT_NAME_INFORMATION { } OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION; /* Exported object types */ +#ifdef _NTSYSTEM_ extern POBJECT_TYPE NTSYSAPI CmKeyObjectType; extern POBJECT_TYPE NTSYSAPI ExEventObjectType; extern POBJECT_TYPE NTSYSAPI ExSemaphoreObjectType; @@ -132,6 +133,30 @@ extern POBJECT_TYPE NTSYSAPI IoFileObjectType; extern POBJECT_TYPE NTSYSAPI PsThreadType; extern POBJECT_TYPE NTSYSAPI SeTokenObjectType; extern POBJECT_TYPE NTSYSAPI PsProcessType; +#else +extern POBJECT_TYPE *CmKeyObjectType; +extern POBJECT_TYPE *IoFileObjectType; +extern POBJECT_TYPE *ExEventObjectType; +extern POBJECT_TYPE *ExSemaphoreObjectType; +extern POBJECT_TYPE *TmTransactionManagerObjectType; +extern POBJECT_TYPE *TmResourceManagerObjectType; +extern POBJECT_TYPE *TmEnlistmentObjectType; +extern POBJECT_TYPE *TmTransactionObjectType; +extern POBJECT_TYPE *PsProcessType; +extern POBJECT_TYPE *PsThreadType; +extern POBJECT_TYPE *SeTokenObjectType; +__CREATE_NTOS_DATA_IMPORT_ALIAS(CmKeyObjectType) +__CREATE_NTOS_DATA_IMPORT_ALIAS(IoFileObjectType) +__CREATE_NTOS_DATA_IMPORT_ALIAS(ExEventObjectType) +__CREATE_NTOS_DATA_IMPORT_ALIAS(ExSemaphoreObjectType) +__CREATE_NTOS_DATA_IMPORT_ALIAS(TmTransactionManagerObjectType) +__CREATE_NTOS_DATA_IMPORT_ALIAS(TmResourceManagerObjectType) +__CREATE_NTOS_DATA_IMPORT_ALIAS(TmEnlistmentObjectType) +__CREATE_NTOS_DATA_IMPORT_ALIAS(TmTransactionObjectType) +__CREATE_NTOS_DATA_IMPORT_ALIAS(PsProcessType) +__CREATE_NTOS_DATA_IMPORT_ALIAS(PsThreadType) +__CREATE_NTOS_DATA_IMPORT_ALIAS(SeTokenObjectType) +#endif $endif (_WDMDDK_) $if (_NTIFS_) diff --git a/include/xdk/rtltypes.h b/include/xdk/rtltypes.h index 0b61c724921..fef0604c5e0 100644 --- a/include/xdk/rtltypes.h +++ b/include/xdk/rtltypes.h @@ -197,11 +197,19 @@ typedef struct _EXCEPTION_POINTERS { PCONTEXT ContextRecord; } EXCEPTION_POINTERS, *PEXCEPTION_POINTERS; -/* MS definition is broken! */ -extern BOOLEAN NTSYSAPI NlsMbCodePageTag; -extern BOOLEAN NTSYSAPI NlsMbOemCodePageTag; +#ifdef _NTSYSTEM_ +extern BOOLEAN NlsMbCodePageTag; #define NLS_MB_CODE_PAGE_TAG NlsMbCodePageTag +extern BOOLEAN NlsMbOemCodePageTag; #define NLS_MB_OEM_CODE_PAGE_TAG NlsMbOemCodePageTag +#else +extern BOOLEAN *NlsMbCodePageTag; +__CREATE_NTOS_DATA_IMPORT_ALIAS(NlsMbCodePageTag) +#define NLS_MB_CODE_PAGE_TAG (*NlsMbCodePageTag) +extern BOOLEAN *NlsMbOemCodePageTag; +__CREATE_NTOS_DATA_IMPORT_ALIAS(NlsMbOemCodePageTag) +#define NLS_MB_OEM_CODE_PAGE_TAG (*NlsMbOemCodePageTag) +#endif #define SHORT_LEAST_SIGNIFICANT_BIT 0 #define SHORT_MOST_SIGNIFICANT_BIT 1 diff --git a/include/xdk/sefuncs.h b/include/xdk/sefuncs.h index 44e5fedfa9e..c7e27666159 100644 --- a/include/xdk/sefuncs.h +++ b/include/xdk/sefuncs.h @@ -588,4 +588,5 @@ SeLocateProcessImageName( ((PSECURITY_SUBJECT_CONTEXT) SubjectContext)->PrimaryToken ) extern NTKERNELAPI PSE_EXPORTS SeExports; + $endif (_NTIFS_) diff --git a/include/xdk/wdm.template.h b/include/xdk/wdm.template.h index fa472156785..e525303877b 100644 --- a/include/xdk/wdm.template.h +++ b/include/xdk/wdm.template.h @@ -82,10 +82,13 @@ extern "C" { #endif /* For ReactOS */ -#if !defined(_NTOSKRNL_) && !defined(_BLDR_) +#if !defined(_NTOSKRNL_) && !defined(_BLDR_) && !defined(_NTSYSTEM_) #define NTKERNELAPI DECLSPEC_IMPORT #else #define NTKERNELAPI +#ifndef _NTSYSTEM_ +#define _NTSYSTEM_ +#endif #endif #if defined(_X86_) && !defined(_NTHAL_) @@ -129,6 +132,29 @@ extern "C" { #define ALLOC_DATA_PRAGMA 1 #endif +#endif /* _MSC_VER */ + +/* These macros are used to create aliases for imported data. We need to do + this to have declarations that are compatible with MS DDK */ +#ifdef _M_IX86 +#define __SYMBOL(_Name) "_"#_Name +#define __IMPORTSYMBOL(_Name) "__imp__"#_Name +#define __IMPORTNAME(_Name) _imp__##_Name +#else +#define __SYMBOL(_Name) #_Name +#define __IMPORTSYMBOL(_Name) "__imp_"#_Name +#define __IMPORTNAME(_Name) __imp_##_Name +#endif +#ifdef _MSC_VER +#define __CREATE_NTOS_DATA_IMPORT_ALIAS(_Name) \ + __pragma(comment(linker, "/alternatename:"__SYMBOL(_Name) "=" __IMPORTSYMBOL(_Name))) +#else /* !_MSC_VER */ +#ifndef __STRINGIFY +#define __STRINGIFY(_exp) #_exp +#endif +#define _Pragma_redefine_extname(_Name, _Target) _Pragma(__STRINGIFY(redefine_extname _Name _Target)) +#define __CREATE_NTOS_DATA_IMPORT_ALIAS(_Name) \ + _Pragma_redefine_extname(_Name,__IMPORTNAME(_Name)) #endif #if defined(_WIN64) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 8918d671094..a030ad192e9 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -11,6 +11,7 @@ add_subdirectory(cryptlib) #add_subdirectory(dnslib) Nothing links to this lib. add_subdirectory(drivers) add_subdirectory(epsapi) +add_subdirectory(fast486) add_subdirectory(fslib) add_subdirectory(lsalib) add_subdirectory(ppcmmu) diff --git a/lib/fast486/CMakeLists.txt b/lib/fast486/CMakeLists.txt new file mode 100644 index 00000000000..2fbdb31586f --- /dev/null +++ b/lib/fast486/CMakeLists.txt @@ -0,0 +1,12 @@ + +include_directories(${REACTOS_SOURCE_DIR}/include/reactos/libs/fast486) + +list(APPEND SOURCE + fast486.c + opcodes.c + opgroups.c + extraops.c + common.c + fpu.c) + +add_library(fast486 ${SOURCE}) diff --git a/lib/fast486/COPYING b/lib/fast486/COPYING new file mode 100644 index 00000000000..d159169d105 --- /dev/null +++ b/lib/fast486/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 2 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/lib/fast486/common.c b/lib/fast486/common.c new file mode 100644 index 00000000000..36f026ec331 --- /dev/null +++ b/lib/fast486/common.c @@ -0,0 +1,356 @@ +/* + * Fast486 386/486 CPU Emulation Library + * common.c + * + * Copyright (C) 2013 Aleksandar Andrejevic + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* INCLUDES *******************************************************************/ + +#include + +// #define NDEBUG +#include + +#include +#include "common.h" + +/* PUBLIC FUNCTIONS ***********************************************************/ + +BOOLEAN +Fast486ReadMemory(PFAST486_STATE State, + FAST486_SEG_REGS SegmentReg, + ULONG Offset, + BOOLEAN InstFetch, + PVOID Buffer, + ULONG Size) +{ + ULONG LinearAddress; + PFAST486_SEG_REG CachedDescriptor; + + ASSERT(SegmentReg < FAST486_NUM_SEG_REGS); + + /* Get the cached descriptor */ + CachedDescriptor = &State->SegmentRegs[SegmentReg]; + + if ((Offset + Size - 1) > CachedDescriptor->Limit) + { + /* Read beyond limit */ + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + + /* Check for protected mode */ + if (State->ControlRegisters[0] & FAST486_CR0_PE) + { + /* Privilege checks */ + + if (!CachedDescriptor->Present) + { + Fast486Exception(State, FAST486_EXCEPTION_NP); + return FALSE; + } + + if ((!InstFetch && (GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl)) + || (Fast486GetCurrentPrivLevel(State) > CachedDescriptor->Dpl)) + { + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + + if (InstFetch) + { + if (!CachedDescriptor->Executable) + { + /* Data segment not executable */ + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + } + else + { + if (CachedDescriptor->Executable && (!CachedDescriptor->ReadWrite)) + { + /* Code segment not readable */ + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + } + } + + /* Find the linear address */ + LinearAddress = CachedDescriptor->Base + Offset; + + /* Read from the linear address */ + return Fast486ReadLinearMemory(State, LinearAddress, Buffer, Size); +} + +BOOLEAN +Fast486WriteMemory(PFAST486_STATE State, + FAST486_SEG_REGS SegmentReg, + ULONG Offset, + PVOID Buffer, + ULONG Size) +{ + ULONG LinearAddress; + PFAST486_SEG_REG CachedDescriptor; + + ASSERT(SegmentReg < FAST486_NUM_SEG_REGS); + + /* Get the cached descriptor */ + CachedDescriptor = &State->SegmentRegs[SegmentReg]; + + if ((Offset + Size - 1) > CachedDescriptor->Limit) + { + /* Write beyond limit */ + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + + /* Check for protected mode */ + if (State->ControlRegisters[0] & FAST486_CR0_PE) + { + /* Privilege checks */ + + if (!CachedDescriptor->Present) + { + Fast486Exception(State, FAST486_EXCEPTION_NP); + return FALSE; + } + + if ((GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl) + || (Fast486GetCurrentPrivLevel(State) > CachedDescriptor->Dpl)) + { + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + + if (CachedDescriptor->Executable) + { + /* Code segment not writable */ + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + else if (!CachedDescriptor->ReadWrite) + { + /* Data segment not writeable */ + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + } + + /* Find the linear address */ + LinearAddress = CachedDescriptor->Base + Offset; + + /* Write to the linear address */ + return Fast486WriteLinearMemory(State, LinearAddress, Buffer, Size); +} + +BOOLEAN +Fast486InterruptInternal(PFAST486_STATE State, + USHORT SegmentSelector, + ULONG Offset, + BOOLEAN InterruptGate) +{ + /* Check for protected mode */ + if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) + { + FAST486_TSS Tss; + USHORT OldSs = State->SegmentRegs[FAST486_REG_SS].Selector; + ULONG OldEsp = State->GeneralRegs[FAST486_REG_ESP].Long; + + /* Check if the interrupt handler is more privileged */ + if (Fast486GetCurrentPrivLevel(State) > GET_SEGMENT_RPL(SegmentSelector)) + { + /* Read the TSS */ + if (!Fast486ReadLinearMemory(State, + State->TaskReg.Base, + &Tss, + sizeof(Tss))) + { + /* Exception occurred */ + return FALSE; + } + + /* Check the new (higher) privilege level */ + switch (GET_SEGMENT_RPL(SegmentSelector)) + { + case 0: + { + if (!Fast486LoadSegment(State, FAST486_REG_SS, Tss.Ss0)) + { + /* Exception occurred */ + return FALSE; + } + State->GeneralRegs[FAST486_REG_ESP].Long = Tss.Esp0; + + break; + } + + case 1: + { + if (!Fast486LoadSegment(State, FAST486_REG_SS, Tss.Ss1)) + { + /* Exception occurred */ + return FALSE; + } + State->GeneralRegs[FAST486_REG_ESP].Long = Tss.Esp1; + + break; + } + + case 2: + { + if (!Fast486LoadSegment(State, FAST486_REG_SS, Tss.Ss2)) + { + /* Exception occurred */ + return FALSE; + } + State->GeneralRegs[FAST486_REG_ESP].Long = Tss.Esp2; + + break; + } + + default: + { + /* Should never reach here! */ + ASSERT(FALSE); + } + } + + /* Push SS selector */ + if (!Fast486StackPush(State, OldSs)) return FALSE; + + /* Push stack pointer */ + if (!Fast486StackPush(State, OldEsp)) return FALSE; + } + } + else + { + if (State->SegmentRegs[FAST486_REG_CS].Size) + { + /* Set OPSIZE, because INT always pushes 16-bit values in real mode */ + State->PrefixFlags |= FAST486_PREFIX_OPSIZE; + } + } + + /* Push EFLAGS */ + if (!Fast486StackPush(State, State->Flags.Long)) return FALSE; + + /* Push CS selector */ + if (!Fast486StackPush(State, State->SegmentRegs[FAST486_REG_CS].Selector)) return FALSE; + + /* Push the instruction pointer */ + if (!Fast486StackPush(State, State->InstPtr.Long)) return FALSE; + + if (InterruptGate) + { + /* Disable interrupts after a jump to an interrupt gate handler */ + State->Flags.If = FALSE; + } + + /* Load new CS */ + if (!Fast486LoadSegment(State, FAST486_REG_CS, SegmentSelector)) + { + /* An exception occurred during the jump */ + return FALSE; + } + + if (State->SegmentRegs[FAST486_REG_CS].Size) + { + /* 32-bit code segment, use EIP */ + State->InstPtr.Long = Offset; + } + else + { + /* 16-bit code segment, use IP */ + State->InstPtr.LowWord = LOWORD(Offset); + } + + return TRUE; +} + +VOID +FASTCALL +Fast486ExceptionWithErrorCode(PFAST486_STATE State, + FAST486_EXCEPTIONS ExceptionCode, + ULONG ErrorCode) +{ + FAST486_IDT_ENTRY IdtEntry; + + /* Increment the exception count */ + State->ExceptionCount++; + + /* Check if the exception occurred more than once */ + if (State->ExceptionCount > 1) + { + /* Then this is a double fault */ + ExceptionCode = FAST486_EXCEPTION_DF; + } + + /* Check if this is a triple fault */ + if (State->ExceptionCount == 3) + { + /* Reset the CPU */ + Fast486Reset(State); + return; + } + + /* Restore the IP to the saved IP */ + State->InstPtr = State->SavedInstPtr; + + if (!Fast486GetIntVector(State, ExceptionCode, &IdtEntry)) + { + /* + * If this function failed, that means Fast486Exception + * was called again, so just return in this case. + */ + return; + } + + /* Perform the interrupt */ + if (!Fast486InterruptInternal(State, + IdtEntry.Selector, + MAKELONG(IdtEntry.Offset, IdtEntry.OffsetHigh), + IdtEntry.Type)) + { + /* + * If this function failed, that means Fast486Exception + * was called again, so just return in this case. + */ + return; + } + + if (EXCEPTION_HAS_ERROR_CODE(ExceptionCode) + && (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)) + { + /* Push the error code */ + if (!Fast486StackPush(State, ErrorCode)) + { + /* + * If this function failed, that means Fast486Exception + * was called again, so just return in this case. + */ + return; + } + } + + /* Reset the exception count */ + State->ExceptionCount = 0; +} + +/* EOF */ diff --git a/lib/fast486/common.h b/lib/fast486/common.h new file mode 100644 index 00000000000..1bfdb311ef2 --- /dev/null +++ b/lib/fast486/common.h @@ -0,0 +1,180 @@ +/* + * Fast486 386/486 CPU Emulation Library + * common.h + * + * Copyright (C) 2013 Aleksandar Andrejevic + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _COMMON_H_ +#define _COMMON_H_ + +#pragma once + +/* DEFINES ********************************************************************/ + +#define SIGN_FLAG_BYTE 0x80 +#define SIGN_FLAG_WORD 0x8000 +#define SIGN_FLAG_LONG 0x80000000 +#define REAL_MODE_FLAGS_MASK 0x57FD5 +#define PROT_MODE_FLAGS_MASK 0x50DD5 + +/* Block size for string operations */ +#define STRING_BLOCK_SIZE 4096 + +#define GET_SEGMENT_RPL(s) ((s) & 3) +#define GET_SEGMENT_INDEX(s) ((s) & 0xFFF8) +#define SEGMENT_TABLE_INDICATOR (1 << 2) +#define EXCEPTION_HAS_ERROR_CODE(x) (((x) == 8) || ((x) >= 10 && (x) <= 14)) + +#define NO_LOCK_PREFIX()\ +if (State->PrefixFlags & FAST486_PREFIX_LOCK)\ +{\ + Fast486Exception(State, FAST486_EXCEPTION_UD);\ + return FALSE;\ +} + +#define TOGGLE_OPSIZE(x)\ + if (State->PrefixFlags & FAST486_PREFIX_OPSIZE) x = !x; + +#define TOGGLE_ADSIZE(x)\ + if (State->PrefixFlags & FAST486_PREFIX_ADSIZE) x = !x; + +#define SWAP(x, y) { (x) ^= (y); (y) ^= (x); (x) ^= (y); } + +#define ALIGNMENT_CHECK(x, a) if (State->Flags.Ac \ + && (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_AM)\ + && (State->Cpl == 3)\ + && (((x) % (a)) != 0))\ +{\ + Fast486Exception(State, FAST486_EXCEPTION_AC);\ + return FALSE;\ +} + +#define PAGE_ALIGN(x) ((x) & 0xFFFFF000) +#define PAGE_OFFSET(x) ((x) & 0x00000FFF) +#define GET_ADDR_PDE(x) ((x) >> 22) +#define GET_ADDR_PTE(x) (((x) >> 12) & 0x3FF) +#define INVALID_TLB_FIELD 0xFFFFFFFF + +#ifndef PAGE_SIZE +#define PAGE_SIZE 4096 +#endif + +typedef struct _FAST486_MOD_REG_RM +{ + FAST486_GEN_REGS Register; + BOOLEAN Memory; + union + { + FAST486_GEN_REGS SecondRegister; + ULONG MemoryAddress; + }; +} FAST486_MOD_REG_RM, *PFAST486_MOD_REG_RM; + +#pragma pack(push, 1) + +typedef union _FAST486_PAGE_DIR +{ + struct + { + ULONG Present : 1; + ULONG Writeable : 1; + ULONG Usermode : 1; + ULONG WriteThrough : 1; + ULONG NoCache : 1; + ULONG Accessed : 1; + ULONG AlwaysZero : 1; + ULONG Size : 1; + ULONG Unused : 4; + ULONG TableAddress : 20; + }; + ULONG Value; +} FAST486_PAGE_DIR, *PFAST486_PAGE_DIR; + +C_ASSERT(sizeof(FAST486_PAGE_DIR) == sizeof(ULONG)); + +typedef union _FAST486_PAGE_TABLE +{ + struct + { + ULONG Present : 1; + ULONG Writeable : 1; + ULONG Usermode : 1; + ULONG WriteThrough : 1; + ULONG NoCache : 1; + ULONG Accessed : 1; + ULONG Dirty : 1; + ULONG AlwaysZero : 1; + ULONG Global : 1; + ULONG Unused : 3; + ULONG Address : 20; + }; + ULONG Value; +} FAST486_PAGE_TABLE, *PFAST486_PAGE_TABLE; + +C_ASSERT(sizeof(FAST486_PAGE_DIR) == sizeof(ULONG)); + +#pragma pack(pop) + +/* FUNCTIONS ******************************************************************/ + +BOOLEAN +Fast486ReadMemory +( + PFAST486_STATE State, + FAST486_SEG_REGS SegmentReg, + ULONG Offset, + BOOLEAN InstFetch, + PVOID Buffer, + ULONG Size +); + +BOOLEAN +Fast486WriteMemory +( + PFAST486_STATE State, + FAST486_SEG_REGS SegmentReg, + ULONG Offset, + PVOID Buffer, + ULONG Size +); + +BOOLEAN +Fast486InterruptInternal +( + PFAST486_STATE State, + USHORT SegmentSelector, + ULONG Offset, + BOOLEAN InterruptGate +); + +VOID +FASTCALL +Fast486ExceptionWithErrorCode +( + PFAST486_STATE State, + FAST486_EXCEPTIONS ExceptionCode, + ULONG ErrorCode +); + +/* INLINED FUNCTIONS **********************************************************/ + +#include "common.inl" + +#endif // _COMMON_H_ + +/* EOF */ diff --git a/lib/fast486/common.inl b/lib/fast486/common.inl new file mode 100644 index 00000000000..fff8fc01474 --- /dev/null +++ b/lib/fast486/common.inl @@ -0,0 +1,1324 @@ +/* + * Fast486 386/486 CPU Emulation Library + * common.inl + * + * Copyright (C) 2013 Aleksandar Andrejevic + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "common.h" + +/* PUBLIC FUNCTIONS ***********************************************************/ + +FORCEINLINE +INT +Fast486GetCurrentPrivLevel(PFAST486_STATE State) +{ + /* Return the CPL, or 3 if we're in virtual 8086 mode */ + return (!State->Flags.Vm) ? State->Cpl : 3; +} + +FORCEINLINE +ULONG +Fast486GetPageTableEntry(PFAST486_STATE State, + ULONG VirtualAddress, + BOOLEAN MarkAsDirty) +{ + ULONG PdeIndex = GET_ADDR_PDE(VirtualAddress); + ULONG PteIndex = GET_ADDR_PTE(VirtualAddress); + FAST486_PAGE_DIR DirectoryEntry; + FAST486_PAGE_TABLE TableEntry; + ULONG PageDirectory = State->ControlRegisters[FAST486_REG_CR3]; + + if ((State->Tlb != NULL) + && (State->Tlb[VirtualAddress >> 12] != INVALID_TLB_FIELD)) + { + /* Return the cached entry */ + return State->Tlb[VirtualAddress >> 12]; + } + + /* Read the directory entry */ + State->MemReadCallback(State, + PageDirectory + PdeIndex * sizeof(ULONG), + &DirectoryEntry.Value, + sizeof(DirectoryEntry)); + + /* Make sure it is present */ + if (!DirectoryEntry.Present) return 0; + + /* Was the directory entry accessed before? */ + if (!DirectoryEntry.Accessed) + { + /* Well, it is now */ + DirectoryEntry.Accessed = TRUE; + + /* Write back the directory entry */ + State->MemWriteCallback(State, + PageDirectory + PdeIndex * sizeof(ULONG), + &DirectoryEntry.Value, + sizeof(DirectoryEntry)); + } + + /* Read the table entry */ + State->MemReadCallback(State, + (DirectoryEntry.TableAddress << 12) + + PteIndex * sizeof(ULONG), + &TableEntry.Value, + sizeof(TableEntry)); + + /* Make sure it is present */ + if (!TableEntry.Present) return 0; + + if (MarkAsDirty) TableEntry.Dirty = TRUE; + + /* Was the table entry accessed before? */ + if (!TableEntry.Accessed) + { + /* Well, it is now */ + TableEntry.Accessed = TRUE; + + /* Write back the table entry */ + State->MemWriteCallback(State, + (DirectoryEntry.TableAddress << 12) + + PteIndex * sizeof(ULONG), + &TableEntry.Value, + sizeof(TableEntry)); + } + + /* + * The resulting permissions depend on the permissions + * in the page directory table too + */ + TableEntry.Writeable &= DirectoryEntry.Writeable; + TableEntry.Usermode &= DirectoryEntry.Usermode; + + if (State->Tlb != NULL) + { + /* Set the TLB entry */ + State->Tlb[VirtualAddress >> 12] = TableEntry.Value; + } + + /* Return the table entry */ + return TableEntry.Value; +} + +FORCEINLINE +BOOLEAN +Fast486ReadLinearMemory(PFAST486_STATE State, + ULONG LinearAddress, + PVOID Buffer, + ULONG Size) +{ + /* Check if paging is enabled */ + if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PG) + { + ULONG Page; + FAST486_PAGE_TABLE TableEntry; + INT Cpl = Fast486GetCurrentPrivLevel(State); + ULONG BufferOffset = 0; + + for (Page = PAGE_ALIGN(LinearAddress); + Page <= PAGE_ALIGN(LinearAddress + Size - 1); + Page += PAGE_SIZE) + { + ULONG PageOffset = 0, PageLength = PAGE_SIZE; + + /* Get the table entry */ + TableEntry.Value = Fast486GetPageTableEntry(State, Page, FALSE); + + if (!TableEntry.Present || (!TableEntry.Usermode && (Cpl > 0))) + { + /* Exception */ + Fast486ExceptionWithErrorCode(State, + FAST486_EXCEPTION_PF, + TableEntry.Value & 0x07); + return FALSE; + } + + /* Check if this is the first page */ + if (Page == PAGE_ALIGN(LinearAddress)) + { + /* Start reading from the offset from the beginning of the page */ + PageOffset = PAGE_OFFSET(LinearAddress); + PageLength -= PageOffset; + } + + /* Check if this is the last page */ + if (Page == PAGE_ALIGN(LinearAddress + Size - 1)) + { + /* Read only a part of the page */ + PageLength = PAGE_OFFSET(LinearAddress + Size - 1) - PageOffset + 1; + } + + /* Read the memory */ + State->MemReadCallback(State, + (TableEntry.Address << 12) | PageOffset, + (PVOID)((ULONG_PTR)Buffer + BufferOffset), + PageLength); + + BufferOffset += PageLength; + } + } + else + { + /* Read the memory */ + State->MemReadCallback(State, LinearAddress, Buffer, Size); + } + + return TRUE; +} + +FORCEINLINE +BOOLEAN +Fast486WriteLinearMemory(PFAST486_STATE State, + ULONG LinearAddress, + PVOID Buffer, + ULONG Size) +{ + /* Check if paging is enabled */ + if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PG) + { + ULONG Page; + FAST486_PAGE_TABLE TableEntry; + INT Cpl = Fast486GetCurrentPrivLevel(State); + ULONG BufferOffset = 0; + + for (Page = PAGE_ALIGN(LinearAddress); + Page <= PAGE_ALIGN(LinearAddress + Size - 1); + Page += PAGE_SIZE) + { + ULONG PageOffset = 0, PageLength = PAGE_SIZE; + + /* Get the table entry */ + TableEntry.Value = Fast486GetPageTableEntry(State, Page, TRUE); + + if ((!TableEntry.Present || (!TableEntry.Usermode && (Cpl > 0))) + || ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_WP) + && !TableEntry.Writeable)) + { + /* Exception */ + Fast486ExceptionWithErrorCode(State, + FAST486_EXCEPTION_PF, + TableEntry.Value & 0x07); + return FALSE; + } + + /* Check if this is the first page */ + if (Page == PAGE_ALIGN(LinearAddress)) + { + /* Start writing from the offset from the beginning of the page */ + PageOffset = PAGE_OFFSET(LinearAddress); + PageLength -= PageOffset; + } + + /* Check if this is the last page */ + if (Page == PAGE_ALIGN(LinearAddress + Size - 1)) + { + /* Write only a part of the page */ + PageLength = PAGE_OFFSET(LinearAddress + Size - 1) - PageOffset + 1; + } + + /* Write the memory */ + State->MemWriteCallback(State, + (TableEntry.Address << 12) | PageOffset, + (PVOID)((ULONG_PTR)Buffer + BufferOffset), + PageLength); + + BufferOffset += PageLength; + } + } + else + { + /* Write the memory */ + State->MemWriteCallback(State, LinearAddress, Buffer, Size); + } + + return TRUE; +} + +FORCEINLINE +VOID +Fast486Exception(PFAST486_STATE State, + FAST486_EXCEPTIONS ExceptionCode) +{ + /* Call the internal function */ + Fast486ExceptionWithErrorCode(State, ExceptionCode, 0); +} + +FORCEINLINE +BOOLEAN +Fast486StackPush(PFAST486_STATE State, + ULONG Value) +{ + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + /* The OPSIZE prefix toggles the size */ + if (State->PrefixFlags & FAST486_PREFIX_OPSIZE) Size = !Size; + + if (Size) + { + /* 32-bit size */ + + /* Check if ESP is between 1 and 3 */ + if (State->GeneralRegs[FAST486_REG_ESP].Long >= 1 + && State->GeneralRegs[FAST486_REG_ESP].Long <= 3) + { + Fast486Exception(State, FAST486_EXCEPTION_SS); + return FALSE; + } + + /* Subtract ESP by 4 */ + State->GeneralRegs[FAST486_REG_ESP].Long -= sizeof(ULONG); + + /* Store the value in SS:ESP */ + return Fast486WriteMemory(State, + FAST486_REG_SS, + State->GeneralRegs[FAST486_REG_ESP].Long, + &Value, + sizeof(ULONG)); + } + else + { + /* 16-bit size */ + USHORT ShortValue = LOWORD(Value); + + /* Check if SP is 1 */ + if (State->GeneralRegs[FAST486_REG_ESP].LowWord == 1) + { + Fast486Exception(State, FAST486_EXCEPTION_SS); + return FALSE; + } + + /* Subtract SP by 2 */ + State->GeneralRegs[FAST486_REG_ESP].LowWord -= sizeof(USHORT); + + /* Store the value in SS:SP */ + return Fast486WriteMemory(State, + FAST486_REG_SS, + State->GeneralRegs[FAST486_REG_ESP].LowWord, + &ShortValue, + sizeof(USHORT)); + } +} + +FORCEINLINE +BOOLEAN +Fast486StackPop(PFAST486_STATE State, + PULONG Value) +{ + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + /* The OPSIZE prefix toggles the size */ + TOGGLE_OPSIZE(Size); + + if (Size) + { + /* 32-bit size */ + ULONG LongValue; + + /* Check if ESP is 0xFFFFFFFF */ + if (State->GeneralRegs[FAST486_REG_ESP].Long == 0xFFFFFFFF) + { + Fast486Exception(State, FAST486_EXCEPTION_SS); + return FALSE; + } + + /* Read the value from SS:ESP */ + if (!Fast486ReadMemory(State, + FAST486_REG_SS, + State->GeneralRegs[FAST486_REG_ESP].Long, + FALSE, + &LongValue, + sizeof(LongValue))) + { + /* An exception occurred */ + return FALSE; + } + + /* Increment ESP by 4 */ + State->GeneralRegs[FAST486_REG_ESP].Long += sizeof(ULONG); + + /* Store the value in the result */ + *Value = LongValue; + } + else + { + /* 16-bit size */ + USHORT ShortValue; + + /* Check if SP is 0xFFFF */ + if (State->GeneralRegs[FAST486_REG_ESP].LowWord == 0xFFFF) + { + Fast486Exception(State, FAST486_EXCEPTION_SS); + return FALSE; + } + + /* Read the value from SS:SP */ + if (!Fast486ReadMemory(State, + FAST486_REG_SS, + State->GeneralRegs[FAST486_REG_ESP].LowWord, + FALSE, + &ShortValue, + sizeof(ShortValue))) + { + /* An exception occurred */ + return FALSE; + } + + /* Increment SP by 2 */ + State->GeneralRegs[FAST486_REG_ESP].LowWord += sizeof(USHORT); + + /* Store the value in the result */ + *Value = ShortValue; + } + + return TRUE; +} + +FORCEINLINE +BOOLEAN +Fast486LoadSegment(PFAST486_STATE State, + FAST486_SEG_REGS Segment, + USHORT Selector) +{ + PFAST486_SEG_REG CachedDescriptor; + FAST486_GDT_ENTRY GdtEntry; + + ASSERT(Segment < FAST486_NUM_SEG_REGS); + + /* Get the cached descriptor */ + CachedDescriptor = &State->SegmentRegs[Segment]; + + /* Check for protected mode */ + if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) && !State->Flags.Vm) + { + if (!(Selector & SEGMENT_TABLE_INDICATOR)) + { + /* Make sure the GDT contains the entry */ + if (GET_SEGMENT_INDEX(Selector) >= (State->Gdtr.Size + 1)) + { + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector); + return FALSE; + } + + /* Read the GDT */ + if (!Fast486ReadLinearMemory(State, + State->Gdtr.Address + + GET_SEGMENT_INDEX(Selector), + &GdtEntry, + sizeof(GdtEntry))) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + /* Make sure the LDT contains the entry */ + if (GET_SEGMENT_INDEX(Selector) >= (State->Ldtr.Limit + 1)) + { + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector); + return FALSE; + } + + /* Read the LDT */ + if (!Fast486ReadLinearMemory(State, + State->Ldtr.Base + + GET_SEGMENT_INDEX(Selector), + &GdtEntry, + sizeof(GdtEntry))) + { + /* Exception occurred */ + return FALSE; + } + } + + if (Segment == FAST486_REG_SS) + { + /* Loading the stack segment */ + + if (GET_SEGMENT_INDEX(Selector) == 0) + { + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + + if (!GdtEntry.SystemType) + { + /* This is a special descriptor */ + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector); + return FALSE; + } + + if (GdtEntry.Executable || !GdtEntry.ReadWrite) + { + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector); + return FALSE; + } + + if ((GET_SEGMENT_RPL(Selector) != Fast486GetCurrentPrivLevel(State)) + || (GET_SEGMENT_RPL(Selector) != GdtEntry.Dpl)) + { + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector); + return FALSE; + } + + if (!GdtEntry.Present) + { + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_SS, Selector); + return FALSE; + } + } + else if (Segment == FAST486_REG_CS) + { + /* Loading the code segment */ + + if (GET_SEGMENT_INDEX(Selector) == 0) + { + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + + if (!GdtEntry.SystemType) + { + // TODO: Call/interrupt/task gates NOT IMPLEMENTED! + UNIMPLEMENTED; + } + else + { + if (!GdtEntry.Present) + { + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_NP, Selector); + return FALSE; + } + + if (!GdtEntry.Executable) + { + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector); + return FALSE; + } + + if (GdtEntry.DirConf) + { + /* Conforming Code Segment */ + + if (GdtEntry.Dpl > Fast486GetCurrentPrivLevel(State)) + { + /* Must be accessed from lower-privileged code */ + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector); + return FALSE; + } + } + else + { + /* Regular code segment */ + + if ((GET_SEGMENT_RPL(Selector) > Fast486GetCurrentPrivLevel(State)) + || (Fast486GetCurrentPrivLevel(State) != GdtEntry.Dpl)) + { + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector); + return FALSE; + } + } + + /* Update CPL */ + State->Cpl = GET_SEGMENT_RPL(Selector); + } + } + else + { + /* Loading a data segment */ + + if (!GdtEntry.SystemType) + { + /* This is a special descriptor */ + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector); + return FALSE; + } + + if ((GET_SEGMENT_RPL(Selector) > GdtEntry.Dpl) + || (Fast486GetCurrentPrivLevel(State) > GdtEntry.Dpl)) + { + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector); + return FALSE; + } + + if (!GdtEntry.Present) + { + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_NP, Selector); + return FALSE; + } + } + + /* Update the cache entry */ + CachedDescriptor->Selector = Selector; + CachedDescriptor->Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (GdtEntry.BaseHigh << 24); + CachedDescriptor->Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16); + CachedDescriptor->Accessed = GdtEntry.Accessed; + CachedDescriptor->ReadWrite = GdtEntry.ReadWrite; + CachedDescriptor->DirConf = GdtEntry.DirConf; + CachedDescriptor->Executable = GdtEntry.Executable; + CachedDescriptor->SystemType = GdtEntry.SystemType; + CachedDescriptor->Dpl = GdtEntry.Dpl; + CachedDescriptor->Present = GdtEntry.Present; + CachedDescriptor->Size = GdtEntry.Size; + + /* Check for page granularity */ + if (GdtEntry.Granularity) CachedDescriptor->Limit <<= 12; + } + else + { + /* Update the selector and base */ + CachedDescriptor->Selector = Selector; + CachedDescriptor->Base = Selector << 4; + } + + return TRUE; +} + +FORCEINLINE +BOOLEAN +Fast486FetchByte(PFAST486_STATE State, + PUCHAR Data) +{ + PFAST486_SEG_REG CachedDescriptor; + + /* Get the cached descriptor of CS */ + CachedDescriptor = &State->SegmentRegs[FAST486_REG_CS]; + + /* Read from memory */ + if (!Fast486ReadMemory(State, + FAST486_REG_CS, + (CachedDescriptor->Size) ? State->InstPtr.Long + : State->InstPtr.LowWord, + TRUE, + Data, + sizeof(UCHAR))) + { + /* Exception occurred during instruction fetch */ + return FALSE; + } + + /* Advance the instruction pointer */ + if (CachedDescriptor->Size) State->InstPtr.Long++; + else State->InstPtr.LowWord++; + + return TRUE; +} + +FORCEINLINE +BOOLEAN +Fast486FetchWord(PFAST486_STATE State, + PUSHORT Data) +{ + PFAST486_SEG_REG CachedDescriptor; + + /* Get the cached descriptor of CS */ + CachedDescriptor = &State->SegmentRegs[FAST486_REG_CS]; + + /* Read from memory */ + // FIXME: Fix byte order on big-endian machines + if (!Fast486ReadMemory(State, + FAST486_REG_CS, + (CachedDescriptor->Size) ? State->InstPtr.Long + : State->InstPtr.LowWord, + TRUE, + Data, + sizeof(USHORT))) + { + /* Exception occurred during instruction fetch */ + return FALSE; + } + + /* Advance the instruction pointer */ + if (CachedDescriptor->Size) State->InstPtr.Long += sizeof(USHORT); + else State->InstPtr.LowWord += sizeof(USHORT); + + return TRUE; +} + +FORCEINLINE +BOOLEAN +Fast486FetchDword(PFAST486_STATE State, + PULONG Data) +{ + PFAST486_SEG_REG CachedDescriptor; + + /* Get the cached descriptor of CS */ + CachedDescriptor = &State->SegmentRegs[FAST486_REG_CS]; + + /* Read from memory */ + // FIXME: Fix byte order on big-endian machines + if (!Fast486ReadMemory(State, + FAST486_REG_CS, + (CachedDescriptor->Size) ? State->InstPtr.Long + : State->InstPtr.LowWord, + TRUE, + Data, + sizeof(ULONG))) + { + /* Exception occurred during instruction fetch */ + return FALSE; + } + + /* Advance the instruction pointer */ + if (CachedDescriptor->Size) State->InstPtr.Long += sizeof(ULONG); + else State->InstPtr.LowWord += sizeof(ULONG); + + return TRUE; +} + +FORCEINLINE +BOOLEAN +Fast486GetIntVector(PFAST486_STATE State, + UCHAR Number, + PFAST486_IDT_ENTRY IdtEntry) +{ + ULONG FarPointer; + + /* Check for protected mode */ + if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) + { + /* Read from the IDT */ + if (!Fast486ReadLinearMemory(State, + State->Idtr.Address + + Number * sizeof(*IdtEntry), + IdtEntry, + sizeof(*IdtEntry))) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + /* Read from the real-mode IVT */ + + /* Paging is always disabled in real mode */ + State->MemReadCallback(State, + State->Idtr.Address + + Number * sizeof(FarPointer), + &FarPointer, + sizeof(FarPointer)); + + /* Fill a fake IDT entry */ + IdtEntry->Offset = LOWORD(FarPointer); + IdtEntry->Selector = HIWORD(FarPointer); + IdtEntry->Zero = 0; + IdtEntry->Type = FAST486_IDT_INT_GATE; + IdtEntry->Storage = FALSE; + IdtEntry->Dpl = 0; + IdtEntry->Present = TRUE; + IdtEntry->OffsetHigh = 0; + } + + return TRUE; +} + +FORCEINLINE +BOOLEAN +Fast486CalculateParity(UCHAR Number) +{ + // See http://graphics.stanford.edu/~seander/bithacks.html#ParityLookupTable too... + return (0x9669 >> ((Number & 0x0F) ^ (Number >> 4))) & 1; +} + +FORCEINLINE +BOOLEAN +Fast486ParseModRegRm(PFAST486_STATE State, + BOOLEAN AddressSize, + PFAST486_MOD_REG_RM ModRegRm) +{ + UCHAR ModRmByte, Mode, RegMem; + + /* Fetch the MOD REG R/M byte */ + if (!Fast486FetchByte(State, &ModRmByte)) + { + /* Exception occurred */ + return FALSE; + } + + /* Unpack the mode and R/M */ + Mode = ModRmByte >> 6; + RegMem = ModRmByte & 0x07; + + /* Set the register operand */ + ModRegRm->Register = (ModRmByte >> 3) & 0x07; + + /* Check the mode */ + if ((ModRmByte >> 6) == 3) + { + /* The second operand is also a register */ + ModRegRm->Memory = FALSE; + ModRegRm->SecondRegister = RegMem; + + /* Done parsing */ + return TRUE; + } + + /* The second operand is memory */ + ModRegRm->Memory = TRUE; + + if (AddressSize) + { + if (RegMem == FAST486_REG_ESP) + { + UCHAR SibByte; + ULONG Scale, Index, Base; + + /* Fetch the SIB byte */ + if (!Fast486FetchByte(State, &SibByte)) + { + /* Exception occurred */ + return FALSE; + } + + /* Unpack the scale, index and base */ + Scale = 1 << (SibByte >> 6); + Index = (SibByte >> 3) & 0x07; + if (Index != FAST486_REG_ESP) Index = State->GeneralRegs[Index].Long; + else Index = 0; + + if (((SibByte & 0x07) != FAST486_REG_EBP) || (Mode != 0)) + { + /* Use the register a base */ + Base = State->GeneralRegs[SibByte & 0x07].Long; + } + else + { + /* Fetch the base */ + if (!Fast486FetchDword(State, &Base)) + { + /* Exception occurred */ + return FALSE; + } + } + + if ((SibByte & 0x07) == FAST486_REG_ESP) + { + /* Check if there is no segment override */ + if (!(State->PrefixFlags & FAST486_PREFIX_SEG)) + { + /* Add a SS: prefix */ + State->PrefixFlags |= FAST486_PREFIX_SEG; + State->SegmentOverride = FAST486_REG_SS; + } + } + + /* Calculate the address */ + ModRegRm->MemoryAddress = Base + Index * Scale; + } + else if (RegMem == FAST486_REG_EBP) + { + if (Mode) ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBP].Long; + else ModRegRm->MemoryAddress = 0; + } + else + { + /* Get the base from the register */ + ModRegRm->MemoryAddress = State->GeneralRegs[RegMem].Long; + } + + /* Check if there is no segment override */ + if (!(State->PrefixFlags & FAST486_PREFIX_SEG)) + { + /* Check if the default segment should be SS */ + if ((RegMem == FAST486_REG_EBP) && Mode) + { + /* Add a SS: prefix */ + State->PrefixFlags |= FAST486_PREFIX_SEG; + State->SegmentOverride = FAST486_REG_SS; + } + } + + if (Mode == 1) + { + CHAR Offset; + + /* Fetch the byte */ + if (!Fast486FetchByte(State, (PUCHAR)&Offset)) + { + /* Exception occurred */ + return FALSE; + } + + /* Add the signed offset to the address */ + ModRegRm->MemoryAddress += (LONG)Offset; + } + else if ((Mode == 2) || ((Mode == 0) && (RegMem == FAST486_REG_EBP))) + { + LONG Offset; + + /* Fetch the dword */ + if (!Fast486FetchDword(State, (PULONG)&Offset)) + { + /* Exception occurred */ + return FALSE; + } + + /* Add the signed offset to the address */ + ModRegRm->MemoryAddress += Offset; + } + } + else + { + /* Check the operand */ + switch (RegMem) + { + case 0: + { + /* [BX + SI] */ + ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBX].LowWord + + State->GeneralRegs[FAST486_REG_ESI].LowWord; + + break; + } + + case 1: + { + /* [BX + DI] */ + ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBX].LowWord + + State->GeneralRegs[FAST486_REG_EDI].LowWord; + + break; + } + + case 2: + { + /* SS:[BP + SI] */ + ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBP].LowWord + + State->GeneralRegs[FAST486_REG_ESI].LowWord; + + break; + } + + case 3: + { + /* SS:[BP + DI] */ + ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBP].LowWord + + State->GeneralRegs[FAST486_REG_EDI].LowWord; + + break; + } + + case 4: + { + /* [SI] */ + ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_ESI].LowWord; + + break; + } + + case 5: + { + /* [DI] */ + ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EDI].LowWord; + + break; + } + + case 6: + { + if (Mode) + { + /* [BP] */ + ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBP].LowWord; + } + else + { + /* [constant] (added later) */ + ModRegRm->MemoryAddress = 0; + } + + break; + } + + case 7: + { + /* [BX] */ + ModRegRm->MemoryAddress = State->GeneralRegs[FAST486_REG_EBX].LowWord; + + break; + } + } + + /* Check if there is no segment override */ + if (!(State->PrefixFlags & FAST486_PREFIX_SEG)) + { + /* Check if the default segment should be SS */ + if ((RegMem == 2) || (RegMem == 3) || ((RegMem == 6) && Mode)) + { + /* Add a SS: prefix */ + State->PrefixFlags |= FAST486_PREFIX_SEG; + State->SegmentOverride = FAST486_REG_SS; + } + } + + if (Mode == 1) + { + CHAR Offset; + + /* Fetch the byte */ + if (!Fast486FetchByte(State, (PUCHAR)&Offset)) + { + /* Exception occurred */ + return FALSE; + } + + /* Add the signed offset to the address */ + ModRegRm->MemoryAddress += (LONG)Offset; + } + else if ((Mode == 2) || ((Mode == 0) && (RegMem == 6))) + { + SHORT Offset; + + /* Fetch the word */ + if (!Fast486FetchWord(State, (PUSHORT)&Offset)) + { + /* Exception occurred */ + return FALSE; + } + + /* Add the signed offset to the address */ + ModRegRm->MemoryAddress += (LONG)Offset; + } + + /* Clear the top 16 bits */ + ModRegRm->MemoryAddress &= 0x0000FFFF; + } + + return TRUE; +} + +FORCEINLINE +BOOLEAN +Fast486ReadModrmByteOperands(PFAST486_STATE State, + PFAST486_MOD_REG_RM ModRegRm, + PUCHAR RegValue, + PUCHAR RmValue) +{ + FAST486_SEG_REGS Segment = FAST486_REG_DS; + + if (RegValue) + { + /* Get the register value */ + if (ModRegRm->Register & 0x04) + { + /* AH, CH, DH, BH */ + *RegValue = State->GeneralRegs[ModRegRm->Register & 0x03].HighByte; + } + else + { + /* AL, CL, DL, BL */ + *RegValue = State->GeneralRegs[ModRegRm->Register & 0x03].LowByte; + } + } + + if (RmValue) + { + if (!ModRegRm->Memory) + { + /* Get the second register value */ + if (ModRegRm->SecondRegister & 0x04) + { + /* AH, CH, DH, BH */ + *RmValue = State->GeneralRegs[ModRegRm->SecondRegister & 0x03].HighByte; + } + else + { + /* AL, CL, DL, BL */ + *RmValue = State->GeneralRegs[ModRegRm->SecondRegister & 0x03].LowByte; + } + } + else + { + /* Check for the segment override */ + if (State->PrefixFlags & FAST486_PREFIX_SEG) + { + /* Use the override segment instead */ + Segment = State->SegmentOverride; + } + + /* Read memory */ + if (!Fast486ReadMemory(State, + Segment, + ModRegRm->MemoryAddress, + FALSE, + RmValue, + sizeof(UCHAR))) + { + /* Exception occurred */ + return FALSE; + } + } + } + + return TRUE; +} + +FORCEINLINE +BOOLEAN +Fast486ReadModrmWordOperands(PFAST486_STATE State, + PFAST486_MOD_REG_RM ModRegRm, + PUSHORT RegValue, + PUSHORT RmValue) +{ + FAST486_SEG_REGS Segment = FAST486_REG_DS; + + if (RegValue) + { + /* Get the register value */ + *RegValue = State->GeneralRegs[ModRegRm->Register].LowWord; + } + + if (RmValue) + { + if (!ModRegRm->Memory) + { + /* Get the second register value */ + *RmValue = State->GeneralRegs[ModRegRm->SecondRegister].LowWord; + } + else + { + /* Check for the segment override */ + if (State->PrefixFlags & FAST486_PREFIX_SEG) + { + /* Use the override segment instead */ + Segment = State->SegmentOverride; + } + + /* Read memory */ + if (!Fast486ReadMemory(State, + Segment, + ModRegRm->MemoryAddress, + FALSE, + RmValue, + sizeof(USHORT))) + { + /* Exception occurred */ + return FALSE; + } + } + } + + return TRUE; +} + +FORCEINLINE +BOOLEAN +Fast486ReadModrmDwordOperands(PFAST486_STATE State, + PFAST486_MOD_REG_RM ModRegRm, + PULONG RegValue, + PULONG RmValue) +{ + FAST486_SEG_REGS Segment = FAST486_REG_DS; + + if (RegValue) + { + /* Get the register value */ + *RegValue = State->GeneralRegs[ModRegRm->Register].Long; + } + + if (RmValue) + { + if (!ModRegRm->Memory) + { + /* Get the second register value */ + *RmValue = State->GeneralRegs[ModRegRm->SecondRegister].Long; + } + else + { + /* Check for the segment override */ + if (State->PrefixFlags & FAST486_PREFIX_SEG) + { + /* Use the override segment instead */ + Segment = State->SegmentOverride; + } + + /* Read memory */ + if (!Fast486ReadMemory(State, + Segment, + ModRegRm->MemoryAddress, + FALSE, + RmValue, + sizeof(ULONG))) + { + /* Exception occurred */ + return FALSE; + } + } + } + + return TRUE; +} + +FORCEINLINE +BOOLEAN +Fast486WriteModrmByteOperands(PFAST486_STATE State, + PFAST486_MOD_REG_RM ModRegRm, + BOOLEAN WriteRegister, + UCHAR Value) +{ + FAST486_SEG_REGS Segment = FAST486_REG_DS; + + if (WriteRegister) + { + /* Store the value in the register */ + if (ModRegRm->Register & 0x04) + { + /* AH, CH, DH, BH */ + State->GeneralRegs[ModRegRm->Register & 0x03].HighByte = Value; + } + else + { + /* AL, CL, DL, BL */ + State->GeneralRegs[ModRegRm->Register & 0x03].LowByte = Value; + } + } + else + { + if (!ModRegRm->Memory) + { + /* Store the value in the second register */ + if (ModRegRm->SecondRegister & 0x04) + { + /* AH, CH, DH, BH */ + State->GeneralRegs[ModRegRm->SecondRegister & 0x03].HighByte = Value; + } + else + { + /* AL, CL, DL, BL */ + State->GeneralRegs[ModRegRm->SecondRegister & 0x03].LowByte = Value; + } + } + else + { + /* Check for the segment override */ + if (State->PrefixFlags & FAST486_PREFIX_SEG) + { + /* Use the override segment instead */ + Segment = State->SegmentOverride; + } + + /* Write memory */ + if (!Fast486WriteMemory(State, + Segment, + ModRegRm->MemoryAddress, + &Value, + sizeof(UCHAR))) + { + /* Exception occurred */ + return FALSE; + } + } + } + + return TRUE; +} + +FORCEINLINE +BOOLEAN +Fast486WriteModrmWordOperands(PFAST486_STATE State, + PFAST486_MOD_REG_RM ModRegRm, + BOOLEAN WriteRegister, + USHORT Value) +{ + FAST486_SEG_REGS Segment = FAST486_REG_DS; + + if (WriteRegister) + { + /* Store the value in the register */ + State->GeneralRegs[ModRegRm->Register].LowWord = Value; + } + else + { + if (!ModRegRm->Memory) + { + /* Store the value in the second register */ + State->GeneralRegs[ModRegRm->SecondRegister].LowWord = Value; + } + else + { + /* Check for the segment override */ + if (State->PrefixFlags & FAST486_PREFIX_SEG) + { + /* Use the override segment instead */ + Segment = State->SegmentOverride; + } + + /* Write memory */ + if (!Fast486WriteMemory(State, + Segment, + ModRegRm->MemoryAddress, + &Value, + sizeof(USHORT))) + { + /* Exception occurred */ + return FALSE; + } + } + } + + return TRUE; +} + +FORCEINLINE +BOOLEAN +Fast486WriteModrmDwordOperands(PFAST486_STATE State, + PFAST486_MOD_REG_RM ModRegRm, + BOOLEAN WriteRegister, + ULONG Value) +{ + FAST486_SEG_REGS Segment = FAST486_REG_DS; + + if (WriteRegister) + { + /* Store the value in the register */ + State->GeneralRegs[ModRegRm->Register].Long = Value; + } + else + { + if (!ModRegRm->Memory) + { + /* Store the value in the second register */ + State->GeneralRegs[ModRegRm->SecondRegister].Long = Value; + } + else + { + /* Check for the segment override */ + if (State->PrefixFlags & FAST486_PREFIX_SEG) + { + /* Use the override segment instead */ + Segment = State->SegmentOverride; + } + + /* Write memory */ + if (!Fast486WriteMemory(State, + Segment, + ModRegRm->MemoryAddress, + &Value, + sizeof(ULONG))) + { + /* Exception occurred */ + return FALSE; + } + } + } + + return TRUE; +} + +/* EOF */ diff --git a/lib/fast486/extraops.c b/lib/fast486/extraops.c new file mode 100644 index 00000000000..f9fe386a638 --- /dev/null +++ b/lib/fast486/extraops.c @@ -0,0 +1,2387 @@ +/* + * Fast486 386/486 CPU Emulation Library + * extraops.c + * + * Copyright (C) 2013 Aleksandar Andrejevic + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* INCLUDES *******************************************************************/ + +#include + +// #define NDEBUG +#include + +#include +#include "opcodes.h" +#include "common.h" +#include "opgroups.h" +#include "extraops.h" + +/* PUBLIC VARIABLES ***********************************************************/ + +FAST486_OPCODE_HANDLER_PROC +Fast486ExtendedHandlers[FAST486_NUM_OPCODE_HANDLERS] = +{ + Fast486OpcodeGroup0F00, + Fast486OpcodeGroup0F01, + Fast486ExtOpcodeLar, + Fast486ExtOpcodeLsl, + NULL, // Invalid + NULL, // Invalid + Fast486ExtOpcodeClts, + NULL, // Invalid + NULL, // TODO: OPCODE 0x08 NOT IMPLEMENTED + NULL, // TODO: OPCODE 0x09 NOT IMPLEMENTED + NULL, // Invalid + NULL, // Reserved (UD1) + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + Fast486ExtOpcodeStoreControlReg, + Fast486ExtOpcodeStoreDebugReg, + Fast486ExtOpcodeLoadControlReg, + Fast486ExtOpcodeLoadDebugReg, + NULL, // TODO: OPCODE 0x24 NOT IMPLEMENTED + NULL, // Invalid + NULL, // TODO: OPCODE 0x26 NOT IMPLEMENTED + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + Fast486ExtOpcodeConditionalJmp, + Fast486ExtOpcodeConditionalJmp, + Fast486ExtOpcodeConditionalJmp, + Fast486ExtOpcodeConditionalJmp, + Fast486ExtOpcodeConditionalJmp, + Fast486ExtOpcodeConditionalJmp, + Fast486ExtOpcodeConditionalJmp, + Fast486ExtOpcodeConditionalJmp, + Fast486ExtOpcodeConditionalJmp, + Fast486ExtOpcodeConditionalJmp, + Fast486ExtOpcodeConditionalJmp, + Fast486ExtOpcodeConditionalJmp, + Fast486ExtOpcodeConditionalJmp, + Fast486ExtOpcodeConditionalJmp, + Fast486ExtOpcodeConditionalJmp, + Fast486ExtOpcodeConditionalJmp, + Fast486ExtOpcodeConditionalSet, + Fast486ExtOpcodeConditionalSet, + Fast486ExtOpcodeConditionalSet, + Fast486ExtOpcodeConditionalSet, + Fast486ExtOpcodeConditionalSet, + Fast486ExtOpcodeConditionalSet, + Fast486ExtOpcodeConditionalSet, + Fast486ExtOpcodeConditionalSet, + Fast486ExtOpcodeConditionalSet, + Fast486ExtOpcodeConditionalSet, + Fast486ExtOpcodeConditionalSet, + Fast486ExtOpcodeConditionalSet, + Fast486ExtOpcodeConditionalSet, + Fast486ExtOpcodeConditionalSet, + Fast486ExtOpcodeConditionalSet, + Fast486ExtOpcodeConditionalSet, + Fast486ExtOpcodePushFs, + Fast486ExtOpcodePopFs, + NULL, // Invalid + Fast486ExtOpcodeBitTest, + Fast486ExtOpcodeShld, + Fast486ExtOpcodeShld, + NULL, // Invalid + NULL, // Invalid + Fast486ExtOpcodePushGs, + Fast486ExtOpcodePopGs, + NULL, // Invalid + Fast486ExtOpcodeBts, + Fast486ExtOpcodeShrd, + Fast486ExtOpcodeShrd, + NULL, // Invalid + Fast486ExtOpcodeImul, + Fast486ExtOpcodeCmpXchgByte, + Fast486ExtOpcodeCmpXchg, + Fast486ExtOpcodeLss, + Fast486ExtOpcodeBtr, + Fast486ExtOpcodeLfsLgs, + Fast486ExtOpcodeLfsLgs, + Fast486ExtOpcodeMovzxByte, + Fast486ExtOpcodeMovzxWord, + NULL, // Invalid + Fast486OpcodeGroup0FB9, + Fast486OpcodeGroup0FBA, + Fast486ExtOpcodeBtc, + Fast486ExtOpcodeBsf, + Fast486ExtOpcodeBsr, + Fast486ExtOpcodeMovsxByte, + Fast486ExtOpcodeMovsxWord, + Fast486ExtOpcodeXaddByte, + Fast486ExtOpcodeXadd, + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + Fast486ExtOpcodeBswap, + Fast486ExtOpcodeBswap, + Fast486ExtOpcodeBswap, + Fast486ExtOpcodeBswap, + Fast486ExtOpcodeBswap, + Fast486ExtOpcodeBswap, + Fast486ExtOpcodeBswap, + Fast486ExtOpcodeBswap, + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid + NULL, // Invalid +}; + +/* PUBLIC FUNCTIONS ***********************************************************/ + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLar) +{ + BOOLEAN OperandSize, AddressSize; + FAST486_MOD_REG_RM ModRegRm; + USHORT Selector; + FAST486_GDT_ENTRY GdtEntry; + DWORD AccessRights; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) + || State->Flags.Vm) + { + /* Not recognized */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + NO_LOCK_PREFIX(); + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (OperandSize) + { + ULONG Value; + + /* Read the value */ + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + Selector = LOWORD(Value); + } + else + { + /* Read the value */ + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Selector)) + { + /* Exception occurred */ + return FALSE; + } + } + + if (!(Selector & SEGMENT_TABLE_INDICATOR)) + { + /* Check if the GDT contains the entry */ + if (GET_SEGMENT_INDEX(Selector) >= (State->Gdtr.Size + 1)) + { + State->Flags.Zf = FALSE; + return TRUE; + } + + /* Read the GDT */ + if (!Fast486ReadLinearMemory(State, + State->Gdtr.Address + + GET_SEGMENT_INDEX(Selector), + &GdtEntry, + sizeof(GdtEntry))) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + /* Check if the LDT contains the entry */ + if (GET_SEGMENT_INDEX(Selector) >= (State->Ldtr.Limit + 1)) + { + State->Flags.Zf = FALSE; + return TRUE; + } + + /* Read the LDT */ + if (!Fast486ReadLinearMemory(State, + State->Ldtr.Base + + GET_SEGMENT_INDEX(Selector), + &GdtEntry, + sizeof(GdtEntry))) + { + /* Exception occurred */ + return FALSE; + } + } + + /* Privilege check */ + if (((GET_SEGMENT_RPL(Selector) > GdtEntry.Dpl)) + || (Fast486GetCurrentPrivLevel(State) > GdtEntry.Dpl)) + { + State->Flags.Zf = FALSE; + return TRUE; + } + + /* Set ZF */ + State->Flags.Zf = TRUE; + + /* Get the access rights */ + AccessRights = ((PDWORD)&GdtEntry)[1] & 0x00F0FF00; + + /* Return the access rights */ + if (OperandSize) + { + if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, TRUE, AccessRights)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + if (!Fast486WriteModrmWordOperands(State, &ModRegRm, TRUE, LOWORD(AccessRights))) + { + /* Exception occurred */ + return FALSE; + } + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLsl) +{ + BOOLEAN OperandSize, AddressSize; + FAST486_MOD_REG_RM ModRegRm; + USHORT Selector; + ULONG Limit; + FAST486_GDT_ENTRY GdtEntry; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) + || State->Flags.Vm) + { + /* Not recognized */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + NO_LOCK_PREFIX(); + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (OperandSize) + { + ULONG Value; + + /* Read the value */ + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + Selector = LOWORD(Value); + } + else + { + /* Read the value */ + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Selector)) + { + /* Exception occurred */ + return FALSE; + } + } + + if (!(Selector & SEGMENT_TABLE_INDICATOR)) + { + /* Check if the GDT contains the entry */ + if (GET_SEGMENT_INDEX(Selector) >= (State->Gdtr.Size + 1)) + { + State->Flags.Zf = FALSE; + return TRUE; + } + + /* Read the GDT */ + if (!Fast486ReadLinearMemory(State, + State->Gdtr.Address + + GET_SEGMENT_INDEX(Selector), + &GdtEntry, + sizeof(GdtEntry))) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + /* Check if the LDT contains the entry */ + if (GET_SEGMENT_INDEX(Selector) >= (State->Ldtr.Limit + 1)) + { + State->Flags.Zf = FALSE; + return TRUE; + } + + /* Read the LDT */ + if (!Fast486ReadLinearMemory(State, + State->Ldtr.Base + + GET_SEGMENT_INDEX(Selector), + &GdtEntry, + sizeof(GdtEntry))) + { + /* Exception occurred */ + return FALSE; + } + } + + /* Privilege check */ + if (((GET_SEGMENT_RPL(Selector) > GdtEntry.Dpl)) + || (Fast486GetCurrentPrivLevel(State) > GdtEntry.Dpl)) + { + State->Flags.Zf = FALSE; + return TRUE; + } + + /* Calculate the limit */ + Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16); + if (GdtEntry.Granularity) Limit <<= 12; + + /* Set ZF */ + State->Flags.Zf = TRUE; + + if (OperandSize) + { + /* Return the limit */ + if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, TRUE, Limit)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + /* Return the limit */ + if (!Fast486WriteModrmWordOperands(State, &ModRegRm, TRUE, LOWORD(Limit))) + { + /* Exception occurred */ + return FALSE; + } + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeClts) +{ + NO_LOCK_PREFIX(); + + /* The current privilege level must be zero */ + if (Fast486GetCurrentPrivLevel(State) != 0) + { + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + + /* Clear the task switch bit */ + State->ControlRegisters[FAST486_REG_CR0] &= ~FAST486_CR0_TS; + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeStoreControlReg) +{ + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + FAST486_MOD_REG_RM ModRegRm; + + NO_LOCK_PREFIX(); + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* The current privilege level must be zero */ + if (Fast486GetCurrentPrivLevel(State) != 0) + { + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + + if ((ModRegRm.Register == 1) || (ModRegRm.Register > 3)) + { + /* CR1, CR4, CR5, CR6 and CR7 don't exist */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + if (ModRegRm.Register != 0) + { + /* CR2 and CR3 and are stored in array indexes 1 and 2 */ + ModRegRm.Register--; + } + + /* Store the value of the control register */ + State->GeneralRegs[ModRegRm.SecondRegister].Long = State->ControlRegisters[ModRegRm.Register]; + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeStoreDebugReg) +{ + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + FAST486_MOD_REG_RM ModRegRm; + + NO_LOCK_PREFIX(); + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* The current privilege level must be zero */ + if (Fast486GetCurrentPrivLevel(State) != 0) + { + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + + if ((ModRegRm.Register == 6) || (ModRegRm.Register == 7)) + { + /* DR6 and DR7 are aliases to DR4 and DR5 */ + ModRegRm.Register -= 2; + } + + if (State->DebugRegisters[FAST486_REG_DR5] & FAST486_DR5_GD) + { + /* Disallow access to debug registers */ + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + + /* Store the value of the debug register */ + State->GeneralRegs[ModRegRm.SecondRegister].Long = State->DebugRegisters[ModRegRm.Register]; + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLoadControlReg) +{ + ULONG Value; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + FAST486_MOD_REG_RM ModRegRm; + + NO_LOCK_PREFIX(); + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* The current privilege level must be zero */ + if (Fast486GetCurrentPrivLevel(State) != 0) + { + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + + if ((ModRegRm.Register == 1) || (ModRegRm.Register > 3)) + { + /* CR1, CR4, CR5, CR6 and CR7 don't exist */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + if (ModRegRm.Register != 0) + { + /* CR2 and CR3 and are stored in array indexes 1 and 2 */ + ModRegRm.Register--; + } + + /* Get the value */ + Value = State->GeneralRegs[ModRegRm.SecondRegister].Long; + + if (ModRegRm.Register == (INT)FAST486_REG_CR0) + { + /* CR0 checks */ + + if (((Value & (FAST486_CR0_PG | FAST486_CR0_PE)) == FAST486_CR0_PG) + || ((Value & (FAST486_CR0_CD | FAST486_CR0_NW)) == FAST486_CR0_NW)) + { + /* Invalid value */ + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + } + + /* Load a value to the control register */ + State->ControlRegisters[ModRegRm.Register] = Value; + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLoadDebugReg) +{ + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + FAST486_MOD_REG_RM ModRegRm; + + NO_LOCK_PREFIX(); + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* The current privilege level must be zero */ + if (Fast486GetCurrentPrivLevel(State) != 0) + { + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + + if ((ModRegRm.Register == 6) || (ModRegRm.Register == 7)) + { + /* DR6 and DR7 are aliases to DR4 and DR5 */ + ModRegRm.Register -= 2; + } + + if (State->DebugRegisters[FAST486_REG_DR5] & FAST486_DR5_GD) + { + /* Disallow access to debug registers */ + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + + /* Load a value to the debug register */ + State->DebugRegisters[ModRegRm.Register] = State->GeneralRegs[ModRegRm.SecondRegister].Long; + + if (ModRegRm.Register == (INT)FAST486_REG_DR4) + { + /* The reserved bits are 1 */ + State->DebugRegisters[ModRegRm.Register] |= FAST486_DR4_RESERVED; + } + else if (ModRegRm.Register == (INT)FAST486_REG_DR5) + { + /* The reserved bits are 0 */ + State->DebugRegisters[ModRegRm.Register] &= ~FAST486_DR5_RESERVED; + } + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushFs) +{ + /* Call the internal API */ + return Fast486StackPush(State, State->SegmentRegs[FAST486_REG_FS].Selector); +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopFs) +{ + ULONG NewSelector; + + if (!Fast486StackPop(State, &NewSelector)) + { + /* Exception occurred */ + return FALSE; + } + + /* Call the internal API */ + return Fast486LoadSegment(State, FAST486_REG_FS, LOWORD(NewSelector)); +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBitTest) +{ + BOOLEAN OperandSize, AddressSize; + FAST486_MOD_REG_RM ModRegRm; + UINT DataSize; + ULONG BitNumber; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + /* Get the number of bits */ + if (OperandSize) DataSize = 32; + else DataSize = 16; + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Get the bit number */ + BitNumber = OperandSize ? State->GeneralRegs[ModRegRm.Register].Long + : (ULONG)State->GeneralRegs[ModRegRm.Register].LowWord; + + if (ModRegRm.Memory) + { + /* + * For memory operands, add the bit offset divided by + * the data size to the address + */ + ModRegRm.MemoryAddress += BitNumber / DataSize; + } + + /* Normalize the bit number */ + BitNumber %= DataSize; + + if (OperandSize) + { + ULONG Value; + + /* Read the value */ + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set CF to the bit value */ + State->Flags.Cf = (Value >> BitNumber) & 1; + } + else + { + USHORT Value; + + /* Read the value */ + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set CF to the bit value */ + State->Flags.Cf = (Value >> BitNumber) & 1; + } + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeShld) +{ + BOOLEAN OperandSize, AddressSize; + FAST486_MOD_REG_RM ModRegRm; + UCHAR Count; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFE) == 0xA4); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (Opcode == 0xA4) + { + /* Fetch the count */ + if (!Fast486FetchByte(State, &Count)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + /* The count is in CL */ + Count = State->GeneralRegs[FAST486_REG_ECX].LowByte; + } + + /* Normalize the count */ + Count &= 0x1F; + + /* Do nothing if the count is zero */ + if (Count == 0) return TRUE; + + if (OperandSize) + { + ULONG Source, Destination, Result; + + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Source, &Destination)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = (Destination << Count) | (Source >> (32 - Count)); + + /* Update flags */ + State->Flags.Cf = (Destination >> (32 - Count)) & 1; + if (Count == 1) State->Flags.Of = (Result & SIGN_FLAG_LONG) + != (Destination & SIGN_FLAG_LONG); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Result); + } + else + { + USHORT Source, Destination, Result; + ULONG DoubleSource; + + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Source, &Destination)) + { + /* Exception occurred */ + return FALSE; + } + + DoubleSource = Source | (Source << 16); + + /* Calculate the result */ + Result = (Destination << Count) | (DoubleSource >> (32 - Count)); + + /* Update flags */ + if (Count <= 16) State->Flags.Cf = (Destination >> (16 - Count)) & 1; + else State->Flags.Cf = (Source >> (32 - Count)) & 1; + + if (Count == 1) State->Flags.Of = (Result & SIGN_FLAG_WORD) + != (Destination & SIGN_FLAG_WORD); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Result); + } +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushGs) +{ + /* Call the internal API */ + return Fast486StackPush(State, State->SegmentRegs[FAST486_REG_GS].Selector); +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopGs) +{ + ULONG NewSelector; + + if (!Fast486StackPop(State, &NewSelector)) + { + /* Exception occurred */ + return FALSE; + } + + /* Call the internal API */ + return Fast486LoadSegment(State, FAST486_REG_GS, LOWORD(NewSelector)); +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBts) +{ + BOOLEAN OperandSize, AddressSize; + FAST486_MOD_REG_RM ModRegRm; + UINT DataSize; + ULONG BitNumber; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + /* Get the number of bits */ + if (OperandSize) DataSize = 32; + else DataSize = 16; + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Get the bit number */ + BitNumber = OperandSize ? State->GeneralRegs[ModRegRm.Register].Long + : (ULONG)State->GeneralRegs[ModRegRm.Register].LowWord; + + if (ModRegRm.Memory) + { + /* + * For memory operands, add the bit offset divided by + * the data size to the address + */ + ModRegRm.MemoryAddress += BitNumber / DataSize; + } + + /* Normalize the bit number */ + BitNumber %= DataSize; + + if (OperandSize) + { + ULONG Value; + + /* Read the value */ + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set CF to the bit value */ + State->Flags.Cf = (Value >> BitNumber) & 1; + + /* Set the bit */ + Value |= 1 << BitNumber; + + /* Write back the result */ + if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + USHORT Value; + + /* Read the value */ + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set CF to the bit value */ + State->Flags.Cf = (Value >> BitNumber) & 1; + + /* Set the bit */ + Value |= 1 << BitNumber; + + /* Write back the result */ + if (!Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value)) + { + /* Exception occurred */ + return FALSE; + } + } + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeShrd) +{ + BOOLEAN OperandSize, AddressSize; + FAST486_MOD_REG_RM ModRegRm; + UCHAR Count; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFE) == 0xAC); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (Opcode == 0xAC) + { + /* Fetch the count */ + if (!Fast486FetchByte(State, &Count)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + /* The count is in CL */ + Count = State->GeneralRegs[FAST486_REG_ECX].LowByte; + } + + /* Normalize the count */ + Count &= 0x1F; + + /* Do nothing if the count is zero */ + if (Count == 0) return TRUE; + + if (OperandSize) + { + ULONG Source, Destination, Result; + + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Source, &Destination)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = (Destination >> Count) | (Source << (32 - Count)); + + /* Update flags */ + State->Flags.Cf = (Destination >> (Count - 1)) & 1; + if (Count == 1) State->Flags.Of = (Result & SIGN_FLAG_LONG) + != (Destination & SIGN_FLAG_LONG); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Result); + } + else + { + USHORT Source, Destination, Result; + + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Source, &Destination)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = (Destination >> Count) | (Source << (16 - Count)); + + if (Count >= 16) Result |= (ULONG)(Source | (Source << 16)) >> (Count - 16); + + /* Update flags */ + if (Count <= 16) State->Flags.Cf = (Destination >> (Count - 1)) & 1; + else State->Flags.Cf = (Source >> (Count - 17)) & 1; + + if (Count == 1) State->Flags.Of = (Result & SIGN_FLAG_WORD) + != (Destination & SIGN_FLAG_WORD); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Result); + } +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeImul) +{ + BOOLEAN OperandSize, AddressSize; + FAST486_MOD_REG_RM ModRegRm; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (OperandSize) + { + LONG Source, Destination; + LONGLONG Result; + + /* Read the operands */ + if (!Fast486ReadModrmDwordOperands(State, + &ModRegRm, + (PULONG)&Destination, + (PULONG)&Source)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = (LONGLONG)Source * (LONGLONG)Destination; + + /* Update the flags */ + State->Flags.Cf = State->Flags.Of = ((Result < -2147483648LL) || (Result > 2147483647LL)); + + /* Write back the result */ + return Fast486WriteModrmDwordOperands(State, &ModRegRm, TRUE, (ULONG)((LONG)Result)); + } + else + { + SHORT Source, Destination; + LONG Result; + + /* Read the operands */ + if (!Fast486ReadModrmWordOperands(State, + &ModRegRm, + (PUSHORT)&Destination, + (PUSHORT)&Source)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = (LONG)Source * (LONG)Destination; + + /* Update the flags */ + State->Flags.Cf = State->Flags.Of = ((Result < -32768) || (Result > 32767)); + + /* Write back the result */ + return Fast486WriteModrmWordOperands(State, &ModRegRm, TRUE, (USHORT)((SHORT)Result)); + } +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeCmpXchgByte) +{ + FAST486_MOD_REG_RM ModRegRm; + UCHAR Accumulator = State->GeneralRegs[FAST486_REG_EAX].LowByte; + UCHAR Source, Destination, Result; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Read the operands */ + if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Source, &Destination)) + { + /* Exception occurred */ + return FALSE; + } + + /* Compare AL with the destination */ + Result = Accumulator - Destination; + + /* Update the flags */ + State->Flags.Cf = (Accumulator < Destination); + State->Flags.Of = ((Accumulator & SIGN_FLAG_BYTE) != (Destination & SIGN_FLAG_BYTE)) + && ((Accumulator & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE)); + State->Flags.Af = (Accumulator & 0x0F) < (Destination & 0x0F); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + if (State->Flags.Zf) + { + /* Load the source operand into the destination */ + return Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Source); + } + else + { + /* Load the destination into AL */ + State->GeneralRegs[FAST486_REG_EAX].LowByte = Destination; + } + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeCmpXchg) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (OperandSize) + { + ULONG Source, Destination, Result; + ULONG Accumulator = State->GeneralRegs[FAST486_REG_EAX].Long; + + /* Read the operands */ + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Source, &Destination)) + { + /* Exception occurred */ + return FALSE; + } + + /* Compare EAX with the destination */ + Result = Accumulator - Destination; + + /* Update the flags */ + State->Flags.Cf = (Accumulator < Destination); + State->Flags.Of = ((Accumulator & SIGN_FLAG_LONG) != (Destination & SIGN_FLAG_LONG)) + && ((Accumulator & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG)); + State->Flags.Af = (Accumulator & 0x0F) < (Destination & 0x0F); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + if (State->Flags.Zf) + { + /* Load the source operand into the destination */ + return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Source); + } + else + { + /* Load the destination into EAX */ + State->GeneralRegs[FAST486_REG_EAX].Long = Destination; + } + } + else + { + USHORT Source, Destination, Result; + USHORT Accumulator = State->GeneralRegs[FAST486_REG_EAX].LowWord; + + /* Read the operands */ + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Source, &Destination)) + { + /* Exception occurred */ + return FALSE; + } + + /* Compare AX with the destination */ + Result = Accumulator - Destination; + + /* Update the flags */ + State->Flags.Cf = (Accumulator < Destination); + State->Flags.Of = ((Accumulator & SIGN_FLAG_WORD) != (Destination & SIGN_FLAG_WORD)) + && ((Accumulator & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD)); + State->Flags.Af = (Accumulator & 0x0F) < (Destination & 0x0F); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + if (State->Flags.Zf) + { + /* Load the source operand into the destination */ + return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Source); + } + else + { + /* Load the destination into AX */ + State->GeneralRegs[FAST486_REG_EAX].LowWord = Destination; + } + } + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLss) +{ + UCHAR FarPointer[6]; + BOOLEAN OperandSize, AddressSize; + FAST486_MOD_REG_RM ModRegRm; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xB2); + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (!ModRegRm.Memory) + { + /* Invalid */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + if (!Fast486ReadMemory(State, + (State->PrefixFlags & FAST486_PREFIX_SEG) + ? State->SegmentOverride : FAST486_REG_DS, + ModRegRm.MemoryAddress, + FALSE, + FarPointer, + OperandSize ? 6 : 4)) + { + /* Exception occurred */ + return FALSE; + } + + if (OperandSize) + { + ULONG Offset = *((PULONG)FarPointer); + USHORT Segment = *((PUSHORT)&FarPointer[sizeof(ULONG)]); + + /* Set the register to the offset */ + State->GeneralRegs[ModRegRm.Register].Long = Offset; + + /* Load the segment */ + return Fast486LoadSegment(State, + FAST486_REG_SS, + Segment); + } + else + { + USHORT Offset = *((PUSHORT)FarPointer); + USHORT Segment = *((PUSHORT)&FarPointer[sizeof(USHORT)]); + + /* Set the register to the offset */ + State->GeneralRegs[ModRegRm.Register].LowWord = Offset; + + /* Load the segment */ + return Fast486LoadSegment(State, + FAST486_REG_SS, + Segment); + } +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBtr) +{ + BOOLEAN OperandSize, AddressSize; + FAST486_MOD_REG_RM ModRegRm; + UINT DataSize; + ULONG BitNumber; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + /* Get the number of bits */ + if (OperandSize) DataSize = 32; + else DataSize = 16; + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Get the bit number */ + BitNumber = OperandSize ? State->GeneralRegs[ModRegRm.Register].Long + : (ULONG)State->GeneralRegs[ModRegRm.Register].LowWord; + + if (ModRegRm.Memory) + { + /* + * For memory operands, add the bit offset divided by + * the data size to the address + */ + ModRegRm.MemoryAddress += BitNumber / DataSize; + } + + /* Normalize the bit number */ + BitNumber %= DataSize; + + if (OperandSize) + { + ULONG Value; + + /* Read the value */ + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set CF to the bit value */ + State->Flags.Cf = (Value >> BitNumber) & 1; + + /* Clear the bit */ + Value &= ~(1 << BitNumber); + + /* Write back the result */ + if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + USHORT Value; + + /* Read the value */ + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set CF to the bit value */ + State->Flags.Cf = (Value >> BitNumber) & 1; + + /* Clear the bit */ + Value &= ~(1 << BitNumber); + + /* Write back the result */ + if (!Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value)) + { + /* Exception occurred */ + return FALSE; + } + } + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLfsLgs) +{ + UCHAR FarPointer[6]; + BOOLEAN OperandSize, AddressSize; + FAST486_MOD_REG_RM ModRegRm; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFE) == 0xB4); + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (!ModRegRm.Memory) + { + /* Invalid */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + if (!Fast486ReadMemory(State, + (State->PrefixFlags & FAST486_PREFIX_SEG) + ? State->SegmentOverride : FAST486_REG_DS, + ModRegRm.MemoryAddress, + FALSE, + FarPointer, + OperandSize ? 6 : 4)) + { + /* Exception occurred */ + return FALSE; + } + + if (OperandSize) + { + ULONG Offset = *((PULONG)FarPointer); + USHORT Segment = *((PUSHORT)&FarPointer[sizeof(ULONG)]); + + /* Set the register to the offset */ + State->GeneralRegs[ModRegRm.Register].Long = Offset; + + /* Load the segment */ + return Fast486LoadSegment(State, + (Opcode == 0xB4) + ? FAST486_REG_FS : FAST486_REG_GS, + Segment); + } + else + { + USHORT Offset = *((PUSHORT)FarPointer); + USHORT Segment = *((PUSHORT)&FarPointer[sizeof(USHORT)]); + + /* Set the register to the offset */ + State->GeneralRegs[ModRegRm.Register].LowWord = Offset; + + /* Load the segment */ + return Fast486LoadSegment(State, + (Opcode == 0xB4) + ? FAST486_REG_FS : FAST486_REG_GS, + Segment); + } +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovzxByte) +{ + UCHAR Value; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + FAST486_MOD_REG_RM ModRegRm; + + TOGGLE_ADSIZE(AddressSize); + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xB6); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Read the operands */ + if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Write back the zero-extended value */ + return Fast486WriteModrmDwordOperands(State, + &ModRegRm, + TRUE, + (ULONG)Value); +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovzxWord) +{ + USHORT Value; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + FAST486_MOD_REG_RM ModRegRm; + + TOGGLE_ADSIZE(AddressSize); + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xB7); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Read the operands */ + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Write back the zero-extended value */ + return Fast486WriteModrmDwordOperands(State, + &ModRegRm, + TRUE, + (ULONG)Value); +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBtc) +{ + BOOLEAN OperandSize, AddressSize; + FAST486_MOD_REG_RM ModRegRm; + UINT DataSize; + ULONG BitNumber; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + /* Get the number of bits */ + if (OperandSize) DataSize = 32; + else DataSize = 16; + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Get the bit number */ + BitNumber = OperandSize ? State->GeneralRegs[ModRegRm.Register].Long + : (ULONG)State->GeneralRegs[ModRegRm.Register].LowWord; + + if (ModRegRm.Memory) + { + /* + * For memory operands, add the bit offset divided by + * the data size to the address + */ + ModRegRm.MemoryAddress += BitNumber / DataSize; + } + + /* Normalize the bit number */ + BitNumber %= DataSize; + + if (OperandSize) + { + ULONG Value; + + /* Read the value */ + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set CF to the bit value */ + State->Flags.Cf = (Value >> BitNumber) & 1; + + /* Toggle the bit */ + Value ^= 1 << BitNumber; + + /* Write back the result */ + if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + USHORT Value; + + /* Read the value */ + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set CF to the bit value */ + State->Flags.Cf = (Value >> BitNumber) & 1; + + /* Toggle the bit */ + Value ^= 1 << BitNumber; + + /* Write back the result */ + if (!Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value)) + { + /* Exception occurred */ + return FALSE; + } + } + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBsf) +{ + INT i; + ULONG Value = 0; + BOOLEAN OperandSize, AddressSize; + FAST486_MOD_REG_RM ModRegRm; + ULONG BitNumber; + UINT DataSize; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xBC); + + /* Get the number of bits */ + if (OperandSize) DataSize = 32; + else DataSize = 16; + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Read the value */ + if (OperandSize) + { + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + if (!Fast486ReadModrmWordOperands(State, + &ModRegRm, + (PUSHORT)NULL, + (PUSHORT)&Value)) + { + /* Exception occurred */ + return FALSE; + } + } + + /* Set ZF */ + State->Flags.Zf = (Value == 0); + if (State->Flags.Zf) return TRUE; + + for (i = 0; i < DataSize; i++) + { + if(Value & (1 << i)) + { + /* Save the bit number */ + BitNumber = i; + + /* Exit the loop */ + break; + } + } + + /* Write back the result */ + if (OperandSize) + { + if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, TRUE, BitNumber)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + if (!Fast486WriteModrmWordOperands(State, &ModRegRm, TRUE, LOWORD(BitNumber))) + { + /* Exception occurred */ + return FALSE; + } + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBsr) +{ + INT i; + ULONG Value = 0; + BOOLEAN OperandSize, AddressSize; + FAST486_MOD_REG_RM ModRegRm; + ULONG BitNumber; + UINT DataSize; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xBD); + + /* Get the number of bits */ + if (OperandSize) DataSize = 32; + else DataSize = 16; + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Read the value */ + if (OperandSize) + { + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + if (!Fast486ReadModrmWordOperands(State, + &ModRegRm, + (PUSHORT)NULL, + (PUSHORT)&Value)) + { + /* Exception occurred */ + return FALSE; + } + } + + /* Set ZF according to the value */ + State->Flags.Zf = (Value == 0); + if (State->Flags.Zf) return TRUE; + + for (i = DataSize - 1; i >= 0; i--) + { + if(Value & (1 << i)) + { + /* Save the bit number */ + BitNumber = i; + + /* Exit the loop */ + break; + } + } + + /* Write back the result */ + if (OperandSize) + { + if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, TRUE, BitNumber)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + if (!Fast486WriteModrmWordOperands(State, &ModRegRm, TRUE, LOWORD(BitNumber))) + { + /* Exception occurred */ + return FALSE; + } + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovsxByte) +{ + CHAR Value; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + FAST486_MOD_REG_RM ModRegRm; + + TOGGLE_ADSIZE(AddressSize); + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xBE); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Read the operands */ + if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, (PUCHAR)&Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Write back the sign-extended value */ + return Fast486WriteModrmDwordOperands(State, + &ModRegRm, + TRUE, + (ULONG)((LONG)Value)); +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovsxWord) +{ + SHORT Value; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + FAST486_MOD_REG_RM ModRegRm; + + TOGGLE_ADSIZE(AddressSize); + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xBF); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Read the operands */ + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, (PUSHORT)&Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Write back the sign-extended value */ + return Fast486WriteModrmDwordOperands(State, + &ModRegRm, + TRUE, + (ULONG)((LONG)Value)); +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeConditionalJmp) +{ + BOOLEAN Jump = FALSE; + LONG Offset = 0; + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_OPSIZE(Size); + NO_LOCK_PREFIX(); + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xF0) == 0x80); + + /* Fetch the offset */ + if (Size) + { + if (!Fast486FetchDword(State, (PULONG)&Offset)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + SHORT Value; + + if (!Fast486FetchWord(State, (PUSHORT)&Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Sign-extend */ + Offset = (LONG)Value; + } + + switch ((Opcode & 0x0F) >> 1) + { + /* JO / JNO */ + case 0: + { + Jump = State->Flags.Of; + break; + } + + /* JC / JNC */ + case 1: + { + Jump = State->Flags.Cf; + break; + } + + /* JZ / JNZ */ + case 2: + { + Jump = State->Flags.Zf; + break; + } + + /* JBE / JNBE */ + case 3: + { + Jump = State->Flags.Cf || State->Flags.Zf; + break; + } + + /* JS / JNS */ + case 4: + { + Jump = State->Flags.Sf; + break; + } + + /* JP / JNP */ + case 5: + { + Jump = State->Flags.Pf; + break; + } + + /* JL / JNL */ + case 6: + { + Jump = State->Flags.Sf != State->Flags.Of; + break; + } + + /* JLE / JNLE */ + case 7: + { + Jump = (State->Flags.Sf != State->Flags.Of) || State->Flags.Zf; + break; + } + } + + if (Opcode & 1) + { + /* Invert the result */ + Jump = !Jump; + } + + if (Jump) + { + /* Move the instruction pointer */ + State->InstPtr.Long += Offset; + } + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeConditionalSet) +{ + BOOLEAN Value = FALSE; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + FAST486_MOD_REG_RM ModRegRm; + + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xF0) == 0x90); + + switch ((Opcode & 0x0F) >> 1) + { + /* SETO / SETNO */ + case 0: + { + Value = State->Flags.Of; + break; + } + + /* SETC / SETNC */ + case 1: + { + Value = State->Flags.Cf; + break; + } + + /* SETZ / SETNZ */ + case 2: + { + Value = State->Flags.Zf; + break; + } + + /* SETBE / SETNBE */ + case 3: + { + Value = State->Flags.Cf || State->Flags.Zf; + break; + } + + /* SETS / SETNS */ + case 4: + { + Value = State->Flags.Sf; + break; + } + + /* SETP / SETNP */ + case 5: + { + Value = State->Flags.Pf; + break; + } + + /* SETL / SETNL */ + case 6: + { + Value = State->Flags.Sf != State->Flags.Of; + break; + } + + /* SETLE / SETNLE */ + case 7: + { + Value = (State->Flags.Sf != State->Flags.Of) || State->Flags.Zf; + break; + } + } + + if (Opcode & 1) + { + /* Invert the result */ + Value = !Value; + } + + /* Write back the result */ + return Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Value); +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeXaddByte) +{ + UCHAR Source, Destination, Result; + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xC0); + + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (!Fast486ReadModrmByteOperands(State, + &ModRegRm, + &Source, + &Destination)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = Source + Destination; + + /* Update the flags */ + State->Flags.Cf = (Result < Source) && (Result < Destination); + State->Flags.Of = ((Source & SIGN_FLAG_BYTE) == (Destination & SIGN_FLAG_BYTE)) + && ((Source & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE)); + State->Flags.Af = ((((Source & 0x0F) + (Destination & 0x0F)) & 0x10) != 0); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write the sum to the destination */ + if (!Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Result)) + { + /* Exception occurred */ + return FALSE; + } + + /* Write the old value of the destination to the source */ + if (!Fast486WriteModrmByteOperands(State, &ModRegRm, TRUE, Destination)) + { + /* Exception occurred */ + return FALSE; + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeXadd) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xC1); + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_ADSIZE(AddressSize); + TOGGLE_OPSIZE(OperandSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Check the operand size */ + if (OperandSize) + { + ULONG Source, Destination, Result; + + if (!Fast486ReadModrmDwordOperands(State, + &ModRegRm, + &Source, + &Destination)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = Source + Destination; + + /* Update the flags */ + State->Flags.Cf = (Result < Source) && (Result < Destination); + State->Flags.Of = ((Source & SIGN_FLAG_LONG) == (Destination & SIGN_FLAG_LONG)) + && ((Source & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG)); + State->Flags.Af = ((((Source & 0x0F) + (Destination & 0x0F)) & 0x10) != 0); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write the old value of the destination to the source */ + if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, TRUE, Destination)) + { + /* Exception occurred */ + return FALSE; + } + + /* Write the sum to the destination */ + if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Result)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + USHORT Source, Destination, Result; + + if (!Fast486ReadModrmWordOperands(State, + &ModRegRm, + &Source, + &Destination)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = Source + Destination; + + /* Update the flags */ + State->Flags.Cf = (Result < Source) && (Result < Destination); + State->Flags.Of = ((Source & SIGN_FLAG_WORD) == (Destination & SIGN_FLAG_WORD)) + && ((Source & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD)); + State->Flags.Af = ((((Source & 0x0F) + (Destination & 0x0F)) & 0x10) != 0); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write the old value of the destination to the source */ + if (!Fast486WriteModrmWordOperands(State, &ModRegRm, TRUE, Destination)) + { + /* Exception occurred */ + return FALSE; + } + + /* Write the sum to the destination */ + if (!Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Result)) + { + /* Exception occurred */ + return FALSE; + } + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBswap) +{ + PUCHAR Pointer; + + NO_LOCK_PREFIX(); + + /* Get a pointer to the value */ + Pointer = (PUCHAR)&State->GeneralRegs[Opcode & 0x07].Long; + + /* Swap the byte order */ + SWAP(Pointer[0], Pointer[3]); + SWAP(Pointer[1], Pointer[2]); + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeExtended) +{ + UCHAR SecondOpcode; + + /* Fetch the second operation code */ + if (!Fast486FetchByte(State, &SecondOpcode)) + { + /* Exception occurred */ + return FALSE; + } + + if (Fast486ExtendedHandlers[SecondOpcode] != NULL) + { + /* Call the extended opcode handler */ + return Fast486ExtendedHandlers[SecondOpcode](State, SecondOpcode); + } + else + { + /* This is not a valid opcode */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } +} + diff --git a/lib/fast486/extraops.h b/lib/fast486/extraops.h new file mode 100644 index 00000000000..eab8e28fb94 --- /dev/null +++ b/lib/fast486/extraops.h @@ -0,0 +1,67 @@ +/* + * Fast486 386/486 CPU Emulation Library + * extraops.h + * + * Copyright (C) 2013 Aleksandar Andrejevic + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _EXTRAOPS_H_ +#define _EXTRAOPS_H_ + +#pragma once + +/* DEFINES ********************************************************************/ + +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLar); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLsl); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeClts); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeStoreControlReg); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeStoreDebugReg); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLoadControlReg); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLoadDebugReg); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushFs); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopFs); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBitTest); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeShld); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushGs); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopGs); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBts); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeShrd); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeImul); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeCmpXchgByte); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeCmpXchg); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLss); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBtr); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeLfsLgs); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovzxByte); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovzxWord); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBtc); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBsf); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBsr); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovsxByte); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeMovsxWord); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeConditionalJmp); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeConditionalSet); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeXaddByte); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeXadd); +FAST486_OPCODE_HANDLER(Fast486ExtOpcodeBswap); +FAST486_OPCODE_HANDLER(Fast486OpcodeExtended); + +#endif // _EXTRAOPS_H_ + +/* EOF */ + diff --git a/lib/fast486/fast486.c b/lib/fast486/fast486.c new file mode 100644 index 00000000000..c47814bb526 --- /dev/null +++ b/lib/fast486/fast486.c @@ -0,0 +1,463 @@ +/* + * Fast486 386/486 CPU Emulation Library + * fast486.c + * + * Copyright (C) 2013 Aleksandar Andrejevic + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* INCLUDES *******************************************************************/ + +#include + +// #define NDEBUG +#include + +#include +#include "common.h" +#include "opcodes.h" + +/* DEFINES ********************************************************************/ + +typedef enum +{ + FAST486_STEP_INTO, + FAST486_STEP_OVER, + FAST486_STEP_OUT, + FAST486_CONTINUE +} FAST486_EXEC_CMD; + +/* PRIVATE FUNCTIONS **********************************************************/ + +static +inline +VOID +NTAPI +Fast486ExecutionControl(PFAST486_STATE State, FAST486_EXEC_CMD Command) +{ + UCHAR Opcode; + INT ProcedureCallCount = 0; + + /* Main execution loop */ + do + { + /* Check if this is a new instruction */ + if (State->PrefixFlags == 0) State->SavedInstPtr = State->InstPtr; + + /* Perform an instruction fetch */ + if (!Fast486FetchByte(State, &Opcode)) + { + /* Exception occurred */ + State->PrefixFlags = 0; + continue; + } + + // TODO: Check for CALL/RET to update ProcedureCallCount. + + if (Fast486OpcodeHandlers[Opcode] != NULL) + { + /* Call the opcode handler */ + Fast486OpcodeHandlers[Opcode](State, Opcode); + } + else + { + /* This is not a valid opcode */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + } + + if (Fast486OpcodeHandlers[Opcode] == Fast486OpcodePrefix) + { + /* This is a prefix, go to the next instruction immediately */ + continue; + } + + /* A non-prefix opcode has been executed, reset the prefix flags */ + State->PrefixFlags = 0; + + /* + * Check if there is an interrupt to execute, or a hardware interrupt signal + * while interrupts are enabled. + */ + if (State->IntStatus == FAST486_INT_EXECUTE) + { + FAST486_IDT_ENTRY IdtEntry; + + /* Get the interrupt vector */ + if (Fast486GetIntVector(State, State->PendingIntNum, &IdtEntry)) + { + /* Perform the interrupt */ + Fast486InterruptInternal(State, + IdtEntry.Selector, + MAKELONG(IdtEntry.Offset, IdtEntry.OffsetHigh), + IdtEntry.Type); + + /* Restore the prefix flags, which would be set to OPSIZE for 32-bit real mode */ + State->PrefixFlags = 0; + } + + /* Clear the interrupt status */ + State->IntStatus = FAST486_INT_NONE; + } + else if (State->Flags.If + && (State->IntAckCallback != NULL) + && (State->IntStatus == FAST486_INT_SIGNAL)) + { + /* Acknowledge the interrupt to get the number */ + State->PendingIntNum = State->IntAckCallback(State); + + /* Set the interrupt status to execute on the next instruction */ + State->IntStatus = FAST486_INT_EXECUTE; + } + } + while ((Command == FAST486_CONTINUE) + || (Command == FAST486_STEP_OVER && ProcedureCallCount > 0) + || (Command == FAST486_STEP_OUT && ProcedureCallCount >= 0) + || (Fast486OpcodeHandlers[Opcode] == Fast486OpcodePrefix)); +} + +/* DEFAULT CALLBACKS **********************************************************/ + +static VOID +NTAPI +Fast486MemReadCallback(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size) +{ + UNREFERENCED_PARAMETER(State); + + RtlMoveMemory(Buffer, (PVOID)Address, Size); +} + +static VOID +NTAPI +Fast486MemWriteCallback(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size) +{ + UNREFERENCED_PARAMETER(State); + + RtlMoveMemory((PVOID)Address, Buffer, Size); +} + +static VOID +NTAPI +Fast486IoReadCallback(PFAST486_STATE State, ULONG Port, PVOID Buffer, ULONG DataCount, UCHAR DataSize) +{ + UNREFERENCED_PARAMETER(State); + UNREFERENCED_PARAMETER(Port); + UNREFERENCED_PARAMETER(Buffer); + UNREFERENCED_PARAMETER(DataCount); + UNREFERENCED_PARAMETER(DataSize); +} + +static VOID +NTAPI +Fast486IoWriteCallback(PFAST486_STATE State, ULONG Port, PVOID Buffer, ULONG DataCount, UCHAR DataSize) +{ + UNREFERENCED_PARAMETER(State); + UNREFERENCED_PARAMETER(Port); + UNREFERENCED_PARAMETER(Buffer); + UNREFERENCED_PARAMETER(DataCount); + UNREFERENCED_PARAMETER(DataSize); +} + +static VOID +NTAPI +Fast486IdleCallback(PFAST486_STATE State) +{ + UNREFERENCED_PARAMETER(State); +} + +static VOID +NTAPI +Fast486BopCallback(PFAST486_STATE State, UCHAR BopCode) +{ + UNREFERENCED_PARAMETER(State); + UNREFERENCED_PARAMETER(BopCode); +} + +static UCHAR +NTAPI +Fast486IntAckCallback(PFAST486_STATE State) +{ + UNREFERENCED_PARAMETER(State); + + /* Return something... */ + return 0; +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID +NTAPI +Fast486Initialize(PFAST486_STATE State, + FAST486_MEM_READ_PROC MemReadCallback, + FAST486_MEM_WRITE_PROC MemWriteCallback, + FAST486_IO_READ_PROC IoReadCallback, + FAST486_IO_WRITE_PROC IoWriteCallback, + FAST486_IDLE_PROC IdleCallback, + FAST486_BOP_PROC BopCallback, + FAST486_INT_ACK_PROC IntAckCallback, + PULONG Tlb) +{ + /* Set the callbacks (or use default ones if some are NULL) */ + State->MemReadCallback = (MemReadCallback ? MemReadCallback : Fast486MemReadCallback ); + State->MemWriteCallback = (MemWriteCallback ? MemWriteCallback : Fast486MemWriteCallback); + State->IoReadCallback = (IoReadCallback ? IoReadCallback : Fast486IoReadCallback ); + State->IoWriteCallback = (IoWriteCallback ? IoWriteCallback : Fast486IoWriteCallback ); + State->IdleCallback = (IdleCallback ? IdleCallback : Fast486IdleCallback ); + State->BopCallback = (BopCallback ? BopCallback : Fast486BopCallback ); + State->IntAckCallback = (IntAckCallback ? IntAckCallback : Fast486IntAckCallback ); + + /* Set the TLB (if given) */ + State->Tlb = Tlb; + + /* Reset the CPU */ + Fast486Reset(State); +} + +VOID +NTAPI +Fast486Reset(PFAST486_STATE State) +{ + FAST486_SEG_REGS i; + + FAST486_MEM_READ_PROC MemReadCallback = State->MemReadCallback; + FAST486_MEM_WRITE_PROC MemWriteCallback = State->MemWriteCallback; + FAST486_IO_READ_PROC IoReadCallback = State->IoReadCallback; + FAST486_IO_WRITE_PROC IoWriteCallback = State->IoWriteCallback; + FAST486_IDLE_PROC IdleCallback = State->IdleCallback; + FAST486_BOP_PROC BopCallback = State->BopCallback; + FAST486_INT_ACK_PROC IntAckCallback = State->IntAckCallback; + PULONG Tlb = State->Tlb; + + /* Clear the entire structure */ + RtlZeroMemory(State, sizeof(*State)); + + /* Initialize the registers */ + State->Flags.AlwaysSet = 1; + State->InstPtr.LowWord = 0xFFF0; + + /* Set the CPL to 0 */ + State->Cpl = 0; + + /* Initialize segments */ + for (i = 0; i < FAST486_NUM_SEG_REGS; i++) + { + State->SegmentRegs[i].Selector = 0; + State->SegmentRegs[i].Base = 0; + State->SegmentRegs[i].Limit = 0xFFFF; + State->SegmentRegs[i].Present = TRUE; + State->SegmentRegs[i].ReadWrite = TRUE; + State->SegmentRegs[i].Executable = FALSE; + State->SegmentRegs[i].DirConf = FALSE; + State->SegmentRegs[i].SystemType = 1; // Segment descriptor + State->SegmentRegs[i].Dpl = 0; + State->SegmentRegs[i].Size = FALSE; // 16-bit + } + + /* Initialize the code segment */ + State->SegmentRegs[FAST486_REG_CS].Executable = TRUE; + State->SegmentRegs[FAST486_REG_CS].Selector = 0xF000; + State->SegmentRegs[FAST486_REG_CS].Base = 0xFFFF0000; + + /* Initialize the IDT */ + State->Idtr.Size = 0x3FF; + State->Idtr.Address = 0; + +#ifndef FAST486_NO_FPU + /* Initialize CR0 */ + State->ControlRegisters[FAST486_REG_CR0] |= FAST486_CR0_ET; +#endif + + /* Restore the callbacks and TLB */ + State->MemReadCallback = MemReadCallback; + State->MemWriteCallback = MemWriteCallback; + State->IoReadCallback = IoReadCallback; + State->IoWriteCallback = IoWriteCallback; + State->IdleCallback = IdleCallback; + State->BopCallback = BopCallback; + State->IntAckCallback = IntAckCallback; + State->Tlb = Tlb; +} + +VOID +NTAPI +Fast486DumpState(PFAST486_STATE State) +{ + DPRINT1("\nCPU currently executing in %s mode at %04X:%08X\n", + (State->ControlRegisters[0] & FAST486_CR0_PE) ? "protected" : "real", + State->SegmentRegs[FAST486_REG_CS].Selector, + State->InstPtr.Long); + DPRINT1("\nGeneral purpose registers:\n" + "EAX = %08X\tECX = %08X\tEDX = %08X\tEBX = %08X\n" + "ESP = %08X\tEBP = %08X\tESI = %08X\tEDI = %08X\n", + State->GeneralRegs[FAST486_REG_EAX].Long, + State->GeneralRegs[FAST486_REG_ECX].Long, + State->GeneralRegs[FAST486_REG_EDX].Long, + State->GeneralRegs[FAST486_REG_EBX].Long, + State->GeneralRegs[FAST486_REG_ESP].Long, + State->GeneralRegs[FAST486_REG_EBP].Long, + State->GeneralRegs[FAST486_REG_ESI].Long, + State->GeneralRegs[FAST486_REG_EDI].Long); + DPRINT1("\nSegment registers:\n" + "ES = %04X (Base: %08X, Limit: %08X, Dpl: %u)\n" + "CS = %04X (Base: %08X, Limit: %08X, Dpl: %u)\n" + "SS = %04X (Base: %08X, Limit: %08X, Dpl: %u)\n" + "DS = %04X (Base: %08X, Limit: %08X, Dpl: %u)\n" + "FS = %04X (Base: %08X, Limit: %08X, Dpl: %u)\n" + "GS = %04X (Base: %08X, Limit: %08X, Dpl: %u)\n", + State->SegmentRegs[FAST486_REG_ES].Selector, + State->SegmentRegs[FAST486_REG_ES].Base, + State->SegmentRegs[FAST486_REG_ES].Limit, + State->SegmentRegs[FAST486_REG_ES].Dpl, + State->SegmentRegs[FAST486_REG_CS].Selector, + State->SegmentRegs[FAST486_REG_CS].Base, + State->SegmentRegs[FAST486_REG_CS].Limit, + State->SegmentRegs[FAST486_REG_CS].Dpl, + State->SegmentRegs[FAST486_REG_SS].Selector, + State->SegmentRegs[FAST486_REG_SS].Base, + State->SegmentRegs[FAST486_REG_SS].Limit, + State->SegmentRegs[FAST486_REG_SS].Dpl, + State->SegmentRegs[FAST486_REG_DS].Selector, + State->SegmentRegs[FAST486_REG_DS].Base, + State->SegmentRegs[FAST486_REG_DS].Limit, + State->SegmentRegs[FAST486_REG_DS].Dpl, + State->SegmentRegs[FAST486_REG_FS].Selector, + State->SegmentRegs[FAST486_REG_FS].Base, + State->SegmentRegs[FAST486_REG_FS].Limit, + State->SegmentRegs[FAST486_REG_FS].Dpl, + State->SegmentRegs[FAST486_REG_GS].Selector, + State->SegmentRegs[FAST486_REG_GS].Base, + State->SegmentRegs[FAST486_REG_GS].Limit, + State->SegmentRegs[FAST486_REG_GS].Dpl); + DPRINT1("\nFlags: %08X (%s %s %s %s %s %s %s %s %s %s %s %s) Iopl: %u\n", + State->Flags.Long, + State->Flags.Cf ? "CF" : "cf", + State->Flags.Pf ? "PF" : "pf", + State->Flags.Af ? "AF" : "af", + State->Flags.Zf ? "ZF" : "zf", + State->Flags.Sf ? "SF" : "sf", + State->Flags.Tf ? "TF" : "tf", + State->Flags.If ? "IF" : "if", + State->Flags.Df ? "DF" : "df", + State->Flags.Of ? "OF" : "of", + State->Flags.Nt ? "NT" : "nt", + State->Flags.Rf ? "RF" : "rf", + State->Flags.Vm ? "VM" : "vm", + State->Flags.Iopl); + DPRINT1("\nControl Registers:\n" + "CR0 = %08X\tCR2 = %08X\tCR3 = %08X\n", + State->ControlRegisters[FAST486_REG_CR0], + State->ControlRegisters[FAST486_REG_CR2], + State->ControlRegisters[FAST486_REG_CR3]); + DPRINT1("\nDebug Registers:\n" + "DR0 = %08X\tDR1 = %08X\tDR2 = %08X\n" + "DR3 = %08X\tDR4 = %08X\tDR5 = %08X\n", + State->DebugRegisters[FAST486_REG_DR0], + State->DebugRegisters[FAST486_REG_DR1], + State->DebugRegisters[FAST486_REG_DR2], + State->DebugRegisters[FAST486_REG_DR3], + State->DebugRegisters[FAST486_REG_DR4], + State->DebugRegisters[FAST486_REG_DR5]); +} + +VOID +NTAPI +Fast486Continue(PFAST486_STATE State) +{ + /* Call the internal function */ + Fast486ExecutionControl(State, FAST486_CONTINUE); +} + +VOID +NTAPI +Fast486StepInto(PFAST486_STATE State) +{ + /* Call the internal function */ + Fast486ExecutionControl(State, FAST486_STEP_INTO); +} + +VOID +NTAPI +Fast486StepOver(PFAST486_STATE State) +{ + /* Call the internal function */ + Fast486ExecutionControl(State, FAST486_STEP_OVER); +} + +VOID +NTAPI +Fast486StepOut(PFAST486_STATE State) +{ + /* Call the internal function */ + Fast486ExecutionControl(State, FAST486_STEP_OUT); +} + +VOID +NTAPI +Fast486Interrupt(PFAST486_STATE State, UCHAR Number) +{ + /* Set the interrupt status and the number */ + State->IntStatus = FAST486_INT_EXECUTE; + State->PendingIntNum = Number; +} + +VOID +NTAPI +Fast486InterruptSignal(PFAST486_STATE State) +{ + /* Set the interrupt status */ + State->IntStatus = FAST486_INT_SIGNAL; +} + +VOID +NTAPI +Fast486ExecuteAt(PFAST486_STATE State, USHORT Segment, ULONG Offset) +{ + /* Load the new CS */ + if (!Fast486LoadSegment(State, FAST486_REG_CS, Segment)) + { + /* An exception occurred, let the handler execute instead */ + return; + } + + /* Set the new IP */ + State->InstPtr.Long = Offset; +} + +VOID +NTAPI +Fast486SetStack(PFAST486_STATE State, USHORT Segment, ULONG Offset) +{ + /* Load the new SS */ + if (!Fast486LoadSegment(State, FAST486_REG_SS, Segment)) + { + /* An exception occurred, let the handler execute instead */ + return; + } + + /* Set the new SP */ + State->GeneralRegs[FAST486_REG_ESP].Long = Offset; +} + +VOID +NTAPI +Fast486SetSegment(PFAST486_STATE State, + FAST486_SEG_REGS Segment, + USHORT Selector) +{ + /* Call the internal function */ + Fast486LoadSegment(State, Segment, Selector); +} + +/* EOF */ diff --git a/lib/fast486/fpu.c b/lib/fast486/fpu.c new file mode 100644 index 00000000000..18f4a892afc --- /dev/null +++ b/lib/fast486/fpu.c @@ -0,0 +1,236 @@ +/* + * Fast486 386/486 CPU Emulation Library + * fpu.c + * + * Copyright (C) 2013 Aleksandar Andrejevic + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* INCLUDES *******************************************************************/ + +#include + +// #define NDEBUG +#include + +#include +#include "common.h" +#include "opcodes.h" +#include "fpu.h" + +/* PUBLIC FUNCTIONS ***********************************************************/ + +FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + FPU_CHECK(); + +#ifndef FAST486_NO_FPU + // TODO: NOT IMPLEMENTED + UNIMPLEMENTED; + + return FALSE; +#else + /* Do nothing */ + return TRUE; +#endif +} + +FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD9) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + FPU_CHECK(); + +#ifndef FAST486_NO_FPU + // TODO: NOT IMPLEMENTED + UNIMPLEMENTED; + + return FALSE; +#else + /* Do nothing */ + return TRUE; +#endif +} + +FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDA) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + FPU_CHECK(); + +#ifndef FAST486_NO_FPU + // TODO: NOT IMPLEMENTED + UNIMPLEMENTED; + + return FALSE; +#else + /* Do nothing */ + return TRUE; +#endif +} + +FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDB) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + FPU_CHECK(); + +#ifndef FAST486_NO_FPU + // TODO: NOT IMPLEMENTED + UNIMPLEMENTED; + + return FALSE; +#else + /* Do nothing */ + return TRUE; +#endif +} + +FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDC) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + FPU_CHECK(); + +#ifndef FAST486_NO_FPU + // TODO: NOT IMPLEMENTED + UNIMPLEMENTED; + + return FALSE; +#else + /* Do nothing */ + return TRUE; +#endif +} + +FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDD) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + FPU_CHECK(); + +#ifndef FAST486_NO_FPU + // TODO: NOT IMPLEMENTED + UNIMPLEMENTED; + + return FALSE; +#else + /* Do nothing */ + return TRUE; +#endif +} + +FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDE) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + FPU_CHECK(); + +#ifndef FAST486_NO_FPU + // TODO: NOT IMPLEMENTED + UNIMPLEMENTED; + + return FALSE; +#else + /* Do nothing */ + return TRUE; +#endif +} + +FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDF) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + FPU_CHECK(); + +#ifndef FAST486_NO_FPU + // TODO: NOT IMPLEMENTED + UNIMPLEMENTED; + + return FALSE; +#else + /* Do nothing */ + return TRUE; +#endif +} + +/* EOF */ diff --git a/lib/fast486/fpu.h b/lib/fast486/fpu.h new file mode 100644 index 00000000000..63128a42599 --- /dev/null +++ b/lib/fast486/fpu.h @@ -0,0 +1,62 @@ +/* + * Fast486 386/486 CPU Emulation Library + * fpu.h + * + * Copyright (C) 2013 Aleksandar Andrejevic + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _FPU_H_ +#define _FPU_H_ + +#pragma once + +/* DEFINES ********************************************************************/ + +#define FPU_CHECK() if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_EM) \ + { \ + Fast486Exception(State, FAST486_EXCEPTION_NM); \ + return FALSE; \ + } +#define FPU_ST(i) State->FpuRegisters[(State->FpuStatus.Top + (i)) % FAST486_NUM_FPU_REGS] + +enum +{ + FPU_SINGLE_PRECISION = 0, + FPU_DOUBLE_PRECISION = 2, + FPU_DOUBLE_EXT_PRECISION = 3 +}; + +enum +{ + FPU_TAG_VALID = 0, + FPU_TAG_ZERO = 1, + FPU_TAG_SPECIAL = 2, + FPU_TAG_EMPTY = 3 +}; + +FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8); +FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD9); +FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDA); +FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDB); +FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDC); +FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDD); +FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDE); +FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDF); + +#endif // _FPU_H_ + +/* EOF */ diff --git a/lib/fast486/opcodes.c b/lib/fast486/opcodes.c new file mode 100644 index 00000000000..3dffdaacc18 --- /dev/null +++ b/lib/fast486/opcodes.c @@ -0,0 +1,6312 @@ +/* + * Fast486 386/486 CPU Emulation Library + * opcodes.c + * + * Copyright (C) 2013 Aleksandar Andrejevic + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* INCLUDES *******************************************************************/ + +#include + +// #define NDEBUG +#include + +#include +#include "opcodes.h" +#include "opgroups.h" +#include "extraops.h" +#include "common.h" +#include "fpu.h" + +/* PUBLIC VARIABLES ***********************************************************/ + +FAST486_OPCODE_HANDLER_PROC +Fast486OpcodeHandlers[FAST486_NUM_OPCODE_HANDLERS] = +{ + Fast486OpcodeAddByteModrm, + Fast486OpcodeAddModrm, + Fast486OpcodeAddByteModrm, + Fast486OpcodeAddModrm, + Fast486OpcodeAddAl, + Fast486OpcodeAddEax, + Fast486OpcodePushEs, + Fast486OpcodePopEs, + Fast486OpcodeOrByteModrm, + Fast486OpcodeOrModrm, + Fast486OpcodeOrByteModrm, + Fast486OpcodeOrModrm, + Fast486OpcodeOrAl, + Fast486OpcodeOrEax, + Fast486OpcodePushCs, + Fast486OpcodeExtended, + Fast486OpcodeAdcByteModrm, + Fast486OpcodeAdcModrm, + Fast486OpcodeAdcByteModrm, + Fast486OpcodeAdcModrm, + Fast486OpcodeAdcAl, + Fast486OpcodeAdcEax, + Fast486OpcodePushSs, + Fast486OpcodePopSs, + Fast486OpcodeSbbByteModrm, + Fast486OpcodeSbbModrm, + Fast486OpcodeSbbByteModrm, + Fast486OpcodeSbbModrm, + Fast486OpcodeSbbAl, + Fast486OpcodeSbbEax, + Fast486OpcodePushDs, + Fast486OpcodePopDs, + Fast486OpcodeAndByteModrm, + Fast486OpcodeAndModrm, + Fast486OpcodeAndByteModrm, + Fast486OpcodeAndModrm, + Fast486OpcodeAndAl, + Fast486OpcodeAndEax, + Fast486OpcodePrefix, + Fast486OpcodeDaa, + Fast486OpcodeCmpSubByteModrm, + Fast486OpcodeCmpSubModrm, + Fast486OpcodeCmpSubByteModrm, + Fast486OpcodeCmpSubModrm, + Fast486OpcodeCmpSubAl, + Fast486OpcodeCmpSubEax, + Fast486OpcodePrefix, + Fast486OpcodeDas, + Fast486OpcodeXorByteModrm, + Fast486OpcodeXorModrm, + Fast486OpcodeXorByteModrm, + Fast486OpcodeXorModrm, + Fast486OpcodeXorAl, + Fast486OpcodeXorEax, + Fast486OpcodePrefix, + Fast486OpcodeAaa, + Fast486OpcodeCmpSubByteModrm, + Fast486OpcodeCmpSubModrm, + Fast486OpcodeCmpSubByteModrm, + Fast486OpcodeCmpSubModrm, + Fast486OpcodeCmpSubAl, + Fast486OpcodeCmpSubEax, + Fast486OpcodePrefix, + Fast486OpcodeAas, + Fast486OpcodeIncrement, + Fast486OpcodeIncrement, + Fast486OpcodeIncrement, + Fast486OpcodeIncrement, + Fast486OpcodeIncrement, + Fast486OpcodeIncrement, + Fast486OpcodeIncrement, + Fast486OpcodeIncrement, + Fast486OpcodeDecrement, + Fast486OpcodeDecrement, + Fast486OpcodeDecrement, + Fast486OpcodeDecrement, + Fast486OpcodeDecrement, + Fast486OpcodeDecrement, + Fast486OpcodeDecrement, + Fast486OpcodeDecrement, + Fast486OpcodePushReg, + Fast486OpcodePushReg, + Fast486OpcodePushReg, + Fast486OpcodePushReg, + Fast486OpcodePushReg, + Fast486OpcodePushReg, + Fast486OpcodePushReg, + Fast486OpcodePushReg, + Fast486OpcodePopReg, + Fast486OpcodePopReg, + Fast486OpcodePopReg, + Fast486OpcodePopReg, + Fast486OpcodePopReg, + Fast486OpcodePopReg, + Fast486OpcodePopReg, + Fast486OpcodePopReg, + Fast486OpcodePushAll, + Fast486OpcodePopAll, + Fast486OpcodeBound, + Fast486OpcodeArpl, + Fast486OpcodePrefix, + Fast486OpcodePrefix, + Fast486OpcodePrefix, + Fast486OpcodePrefix, + Fast486OpcodePushImm, + Fast486OpcodeImulModrmImm, + Fast486OpcodePushByteImm, + Fast486OpcodeImulModrmImm, + Fast486OpcodeIns, + Fast486OpcodeIns, + Fast486OpcodeOuts, + Fast486OpcodeOuts, + Fast486OpcodeShortConditionalJmp, + Fast486OpcodeShortConditionalJmp, + Fast486OpcodeShortConditionalJmp, + Fast486OpcodeShortConditionalJmp, + Fast486OpcodeShortConditionalJmp, + Fast486OpcodeShortConditionalJmp, + Fast486OpcodeShortConditionalJmp, + Fast486OpcodeShortConditionalJmp, + Fast486OpcodeShortConditionalJmp, + Fast486OpcodeShortConditionalJmp, + Fast486OpcodeShortConditionalJmp, + Fast486OpcodeShortConditionalJmp, + Fast486OpcodeShortConditionalJmp, + Fast486OpcodeShortConditionalJmp, + Fast486OpcodeShortConditionalJmp, + Fast486OpcodeShortConditionalJmp, + Fast486OpcodeGroup8082, + Fast486OpcodeGroup81, + Fast486OpcodeGroup8082, + Fast486OpcodeGroup83, + Fast486OpcodeTestByteModrm, + Fast486OpcodeTestModrm, + Fast486OpcodeXchgByteModrm, + Fast486OpcodeXchgModrm, + Fast486OpcodeMovByteModrm, + Fast486OpcodeMovModrm, + Fast486OpcodeMovByteModrm, + Fast486OpcodeMovModrm, + Fast486OpcodeMovStoreSeg, + Fast486OpcodeLea, + Fast486OpcodeMovLoadSeg, + Fast486OpcodeGroup8F, + Fast486OpcodeNop, + Fast486OpcodeExchangeEax, + Fast486OpcodeExchangeEax, + Fast486OpcodeExchangeEax, + Fast486OpcodeExchangeEax, + Fast486OpcodeExchangeEax, + Fast486OpcodeExchangeEax, + Fast486OpcodeExchangeEax, + Fast486OpcodeCwde, + Fast486OpcodeCdq, + Fast486OpcodeCallAbs, + Fast486OpcodeWait, + Fast486OpcodePushFlags, + Fast486OpcodePopFlags, + Fast486OpcodeSahf, + Fast486OpcodeLahf, + Fast486OpcodeMovAlOffset, + Fast486OpcodeMovEaxOffset, + Fast486OpcodeMovOffsetAl, + Fast486OpcodeMovOffsetEax, + Fast486OpcodeMovs, + Fast486OpcodeMovs, + Fast486OpcodeCmps, + Fast486OpcodeCmps, + Fast486OpcodeTestAl, + Fast486OpcodeTestEax, + Fast486OpcodeStos, + Fast486OpcodeStos, + Fast486OpcodeLods, + Fast486OpcodeLods, + Fast486OpcodeScas, + Fast486OpcodeScas, + Fast486OpcodeMovByteRegImm, + Fast486OpcodeMovByteRegImm, + Fast486OpcodeMovByteRegImm, + Fast486OpcodeMovByteRegImm, + Fast486OpcodeMovByteRegImm, + Fast486OpcodeMovByteRegImm, + Fast486OpcodeMovByteRegImm, + Fast486OpcodeMovByteRegImm, + Fast486OpcodeMovRegImm, + Fast486OpcodeMovRegImm, + Fast486OpcodeMovRegImm, + Fast486OpcodeMovRegImm, + Fast486OpcodeMovRegImm, + Fast486OpcodeMovRegImm, + Fast486OpcodeMovRegImm, + Fast486OpcodeMovRegImm, + Fast486OpcodeGroupC0, + Fast486OpcodeGroupC1, + Fast486OpcodeRet, + Fast486OpcodeRet, + Fast486OpcodeLdsLes, + Fast486OpcodeLdsLes, + Fast486OpcodeGroupC6, + Fast486OpcodeGroupC7, + Fast486OpcodeEnter, + Fast486OpcodeLeave, + Fast486OpcodeRetFar, + Fast486OpcodeRetFar, + Fast486OpcodeInt, + Fast486OpcodeInt, + Fast486OpcodeInt, + Fast486OpcodeIret, + Fast486OpcodeGroupD0, + Fast486OpcodeGroupD1, + Fast486OpcodeGroupD2, + Fast486OpcodeGroupD3, + Fast486OpcodeAam, + Fast486OpcodeAad, + Fast486OpcodeSalc, + Fast486OpcodeXlat, + Fast486FpuOpcodeD8, + Fast486FpuOpcodeD9, + Fast486FpuOpcodeDA, + Fast486FpuOpcodeDB, + Fast486FpuOpcodeDC, + Fast486FpuOpcodeDD, + Fast486FpuOpcodeDE, + Fast486FpuOpcodeDF, + Fast486OpcodeLoop, + Fast486OpcodeLoop, + Fast486OpcodeLoop, + Fast486OpcodeJecxz, + Fast486OpcodeInByte, + Fast486OpcodeIn, + Fast486OpcodeOutByte, + Fast486OpcodeOut, + Fast486OpcodeCall, + Fast486OpcodeJmp, + Fast486OpcodeJmpAbs, + Fast486OpcodeShortJump, + Fast486OpcodeInByte, + Fast486OpcodeIn, + Fast486OpcodeOutByte, + Fast486OpcodeOut, + Fast486OpcodePrefix, + NULL, // Invalid + Fast486OpcodePrefix, + Fast486OpcodePrefix, + Fast486OpcodeHalt, + Fast486OpcodeComplCarry, + Fast486OpcodeGroupF6, + Fast486OpcodeGroupF7, + Fast486OpcodeClearCarry, + Fast486OpcodeSetCarry, + Fast486OpcodeClearInt, + Fast486OpcodeSetInt, + Fast486OpcodeClearDir, + Fast486OpcodeSetDir, + Fast486OpcodeGroupFE, + Fast486OpcodeGroupFF, +}; + +/* PUBLIC FUNCTIONS ***********************************************************/ + +FAST486_OPCODE_HANDLER(Fast486OpcodePrefix) +{ + BOOLEAN Valid = FALSE; + + switch (Opcode) + { + /* ES: */ + case 0x26: + { + if (!(State->PrefixFlags & FAST486_PREFIX_SEG)) + { + State->PrefixFlags |= FAST486_PREFIX_SEG; + State->SegmentOverride = FAST486_REG_ES; + Valid = TRUE; + } + + break; + } + + /* CS: */ + case 0x2E: + { + if (!(State->PrefixFlags & FAST486_PREFIX_SEG)) + { + State->PrefixFlags |= FAST486_PREFIX_SEG; + State->SegmentOverride = FAST486_REG_CS; + Valid = TRUE; + } + + break; + } + + /* SS: */ + case 0x36: + { + if (!(State->PrefixFlags & FAST486_PREFIX_SEG)) + { + State->PrefixFlags |= FAST486_PREFIX_SEG; + State->SegmentOverride = FAST486_REG_SS; + Valid = TRUE; + } + + break; + } + + /* DS: */ + case 0x3E: + { + if (!(State->PrefixFlags & FAST486_PREFIX_SEG)) + { + State->PrefixFlags |= FAST486_PREFIX_SEG; + State->SegmentOverride = FAST486_REG_DS; + Valid = TRUE; + } + + break; + } + + /* FS: */ + case 0x64: + { + if (!(State->PrefixFlags & FAST486_PREFIX_SEG)) + { + State->PrefixFlags |= FAST486_PREFIX_SEG; + State->SegmentOverride = FAST486_REG_FS; + Valid = TRUE; + } + + break; + } + + /* GS: */ + case 0x65: + { + if (!(State->PrefixFlags & FAST486_PREFIX_SEG)) + { + State->PrefixFlags |= FAST486_PREFIX_SEG; + State->SegmentOverride = FAST486_REG_GS; + Valid = TRUE; + } + + break; + } + + /* OPSIZE */ + case 0x66: + { + if (!(State->PrefixFlags & FAST486_PREFIX_OPSIZE)) + { + State->PrefixFlags |= FAST486_PREFIX_OPSIZE; + Valid = TRUE; + } + + break; + } + + /* ADSIZE */ + case 0x67: + { + if (!(State->PrefixFlags & FAST486_PREFIX_ADSIZE)) + { + State->PrefixFlags |= FAST486_PREFIX_ADSIZE; + Valid = TRUE; + } + break; + } + + /* LOCK */ + case 0xF0: + { + if (!(State->PrefixFlags & FAST486_PREFIX_LOCK)) + { + State->PrefixFlags |= FAST486_PREFIX_LOCK; + Valid = TRUE; + } + + break; + } + + /* REPNZ */ + case 0xF2: + { + /* Mutually exclusive with REP */ + if (!(State->PrefixFlags + & (FAST486_PREFIX_REPNZ | FAST486_PREFIX_REP))) + { + State->PrefixFlags |= FAST486_PREFIX_REPNZ; + Valid = TRUE; + } + + break; + } + + /* REP / REPZ */ + case 0xF3: + { + /* Mutually exclusive with REPNZ */ + if (!(State->PrefixFlags + & (FAST486_PREFIX_REPNZ | FAST486_PREFIX_REP))) + { + State->PrefixFlags |= FAST486_PREFIX_REP; + Valid = TRUE; + } + + break; + } + } + + if (!Valid) + { + /* Clear all prefixes */ + State->PrefixFlags = 0; + + /* Throw an exception */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeIncrement) +{ + ULONG Value; + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_OPSIZE(Size); + NO_LOCK_PREFIX(); + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xF8) == 0x40); + + if (Size) + { + Value = ++State->GeneralRegs[Opcode & 0x07].Long; + + State->Flags.Of = (Value == SIGN_FLAG_LONG); + State->Flags.Sf = ((Value & SIGN_FLAG_LONG) != 0); + } + else + { + Value = ++State->GeneralRegs[Opcode & 0x07].LowWord; + + State->Flags.Of = (Value == SIGN_FLAG_WORD); + State->Flags.Sf = ((Value & SIGN_FLAG_WORD) != 0); + } + + State->Flags.Zf = (Value == 0); + State->Flags.Af = ((Value & 0x0F) == 0); + State->Flags.Pf = Fast486CalculateParity(LOBYTE(Value)); + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeDecrement) +{ + ULONG Value; + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_OPSIZE(Size); + NO_LOCK_PREFIX(); + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xF8) == 0x48); + + if (Size) + { + Value = --State->GeneralRegs[Opcode & 0x07].Long; + + State->Flags.Of = (Value == (SIGN_FLAG_LONG - 1)); + State->Flags.Sf = ((Value & SIGN_FLAG_LONG) != 0); + } + else + { + Value = --State->GeneralRegs[Opcode & 0x07].LowWord; + + State->Flags.Of = (Value == (SIGN_FLAG_WORD - 1)); + State->Flags.Sf = ((Value & SIGN_FLAG_WORD) != 0); + } + + State->Flags.Zf = (Value == 0); + State->Flags.Af = ((Value & 0x0F) == 0x0F); + State->Flags.Pf = Fast486CalculateParity(LOBYTE(Value)); + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodePushReg) +{ + NO_LOCK_PREFIX(); + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xF8) == 0x50); + + /* Call the internal function */ + return Fast486StackPush(State, State->GeneralRegs[Opcode & 0x07].Long); +} + +FAST486_OPCODE_HANDLER(Fast486OpcodePopReg) +{ + ULONG Value; + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_OPSIZE(Size); + NO_LOCK_PREFIX(); + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xF8) == 0x58); + + /* Call the internal function */ + if (!Fast486StackPop(State, &Value)) return FALSE; + + /* Store the value */ + if (Size) State->GeneralRegs[Opcode & 0x07].Long = Value; + else State->GeneralRegs[Opcode & 0x07].LowWord = Value; + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeNop) +{ + if (State->PrefixFlags & FAST486_PREFIX_REP) + { + /* Idle cycle */ + State->IdleCallback(State); + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeExchangeEax) +{ + INT Reg = Opcode & 0x07; + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_OPSIZE(Size); + NO_LOCK_PREFIX(); + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xF8) == 0x90); + + /* Exchange the values */ + if (Size) + { + ULONG Value; + + Value = State->GeneralRegs[Reg].Long; + State->GeneralRegs[Reg].Long = State->GeneralRegs[FAST486_REG_EAX].Long; + State->GeneralRegs[FAST486_REG_EAX].Long = Value; + } + else + { + USHORT Value; + + Value = State->GeneralRegs[Reg].LowWord; + State->GeneralRegs[Reg].LowWord = State->GeneralRegs[FAST486_REG_EAX].LowWord; + State->GeneralRegs[FAST486_REG_EAX].LowWord = Value; + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeShortConditionalJmp) +{ + BOOLEAN Jump = FALSE; + CHAR Offset = 0; + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xF0) == 0x70); + + TOGGLE_OPSIZE(Size); + + /* Fetch the offset */ + if (!Fast486FetchByte(State, (PUCHAR)&Offset)) + { + /* An exception occurred */ + return FALSE; + } + + switch ((Opcode & 0x0F) >> 1) + { + /* JO / JNO */ + case 0: + { + Jump = State->Flags.Of; + break; + } + + /* JC / JNC */ + case 1: + { + Jump = State->Flags.Cf; + break; + } + + /* JZ / JNZ */ + case 2: + { + Jump = State->Flags.Zf; + break; + } + + /* JBE / JNBE */ + case 3: + { + Jump = State->Flags.Cf || State->Flags.Zf; + break; + } + + /* JS / JNS */ + case 4: + { + Jump = State->Flags.Sf; + break; + } + + /* JP / JNP */ + case 5: + { + Jump = State->Flags.Pf; + break; + } + + /* JL / JNL */ + case 6: + { + Jump = State->Flags.Sf != State->Flags.Of; + break; + } + + /* JLE / JNLE */ + case 7: + { + Jump = (State->Flags.Sf != State->Flags.Of) || State->Flags.Zf; + break; + } + } + + if (Opcode & 1) + { + /* Invert the result */ + Jump = !Jump; + } + + if (Jump) + { + /* Move the instruction pointer */ + State->InstPtr.Long += Offset; + + if (!Size) + { + /* Clear the top half of EIP */ + State->InstPtr.Long &= 0xFFFF; + } + } + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeClearCarry) +{ + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xF8); + + /* No prefixes allowed */ + if (State->PrefixFlags) + { + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + /* Clear CF and return success */ + State->Flags.Cf = FALSE; + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeSetCarry) +{ + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xF9); + + /* No prefixes allowed */ + if (State->PrefixFlags) + { + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + /* Set CF and return success*/ + State->Flags.Cf = TRUE; + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeComplCarry) +{ + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xF5); + + /* No prefixes allowed */ + if (State->PrefixFlags) + { + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + /* Toggle CF and return success */ + State->Flags.Cf = !State->Flags.Cf; + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeClearInt) +{ + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xFA); + + /* No prefixes allowed */ + if (State->PrefixFlags) + { + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + /* Check for protected mode */ + if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) + { + /* Check IOPL */ + if (State->Flags.Iopl >= State->SegmentRegs[FAST486_REG_CS].Dpl) + { + /* Clear the interrupt flag */ + State->Flags.If = FALSE; + } + else + { + /* General Protection Fault */ + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + } + else + { + /* Just clear the interrupt flag */ + State->Flags.If = FALSE; + } + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeSetInt) +{ + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xFB); + + /* No prefixes allowed */ + if (State->PrefixFlags) + { + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + /* Check for protected mode */ + if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) + { + /* Check IOPL */ + if (State->Flags.Iopl >= State->SegmentRegs[FAST486_REG_CS].Dpl) + { + /* Set the interrupt flag */ + State->Flags.If = TRUE; + } + else + { + /* General Protection Fault */ + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + } + else + { + /* Just set the interrupt flag */ + State->Flags.If = TRUE; + } + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeClearDir) +{ + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xFC); + + /* No prefixes allowed */ + if (State->PrefixFlags) + { + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + /* Clear DF and return success */ + State->Flags.Df = FALSE; + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeSetDir) +{ + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xFD); + + /* No prefixes allowed */ + if (State->PrefixFlags) + { + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + /* Set DF and return success*/ + State->Flags.Df = TRUE; + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeHalt) +{ + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xF4); + + /* No prefixes allowed */ + if (State->PrefixFlags) + { + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + /* Privileged instructions can only be executed under CPL = 0 */ + if (State->SegmentRegs[FAST486_REG_CS].Dpl != 0) + { + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + + /* Halt */ + // TODO: Halt the CPU until an interrupt occurs, using IdleCallback if needed. + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeInByte) +{ + UCHAR Data; + ULONG Port; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xF7) == 0xE4); + + if (Opcode == 0xE4) + { + /* Fetch the parameter */ + if (!Fast486FetchByte(State, &Data)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set the port number to the parameter */ + Port = Data; + } + else + { + /* The port number is in DX */ + Port = State->GeneralRegs[FAST486_REG_EDX].LowWord; + } + + /* Read a byte from the I/O port */ + State->IoReadCallback(State, Port, &Data, 1, sizeof(UCHAR)); + + /* Store the result in AL */ + State->GeneralRegs[FAST486_REG_EAX].LowByte = Data; + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeIn) +{ + ULONG Port; + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xF7) == 0xE5); + + TOGGLE_OPSIZE(Size); + NO_LOCK_PREFIX(); + + if (Opcode == 0xE5) + { + UCHAR Data; + + /* Fetch the parameter */ + if (!Fast486FetchByte(State, &Data)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set the port number to the parameter */ + Port = Data; + } + else + { + /* The port number is in DX */ + Port = State->GeneralRegs[FAST486_REG_EDX].LowWord; + } + + if (Size) + { + ULONG Data; + + /* Read a dword from the I/O port */ + State->IoReadCallback(State, Port, &Data, 1, sizeof(ULONG)); + + /* Store the value in EAX */ + State->GeneralRegs[FAST486_REG_EAX].Long = Data; + } + else + { + USHORT Data; + + /* Read a word from the I/O port */ + State->IoReadCallback(State, Port, &Data, 1, sizeof(USHORT)); + + /* Store the value in AX */ + State->GeneralRegs[FAST486_REG_EAX].LowWord = Data; + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeOutByte) +{ + UCHAR Data; + ULONG Port; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xF7) == 0xE6); + + if (Opcode == 0xE6) + { + /* Fetch the parameter */ + if (!Fast486FetchByte(State, &Data)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set the port number to the parameter */ + Port = Data; + } + else + { + /* The port number is in DX */ + Port = State->GeneralRegs[FAST486_REG_EDX].LowWord; + } + + /* Read the value from AL */ + Data = State->GeneralRegs[FAST486_REG_EAX].LowByte; + + /* Write the byte to the I/O port */ + State->IoWriteCallback(State, Port, &Data, 1, sizeof(UCHAR)); + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeOut) +{ + ULONG Port; + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xF7) == 0xE7); + + TOGGLE_OPSIZE(Size); + NO_LOCK_PREFIX(); + + if (Opcode == 0xE7) + { + UCHAR Data; + + /* Fetch the parameter */ + if (!Fast486FetchByte(State, &Data)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set the port number to the parameter */ + Port = Data; + } + else + { + /* The port number is in DX */ + Port = State->GeneralRegs[FAST486_REG_EDX].LowWord; + } + + if (Size) + { + /* Get the value from EAX */ + ULONG Data = State->GeneralRegs[FAST486_REG_EAX].Long; + + /* Write a dword to the I/O port */ + State->IoWriteCallback(State, Port, &Data, 1, sizeof(ULONG)); + } + else + { + /* Get the value from AX */ + USHORT Data = State->GeneralRegs[FAST486_REG_EAX].LowWord; + + /* Write a word to the I/O port */ + State->IoWriteCallback(State, Port, &Data, 1, sizeof(USHORT)); + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeShortJump) +{ + CHAR Offset = 0; + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_OPSIZE(Size); + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xEB); + + /* Fetch the offset */ + if (!Fast486FetchByte(State, (PUCHAR)&Offset)) + { + /* An exception occurred */ + return FALSE; + } + + /* Move the instruction pointer */ + State->InstPtr.Long += Offset; + + if (!Size) + { + /* Clear the top half of EIP */ + State->InstPtr.Long &= 0xFFFF; + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeMovRegImm) +{ + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xF8) == 0xB8); + + TOGGLE_OPSIZE(Size); + NO_LOCK_PREFIX(); + + if (Size) + { + ULONG Value; + + /* Fetch the dword */ + if (!Fast486FetchDword(State, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Store the value in the register */ + State->GeneralRegs[Opcode & 0x07].Long = Value; + } + else + { + USHORT Value; + + /* Fetch the word */ + if (!Fast486FetchWord(State, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Store the value in the register */ + State->GeneralRegs[Opcode & 0x07].LowWord = Value; + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeMovByteRegImm) +{ + UCHAR Value; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xF8) == 0xB0); + + if (State->PrefixFlags != 0) + { + /* Invalid prefix */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + /* Fetch the byte */ + if (!Fast486FetchByte(State, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + if (Opcode & 0x04) + { + /* AH, CH, DH or BH */ + State->GeneralRegs[Opcode & 0x03].HighByte = Value; + } + else + { + /* AL, CL, DL or BL */ + State->GeneralRegs[Opcode & 0x03].LowByte = Value; + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeAddByteModrm) +{ + UCHAR FirstValue, SecondValue, Result; + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFD) == 0x00); + + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (!Fast486ReadModrmByteOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue + SecondValue; + + /* Update the flags */ + State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue); + State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE)) + && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE)); + State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + return Fast486WriteModrmByteOperands(State, + &ModRegRm, + Opcode & FAST486_OPCODE_WRITE_REG, + Result); +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeAddModrm) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFD) == 0x01); + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_ADSIZE(AddressSize); + TOGGLE_OPSIZE(OperandSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Check the operand size */ + if (OperandSize) + { + ULONG FirstValue, SecondValue, Result; + + if (!Fast486ReadModrmDwordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue + SecondValue; + + /* Update the flags */ + State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue); + State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG)) + && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG)); + State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + return Fast486WriteModrmDwordOperands(State, + &ModRegRm, + Opcode & FAST486_OPCODE_WRITE_REG, + Result); + } + else + { + USHORT FirstValue, SecondValue, Result; + + if (!Fast486ReadModrmWordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue + SecondValue; + + /* Update the flags */ + State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue); + State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD)) + && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD)); + State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + return Fast486WriteModrmWordOperands(State, + &ModRegRm, + Opcode & FAST486_OPCODE_WRITE_REG, + Result); + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeAddAl) +{ + UCHAR FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowByte; + UCHAR SecondValue, Result; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x04); + + if (State->PrefixFlags) + { + /* This opcode doesn't take any prefixes */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + if (!Fast486FetchByte(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue + SecondValue; + + /* Update the flags */ + State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue); + State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE)) + && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE)); + State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].LowByte = Result; + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeAddEax) +{ + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x05); + + NO_LOCK_PREFIX(); + TOGGLE_OPSIZE(Size); + + if (Size) + { + ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long; + ULONG SecondValue, Result; + + if (!Fast486FetchDword(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue + SecondValue; + + /* Update the flags */ + State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue); + State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG)) + && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG)); + State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].Long = Result; + } + else + { + USHORT FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowWord; + USHORT SecondValue, Result; + + if (!Fast486FetchWord(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue + SecondValue; + + /* Update the flags */ + State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue); + State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD)) + && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD)); + State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].LowWord = Result; + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeOrByteModrm) +{ + UCHAR FirstValue, SecondValue, Result; + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFD) == 0x08); + + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (!Fast486ReadModrmByteOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue | SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + return Fast486WriteModrmByteOperands(State, + &ModRegRm, + Opcode & FAST486_OPCODE_WRITE_REG, + Result); +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeOrModrm) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFD) == 0x09); + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_ADSIZE(AddressSize); + TOGGLE_OPSIZE(OperandSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Check the operand size */ + if (OperandSize) + { + ULONG FirstValue, SecondValue, Result; + + if (!Fast486ReadModrmDwordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue | SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + return Fast486WriteModrmDwordOperands(State, + &ModRegRm, + Opcode & FAST486_OPCODE_WRITE_REG, + Result); + } + else + { + USHORT FirstValue, SecondValue, Result; + + if (!Fast486ReadModrmWordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue | SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + return Fast486WriteModrmWordOperands(State, + &ModRegRm, + Opcode & FAST486_OPCODE_WRITE_REG, + Result); + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeOrAl) +{ + UCHAR FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowByte; + UCHAR SecondValue, Result; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x0C); + + if (State->PrefixFlags) + { + /* This opcode doesn't take any prefixes */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + if (!Fast486FetchByte(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue | SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].LowByte = Result; + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeOrEax) +{ + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x0D); + + NO_LOCK_PREFIX(); + TOGGLE_OPSIZE(Size); + + if (Size) + { + ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long; + ULONG SecondValue, Result; + + if (!Fast486FetchDword(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue | SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].Long = Result; + } + else + { + USHORT FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowWord; + USHORT SecondValue, Result; + + if (!Fast486FetchWord(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue | SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].LowWord = Result; + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeAndByteModrm) +{ + UCHAR FirstValue, SecondValue, Result; + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFD) == 0x20); + + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (!Fast486ReadModrmByteOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue & SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + return Fast486WriteModrmByteOperands(State, + &ModRegRm, + Opcode & FAST486_OPCODE_WRITE_REG, + Result); +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeAndModrm) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFD) == 0x21); + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_ADSIZE(AddressSize); + TOGGLE_OPSIZE(OperandSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Check the operand size */ + if (OperandSize) + { + ULONG FirstValue, SecondValue, Result; + + if (!Fast486ReadModrmDwordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue & SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + return Fast486WriteModrmDwordOperands(State, + &ModRegRm, + Opcode & FAST486_OPCODE_WRITE_REG, + Result); + } + else + { + USHORT FirstValue, SecondValue, Result; + + if (!Fast486ReadModrmWordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue & SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + return Fast486WriteModrmWordOperands(State, + &ModRegRm, + Opcode & FAST486_OPCODE_WRITE_REG, + Result); + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeAndAl) +{ + UCHAR FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowByte; + UCHAR SecondValue, Result; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x24); + + NO_LOCK_PREFIX(); + + if (!Fast486FetchByte(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue & SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].LowByte = Result; + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeAndEax) +{ + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x25); + + NO_LOCK_PREFIX(); + TOGGLE_OPSIZE(Size); + + if (Size) + { + ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long; + ULONG SecondValue, Result; + + if (!Fast486FetchDword(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue & SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].Long = Result; + } + else + { + USHORT FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowWord; + USHORT SecondValue, Result; + + if (!Fast486FetchWord(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue & SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].LowWord = Result; + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeXorByteModrm) +{ + UCHAR FirstValue, SecondValue, Result; + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFD) == 0x30); + + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (!Fast486ReadModrmByteOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue ^ SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + return Fast486WriteModrmByteOperands(State, + &ModRegRm, + Opcode & FAST486_OPCODE_WRITE_REG, + Result); +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeXorModrm) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFD) == 0x31); + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_ADSIZE(AddressSize); + TOGGLE_OPSIZE(OperandSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Check the operand size */ + if (OperandSize) + { + ULONG FirstValue, SecondValue, Result; + + if (!Fast486ReadModrmDwordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue ^ SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + return Fast486WriteModrmDwordOperands(State, + &ModRegRm, + Opcode & FAST486_OPCODE_WRITE_REG, + Result); + } + else + { + USHORT FirstValue, SecondValue, Result; + + if (!Fast486ReadModrmWordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue ^ SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + return Fast486WriteModrmWordOperands(State, + &ModRegRm, + Opcode & FAST486_OPCODE_WRITE_REG, + Result); + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeXorAl) +{ + UCHAR FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowByte; + UCHAR SecondValue, Result; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x34); + + if (State->PrefixFlags) + { + /* This opcode doesn't take any prefixes */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + if (!Fast486FetchByte(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue ^ SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].LowByte = Result; + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeXorEax) +{ + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x35); + + NO_LOCK_PREFIX(); + TOGGLE_OPSIZE(Size); + + if (Size) + { + ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long; + ULONG SecondValue, Result; + + if (!Fast486FetchDword(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue ^ SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].Long = Result; + } + else + { + USHORT FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowWord; + USHORT SecondValue, Result; + + if (!Fast486FetchWord(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue ^ SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].LowWord = Result; + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeTestByteModrm) +{ + UCHAR FirstValue, SecondValue, Result; + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x84); + + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (!Fast486ReadModrmByteOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + /* Calculate the result */ + Result = FirstValue & SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* The result is discarded */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeTestModrm) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x85); + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_ADSIZE(AddressSize); + TOGGLE_OPSIZE(OperandSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Check the operand size */ + if (OperandSize) + { + ULONG FirstValue, SecondValue, Result; + + if (!Fast486ReadModrmDwordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue & SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + } + else + { + USHORT FirstValue, SecondValue, Result; + + if (!Fast486ReadModrmWordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue & SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + } + + /* The result is discarded */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeTestAl) +{ + UCHAR FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowByte; + UCHAR SecondValue, Result; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xA8); + + if (State->PrefixFlags) + { + /* This opcode doesn't take any prefixes */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + if (!Fast486FetchByte(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue & SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* The result is discarded */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeTestEax) +{ + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xA9); + + NO_LOCK_PREFIX(); + TOGGLE_OPSIZE(Size); + + if (Size) + { + ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long; + ULONG SecondValue, Result; + + if (!Fast486FetchDword(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue & SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + } + else + { + USHORT FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowWord; + USHORT SecondValue, Result; + + if (!Fast486FetchWord(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue & SecondValue; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + } + + /* The result is discarded */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeXchgByteModrm) +{ + UCHAR FirstValue, SecondValue; + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x86); + + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (!Fast486ReadModrmByteOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Write the value from the register to the R/M */ + if (!Fast486WriteModrmByteOperands(State, + &ModRegRm, + FALSE, + FirstValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Write the value from the R/M to the register */ + if (!Fast486WriteModrmByteOperands(State, + &ModRegRm, + TRUE, + SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeXchgModrm) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x87); + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_ADSIZE(AddressSize); + TOGGLE_OPSIZE(OperandSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Check the operand size */ + if (OperandSize) + { + ULONG FirstValue, SecondValue; + + if (!Fast486ReadModrmDwordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Write the value from the register to the R/M */ + if (!Fast486WriteModrmDwordOperands(State, + &ModRegRm, + FALSE, + FirstValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Write the value from the R/M to the register */ + if (!Fast486WriteModrmDwordOperands(State, + &ModRegRm, + TRUE, + SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + USHORT FirstValue, SecondValue; + + if (!Fast486ReadModrmWordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Write the value from the register to the R/M */ + if (!Fast486WriteModrmWordOperands(State, + &ModRegRm, + FALSE, + FirstValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Write the value from the R/M to the register */ + if (!Fast486WriteModrmWordOperands(State, + &ModRegRm, + TRUE, + SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + } + + /* The result is discarded */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodePushEs) +{ + /* Call the internal API */ + return Fast486StackPush(State, State->SegmentRegs[FAST486_REG_ES].Selector); +} + +FAST486_OPCODE_HANDLER(Fast486OpcodePopEs) +{ + ULONG NewSelector; + + if (!Fast486StackPop(State, &NewSelector)) + { + /* Exception occurred */ + return FALSE; + } + + /* Call the internal API */ + return Fast486LoadSegment(State, FAST486_REG_ES, LOWORD(NewSelector)); +} + +FAST486_OPCODE_HANDLER(Fast486OpcodePushCs) +{ + /* Call the internal API */ + return Fast486StackPush(State, State->SegmentRegs[FAST486_REG_CS].Selector); +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeAdcByteModrm) +{ + UCHAR FirstValue, SecondValue, Result; + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFD) == 0x10); + + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (!Fast486ReadModrmByteOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue + SecondValue + State->Flags.Cf; + + /* Special exception for CF */ + State->Flags.Cf = State->Flags.Cf + && ((FirstValue == 0xFF) || (SecondValue == 0xFF)); + + /* Update the flags */ + State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue)); + State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE)) + && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE)); + State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + return Fast486WriteModrmByteOperands(State, + &ModRegRm, + Opcode & FAST486_OPCODE_WRITE_REG, + Result); +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeAdcModrm) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFD) == 0x11); + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_ADSIZE(AddressSize); + TOGGLE_OPSIZE(OperandSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Check the operand size */ + if (OperandSize) + { + ULONG FirstValue, SecondValue, Result; + + if (!Fast486ReadModrmDwordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue + SecondValue + State->Flags.Cf; + + /* Special exception for CF */ + State->Flags.Cf = State->Flags.Cf + && ((FirstValue == 0xFFFFFFFF) || (SecondValue == 0xFFFFFFFF)); + + /* Update the flags */ + State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue)); + State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG)) + && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG)); + State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + return Fast486WriteModrmDwordOperands(State, + &ModRegRm, + Opcode & FAST486_OPCODE_WRITE_REG, + Result); + } + else + { + USHORT FirstValue, SecondValue, Result; + + if (!Fast486ReadModrmWordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue + SecondValue + State->Flags.Cf; + + /* Special exception for CF */ + State->Flags.Cf = State->Flags.Cf + && ((FirstValue == 0xFFFF) || (SecondValue == 0xFFFF)); + + /* Update the flags */ + State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue)); + State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD)) + && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD)); + State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + return Fast486WriteModrmWordOperands(State, + &ModRegRm, + Opcode & FAST486_OPCODE_WRITE_REG, + Result); + } + +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeAdcAl) +{ + UCHAR FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowByte; + UCHAR SecondValue, Result; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x14); + + if (State->PrefixFlags) + { + /* This opcode doesn't take any prefixes */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + if (!Fast486FetchByte(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue + SecondValue + State->Flags.Cf; + + /* Special exception for CF */ + State->Flags.Cf = State->Flags.Cf && + ((FirstValue == 0xFF) || (SecondValue == 0xFF)); + + /* Update the flags */ + State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue)); + State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE)) + && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE)); + State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].LowByte = Result; + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeAdcEax) +{ + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x15); + + NO_LOCK_PREFIX(); + TOGGLE_OPSIZE(Size); + + if (Size) + { + ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long; + ULONG SecondValue, Result; + + if (!Fast486FetchDword(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue + SecondValue + State->Flags.Cf; + + /* Special exception for CF */ + State->Flags.Cf = State->Flags.Cf && + ((FirstValue == 0xFFFFFFFF) || (SecondValue == 0xFFFFFFFF)); + + /* Update the flags */ + State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue)); + State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG)) + && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG)); + State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].Long = Result; + } + else + { + USHORT FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowWord; + USHORT SecondValue, Result; + + if (!Fast486FetchWord(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue + SecondValue + State->Flags.Cf; + + /* Special exception for CF */ + State->Flags.Cf = State->Flags.Cf && + ((FirstValue == 0xFFFF) || (SecondValue == 0xFFFF)); + + /* Update the flags */ + State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue)); + State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD)) + && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD)); + State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].LowWord = Result; + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodePushSs) +{ + /* Call the internal API */ + return Fast486StackPush(State, State->SegmentRegs[FAST486_REG_SS].Selector); +} + +FAST486_OPCODE_HANDLER(Fast486OpcodePopSs) +{ + ULONG NewSelector; + + if (!Fast486StackPop(State, &NewSelector)) + { + /* Exception occurred */ + return FALSE; + } + + /* Call the internal API */ + return Fast486LoadSegment(State, FAST486_REG_SS, LOWORD(NewSelector)); +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeSbbByteModrm) +{ + UCHAR FirstValue, SecondValue, Result; + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + INT Carry = State->Flags.Cf ? 1 : 0; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFD) == 0x18); + + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (!Fast486ReadModrmByteOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Check if this is the instruction that writes to R/M */ + if (!(Opcode & FAST486_OPCODE_WRITE_REG)) + { + /* Swap the order */ + SWAP(FirstValue, SecondValue); + } + + /* Calculate the result */ + Result = FirstValue - SecondValue - Carry; + + /* Update the flags */ + State->Flags.Cf = Carry ? (FirstValue <= SecondValue) : (FirstValue < SecondValue); + State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) != (SecondValue & SIGN_FLAG_BYTE)) + && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE)); + State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + return Fast486WriteModrmByteOperands(State, + &ModRegRm, + Opcode & FAST486_OPCODE_WRITE_REG, + Result); +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeSbbModrm) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + INT Carry = State->Flags.Cf ? 1 : 0; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFD) == 0x19); + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_ADSIZE(AddressSize); + TOGGLE_OPSIZE(OperandSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Check the operand size */ + if (OperandSize) + { + ULONG FirstValue, SecondValue, Result; + + if (!Fast486ReadModrmDwordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Check if this is the instruction that writes to R/M */ + if (!(Opcode & FAST486_OPCODE_WRITE_REG)) + { + /* Swap the order */ + SWAP(FirstValue, SecondValue); + } + + /* Calculate the result */ + Result = FirstValue - SecondValue - Carry; + + /* Update the flags */ + State->Flags.Cf = Carry ? (FirstValue <= SecondValue) : (FirstValue < SecondValue); + State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) != (SecondValue & SIGN_FLAG_LONG)) + && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG)); + State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + return Fast486WriteModrmDwordOperands(State, + &ModRegRm, + Opcode & FAST486_OPCODE_WRITE_REG, + Result); + } + else + { + USHORT FirstValue, SecondValue, Result; + + if (!Fast486ReadModrmWordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Check if this is the instruction that writes to R/M */ + if (!(Opcode & FAST486_OPCODE_WRITE_REG)) + { + /* Swap the order */ + SWAP(FirstValue, SecondValue); + } + + /* Calculate the result */ + Result = FirstValue - SecondValue - Carry; + + /* Update the flags */ + State->Flags.Cf = Carry ? (FirstValue <= SecondValue) : (FirstValue < SecondValue); + State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) != (SecondValue & SIGN_FLAG_WORD)) + && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD)); + State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + return Fast486WriteModrmWordOperands(State, + &ModRegRm, + Opcode & FAST486_OPCODE_WRITE_REG, + Result); + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeSbbAl) +{ + UCHAR FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowByte; + UCHAR SecondValue, Result; + INT Carry = State->Flags.Cf ? 1 : 0; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x1C); + + if (State->PrefixFlags) + { + /* This opcode doesn't take any prefixes */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + if (!Fast486FetchByte(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue - SecondValue - Carry; + + /* Update the flags */ + State->Flags.Cf = Carry ? (FirstValue <= SecondValue) : (FirstValue < SecondValue); + State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) != (SecondValue & SIGN_FLAG_BYTE)) + && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE)); + State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].LowByte = Result; + + return TRUE; + +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeSbbEax) +{ + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + INT Carry = State->Flags.Cf ? 1 : 0; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x1D); + + NO_LOCK_PREFIX(); + TOGGLE_OPSIZE(Size); + + if (Size) + { + ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long; + ULONG SecondValue, Result; + + if (!Fast486FetchDword(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue - SecondValue - Carry; + + /* Update the flags */ + State->Flags.Cf = Carry ? (FirstValue <= SecondValue) : (FirstValue < SecondValue); + State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) != (SecondValue & SIGN_FLAG_LONG)) + && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG)); + State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].Long = Result; + } + else + { + USHORT FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowWord; + USHORT SecondValue, Result; + + if (!Fast486FetchWord(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue - SecondValue - Carry; + + /* Update the flags */ + State->Flags.Cf = Carry ? (FirstValue <= SecondValue) : (FirstValue < SecondValue); + State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) != (SecondValue & SIGN_FLAG_WORD)) + && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD)); + State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].LowWord = Result; + } + + return TRUE; + +} + +FAST486_OPCODE_HANDLER(Fast486OpcodePushDs) +{ + /* Call the internal API */ + return Fast486StackPush(State, State->SegmentRegs[FAST486_REG_DS].Selector); +} + +FAST486_OPCODE_HANDLER(Fast486OpcodePopDs) +{ + ULONG NewSelector; + + if (!Fast486StackPop(State, &NewSelector)) + { + /* Exception occurred */ + return FALSE; + } + + /* Call the internal API */ + return Fast486LoadSegment(State, FAST486_REG_DS, LOWORD(NewSelector)); +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeDaa) +{ + UCHAR Value = State->GeneralRegs[FAST486_REG_EAX].LowByte; + BOOLEAN Carry = State->Flags.Cf; + + /* Clear the carry flag */ + State->Flags.Cf = FALSE; + + /* Check if the first BCD digit is invalid or there was a carry from it */ + if (((Value & 0x0F) > 9) || State->Flags.Af) + { + /* Correct it */ + State->GeneralRegs[FAST486_REG_EAX].LowByte += 0x06; + if (State->GeneralRegs[FAST486_REG_EAX].LowByte < 0x06) + { + /* A carry occurred */ + State->Flags.Cf = TRUE; + } + + /* Set the adjust flag */ + State->Flags.Af = TRUE; + } + + /* Check if the second BCD digit is invalid or there was a carry from it */ + if ((Value > 0x99) || Carry) + { + /* Correct it */ + State->GeneralRegs[FAST486_REG_EAX].LowByte += 0x60; + + /* There was a carry */ + State->Flags.Cf = TRUE; + } + + Value = State->GeneralRegs[FAST486_REG_EAX].LowByte; + + /* Update the flags */ + State->Flags.Sf = (Value & SIGN_FLAG_BYTE) != 0; + State->Flags.Zf = (Value == 0); + State->Flags.Pf = Fast486CalculateParity(Value); + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubByteModrm) +{ + UCHAR FirstValue, SecondValue, Result; + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xED) == 0x28); + + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (!Fast486ReadModrmByteOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Check if this is the instruction that writes to R/M */ + if (!(Opcode & FAST486_OPCODE_WRITE_REG)) + { + /* Swap the order */ + SWAP(FirstValue, SecondValue); + } + + /* Calculate the result */ + Result = FirstValue - SecondValue; + + /* Update the flags */ + State->Flags.Cf = (FirstValue < SecondValue); + State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) != (SecondValue & SIGN_FLAG_BYTE)) + && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE)); + State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Check if this is not a CMP */ + if (!(Opcode & 0x10)) + { + /* Write back the result */ + return Fast486WriteModrmByteOperands(State, + &ModRegRm, + Opcode & FAST486_OPCODE_WRITE_REG, + Result); + } + else + { + /* Discard the result */ + return TRUE; + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubModrm) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xED) == 0x29); + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_ADSIZE(AddressSize); + TOGGLE_OPSIZE(OperandSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Check the operand size */ + if (OperandSize) + { + ULONG FirstValue, SecondValue, Result; + + if (!Fast486ReadModrmDwordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Check if this is the instruction that writes to R/M */ + if (!(Opcode & FAST486_OPCODE_WRITE_REG)) + { + /* Swap the order */ + SWAP(FirstValue, SecondValue); + } + + /* Calculate the result */ + Result = FirstValue - SecondValue; + + /* Update the flags */ + State->Flags.Cf = (FirstValue < SecondValue); + State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) != (SecondValue & SIGN_FLAG_LONG)) + && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG)); + State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Check if this is not a CMP */ + if (!(Opcode & 0x10)) + { + /* Write back the result */ + return Fast486WriteModrmDwordOperands(State, + &ModRegRm, + Opcode & FAST486_OPCODE_WRITE_REG, + Result); + } + else + { + /* Discard the result */ + return TRUE; + } + } + else + { + USHORT FirstValue, SecondValue, Result; + + if (!Fast486ReadModrmWordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Check if this is the instruction that writes to R/M */ + if (!(Opcode & FAST486_OPCODE_WRITE_REG)) + { + /* Swap the order */ + SWAP(FirstValue, SecondValue); + } + + /* Calculate the result */ + Result = FirstValue - SecondValue; + + /* Update the flags */ + State->Flags.Cf = (FirstValue < SecondValue); + State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) != (SecondValue & SIGN_FLAG_WORD)) + && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD)); + State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Check if this is not a CMP */ + if (!(Opcode & 0x10)) + { + /* Write back the result */ + return Fast486WriteModrmWordOperands(State, + &ModRegRm, + Opcode & FAST486_OPCODE_WRITE_REG, + Result); + } + else + { + /* Discard the result */ + return TRUE; + } + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubAl) +{ + UCHAR FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowByte; + UCHAR SecondValue, Result; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xEF) == 0x2C); + + if (State->PrefixFlags) + { + /* This opcode doesn't take any prefixes */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + if (!Fast486FetchByte(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue - SecondValue; + + /* Update the flags */ + State->Flags.Cf = (FirstValue < SecondValue); + State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) != (SecondValue & SIGN_FLAG_BYTE)) + && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE)); + State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Check if this is not a CMP */ + if (!(Opcode & 0x10)) + { + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].LowByte = Result; + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubEax) +{ + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xEF) == 0x2D); + + NO_LOCK_PREFIX(); + TOGGLE_OPSIZE(Size); + + if (Size) + { + ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long; + ULONG SecondValue, Result; + + if (!Fast486FetchDword(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue - SecondValue; + + /* Update the flags */ + State->Flags.Cf = (FirstValue < SecondValue); + State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) != (SecondValue & SIGN_FLAG_LONG)) + && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG)); + State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Check if this is not a CMP */ + if (!(Opcode & 0x10)) + { + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].Long = Result; + } + } + else + { + USHORT FirstValue = State->GeneralRegs[FAST486_REG_EAX].LowWord; + USHORT SecondValue, Result; + + if (!Fast486FetchWord(State, &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = FirstValue - SecondValue; + + /* Update the flags */ + State->Flags.Cf = (FirstValue < SecondValue); + State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) != (SecondValue & SIGN_FLAG_WORD)) + && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD)); + State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Check if this is not a CMP */ + if (!(Opcode & 0x10)) + { + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].LowWord = Result; + } + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeDas) +{ + UCHAR Value = State->GeneralRegs[FAST486_REG_EAX].LowByte; + BOOLEAN Carry = State->Flags.Cf; + + /* Clear the carry flag */ + State->Flags.Cf = FALSE; + + /* Check if the first BCD digit is invalid or there was a borrow */ + if (((Value & 0x0F) > 9) || State->Flags.Af) + { + /* Correct it */ + State->GeneralRegs[FAST486_REG_EAX].LowByte -= 0x06; + if (State->GeneralRegs[FAST486_REG_EAX].LowByte > 0xFB) + { + /* A borrow occurred */ + State->Flags.Cf = TRUE; + } + + /* Set the adjust flag */ + State->Flags.Af = TRUE; + } + + /* Check if the second BCD digit is invalid or there was a borrow */ + if ((Value > 0x99) || Carry) + { + /* Correct it */ + State->GeneralRegs[FAST486_REG_EAX].LowByte -= 0x60; + + /* There was a borrow */ + State->Flags.Cf = TRUE; + } + + Value = State->GeneralRegs[FAST486_REG_EAX].LowByte; + + /* Update the flags */ + State->Flags.Sf = (Value & SIGN_FLAG_BYTE) != 0; + State->Flags.Zf = (Value == 0); + State->Flags.Pf = Fast486CalculateParity(Value); + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeAaa) +{ + UCHAR Value = State->GeneralRegs[FAST486_REG_EAX].LowByte; + + /* + * Check if the value in AL is not a valid BCD digit, + * or there was a carry from the lowest 4 bits of AL + */ + if (((Value & 0x0F) > 9) || State->Flags.Af) + { + /* Correct it */ + State->GeneralRegs[FAST486_REG_EAX].LowWord += 0x06; + State->GeneralRegs[FAST486_REG_EAX].HighByte++; + + /* Set CF and AF */ + State->Flags.Cf = State->Flags.Af = TRUE; + } + else + { + /* Clear CF and AF */ + State->Flags.Cf = State->Flags.Af = FALSE; + } + + /* Keep only the lowest 4 bits of AL */ + State->GeneralRegs[FAST486_REG_EAX].LowByte &= 0x0F; + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeAas) +{ + UCHAR Value = State->GeneralRegs[FAST486_REG_EAX].LowByte; + + /* + * Check if the value in AL is not a valid BCD digit, + * or there was a borrow from the lowest 4 bits of AL + */ + if (((Value & 0x0F) > 9) || State->Flags.Af) + { + /* Correct it */ + State->GeneralRegs[FAST486_REG_EAX].LowWord -= 0x06; + State->GeneralRegs[FAST486_REG_EAX].HighByte--; + + /* Set CF and AF */ + State->Flags.Cf = State->Flags.Af = TRUE; + } + else + { + /* Clear CF and AF */ + State->Flags.Cf = State->Flags.Af = FALSE; + } + + /* Keep only the lowest 4 bits of AL */ + State->GeneralRegs[FAST486_REG_EAX].LowByte &= 0x0F; + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodePushAll) +{ + INT i; + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + FAST486_REG SavedEsp = State->GeneralRegs[FAST486_REG_ESP]; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x60); + + TOGGLE_OPSIZE(Size); + NO_LOCK_PREFIX(); + + /* Push all the registers in order */ + for (i = 0; i < FAST486_NUM_GEN_REGS; i++) + { + if (i == FAST486_REG_ESP) + { + /* Use the saved ESP instead */ + if (!Fast486StackPush(State, Size ? SavedEsp.Long : SavedEsp.LowWord)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + /* Push the register */ + if (!Fast486StackPush(State, Size ? State->GeneralRegs[i].Long + : State->GeneralRegs[i].LowWord)) + { + /* Exception occurred */ + return FALSE; + } + } + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodePopAll) +{ + INT i; + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + ULONG Value; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x61); + + TOGGLE_OPSIZE(Size); + NO_LOCK_PREFIX(); + + /* Pop all the registers in reverse order */ + for (i = FAST486_NUM_GEN_REGS - 1; i >= 0; i--) + { + /* Pop the value */ + if (!Fast486StackPop(State, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Don't modify ESP */ + if (i != FAST486_REG_ESP) + { + if (Size) State->GeneralRegs[i].Long = Value; + else State->GeneralRegs[i].LowWord = LOWORD(Value); + } + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeBound) +{ + BOOLEAN OperandSize, AddressSize; + FAST486_MOD_REG_RM ModRegRm; + FAST486_SEG_REGS Segment = FAST486_REG_DS; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + NO_LOCK_PREFIX(); + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (!ModRegRm.Memory) + { + /* Invalid */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + /* Check for the segment override */ + if (State->PrefixFlags & FAST486_PREFIX_SEG) + { + /* Use the override segment instead */ + Segment = State->SegmentOverride; + } + + if (OperandSize) + { + LONG Index, LowerBound, UpperBound; + + /* Read the operands */ + if (!Fast486ReadModrmDwordOperands(State, + &ModRegRm, + (PULONG)&Index, + (PULONG)&LowerBound)) + { + /* Exception occurred */ + return FALSE; + } + + if (!Fast486ReadMemory(State, + Segment, + ModRegRm.MemoryAddress + sizeof(ULONG), + FALSE, + &UpperBound, + sizeof(ULONG))) + { + /* Exception occurred */ + return FALSE; + } + + if ((Index < LowerBound) || (Index > UpperBound)) + { + /* Out of bounds */ + Fast486Exception(State, FAST486_EXCEPTION_BR); + return FALSE; + } + } + else + { + SHORT Index, LowerBound, UpperBound; + + /* Read the operands */ + if (!Fast486ReadModrmWordOperands(State, + &ModRegRm, + (PUSHORT)&Index, + (PUSHORT)&LowerBound)) + { + /* Exception occurred */ + return FALSE; + } + + if (!Fast486ReadMemory(State, + Segment, + ModRegRm.MemoryAddress + sizeof(USHORT), + FALSE, + &UpperBound, + sizeof(USHORT))) + { + /* Exception occurred */ + return FALSE; + } + + if ((Index < LowerBound) || (Index > UpperBound)) + { + /* Out of bounds */ + Fast486Exception(State, FAST486_EXCEPTION_BR); + return FALSE; + } + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeArpl) +{ + USHORT FirstValue, SecondValue; + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) + || State->Flags.Vm + || (State->PrefixFlags & FAST486_PREFIX_LOCK)) + { + /* Cannot be used in real mode or with a LOCK prefix */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Read the operands */ + if (!Fast486ReadModrmWordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + /* Check if the RPL needs adjusting */ + if ((SecondValue & 3) < (FirstValue & 3)) + { + /* Adjust the RPL */ + SecondValue &= ~3; + SecondValue |= FirstValue & 3; + + /* Set ZF */ + State->Flags.Zf = TRUE; + + /* Write back the result */ + return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, SecondValue); + } + else + { + /* Clear ZF */ + State->Flags.Zf = FALSE; + return TRUE; + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodePushImm) +{ + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x68); + + NO_LOCK_PREFIX(); + TOGGLE_OPSIZE(Size); + + if (Size) + { + ULONG Data; + + if (!Fast486FetchDword(State, &Data)) + { + /* Exception occurred */ + return FALSE; + } + + /* Call the internal API */ + return Fast486StackPush(State, Data); + } + else + { + USHORT Data; + + if (!Fast486FetchWord(State, &Data)) + { + /* Exception occurred */ + return FALSE; + } + + /* Call the internal API */ + return Fast486StackPush(State, Data); + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeImulModrmImm) +{ + BOOLEAN OperandSize, AddressSize; + FAST486_MOD_REG_RM ModRegRm; + LONG Multiplier; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFD) == 0x69); + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_ADSIZE(AddressSize); + TOGGLE_OPSIZE(OperandSize); + + /* Fetch the parameters */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (Opcode == 0x6B) + { + CHAR Byte; + + /* Fetch the immediate operand */ + if (!Fast486FetchByte(State, (PUCHAR)&Byte)) + { + /* Exception occurred */ + return FALSE; + } + + Multiplier = (LONG)Byte; + } + else + { + if (OperandSize) + { + LONG Dword; + + /* Fetch the immediate operand */ + if (!Fast486FetchDword(State, (PULONG)&Dword)) + { + /* Exception occurred */ + return FALSE; + } + + Multiplier = Dword; + } + else + { + SHORT Word; + + /* Fetch the immediate operand */ + if (!Fast486FetchWord(State, (PUSHORT)&Word)) + { + /* Exception occurred */ + return FALSE; + } + + Multiplier = (LONG)Word; + } + } + + if (OperandSize) + { + LONG RegValue, Multiplicand; + LONGLONG Product; + + /* Read the operands */ + if (!Fast486ReadModrmDwordOperands(State, + &ModRegRm, + (PULONG)&RegValue, + (PULONG)&Multiplicand)) + { + /* Exception occurred */ + return FALSE; + } + + /* Multiply */ + Product = (LONGLONG)Multiplicand * (LONGLONG)Multiplier; + + /* Check for carry/overflow */ + State->Flags.Cf = State->Flags.Of = ((Product < MINLONG) || (Product > MAXLONG)); + + /* Write-back the result */ + return Fast486WriteModrmDwordOperands(State, + &ModRegRm, + TRUE, + (ULONG)((LONG)Product)); + } + else + { + SHORT RegValue, Multiplicand; + LONG Product; + + /* Read the operands */ + if (!Fast486ReadModrmWordOperands(State, + &ModRegRm, + (PUSHORT)&RegValue, + (PUSHORT)&Multiplicand)) + { + /* Exception occurred */ + return FALSE; + } + + /* Multiply */ + Product = (LONG)Multiplicand * (LONG)Multiplier; + + /* Check for carry/overflow */ + State->Flags.Cf = State->Flags.Of = ((Product < MINSHORT) || (Product > MAXSHORT)); + + /* Write-back the result */ + return Fast486WriteModrmWordOperands(State, + &ModRegRm, + TRUE, + (USHORT)((SHORT)Product)); + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodePushByteImm) +{ + UCHAR Data; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x6A); + + if (!Fast486FetchByte(State, &Data)) + { + /* Exception occurred */ + return FALSE; + } + + /* Call the internal API */ + return Fast486StackPush(State, Data); +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeMovByteModrm) +{ + UCHAR FirstValue, SecondValue, Result; + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFD) == 0x88); + + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (!Fast486ReadModrmByteOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + if (Opcode & FAST486_OPCODE_WRITE_REG) Result = SecondValue; + else Result = FirstValue; + + /* Write back the result */ + return Fast486WriteModrmByteOperands(State, + &ModRegRm, + Opcode & FAST486_OPCODE_WRITE_REG, + Result); + +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeMovModrm) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFD) == 0x89); + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_ADSIZE(AddressSize); + TOGGLE_OPSIZE(OperandSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Check the operand size */ + if (OperandSize) + { + ULONG FirstValue, SecondValue, Result; + + if (!Fast486ReadModrmDwordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + if (Opcode & FAST486_OPCODE_WRITE_REG) Result = SecondValue; + else Result = FirstValue; + + /* Write back the result */ + return Fast486WriteModrmDwordOperands(State, + &ModRegRm, + Opcode & FAST486_OPCODE_WRITE_REG, + Result); + } + else + { + USHORT FirstValue, SecondValue, Result; + + if (!Fast486ReadModrmWordOperands(State, + &ModRegRm, + &FirstValue, + &SecondValue)) + { + /* Exception occurred */ + return FALSE; + } + + if (Opcode & FAST486_OPCODE_WRITE_REG) Result = SecondValue; + else Result = FirstValue; + + /* Write back the result */ + return Fast486WriteModrmWordOperands(State, + &ModRegRm, + Opcode & FAST486_OPCODE_WRITE_REG, + Result); + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeMovStoreSeg) +{ + BOOLEAN OperandSize, AddressSize; + FAST486_MOD_REG_RM ModRegRm; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x8C); + + TOGGLE_ADSIZE(AddressSize); + TOGGLE_OPSIZE(OperandSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (ModRegRm.Register >= FAST486_NUM_SEG_REGS) + { + /* Invalid */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + if (OperandSize) + { + return Fast486WriteModrmDwordOperands(State, + &ModRegRm, + FALSE, + State->SegmentRegs[ModRegRm.Register].Selector); + } + else + { + return Fast486WriteModrmWordOperands(State, + &ModRegRm, + FALSE, + State->SegmentRegs[ModRegRm.Register].Selector); + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeLea) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x8D); + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_ADSIZE(AddressSize); + TOGGLE_OPSIZE(OperandSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* The second operand must be memory */ + if (!ModRegRm.Memory) + { + /* Invalid */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + /* Write the address to the register */ + if (OperandSize) + { + return Fast486WriteModrmDwordOperands(State, + &ModRegRm, + TRUE, + ModRegRm.MemoryAddress); + } + else + { + return Fast486WriteModrmWordOperands(State, + &ModRegRm, + TRUE, + ModRegRm.MemoryAddress); + + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeMovLoadSeg) +{ + BOOLEAN OperandSize, AddressSize; + FAST486_MOD_REG_RM ModRegRm; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x8E); + + TOGGLE_ADSIZE(AddressSize); + TOGGLE_OPSIZE(OperandSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if ((ModRegRm.Register >= FAST486_NUM_SEG_REGS) + || ((FAST486_SEG_REGS)ModRegRm.Register == FAST486_REG_CS)) + { + /* Invalid */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + if (OperandSize) + { + ULONG Selector; + + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Selector)) + { + /* Exception occurred */ + return FALSE; + } + + return Fast486LoadSegment(State, ModRegRm.Register, LOWORD(Selector)); + } + else + { + USHORT Selector; + + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Selector)) + { + /* Exception occurred */ + return FALSE; + } + + return Fast486LoadSegment(State, ModRegRm.Register, Selector); + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeCwde) +{ + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x98); + + TOGGLE_OPSIZE(Size); + NO_LOCK_PREFIX(); + + if (Size) + { + /* Sign extend AX to EAX */ + State->GeneralRegs[FAST486_REG_EAX].Long = MAKELONG + ( + State->GeneralRegs[FAST486_REG_EAX].LowWord, + (State->GeneralRegs[FAST486_REG_EAX].LowWord & SIGN_FLAG_WORD) + ? 0xFFFF : 0x0000 + ); + } + else + { + /* Sign extend AL to AX */ + State->GeneralRegs[FAST486_REG_EAX].HighByte = + (State->GeneralRegs[FAST486_REG_EAX].LowByte & SIGN_FLAG_BYTE) + ? 0xFF : 0x00; + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeCdq) +{ + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x99); + + TOGGLE_OPSIZE(Size); + NO_LOCK_PREFIX(); + + if (Size) + { + /* Sign extend EAX to EDX:EAX */ + State->GeneralRegs[FAST486_REG_EDX].Long = + (State->GeneralRegs[FAST486_REG_EAX].Long & SIGN_FLAG_LONG) + ? 0xFFFFFFFF : 0x00000000; + } + else + { + /* Sign extend AX to DX:AX */ + State->GeneralRegs[FAST486_REG_EDX].LowWord = + (State->GeneralRegs[FAST486_REG_EAX].LowWord & SIGN_FLAG_WORD) + ? 0xFFFF : 0x0000; + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeCallAbs) +{ + USHORT Segment = 0; + ULONG Offset = 0; + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x9A); + + TOGGLE_OPSIZE(Size); + NO_LOCK_PREFIX(); + + /* Fetch the offset */ + if (Size) + { + if (!Fast486FetchDword(State, &Offset)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + if (!Fast486FetchWord(State, (PUSHORT)&Offset)) + { + /* Exception occurred */ + return FALSE; + } + } + + /* Fetch the segment */ + if (!Fast486FetchWord(State, &Segment)) + { + /* Exception occurred */ + return FALSE; + } + + /* Push the current code segment selector */ + if (!Fast486StackPush(State, State->SegmentRegs[FAST486_REG_CS].Selector)) + { + /* Exception occurred */ + return FALSE; + } + + /* Push the current value of the instruction pointer */ + if (!Fast486StackPush(State, State->InstPtr.Long)) + { + /* Exception occurred */ + return FALSE; + } + + /* Load the new CS */ + if (!Fast486LoadSegment(State, FAST486_REG_CS, Segment)) + { + /* Exception occurred */ + return FALSE; + } + + /* Load new (E)IP */ + if (Size) State->InstPtr.Long = Offset; + else State->InstPtr.LowWord = LOWORD(Offset); + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeWait) +{ + // TODO: NOT IMPLEMENTED + UNIMPLEMENTED; + + return FALSE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodePushFlags) +{ + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + NO_LOCK_PREFIX(); + TOGGLE_OPSIZE(Size); + + /* Check for VM86 mode when IOPL is not 3 */ + if (State->Flags.Vm && (State->Flags.Iopl != 3)) + { + /* Call the VM86 monitor */ + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, 0); + return FALSE; + } + + /* Push the flags */ + if (Size) return Fast486StackPush(State, State->Flags.Long); + else return Fast486StackPush(State, LOWORD(State->Flags.Long)); +} + +FAST486_OPCODE_HANDLER(Fast486OpcodePopFlags) +{ + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + INT Cpl = Fast486GetCurrentPrivLevel(State); + FAST486_FLAGS_REG NewFlags; + + NO_LOCK_PREFIX(); + TOGGLE_OPSIZE(Size); + + /* Pop the new flags */ + if (!Fast486StackPop(State, &NewFlags.Long)) + { + /* Exception occurred */ + return FALSE; + } + + /* Check for VM86 mode when IOPL is not 3 */ + if (State->Flags.Vm && (State->Flags.Iopl != 3)) + { + /* Call the VM86 monitor */ + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, 0); + return FALSE; + } + + State->Flags.Cf = NewFlags.Cf; + State->Flags.Pf = NewFlags.Pf; + State->Flags.Af = NewFlags.Af; + State->Flags.Zf = NewFlags.Zf; + State->Flags.Sf = NewFlags.Sf; + State->Flags.Tf = NewFlags.Tf; + State->Flags.Df = NewFlags.Df; + State->Flags.Of = NewFlags.Of; + State->Flags.Nt = NewFlags.Nt; + State->Flags.Ac = NewFlags.Ac; + + if (Cpl == 0) State->Flags.Iopl = NewFlags.Iopl; + if (Cpl <= State->Flags.Iopl) State->Flags.If = NewFlags.If; + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeSahf) +{ + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x9E); + + /* Set the low-order byte of FLAGS to AH */ + State->Flags.Long &= 0xFFFFFF00; + State->Flags.Long |= State->GeneralRegs[FAST486_REG_EAX].HighByte; + + /* Restore the reserved bits of FLAGS */ + State->Flags.AlwaysSet = TRUE; + State->Flags.Reserved0 = State->Flags.Reserved1 = FALSE; + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeLahf) +{ + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0x9F); + + /* Set AH to the low-order byte of FLAGS */ + State->GeneralRegs[FAST486_REG_EAX].HighByte = LOBYTE(State->Flags.Long); + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeRet) +{ + ULONG ReturnAddress; + USHORT BytesToPop = 0; + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFE) == 0xC2); + + NO_LOCK_PREFIX(); + TOGGLE_OPSIZE(Size); + + if (Opcode == 0xC2) + { + /* Fetch the number of bytes to pop after the return */ + if (!Fast486FetchWord(State, &BytesToPop)) return FALSE; + } + + /* Pop the return address */ + if (!Fast486StackPop(State, &ReturnAddress)) return FALSE; + + /* Return to the calling procedure, and if necessary, pop the parameters */ + if (Size) + { + State->InstPtr.Long = ReturnAddress; + State->GeneralRegs[FAST486_REG_ESP].Long += BytesToPop; + } + else + { + State->InstPtr.LowWord = LOWORD(ReturnAddress); + State->GeneralRegs[FAST486_REG_ESP].LowWord += BytesToPop; + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeLdsLes) +{ + UCHAR FarPointer[6]; + BOOLEAN OperandSize, AddressSize; + FAST486_MOD_REG_RM ModRegRm; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFE) == 0xC4); + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + /* Get the operands */ + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (!ModRegRm.Memory) + { + /* Check if this is a BOP and the host supports BOPs */ + if ((Opcode == 0xC4) + && (ModRegRm.Register == FAST486_REG_EAX) + && (ModRegRm.SecondRegister == FAST486_REG_ESP) + && (State->BopCallback != NULL)) + { + UCHAR BopCode; + + /* Fetch the BOP code */ + if (!Fast486FetchByte(State, &BopCode)) + { + /* Exception occurred */ + return FALSE; + } + + /* Call the BOP handler */ + State->BopCallback(State, BopCode); + + /* Return success */ + return TRUE; + } + + /* Invalid */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + if (!Fast486ReadMemory(State, + (State->PrefixFlags & FAST486_PREFIX_SEG) + ? State->SegmentOverride : FAST486_REG_DS, + ModRegRm.MemoryAddress, + FALSE, + FarPointer, + OperandSize ? 6 : 4)) + { + /* Exception occurred */ + return FALSE; + } + + if (OperandSize) + { + ULONG Offset = *((PULONG)FarPointer); + USHORT Segment = *((PUSHORT)&FarPointer[sizeof(ULONG)]); + + /* Set the register to the offset */ + State->GeneralRegs[ModRegRm.Register].Long = Offset; + + /* Load the segment */ + return Fast486LoadSegment(State, + (Opcode == 0xC4) + ? FAST486_REG_ES : FAST486_REG_DS, + Segment); + } + else + { + USHORT Offset = *((PUSHORT)FarPointer); + USHORT Segment = *((PUSHORT)&FarPointer[sizeof(USHORT)]); + + /* Set the register to the offset */ + State->GeneralRegs[ModRegRm.Register].LowWord = Offset; + + /* Load the segment */ + return Fast486LoadSegment(State, + (Opcode == 0xC4) + ? FAST486_REG_ES : FAST486_REG_DS, + Segment); + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeEnter) +{ + INT i; + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + USHORT FrameSize; + UCHAR NestingLevel; + FAST486_REG FramePointer; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xC8); + + NO_LOCK_PREFIX(); + TOGGLE_OPSIZE(Size); + + if (!Fast486FetchWord(State, &FrameSize)) + { + /* Exception occurred */ + return FALSE; + } + + if (!Fast486FetchByte(State, &NestingLevel)) + { + /* Exception occurred */ + return FALSE; + } + + /* Push EBP */ + if (!Fast486StackPush(State, State->GeneralRegs[FAST486_REG_EBP].Long)) + { + /* Exception occurred */ + return FALSE; + } + + /* Save ESP */ + FramePointer = State->GeneralRegs[FAST486_REG_ESP]; + + /* Set up the nested procedure stacks */ + for (i = 1; i < NestingLevel; i++) + { + if (Size) + { + State->GeneralRegs[FAST486_REG_EBP].Long -= 4; + Fast486StackPush(State, State->GeneralRegs[FAST486_REG_EBP].Long); + } + else + { + State->GeneralRegs[FAST486_REG_EBP].LowWord -= 2; + Fast486StackPush(State, State->GeneralRegs[FAST486_REG_EBP].LowWord); + } + } + + if (NestingLevel > 0) Fast486StackPush(State, FramePointer.Long); + + /* Set EBP to the frame pointer */ + State->GeneralRegs[FAST486_REG_EBP] = FramePointer; + + /* Reserve space for the frame */ + if (Size) State->GeneralRegs[FAST486_REG_ESP].Long -= (ULONG)FrameSize; + else State->GeneralRegs[FAST486_REG_ESP].LowWord -= FrameSize; + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeLeave) +{ + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xC9); + + NO_LOCK_PREFIX(); + TOGGLE_OPSIZE(Size); + + if (Size) + { + /* Set the stack pointer (ESP) to the base pointer (EBP) */ + State->GeneralRegs[FAST486_REG_ESP].Long = State->GeneralRegs[FAST486_REG_EBP].Long; + + /* Pop the saved base pointer from the stack */ + return Fast486StackPop(State, &State->GeneralRegs[FAST486_REG_EBP].Long); + } + else + { + ULONG Value; + + /* Set the stack pointer (SP) to the base pointer (BP) */ + State->GeneralRegs[FAST486_REG_ESP].LowWord = State->GeneralRegs[FAST486_REG_EBP].LowWord; + + /* Pop the saved base pointer from the stack */ + if (Fast486StackPop(State, &Value)) + { + State->GeneralRegs[FAST486_REG_EBP].LowWord = LOWORD(Value); + return TRUE; + } + else return FALSE; + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeRetFar) +{ + ULONG Segment = 0; + ULONG Offset = 0; + USHORT BytesToPop = 0; + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFE) == 0xCA); + + TOGGLE_OPSIZE(Size); + NO_LOCK_PREFIX(); + + if (Opcode == 0xCA) + { + /* Fetch the number of bytes to pop after the return */ + if (!Fast486FetchWord(State, &BytesToPop)) return FALSE; + } + + /* Pop the offset */ + if (!Fast486StackPop(State, &Offset)) + { + /* Exception occurred */ + return FALSE; + } + + /* Pop the segment */ + if (!Fast486StackPop(State, &Segment)) + { + /* Exception occurred */ + return FALSE; + } + + /* Load the new CS */ + if (!Fast486LoadSegment(State, FAST486_REG_CS, Segment)) + { + /* Exception occurred */ + return FALSE; + } + + /* Load new (E)IP, and if necessary, pop the parameters */ + if (Size) + { + State->InstPtr.Long = Offset; + State->GeneralRegs[FAST486_REG_ESP].Long += BytesToPop; + } + else + { + State->InstPtr.LowWord = LOWORD(Offset); + State->GeneralRegs[FAST486_REG_ESP].LowWord += BytesToPop; + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeInt) +{ + UCHAR IntNum; + FAST486_IDT_ENTRY IdtEntry; + + switch (Opcode) + { + case 0xCC: + { + /* This is the INT3 instruction */ + IntNum = 3; + break; + } + + case 0xCD: + { + /* Fetch the interrupt number */ + if (!Fast486FetchByte(State, &IntNum)) + { + /* Exception occurred */ + return FALSE; + } + + break; + } + + case 0xCE: + { + /* Don't do anything if OF is cleared */ + if (!State->Flags.Of) return TRUE; + + /* Exception #OF */ + IntNum = FAST486_EXCEPTION_OF; + + break; + } + + default: + { + /* Should not happen */ + ASSERT(FALSE); + } + } + + /* Get the interrupt vector */ + if (!Fast486GetIntVector(State, IntNum, &IdtEntry)) + { + /* Exception occurred */ + return FALSE; + } + + /* Perform the interrupt */ + if (!Fast486InterruptInternal(State, + IdtEntry.Selector, + MAKELONG(IdtEntry.Offset, IdtEntry.OffsetHigh), + IdtEntry.Type)) + { + /* Exception occurred */ + return FALSE; + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeIret) +{ + FAST486_SEG_REGS i; + ULONG InstPtr, CodeSel, StackPtr, StackSel; + FAST486_FLAGS_REG NewFlags; + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xCF); + + NO_LOCK_PREFIX(); + TOGGLE_OPSIZE(Size); + + /* Pop EIP */ + if (!Fast486StackPop(State, &InstPtr)) + { + /* Exception occurred */ + return FALSE; + } + + /* Pop CS */ + if (!Fast486StackPop(State, &CodeSel)) + { + /* Exception occurred */ + return FALSE; + } + + /* Pop EFLAGS */ + if (!Fast486StackPop(State, &NewFlags.Long)) + { + /* Exception occurred */ + return FALSE; + } + + /* Check for protected mode */ + if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) + { + INT Cpl = Fast486GetCurrentPrivLevel(State); + + if (State->Flags.Vm) + { + /* Return from VM86 mode */ + + /* Check the IOPL */ + if (State->Flags.Iopl == 3) + { + /* Set new EIP */ + State->InstPtr.Long = LOWORD(InstPtr); + + /* Load new CS */ + if (!Fast486LoadSegment(State, FAST486_REG_CS, CodeSel)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set the new flags */ + if (Size) State->Flags.Long = NewFlags.Long & REAL_MODE_FLAGS_MASK; + else State->Flags.LowWord = NewFlags.LowWord & REAL_MODE_FLAGS_MASK; + State->Flags.AlwaysSet = State->Flags.Vm = TRUE; + State->Flags.Iopl = 3; + } + else + { + /* Call the VM86 monitor */ + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, 0); + return FALSE; + } + + return TRUE; + } + + if (State->Flags.Nt) + { + /* Nested task return */ + + UNIMPLEMENTED; + return FALSE; + } + + if (NewFlags.Vm) + { + /* Return to VM86 mode */ + ULONG Es, Ds, Fs, Gs; + + /* Pop ESP, SS, ES, FS, GS */ + if (!Fast486StackPop(State, &StackPtr)) return FALSE; + if (!Fast486StackPop(State, &StackSel)) return FALSE; + if (!Fast486StackPop(State, &Es)) return FALSE; + if (!Fast486StackPop(State, &Ds)) return FALSE; + if (!Fast486StackPop(State, &Fs)) return FALSE; + if (!Fast486StackPop(State, &Gs)) return FALSE; + + /* Set the new IP */ + State->InstPtr.Long = LOWORD(InstPtr); + + /* Set the new flags */ + if (Size) State->Flags.Long = NewFlags.Long & REAL_MODE_FLAGS_MASK; + else State->Flags.LowWord = NewFlags.LowWord & REAL_MODE_FLAGS_MASK; + State->Flags.AlwaysSet = State->Flags.Vm = TRUE; + + /* Load the new segments */ + if (!Fast486LoadSegment(State, FAST486_REG_CS, CodeSel)) return FALSE; + if (!Fast486LoadSegment(State, FAST486_REG_SS, StackSel)) return FALSE; + if (!Fast486LoadSegment(State, FAST486_REG_ES, Es)) return FALSE; + if (!Fast486LoadSegment(State, FAST486_REG_DS, Ds)) return FALSE; + if (!Fast486LoadSegment(State, FAST486_REG_FS, Fs)) return FALSE; + if (!Fast486LoadSegment(State, FAST486_REG_GS, Gs)) return FALSE; + + return TRUE; + } + + /* Load the new CS */ + if (!Fast486LoadSegment(State, FAST486_REG_CS, CodeSel)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set EIP */ + if (Size) State->InstPtr.Long = InstPtr; + else State->InstPtr.LowWord = LOWORD(InstPtr); + + if (GET_SEGMENT_RPL(CodeSel) > Cpl) + { + /* Pop ESP */ + if (!Fast486StackPop(State, &StackPtr)) + { + /* Exception */ + return FALSE; + } + + /* Pop SS */ + if (!Fast486StackPop(State, &StackSel)) + { + /* Exception */ + return FALSE; + } + + /* Load new SS */ + if (!Fast486LoadSegment(State, FAST486_REG_SS, StackSel)) + { + /* Exception */ + return FALSE; + } + + /* Set ESP */ + if (Size) State->GeneralRegs[FAST486_REG_ESP].Long = StackPtr; + else State->GeneralRegs[FAST486_REG_ESP].LowWord = LOWORD(StackPtr); + } + + /* Set the new flags */ + if (Size) State->Flags.Long = NewFlags.Long & PROT_MODE_FLAGS_MASK; + else State->Flags.LowWord = NewFlags.LowWord & PROT_MODE_FLAGS_MASK; + State->Flags.AlwaysSet = TRUE; + + /* Set additional flags */ + if (Cpl <= State->Flags.Iopl) State->Flags.If = NewFlags.If; + if (Cpl == 0) State->Flags.Iopl = NewFlags.Iopl; + + if (GET_SEGMENT_RPL(CodeSel) > Cpl) + { + /* Update the CPL */ + Cpl = Fast486GetCurrentPrivLevel(State); + + /* Check segment security */ + for (i = 0; i < FAST486_NUM_SEG_REGS; i++) + { + /* Don't check CS or SS */ + if ((i == FAST486_REG_CS) || (i == FAST486_REG_SS)) continue; + + if ((Cpl > State->SegmentRegs[i].Dpl) + && (!State->SegmentRegs[i].Executable + || !State->SegmentRegs[i].DirConf)) + { + /* Load the NULL descriptor in the segment */ + if (!Fast486LoadSegment(State, i, 0)) return FALSE; + } + } + } + } + else + { + if (Size && (InstPtr & 0xFFFF0000)) + { + /* Invalid */ + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, 0); + return FALSE; + } + + /* Set new EIP */ + State->InstPtr.Long = InstPtr; + + /* Load new CS */ + if (!Fast486LoadSegment(State, FAST486_REG_CS, CodeSel)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set the new flags */ + if (Size) State->Flags.Long = NewFlags.Long & REAL_MODE_FLAGS_MASK; + else State->Flags.LowWord = NewFlags.LowWord & REAL_MODE_FLAGS_MASK; + State->Flags.AlwaysSet = TRUE; + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeAam) +{ + UCHAR Base; + UCHAR Value = State->GeneralRegs[FAST486_REG_EAX].LowByte; + + NO_LOCK_PREFIX(); + + /* Fetch the base */ + if (!Fast486FetchByte(State, &Base)) + { + /* Exception occurred */ + return FALSE; + } + + /* Check if the base is zero */ + if (Base == 0) + { + /* Divide error */ + Fast486Exception(State, FAST486_EXCEPTION_DE); + return FALSE; + } + + /* Adjust */ + State->GeneralRegs[FAST486_REG_EAX].HighByte = Value / Base; + State->GeneralRegs[FAST486_REG_EAX].LowByte = Value %= Base; + + /* Update flags */ + State->Flags.Af = FALSE; + State->Flags.Zf = (Value == 0); + State->Flags.Sf = ((Value & SIGN_FLAG_BYTE) != 0); + State->Flags.Pf = Fast486CalculateParity(Value); + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeAad) +{ + UCHAR Base; + UCHAR Value = State->GeneralRegs[FAST486_REG_EAX].LowByte; + + NO_LOCK_PREFIX(); + + /* Fetch the base */ + if (!Fast486FetchByte(State, &Base)) + { + /* Exception occurred */ + return FALSE; + } + + /* Adjust */ + Value += State->GeneralRegs[FAST486_REG_EAX].HighByte * Base; + State->GeneralRegs[FAST486_REG_EAX].LowWord = Value; + + /* Update flags */ + State->Flags.Af = FALSE; + State->Flags.Zf = (Value == 0); + State->Flags.Sf = ((Value & SIGN_FLAG_BYTE) != 0); + State->Flags.Pf = Fast486CalculateParity(Value); + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeXlat) +{ + UCHAR Value; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_ADSIZE(AddressSize); + + /* Read a byte from DS:[(E)BX + AL] */ + if (!Fast486ReadMemory(State, + FAST486_REG_DS, + (AddressSize ? State->GeneralRegs[FAST486_REG_EBX].Long + : State->GeneralRegs[FAST486_REG_EBX].LowWord) + + State->GeneralRegs[FAST486_REG_EAX].LowByte, + FALSE, + &Value, + sizeof(UCHAR))) + { + /* Exception occurred */ + return FALSE; + } + + /* Set AL to the result */ + State->GeneralRegs[FAST486_REG_EAX].LowByte = Value; + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeLoop) +{ + BOOLEAN Condition; + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + CHAR Offset = 0; + + /* Make sure this is the right instruction */ + ASSERT((Opcode >= 0xE0) && (Opcode <= 0xE2)); + + NO_LOCK_PREFIX(); + TOGGLE_ADSIZE(Size); + + if (Size) Condition = ((--State->GeneralRegs[FAST486_REG_ECX].Long) != 0); + else Condition = ((--State->GeneralRegs[FAST486_REG_ECX].LowWord) != 0); + + if (Opcode == 0xE0) + { + /* Additional rule for LOOPNZ */ + if (State->Flags.Zf) Condition = FALSE; + } + + if (Opcode == 0xE1) + { + /* Additional rule for LOOPZ */ + if (!State->Flags.Zf) Condition = FALSE; + } + + /* Fetch the offset */ + if (!Fast486FetchByte(State, (PUCHAR)&Offset)) + { + /* An exception occurred */ + return FALSE; + } + + if (Condition) + { + /* Move the instruction pointer */ + if (Size) State->InstPtr.Long += Offset; + else State->InstPtr.LowWord += Offset; + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeJecxz) +{ + BOOLEAN Condition; + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + CHAR Offset = 0; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xE3); + + NO_LOCK_PREFIX(); + TOGGLE_ADSIZE(Size); + + if (Size) Condition = (State->GeneralRegs[FAST486_REG_ECX].Long == 0); + else Condition = (State->GeneralRegs[FAST486_REG_ECX].LowWord == 0); + + /* Fetch the offset */ + if (!Fast486FetchByte(State, (PUCHAR)&Offset)) + { + /* An exception occurred */ + return FALSE; + } + + if (Condition) + { + /* Move the instruction pointer */ + if (Size) State->InstPtr.Long += Offset; + else State->InstPtr.LowWord += Offset; + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeCall) +{ + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xE8); + + TOGGLE_OPSIZE(Size); + NO_LOCK_PREFIX(); + + if (Size) + { + LONG Offset = 0; + + /* Fetch the offset */ + if (!Fast486FetchDword(State, (PULONG)&Offset)) + { + /* An exception occurred */ + return FALSE; + } + + /* Push the current value of the instruction pointer */ + if (!Fast486StackPush(State, State->InstPtr.Long)) + { + /* Exception occurred */ + return FALSE; + } + + /* Move the instruction pointer */ + State->InstPtr.Long += Offset; + } + else + { + SHORT Offset = 0; + + /* Fetch the offset */ + if (!Fast486FetchWord(State, (PUSHORT)&Offset)) + { + /* An exception occurred */ + return FALSE; + } + + /* Push the current value of the instruction pointer */ + if (!Fast486StackPush(State, State->InstPtr.Long)) + { + /* Exception occurred */ + return FALSE; + } + + /* Move the instruction pointer */ + State->InstPtr.LowWord += Offset; + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeJmp) +{ + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xE9); + + TOGGLE_OPSIZE(Size); + NO_LOCK_PREFIX(); + + if (Size) + { + LONG Offset = 0; + + /* Fetch the offset */ + if (!Fast486FetchDword(State, (PULONG)&Offset)) + { + /* An exception occurred */ + return FALSE; + } + + /* Move the instruction pointer */ + State->InstPtr.Long += Offset; + } + else + { + SHORT Offset = 0; + + /* Fetch the offset */ + if (!Fast486FetchWord(State, (PUSHORT)&Offset)) + { + /* An exception occurred */ + return FALSE; + } + + /* Move the instruction pointer */ + State->InstPtr.Long += Offset; + + /* Clear the top half of EIP */ + State->InstPtr.Long &= 0xFFFF; + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeJmpAbs) +{ + USHORT Segment = 0; + ULONG Offset = 0; + BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xEA); + + TOGGLE_OPSIZE(Size); + NO_LOCK_PREFIX(); + + /* Fetch the offset */ + if (Size) + { + if (!Fast486FetchDword(State, &Offset)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + if (!Fast486FetchWord(State, (PUSHORT)&Offset)) + { + /* Exception occurred */ + return FALSE; + } + } + + /* Fetch the segment */ + if (!Fast486FetchWord(State, &Segment)) + { + /* Exception occurred */ + return FALSE; + } + + /* Load the new CS */ + if (!Fast486LoadSegment(State, FAST486_REG_CS, Segment)) + { + /* Exception occurred */ + return FALSE; + } + + /* Load new EIP */ + State->InstPtr.Long = Offset; + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeMovAlOffset) +{ + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + ULONG Offset; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xA0); + + TOGGLE_ADSIZE(AddressSize); + + if (AddressSize) + { + if (!Fast486FetchDword(State, &Offset)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + USHORT WordOffset; + + if (!Fast486FetchWord(State, &WordOffset)) + { + /* Exception occurred */ + return FALSE; + } + + Offset = (ULONG)WordOffset; + } + + /* Read from memory */ + return Fast486ReadMemory(State, + (State->PrefixFlags & FAST486_PREFIX_SEG) ? + State->SegmentOverride : FAST486_REG_DS, + Offset, + FALSE, + &State->GeneralRegs[FAST486_REG_EAX].LowByte, + sizeof(UCHAR)); +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeMovEaxOffset) +{ + BOOLEAN OperandSize, AddressSize; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xA1); + + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + if (AddressSize) + { + ULONG Offset; + + if (!Fast486FetchDword(State, &Offset)) + { + /* Exception occurred */ + return FALSE; + } + + /* Read from memory */ + if (OperandSize) + { + return Fast486ReadMemory(State, + (State->PrefixFlags & FAST486_PREFIX_SEG) ? + State->SegmentOverride : FAST486_REG_DS, + Offset, + FALSE, + &State->GeneralRegs[FAST486_REG_EAX].Long, + sizeof(ULONG)); + } + else + { + return Fast486ReadMemory(State, + (State->PrefixFlags & FAST486_PREFIX_SEG) ? + State->SegmentOverride : FAST486_REG_DS, + Offset, + FALSE, + &State->GeneralRegs[FAST486_REG_EAX].LowWord, + sizeof(USHORT)); + } + } + else + { + USHORT Offset; + + if (!Fast486FetchWord(State, &Offset)) + { + /* Exception occurred */ + return FALSE; + } + + /* Read from memory */ + if (OperandSize) + { + return Fast486ReadMemory(State, + (State->PrefixFlags & FAST486_PREFIX_SEG) ? + State->SegmentOverride : FAST486_REG_DS, + Offset, + FALSE, + &State->GeneralRegs[FAST486_REG_EAX].Long, + sizeof(ULONG)); + } + else + { + return Fast486ReadMemory(State, + (State->PrefixFlags & FAST486_PREFIX_SEG) ? + State->SegmentOverride : FAST486_REG_DS, + Offset, + FALSE, + &State->GeneralRegs[FAST486_REG_EAX].LowWord, + sizeof(USHORT)); + } + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeMovOffsetAl) +{ + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + ULONG Offset; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xA2); + + TOGGLE_ADSIZE(AddressSize); + + if (AddressSize) + { + if (!Fast486FetchDword(State, &Offset)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + USHORT WordOffset; + + if (!Fast486FetchWord(State, &WordOffset)) + { + /* Exception occurred */ + return FALSE; + } + + Offset = (ULONG)WordOffset; + } + + /* Write to memory */ + return Fast486WriteMemory(State, + (State->PrefixFlags & FAST486_PREFIX_SEG) ? + State->SegmentOverride : FAST486_REG_DS, + Offset, + &State->GeneralRegs[FAST486_REG_EAX].LowByte, + sizeof(UCHAR)); +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeMovOffsetEax) +{ + BOOLEAN OperandSize, AddressSize; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xA3); + + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + if (AddressSize) + { + ULONG Offset; + + if (!Fast486FetchDword(State, &Offset)) + { + /* Exception occurred */ + return FALSE; + } + + /* Write to memory */ + if (OperandSize) + { + return Fast486WriteMemory(State, + (State->PrefixFlags & FAST486_PREFIX_SEG) ? + State->SegmentOverride : FAST486_REG_DS, + Offset, + &State->GeneralRegs[FAST486_REG_EAX].Long, + sizeof(ULONG)); + } + else + { + return Fast486WriteMemory(State, + (State->PrefixFlags & FAST486_PREFIX_SEG) ? + State->SegmentOverride : FAST486_REG_DS, + Offset, + &State->GeneralRegs[FAST486_REG_EAX].LowWord, + sizeof(USHORT)); + } + } + else + { + USHORT Offset; + + if (!Fast486FetchWord(State, &Offset)) + { + /* Exception occurred */ + return FALSE; + } + + /* Write to memory */ + if (OperandSize) + { + return Fast486WriteMemory(State, + (State->PrefixFlags & FAST486_PREFIX_SEG) ? + State->SegmentOverride : FAST486_REG_DS, + Offset, + &State->GeneralRegs[FAST486_REG_EAX].Long, + sizeof(ULONG)); + } + else + { + return Fast486WriteMemory(State, + (State->PrefixFlags & FAST486_PREFIX_SEG) ? + State->SegmentOverride : FAST486_REG_DS, + Offset, + &State->GeneralRegs[FAST486_REG_EAX].LowWord, + sizeof(USHORT)); + } + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeSalc) +{ + /* Make sure this is the right instruction */ + ASSERT(Opcode == 0xD6); + + NO_LOCK_PREFIX(); + + /* Set all the bits of AL to CF */ + State->GeneralRegs[FAST486_REG_EAX].LowByte = State->Flags.Cf ? 0xFF : 0x00; + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeMovs) +{ + ULONG Data, DataSize; + BOOLEAN OperandSize, AddressSize; + FAST486_SEG_REGS Segment = FAST486_REG_DS; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFE) == 0xA4); + + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + if (State->PrefixFlags & FAST486_PREFIX_SEG) + { + /* Use the override segment instead of DS */ + Segment = State->SegmentOverride; + } + + if (State->PrefixFlags & FAST486_PREFIX_REP) + { + if ((AddressSize && (State->GeneralRegs[FAST486_REG_ECX].Long == 0)) + || (!AddressSize && (State->GeneralRegs[FAST486_REG_ECX].LowWord == 0))) + { + /* Do nothing */ + return TRUE; + } + } + + /* Calculate the size */ + if (Opcode == 0xA4) DataSize = sizeof(UCHAR); + else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT); + + /* Read from the source operand */ + if (!Fast486ReadMemory(State, + Segment, + AddressSize ? State->GeneralRegs[FAST486_REG_ESI].Long + : State->GeneralRegs[FAST486_REG_ESI].LowWord, + FALSE, + &Data, + DataSize)) + { + /* Exception occurred */ + return FALSE; + } + + /* Write to the destination operand */ + if (!Fast486WriteMemory(State, + FAST486_REG_ES, + AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long + : State->GeneralRegs[FAST486_REG_EDI].LowWord, + &Data, + DataSize)) + { + /* Exception occurred */ + return FALSE; + } + + /* Increment/decrement ESI and EDI */ + if (AddressSize) + { + if (!State->Flags.Df) + { + State->GeneralRegs[FAST486_REG_ESI].Long += DataSize; + State->GeneralRegs[FAST486_REG_EDI].Long += DataSize; + } + else + { + State->GeneralRegs[FAST486_REG_ESI].Long -= DataSize; + State->GeneralRegs[FAST486_REG_EDI].Long -= DataSize; + } + } + else + { + if (!State->Flags.Df) + { + State->GeneralRegs[FAST486_REG_ESI].LowWord += DataSize; + State->GeneralRegs[FAST486_REG_EDI].LowWord += DataSize; + } + else + { + State->GeneralRegs[FAST486_REG_ESI].LowWord -= DataSize; + State->GeneralRegs[FAST486_REG_EDI].LowWord -= DataSize; + } + } + + // FIXME: This method is slow! + if (State->PrefixFlags & FAST486_PREFIX_REP) + { + if (AddressSize) + { + if (--State->GeneralRegs[FAST486_REG_ECX].Long) + { + /* Repeat the instruction */ + State->InstPtr = State->SavedInstPtr; + } + } + else + { + if (--State->GeneralRegs[FAST486_REG_ECX].LowWord) + { + /* Repeat the instruction */ + State->InstPtr = State->SavedInstPtr; + } + } + } + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeCmps) +{ + ULONG FirstValue = 0, SecondValue = 0, Result; + ULONG DataSize, DataMask, SignFlag; + BOOLEAN OperandSize, AddressSize; + FAST486_SEG_REGS Segment = FAST486_REG_DS; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFE) == 0xA6); + + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + if (State->PrefixFlags & FAST486_PREFIX_SEG) + { + /* Use the override segment instead of DS */ + Segment = State->SegmentOverride; + } + + if ((State->PrefixFlags & FAST486_PREFIX_REP) + || (State->PrefixFlags & FAST486_PREFIX_REPNZ)) + { + if ((AddressSize && (State->GeneralRegs[FAST486_REG_ECX].Long == 0)) + || (!AddressSize && (State->GeneralRegs[FAST486_REG_ECX].LowWord == 0))) + { + /* Do nothing */ + return TRUE; + } + } + + /* Calculate the size */ + if (Opcode == 0xA6) DataSize = sizeof(UCHAR); + else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT); + + /* Calculate the mask and sign flag */ + SignFlag = 1 << ((DataSize * 8) - 1); + DataMask = SignFlag | (SignFlag - 1); + + /* Read from the first source operand */ + if (!Fast486ReadMemory(State, + Segment, + AddressSize ? State->GeneralRegs[FAST486_REG_ESI].Long + : State->GeneralRegs[FAST486_REG_ESI].LowWord, + FALSE, + &FirstValue, + DataSize)) + { + /* Exception occurred */ + return FALSE; + } + + /* Read from the second source operand */ + if (!Fast486ReadMemory(State, + FAST486_REG_ES, + AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long + : State->GeneralRegs[FAST486_REG_EDI].LowWord, + FALSE, + &SecondValue, + DataSize)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + FirstValue &= DataMask; + SecondValue &= DataMask; + Result = (FirstValue - SecondValue) & DataMask; + + /* Update the flags */ + State->Flags.Cf = (FirstValue < SecondValue); + State->Flags.Of = ((FirstValue & SignFlag) != (SecondValue & SignFlag)) + && ((FirstValue & SignFlag) != (Result & SignFlag)); + State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SignFlag) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Increment/decrement ESI and EDI */ + if (AddressSize) + { + if (!State->Flags.Df) + { + State->GeneralRegs[FAST486_REG_ESI].Long += DataSize; + State->GeneralRegs[FAST486_REG_EDI].Long += DataSize; + } + else + { + State->GeneralRegs[FAST486_REG_ESI].Long -= DataSize; + State->GeneralRegs[FAST486_REG_EDI].Long -= DataSize; + } + } + else + { + if (!State->Flags.Df) + { + State->GeneralRegs[FAST486_REG_ESI].LowWord += DataSize; + State->GeneralRegs[FAST486_REG_EDI].LowWord += DataSize; + } + else + { + State->GeneralRegs[FAST486_REG_ESI].LowWord -= DataSize; + State->GeneralRegs[FAST486_REG_EDI].LowWord -= DataSize; + } + } + + // FIXME: This method is slow! + if ((State->PrefixFlags & FAST486_PREFIX_REP) + || (State->PrefixFlags & FAST486_PREFIX_REPNZ)) + { + BOOLEAN Repeat = TRUE; + + if (AddressSize) + { + if ((--State->GeneralRegs[FAST486_REG_ECX].Long) == 0) + { + /* ECX is 0 */ + Repeat = FALSE; + } + } + else + { + if ((--State->GeneralRegs[FAST486_REG_ECX].LowWord) == 0) + { + /* CX is 0 */ + Repeat = FALSE; + } + } + + if (((State->PrefixFlags & FAST486_PREFIX_REP) && !State->Flags.Zf) + || ((State->PrefixFlags & FAST486_PREFIX_REPNZ) && State->Flags.Zf)) + { + /* REPZ with ZF = 0 or REPNZ with ZF = 1 */ + Repeat = FALSE; + } + + if (Repeat) + { + /* Repeat the instruction */ + State->InstPtr = State->SavedInstPtr; + } + } + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeStos) +{ + ULONG DataSize; + BOOLEAN OperandSize, AddressSize; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFE) == 0xAA); + + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + /* Calculate the size */ + if (Opcode == 0xAA) DataSize = sizeof(UCHAR); + else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT); + + if (State->PrefixFlags & FAST486_PREFIX_REP) + { + UCHAR Block[STRING_BLOCK_SIZE]; + ULONG Count = AddressSize ? State->GeneralRegs[FAST486_REG_ECX].Long + : State->GeneralRegs[FAST486_REG_ECX].LowWord; + + /* Fill the memory block with the data */ + if (DataSize == sizeof(UCHAR)) + { + RtlFillMemory(Block, sizeof(Block), State->GeneralRegs[FAST486_REG_EAX].LowByte); + } + else + { + ULONG i; + + for (i = 0; i < STRING_BLOCK_SIZE / DataSize; i++) + { + if (DataSize == sizeof(USHORT)) + { + ((PUSHORT)Block)[i] = State->GeneralRegs[FAST486_REG_EAX].LowWord; + } + else + { + ((PULONG)Block)[i] = State->GeneralRegs[FAST486_REG_EAX].Long; + } + } + } + + /* Transfer until finished */ + while (Count) + { + ULONG Processed = min(Count, STRING_BLOCK_SIZE / DataSize); + + /* Simulate the 16-bit wrap-around of DI in 16-bit address mode */ + if (!AddressSize) + { + ULONG MaxBytes = State->Flags.Df + ? (ULONG)State->GeneralRegs[FAST486_REG_EDI].LowWord + : (0x10000 - (ULONG)State->GeneralRegs[FAST486_REG_EDI].LowWord); + + Processed = min(Processed, MaxBytes / DataSize); + if (Processed == 0) Processed = 1; + } + + if (State->Flags.Df) + { + /* Set EDI to the starting location */ + if (AddressSize) State->GeneralRegs[FAST486_REG_EDI].Long -= (Processed - 1) * DataSize; + else State->GeneralRegs[FAST486_REG_EDI].LowWord -= (Processed - 1) * DataSize; + } + + /* Write to memory */ + if (!Fast486WriteMemory(State, + FAST486_REG_ES, + AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long + : State->GeneralRegs[FAST486_REG_EDI].LowWord, + Block, + Processed * DataSize)) + { + /* Set ECX */ + if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = Count; + else State->GeneralRegs[FAST486_REG_ECX].LowWord = LOWORD(Count); + + /* Exception occurred */ + return FALSE; + } + + if (!State->Flags.Df) + { + /* Increase EDI by the number of bytes transfered */ + if (AddressSize) State->GeneralRegs[FAST486_REG_EDI].Long += Processed * DataSize; + else State->GeneralRegs[FAST486_REG_EDI].LowWord += Processed * DataSize; + } + else + { + /* Reduce EDI */ + if (AddressSize) State->GeneralRegs[FAST486_REG_EDI].Long -= DataSize; + else State->GeneralRegs[FAST486_REG_EDI].LowWord -= DataSize; + } + + /* Reduce the total count by the number processed in this run */ + Count -= Processed; + } + + /* Clear ECX */ + if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = 0; + else State->GeneralRegs[FAST486_REG_ECX].LowWord = 0; + } + else + { + /* Write to the destination operand */ + if (!Fast486WriteMemory(State, + FAST486_REG_ES, + AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long + : State->GeneralRegs[FAST486_REG_EDI].LowWord, + &State->GeneralRegs[FAST486_REG_EAX].Long, + DataSize)) + { + /* Exception occurred */ + return FALSE; + } + + /* Increment/decrement EDI */ + if (AddressSize) + { + if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_EDI].Long += DataSize; + else State->GeneralRegs[FAST486_REG_EDI].Long -= DataSize; + } + else + { + if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_EDI].LowWord += DataSize; + else State->GeneralRegs[FAST486_REG_EDI].LowWord -= DataSize; + } + } + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeLods) +{ + ULONG DataSize; + BOOLEAN OperandSize, AddressSize; + FAST486_SEG_REGS Segment = FAST486_REG_DS; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFE) == 0xAC); + + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + if (State->PrefixFlags & FAST486_PREFIX_SEG) + { + /* Use the override segment instead of DS */ + Segment = State->SegmentOverride; + } + + /* Calculate the size */ + if (Opcode == 0xAC) DataSize = sizeof(UCHAR); + else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT); + + if (State->PrefixFlags & FAST486_PREFIX_REP) + { + ULONG Count = AddressSize ? State->GeneralRegs[FAST486_REG_ECX].Long + : State->GeneralRegs[FAST486_REG_ECX].LowWord; + + /* If the count is 0, do nothing */ + if (Count == 0) return TRUE; + + /* Only the last entry will be loaded */ + if (!State->Flags.Df) + { + if (AddressSize) State->GeneralRegs[FAST486_REG_ESI].Long += (Count - 1) * DataSize; + else State->GeneralRegs[FAST486_REG_ESI].LowWord += (Count - 1) * DataSize; + } + else + { + if (AddressSize) State->GeneralRegs[FAST486_REG_ESI].Long -= (Count - 1) * DataSize; + else State->GeneralRegs[FAST486_REG_ESI].LowWord -= (Count - 1) * DataSize; + } + + /* Clear ECX */ + if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = 0; + else State->GeneralRegs[FAST486_REG_ECX].LowWord = 0; + } + + /* Read from the source operand */ + if (!Fast486ReadMemory(State, + Segment, + AddressSize ? State->GeneralRegs[FAST486_REG_ESI].Long + : State->GeneralRegs[FAST486_REG_ESI].LowWord, + FALSE, + &State->GeneralRegs[FAST486_REG_EAX].Long, + DataSize)) + { + /* Exception occurred */ + return FALSE; + } + + /* Increment/decrement ESI */ + if (AddressSize) + { + if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_ESI].Long += DataSize; + else State->GeneralRegs[FAST486_REG_ESI].Long -= DataSize; + } + else + { + if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_ESI].LowWord += DataSize; + else State->GeneralRegs[FAST486_REG_ESI].LowWord -= DataSize; + } + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeScas) +{ + ULONG FirstValue = State->GeneralRegs[FAST486_REG_EAX].Long; + ULONG SecondValue = 0; + ULONG Result; + ULONG DataSize, DataMask, SignFlag; + BOOLEAN OperandSize, AddressSize; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFE) == 0xAE); + + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + if ((State->PrefixFlags & FAST486_PREFIX_REP) + || (State->PrefixFlags & FAST486_PREFIX_REPNZ)) + { + if ((AddressSize && (State->GeneralRegs[FAST486_REG_ECX].Long == 0)) + || (!AddressSize && (State->GeneralRegs[FAST486_REG_ECX].LowWord == 0))) + { + /* Do nothing */ + return TRUE; + } + } + + /* Calculate the size */ + if (Opcode == 0xAE) DataSize = sizeof(UCHAR); + else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT); + + /* Calculate the mask and sign flag */ + SignFlag = 1 << ((DataSize * 8) - 1); + DataMask = SignFlag | (SignFlag - 1); + + /* Read from the source operand */ + if (!Fast486ReadMemory(State, + FAST486_REG_ES, + AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long + : State->GeneralRegs[FAST486_REG_EDI].LowWord, + FALSE, + &SecondValue, + DataSize)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + FirstValue &= DataMask; + SecondValue &= DataMask; + Result = (FirstValue - SecondValue) & DataMask; + + /* Update the flags */ + State->Flags.Cf = (FirstValue < SecondValue); + State->Flags.Of = ((FirstValue & SignFlag) != (SecondValue & SignFlag)) + && ((FirstValue & SignFlag) != (Result & SignFlag)); + State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SignFlag) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Increment/decrement EDI */ + if (AddressSize) + { + if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_EDI].Long += DataSize; + else State->GeneralRegs[FAST486_REG_EDI].Long -= DataSize; + } + else + { + if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_EDI].LowWord += DataSize; + else State->GeneralRegs[FAST486_REG_EDI].LowWord -= DataSize; + } + + // FIXME: This method is slow! + if ((State->PrefixFlags & FAST486_PREFIX_REP) + || (State->PrefixFlags & FAST486_PREFIX_REPNZ)) + { + BOOLEAN Repeat = TRUE; + + if (AddressSize) + { + if ((--State->GeneralRegs[FAST486_REG_ECX].Long) == 0) + { + /* ECX is 0 */ + Repeat = FALSE; + } + } + else + { + if ((--State->GeneralRegs[FAST486_REG_ECX].LowWord) == 0) + { + /* CX is 0 */ + Repeat = FALSE; + } + } + + if (((State->PrefixFlags & FAST486_PREFIX_REP) && !State->Flags.Zf) + || ((State->PrefixFlags & FAST486_PREFIX_REPNZ) && State->Flags.Zf)) + { + /* REPZ with ZF = 0 or REPNZ with ZF = 1 */ + Repeat = FALSE; + } + + if (Repeat) + { + /* Repeat the instruction */ + State->InstPtr = State->SavedInstPtr; + } + } + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeIns) +{ + ULONG DataSize; + BOOLEAN OperandSize, AddressSize; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFE) == 0x6C); + + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + /* Calculate the size */ + if (Opcode == 0x6C) DataSize = sizeof(UCHAR); + else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT); + + if (State->PrefixFlags & FAST486_PREFIX_REP) + { + UCHAR Block[STRING_BLOCK_SIZE]; + ULONG Count = AddressSize ? State->GeneralRegs[FAST486_REG_ECX].Long + : State->GeneralRegs[FAST486_REG_ECX].LowWord; + + /* Clear the memory block */ + RtlZeroMemory(Block, sizeof(Block)); + + /* Transfer until finished */ + while (Count) + { + ULONG Processed = min(Count, STRING_BLOCK_SIZE / DataSize); + + /* Simulate the 16-bit wrap-around of DI in 16-bit address mode */ + if (!AddressSize) + { + ULONG MaxBytes = State->Flags.Df + ? (ULONG)State->GeneralRegs[FAST486_REG_EDI].LowWord + : (0x10000 - (ULONG)State->GeneralRegs[FAST486_REG_EDI].LowWord); + + Processed = min(Processed, MaxBytes / DataSize); + if (Processed == 0) Processed = 1; + } + + /* Read from the I/O port */ + State->IoReadCallback(State, + State->GeneralRegs[FAST486_REG_EDX].LowWord, + Block, + Processed, + DataSize); + + if (State->Flags.Df) + { + ULONG i, j; + + /* Reduce EDI by the number of bytes to transfer */ + if (AddressSize) State->GeneralRegs[FAST486_REG_EDI].Long -= Processed * DataSize; + else State->GeneralRegs[FAST486_REG_EDI].LowWord -= Processed * DataSize; + + /* Reverse the block data */ + for (i = 0; i < Processed / 2; i++) + { + /* Swap the values */ + for (j = 0; j < DataSize; j++) + { + UCHAR Temp = Block[i * DataSize + j]; + Block[i * DataSize + j] = Block[(Processed - i - 1) * DataSize + j]; + Block[(Processed - i - 1) * DataSize + j] = Temp; + } + } + } + + /* Write to memory */ + if (!Fast486WriteMemory(State, + FAST486_REG_ES, + AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long + : State->GeneralRegs[FAST486_REG_EDI].LowWord, + Block, + Processed * DataSize)) + { + /* Set ECX */ + if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = Count; + else State->GeneralRegs[FAST486_REG_ECX].LowWord = LOWORD(Count); + + /* Exception occurred */ + return FALSE; + } + + if (!State->Flags.Df) + { + /* Increase EDI by the number of bytes transfered */ + if (AddressSize) State->GeneralRegs[FAST486_REG_EDI].Long += Processed * DataSize; + else State->GeneralRegs[FAST486_REG_EDI].LowWord += Processed * DataSize; + } + + /* Reduce the total count by the number processed in this run */ + Count -= Processed; + } + + /* Clear ECX */ + if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = 0; + else State->GeneralRegs[FAST486_REG_ECX].LowWord = 0; + } + else + { + ULONG Data = 0; + + /* Read from the I/O port */ + State->IoReadCallback(State, + State->GeneralRegs[FAST486_REG_EDX].LowWord, + &Data, + 1, + DataSize); + + /* Write to the destination operand */ + if (!Fast486WriteMemory(State, + FAST486_REG_ES, + AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long + : State->GeneralRegs[FAST486_REG_EDI].LowWord, + &Data, + DataSize)) + { + /* Exception occurred */ + return FALSE; + } + + /* Increment/decrement EDI */ + if (AddressSize) + { + if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_EDI].Long += DataSize; + else State->GeneralRegs[FAST486_REG_EDI].Long -= DataSize; + } + else + { + if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_EDI].LowWord += DataSize; + else State->GeneralRegs[FAST486_REG_EDI].LowWord -= DataSize; + } + } + + /* Return success */ + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeOuts) +{ + ULONG DataSize; + BOOLEAN OperandSize, AddressSize; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + /* Make sure this is the right instruction */ + ASSERT((Opcode & 0xFE) == 0x6E); + + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + /* Calculate the size */ + if (Opcode == 0x6E) DataSize = sizeof(UCHAR); + else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT); + + if (State->PrefixFlags & FAST486_PREFIX_REP) + { + UCHAR Block[STRING_BLOCK_SIZE]; + ULONG Count = AddressSize ? State->GeneralRegs[FAST486_REG_ECX].Long + : State->GeneralRegs[FAST486_REG_ECX].LowWord; + + /* Clear the memory block */ + RtlZeroMemory(Block, sizeof(Block)); + + /* Transfer until finished */ + while (Count) + { + ULONG Processed = min(Count, STRING_BLOCK_SIZE / DataSize); + + /* Simulate the 16-bit wrap-around of DI in 16-bit address mode */ + if (!AddressSize) + { + ULONG MaxBytes = State->Flags.Df + ? (ULONG)State->GeneralRegs[FAST486_REG_EDI].LowWord + : (0x10000 - (ULONG)State->GeneralRegs[FAST486_REG_EDI].LowWord); + + Processed = min(Processed, MaxBytes / DataSize); + if (Processed == 0) Processed = 1; + } + + /* Read from memory */ + if (!Fast486ReadMemory(State, + FAST486_REG_ES, + AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long + : State->GeneralRegs[FAST486_REG_EDI].LowWord, + FALSE, + Block, + Processed * DataSize)) + { + /* Set ECX */ + if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = Count; + else State->GeneralRegs[FAST486_REG_ECX].LowWord = LOWORD(Count); + + /* Exception occurred */ + return FALSE; + } + + if (State->Flags.Df) + { + ULONG i, j; + + /* Reduce EDI by the number of bytes to transfer */ + if (AddressSize) State->GeneralRegs[FAST486_REG_EDI].Long -= Processed * DataSize; + else State->GeneralRegs[FAST486_REG_EDI].LowWord -= Processed * DataSize; + + /* Reverse the block data */ + for (i = 0; i < Processed / 2; i++) + { + /* Swap the values */ + for (j = 0; j < DataSize; j++) + { + UCHAR Temp = Block[i * DataSize + j]; + Block[i * DataSize + j] = Block[(Processed - i - 1) * DataSize + j]; + Block[(Processed - i - 1) * DataSize + j] = Temp; + } + } + } + + /* Write to the I/O port */ + State->IoWriteCallback(State, + State->GeneralRegs[FAST486_REG_EDX].LowWord, + Block, + Processed, + DataSize); + + if (!State->Flags.Df) + { + /* Increase EDI by the number of bytes transfered */ + if (AddressSize) State->GeneralRegs[FAST486_REG_EDI].Long += Processed * DataSize; + else State->GeneralRegs[FAST486_REG_EDI].LowWord += Processed * DataSize; + } + + /* Reduce the total count by the number processed in this run */ + Count -= Processed; + } + + /* Clear ECX */ + if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = 0; + else State->GeneralRegs[FAST486_REG_ECX].LowWord = 0; + } + else + { + ULONG Data = 0; + + /* Read from the source operand */ + if (!Fast486ReadMemory(State, + FAST486_REG_DS, + AddressSize ? State->GeneralRegs[FAST486_REG_ESI].Long + : State->GeneralRegs[FAST486_REG_ESI].LowWord, + FALSE, + &Data, + DataSize)) + { + /* Exception occurred */ + return FALSE; + } + + /* Write to the I/O port */ + State->IoWriteCallback(State, + State->GeneralRegs[FAST486_REG_EDX].LowWord, + &Data, + 1, + DataSize); + + /* Increment/decrement ESI */ + if (AddressSize) + { + if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_ESI].Long += DataSize; + else State->GeneralRegs[FAST486_REG_ESI].Long -= DataSize; + } + else + { + if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_ESI].LowWord += DataSize; + else State->GeneralRegs[FAST486_REG_ESI].LowWord -= DataSize; + } + } + + /* Return success */ + return TRUE; +} diff --git a/lib/fast486/opcodes.h b/lib/fast486/opcodes.h new file mode 100644 index 00000000000..3d29e4794c7 --- /dev/null +++ b/lib/fast486/opcodes.h @@ -0,0 +1,157 @@ +/* + * Fast486 386/486 CPU Emulation Library + * opcodes.h + * + * Copyright (C) 2013 Aleksandar Andrejevic + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _OPCODES_H_ +#define _OPCODES_H_ + +#pragma once + +/* DEFINES ********************************************************************/ + +#define FAST486_NUM_OPCODE_HANDLERS 256 +#define FAST486_OPCODE_WRITE_REG (1 << 1) +#define FAST486_OPCODE_HANDLER(x) \ + BOOLEAN FASTCALL x(PFAST486_STATE State, UCHAR Opcode) + +typedef BOOLEAN (FASTCALL *FAST486_OPCODE_HANDLER_PROC)(PFAST486_STATE, UCHAR); + +extern +FAST486_OPCODE_HANDLER_PROC +Fast486OpcodeHandlers[FAST486_NUM_OPCODE_HANDLERS]; + +FAST486_OPCODE_HANDLER(Fast486OpcodePrefix); +FAST486_OPCODE_HANDLER(Fast486OpcodeIncrement); +FAST486_OPCODE_HANDLER(Fast486OpcodeDecrement); +FAST486_OPCODE_HANDLER(Fast486OpcodePushReg); +FAST486_OPCODE_HANDLER(Fast486OpcodePopReg); +FAST486_OPCODE_HANDLER(Fast486OpcodeNop); +FAST486_OPCODE_HANDLER(Fast486OpcodeExchangeEax); +FAST486_OPCODE_HANDLER(Fast486OpcodeShortConditionalJmp); +FAST486_OPCODE_HANDLER(Fast486OpcodeClearCarry); +FAST486_OPCODE_HANDLER(Fast486OpcodeSetCarry); +FAST486_OPCODE_HANDLER(Fast486OpcodeComplCarry); +FAST486_OPCODE_HANDLER(Fast486OpcodeClearInt); +FAST486_OPCODE_HANDLER(Fast486OpcodeSetInt); +FAST486_OPCODE_HANDLER(Fast486OpcodeClearDir); +FAST486_OPCODE_HANDLER(Fast486OpcodeSetDir); +FAST486_OPCODE_HANDLER(Fast486OpcodeHalt); +FAST486_OPCODE_HANDLER(Fast486OpcodeInByte); +FAST486_OPCODE_HANDLER(Fast486OpcodeIn); +FAST486_OPCODE_HANDLER(Fast486OpcodeOutByte); +FAST486_OPCODE_HANDLER(Fast486OpcodeOut); +FAST486_OPCODE_HANDLER(Fast486OpcodeShortJump); +FAST486_OPCODE_HANDLER(Fast486OpcodeMovRegImm); +FAST486_OPCODE_HANDLER(Fast486OpcodeMovByteRegImm); +FAST486_OPCODE_HANDLER(Fast486OpcodeAddByteModrm); +FAST486_OPCODE_HANDLER(Fast486OpcodeAddModrm); +FAST486_OPCODE_HANDLER(Fast486OpcodeAddAl); +FAST486_OPCODE_HANDLER(Fast486OpcodeAddEax); +FAST486_OPCODE_HANDLER(Fast486OpcodeOrByteModrm); +FAST486_OPCODE_HANDLER(Fast486OpcodeOrModrm); +FAST486_OPCODE_HANDLER(Fast486OpcodeOrAl); +FAST486_OPCODE_HANDLER(Fast486OpcodeOrEax); +FAST486_OPCODE_HANDLER(Fast486OpcodeAndByteModrm); +FAST486_OPCODE_HANDLER(Fast486OpcodeAndModrm); +FAST486_OPCODE_HANDLER(Fast486OpcodeAndAl); +FAST486_OPCODE_HANDLER(Fast486OpcodeAndEax); +FAST486_OPCODE_HANDLER(Fast486OpcodeXorByteModrm); +FAST486_OPCODE_HANDLER(Fast486OpcodeXorModrm); +FAST486_OPCODE_HANDLER(Fast486OpcodeXorAl); +FAST486_OPCODE_HANDLER(Fast486OpcodeXorEax); +FAST486_OPCODE_HANDLER(Fast486OpcodeTestByteModrm); +FAST486_OPCODE_HANDLER(Fast486OpcodeTestModrm); +FAST486_OPCODE_HANDLER(Fast486OpcodeTestAl); +FAST486_OPCODE_HANDLER(Fast486OpcodeTestEax); +FAST486_OPCODE_HANDLER(Fast486OpcodeXchgByteModrm); +FAST486_OPCODE_HANDLER(Fast486OpcodeXchgModrm); +FAST486_OPCODE_HANDLER(Fast486OpcodePushEs); +FAST486_OPCODE_HANDLER(Fast486OpcodePopEs); +FAST486_OPCODE_HANDLER(Fast486OpcodePushCs); +FAST486_OPCODE_HANDLER(Fast486OpcodeAdcByteModrm); +FAST486_OPCODE_HANDLER(Fast486OpcodeAdcModrm); +FAST486_OPCODE_HANDLER(Fast486OpcodeAdcAl); +FAST486_OPCODE_HANDLER(Fast486OpcodeAdcEax); +FAST486_OPCODE_HANDLER(Fast486OpcodePushSs); +FAST486_OPCODE_HANDLER(Fast486OpcodePopSs); +FAST486_OPCODE_HANDLER(Fast486OpcodeSbbByteModrm); +FAST486_OPCODE_HANDLER(Fast486OpcodeSbbModrm); +FAST486_OPCODE_HANDLER(Fast486OpcodeSbbAl); +FAST486_OPCODE_HANDLER(Fast486OpcodeSbbEax); +FAST486_OPCODE_HANDLER(Fast486OpcodePushDs); +FAST486_OPCODE_HANDLER(Fast486OpcodePopDs); +FAST486_OPCODE_HANDLER(Fast486OpcodeDaa); +FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubByteModrm); +FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubModrm); +FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubAl); +FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubEax); +FAST486_OPCODE_HANDLER(Fast486OpcodeDas); +FAST486_OPCODE_HANDLER(Fast486OpcodeAaa); +FAST486_OPCODE_HANDLER(Fast486OpcodeAas); +FAST486_OPCODE_HANDLER(Fast486OpcodePushAll); +FAST486_OPCODE_HANDLER(Fast486OpcodePopAll); +FAST486_OPCODE_HANDLER(Fast486OpcodeBound); +FAST486_OPCODE_HANDLER(Fast486OpcodeArpl); +FAST486_OPCODE_HANDLER(Fast486OpcodePushImm); +FAST486_OPCODE_HANDLER(Fast486OpcodeImulModrmImm); +FAST486_OPCODE_HANDLER(Fast486OpcodePushByteImm); +FAST486_OPCODE_HANDLER(Fast486OpcodeMovByteModrm); +FAST486_OPCODE_HANDLER(Fast486OpcodeMovModrm); +FAST486_OPCODE_HANDLER(Fast486OpcodeMovStoreSeg); +FAST486_OPCODE_HANDLER(Fast486OpcodeLea); +FAST486_OPCODE_HANDLER(Fast486OpcodeMovLoadSeg); +FAST486_OPCODE_HANDLER(Fast486OpcodeCwde); +FAST486_OPCODE_HANDLER(Fast486OpcodeCdq); +FAST486_OPCODE_HANDLER(Fast486OpcodeCallAbs); +FAST486_OPCODE_HANDLER(Fast486OpcodeWait); +FAST486_OPCODE_HANDLER(Fast486OpcodePushFlags); +FAST486_OPCODE_HANDLER(Fast486OpcodePopFlags); +FAST486_OPCODE_HANDLER(Fast486OpcodeSahf); +FAST486_OPCODE_HANDLER(Fast486OpcodeLahf); +FAST486_OPCODE_HANDLER(Fast486OpcodeRet); +FAST486_OPCODE_HANDLER(Fast486OpcodeLdsLes); +FAST486_OPCODE_HANDLER(Fast486OpcodeEnter); +FAST486_OPCODE_HANDLER(Fast486OpcodeLeave); +FAST486_OPCODE_HANDLER(Fast486OpcodeRetFarImm); +FAST486_OPCODE_HANDLER(Fast486OpcodeRetFar); +FAST486_OPCODE_HANDLER(Fast486OpcodeInt); +FAST486_OPCODE_HANDLER(Fast486OpcodeIret); +FAST486_OPCODE_HANDLER(Fast486OpcodeAam); +FAST486_OPCODE_HANDLER(Fast486OpcodeAad); +FAST486_OPCODE_HANDLER(Fast486OpcodeXlat); +FAST486_OPCODE_HANDLER(Fast486OpcodeLoop); +FAST486_OPCODE_HANDLER(Fast486OpcodeJecxz); +FAST486_OPCODE_HANDLER(Fast486OpcodeCall); +FAST486_OPCODE_HANDLER(Fast486OpcodeJmp); +FAST486_OPCODE_HANDLER(Fast486OpcodeJmpAbs); +FAST486_OPCODE_HANDLER(Fast486OpcodeMovAlOffset); +FAST486_OPCODE_HANDLER(Fast486OpcodeMovEaxOffset); +FAST486_OPCODE_HANDLER(Fast486OpcodeMovOffsetAl); +FAST486_OPCODE_HANDLER(Fast486OpcodeMovOffsetEax); +FAST486_OPCODE_HANDLER(Fast486OpcodeSalc); +FAST486_OPCODE_HANDLER(Fast486OpcodeMovs); +FAST486_OPCODE_HANDLER(Fast486OpcodeCmps); +FAST486_OPCODE_HANDLER(Fast486OpcodeStos); +FAST486_OPCODE_HANDLER(Fast486OpcodeLods); +FAST486_OPCODE_HANDLER(Fast486OpcodeScas); +FAST486_OPCODE_HANDLER(Fast486OpcodeIns); +FAST486_OPCODE_HANDLER(Fast486OpcodeOuts); + +#endif // _OPCODES_H_ diff --git a/lib/fast486/opgroups.c b/lib/fast486/opgroups.c new file mode 100644 index 00000000000..264fa66ba2c --- /dev/null +++ b/lib/fast486/opgroups.c @@ -0,0 +1,2370 @@ +/* + * Fast486 386/486 CPU Emulation Library + * opgroups.c + * + * Copyright (C) 2013 Aleksandar Andrejevic + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* INCLUDES *******************************************************************/ + +#include + +// #define NDEBUG +#include + +#include +#include "opcodes.h" +#include "common.h" + +/* PRIVATE FUNCTIONS **********************************************************/ + +inline +static +ULONG +Fast486ArithmeticOperation(PFAST486_STATE State, + INT Operation, + ULONG FirstValue, + ULONG SecondValue, + UCHAR Bits) +{ + ULONG Result; + ULONG SignFlag = 1 << (Bits - 1); + ULONG MaxValue = (SignFlag - 1) | SignFlag; + + /* Make sure the values don't exceed the maximum for their size */ + FirstValue &= MaxValue; + SecondValue &= MaxValue; + + /* Check which operation is this */ + switch (Operation) + { + /* ADD */ + case 0: + { + Result = (FirstValue + SecondValue) & MaxValue; + + /* Update CF, OF and AF */ + State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue); + State->Flags.Of = ((FirstValue & SignFlag) == (SecondValue & SignFlag)) + && ((FirstValue & SignFlag) != (Result & SignFlag)); + State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0); + + break; + } + + /* OR */ + case 1: + { + Result = FirstValue | SecondValue; + break; + } + + /* ADC */ + case 2: + { + INT Carry = State->Flags.Cf ? 1 : 0; + + Result = (FirstValue + SecondValue + Carry) & MaxValue; + + /* Update CF, OF and AF */ + State->Flags.Cf = ((SecondValue == MaxValue) && (Carry == 1)) + || ((Result < FirstValue) && (Result < (SecondValue + Carry))); + State->Flags.Of = ((FirstValue & SignFlag) == (SecondValue & SignFlag)) + && ((FirstValue & SignFlag) != (Result & SignFlag)); + State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0; + + break; + } + + /* SBB */ + case 3: + { + INT Carry = State->Flags.Cf ? 1 : 0; + + Result = (FirstValue - SecondValue - Carry) & MaxValue; + + /* Update CF, OF and AF */ + State->Flags.Cf = Carry + ? (FirstValue <= SecondValue) + : (FirstValue < SecondValue); + State->Flags.Of = ((FirstValue & SignFlag) != (SecondValue & SignFlag)) + && ((FirstValue & SignFlag) != (Result & SignFlag)); + State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0; + + break; + } + + /* AND */ + case 4: + { + Result = FirstValue & SecondValue; + break; + } + + /* SUB or CMP */ + case 5: + case 7: + { + Result = (FirstValue - SecondValue) & MaxValue; + + /* Update CF, OF and AF */ + State->Flags.Cf = (FirstValue < SecondValue); + State->Flags.Of = ((FirstValue & SignFlag) != (SecondValue & SignFlag)) + && ((FirstValue & SignFlag) != (Result & SignFlag)); + State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F); + + break; + } + + /* XOR */ + case 6: + { + Result = FirstValue ^ SecondValue; + break; + } + + default: + { + /* Shouldn't happen */ + ASSERT(FALSE); + } + } + + /* Update ZF, SF and PF */ + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SignFlag) != 0); + State->Flags.Pf = Fast486CalculateParity(LOBYTE(Result)); + + /* Return the result */ + return Result; +} + +static +inline +ULONG +Fast486RotateOperation(PFAST486_STATE State, + INT Operation, + ULONG Value, + UCHAR Bits, + UCHAR Count) +{ + ULONG HighestBit = 1 << (Bits - 1); + ULONG MaxValue = HighestBit | (HighestBit - 1); + ULONG Result; + + /* Normalize the count */ + Count &= 0x1F; + + if ((Operation == 2) || (Operation == 3)) Count %= Bits + 1; + + /* If the count is zero, do nothing */ + if (Count == 0) return Value; + + /* Check which operation is this */ + switch (Operation) + { + /* ROL */ + case 0: + { + Count %= Bits; + Result = (Value << Count) | (Value >> (Bits - Count)); + + /* Update CF and OF */ + State->Flags.Cf = Result & 1; + if (Count == 1) State->Flags.Of = State->Flags.Cf + ^ ((Result & HighestBit) != 0); + + break; + } + + /* ROR */ + case 1: + { + Count %= Bits; + Result = (Value >> Count) | (Value << (Bits - Count)); + + /* Update CF and OF */ + State->Flags.Cf = ((Result & HighestBit) != 0); + if (Count == 1) State->Flags.Of = State->Flags.Cf + ^ ((Result & (HighestBit >> 1)) != 0); + + break; + } + + /* RCL */ + case 2: + { + Result = (Value << Count) | (State->Flags.Cf << (Count - 1)); + + /* Complete the calculation, but make sure we don't shift by too much */ + if ((Bits - Count) < 31) Result |= Value >> (Bits - Count + 1); + + /* Update CF and OF */ + State->Flags.Cf = ((Value & (1 << (Bits - Count))) != 0); + if (Count == 1) State->Flags.Of = State->Flags.Cf ^ ((Result & HighestBit) != 0); + + break; + } + + /* RCR */ + case 3: + { + /* Update OF */ + if (Count == 1) State->Flags.Of = State->Flags.Cf ^ ((Value & HighestBit) != 0); + + Result = (Value >> Count) | (State->Flags.Cf << (Bits - Count)); + + /* Complete the calculation, but make sure we don't shift by too much */ + if ((Bits - Count) < 31) Result |= Value << (Bits - Count + 1); + + /* Update CF */ + State->Flags.Cf = ((Value & (1 << (Count - 1))) != 0); + + break; + } + + /* SHL/SAL */ + case 4: + case 6: + { + Result = Value << Count; + + /* Update CF and OF */ + State->Flags.Cf = ((Value & (1 << (Bits - Count))) != 0); + if (Count == 1) State->Flags.Of = State->Flags.Cf + ^ ((Result & HighestBit) != 0); + + break; + } + + /* SHR */ + case 5: + { + Result = Value >> Count; + + /* Update CF and OF */ + State->Flags.Cf = ((Value & (1 << (Count - 1))) != 0); + if (Count == 1) State->Flags.Of = ((Value & HighestBit) != 0); + + break; + } + + /* SAR */ + case 7: + { + Result = Value >> Count; + + /* Fill the top Count bits with the sign bit */ + if (Value & HighestBit) Result |= ((1 << Count) - 1) << (Bits - Count); + + /* Update CF and OF */ + State->Flags.Cf = ((Value & (1 << (Count - 1))) != 0); + if (Count == 1) State->Flags.Of = FALSE; + + break; + } + } + + if (Operation >= 4) + { + /* Update ZF, SF and PF */ + State->Flags.Zf = ((Result & MaxValue) == 0); + State->Flags.Sf = ((Result & HighestBit) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + } + + /* Return the result */ + return Result; +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8082) +{ + UCHAR Immediate, Value; + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_ADSIZE(AddressSize); + + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Fetch the immediate operand */ + if (!Fast486FetchByte(State, &Immediate)) + { + /* Exception occurred */ + return FALSE; + } + + /* Read the operands */ + if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Value = Fast486ArithmeticOperation(State, ModRegRm.Register, Value, Immediate, 8); + + /* Unless this is CMP, write back the result */ + if (ModRegRm.Register != 7) + { + return Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Value); + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeGroup81) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (OperandSize) + { + ULONG Immediate, Value; + + /* Fetch the immediate operand */ + if (!Fast486FetchDword(State, &Immediate)) + { + /* Exception occurred */ + return FALSE; + } + + /* Read the operands */ + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Value = Fast486ArithmeticOperation(State, ModRegRm.Register, Value, Immediate, 32); + + /* Unless this is CMP, write back the result */ + if (ModRegRm.Register != 7) + { + return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value); + } + } + else + { + USHORT Immediate, Value; + + /* Fetch the immediate operand */ + if (!Fast486FetchWord(State, &Immediate)) + { + /* Exception occurred */ + return FALSE; + } + + /* Read the operands */ + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Value = Fast486ArithmeticOperation(State, ModRegRm.Register, Value, Immediate, 16); + + /* Unless this is CMP, write back the result */ + if (ModRegRm.Register != 7) + { + return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value); + } + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeGroup83) +{ + CHAR ImmByte; + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Fetch the immediate operand */ + if (!Fast486FetchByte(State, (PUCHAR)&ImmByte)) + { + /* Exception occurred */ + return FALSE; + } + + if (OperandSize) + { + ULONG Immediate = (ULONG)((LONG)ImmByte); // Sign extend + ULONG Value; + + /* Read the operands */ + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Value = Fast486ArithmeticOperation(State, ModRegRm.Register, Value, Immediate, 32); + + /* Unless this is CMP, write back the result */ + if (ModRegRm.Register != 7) + { + return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value); + } + } + else + { + USHORT Immediate = (USHORT)((SHORT)ImmByte); // Sign extend + USHORT Value; + + /* Read the operands */ + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Value = Fast486ArithmeticOperation(State, ModRegRm.Register, Value, Immediate, 16); + + /* Unless this is CMP, write back the result */ + if (ModRegRm.Register != 7) + { + return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value); + } + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8F) +{ + ULONG Value; + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + /* Pop a value from the stack - this must be done first */ + if (!Fast486StackPop(State, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred - restore SP */ + if (OperandSize) State->GeneralRegs[FAST486_REG_ESP].Long -= sizeof(ULONG); + else State->GeneralRegs[FAST486_REG_ESP].LowWord -= sizeof(USHORT); + + return FALSE; + } + + if (ModRegRm.Register != 0) + { + /* Invalid */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + if (OperandSize) + { + return Fast486WriteModrmDwordOperands(State, + &ModRegRm, + FALSE, + Value); + } + else + { + return Fast486WriteModrmWordOperands(State, + &ModRegRm, + FALSE, + LOWORD(Value)); + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC0) +{ + UCHAR Value, Count; + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_ADSIZE(AddressSize); + + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Fetch the count */ + if (!Fast486FetchByte(State, &Count)) + { + /* Exception occurred */ + return FALSE; + } + + /* Read the operands */ + if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Value = LOBYTE(Fast486RotateOperation(State, + ModRegRm.Register, + Value, + 8, + Count)); + + /* Write back the result */ + return Fast486WriteModrmByteOperands(State, + &ModRegRm, + FALSE, + Value); +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC1) +{ + UCHAR Count; + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Fetch the count */ + if (!Fast486FetchByte(State, &Count)) + { + /* Exception occurred */ + return FALSE; + } + + if (OperandSize) + { + ULONG Value; + + /* Read the operands */ + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Value = Fast486RotateOperation(State, + ModRegRm.Register, + Value, + 32, + Count); + + /* Write back the result */ + return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value); + } + else + { + USHORT Value; + + /* Read the operands */ + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Value = LOWORD(Fast486RotateOperation(State, + ModRegRm.Register, + Value, + 16, + Count)); + + /* Write back the result */ + return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value); + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC6) +{ + UCHAR Immediate; + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_ADSIZE(AddressSize); + + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (ModRegRm.Register != 0) + { + /* Invalid */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + /* Get the immediate operand */ + if (!Fast486FetchByte(State, &Immediate)) + { + /* Exception occurred */ + return FALSE; + } + + return Fast486WriteModrmByteOperands(State, + &ModRegRm, + FALSE, + Immediate); +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC7) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (ModRegRm.Register != 0) + { + /* Invalid */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + if (OperandSize) + { + ULONG Immediate; + + /* Get the immediate operand */ + if (!Fast486FetchDword(State, &Immediate)) + { + /* Exception occurred */ + return FALSE; + } + + return Fast486WriteModrmDwordOperands(State, + &ModRegRm, + FALSE, + Immediate); + } + else + { + USHORT Immediate; + + /* Get the immediate operand */ + if (!Fast486FetchWord(State, &Immediate)) + { + /* Exception occurred */ + return FALSE; + } + + return Fast486WriteModrmWordOperands(State, + &ModRegRm, + FALSE, + Immediate); + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD0) +{ + UCHAR Value; + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_ADSIZE(AddressSize); + + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Read the operands */ + if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Value = LOBYTE(Fast486RotateOperation(State, ModRegRm.Register, Value, 8, 1)); + + /* Write back the result */ + return Fast486WriteModrmByteOperands(State, + &ModRegRm, + FALSE, + Value); + +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD1) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (OperandSize) + { + ULONG Value; + + /* Read the operands */ + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Value = Fast486RotateOperation(State, ModRegRm.Register, Value, 32, 1); + + /* Write back the result */ + return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value); + } + else + { + USHORT Value; + + /* Read the operands */ + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Value = LOWORD(Fast486RotateOperation(State, ModRegRm.Register, Value, 16, 1)); + + /* Write back the result */ + return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value); + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD2) +{ + UCHAR Value; + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_ADSIZE(AddressSize); + + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Read the operands */ + if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Value = LOBYTE(Fast486RotateOperation(State, + ModRegRm.Register, + Value, + 8, + State->GeneralRegs[FAST486_REG_ECX].LowByte)); + + /* Write back the result */ + return Fast486WriteModrmByteOperands(State, + &ModRegRm, + FALSE, + Value); +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD3) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (OperandSize) + { + ULONG Value; + + /* Read the operands */ + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Value = Fast486RotateOperation(State, + ModRegRm.Register, + Value, + 32, + State->GeneralRegs[FAST486_REG_ECX].LowByte); + + /* Write back the result */ + return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value); + } + else + { + USHORT Value; + + /* Read the operands */ + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Value = LOWORD(Fast486RotateOperation(State, + ModRegRm.Register, + Value, + 16, + State->GeneralRegs[FAST486_REG_ECX].LowByte)); + + /* Write back the result */ + return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value); + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6) +{ + UCHAR Value = 0; + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_ADSIZE(AddressSize); + + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Read the operands */ + if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + switch (ModRegRm.Register) + { + /* TEST */ + case 0: + case 1: + { + UCHAR Immediate, Result; + + /* Fetch the immediate byte */ + if (!Fast486FetchByte(State, &Immediate)) + { + /* Exception occurred */ + return FALSE; + } + + /* Calculate the result */ + Result = Value & Immediate; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + break; + } + + /* NOT */ + case 2: + { + /* Write back the result */ + return Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, ~Value); + } + + /* NEG */ + case 3: + { + /* Calculate the result */ + UCHAR Result = -Value; + + /* Update the flags */ + State->Flags.Cf = (Value != 0); + State->Flags.Of = (Value & SIGN_FLAG_BYTE) && (Result & SIGN_FLAG_BYTE); + State->Flags.Af = ((Value & 0x0F) != 0); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + return Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Result); + } + + /* MUL */ + case 4: + { + USHORT Result = (USHORT)Value * (USHORT)State->GeneralRegs[FAST486_REG_EAX].LowByte; + + /* Update the flags */ + State->Flags.Cf = State->Flags.Of = (HIBYTE(Result) != 0); + + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].LowWord = Result; + + break; + } + + /* IMUL */ + case 5: + { + SHORT Result = (SHORT)((CHAR)Value) * (SHORT)((CHAR)State->GeneralRegs[FAST486_REG_EAX].LowByte); + + /* Update the flags */ + State->Flags.Cf = State->Flags.Of = ((Result < -128) || (Result > 127)); + + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].LowWord = (USHORT)Result; + + break; + } + + /* DIV */ + case 6: + { + UCHAR Quotient, Remainder; + + if (Value == 0) + { + /* Divide error */ + Fast486Exception(State, FAST486_EXCEPTION_DE); + return FALSE; + } + + Quotient = State->GeneralRegs[FAST486_REG_EAX].LowWord / Value; + Remainder = State->GeneralRegs[FAST486_REG_EAX].LowWord % Value; + + /* Write back the results */ + State->GeneralRegs[FAST486_REG_EAX].LowByte = Quotient; + State->GeneralRegs[FAST486_REG_EAX].HighByte = Remainder; + + break; + } + + /* IDIV */ + case 7: + { + CHAR Quotient, Remainder; + + if (Value == 0) + { + /* Divide error */ + Fast486Exception(State, FAST486_EXCEPTION_DE); + return FALSE; + } + + Quotient = (SHORT)State->GeneralRegs[FAST486_REG_EAX].LowWord / (CHAR)Value; + Remainder = (SHORT)State->GeneralRegs[FAST486_REG_EAX].LowWord % (CHAR)Value; + + /* Write back the results */ + State->GeneralRegs[FAST486_REG_EAX].LowByte = (UCHAR)Quotient; + State->GeneralRegs[FAST486_REG_EAX].HighByte = (UCHAR)Remainder; + + break; + } + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7) +{ + ULONG Value = 0, SignFlag; + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set the sign flag */ + if (OperandSize) SignFlag = SIGN_FLAG_LONG; + else SignFlag = SIGN_FLAG_WORD; + + /* Read the operand */ + if (OperandSize) + { + /* 32-bit */ + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + /* 16-bit */ + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, (PUSHORT)&Value)) + { + /* Exception occurred */ + return FALSE; + } + } + + switch (ModRegRm.Register) + { + /* TEST */ + case 0: + case 1: + { + ULONG Immediate = 0, Result = 0; + + if (OperandSize) + { + /* Fetch the immediate dword */ + if (!Fast486FetchDword(State, &Immediate)) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + /* Fetch the immediate word */ + if (!Fast486FetchWord(State, (PUSHORT)&Immediate)) + { + /* Exception occurred */ + return FALSE; + } + } + + /* Calculate the result */ + Result = Value & Immediate; + + /* Update the flags */ + State->Flags.Cf = FALSE; + State->Flags.Of = FALSE; + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SignFlag) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + break; + } + + /* NOT */ + case 2: + { + /* Write back the result */ + if (OperandSize) + { + /* 32-bit */ + return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, ~Value); + } + else + { + /* 16-bit */ + return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, LOWORD(~Value)); + } + } + + /* NEG */ + case 3: + { + /* Calculate the result */ + ULONG Result = -Value; + if (!OperandSize) Result &= 0xFFFF; + + /* Update the flags */ + State->Flags.Cf = (Value != 0); + State->Flags.Of = (Value & SignFlag) && (Result & SignFlag); + State->Flags.Af = ((Value & 0x0F) != 0); + State->Flags.Zf = (Result == 0); + State->Flags.Sf = ((Result & SignFlag) != 0); + State->Flags.Pf = Fast486CalculateParity(Result); + + /* Write back the result */ + if (OperandSize) + { + /* 32-bit */ + return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Result); + } + else + { + /* 16-bit */ + return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, LOWORD(Result)); + } + } + + /* MUL */ + case 4: + { + if (OperandSize) + { + ULONGLONG Result = (ULONGLONG)Value * (ULONGLONG)State->GeneralRegs[FAST486_REG_EAX].Long; + + /* Update the flags */ + State->Flags.Cf = State->Flags.Of = ((Result & 0xFFFFFFFF00000000ULL) != 0); + + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].Long = Result & 0xFFFFFFFFULL; + State->GeneralRegs[FAST486_REG_EDX].Long = Result >> 32; + } + else + { + ULONG Result = (ULONG)Value * (ULONG)State->GeneralRegs[FAST486_REG_EAX].LowWord; + + /* Update the flags */ + State->Flags.Cf = State->Flags.Of = (HIWORD(Result) != 0); + + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].LowWord = LOWORD(Result); + State->GeneralRegs[FAST486_REG_EDX].LowWord = HIWORD(Result); + } + + break; + } + + /* IMUL */ + case 5: + { + if (OperandSize) + { + LONGLONG Result = (LONGLONG)((LONG)Value) * (LONGLONG)((LONG)State->GeneralRegs[FAST486_REG_EAX].Long); + + /* Update the flags */ + State->Flags.Cf = State->Flags.Of = ((Result < -2147483648LL) || (Result > 2147483647LL)); + + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].Long = Result & 0xFFFFFFFFULL; + State->GeneralRegs[FAST486_REG_EDX].Long = Result >> 32; + } + else + { + LONG Result = (LONG)((SHORT)Value) * (LONG)((SHORT)State->GeneralRegs[FAST486_REG_EAX].LowWord); + + /* Update the flags */ + State->Flags.Cf = State->Flags.Of = ((Result < -32768) || (Result > 32767)); + + /* Write back the result */ + State->GeneralRegs[FAST486_REG_EAX].LowWord = LOWORD(Result); + State->GeneralRegs[FAST486_REG_EDX].LowWord = HIWORD(Result); + } + + break; + } + + /* DIV */ + case 6: + { + if (Value == 0) + { + /* Divide error */ + Fast486Exception(State, FAST486_EXCEPTION_DE); + return FALSE; + } + + if (OperandSize) + { + ULONGLONG Dividend = (ULONGLONG)State->GeneralRegs[FAST486_REG_EAX].Long + | ((ULONGLONG)State->GeneralRegs[FAST486_REG_EDX].Long << 32); + ULONG Quotient = Dividend / Value; + ULONG Remainder = Dividend % Value; + + /* Write back the results */ + State->GeneralRegs[FAST486_REG_EAX].Long = Quotient; + State->GeneralRegs[FAST486_REG_EDX].Long = Remainder; + } + else + { + ULONG Dividend = (ULONG)State->GeneralRegs[FAST486_REG_EAX].LowWord + | ((ULONG)State->GeneralRegs[FAST486_REG_EDX].LowWord << 16); + USHORT Quotient = Dividend / Value; + USHORT Remainder = Dividend % Value; + + /* Write back the results */ + State->GeneralRegs[FAST486_REG_EAX].LowWord = Quotient; + State->GeneralRegs[FAST486_REG_EDX].LowWord = Remainder; + } + + break; + } + + /* IDIV */ + case 7: + { + if (Value == 0) + { + /* Divide error */ + Fast486Exception(State, FAST486_EXCEPTION_DE); + return FALSE; + } + + if (OperandSize) + { + LONGLONG Dividend = (LONGLONG)State->GeneralRegs[FAST486_REG_EAX].Long + | ((LONGLONG)State->GeneralRegs[FAST486_REG_EDX].Long << 32); + LONG Quotient = Dividend / (LONG)Value; + LONG Remainder = Dividend % (LONG)Value; + + /* Write back the results */ + State->GeneralRegs[FAST486_REG_EAX].Long = (ULONG)Quotient; + State->GeneralRegs[FAST486_REG_EDX].Long = (ULONG)Remainder; + } + else + { + LONG Dividend = (LONG)State->GeneralRegs[FAST486_REG_EAX].LowWord + | ((LONG)State->GeneralRegs[FAST486_REG_EDX].LowWord << 16); + SHORT Quotient = Dividend / (SHORT)LOWORD(Value); + SHORT Remainder = Dividend % (SHORT)LOWORD(Value); + + /* Write back the results */ + State->GeneralRegs[FAST486_REG_EAX].LowWord = (USHORT)Quotient; + State->GeneralRegs[FAST486_REG_EDX].LowWord = (USHORT)Remainder; + } + + break; + } + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFE) +{ + UCHAR Value; + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_ADSIZE(AddressSize); + + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (ModRegRm.Register > 1) + { + /* Invalid */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + /* Read the operands */ + if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + if (ModRegRm.Register == 0) + { + /* Increment and update OF and AF */ + Value++; + State->Flags.Of = (Value == SIGN_FLAG_BYTE); + State->Flags.Af = ((Value & 0x0F) == 0); + } + else + { + /* Decrement and update OF and AF */ + State->Flags.Of = (Value == SIGN_FLAG_BYTE); + Value--; + State->Flags.Af = ((Value & 0x0F) == 0x0F); + } + + /* Update flags */ + State->Flags.Zf = (Value == 0); + State->Flags.Sf = ((Value & SIGN_FLAG_BYTE) != 0); + State->Flags.Pf = Fast486CalculateParity(Value); + + /* Write back the result */ + return Fast486WriteModrmByteOperands(State, + &ModRegRm, + FALSE, + Value); +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (ModRegRm.Register == 7) + { + /* Invalid */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + /* Read the operands */ + if (OperandSize) + { + ULONG Value; + + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + if (ModRegRm.Register == 0) + { + /* Increment and update OF and AF */ + Value++; + State->Flags.Of = (Value == SIGN_FLAG_LONG); + State->Flags.Af = ((Value & 0x0F) == 0); + } + else if (ModRegRm.Register == 1) + { + /* Decrement and update OF and AF */ + State->Flags.Of = (Value == SIGN_FLAG_LONG); + Value--; + State->Flags.Af = ((Value & 0x0F) == 0x0F); + } + else if (ModRegRm.Register == 2) + { + /* Push the current value of EIP */ + if (!Fast486StackPush(State, State->InstPtr.Long)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set the EIP to the address */ + State->InstPtr.Long = Value; + } + else if (ModRegRm.Register == 3) + { + USHORT Selector; + FAST486_SEG_REGS Segment = FAST486_REG_DS; + + /* Check for the segment override */ + if (State->PrefixFlags & FAST486_PREFIX_SEG) + { + /* Use the override segment instead */ + Segment = State->SegmentOverride; + } + + /* Read the selector */ + if (!Fast486ReadMemory(State, + Segment, + ModRegRm.MemoryAddress + sizeof(ULONG), + FALSE, + &Selector, + sizeof(USHORT))) + { + /* Exception occurred */ + return FALSE; + } + + /* Push the current value of CS */ + if (!Fast486StackPush(State, State->SegmentRegs[FAST486_REG_CS].Selector)) + { + /* Exception occurred */ + return FALSE; + } + + /* Push the current value of EIP */ + if (!Fast486StackPush(State, State->InstPtr.Long)) + { + /* Exception occurred */ + return FALSE; + } + + /* Load the new code segment */ + if (!Fast486LoadSegment(State, FAST486_REG_CS, Selector)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set the EIP to the address */ + State->InstPtr.Long = Value; + } + else if (ModRegRm.Register == 4) + { + /* Set the EIP to the address */ + State->InstPtr.Long = Value; + } + else if (ModRegRm.Register == 5) + { + USHORT Selector; + FAST486_SEG_REGS Segment = FAST486_REG_DS; + + /* Check for the segment override */ + if (State->PrefixFlags & FAST486_PREFIX_SEG) + { + /* Use the override segment instead */ + Segment = State->SegmentOverride; + } + + /* Read the selector */ + if (!Fast486ReadMemory(State, + Segment, + ModRegRm.MemoryAddress + sizeof(ULONG), + FALSE, + &Selector, + sizeof(USHORT))) + { + /* Exception occurred */ + return FALSE; + } + + /* Load the new code segment */ + if (!Fast486LoadSegment(State, FAST486_REG_CS, Selector)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set the EIP to the address */ + State->InstPtr.Long = Value; + } + else if (ModRegRm.Register == 6) + { + /* Push the value on to the stack */ + return Fast486StackPush(State, Value); + } + + if (ModRegRm.Register <= 1) + { + /* Update flags */ + State->Flags.Sf = ((Value & SIGN_FLAG_LONG) != 0); + State->Flags.Zf = (Value == 0); + State->Flags.Pf = Fast486CalculateParity(Value); + + /* Write back the result */ + return Fast486WriteModrmDwordOperands(State, + &ModRegRm, + FALSE, + Value); + } + } + else + { + USHORT Value; + + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + if (ModRegRm.Register == 0) + { + /* Increment and update OF */ + Value++; + State->Flags.Of = (Value == SIGN_FLAG_WORD); + State->Flags.Af = ((Value & 0x0F) == 0); + } + else if (ModRegRm.Register == 1) + { + /* Decrement and update OF */ + State->Flags.Of = (Value == SIGN_FLAG_WORD); + Value--; + State->Flags.Af = ((Value & 0x0F) == 0x0F); + } + else if (ModRegRm.Register == 2) + { + /* Push the current value of IP */ + if (!Fast486StackPush(State, State->InstPtr.LowWord)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set the IP to the address */ + State->InstPtr.LowWord = Value; + + /* Clear the top half of EIP */ + State->InstPtr.Long &= 0xFFFF; + } + else if (ModRegRm.Register == 3) + { + USHORT Selector; + FAST486_SEG_REGS Segment = FAST486_REG_DS; + + /* Check for the segment override */ + if (State->PrefixFlags & FAST486_PREFIX_SEG) + { + /* Use the override segment instead */ + Segment = State->SegmentOverride; + } + + /* Read the selector */ + if (!Fast486ReadMemory(State, + Segment, + ModRegRm.MemoryAddress + sizeof(USHORT), + FALSE, + &Selector, + sizeof(USHORT))) + { + /* Exception occurred */ + return FALSE; + } + + /* Push the current value of CS */ + if (!Fast486StackPush(State, State->SegmentRegs[FAST486_REG_CS].Selector)) + { + /* Exception occurred */ + return FALSE; + } + + /* Push the current value of IP */ + if (!Fast486StackPush(State, State->InstPtr.LowWord)) + { + /* Exception occurred */ + return FALSE; + } + + /* Load the new code segment */ + if (!Fast486LoadSegment(State, FAST486_REG_CS, Selector)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set the IP to the address */ + State->InstPtr.LowWord = Value; + + /* Clear the top half of EIP */ + State->InstPtr.Long &= 0xFFFF; + } + else if (ModRegRm.Register == 4) + { + /* Set the IP to the address */ + State->InstPtr.LowWord = Value; + + /* Clear the top half of EIP */ + State->InstPtr.Long &= 0xFFFF; + } + else if (ModRegRm.Register == 5) + { + USHORT Selector; + FAST486_SEG_REGS Segment = FAST486_REG_DS; + + /* Check for the segment override */ + if (State->PrefixFlags & FAST486_PREFIX_SEG) + { + /* Use the override segment instead */ + Segment = State->SegmentOverride; + } + + /* Read the selector */ + if (!Fast486ReadMemory(State, + Segment, + ModRegRm.MemoryAddress + sizeof(USHORT), + FALSE, + &Selector, + sizeof(USHORT))) + { + /* Exception occurred */ + return FALSE; + } + + /* Load the new code segment */ + if (!Fast486LoadSegment(State, FAST486_REG_CS, Selector)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set the IP to the address */ + State->InstPtr.LowWord = Value; + + /* Clear the top half of EIP */ + State->InstPtr.Long &= 0xFFFF; + } + else if (ModRegRm.Register == 6) + { + /* Push the value on to the stack */ + return Fast486StackPush(State, Value); + } + else + { + /* Invalid */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + if (ModRegRm.Register <= 1) + { + /* Update flags */ + State->Flags.Sf = ((Value & SIGN_FLAG_WORD) != 0); + State->Flags.Zf = (Value == 0); + State->Flags.Pf = Fast486CalculateParity(Value); + + /* Write back the result */ + return Fast486WriteModrmWordOperands(State, + &ModRegRm, + FALSE, + Value); + } + } + + return TRUE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F00) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + NO_LOCK_PREFIX(); + TOGGLE_ADSIZE(AddressSize); + + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Check which operation this is */ + switch (ModRegRm.Register) + { + /* SLDT */ + case 0: + { + /* Not recognized in real mode or virtual 8086 mode */ + if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) + || State->Flags.Vm) + { + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + return Fast486WriteModrmWordOperands(State, + &ModRegRm, + FALSE, + State->Ldtr.Selector); + } + + /* STR */ + case 1: + { + /* Not recognized in real mode or virtual 8086 mode */ + if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) + || State->Flags.Vm) + { + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + return Fast486WriteModrmWordOperands(State, + &ModRegRm, + FALSE, + State->TaskReg.Selector); + } + + /* LLDT */ + case 2: + { + USHORT Selector; + FAST486_SYSTEM_DESCRIPTOR GdtEntry; + + /* Not recognized in real mode or virtual 8086 mode */ + if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) + || State->Flags.Vm) + { + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + /* This is a privileged instruction */ + if (Fast486GetCurrentPrivLevel(State) != 0) + { + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + + if (!Fast486ReadModrmWordOperands(State, + &ModRegRm, + NULL, + &Selector)) + { + /* Exception occurred */ + return FALSE; + } + + /* Make sure the GDT contains the entry */ + if (GET_SEGMENT_INDEX(Selector) >= (State->Gdtr.Size + 1)) + { + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector); + return FALSE; + } + + /* Read the GDT */ + if (!Fast486ReadLinearMemory(State, + State->Gdtr.Address + + GET_SEGMENT_INDEX(Selector), + &GdtEntry, + sizeof(GdtEntry))) + { + /* Exception occurred */ + return FALSE; + } + + if (GET_SEGMENT_INDEX(Selector) == 0) + { + RtlZeroMemory(&State->Ldtr, sizeof(State->Ldtr)); + return TRUE; + } + + if (!GdtEntry.Present) + { + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_NP, Selector); + return FALSE; + } + + if (GdtEntry.Signature != FAST486_LDT_SIGNATURE) + { + /* This is not a LDT descriptor */ + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector); + return FALSE; + } + + /* Update the LDTR */ + State->Ldtr.Selector = Selector; + State->Ldtr.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (GdtEntry.BaseHigh << 24); + State->Ldtr.Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16); + if (GdtEntry.Granularity) State->Ldtr.Limit <<= 12; + + return TRUE; + } + + /* LTR */ + case 3: + { + USHORT Selector; + FAST486_SYSTEM_DESCRIPTOR GdtEntry; + + /* Not recognized in real mode or virtual 8086 mode */ + if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) + || State->Flags.Vm) + { + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + /* This is a privileged instruction */ + if (Fast486GetCurrentPrivLevel(State) != 0) + { + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + + if (!Fast486ReadModrmWordOperands(State, + &ModRegRm, + NULL, + &Selector)) + { + /* Exception occurred */ + return FALSE; + } + + /* Make sure the GDT contains the entry */ + if (GET_SEGMENT_INDEX(Selector) >= (State->Gdtr.Size + 1)) + { + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector); + return FALSE; + } + + /* Read the GDT */ + if (!Fast486ReadLinearMemory(State, + State->Gdtr.Address + + GET_SEGMENT_INDEX(Selector), + &GdtEntry, + sizeof(GdtEntry))) + { + /* Exception occurred */ + return FALSE; + } + + if (GET_SEGMENT_INDEX(Selector) == 0) + { + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + + if (!GdtEntry.Present) + { + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_NP, Selector); + return FALSE; + } + + if (GdtEntry.Signature != FAST486_TSS_SIGNATURE) + { + /* This is not a TSS descriptor */ + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector); + return FALSE; + } + + /* Update the TR */ + State->TaskReg.Selector = Selector; + State->TaskReg.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (GdtEntry.BaseHigh << 24); + State->TaskReg.Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16); + if (GdtEntry.Granularity) State->TaskReg.Limit <<= 12; + State->TaskReg.Busy = TRUE; + + return TRUE; + } + + /* VERR/VERW */ + case 4: + case 5: + { + USHORT Selector; + FAST486_GDT_ENTRY GdtEntry; + + /* Not recognized in real mode or virtual 8086 mode */ + if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) + || State->Flags.Vm) + { + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + /* This is a privileged instruction */ + if (Fast486GetCurrentPrivLevel(State) != 0) + { + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + + if (!Fast486ReadModrmWordOperands(State, + &ModRegRm, + NULL, + &Selector)) + { + /* Exception occurred */ + return FALSE; + } + + if (!(Selector & SEGMENT_TABLE_INDICATOR)) + { + /* Make sure the GDT contains the entry */ + if (GET_SEGMENT_INDEX(Selector) >= (State->Gdtr.Size + 1)) + { + /* Clear ZF */ + State->Flags.Zf = FALSE; + return TRUE; + } + + /* Read the GDT */ + if (!Fast486ReadLinearMemory(State, + State->Gdtr.Address + + GET_SEGMENT_INDEX(Selector), + &GdtEntry, + sizeof(GdtEntry))) + { + /* Exception occurred */ + return FALSE; + } + } + else + { + /* Make sure the LDT contains the entry */ + if (GET_SEGMENT_INDEX(Selector) >= (State->Ldtr.Limit + 1)) + { + /* Clear ZF */ + State->Flags.Zf = FALSE; + return TRUE; + } + + /* Read the LDT */ + if (!Fast486ReadLinearMemory(State, + State->Ldtr.Base + + GET_SEGMENT_INDEX(Selector), + &GdtEntry, + sizeof(GdtEntry))) + { + /* Exception occurred */ + return FALSE; + } + } + + /* Set ZF if it is valid and accessible */ + State->Flags.Zf = GdtEntry.Present // must be present + && GdtEntry.SystemType // must be a segment + && (((ModRegRm.Register == 4) + /* code segments are only readable if the RW bit is set */ + && (!GdtEntry.Executable || GdtEntry.ReadWrite)) + || ((ModRegRm.Register == 5) + /* code segments are never writable, data segments are writable when RW is set */ + && (!GdtEntry.Executable && GdtEntry.ReadWrite))) + /* + * for segments other than conforming code segments, + * both RPL and CPL must be less than or equal to DPL + */ + && ((!GdtEntry.Executable || !GdtEntry.DirConf) + && ((GET_SEGMENT_RPL(Selector) <= GdtEntry.Dpl) + && (Fast486GetCurrentPrivLevel(State) <= GdtEntry.Dpl))) + /* for conforming code segments, DPL must be less than or equal to CPL */ + && ((GdtEntry.Executable && GdtEntry.DirConf) + && (GdtEntry.Dpl <= Fast486GetCurrentPrivLevel(State))); + + + return TRUE; + } + + /* Invalid */ + default: + { + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01) +{ + UCHAR TableReg[6]; + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + FAST486_SEG_REGS Segment = FAST486_REG_DS; + + NO_LOCK_PREFIX(); + TOGGLE_ADSIZE(AddressSize); + + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* Check for the segment override */ + if (State->PrefixFlags & FAST486_PREFIX_SEG) + { + /* Use the override segment instead */ + Segment = State->SegmentOverride; + } + + /* Check which operation this is */ + switch (ModRegRm.Register) + { + /* SGDT */ + case 0: + { + if (!ModRegRm.Memory) + { + /* The second operand must be a memory location */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + /* Fill the 6-byte table register */ + RtlCopyMemory(TableReg, &State->Gdtr.Size, sizeof(USHORT)); + RtlCopyMemory(&TableReg[sizeof(USHORT)], &State->Gdtr.Address, sizeof(ULONG)); + + /* Store the GDTR */ + return Fast486WriteMemory(State, + Segment, + ModRegRm.MemoryAddress, + TableReg, + sizeof(TableReg)); + } + + /* SIDT */ + case 1: + { + if (!ModRegRm.Memory) + { + /* The second operand must be a memory location */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + /* Fill the 6-byte table register */ + RtlCopyMemory(TableReg, &State->Idtr.Size, sizeof(USHORT)); + RtlCopyMemory(&TableReg[sizeof(USHORT)], &State->Idtr.Address, sizeof(ULONG)); + + /* Store the IDTR */ + return Fast486WriteMemory(State, + Segment, + ModRegRm.MemoryAddress, + TableReg, + sizeof(TableReg)); + } + + /* LGDT */ + case 2: + { + /* This is a privileged instruction */ + if (Fast486GetCurrentPrivLevel(State) != 0) + { + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + + if (!ModRegRm.Memory) + { + /* The second operand must be a memory location */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + /* Read the new GDTR */ + if (!Fast486ReadMemory(State, + Segment, + ModRegRm.MemoryAddress, + FALSE, + TableReg, + sizeof(TableReg))) + { + /* Exception occurred */ + return FALSE; + } + + /* Load the new GDT */ + State->Gdtr.Size = *((PUSHORT)TableReg); + State->Gdtr.Address = *((PULONG)&TableReg[sizeof(USHORT)]); + + return TRUE; + } + + /* LIDT */ + case 3: + { + /* This is a privileged instruction */ + if (Fast486GetCurrentPrivLevel(State) != 0) + { + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + + if (!ModRegRm.Memory) + { + /* The second operand must be a memory location */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + /* Read the new IDTR */ + if (!Fast486ReadMemory(State, + Segment, + ModRegRm.MemoryAddress, + FALSE, + TableReg, + sizeof(TableReg))) + { + /* Exception occurred */ + return FALSE; + } + + /* Load the new IDT */ + State->Idtr.Size = *((PUSHORT)TableReg); + State->Idtr.Address = *((PULONG)&TableReg[sizeof(USHORT)]); + + return TRUE; + } + + /* SMSW */ + case 4: + { + /* Store the lower 16 bits (Machine Status Word) of CR0 */ + return Fast486WriteModrmWordOperands(State, + &ModRegRm, + FALSE, + LOWORD(State->ControlRegisters[FAST486_REG_CR0])); + } + + /* LMSW */ + case 6: + { + USHORT MachineStatusWord; + + /* This is a privileged instruction */ + if (Fast486GetCurrentPrivLevel(State) != 0) + { + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + + /* Read the new Machine Status Word */ + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &MachineStatusWord)) + { + /* Exception occurred */ + return FALSE; + } + + /* This instruction cannot be used to return to real mode */ + if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) + && !(MachineStatusWord & FAST486_CR0_PE)) + { + Fast486Exception(State, FAST486_EXCEPTION_GP); + return FALSE; + } + + /* Set the lowest 4 bits */ + State->ControlRegisters[FAST486_REG_CR0] &= 0xFFFFFFF0; + State->ControlRegisters[FAST486_REG_CR0] |= MachineStatusWord & 0x0F; + + return TRUE; + } + + /* INVLPG */ + case 7: + { + UNIMPLEMENTED; + return FALSE; + } + + /* Invalid */ + default: + { + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + } +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FB9) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_ADSIZE(AddressSize); + + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + /* All of them are reserved (UD2) */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; +} + +FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FBA) +{ + FAST486_MOD_REG_RM ModRegRm; + BOOLEAN OperandSize, AddressSize; + UINT DataSize; + UCHAR BitNumber; + + OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; + + TOGGLE_OPSIZE(OperandSize); + TOGGLE_ADSIZE(AddressSize); + + /* Get the number of bits */ + if (OperandSize) DataSize = 32; + else DataSize = 16; + + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + + if (ModRegRm.Register < 4) + { + /* Invalid */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return FALSE; + } + + /* Get the bit number */ + if (!Fast486FetchByte(State, &BitNumber)) + { + /* Exception occurred */ + return FALSE; + } + + if (ModRegRm.Memory) + { + /* + * For memory operands, add the bit offset divided by + * the data size to the address + */ + ModRegRm.MemoryAddress += BitNumber / DataSize; + } + + /* Normalize the bit number */ + BitNumber %= DataSize; + + if (OperandSize) + { + ULONG Value; + + /* Read the value */ + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set CF to the bit value */ + State->Flags.Cf = (Value >> BitNumber) & 1; + + if (ModRegRm.Register == 5) + { + /* BTS */ + Value |= 1 << BitNumber; + } + else if (ModRegRm.Register == 6) + { + /* BTR */ + Value &= ~(1 << BitNumber); + } + else if (ModRegRm.Register == 7) + { + /* BTC */ + Value ^= 1 << BitNumber; + } + + if (ModRegRm.Register >= 5) + { + /* Write back the result */ + if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value)) + { + /* Exception occurred */ + return FALSE; + } + } + } + else + { + USHORT Value; + + /* Read the value */ + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return FALSE; + } + + /* Set CF to the bit value */ + State->Flags.Cf = (Value >> BitNumber) & 1; + + if (ModRegRm.Register == 5) + { + /* BTS */ + Value |= 1 << BitNumber; + } + else if (ModRegRm.Register == 6) + { + /* BTR */ + Value &= ~(1 << BitNumber); + } + else if (ModRegRm.Register == 7) + { + /* BTC */ + Value ^= 1 << BitNumber; + } + + if (ModRegRm.Register >= 5) + { + /* Write back the result */ + if (!Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value)) + { + /* Exception occurred */ + return FALSE; + } + } + } + + /* Return success */ + return TRUE; +} + +/* EOF */ diff --git a/lib/fast486/opgroups.h b/lib/fast486/opgroups.h new file mode 100644 index 00000000000..bf55cce9c3f --- /dev/null +++ b/lib/fast486/opgroups.h @@ -0,0 +1,53 @@ +/* + * Fast486 386/486 CPU Emulation Library + * opgroups.h + * + * Copyright (C) 2013 Aleksandar Andrejevic + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _OPGROUPS_H_ +#define _OPGROUPS_H_ + +#pragma once + +/* DEFINES ********************************************************************/ + +FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8082); +FAST486_OPCODE_HANDLER(Fast486OpcodeGroup81); +FAST486_OPCODE_HANDLER(Fast486OpcodeGroup83); +FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8F); +FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC0); +FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC1); +FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC6); +FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC7); +FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD0); +FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD1); +FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD2); +FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD3); +FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6); +FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7); +FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFE); +FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF); +FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F00); +FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01); +FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FB9); +FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FBA); + +#endif // _OPGROUPS_H_ + +/* EOF */ + diff --git a/lib/rtl/actctx.c b/lib/rtl/actctx.c index 1243f59ceab..784e446a550 100644 --- a/lib/rtl/actctx.c +++ b/lib/rtl/actctx.c @@ -12,7 +12,7 @@ * Samuel Serapin */ -/* Based on Wine 1.1.26 */ +/* Based on Wine 1.7.17 */ #include @@ -24,14 +24,17 @@ BOOLEAN RtlpNotAllowingMultipleActivation; #define ACTCTX_FLAGS_ALL (\ - ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\ - ACTCTX_FLAG_LANGID_VALID |\ - ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\ - ACTCTX_FLAG_RESOURCE_NAME_VALID |\ - ACTCTX_FLAG_SET_PROCESS_DEFAULT |\ - ACTCTX_FLAG_APPLICATION_NAME_VALID |\ - ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\ - ACTCTX_FLAG_HMODULE_VALID ) + ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\ + ACTCTX_FLAG_LANGID_VALID |\ + ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\ + ACTCTX_FLAG_RESOURCE_NAME_VALID |\ + ACTCTX_FLAG_SET_PROCESS_DEFAULT |\ + ACTCTX_FLAG_APPLICATION_NAME_VALID |\ + ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\ + ACTCTX_FLAG_HMODULE_VALID ) + +#define STRSECTION_MAGIC 0x64487353 /* dHsS */ +#define GUIDSECTION_MAGIC 0x64487347 /* dHsG */ #define ACTCTX_MAGIC_MARKER (PVOID)'gMcA' @@ -77,6 +80,291 @@ struct assembly_identity BOOL optional; }; +struct strsection_header +{ + DWORD magic; + ULONG size; + DWORD unk1[3]; + ULONG count; + ULONG index_offset; + DWORD unk2[2]; + ULONG global_offset; + ULONG global_len; +}; + +struct string_index +{ + ULONG hash; /* key string hash */ + ULONG name_offset; + ULONG name_len; + ULONG data_offset; /* redirect data offset */ + ULONG data_len; + ULONG rosterindex; +}; + +struct guidsection_header +{ + DWORD magic; + ULONG size; + DWORD unk[3]; + ULONG count; + ULONG index_offset; + DWORD unk2; + ULONG names_offset; + ULONG names_len; +}; + +struct guid_index +{ + GUID guid; + ULONG data_offset; + ULONG data_len; + ULONG rosterindex; +}; + +struct wndclass_redirect_data +{ + ULONG size; + DWORD res; + ULONG name_len; + ULONG name_offset; /* versioned name offset */ + ULONG module_len; + ULONG module_offset;/* container name offset */ +}; + +struct dllredirect_data +{ + ULONG size; + ULONG unk; + DWORD res[3]; +}; + +struct tlibredirect_data +{ + ULONG size; + DWORD res; + ULONG name_len; + ULONG name_offset; + LANGID langid; + WORD flags; + ULONG help_len; + ULONG help_offset; + WORD major_version; + WORD minor_version; +}; + +enum comclass_threadingmodel +{ + ThreadingModel_Apartment = 1, + ThreadingModel_Free = 2, + ThreadingModel_No = 3, + ThreadingModel_Both = 4, + ThreadingModel_Neutral = 5 +}; + +enum comclass_miscfields +{ + MiscStatus = 1, + MiscStatusIcon = 2, + MiscStatusContent = 4, + MiscStatusThumbnail = 8, + MiscStatusDocPrint = 16 +}; + +struct comclassredirect_data +{ + ULONG size; + BYTE res; + BYTE miscmask; + BYTE res1[2]; + DWORD model; + GUID clsid; + GUID alias; + GUID clsid2; + GUID tlbid; + ULONG name_len; + ULONG name_offset; + ULONG progid_len; + ULONG progid_offset; + ULONG clrdata_len; + ULONG clrdata_offset; + DWORD miscstatus; + DWORD miscstatuscontent; + DWORD miscstatusthumbnail; + DWORD miscstatusicon; + DWORD miscstatusdocprint; +}; + +enum ifaceps_mask +{ + NumMethods = 1, + BaseIface = 2 +}; + +struct ifacepsredirect_data +{ + ULONG size; + DWORD mask; + GUID iid; + ULONG nummethods; + GUID tlbid; + GUID base; + ULONG name_len; + ULONG name_offset; +}; + +struct clrsurrogate_data +{ + ULONG size; + DWORD res; + GUID clsid; + ULONG version_offset; + ULONG version_len; + ULONG name_offset; + ULONG name_len; +}; + +struct clrclass_data +{ + ULONG size; + DWORD res[2]; + ULONG module_len; + ULONG module_offset; + ULONG name_len; + ULONG name_offset; + ULONG version_len; + ULONG version_offset; + DWORD res2[2]; +}; + +struct progidredirect_data +{ + ULONG size; + DWORD reserved; + ULONG clsid_offset; +}; + +/* + + Sections structure. + + Sections are accessible by string or guid key, that defines two types of sections. + All sections of each type have same magic value and header structure, index + data could be of two possible types too. So every string based section uses + the same index format, same applies to guid sections - they share same guid index + format. + + - window class redirection section is a plain buffer with following format: + +
+ + --- + + + + + Header is fixed length structure - struct strsection_header, + contains redirected classes count; + + Index is an array of fixed length index records, each record is + struct string_index. + + All strings in data itself are WCHAR, null terminated, 4-bytes aligned. + + Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data), + others are relative to section itself. + + - dll redirect section format: + +
+ + --- + + + This section doesn't seem to carry any payload data except dll names. + + - typelib section format: + +
+ + + --- + + + Header is fixed length, index is an array of fixed length 'struct guid_index'. + All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is + 4-bytes aligned as a whole. + + Module name offsets are relative to section, helpstring offset is relative to data + structure itself. + + - comclass section format: + +
+ + + --- --- + + + + + + This section uses two index records per comclass, one entry contains original guid + as specified by context, another one has a generated guid. Index and strings handling + is similar to typelib sections. + + For CLR classes additional data is stored after main COM class data, it contains + class name and runtime version string, see 'struct clrclass_data'. + + Module name offsets are relative to section, progid offset is relative to data + structure itself. + + - COM interface section format: + +
+ + --- + + + Interface section contains data for proxy/stubs and external proxy/stubs. External + ones are defined at assembly level, so this section has no module information. + All records are indexed with 'iid' value from manifest. There an exception for + external variants - if 'proxyStubClsid32' is specified, it's stored as iid in + redirect data, but index is still 'iid' from manifest. + + Interface name offset is relative to data structure itself. + + - CLR surrogates section format: + +
+ + --- + + + + There's nothing special about this section, same way to store strings is used, + no modules part as it belongs to assembly level, not a file. + + - ProgID section format: + +
+ + + --- + + + This sections uses generated alias guids from COM server section. This way + ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string + is stored too, aligned. +*/ + +struct progids +{ + WCHAR **progids; + unsigned int num; + unsigned int allocated; +}; + struct entity { DWORD kind; @@ -85,30 +373,45 @@ struct entity struct { WCHAR *tlbid; - WCHAR *version; WCHAR *helpdir; - } typelib; + WORD flags; + WORD major; + WORD minor; + } typelib; struct { WCHAR *clsid; - } comclass; - struct { + WCHAR *tlbid; + WCHAR *progid; + WCHAR *name; /* clrClass: class name */ + WCHAR *version; /* clrClass: CLR runtime version */ + DWORD model; + DWORD miscstatus; + DWORD miscstatuscontent; + DWORD miscstatusthumbnail; + DWORD miscstatusicon; + DWORD miscstatusdocprint; + struct progids progids; + } comclass; + struct { WCHAR *iid; + WCHAR *base; + WCHAR *tlib; WCHAR *name; - } proxy; + WCHAR *ps32; /* only stored for 'comInterfaceExternalProxyStub' */ + DWORD mask; + ULONG nummethods; + } ifaceps; struct { WCHAR *name; + BOOL versioned; } class; struct { WCHAR *name; WCHAR *clsid; - } clrclass; - struct - { - WCHAR *name; - WCHAR *clsid; + WCHAR *version; } clrsurrogate; } u; }; @@ -147,6 +450,17 @@ struct assembly struct entity_array entities; }; +enum context_sections +{ + WINDOWCLASS_SECTION = 1, + DLLREDIRECT_SECTION = 2, + TLIBREDIRECT_SECTION = 4, + SERVERREDIRECT_SECTION = 8, + IFACEREDIRECT_SECTION = 16, + CLRSURROGATES_SECTION = 32, + PROGIDREDIRECT_SECTION = 64 +}; + typedef struct _ASSEMBLY_STORAGE_MAP_ENTRY { ULONG Flags; @@ -180,6 +494,15 @@ typedef struct _ACTIVATION_CONTEXT struct assembly *assemblies; unsigned int num_assemblies; unsigned int allocated_assemblies; + /* section data */ + DWORD sections; + struct strsection_header *wndclass_section; + struct strsection_header *dllredirect_section; + struct strsection_header *progid_section; + struct guidsection_header *tlib_section; + struct guidsection_header *comserver_section; + struct guidsection_header *ifaceps_section; + struct guidsection_header *clrsurrogate_section; } ACTIVATION_CONTEXT, *PIACTIVATION_CONTEXT; struct actctx_loader @@ -278,11 +601,87 @@ static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0}; static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0}; static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0}; static const WCHAR processorArchitectureW[] = {'p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e',0}; +static const WCHAR progidW[] = {'p','r','o','g','i','d',0}; static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0}; +static const WCHAR threadingmodelW[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0}; static const WCHAR tlbidW[] = {'t','l','b','i','d',0}; static const WCHAR typeW[] = {'t','y','p','e',0}; static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0}; static const WCHAR xmlnsW[] = {'x','m','l','n','s',0}; +static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0}; +static const WCHAR yesW[] = {'y','e','s',0}; +static const WCHAR noW[] = {'n','o',0}; +static const WCHAR restrictedW[] = {'R','E','S','T','R','I','C','T','E','D',0}; +static const WCHAR controlW[] = {'C','O','N','T','R','O','L',0}; +static const WCHAR hiddenW[] = {'H','I','D','D','E','N',0}; +static const WCHAR hasdiskimageW[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0}; +static const WCHAR flagsW[] = {'f','l','a','g','s',0}; +static const WCHAR miscstatusW[] = {'m','i','s','c','S','t','a','t','u','s',0}; +static const WCHAR miscstatusiconW[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0}; +static const WCHAR miscstatuscontentW[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0}; +static const WCHAR miscstatusthumbnailW[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0}; +static const WCHAR miscstatusdocprintW[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0}; +static const WCHAR baseInterfaceW[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0}; +static const WCHAR nummethodsW[] = {'n','u','m','M','e','t','h','o','d','s',0}; +static const WCHAR proxyStubClsid32W[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0}; +static const WCHAR runtimeVersionW[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0}; +static const WCHAR mscoreeW[] = {'M','S','C','O','R','E','E','.','D','L','L',0}; +static const WCHAR mscoree2W[] = {'m','s','c','o','r','e','e','.','d','l','l',0}; + +static const WCHAR activatewhenvisibleW[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0}; +static const WCHAR actslikebuttonW[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0}; +static const WCHAR actslikelabelW[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0}; +static const WCHAR alignableW[] = {'a','l','i','g','n','a','b','l','e',0}; +static const WCHAR alwaysrunW[] = {'a','l','w','a','y','s','r','u','n',0}; +static const WCHAR canlinkbyole1W[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0}; +static const WCHAR cantlinkinsideW[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0}; +static const WCHAR ignoreactivatewhenvisibleW[] = {'i','g','n','o','r','e','a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0}; +static const WCHAR imemodeW[] = {'i','m','e','m','o','d','e',0}; +static const WCHAR insertnotreplaceW[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0}; +static const WCHAR insideoutW[] = {'i','n','s','i','d','e','o','u','t',0}; +static const WCHAR invisibleatruntimeW[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0}; +static const WCHAR islinkobjectW[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0}; +static const WCHAR nouiactivateW[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0}; +static const WCHAR onlyiconicW[] = {'o','n','l','y','i','c','o','n','i','c',0}; +static const WCHAR recomposeonresizeW[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0}; +static const WCHAR renderingisdeviceindependentW[] = {'r','e','n','d','e','r','i','n','g','i','s','d','e','v','i','c','e','i','n','d','e','p','e','n','d','e','n','t',0}; +static const WCHAR setclientsitefirstW[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0}; +static const WCHAR simpleframeW[] = {'s','i','m','p','l','e','f','r','a','m','e',0}; +static const WCHAR staticW[] = {'s','t','a','t','i','c',0}; +static const WCHAR supportsmultilevelundoW[] = {'s','u','p','p','o','r','t','s','m','u','l','t','i','l','e','v','e','l','u','n','d','o',0}; +static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0}; + +struct olemisc_entry +{ + const WCHAR *name; + OLEMISC value; +}; + +static const struct olemisc_entry olemisc_values[] = +{ + { activatewhenvisibleW, OLEMISC_ACTIVATEWHENVISIBLE }, + { actslikebuttonW, OLEMISC_ACTSLIKEBUTTON }, + { actslikelabelW, OLEMISC_ACTSLIKELABEL }, + { alignableW, OLEMISC_ALIGNABLE }, + { alwaysrunW, OLEMISC_ALWAYSRUN }, + { canlinkbyole1W, OLEMISC_CANLINKBYOLE1 }, + { cantlinkinsideW, OLEMISC_CANTLINKINSIDE }, + { ignoreactivatewhenvisibleW, OLEMISC_IGNOREACTIVATEWHENVISIBLE }, + { imemodeW, OLEMISC_IMEMODE }, + { insertnotreplaceW, OLEMISC_INSERTNOTREPLACE }, + { insideoutW, OLEMISC_INSIDEOUT }, + { invisibleatruntimeW, OLEMISC_INVISIBLEATRUNTIME }, + { islinkobjectW, OLEMISC_ISLINKOBJECT }, + { nouiactivateW, OLEMISC_NOUIACTIVATE }, + { onlyiconicW, OLEMISC_ONLYICONIC }, + { recomposeonresizeW, OLEMISC_RECOMPOSEONRESIZE }, + { renderingisdeviceindependentW, OLEMISC_RENDERINGISDEVICEINDEPENDENT }, + { setclientsitefirstW, OLEMISC_SETCLIENTSITEFIRST }, + { simpleframeW, OLEMISC_SIMPLEFRAME }, + { staticW, OLEMISC_STATIC }, + { supportsmultilevelundoW, OLEMISC_SUPPORTSMULTILEVELUNDO }, + { wantstomenumergeW, OLEMISC_WANTSTOMENUMERGE } +}; static const WCHAR g_xmlW[] = {'?','x','m','l',0}; static const WCHAR manifestv1W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','1',0}; @@ -460,7 +859,7 @@ static struct entity* add_entity(struct entity_array *array, DWORD kind) static void free_entity_array(struct entity_array *array) { - unsigned int i; + unsigned int i, j; for (i = 0; i < array->num; i++) { struct entity *entity = &array->base[i]; @@ -468,26 +867,31 @@ static void free_entity_array(struct entity_array *array) { case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION: RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.clsid); + RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.tlbid); + RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progid); + RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.name); + RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.version); + for (j = 0; j < entity->u.comclass.progids.num; j++) + RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progids.progids[j]); + RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progids.progids); break; case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION: - RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.proxy.iid); - RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.proxy.name); + RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.iid); + RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.base); + RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.ps32); + RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.name); break; case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION: RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.tlbid); - RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.version); RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.helpdir); break; case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION: RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.class.name); break; - case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION: - RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrclass.name); - RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrclass.clsid); - break; case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES: RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.name); RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.clsid); + RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.version); break; default: DPRINT1("Unknown entity kind %u\n", entity->kind); @@ -1004,7 +1408,110 @@ static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* a return parse_expect_end_elem(xmlbuf, assemblyIdentityW, asmv1W); } -static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll) +static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value) +{ + static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0}; + static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0}; + static const WCHAR freeW[] = {'F','r','e','e',0}; + static const WCHAR bothW[] = {'B','o','t','h',0}; + + if (value->len == 0) return ThreadingModel_No; + if (xmlstr_cmp(value, apartW)) + return ThreadingModel_Apartment; + else if (xmlstr_cmp(value, freeW)) + return ThreadingModel_Free; + else if (xmlstr_cmp(value, bothW)) + return ThreadingModel_Both; + else if (xmlstr_cmp(value, neutralW)) + return ThreadingModel_Neutral; + else + return ThreadingModel_No; +}; + +static OLEMISC get_olemisc_value(const WCHAR *str, int len) +{ + int min, max; + + min = 0; + max = sizeof(olemisc_values)/sizeof(struct olemisc_entry) - 1; + + while (min <= max) + { + int n, c; + + n = (min+max)/2; + + c = strncmpW(olemisc_values[n].name, str, len); + if (!c && !olemisc_values[n].name[len]) + return olemisc_values[n].value; + + if (c >= 0) + max = n-1; + else + min = n+1; + } + + DPRINT1("unknown flag %S\n", str); + return 0; +} + +static DWORD parse_com_class_misc(const xmlstr_t *value) +{ + const WCHAR *str = value->ptr, *start; + DWORD flags = 0; + int i = 0; + + /* it's comma separated list of flags */ + while (i < value->len) + { + start = str; + while (*str != ',' && (i++ < value->len)) str++; + + flags |= get_olemisc_value(start, str-start); + + /* skip separator */ + str++; + i++; + } + + return flags; +} + +static BOOL com_class_add_progid(const xmlstr_t *progid, struct entity *entity) +{ + struct progids *progids = &entity->u.comclass.progids; + + if (progids->allocated == 0) + { + progids->allocated = 4; + if (!(progids->progids = RtlAllocateHeap(RtlGetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE; + } + + if (progids->allocated == progids->num) + { + progids->allocated *= 2; + progids->progids = RtlReAllocateHeap(RtlGetProcessHeap(), 0, progids->progids, progids->allocated * sizeof(WCHAR*)); + } + + if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE; + progids->num++; + + return TRUE; +} + +static BOOL parse_com_class_progid(xmlbuf_t* xmlbuf, struct entity *entity) +{ + xmlstr_t content; + BOOL end = FALSE; + + if (!parse_expect_no_attr(xmlbuf, &end) || end || !parse_text_content(xmlbuf, &content)) + return FALSE; + + if (!com_class_add_progid(&content, entity)) return FALSE; + return parse_expect_end_elem(xmlbuf, progidW, asmv1W); +} + +static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader *acl) { xmlstr_t elem, attr_name, attr_value; BOOL ret = TRUE, end = FALSE, error; @@ -1020,6 +1527,42 @@ static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll) { if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE; } + else if (xmlstr_cmp(&attr_name, progidW)) + { + if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE; + } + else if (xmlstr_cmp(&attr_name, tlbidW)) + { + if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE; + } + else if (xmlstr_cmp(&attr_name, threadingmodelW)) + { + entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value); + } + else if (xmlstr_cmp(&attr_name, miscstatusW)) + { + entity->u.comclass.miscstatus = parse_com_class_misc(&attr_value); + } + else if (xmlstr_cmp(&attr_name, miscstatuscontentW)) + { + entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr_value); + } + else if (xmlstr_cmp(&attr_name, miscstatusthumbnailW)) + { + entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr_value); + } + else if (xmlstr_cmp(&attr_name, miscstatusiconW)) + { + entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr_value); + } + else if (xmlstr_cmp(&attr_name, miscstatusdocprintW)) + { + entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr_value); + } + else if (xmlstr_cmp(&attr_name, descriptionW)) + { + /* not stored */ + } else { attr_nameU = xmlstr2unicode(&attr_name); @@ -1028,15 +1571,25 @@ static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll) } } - if (error || end) return end; + if (error) return FALSE; - while ((ret = next_xml_elem(xmlbuf, &elem))) + acl->actctx->sections |= SERVERREDIRECT_SECTION; + if (entity->u.comclass.progid) + acl->actctx->sections |= PROGIDREDIRECT_SECTION; + + if (end) return TRUE; + + while (ret && (ret = next_xml_elem(xmlbuf, &elem))) { if (xmlstr_cmp_end(&elem, comClassW)) { ret = parse_end_element(xmlbuf); break; } + else if (xmlstr_cmp(&elem, progidW)) + { + ret = parse_com_class_progid(xmlbuf, entity); + } else { attr_nameU = xmlstr2unicode(&elem); @@ -1044,10 +1597,35 @@ static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll) ret = parse_unknown_elem(xmlbuf, &elem); } } + + if (entity->u.comclass.progids.num) + acl->actctx->sections |= PROGIDREDIRECT_SECTION; + return ret; } -static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll) +static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity) +{ + const WCHAR *curr; + ULONG num = 0; + + for (curr = str->ptr; curr < str->ptr + str->len; curr++) + { + if (*curr >= '0' && *curr <= '9') + num = num * 10 + *curr - '0'; + else + { + UNICODE_STRING strU = xmlstr2unicode(str); + DPRINT1("wrong numeric value %wZ\n", &strU); + return FALSE; + } + } + entity->u.ifaceps.nummethods = num; + + return TRUE; +} + +static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl) { xmlstr_t attr_name, attr_value; BOOL end = FALSE, error; @@ -1061,11 +1639,29 @@ static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redi { if (xmlstr_cmp(&attr_name, iidW)) { - if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE; + if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE; } - if (xmlstr_cmp(&attr_name, g_nameW)) + else if (xmlstr_cmp(&attr_name, g_nameW)) + { + if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE; + } + else if (xmlstr_cmp(&attr_name, baseInterfaceW)) + { + if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE; + entity->u.ifaceps.mask |= BaseIface; + } + else if (xmlstr_cmp(&attr_name, nummethodsW)) + { + if (!(parse_nummethods(&attr_value, entity))) return FALSE; + entity->u.ifaceps.mask |= NumMethods; + } + else if (xmlstr_cmp(&attr_name, tlbidW)) + { + if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE; + } + /* not used */ + else if (xmlstr_cmp(&attr_name, proxyStubClsid32W) || xmlstr_cmp(&attr_name, threadingmodelW)) { - if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE; } else { @@ -1075,11 +1671,83 @@ static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redi } } - if (error || end) return end; + if (error) return FALSE; + acl->actctx->sections |= IFACEREDIRECT_SECTION; + if (end) return TRUE; + return parse_expect_end_elem(xmlbuf, comInterfaceProxyStubW, asmv1W); } -static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll) +static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity) +{ + WORD *flags = &entity->u.typelib.flags; + const WCHAR *str = value->ptr, *start; + int i = 0; + + *flags = 0; + + /* it's comma separated list of flags */ + while (i < value->len) + { + start = str; + while (*str != ',' && (i++ < value->len)) str++; + + if (!strncmpiW(start, restrictedW, str-start)) + *flags |= LIBFLAG_FRESTRICTED; + else if (!strncmpiW(start, controlW, str-start)) + *flags |= LIBFLAG_FCONTROL; + else if (!strncmpiW(start, hiddenW, str-start)) + *flags |= LIBFLAG_FHIDDEN; + else if (!strncmpiW(start, hasdiskimageW, str-start)) + *flags |= LIBFLAG_FHASDISKIMAGE; + else + { + UNICODE_STRING valueU = xmlstr2unicode(value); + DPRINT1("unknown flags value %wZ\n", &valueU); + return FALSE; + } + + /* skip separator */ + str++; + i++; + } + + return TRUE; +} + +static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity) +{ + unsigned int ver[2]; + unsigned int pos; + const WCHAR *curr; + UNICODE_STRING strW; + + /* major.minor */ + ver[0] = ver[1] = pos = 0; + for (curr = str->ptr; curr < str->ptr + str->len; curr++) + { + if (*curr >= '0' && *curr <= '9') + { + ver[pos] = ver[pos] * 10 + *curr - '0'; + if (ver[pos] >= 0x10000) goto error; + } + else if (*curr == '.') + { + if (++pos >= 2) goto error; + } + else goto error; + } + entity->u.typelib.major = ver[0]; + entity->u.typelib.minor = ver[1]; + return TRUE; + +error: + strW = xmlstr2unicode(str); + DPRINT1("FIXME: wrong typelib version value (%wZ)\n", &strW); + return FALSE; +} + +static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl) { xmlstr_t attr_name, attr_value; BOOL end = FALSE, error; @@ -1095,14 +1763,70 @@ static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll) { if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE; } - if (xmlstr_cmp(&attr_name, versionW)) + else if (xmlstr_cmp(&attr_name, versionW)) { - if (!(entity->u.typelib.version = xmlstrdupW(&attr_value))) return FALSE; + if (!parse_typelib_version(&attr_value, entity)) return FALSE; } - if (xmlstr_cmp(&attr_name, helpdirW)) + else if (xmlstr_cmp(&attr_name, helpdirW)) { if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE; } + else if (xmlstr_cmp(&attr_name, flagsW)) + { + if (!parse_typelib_flags(&attr_value, entity)) return FALSE; + } + else + { + attr_nameU = xmlstr2unicode(&attr_name); + attr_valueU = xmlstr2unicode(&attr_value); + DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU); + } + } + + if (error) return FALSE; + + acl->actctx->sections |= TLIBREDIRECT_SECTION; + + if (end) return TRUE; + + return parse_expect_end_elem(xmlbuf, typelibW, asmv1W); +} + +static inline int aligned_string_len(int len) +{ + return (len + 3) & ~3; +} + +static int get_assembly_version(struct assembly *assembly, WCHAR *ret) +{ + static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0}; + struct assembly_version *ver = &assembly->id.version; + WCHAR buff[25]; + + if (!ret) ret = buff; + return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision); +} + +static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl) +{ + xmlstr_t elem, content, attr_name, attr_value; + BOOL end = FALSE, ret = TRUE, error; + struct entity* entity; + UNICODE_STRING elemU, attr_nameU, attr_valueU; + + if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION))) + return FALSE; + + entity->u.class.versioned = TRUE; + while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end)) + { + if (xmlstr_cmp(&attr_name, versionedW)) + { + if (xmlstr_cmpi(&attr_value, noW)) + entity->u.class.versioned = FALSE; + else if (!xmlstr_cmpi(&attr_value, yesW)) + return FALSE; + } else { attr_nameU = xmlstr2unicode(&attr_name); @@ -1112,26 +1836,13 @@ static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll) } if (error || end) return end; - return parse_expect_end_elem(xmlbuf, typelibW, asmv1W); -} - -static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll) -{ - xmlstr_t elem, content; - BOOL end = FALSE, ret = TRUE; - struct entity* entity; - UNICODE_STRING elemU; - - if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION))) - return FALSE; - - if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE; - if (end) return FALSE; if (!parse_text_content(xmlbuf, &content)) return FALSE; if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE; + acl->actctx->sections |= WINDOWCLASS_SECTION; + while (ret && (ret = next_xml_elem(xmlbuf, &elem))) { if (xmlstr_cmp_end(&elem, windowClassW)) @@ -1211,7 +1922,8 @@ static BOOL parse_description_elem(xmlbuf_t* xmlbuf) } static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf, - struct assembly* assembly) + struct assembly* assembly, + struct actctx_loader* acl) { xmlstr_t attr_name, attr_value; UNICODE_STRING attr_nameU, attr_valueU; @@ -1225,11 +1937,29 @@ static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf, { if (xmlstr_cmp(&attr_name, iidW)) { - if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE; + if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE; } - if (xmlstr_cmp(&attr_name, g_nameW)) + else if (xmlstr_cmp(&attr_name, g_nameW)) { - if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE; + if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE; + } + else if (xmlstr_cmp(&attr_name, baseInterfaceW)) + { + if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE; + entity->u.ifaceps.mask |= BaseIface; + } + else if (xmlstr_cmp(&attr_name, nummethodsW)) + { + if (!(parse_nummethods(&attr_value, entity))) return FALSE; + entity->u.ifaceps.mask |= NumMethods; + } + else if (xmlstr_cmp(&attr_name, proxyStubClsid32W)) + { + if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr_value))) return FALSE; + } + else if (xmlstr_cmp(&attr_name, tlbidW)) + { + if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE; } else { @@ -1239,43 +1969,89 @@ static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf, } } - if (error || end) return end; + if (error) return FALSE; + acl->actctx->sections |= IFACEREDIRECT_SECTION; + if (end) return TRUE; + return parse_expect_end_elem(xmlbuf, comInterfaceExternalProxyStubW, asmv1W); } -static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly) +static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl) { - xmlstr_t attr_name, attr_value; - UNICODE_STRING attr_nameU, attr_valueU; - BOOL end = FALSE, error; + xmlstr_t attr_name, attr_value, elem; + BOOL end = FALSE, error, ret = TRUE; struct entity* entity; - entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION); + entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION); if (!entity) return FALSE; while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end)) { if (xmlstr_cmp(&attr_name, g_nameW)) { - if (!(entity->u.clrclass.name = xmlstrdupW(&attr_value))) return FALSE; + if (!(entity->u.comclass.name = xmlstrdupW(&attr_value))) return FALSE; } else if (xmlstr_cmp(&attr_name, clsidW)) { - if (!(entity->u.clrclass.clsid = xmlstrdupW(&attr_value))) return FALSE; + if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE; + } + else if (xmlstr_cmp(&attr_name, progidW)) + { + if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE; + } + else if (xmlstr_cmp(&attr_name, tlbidW)) + { + if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE; + } + else if (xmlstr_cmp(&attr_name, threadingmodelW)) + { + entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value); + } + else if (xmlstr_cmp(&attr_name, runtimeVersionW)) + { + if (!(entity->u.comclass.version = xmlstrdupW(&attr_value))) return FALSE; } else { + UNICODE_STRING attr_nameU, attr_valueU; attr_nameU = xmlstr2unicode(&attr_name); attr_valueU = xmlstr2unicode(&attr_value); DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU); } } - if (error || end) return end; - return parse_expect_end_elem(xmlbuf, clrClassW, asmv1W); + if (error) return FALSE; + acl->actctx->sections |= SERVERREDIRECT_SECTION; + if (entity->u.comclass.progid) + acl->actctx->sections |= PROGIDREDIRECT_SECTION; + if (end) return TRUE; + + while (ret && (ret = next_xml_elem(xmlbuf, &elem))) + { + if (xmlstr_cmp_end(&elem, clrClassW)) + { + ret = parse_end_element(xmlbuf); + break; + } + else if (xmlstr_cmp(&elem, progidW)) + { + ret = parse_com_class_progid(xmlbuf, entity); + } + else + { + UNICODE_STRING elemU = xmlstr2unicode(&elem); + DPRINT1("unknown elem %wZ\n", &elemU); + ret = parse_unknown_elem(xmlbuf, &elem); + } + } + + if (entity->u.comclass.progids.num) + acl->actctx->sections |= PROGIDREDIRECT_SECTION; + + return ret; } -static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly) +static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl) { xmlstr_t attr_name, attr_value; UNICODE_STRING attr_nameU, attr_valueU; @@ -1295,6 +2071,10 @@ static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly { if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE; } + else if (xmlstr_cmp(&attr_name, runtimeVersionW)) + { + if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr_value))) return FALSE; + } else { attr_nameU = xmlstr2unicode(&attr_name); @@ -1303,7 +2083,10 @@ static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly } } - if (error || end) return end; + if (error) return FALSE; + acl->actctx->sections |= CLRSURROGATES_SECTION; + if (end) return TRUE; + return parse_expect_end_elem(xmlbuf, clrSurrogateW, asmv1W); } @@ -1322,6 +2105,8 @@ static BOOL parse_dependent_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai)) return FALSE; + //TRACE( "adding name=%s version=%s arch=%s\n", debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) ); + /* store the newly found identity for later loading */ if (!add_dependent_assembly_id(acl, &ai)) return FALSE; @@ -1359,7 +2144,6 @@ static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl) if (xmlstr_cmp(&attr_name, optionalW)) { - static const WCHAR yesW[] = {'y','e','s',0}; optional = xmlstr_cmpi( &attr_value, yesW ); DPRINT1("optional=%wZ\n", &attr_valueU); } @@ -1407,7 +2191,7 @@ static BOOL parse_noinheritable_elem(xmlbuf_t* xmlbuf) return end || parse_expect_end_elem(xmlbuf, noInheritableW, asmv1W); } -static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly) +static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader* acl) { xmlstr_t attr_name, attr_value, elem; UNICODE_STRING attr_nameU, attr_valueU; @@ -1443,6 +2227,9 @@ static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly) } if (error || !dll->name) return FALSE; + + acl->actctx->sections |= DLLREDIRECT_SECTION; + if (end) return TRUE; while (ret && (ret = next_xml_elem(xmlbuf, &elem))) @@ -1454,24 +2241,24 @@ static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly) } else if (xmlstr_cmp(&elem, comClassW)) { - ret = parse_com_class_elem(xmlbuf, dll); + ret = parse_com_class_elem(xmlbuf, dll, acl); } else if (xmlstr_cmp(&elem, comInterfaceProxyStubW)) { - ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll); + ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl); } - else if (xmlstr_cmp(&elem, asmv2hashW)) + else if (xml_elem_cmp(&elem, hashW, asmv2W)) { DPRINT1("asmv2hash (undocumented) not supported\n"); ret = parse_unknown_elem(xmlbuf, &elem); } else if (xmlstr_cmp(&elem, typelibW)) { - ret = parse_typelib_elem(xmlbuf, dll); + ret = parse_typelib_elem(xmlbuf, dll, acl); } else if (xmlstr_cmp(&elem, windowClassW)) { - ret = parse_window_class_elem(xmlbuf, dll); + ret = parse_window_class_elem(xmlbuf, dll, acl); } else { @@ -1492,6 +2279,8 @@ static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, UNICODE_STRING attr_nameU, attr_valueU; BOOL end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE; + DPRINT("(%p)\n", xmlbuf); + while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end)) { attr_nameU = xmlstr2unicode(&attr_name); @@ -1532,7 +2321,7 @@ static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, assembly->no_inherit = TRUE; } - if (xmlstr_cmp(&elem, noInheritableW)) + if (xml_elem_cmp(&elem, noInheritableW, asmv1W)) { if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem)) return FALSE; @@ -1543,36 +2332,36 @@ static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, while (ret) { - if (xmlstr_cmp_end(&elem, assemblyW)) + if (xml_elem_cmp_end(&elem, assemblyW, asmv1W)) { ret = parse_end_element(xmlbuf); break; } - else if (xmlstr_cmp(&elem, descriptionW)) + else if (xml_elem_cmp(&elem, descriptionW, asmv1W)) { ret = parse_description_elem(xmlbuf); } - else if (xmlstr_cmp(&elem, comInterfaceExternalProxyStubW)) + else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W)) { - ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly); + ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl); } - else if (xmlstr_cmp(&elem, dependencyW)) + else if (xml_elem_cmp(&elem, dependencyW, asmv1W)) { ret = parse_dependency_elem(xmlbuf, acl); } - else if (xmlstr_cmp(&elem, fileW)) + else if (xml_elem_cmp(&elem, fileW, asmv1W)) { - ret = parse_file_elem(xmlbuf, assembly); + ret = parse_file_elem(xmlbuf, assembly, acl); } - else if (xmlstr_cmp(&elem, clrClassW)) + else if (xml_elem_cmp(&elem, clrClassW, asmv1W)) { - ret = parse_clr_class_elem(xmlbuf, assembly); + ret = parse_clr_class_elem(xmlbuf, assembly, acl); } - else if (xmlstr_cmp(&elem, clrSurrogateW)) + else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W)) { - ret = parse_clr_surrogate_elem(xmlbuf, assembly); + ret = parse_clr_surrogate_elem(xmlbuf, assembly, acl); } - else if (xmlstr_cmp(&elem, assemblyIdentityW)) + else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W)) { if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE; @@ -1625,7 +2414,7 @@ static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembl (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem))) return STATUS_SXS_CANT_GEN_ACTCTX; - if (!xmlstr_cmp(&elem, assemblyW)) + if (!xml_elem_cmp(&elem, assemblyW, asmv1W)) { elemU = xmlstr2unicode(&elem); DPRINT1("root element is %wZ, not \n", &elemU); @@ -2220,7 +3009,10 @@ static NTSTATUS parse_depend_manifests(struct actctx_loader* acl) { if (!acl->dependencies[i].optional) { - DPRINT1( "Could not find dependent assembly %S\n", acl->dependencies[i].name ); + const struct assembly_version *ver = &acl->dependencies[i].version; + DPRINT1( "Could not find dependent assembly %S (%u.%u.%u.%u)\n", + acl->dependencies[i].name, + ver->major, ver->minor, ver->build, ver->revision ); status = STATUS_SXS_CANT_GEN_ACTCTX; break; } @@ -2266,26 +3058,43 @@ static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class ) return status; } -static NTSTATUS fill_keyed_data(PACTCTX_SECTION_KEYED_DATA data, PVOID v1, PVOID v2, unsigned int i) +static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section) { - data->ulDataFormatVersion = 1; - data->lpData = v1; - data->ulLength = 20; /* FIXME */ - data->lpSectionGlobalData = NULL; /* FIXME */ - data->ulSectionGlobalDataLength = 0; /* FIXME */ - data->lpSectionBase = v2; - data->ulSectionTotalLength = 0; /* FIXME */ - data->hActCtx = NULL; - if (data->cbSize >= offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) - data->ulAssemblyRosterIndex = i + 1; + unsigned int i, j, total_len = 0, dll_count = 0; + struct strsection_header *header; + struct dllredirect_data *data; + struct string_index *index; + ULONG name_offset; - return STATUS_SUCCESS; -} + /* compute section length */ + for (i = 0; i < actctx->num_assemblies; i++) + { + struct assembly *assembly = &actctx->assemblies[i]; + for (j = 0; j < assembly->num_dlls; j++) + { + struct dll_redirect *dll = &assembly->dlls[j]; -static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *section_name, - PACTCTX_SECTION_KEYED_DATA data) -{ - unsigned int i, j, snlen = section_name->Length / sizeof(WCHAR); + /* each entry needs index, data and string data */ + total_len += sizeof(*index); + total_len += sizeof(*data); + total_len += aligned_string_len((strlenW(dll->name)+1)*sizeof(WCHAR)); + } + + dll_count += assembly->num_dlls; + } + + total_len += sizeof(*header); + + header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); + if (!header) return STATUS_NO_MEMORY; + + memset(header, 0, sizeof(*header)); + header->magic = STRSECTION_MAGIC; + header->size = sizeof(*header); + header->count = dll_count; + header->index_offset = sizeof(*header); + index = (struct string_index*)((BYTE*)header + header->index_offset); + name_offset = header->index_offset + header->count*sizeof(*index); for (i = 0; i < actctx->num_assemblies; i++) { @@ -2293,17 +3102,200 @@ static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_S for (j = 0; j < assembly->num_dlls; j++) { struct dll_redirect *dll = &assembly->dlls[j]; - if (!strncmpiW(section_name->Buffer, dll->name, snlen) && !dll->name[snlen]) - return fill_keyed_data(data, dll, assembly, i); + UNICODE_STRING str; + WCHAR *ptrW; + + /* setup new index entry */ + str.Buffer = dll->name; + str.Length = strlenW(dll->name)*sizeof(WCHAR); + str.MaximumLength = str.Length + sizeof(WCHAR); + /* hash original class name */ + RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash); + + index->name_offset = name_offset; + index->name_len = str.Length; + index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength); + index->data_len = sizeof(*data); + index->rosterindex = i + 1; + + /* setup data */ + data = (struct dllredirect_data*)((BYTE*)header + index->data_offset); + data->size = sizeof(*data); + data->unk = 2; /* FIXME: seems to be constant */ + memset(data->res, 0, sizeof(data->res)); + + /* dll name */ + ptrW = (WCHAR*)((BYTE*)header + index->name_offset); + memcpy(ptrW, dll->name, index->name_len); + ptrW[index->name_len/sizeof(WCHAR)] = 0; + + name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength); + + index++; } } - return STATUS_SXS_KEY_NOT_FOUND; + + *section = header; + + return STATUS_SUCCESS; } -static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *section_name, - PACTCTX_SECTION_KEYED_DATA data) +static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name) { - unsigned int i, j, k, snlen = section_name->Length / sizeof(WCHAR); + struct string_index *iter, *index = NULL; + ULONG hash = 0, i; + + RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash); + iter = (struct string_index*)((BYTE*)section + section->index_offset); + + for (i = 0; i < section->count; i++) + { + if (iter->hash == hash) + { + const WCHAR *nameW = (WCHAR*)((BYTE*)section + iter->name_offset); + + if (!strcmpiW(nameW, name->Buffer)) + { + index = iter; + break; + } + else + DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash, name, nameW); + } + iter++; + } + + return index; +} + +static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid) +{ + struct guid_index *iter, *index = NULL; + ULONG i; + + iter = (struct guid_index*)((BYTE*)section + section->index_offset); + + for (i = 0; i < section->count; i++) + { + if (!memcmp(guid, &iter->guid, sizeof(*guid))) + { + index = iter; + break; + } + iter++; + } + + return index; +} + +static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index) +{ + return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset); +} + +static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name, + PACTCTX_SECTION_KEYED_DATA data) +{ + struct dllredirect_data *dll; + struct string_index *index; + + if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; + + if (!actctx->dllredirect_section) + { + struct strsection_header *section; + + NTSTATUS status = build_dllredirect_section(actctx, §ion); + if (status) return status; + + if (InterlockedCompareExchangePointer((void**)&actctx->dllredirect_section, section, NULL)) + RtlFreeHeap(RtlGetProcessHeap(), 0, section); + } + + index = find_string_index(actctx->dllredirect_section, name); + if (!index) return STATUS_SXS_KEY_NOT_FOUND; + + dll = get_dllredirect_data(actctx, index); + + data->ulDataFormatVersion = 1; + data->lpData = dll; + data->ulLength = dll->size; + data->lpSectionGlobalData = NULL; + data->ulSectionGlobalDataLength = 0; + data->lpSectionBase = actctx->dllredirect_section; + data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->dllredirect_section ); + data->hActCtx = NULL; + + if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) + data->ulAssemblyRosterIndex = index->rosterindex; + + return STATUS_SUCCESS; +} + +static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx) +{ + return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset); +} + +static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index) +{ + return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset); +} + +static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section) +{ + unsigned int i, j, k, total_len = 0, class_count = 0; + struct wndclass_redirect_data *data; + struct strsection_header *header; + struct string_index *index; + ULONG name_offset; + + /* compute section length */ + for (i = 0; i < actctx->num_assemblies; i++) + { + struct assembly *assembly = &actctx->assemblies[i]; + for (j = 0; j < assembly->num_dlls; j++) + { + struct dll_redirect *dll = &assembly->dlls[j]; + for (k = 0; k < dll->entities.num; k++) + { + struct entity *entity = &dll->entities.base[k]; + if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION) + { + int class_len = strlenW(entity->u.class.name) + 1; + int len; + + /* each class entry needs index, data and string data */ + total_len += sizeof(*index); + total_len += sizeof(*data); + /* original name is stored separately */ + total_len += aligned_string_len(class_len*sizeof(WCHAR)); + /* versioned name and module name are stored one after another */ + if (entity->u.class.versioned) + len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */; + else + len = class_len; + len += strlenW(dll->name) + 1; + total_len += aligned_string_len(len*sizeof(WCHAR)); + + class_count++; + } + } + } + } + + total_len += sizeof(*header); + + header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); + if (!header) return STATUS_NO_MEMORY; + + memset(header, 0, sizeof(*header)); + header->magic = STRSECTION_MAGIC; + header->size = sizeof(*header); + header->count = class_count; + header->index_offset = sizeof(*header); + index = (struct string_index*)((BYTE*)header + header->index_offset); + name_offset = header->index_offset + header->count*sizeof(*index); for (i = 0; i < actctx->num_assemblies; i++) { @@ -2316,13 +3308,1192 @@ static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRI struct entity *entity = &dll->entities.base[k]; if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION) { - if (!strncmpiW(section_name->Buffer, entity->u.class.name, snlen) && !entity->u.class.name[snlen]) - return fill_keyed_data(data, entity, dll, i); + static const WCHAR exclW[] = {'!',0}; + ULONG versioned_len, module_len; + UNICODE_STRING str; + WCHAR *ptrW; + + /* setup new index entry */ + str.Buffer = entity->u.class.name; + str.Length = strlenW(entity->u.class.name)*sizeof(WCHAR); + str.MaximumLength = str.Length + sizeof(WCHAR); + /* hash original class name */ + RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash); + + /* include '!' separator too */ + if (entity->u.class.versioned) + versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length; + else + versioned_len = str.Length; + module_len = strlenW(dll->name)*sizeof(WCHAR); + + index->name_offset = name_offset; + index->name_len = str.Length; + index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength); + index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */; + index->rosterindex = i + 1; + + /* setup data */ + data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset); + data->size = sizeof(*data); + data->res = 0; + data->name_len = versioned_len; + data->name_offset = sizeof(*data); + data->module_len = module_len; + data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR); + + /* original class name */ + ptrW = (WCHAR*)((BYTE*)header + index->name_offset); + memcpy(ptrW, entity->u.class.name, index->name_len); + ptrW[index->name_len/sizeof(WCHAR)] = 0; + + /* module name */ + ptrW = (WCHAR*)((BYTE*)header + data->module_offset); + memcpy(ptrW, dll->name, data->module_len); + ptrW[data->module_len/sizeof(WCHAR)] = 0; + + /* versioned name */ + ptrW = (WCHAR*)((BYTE*)data + data->name_offset); + if (entity->u.class.versioned) + { + get_assembly_version(assembly, ptrW); + strcatW(ptrW, exclW); + strcatW(ptrW, entity->u.class.name); + } + else + { + memcpy(ptrW, entity->u.class.name, index->name_len); + ptrW[index->name_len/sizeof(WCHAR)] = 0; + } + + name_offset += sizeof(*data); + name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR)); + + index++; } } } } - return STATUS_SXS_KEY_NOT_FOUND; + + *section = header; + + return STATUS_SUCCESS; +} + +static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name, + PACTCTX_SECTION_KEYED_DATA data) +{ + struct string_index *iter, *index = NULL; + struct wndclass_redirect_data *class; + ULONG hash; + int i; + + if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; + + if (!actctx->wndclass_section) + { + struct strsection_header *section; + + NTSTATUS status = build_wndclass_section(actctx, §ion); + if (status) return status; + + if (InterlockedCompareExchangePointer((void**)&actctx->wndclass_section, section, NULL)) + RtlFreeHeap(RtlGetProcessHeap(), 0, section); + } + + hash = 0; + RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash); + iter = get_wndclass_first_index(actctx); + + for (i = 0; i < actctx->wndclass_section->count; i++) + { + if (iter->hash == hash) + { + const WCHAR *nameW = (WCHAR*)((BYTE*)actctx->wndclass_section + iter->name_offset); + + if (!strcmpW(nameW, name->Buffer)) + { + index = iter; + break; + } + else + DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash, name, nameW); + } + iter++; + } + + if (!index) return STATUS_SXS_KEY_NOT_FOUND; + + class = get_wndclass_data(actctx, index); + + data->ulDataFormatVersion = 1; + data->lpData = class; + /* full length includes string length with nulls */ + data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR); + data->lpSectionGlobalData = NULL; + data->ulSectionGlobalDataLength = 0; + data->lpSectionBase = actctx->wndclass_section; + data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->wndclass_section ); + data->hActCtx = NULL; + + if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) + data->ulAssemblyRosterIndex = index->rosterindex; + + return STATUS_SUCCESS; +} + +static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section) +{ + unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0; + struct guidsection_header *header; + ULONG module_offset, data_offset; + struct tlibredirect_data *data; + struct guid_index *index; + + /* compute section length */ + for (i = 0; i < actctx->num_assemblies; i++) + { + struct assembly *assembly = &actctx->assemblies[i]; + for (j = 0; j < assembly->num_dlls; j++) + { + struct dll_redirect *dll = &assembly->dlls[j]; + for (k = 0; k < dll->entities.num; k++) + { + struct entity *entity = &dll->entities.base[k]; + if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION) + { + /* each entry needs index, data and string data for module name and help string */ + total_len += sizeof(*index); + total_len += sizeof(*data); + /* help string is stored separately */ + if (*entity->u.typelib.helpdir) + total_len += aligned_string_len((strlenW(entity->u.typelib.helpdir)+1)*sizeof(WCHAR)); + + /* module names are packed one after another */ + names_len += (strlenW(dll->name)+1)*sizeof(WCHAR); + + tlib_count++; + } + } + } + } + + total_len += aligned_string_len(names_len); + total_len += sizeof(*header); + + header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); + if (!header) return STATUS_NO_MEMORY; + + memset(header, 0, sizeof(*header)); + header->magic = GUIDSECTION_MAGIC; + header->size = sizeof(*header); + header->count = tlib_count; + header->index_offset = sizeof(*header) + aligned_string_len(names_len); + index = (struct guid_index*)((BYTE*)header + header->index_offset); + module_offset = sizeof(*header); + data_offset = header->index_offset + tlib_count*sizeof(*index); + + for (i = 0; i < actctx->num_assemblies; i++) + { + struct assembly *assembly = &actctx->assemblies[i]; + for (j = 0; j < assembly->num_dlls; j++) + { + struct dll_redirect *dll = &assembly->dlls[j]; + for (k = 0; k < dll->entities.num; k++) + { + struct entity *entity = &dll->entities.base[k]; + if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION) + { + ULONG module_len, help_len; + UNICODE_STRING str; + WCHAR *ptrW; + + if (*entity->u.typelib.helpdir) + help_len = strlenW(entity->u.typelib.helpdir)*sizeof(WCHAR); + else + help_len = 0; + + module_len = strlenW(dll->name)*sizeof(WCHAR); + + /* setup new index entry */ + RtlInitUnicodeString(&str, entity->u.typelib.tlbid); + RtlGUIDFromString(&str, &index->guid); + index->data_offset = data_offset; + index->data_len = sizeof(*data) + aligned_string_len(help_len); + index->rosterindex = i + 1; + + /* setup data */ + data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset); + data->size = sizeof(*data); + data->res = 0; + data->name_len = module_len; + data->name_offset = module_offset; + /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */ + data->langid = 0; + data->flags = entity->u.typelib.flags; + data->help_len = help_len; + data->help_offset = sizeof(*data); + data->major_version = entity->u.typelib.major; + data->minor_version = entity->u.typelib.minor; + + /* module name */ + ptrW = (WCHAR*)((BYTE*)header + data->name_offset); + memcpy(ptrW, dll->name, data->name_len); + ptrW[data->name_len/sizeof(WCHAR)] = 0; + + /* help string */ + if (data->help_len) + { + ptrW = (WCHAR*)((BYTE*)data + data->help_offset); + memcpy(ptrW, entity->u.typelib.helpdir, data->help_len); + ptrW[data->help_len/sizeof(WCHAR)] = 0; + } + + data_offset += sizeof(*data); + if (help_len) + data_offset += aligned_string_len(help_len + sizeof(WCHAR)); + + module_offset += module_len + sizeof(WCHAR); + + index++; + } + } + } + } + + *section = header; + + return STATUS_SUCCESS; +} + +static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index) +{ + return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset); +} + +static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data) +{ + struct guid_index *index = NULL; + struct tlibredirect_data *tlib; + + if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; + + if (!actctx->tlib_section) + { + struct guidsection_header *section; + + NTSTATUS status = build_tlib_section(actctx, §ion); + if (status) return status; + + if (InterlockedCompareExchangePointer((void**)&actctx->tlib_section, section, NULL)) + RtlFreeHeap(RtlGetProcessHeap(), 0, section); + } + + index = find_guid_index(actctx->tlib_section, guid); + if (!index) return STATUS_SXS_KEY_NOT_FOUND; + + tlib = get_tlib_data(actctx, index); + + data->ulDataFormatVersion = 1; + data->lpData = tlib; + /* full length includes string length with nulls */ + data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR); + data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset; + data->ulSectionGlobalDataLength = actctx->tlib_section->names_len; + data->lpSectionBase = actctx->tlib_section; + data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->tlib_section ); + data->hActCtx = NULL; + + if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) + data->ulAssemblyRosterIndex = index->rosterindex; + + return STATUS_SUCCESS; +} + +static void generate_uuid(ULONG *seed, GUID *guid) +{ + ULONG *ptr = (ULONG*)guid; + int i; + + /* GUID is 16 bytes long */ + for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++) + *ptr = RtlUniform(seed); + + guid->Data3 &= 0x0fff; + guid->Data3 |= (4 << 12); + guid->Data4[0] &= 0x3f; + guid->Data4[0] |= 0x80; +} + +static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll, + unsigned int *count, unsigned int *len, unsigned int *module_len) +{ + unsigned int i; + + for (i = 0; i < entities->num; i++) + { + struct entity *entity = &entities->base[i]; + if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION) + { + /* each entry needs two index entries, extra one goes for alias GUID */ + *len += 2*sizeof(struct guid_index); + /* To save some memory we don't allocated two data structures, + instead alias index and normal index point to the same data structure. */ + *len += sizeof(struct comclassredirect_data); + + /* for clrClass store some more */ + if (entity->u.comclass.name) + { + unsigned int str_len; + + /* all string data is stored together in aligned block */ + str_len = strlenW(entity->u.comclass.name)+1; + if (entity->u.comclass.progid) + str_len += strlenW(entity->u.comclass.progid)+1; + if (entity->u.comclass.version) + str_len += strlenW(entity->u.comclass.version)+1; + + *len += sizeof(struct clrclass_data); + *len += aligned_string_len(str_len*sizeof(WCHAR)); + + /* module name is forced to mscoree.dll, and stored two times with different case */ + *module_len += sizeof(mscoreeW) + sizeof(mscoree2W); + } + else + { + /* progid string is stored separately */ + if (entity->u.comclass.progid) + *len += aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR)); + + *module_len += (strlenW(dll->name)+1)*sizeof(WCHAR); + } + + *count += 1; + } + } +} + +static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities, + const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset, + ULONG *seed, ULONG rosterindex) +{ + unsigned int i; + + for (i = 0; i < entities->num; i++) + { + struct entity *entity = &entities->base[i]; + if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION) + { + ULONG module_len, progid_len, str_len = 0; + struct comclassredirect_data *data; + struct guid_index *alias_index; + struct clrclass_data *clrdata; + UNICODE_STRING str; + WCHAR *ptrW; + + if (entity->u.comclass.progid) + progid_len = strlenW(entity->u.comclass.progid)*sizeof(WCHAR); + else + progid_len = 0; + + module_len = dll ? strlenW(dll->name)*sizeof(WCHAR) : strlenW(mscoreeW)*sizeof(WCHAR); + + /* setup new index entry */ + RtlInitUnicodeString(&str, entity->u.comclass.clsid); + RtlGUIDFromString(&str, &(*index)->guid); + + (*index)->data_offset = *data_offset; + (*index)->data_len = sizeof(*data); /* additional length added later */ + (*index)->rosterindex = rosterindex; + + /* Setup new index entry for alias guid. Alias index records are placed after + normal records, so normal guids are hit first on search. Note that class count + is doubled. */ + alias_index = (*index) + section->count/2; + generate_uuid(seed, &alias_index->guid); + alias_index->data_offset = (*index)->data_offset; + alias_index->data_len = 0; + alias_index->rosterindex = (*index)->rosterindex; + + /* setup data */ + data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset); + data->size = sizeof(*data); + data->res = 0; + data->res1[0] = 0; + data->res1[1] = 0; + data->model = entity->u.comclass.model; + data->clsid = (*index)->guid; + data->alias = alias_index->guid; + data->clsid2 = data->clsid; + if (entity->u.comclass.tlbid) + { + RtlInitUnicodeString(&str, entity->u.comclass.tlbid); + RtlGUIDFromString(&str, &data->tlbid); + } + else + memset(&data->tlbid, 0, sizeof(data->tlbid)); + data->name_len = module_len; + data->name_offset = *module_offset; + data->progid_len = progid_len; + data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */ + data->clrdata_len = 0; /* will be set later */ + data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0; + data->miscstatus = entity->u.comclass.miscstatus; + data->miscstatuscontent = entity->u.comclass.miscstatuscontent; + data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail; + data->miscstatusicon = entity->u.comclass.miscstatusicon; + data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint; + + /* mask describes which misc* data is available */ + data->miscmask = 0; + if (data->miscstatus) + data->miscmask |= MiscStatus; + if (data->miscstatuscontent) + data->miscmask |= MiscStatusContent; + if (data->miscstatusthumbnail) + data->miscmask |= MiscStatusThumbnail; + if (data->miscstatusicon) + data->miscmask |= MiscStatusIcon; + if (data->miscstatusdocprint) + data->miscmask |= MiscStatusDocPrint; + + if (data->clrdata_offset) + { + clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset); + + clrdata->size = sizeof(*clrdata); + clrdata->res[0] = 0; + clrdata->res[1] = 2; /* FIXME: unknown field */ + clrdata->module_len = strlenW(mscoreeW)*sizeof(WCHAR); + clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR); + clrdata->name_len = strlenW(entity->u.comclass.name)*sizeof(WCHAR); + clrdata->name_offset = clrdata->size; + clrdata->version_len = entity->u.comclass.version ? strlenW(entity->u.comclass.version)*sizeof(WCHAR) : 0; + clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0; + clrdata->res2[0] = 0; + clrdata->res2[1] = 0; + + data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR); + + /* module name */ + ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset); + memcpy(ptrW, mscoree2W, clrdata->module_len); + ptrW[clrdata->module_len/sizeof(WCHAR)] = 0; + + ptrW = (WCHAR*)((BYTE*)section + data->name_offset); + memcpy(ptrW, mscoreeW, data->name_len); + ptrW[data->name_len/sizeof(WCHAR)] = 0; + + /* class name */ + ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset); + memcpy(ptrW, entity->u.comclass.name, clrdata->name_len); + ptrW[clrdata->name_len/sizeof(WCHAR)] = 0; + + /* runtime version, optional */ + if (clrdata->version_len) + { + data->clrdata_len += clrdata->version_len + sizeof(WCHAR); + + ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset); + memcpy(ptrW, entity->u.comclass.version, clrdata->version_len); + ptrW[clrdata->version_len/sizeof(WCHAR)] = 0; + } + + if (data->progid_len) + data->progid_offset += data->clrdata_len; + (*index)->data_len += sizeof(*clrdata); + } + else + { + clrdata = NULL; + + /* module name */ + ptrW = (WCHAR*)((BYTE*)section + data->name_offset); + memcpy(ptrW, dll->name, data->name_len); + ptrW[data->name_len/sizeof(WCHAR)] = 0; + } + + /* progid string */ + if (data->progid_len) + { + ptrW = (WCHAR*)((BYTE*)data + data->progid_offset); + memcpy(ptrW, entity->u.comclass.progid, data->progid_len); + ptrW[data->progid_len/sizeof(WCHAR)] = 0; + } + + /* string block length */ + str_len = 0; + if (clrdata) + { + str_len += clrdata->name_len + sizeof(WCHAR); + if (clrdata->version_len) + str_len += clrdata->version_len + sizeof(WCHAR); + } + if (progid_len) + str_len += progid_len + sizeof(WCHAR); + + (*index)->data_len += aligned_string_len(str_len); + alias_index->data_len = (*index)->data_len; + + /* move to next data record */ + (*data_offset) += sizeof(*data) + aligned_string_len(str_len); + (*module_offset) += module_len + sizeof(WCHAR); + + if (clrdata) + { + (*data_offset) += sizeof(*clrdata); + (*module_offset) += clrdata->module_len + sizeof(WCHAR); + } + (*index) += 1; + } + } +} + +static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section) +{ + unsigned int i, j, total_len = 0, class_count = 0, names_len = 0; + struct guidsection_header *header; + ULONG module_offset, data_offset; + struct guid_index *index; + ULONG seed; + + /* compute section length */ + for (i = 0; i < actctx->num_assemblies; i++) + { + struct assembly *assembly = &actctx->assemblies[i]; + get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len); + for (j = 0; j < assembly->num_dlls; j++) + { + struct dll_redirect *dll = &assembly->dlls[j]; + get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len); + } + } + + total_len += aligned_string_len(names_len); + total_len += sizeof(*header); + + header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); + if (!header) return STATUS_NO_MEMORY; + + memset(header, 0, sizeof(*header)); + header->magic = GUIDSECTION_MAGIC; + header->size = sizeof(*header); + header->count = 2*class_count; + header->index_offset = sizeof(*header) + aligned_string_len(names_len); + index = (struct guid_index*)((BYTE*)header + header->index_offset); + module_offset = sizeof(*header); + data_offset = header->index_offset + 2*class_count*sizeof(*index); + + seed = NtGetTickCount(); + for (i = 0; i < actctx->num_assemblies; i++) + { + struct assembly *assembly = &actctx->assemblies[i]; + add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1); + for (j = 0; j < assembly->num_dlls; j++) + { + struct dll_redirect *dll = &assembly->dlls[j]; + add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1); + } + } + + *section = header; + + return STATUS_SUCCESS; +} + +static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index) +{ + return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset); +} + +static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data) +{ + struct comclassredirect_data *comclass; + struct guid_index *index = NULL; + + if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; + + if (!actctx->comserver_section) + { + struct guidsection_header *section; + + NTSTATUS status = build_comserver_section(actctx, §ion); + if (status) return status; + + if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL)) + RtlFreeHeap(RtlGetProcessHeap(), 0, section); + } + + index = find_guid_index(actctx->comserver_section, guid); + if (!index) return STATUS_SXS_KEY_NOT_FOUND; + + comclass = get_comclass_data(actctx, index); + + data->ulDataFormatVersion = 1; + data->lpData = comclass; + /* full length includes string length with nulls */ + data->ulLength = comclass->size + comclass->clrdata_len; + if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR); + data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset; + data->ulSectionGlobalDataLength = actctx->comserver_section->names_len; + data->lpSectionBase = actctx->comserver_section; + data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->comserver_section ); + data->hActCtx = NULL; + + if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) + data->ulAssemblyRosterIndex = index->rosterindex; + + return STATUS_SUCCESS; +} + +static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len) +{ + unsigned int i; + + for (i = 0; i < entities->num; i++) + { + struct entity *entity = &entities->base[i]; + if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION) + { + *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data); + if (entity->u.ifaceps.name) + *len += aligned_string_len((strlenW(entity->u.ifaceps.name)+1)*sizeof(WCHAR)); + *count += 1; + } + } +} + +static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities, + struct guid_index **index, ULONG *data_offset, ULONG rosterindex) +{ + unsigned int i; + + for (i = 0; i < entities->num; i++) + { + struct entity *entity = &entities->base[i]; + if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION) + { + struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset); + UNICODE_STRING str; + ULONG name_len; + + if (entity->u.ifaceps.name) + name_len = strlenW(entity->u.ifaceps.name)*sizeof(WCHAR); + else + name_len = 0; + + /* setup index */ + RtlInitUnicodeString(&str, entity->u.ifaceps.iid); + RtlGUIDFromString(&str, &(*index)->guid); + (*index)->data_offset = *data_offset; + (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0; + (*index)->rosterindex = rosterindex; + + /* setup data record */ + data->size = sizeof(*data); + data->mask = entity->u.ifaceps.mask; + + /* proxyStubClsid32 value is only stored for external PS, + if set it's used as iid, otherwise 'iid' attribute value is used */ + if (entity->u.ifaceps.ps32) + { + RtlInitUnicodeString(&str, entity->u.ifaceps.ps32); + RtlGUIDFromString(&str, &data->iid); + } + else + data->iid = (*index)->guid; + + data->nummethods = entity->u.ifaceps.nummethods; + + if (entity->u.ifaceps.tlib) + { + RtlInitUnicodeString(&str, entity->u.ifaceps.tlib); + RtlGUIDFromString(&str, &data->tlbid); + } + else + memset(&data->tlbid, 0, sizeof(data->tlbid)); + + if (entity->u.ifaceps.base) + { + RtlInitUnicodeString(&str, entity->u.ifaceps.base); + RtlGUIDFromString(&str, &data->base); + } + else + memset(&data->base, 0, sizeof(data->base)); + + data->name_len = name_len; + data->name_offset = data->name_len ? sizeof(*data) : 0; + + /* name string */ + if (data->name_len) + { + WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset); + memcpy(ptrW, entity->u.ifaceps.name, data->name_len); + ptrW[data->name_len/sizeof(WCHAR)] = 0; + } + + /* move to next record */ + (*index) += 1; + *data_offset += sizeof(*data); + if (data->name_len) + *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR)); + } + } +} + +static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section) +{ + unsigned int i, j, total_len = 0, count = 0; + struct guidsection_header *header; + struct guid_index *index; + ULONG data_offset; + + /* compute section length */ + for (i = 0; i < actctx->num_assemblies; i++) + { + struct assembly *assembly = &actctx->assemblies[i]; + + get_ifaceps_datalen(&assembly->entities, &count, &total_len); + for (j = 0; j < assembly->num_dlls; j++) + { + struct dll_redirect *dll = &assembly->dlls[j]; + get_ifaceps_datalen(&dll->entities, &count, &total_len); + } + } + + total_len += sizeof(*header); + + header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); + if (!header) return STATUS_NO_MEMORY; + + memset(header, 0, sizeof(*header)); + header->magic = GUIDSECTION_MAGIC; + header->size = sizeof(*header); + header->count = count; + header->index_offset = sizeof(*header); + index = (struct guid_index*)((BYTE*)header + header->index_offset); + data_offset = header->index_offset + count*sizeof(*index); + + for (i = 0; i < actctx->num_assemblies; i++) + { + struct assembly *assembly = &actctx->assemblies[i]; + + add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1); + for (j = 0; j < assembly->num_dlls; j++) + { + struct dll_redirect *dll = &assembly->dlls[j]; + add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1); + } + } + + *section = header; + + return STATUS_SUCCESS; +} + +static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index) +{ + return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset); +} + +static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data) +{ + struct ifacepsredirect_data *iface; + struct guid_index *index = NULL; + + if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; + + if (!actctx->ifaceps_section) + { + struct guidsection_header *section; + + NTSTATUS status = build_ifaceps_section(actctx, §ion); + if (status) return status; + + if (InterlockedCompareExchangePointer((void**)&actctx->ifaceps_section, section, NULL)) + RtlFreeHeap(RtlGetProcessHeap(), 0, section); + } + + index = find_guid_index(actctx->ifaceps_section, guid); + if (!index) return STATUS_SXS_KEY_NOT_FOUND; + + iface = get_ifaceps_data(actctx, index); + + data->ulDataFormatVersion = 1; + data->lpData = iface; + data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0); + data->lpSectionGlobalData = NULL; + data->ulSectionGlobalDataLength = 0; + data->lpSectionBase = actctx->ifaceps_section; + data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->ifaceps_section ); + data->hActCtx = NULL; + + if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) + data->ulAssemblyRosterIndex = index->rosterindex; + + return STATUS_SUCCESS; +} + +static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section) +{ + unsigned int i, j, total_len = 0, count = 0; + struct guidsection_header *header; + struct clrsurrogate_data *data; + struct guid_index *index; + ULONG data_offset; + + /* compute section length */ + for (i = 0; i < actctx->num_assemblies; i++) + { + struct assembly *assembly = &actctx->assemblies[i]; + for (j = 0; j < assembly->entities.num; j++) + { + struct entity *entity = &assembly->entities.base[j]; + if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES) + { + ULONG len; + + total_len += sizeof(*index) + sizeof(*data); + len = strlenW(entity->u.clrsurrogate.name) + 1; + if (entity->u.clrsurrogate.version) + len += strlenW(entity->u.clrsurrogate.version) + 1; + total_len += aligned_string_len(len*sizeof(WCHAR)); + + count++; + } + } + } + + total_len += sizeof(*header); + + header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); + if (!header) return STATUS_NO_MEMORY; + + memset(header, 0, sizeof(*header)); + header->magic = GUIDSECTION_MAGIC; + header->size = sizeof(*header); + header->count = count; + header->index_offset = sizeof(*header); + index = (struct guid_index*)((BYTE*)header + header->index_offset); + data_offset = header->index_offset + count*sizeof(*index); + + for (i = 0; i < actctx->num_assemblies; i++) + { + struct assembly *assembly = &actctx->assemblies[i]; + for (j = 0; j < assembly->entities.num; j++) + { + struct entity *entity = &assembly->entities.base[j]; + if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES) + { + ULONG version_len, name_len; + UNICODE_STRING str; + WCHAR *ptrW; + + if (entity->u.clrsurrogate.version) + version_len = strlenW(entity->u.clrsurrogate.version)*sizeof(WCHAR); + else + version_len = 0; + name_len = strlenW(entity->u.clrsurrogate.name)*sizeof(WCHAR); + + /* setup new index entry */ + RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid); + RtlGUIDFromString(&str, &index->guid); + + index->data_offset = data_offset; + index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0)); + index->rosterindex = i + 1; + + /* setup data */ + data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset); + data->size = sizeof(*data); + data->res = 0; + data->clsid = index->guid; + data->version_offset = version_len ? data->size : 0; + data->version_len = version_len; + data->name_offset = data->size + version_len; + if (version_len) + data->name_offset += sizeof(WCHAR); + data->name_len = name_len; + + /* surrogate name */ + ptrW = (WCHAR*)((BYTE*)data + data->name_offset); + memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len); + ptrW[data->name_len/sizeof(WCHAR)] = 0; + + /* runtime version */ + if (data->version_len) + { + ptrW = (WCHAR*)((BYTE*)data + data->version_offset); + memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len); + ptrW[data->version_len/sizeof(WCHAR)] = 0; + } + + data_offset += index->data_offset; + index++; + } + } + } + + *section = header; + + return STATUS_SUCCESS; +} + +static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index) +{ + return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset); +} + +static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data) +{ + struct clrsurrogate_data *surrogate; + struct guid_index *index = NULL; + + if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; + + if (!actctx->clrsurrogate_section) + { + struct guidsection_header *section; + + NTSTATUS status = build_clr_surrogate_section(actctx, §ion); + if (status) return status; + + if (InterlockedCompareExchangePointer((void**)&actctx->clrsurrogate_section, section, NULL)) + RtlFreeHeap(RtlGetProcessHeap(), 0, section); + } + + index = find_guid_index(actctx->clrsurrogate_section, guid); + if (!index) return STATUS_SXS_KEY_NOT_FOUND; + + surrogate = get_surrogate_data(actctx, index); + + data->ulDataFormatVersion = 1; + data->lpData = surrogate; + /* full length includes string length with nulls */ + data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR); + if (surrogate->version_len) + data->ulLength += surrogate->version_len + sizeof(WCHAR); + + data->lpSectionGlobalData = NULL; + data->ulSectionGlobalDataLength = 0; + data->lpSectionBase = actctx->clrsurrogate_section; + data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->clrsurrogate_section ); + data->hActCtx = NULL; + + if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) + data->ulAssemblyRosterIndex = index->rosterindex; + + return STATUS_SUCCESS; +} + +static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len) +{ + unsigned int i, j, single_len; + + single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID); + for (i = 0; i < entities->num; i++) + { + struct entity *entity = &entities->base[i]; + if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION) + { + if (entity->u.comclass.progid) + { + *total_len += single_len + aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR)); + *count += 1; + } + + for (j = 0; j < entity->u.comclass.progids.num; j++) + *total_len += aligned_string_len((strlenW(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR)); + + *total_len += single_len*entity->u.comclass.progids.num; + *count += entity->u.comclass.progids.num; + } + } +} + +static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias, + struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex) +{ + struct progidredirect_data *data; + UNICODE_STRING str; + GUID *guid_ptr; + WCHAR *ptrW; + + /* setup new index entry */ + + /* hash progid name */ + RtlInitUnicodeString(&str, progid); + RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash); + + (*index)->name_offset = *data_offset; + (*index)->name_len = str.Length; + (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength); + (*index)->data_len = sizeof(*data); + (*index)->rosterindex = rosterindex; + + *data_offset += aligned_string_len(str.MaximumLength); + + /* setup data structure */ + data = (struct progidredirect_data*)((BYTE*)section + *data_offset); + data->size = sizeof(*data); + data->reserved = 0; + data->clsid_offset = *global_offset; + + /* write progid string */ + ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset); + memcpy(ptrW, progid, (*index)->name_len); + ptrW[(*index)->name_len/sizeof(WCHAR)] = 0; + + /* write guid to global area */ + guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset); + *guid_ptr = *alias; + + /* to next entry */ + *global_offset += sizeof(GUID); + *data_offset += data->size; + (*index) += 1; +} + +static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities, + struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex) +{ + unsigned int i, j; + + for (i = 0; i < entities->num; i++) + { + struct entity *entity = &entities->base[i]; + if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION) + { + const struct progids *progids = &entity->u.comclass.progids; + struct comclassredirect_data *comclass; + struct guid_index *guid_index; + UNICODE_STRING str; + GUID clsid; + + RtlInitUnicodeString(&str, entity->u.comclass.clsid); + RtlGUIDFromString(&str, &clsid); + + guid_index = find_guid_index(actctx->comserver_section, &clsid); + comclass = get_comclass_data(actctx, guid_index); + + if (entity->u.comclass.progid) + write_progid_record(section, entity->u.comclass.progid, &comclass->alias, + index, data_offset, global_offset, rosterindex); + + for (j = 0; j < progids->num; j++) + write_progid_record(section, progids->progids[j], &comclass->alias, + index, data_offset, global_offset, rosterindex); + } + } +} + +static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section) +{ + unsigned int i, j, total_len = 0, count = 0; + struct strsection_header *header; + ULONG data_offset, global_offset; + struct string_index *index; + + /* compute section length */ + for (i = 0; i < actctx->num_assemblies; i++) + { + struct assembly *assembly = &actctx->assemblies[i]; + + get_progid_datalen(&assembly->entities, &count, &total_len); + for (j = 0; j < assembly->num_dlls; j++) + { + struct dll_redirect *dll = &assembly->dlls[j]; + get_progid_datalen(&dll->entities, &count, &total_len); + } + } + + total_len += sizeof(*header); + + header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); + if (!header) return STATUS_NO_MEMORY; + + memset(header, 0, sizeof(*header)); + header->magic = STRSECTION_MAGIC; + header->size = sizeof(*header); + header->count = count; + header->global_offset = header->size; + header->global_len = count*sizeof(GUID); + header->index_offset = header->size + header->global_len; + + index = (struct string_index*)((BYTE*)header + header->index_offset); + data_offset = header->index_offset + count*sizeof(*index); + global_offset = header->global_offset; + + for (i = 0; i < actctx->num_assemblies; i++) + { + struct assembly *assembly = &actctx->assemblies[i]; + + add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1); + for (j = 0; j < assembly->num_dlls; j++) + { + struct dll_redirect *dll = &assembly->dlls[j]; + add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1); + } + } + + *section = header; + + return STATUS_SUCCESS; +} + +static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index) +{ + return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset); +} + +static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name, + PACTCTX_SECTION_KEYED_DATA data) +{ + struct progidredirect_data *progid; + struct string_index *index; + + if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; + + if (!actctx->comserver_section) + { + struct guidsection_header *section; + + NTSTATUS status = build_comserver_section(actctx, §ion); + if (status) return status; + + if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL)) + RtlFreeHeap(RtlGetProcessHeap(), 0, section); + } + + if (!actctx->progid_section) + { + struct strsection_header *section; + + NTSTATUS status = build_progid_section(actctx, §ion); + if (status) return status; + + if (InterlockedCompareExchangePointer((void**)&actctx->progid_section, section, NULL)) + RtlFreeHeap(RtlGetProcessHeap(), 0, section); + } + + index = find_string_index(actctx->progid_section, name); + if (!index) return STATUS_SXS_KEY_NOT_FOUND; + + progid = get_progid_data(actctx, index); + + data->ulDataFormatVersion = 1; + data->lpData = progid; + data->ulLength = progid->size; + data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset; + data->ulSectionGlobalDataLength = actctx->progid_section->global_len; + data->lpSectionBase = actctx->progid_section; + data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->progid_section ); + data->hActCtx = NULL; + + if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) + data->ulAssemblyRosterIndex = index->rosterindex; + + return STATUS_SUCCESS; } static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind, @@ -2339,12 +4510,10 @@ static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind, case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION: status = find_window_class(actctx, section_name, data); break; - case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION: - case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION: - case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION: case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION: + status = find_progid_redirection(actctx, section_name, data); + break; case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE: - case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES: DPRINT1("Unsupported yet section_kind %x\n", section_kind); return STATUS_SXS_SECTION_NOT_FOUND; default: @@ -2369,6 +4538,18 @@ static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind, switch (section_kind) { + case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION: + status = find_tlib_redirection(actctx, guid, data); + break; + case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION: + status = find_comserver_redirection(actctx, guid, data); + break; + case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION: + status = find_cominterface_redirection(actctx, guid, data); + break; + case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES: + status = find_clr_surrogate(actctx, guid, data); + break; default: DPRINT("Unknown section_kind %x\n", section_kind); return STATUS_SXS_SECTION_NOT_FOUND; @@ -2946,10 +5127,10 @@ RtlQueryInformationActiveActivationContext(ULONG ulInfoClass, NTSTATUS NTAPI RtlpFindActivationContextSection_CheckParameters( ULONG flags, const GUID *guid, ULONG section_kind, - UNICODE_STRING *section_name, PACTCTX_SECTION_KEYED_DATA data ) + const UNICODE_STRING *section_name, PACTCTX_SECTION_KEYED_DATA data ) { /* Check general parameter combinations */ - if (!section_name || + if (!section_name || !section_name->Buffer || (flags & ~FIND_ACTCTX_VALID_MASK) || ((flags & FIND_ACTCTX_VALID_MASK) && !data) || (data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex))) @@ -2972,7 +5153,7 @@ RtlpFindActivationContextSection_CheckParameters( ULONG flags, const GUID *guid, NTSTATUS NTAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind, - UNICODE_STRING *section_name, PVOID ptr ) + const UNICODE_STRING *section_name, PVOID ptr ) { PACTCTX_SECTION_KEYED_DATA data = ptr; NTSTATUS status; diff --git a/lib/rtl/nls.c b/lib/rtl/nls.c index 49a8fa13f43..ee892a09324 100644 --- a/lib/rtl/nls.c +++ b/lib/rtl/nls.c @@ -31,13 +31,12 @@ BOOLEAN NlsMbOemCodePageTag = FALSE; /* exported */ PWCHAR NlsOemToUnicodeTable = NULL; PCHAR NlsUnicodeToOemTable =NULL; PWCHAR NlsDbcsUnicodeToOemTable = NULL; -PUSHORT _NlsOemLeadByteInfo = NULL; /* exported */ +PUSHORT NlsOemLeadByteInfo = NULL; /* exported */ USHORT NlsOemDefaultChar = '\0'; USHORT NlsUnicodeDefaultChar = 0; -#define NlsOemLeadByteInfo _NlsOemLeadByteInfo #define INIT_FUNCTION /* FUNCTIONS *****************************************************************/ diff --git a/lib/rtl/rtlp.h b/lib/rtl/rtlp.h index 634357bf7f9..b9429af356f 100644 --- a/lib/rtl/rtlp.h +++ b/lib/rtl/rtlp.h @@ -125,6 +125,11 @@ RtlpHandleDpcStackException(IN PEXCEPTION_REGISTRATION_RECORD RegistrationFrame, #define RtlpAllocateStringMemory RtlpAllocateMemory #define RtlpFreeStringMemory RtlpFreeMemory +ULONG +NTAPI +RtlGetTickCount(VOID); +#define NtGetTickCount RtlGetTickCount + BOOLEAN NTAPI RtlpSetInDbgPrint( diff --git a/lib/sdk/cpprt/amd64/cpprt.s b/lib/sdk/cpprt/amd64/cpprt.s index ae741c57869..526caa66c6c 100644 --- a/lib/sdk/cpprt/amd64/cpprt.s +++ b/lib/sdk/cpprt/amd64/cpprt.s @@ -13,4 +13,7 @@ DEFINE_ALIAS ??_L@YAXPEAX_KHP6AX0@Z2@Z, ?MSVCRTEX_eh_vector_constructor_iterator ; void __cdecl `eh vector destructor iterator'(void *,unsigned __int64,int,void (__cdecl*)(void *)) DEFINE_ALIAS ??_M@YAXPEAX_KHP6AX0@Z@Z, ?MSVCRTEX_eh_vector_destructor_iterator@@YAXPEAX_KHP6AX0@Z@Z +; These are the same +DEFINE_ALIAS __CxxFrameHandler3, __CxxFrameHandler + END diff --git a/lib/sdk/crt/include/internal/safecrt.h b/lib/sdk/crt/include/internal/safecrt.h index ad948fe0c92..ec5c93038a4 100644 --- a/lib/sdk/crt/include/internal/safecrt.h +++ b/lib/sdk/crt/include/internal/safecrt.h @@ -11,10 +11,12 @@ void _invalid_parameter( uintptr_t pReserved); #ifndef _LIBCNT_ -#define MSVCRT_INVALID_PMT(x) _invalid_parameter(NULL, NULL, NULL, 0, 0) -#define MSVCRT_CHECK_PMT(x) ((x) || (MSVCRT_INVALID_PMT(0),0)) +#define MSVCRT_INVALID_PMT(x,err) (*_errno() = (err), _invalid_parameter(NULL, NULL, NULL, 0, 0)) +#define MSVCRT_CHECK_PMT_ERR(x,err) ((x) || (MSVCRT_INVALID_PMT( 0, (err) ), 0)) +#define MSVCRT_CHECK_PMT(x) MSVCRT_CHECK_PMT_ERR((x), EINVAL) #else /* disable secure crt parameter checks */ -#define MSVCRT_CHECK_PMT -#define MSVCRT_INVALID_PMT +#define MSVCRT_INVALID_PMT(x,err) +#define MSVCRT_CHECK_PMT_ERR(x,err) +#define MSVCRT_CHECK_PMT(x) (x) #endif diff --git a/lib/sdk/crt/printf/_sxprintf.c b/lib/sdk/crt/printf/_sxprintf.c index 57d7f4ff336..46667195314 100644 --- a/lib/sdk/crt/printf/_sxprintf.c +++ b/lib/sdk/crt/printf/_sxprintf.c @@ -104,7 +104,7 @@ _sxprintf( if (count != _TRUNCATE) { /* We can't, invoke invalid parameter handler */ - MSVCRT_INVALID_PMT("Buffer is too small"); + MSVCRT_INVALID_PMT("Buffer is too small", ERANGE); /* If we came back, set the buffer to an empty string */ *buffer = 0; diff --git a/lib/sdk/crt/stdio/file.c b/lib/sdk/crt/stdio/file.c index 52e7f09f244..0c7533ef5c2 100644 --- a/lib/sdk/crt/stdio/file.c +++ b/lib/sdk/crt/stdio/file.c @@ -52,6 +52,12 @@ int *__p__fmode(void); int *__p___mb_cur_max(void); +extern int _commode; + +#ifndef _IOCOMMIT +#define _IOCOMMIT 0x4000 +#endif + #ifdef feof #undef feof #endif @@ -83,21 +89,33 @@ int *__p___mb_cur_max(void); /* values for wxflag in file descriptor */ #define WX_OPEN 0x01 #define WX_ATEOF 0x02 +#define WX_READNL 0x04 /* read started with \n */ #define WX_READEOF 0x04 /* like ATEOF, but for underlying file rather than buffer */ +#define WX_PIPE 0x08 #define WX_READCR 0x08 /* underlying file is at \r */ #define WX_DONTINHERIT 0x10 #define WX_APPEND 0x20 +#define WX_NOSEEK 0x40 #define WX_TEXT 0x80 +/* values for exflag - it's used differently in msvcr90.dll*/ +#define EF_UTF8 0x01 +#define EF_UTF16 0x02 +#define EF_UNK_UNICODE 0x08 + +static char utf8_bom[3] = { 0xef, 0xbb, 0xbf }; +static char utf16_bom[2] = { 0xff, 0xfe }; + /* FIXME: this should be allocated dynamically */ #define MAX_FILES 2048 #define FD_BLOCK_SIZE 64 +/* ioinfo structure size is different in msvcrXX.dll's */ typedef struct { HANDLE handle; unsigned char wxflag; - char unk1; - BOOL crit_init; + char lookahead[3]; + int exflag; CRITICAL_SECTION crit; } ioinfo; @@ -245,7 +263,7 @@ static void free_fd(int fd) /* INTERNAL: Allocate an fd slot from a Win32 HANDLE, starting from fd */ /* caller must hold the files lock */ -static int alloc_fd_from(HANDLE hand, int flag, int fd) +static int set_fd(HANDLE hand, int flag, int fd) { ioinfo *fdinfo; @@ -274,7 +292,11 @@ static int alloc_fd_from(HANDLE hand, int flag, int fd) } fdinfo->handle = hand; - fdinfo->wxflag = WX_OPEN | (flag & (WX_DONTINHERIT | WX_APPEND | WX_TEXT)); + fdinfo->wxflag = WX_OPEN | (flag & (WX_DONTINHERIT | WX_APPEND | WX_TEXT | WX_PIPE | WX_NOSEEK)); + fdinfo->lookahead[0] = '\n'; + fdinfo->lookahead[1] = '\n'; + fdinfo->lookahead[2] = '\n'; + fdinfo->exflag = 0; /* locate next free slot */ if (fd == fdstart && fd == fdend) @@ -305,7 +327,7 @@ static int alloc_fd_from(HANDLE hand, int flag, int fd) LOCK_FILES(); TRACE(":handle (%p) allocating fd (%d)\n",hand,fdstart); - ret = alloc_fd_from(hand, flag, fdstart); + ret = set_fd(hand, flag, fdstart); UNLOCK_FILES(); return ret; } @@ -425,7 +447,7 @@ void msvcrt_init_io(void) for (i = 0; i < count; i++) { if ((*wxflag_ptr & WX_OPEN) && *handle_ptr != INVALID_HANDLE_VALUE) - alloc_fd_from(*handle_ptr, *wxflag_ptr, i); + set_fd(*handle_ptr, *wxflag_ptr, i); wxflag_ptr++; handle_ptr++; } @@ -435,7 +457,7 @@ void msvcrt_init_io(void) } if(!__pioinfo[0]) - alloc_fd_from(INVALID_HANDLE_VALUE, 0, 3); + set_fd(INVALID_HANDLE_VALUE, 0, 3); fdinfo = get_ioinfo(0); if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) @@ -877,7 +899,7 @@ int CDECL _dup2(int od, int nd) if (is_valid_fd(nd)) _close(nd); - ret = alloc_fd_from(handle, wxflag, nd); + ret = set_fd(handle, wxflag, nd); if (ret == -1) { CloseHandle(handle); @@ -1238,6 +1260,10 @@ static int get_flags(const wchar_t* mode, int *open_flags, int* stream_flags) { int plus = strchrW(mode, '+') != NULL; + TRACE("%s\n", debugstr_w(mode)); + + while(*mode == ' ') mode++; + switch(*mode++) { case 'R': case 'r': @@ -1253,12 +1279,13 @@ static int get_flags(const wchar_t* mode, int *open_flags, int* stream_flags) *stream_flags = plus ? _IORW : _IOWRT; break; default: - _invalid_parameter(NULL, NULL, NULL, 0, 0); - *_errno() = EINVAL; + MSVCRT_INVALID_PMT(0, EINVAL); return -1; } - while (*mode) + *stream_flags |= _commode; + + while (*mode && *mode!=',') switch (*mode++) { case 'B': case 'b': @@ -1269,12 +1296,79 @@ static int get_flags(const wchar_t* mode, int *open_flags, int* stream_flags) *open_flags |= _O_TEXT; *open_flags &= ~_O_BINARY; break; + case 'D': + *open_flags |= _O_TEMPORARY; + break; + case 'T': + *open_flags |= _O_SHORT_LIVED; + break; + case 'c': + *stream_flags |= _IOCOMMIT; + break; + case 'n': + *stream_flags &= ~_IOCOMMIT; + break; + case 'N': + *open_flags |= _O_NOINHERIT; + break; case '+': case ' ': + case 'a': + case 'w': + break; + case 'S': + case 'R': + FIXME("ignoring cache optimization flag: %c\n", mode[-1]); break; default: - FIXME(":unknown flag %c not supported\n",mode[-1]); + ERR("incorrect mode flag: %c\n", mode[-1]); + break; } + + if(*mode == ',') + { + static const WCHAR ccs[] = {'c','c','s'}; + static const WCHAR utf8[] = {'u','t','f','-','8'}; + static const WCHAR utf16le[] = {'u','t','f','-','1','6','l','e'}; + static const WCHAR unicode[] = {'u','n','i','c','o','d','e'}; + + mode++; + while(*mode == ' ') mode++; + if(!MSVCRT_CHECK_PMT(!strncmpW(ccs, mode, sizeof(ccs)/sizeof(ccs[0])))) + return -1; + mode += sizeof(ccs)/sizeof(ccs[0]); + while(*mode == ' ') mode++; + if(!MSVCRT_CHECK_PMT(*mode == '=')) + return -1; + mode++; + while(*mode == ' ') mode++; + + if(!strncmpiW(utf8, mode, sizeof(utf8)/sizeof(utf8[0]))) + { + *open_flags |= _O_U8TEXT; + mode += sizeof(utf8)/sizeof(utf8[0]); + } + else if(!strncmpiW(utf16le, mode, sizeof(utf16le)/sizeof(utf16le[0]))) + { + *open_flags |= _O_U16TEXT; + mode += sizeof(utf16le)/sizeof(utf16le[0]); + } + else if(!strncmpiW(unicode, mode, sizeof(unicode)/sizeof(unicode[0]))) + { + *open_flags |= _O_WTEXT; + mode += sizeof(unicode)/sizeof(unicode[0]); + } + else + { + MSVCRT_INVALID_PMT(0, EINVAL); + return -1; + } + + while(*mode == ' ') mode++; + } + + if(!MSVCRT_CHECK_PMT(*mode == 0)) + return -1; return 0; } @@ -1400,9 +1494,12 @@ char * CDECL _mktemp(char *pattern) int id; char letter = 'a'; + if(!pattern) + return NULL; + while(*pattern) numX = (*pattern++ == 'X')? numX + 1 : 0; - if (numX < 5) + if (numX < 6) return NULL; pattern--; id = GetCurrentProcessId(); @@ -1417,8 +1514,7 @@ char * CDECL _mktemp(char *pattern) do { *pattern = letter++; - if (GetFileAttributesA(retVal) == INVALID_FILE_ATTRIBUTES && - GetLastError() == ERROR_FILE_NOT_FOUND) + if (GetFileAttributesA(retVal) == INVALID_FILE_ATTRIBUTES) return retVal; } while(letter <= 'z'); return NULL; @@ -1537,6 +1633,207 @@ int CDECL _pipe(int *pfds, unsigned int psize, int textmode) return ret; } +static int check_bom(HANDLE h, int oflags, BOOL seek) +{ + char bom[sizeof(utf8_bom)]; + DWORD r; + + oflags &= ~(_O_WTEXT|_O_U16TEXT|_O_U8TEXT); + + if (!ReadFile(h, bom, sizeof(utf8_bom), &r, NULL)) + return oflags; + + if (r==sizeof(utf8_bom) && !memcmp(bom, utf8_bom, sizeof(utf8_bom))) { + oflags |= _O_U8TEXT; + }else if (r>=sizeof(utf16_bom) && !memcmp(bom, utf16_bom, sizeof(utf16_bom))) { + if (seek && r>2) + SetFilePointer(h, 2, NULL, FILE_BEGIN); + oflags |= _O_U16TEXT; + }else if (seek) { + SetFilePointer(h, 0, NULL, FILE_BEGIN); + } + + return oflags; +} + +/********************************************************************* + * _wsopen_s (MSVCRT.@) + */ +int CDECL _wsopen_s( int *fd, const wchar_t* path, int oflags, int shflags, int pmode ) +{ + DWORD access = 0, creation = 0, attrib; + SECURITY_ATTRIBUTES sa; + DWORD sharing; + int wxflag; + HANDLE hand; + + TRACE("fd*: %p :file (%s) oflags: 0x%04x shflags: 0x%04x pmode: 0x%04x\n", + fd, debugstr_w(path), oflags, shflags, pmode); + + if (!MSVCRT_CHECK_PMT( fd != NULL )) return EINVAL; + + *fd = -1; + wxflag = split_oflags(oflags); + switch (oflags & (_O_RDONLY | _O_WRONLY | _O_RDWR)) + { + case _O_RDONLY: access |= GENERIC_READ; break; + case _O_WRONLY: access |= GENERIC_WRITE; break; + case _O_RDWR: access |= GENERIC_WRITE | GENERIC_READ; break; + } + + if (oflags & _O_CREAT) + { + if(pmode & ~(_S_IREAD | _S_IWRITE)) + FIXME(": pmode 0x%04x ignored\n", pmode); + else + WARN(": pmode 0x%04x ignored\n", pmode); + + if (oflags & _O_EXCL) + creation = CREATE_NEW; + else if (oflags & _O_TRUNC) + creation = CREATE_ALWAYS; + else + creation = OPEN_ALWAYS; + } + else /* no _O_CREAT */ + { + if (oflags & _O_TRUNC) + creation = TRUNCATE_EXISTING; + else + creation = OPEN_EXISTING; + } + + switch( shflags ) + { + case _SH_DENYRW: + sharing = 0L; + break; + case _SH_DENYWR: + sharing = FILE_SHARE_READ; + break; + case _SH_DENYRD: + sharing = FILE_SHARE_WRITE; + break; + case _SH_DENYNO: + sharing = FILE_SHARE_READ | FILE_SHARE_WRITE; + break; + default: + ERR( "Unhandled shflags 0x%x\n", shflags ); + return EINVAL; + } + attrib = FILE_ATTRIBUTE_NORMAL; + + if (oflags & _O_TEMPORARY) + { + attrib |= FILE_FLAG_DELETE_ON_CLOSE; + access |= DELETE; + sharing |= FILE_SHARE_DELETE; + } + + sa.nLength = sizeof( SECURITY_ATTRIBUTES ); + sa.lpSecurityDescriptor = NULL; + sa.bInheritHandle = !(oflags & _O_NOINHERIT); + + if ((oflags&(_O_WTEXT|_O_U16TEXT|_O_U8TEXT)) + && (creation==OPEN_ALWAYS || creation==OPEN_EXISTING) + && !(access&GENERIC_READ)) + { + hand = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, + &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + if (hand != INVALID_HANDLE_VALUE) + { + oflags = check_bom(hand, oflags, FALSE); + CloseHandle(hand); + } + else + oflags &= ~(_O_WTEXT|_O_U16TEXT|_O_U8TEXT); + } + + hand = CreateFileW(path, access, sharing, &sa, creation, attrib, 0); + if (hand == INVALID_HANDLE_VALUE) { + WARN(":failed-last error (%d)\n",GetLastError()); + _dosmaperr(GetLastError()); + return *_errno(); + } + + if (oflags & (_O_WTEXT|_O_U16TEXT|_O_U8TEXT)) + { + if ((access & GENERIC_WRITE) && (creation==CREATE_NEW + || creation==CREATE_ALWAYS || creation==TRUNCATE_EXISTING + || (creation==OPEN_ALWAYS && GetLastError()==ERROR_ALREADY_EXISTS))) + { + if (oflags & _O_U8TEXT) + { + DWORD written = 0, tmp; + + while(written!=sizeof(utf8_bom) && WriteFile(hand, (char*)utf8_bom+written, + sizeof(utf8_bom)-written, &tmp, NULL)) + written += tmp; + if (written != sizeof(utf8_bom)) { + WARN("error writing BOM\n"); + CloseHandle(hand); + _dosmaperr(GetLastError()); + return *_errno(); + } + } + else + { + DWORD written = 0, tmp; + + while(written!=sizeof(utf16_bom) && WriteFile(hand, (char*)utf16_bom+written, + sizeof(utf16_bom)-written, &tmp, NULL)) + written += tmp; + if (written != sizeof(utf16_bom)) + { + WARN("error writing BOM\n"); + CloseHandle(hand); + _dosmaperr(GetLastError()); + return *_errno(); + } + } + } + else if (access & GENERIC_READ) + oflags = check_bom(hand, oflags, TRUE); + } + + *fd = alloc_fd(hand, wxflag); + if (*fd == -1) + return *_errno(); + + if (oflags & _O_WTEXT) + get_ioinfo(*fd)->exflag |= EF_UTF16|EF_UNK_UNICODE; + else if (oflags & _O_U16TEXT) + get_ioinfo(*fd)->exflag |= EF_UTF16; + else if (oflags & _O_U8TEXT) + get_ioinfo(*fd)->exflag |= EF_UTF8; + + TRACE(":fd (%d) handle (%p)\n", *fd, hand); + return 0; +} + +/********************************************************************* + * _wsopen (MSVCRT.@) + */ +int CDECL _wsopen( const wchar_t *path, int oflags, int shflags, ... ) +{ + int pmode; + int fd; + + if (oflags & _O_CREAT) + { + va_list ap; + + va_start(ap, shflags); + pmode = va_arg(ap, int); + va_end(ap); + } + else + pmode = 0; + + _wsopen_s(&fd, path, oflags, shflags, pmode); + return fd; +} + /********************************************************************* * _sopen_s (MSVCRT.@) */ @@ -1553,8 +1850,7 @@ int CDECL _sopen_s( int *fd, const char *path, int oflags, int shflags, int pmod if (!fd) { - MSVCRT_INVALID_PMT("null out fd pointer"); - *_errno() = EINVAL; + MSVCRT_INVALID_PMT("null out fd pointer", EINVAL); return EINVAL; } @@ -1656,126 +1952,6 @@ int CDECL _sopen( const char *path, int oflags, int shflags, ... ) return fd; } -/********************************************************************* - * _wsopen_s (MSVCRT.@) - */ -int CDECL _wsopen_s( int *fd, const wchar_t* path, int oflags, int shflags, int pmode ) -{ - DWORD access = 0, creation = 0, attrib; - SECURITY_ATTRIBUTES sa; - DWORD sharing; - int wxflag; - HANDLE hand; - - TRACE("fd*: %p :file (%s) oflags: 0x%04x shflags: 0x%04x pmode: 0x%04x\n", - fd, debugstr_w(path), oflags, shflags, pmode); - - if (!fd) - { - MSVCRT_INVALID_PMT("null out fd pointer"); - *_errno() = EINVAL; - return EINVAL; - } - - *fd = -1; - wxflag = split_oflags(oflags); - switch (oflags & (_O_RDONLY | _O_WRONLY | _O_RDWR)) - { - case _O_RDONLY: access |= GENERIC_READ; break; - case _O_WRONLY: access |= GENERIC_WRITE; break; - case _O_RDWR: access |= GENERIC_WRITE | GENERIC_READ; break; - } - - if (oflags & _O_CREAT) - { - if(pmode & ~(_S_IREAD | _S_IWRITE)) - FIXME(": pmode 0x%04x ignored\n", pmode); - else - WARN(": pmode 0x%04x ignored\n", pmode); - - if (oflags & _O_EXCL) - creation = CREATE_NEW; - else if (oflags & _O_TRUNC) - creation = CREATE_ALWAYS; - else - creation = OPEN_ALWAYS; - } - else /* no _O_CREAT */ - { - if (oflags & _O_TRUNC) - creation = TRUNCATE_EXISTING; - else - creation = OPEN_EXISTING; - } - - switch( shflags ) - { - case _SH_DENYRW: - sharing = 0L; - break; - case _SH_DENYWR: - sharing = FILE_SHARE_READ; - break; - case _SH_DENYRD: - sharing = FILE_SHARE_WRITE; - break; - case _SH_DENYNO: - sharing = FILE_SHARE_READ | FILE_SHARE_WRITE; - break; - default: - ERR( "Unhandled shflags 0x%x\n", shflags ); - return EINVAL; - } - attrib = FILE_ATTRIBUTE_NORMAL; - - if (oflags & _O_TEMPORARY) - { - attrib |= FILE_FLAG_DELETE_ON_CLOSE; - access |= DELETE; - sharing |= FILE_SHARE_DELETE; - } - - sa.nLength = sizeof( SECURITY_ATTRIBUTES ); - sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = (oflags & _O_NOINHERIT) ? FALSE : TRUE; - - hand = CreateFileW(path, access, sharing, &sa, creation, attrib, 0); - - if (hand == INVALID_HANDLE_VALUE) { - WARN(":failed-last error (%d)\n",GetLastError()); - _dosmaperr(GetLastError()); - return *_errno(); - } - - *fd = alloc_fd(hand, wxflag); - - TRACE(":fd (%d) handle (%p)\n", *fd, hand); - return 0; -} - -/********************************************************************* - * _wsopen (MSVCRT.@) - */ -int CDECL _wsopen( const wchar_t *path, int oflags, int shflags, ... ) -{ - int pmode; - int fd; - - if (oflags & _O_CREAT) - { - va_list ap; - - va_start(ap, shflags); - pmode = va_arg(ap, int); - va_end(ap); - } - else - pmode = 0; - - _wsopen_s(&fd, path, oflags, shflags, pmode); - return fd; -} - /********************************************************************* * _open (MSVCRT.@) */ @@ -1837,6 +2013,7 @@ int CDECL _wcreat(const wchar_t *path, int flags) */ int CDECL _open_osfhandle(intptr_t handle, int oflags) { + DWORD flags; int fd; /* _O_RDONLY (0) always matches, so set the read flag @@ -1848,8 +2025,23 @@ int CDECL _open_osfhandle(intptr_t handle, int oflags) if (!(oflags & (_O_BINARY | _O_TEXT))) oflags |= _O_BINARY; - fd = alloc_fd((HANDLE)handle, split_oflags(oflags)); - TRACE(":handle (%ld) fd (%d) flags 0x%08x\n", handle, fd, oflags); + flags = GetFileType((HANDLE)handle); + if (flags==FILE_TYPE_UNKNOWN && GetLastError()!=NO_ERROR) + { + _dosmaperr(GetLastError()); + return -1; + } + + if (flags == FILE_TYPE_CHAR) + flags = WX_NOSEEK; + else if (flags == FILE_TYPE_PIPE) + flags = WX_PIPE; + else + flags = 0; + flags |= split_oflags(oflags); + + fd = alloc_fd((HANDLE)handle, flags); + TRACE(":handle (%ld) fd (%d) flags 0x%08x\n", handle, fd, flags); return fd; } @@ -1989,14 +2181,32 @@ int CDECL _read(int fd, void *buf, unsigned int count) */ int CDECL _setmode(int fd,int mode) { - int ret = get_ioinfo(fd)->wxflag & WX_TEXT ? _O_TEXT : _O_BINARY; - if (mode & (~(_O_TEXT|_O_BINARY))) - FIXME("fd (%d) mode (0x%08x) unknown\n",fd,mode); - if ((mode & _O_TEXT) == _O_TEXT) + int ret = get_ioinfo(fd)->wxflag & WX_TEXT ? _O_TEXT : _O_BINARY; + if(ret==_O_TEXT && (get_ioinfo(fd)->exflag & (EF_UTF8|EF_UTF16))) + ret = _O_WTEXT; + + if(mode!=_O_TEXT && mode!=_O_BINARY && mode!=_O_WTEXT + && mode!=_O_U16TEXT && mode!=_O_U8TEXT) { + *_errno() = EINVAL; + return -1; + } + + if(mode == _O_BINARY) { + get_ioinfo(fd)->wxflag &= ~WX_TEXT; + get_ioinfo(fd)->exflag &= ~(EF_UTF8|EF_UTF16); + return ret; + } + get_ioinfo(fd)->wxflag |= WX_TEXT; - else - get_ioinfo(fd)->wxflag &= ~WX_TEXT; - return ret; + if(mode == _O_TEXT) + get_ioinfo(fd)->exflag &= ~(EF_UTF8|EF_UTF16); + else if(mode == _O_U8TEXT) + get_ioinfo(fd)->exflag = (get_ioinfo(fd)->exflag & ~EF_UTF16) | EF_UTF8; + else + get_ioinfo(fd)->exflag = (get_ioinfo(fd)->exflag & ~EF_UTF8) | EF_UTF16; + + return ret; + } /********************************************************************* @@ -2070,89 +2280,170 @@ int CDECL _umask(int umask) */ int CDECL _write(int fd, const void* buf, unsigned int count) { - DWORD num_written; - HANDLE hand = fdtoh(fd); + DWORD num_written; + ioinfo *info = get_ioinfo(fd); + HANDLE hand = info->handle; - /* Don't trace small writes, it gets *very* annoying */ + /* Don't trace small writes, it gets *very* annoying */ #if 0 - if (count > 32) - TRACE(":fd (%d) handle (%d) buf (%p) len (%d)\n",fd,hand,buf,count); + if (count > 32) + TRACE(":fd (%d) handle (%d) buf (%p) len (%d)\n",fd,hand,buf,count); #endif - if (hand == INVALID_HANDLE_VALUE) + if (hand == INVALID_HANDLE_VALUE) { - *_errno() = EBADF; - return -1; + *_errno() = EBADF; + return -1; } - /* If appending, go to EOF */ - if (get_ioinfo(fd)->wxflag & WX_APPEND) - _lseek(fd, 0, FILE_END); - - if (!(get_ioinfo(fd)->wxflag & WX_TEXT)) + if (((info->exflag&EF_UTF8) || (info->exflag&EF_UTF16)) && count&1) { - if (WriteFile(hand, buf, count, &num_written, NULL) - && (num_written == count)) - return num_written; - TRACE("WriteFile (fd %d, hand %p) failed-last error (%d)\n", fd, - hand, GetLastError()); - *_errno() = ENOSPC; + *_errno() = EINVAL; + return -1; } - else - { - unsigned int i, j, nr_lf; - char *p = NULL; - const char *q; - const char *s = buf, *buf_start = buf; - /* find number of \n ( without preceding \r ) */ - for ( nr_lf=0,i = 0; i 1) && (s[i-1] == '\r')) nr_lf--; */ - } - } - if (nr_lf) - { - if ((q = p = malloc(count + nr_lf))) - { - for (s = buf, i = 0, j = 0; i < count; i++) - { - if (s[i]== '\n') - { - p[j++] = '\r'; - /*if ((i >1) && (s[i-1] == '\r'))j--;*/ - } - p[j++] = s[i]; - } - } - else - { - FIXME("Malloc failed\n"); - nr_lf =0; - q = buf; - } - } - else - q = buf; - if ((WriteFile(hand, q, count+nr_lf, &num_written, NULL) == 0 ) || (num_written != count+nr_lf)) - { - TRACE("WriteFile (fd %d, hand %p) failed-last error (%d), num_written %d\n", - fd, hand, GetLastError(), num_written); - *_errno() = ENOSPC; - if(nr_lf) - free(p); - return s - buf_start; - } - else - { - if(nr_lf) - free(p); - return count; - } - } - return -1; + /* If appending, go to EOF */ + if (info->wxflag & WX_APPEND) + _lseek(fd, 0, FILE_END); + + if (!(info->wxflag & WX_TEXT)) + { + if (WriteFile(hand, buf, count, &num_written, NULL) + && (num_written == count)) + return num_written; + TRACE("WriteFile (fd %d, hand %p) failed-last error (%d)\n", fd, + hand, GetLastError()); + *_errno() = ENOSPC; + } + else + { + unsigned int i, j, nr_lf, size; + char *p = NULL; + const char *q; + const char *s = buf, *buf_start = buf; + + if (!(info->exflag & (EF_UTF8|EF_UTF16))) + { + /* find number of \n */ + for (nr_lf=0, i=0; iexflag & EF_UTF16) + { + for (nr_lf=0, i=0; i_flag & _IOEOF; - _unlock_file(file); - - return ret; + return file->_flag & _IOEOF; } /********************************************************************* @@ -2227,13 +2512,7 @@ int CDECL feof(FILE* file) */ int CDECL ferror(FILE* file) { - int ret; - - _lock_file(file); - ret = file->_flag & _IOERR; - _unlock_file(file); - - return ret; + return file->_flag & _IOERR; } /********************************************************************* @@ -2244,6 +2523,11 @@ int CDECL _filbuf(FILE* file) unsigned char c; _lock_file(file); + if(file->_flag & _IOSTRG) { + _unlock_file(file); + return EOF; + } + /* Allocate buffer if needed */ if(file->_bufsiz == 0 && !(file->_flag & _IONBF)) alloc_buffer(file); @@ -2494,33 +2778,36 @@ size_t CDECL fwrite(const void *ptr, size_t size, size_t nmemb, FILE* file) return 0; _lock_file(file); - if(file->_cnt) { - int pcnt=((unsigned)file->_cnt>wrcnt)? wrcnt: file->_cnt; - memcpy(file->_ptr, ptr, pcnt); - file->_cnt -= pcnt; - file->_ptr += pcnt; - written = pcnt; - wrcnt -= pcnt; - ptr = (const char*)ptr + pcnt; - } else if(!(file->_flag & _IOWRT)) { - if(file->_flag & _IORW) { - file->_flag |= _IOWRT; - } else { - _unlock_file(file); - return 0; - } - } - if(wrcnt) { - /* Flush buffer */ - int res=flush_buffer(file); - if(!res) { - int pwritten = _write(file->_file, ptr, wrcnt); - if (pwritten <= 0) - { - file->_flag |= _IOERR; - pwritten=0; + + while(wrcnt) { + if(file->_cnt) { + int pcnt=((unsigned)file->_cnt>wrcnt)? wrcnt: file->_cnt; + memcpy(file->_ptr, ptr, pcnt); + file->_cnt -= pcnt; + file->_ptr += pcnt; + written += pcnt; + wrcnt -= pcnt; + ptr = (const char*)ptr + pcnt; + } else if(!file->_bufsiz && (file->_flag & _IONBF)) { + if(!(file->_flag & _IOWRT)) { + if(file->_flag & _IORW) + file->_flag |= _IOWRT; + else + break; } - written += pwritten; + + if(_write(file->_file, ptr, wrcnt) <= 0) { + file->_flag |= _IOERR; + break; + } + written += wrcnt; + wrcnt = 0; + } else { + if(_flsbuf(*(const char*)ptr, file) == EOF) + break; + written++; + wrcnt--; + ptr = (const char*)ptr + 1; } } @@ -2896,8 +3183,6 @@ int CDECL fsetpos(FILE* file, const fpos_t *pos) */ __int64 CDECL _ftelli64(FILE* file) { - /* TODO: just call fgetpos and return lower half of result */ - int off=0; __int64 pos; _lock_file(file); @@ -2907,26 +3192,50 @@ __int64 CDECL _ftelli64(FILE* file) return -1; } if(file->_bufsiz) { - if( file->_flag & _IOWRT ) { - off = file->_ptr - file->_base; + if(file->_flag & _IOWRT) { + pos += file->_ptr - file->_base; + + if(get_ioinfo(file->_file)->wxflag & WX_TEXT) { + char *p; + + for(p=file->_base; p_ptr; p++) + if(*p == '\n') + pos++; + } + } else if(!file->_cnt) { /* nothing to do */ + } else if(_lseeki64(file->_file, 0, SEEK_END)==pos) { + int i; + + pos -= file->_cnt; + if(get_ioinfo(file->_file)->wxflag & WX_TEXT) { + for(i=0; i_cnt; i++) + if(file->_ptr[i] == '\n') + pos--; + } } else { - off = -file->_cnt; - if (get_ioinfo(file->_file)->wxflag & WX_TEXT) { - /* Black magic correction for CR removal */ - int i; - for (i=0; i_cnt; i++) { - if (file->_ptr[i] == '\n') - off--; - } - /* Black magic when reading CR at buffer boundary*/ - if(get_ioinfo(file->_file)->wxflag & WX_READCR) - off--; + char *p; + + if(_lseeki64(file->_file, pos, SEEK_SET) != pos) { + _unlock_file(file); + return -1; + } + + pos -= file->_bufsiz; + pos += file->_ptr - file->_base; + + if(get_ioinfo(file->_file)->wxflag & WX_TEXT) { + if(get_ioinfo(file->_file)->wxflag & WX_READNL) + pos--; + + for(p=file->_base; p_ptr; p++) + if(*p == '\n') + pos++; } } } _unlock_file(file); - return off + pos; + return pos; } /********************************************************************* @@ -3300,16 +3609,20 @@ FILE* CDECL tmpfile(void) FILE* file = NULL; LOCK_FILES(); - fd = _open(filename, _O_CREAT | _O_BINARY | _O_RDWR | _O_TEMPORARY); + fd = _open(filename, _O_CREAT | _O_BINARY | _O_RDWR | _O_TEMPORARY, + _S_IREAD | _S_IWRITE); if (fd != -1 && (file = alloc_fp())) { - if (init_fp(file, fd, _O_RDWR) == -1) + if (init_fp(file, fd, _IORW) == -1) { file->_flag = 0; file = NULL; } else file->_tmpfname = _strdup(filename); } + + if(fd != -1 && !file) + _close(fd); UNLOCK_FILES(); return file; } diff --git a/lib/sdk/crt/stdio/stat64.c b/lib/sdk/crt/stdio/stat64.c index 55e5c8f9f10..41340bbd9f5 100644 --- a/lib/sdk/crt/stdio/stat64.c +++ b/lib/sdk/crt/stdio/stat64.c @@ -27,14 +27,25 @@ int CDECL _tstat64(const _TCHAR *path, struct __stat64 *buf) DWORD dw; WIN32_FILE_ATTRIBUTE_DATA hfi; unsigned short mode = ALL_S_IREAD; - size_t plen; + int plen; TRACE(":file (%s) buf(%p)\n",path,buf); + plen = _tcslen(path); + while (plen && path[plen-1]==' ') + plen--; + + if (plen && (plen<2 || path[plen-2]!=':') && + (path[plen-1]==':' || path[plen-1]=='\\' || path[plen-1]=='/')) + { + *_errno() = ENOENT; + return -1; + } + if (!GetFileAttributesEx(path, GetFileExInfoStandard, &hfi)) { TRACE("failed (%d)\n",GetLastError()); - _dosmaperr(ERROR_FILE_NOT_FOUND); + *_errno() = ENOENT; return -1; } @@ -45,16 +56,13 @@ int CDECL _tstat64(const _TCHAR *path, struct __stat64 *buf) Also a letter as first char isn't enough to be classified as a drive letter */ - if (isalpha((unsigned char)*path)&& (*(path+1)==':')) - buf->st_dev = buf->st_rdev = _totupper(*path) - 'A'; /* drive num */ + if (isalpha(*path)&& (*(path+1)==':')) + buf->st_dev = buf->st_rdev = toupper(*path) - 'A'; /* drive num */ else buf->st_dev = buf->st_rdev = _getdrive() - 1; - plen = _tcslen(path); - /* Dir, or regular file? */ - if ((hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || - (path[plen-1] == '\\')) + if (hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) mode |= (_S_IFDIR | ALL_S_IEXEC); else { @@ -62,8 +70,8 @@ int CDECL _tstat64(const _TCHAR *path, struct __stat64 *buf) /* executable? */ if (plen > 6 && path[plen-4] == '.') /* shortest exe: "\x.exe" */ { - TCHAR4 ext = _totlower(path[plen-1]) | (_totlower(path[plen-2]) << TCSIZE) | - (_totlower(path[plen-3]) << (2*TCSIZE)); + unsigned int ext = tolower(path[plen-1]) | (tolower(path[plen-2]) << 8) | + (tolower(path[plen-3]) << 16); if (ext == EXE || ext == BAT || ext == CMD || ext == COM) mode |= ALL_S_IEXEC; } @@ -79,9 +87,9 @@ int CDECL _tstat64(const _TCHAR *path, struct __stat64 *buf) buf->st_atime = dw; RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastWriteTime, &dw); buf->st_mtime = buf->st_ctime = dw; - TRACE("%d %d 0x%08lx%08lx %ld %ld %ld\n", buf->st_mode,buf->st_nlink, - (long)(buf->st_size >> 32),(long)buf->st_size, - (long)buf->st_atime,(long)buf->st_mtime,(long)buf->st_ctime); + TRACE("%d %d 0x%08x%08x %d %d %d\n", buf->st_mode,buf->st_nlink, + (int)(buf->st_size >> 32),(int)buf->st_size, + (int)buf->st_atime,(int)buf->st_mtime,(int)buf->st_ctime); return 0; } diff --git a/lib/sdk/crt/stdlib/errno.c b/lib/sdk/crt/stdlib/errno.c index a56c0dd6d4e..049ad2c1fb8 100644 --- a/lib/sdk/crt/stdlib/errno.c +++ b/lib/sdk/crt/stdlib/errno.c @@ -13,45 +13,24 @@ static _invalid_parameter_handler invalid_parameter_handler = NULL; -/* - * @implemented - */ -unsigned long* CDECL __doserrno(void) -{ - return &(msvcrt_get_thread_data()->thread_doserrno); -} - -/* - * @implemented +/********************************************************************* + * _errno (MSVCRT.@) */ int CDECL *_errno(void) { return &(msvcrt_get_thread_data()->thread_errno); } -/* - * @implemented +/********************************************************************* + * __doserrno (MSVCRT.@) */ -errno_t CDECL _get_doserrno(unsigned long *pValue) +unsigned long* CDECL __doserrno(void) { - if (!pValue) - return EINVAL; - - *pValue = *__doserrno(); - return 0; + return &(msvcrt_get_thread_data()->thread_doserrno); } -/* - * @implemented - */ -errno_t CDECL _set_doserrno(unsigned long error) -{ - *__doserrno() = error; - return 0; -} - -/* - * @implemented +/********************************************************************* + * _get_errno (MSVCRT.@) */ errno_t CDECL _get_errno(int *pValue) { @@ -62,12 +41,33 @@ errno_t CDECL _get_errno(int *pValue) return 0; } -/* - * @implemented +/********************************************************************* + * _get_doserrno (MSVCRT.@) */ -int CDECL _set_errno(int error) +errno_t CDECL _get_doserrno(unsigned long *pValue) { - *_errno() = error; + if (!pValue) + return EINVAL; + + *pValue = *__doserrno(); + return 0; +} + +/********************************************************************* + * _set_errno (MSVCRT.@) + */ +errno_t CDECL _set_errno(int value) +{ + *_errno() = value; + return 0; +} + +/********************************************************************* + * _set_doserrno (MSVCRT.@) + */ +errno_t CDECL _set_doserrno(unsigned long value) +{ + *__doserrno() = value; return 0; } @@ -124,8 +124,8 @@ int CDECL _set_error_mode(int mode) } /****************************************************************************** -* _seterrormode (MSVCRT.@) -*/ + * _seterrormode (MSVCRT.@) + */ void CDECL _seterrormode(int mode) { SetErrorMode( mode ); @@ -134,8 +134,8 @@ void CDECL _seterrormode(int mode) /****************************************************************************** * _invalid_parameter (MSVCRT.@) */ -void CDECL _invalid_parameter(const wchar_t *expr, const wchar_t *func, - const wchar_t *file, unsigned int line, uintptr_t arg) +void __cdecl _invalid_parameter(const wchar_t *expr, const wchar_t *func, + const wchar_t *file, unsigned int line, uintptr_t arg) { if (invalid_parameter_handler) invalid_parameter_handler( expr, func, file, line, arg ); else @@ -163,4 +163,3 @@ _invalid_parameter_handler CDECL _set_invalid_parameter_handler( invalid_parameter_handler = handler; return old; } -/* EOF */ diff --git a/lib/sdk/crt/stdlib/senv.c b/lib/sdk/crt/stdlib/senv.c index a7a45438b2c..ea7cafd309e 100644 --- a/lib/sdk/crt/stdlib/senv.c +++ b/lib/sdk/crt/stdlib/senv.c @@ -109,8 +109,7 @@ int _tsearchenv_s(const _TCHAR* file, const _TCHAR* env, _TCHAR *buf, size_t cou { if (_tcslen(curPath) + 1 > count) { - MSVCRT_INVALID_PMT("buf[count] is too small"); - *_errno() = ERANGE; + MSVCRT_INVALID_PMT("buf[count] is too small", ERANGE); return ERANGE; } _tcscpy(buf, curPath); diff --git a/lib/sdk/crt/string/_tsplitpath_x.h b/lib/sdk/crt/string/_tsplitpath_x.h index 76473c98257..c8c89e4d52c 100644 --- a/lib/sdk/crt/string/_tsplitpath_x.h +++ b/lib/sdk/crt/string/_tsplitpath_x.h @@ -7,6 +7,7 @@ #include #include +#include #if IS_SECAPI #define _FAILURE -1 @@ -99,12 +100,24 @@ _tsplitpath_x( drive[2] = '\0'; } path += 2; - } + } /* Scan the rest of the string */ dir_start = path; while (*path != '\0') { +#if !defined(_UNICODE) && !defined(_LIBCNT_) + /* Check for multibyte lead bytes */ + if (_ismbblead((unsigned char)*path)) + { + /* Check for unexpected end of string */ + if (path[1] == 0) break; + + /* Skip the lead byte and the following byte */ + path += 2; + continue; + } +#endif /* Remember last path separator and last dot */ if ((*path == '\\') || (*path == '/')) file_start = path + 1; if (*path == '.') ext_start = path; @@ -114,14 +127,14 @@ _tsplitpath_x( /* Check if we got a file name / extension */ if (!file_start) file_start = dir_start; - if (!ext_start || ext_start < file_start) + if (!ext_start || (ext_start < file_start)) ext_start = path; if (dir) { src = dir_start; count = dir_size - 1; - while (src < file_start && count--) *dir++ = *src++; + while ((src < file_start) && count--) *dir++ = *src++; *dir = '\0'; } diff --git a/lib/sdk/crt/string/itoa.c b/lib/sdk/crt/string/itoa.c index e2f5918c13d..0d6e0e575c2 100644 --- a/lib/sdk/crt/string/itoa.c +++ b/lib/sdk/crt/string/itoa.c @@ -113,10 +113,7 @@ int CDECL _i64toa_s(__int64 value, char *str, size_t size, int radix) *p++ = *pos--; str[0] = '\0'; - MSVCRT_INVALID_PMT("str[size] is too small"); -#ifndef _LIBCNT_ - *_errno() = ERANGE; -#endif + MSVCRT_INVALID_PMT("str[size] is too small", ERANGE); return ERANGE; } @@ -182,10 +179,7 @@ int CDECL _ui64toa_s(unsigned __int64 value, char *str, }while(value != 0); if((unsigned)(buffer-pos+65) > size) { - MSVCRT_INVALID_PMT("str[size] is too small"); -#ifndef _LIBCNT_ - *_errno() = EINVAL; -#endif + MSVCRT_INVALID_PMT("str[size] is too small", EINVAL); return EINVAL; } @@ -322,10 +316,7 @@ int CDECL _ltoa_s(long value, char *str, size_t size, int radix) *p++ = *pos--; str[0] = '\0'; - MSVCRT_INVALID_PMT("str[size] is too small"); -#ifndef _LIBCNT_ - *_errno() = EINVAL; -#endif + MSVCRT_INVALID_PMT("str[size] is too small", ERANGE); return ERANGE; } diff --git a/lib/sdk/crt/string/itow.c b/lib/sdk/crt/string/itow.c index c18b679665a..204bcf7e3c6 100644 --- a/lib/sdk/crt/string/itow.c +++ b/lib/sdk/crt/string/itow.c @@ -123,11 +123,8 @@ _i64tow_s(__int64 value, wchar_t *str, size_t size, int radix) for (pos = buffer + 63, i = 0; i < size; i++) *p++ = *pos--; - MSVCRT_INVALID_PMT("str[size] is too small"); + MSVCRT_INVALID_PMT("str[size] is too small", ERANGE); str[0] = '\0'; -#ifndef _LIBCNT_ - *_errno() = ERANGE; -#endif return ERANGE; } @@ -195,10 +192,7 @@ _ui64tow_s( unsigned __int64 value, wchar_t *str, } while (value != 0); if((size_t)(buffer-pos+65) > size) { - MSVCRT_INVALID_PMT("str[size] is too small"); -#ifndef _LIBCNT_ - *_errno() = EINVAL; -#endif + MSVCRT_INVALID_PMT("str[size] is too small", EINVAL); return EINVAL; } @@ -338,11 +332,8 @@ _ltow_s(long value, wchar_t *str, size_t size, int radix) for (pos = buffer + 31, i = 0; i < size; i++) *p++ = *pos--; - MSVCRT_INVALID_PMT("str[size] is too small"); + MSVCRT_INVALID_PMT("str[size] is too small", ERANGE); str[0] = '\0'; -#ifndef _LIBCNT_ - *_errno() = ERANGE; -#endif return ERANGE; } diff --git a/lib/sdk/crt/string/strerror.c b/lib/sdk/crt/string/strerror.c index 8d0eced6a8b..a583c22c7bd 100644 --- a/lib/sdk/crt/string/strerror.c +++ b/lib/sdk/crt/string/strerror.c @@ -204,8 +204,7 @@ int CDECL __wcserror_s(wchar_t* buffer, size_t nc, const wchar_t* str) if (str && *str) len += lstrlenW(str) + 2 /* ': ' */; if (len > nc) { - MSVCRT_INVALID_PMT("buffer[nc] is too small"); - _set_errno(ERANGE); + MSVCRT_INVALID_PMT("buffer[nc] is too small", ERANGE); return ERANGE; } if (str && *str) diff --git a/lib/sdk/crt/string/wcs.c b/lib/sdk/crt/string/wcs.c index 846179a0589..81adfdb5e46 100644 --- a/lib/sdk/crt/string/wcs.c +++ b/lib/sdk/crt/string/wcs.c @@ -432,7 +432,7 @@ INT CDECL wcsncat_s(wchar_t *dst, size_t elem, } if (dststart == elem) { - MSVCRT_INVALID_PMT("dst[elem] is not NULL terminated\n"); + MSVCRT_INVALID_PMT("dst[elem] is not NULL terminated\n", EINVAL); return EINVAL; } @@ -453,7 +453,7 @@ INT CDECL wcsncat_s(wchar_t *dst, size_t elem, dst[dststart+srclen] = '\0'; return ret; } - MSVCRT_INVALID_PMT("dst[elem] is too small"); + MSVCRT_INVALID_PMT("dst[elem] is too small", ERANGE); dst[0] = '\0'; return ERANGE; } diff --git a/lib/sdk/crt/time/gmtime.c b/lib/sdk/crt/time/gmtime.c index ad4eafbe46c..314811ac586 100644 --- a/lib/sdk/crt/time/gmtime.c +++ b/lib/sdk/crt/time/gmtime.c @@ -126,15 +126,13 @@ _gmtime64_s( __time64_t time = *ptime; if (!ptm) { - _set_errno(ERROR_BAD_COMMAND); - MSVCRT_INVALID_PMT("ptm == NULL"); + MSVCRT_INVALID_PMT("ptm == NULL", ERROR_BAD_COMMAND); return ERROR_BAD_COMMAND; } if (!ptime) { - _set_errno(ERROR_BAD_COMMAND); - MSVCRT_INVALID_PMT("ptime == NULL"); + MSVCRT_INVALID_PMT("ptime == NULL", ERROR_BAD_COMMAND); return ERROR_BAD_COMMAND; } @@ -167,15 +165,13 @@ _gmtime32_s( __time64_t time = *ptime; if (!ptm) { - _set_errno(ERROR_BAD_COMMAND); - MSVCRT_INVALID_PMT("ptm == NULL"); + MSVCRT_INVALID_PMT("ptm == NULL", ERROR_BAD_COMMAND); return ERROR_BAD_COMMAND; } if (!ptime) { - _set_errno(ERROR_BAD_COMMAND); - MSVCRT_INVALID_PMT("ptime == NULL"); + MSVCRT_INVALID_PMT("ptime == NULL", ERROR_BAD_COMMAND); return ERROR_BAD_COMMAND; } diff --git a/lib/sdk/crt/wine/heap.c b/lib/sdk/crt/wine/heap.c index b72f63fe6cb..8ee2d1b433f 100644 --- a/lib/sdk/crt/wine/heap.c +++ b/lib/sdk/crt/wine/heap.c @@ -603,8 +603,7 @@ int CDECL strncpy_s(char *dest, size_t numberOfElements, return 0; } - MSVCRT_INVALID_PMT("dest[numberOfElements] is too small"); + MSVCRT_INVALID_PMT("dest[numberOfElements] is too small", EINVAL); dest[0] = '\0'; - *_errno() = EINVAL; return EINVAL; } diff --git a/media/doc/README.WINE b/media/doc/README.WINE index ec4763afd84..b88a56ed424 100644 --- a/media/doc/README.WINE +++ b/media/doc/README.WINE @@ -258,7 +258,7 @@ gdi32 - reactos/dll/win32/gdi32/objects/linedda.c # Synced at 20090410 kernel32 - - reactos/dll/win32/kernel32/wine/actctx.c # Partly synced + reactos/dll/win32/kernel32/wine/actctx.c # Partly synced with Wine 1.7.17 reactos/dll/win32/kernel32/wine/comm.c # Synced in r52754 reactos/dll/win32/kernel32/wine/lzexpand.c # Synced in r52754 reactos/dll/win32/kernel32/wine/profile.c # Synced in r52754 diff --git a/media/inf/audio.inf b/media/inf/audio.inf index 984177104cf..b197c0edb51 100644 Binary files a/media/inf/audio.inf and b/media/inf/audio.inf differ diff --git a/media/inf/battery.inf b/media/inf/battery.inf index cb5ae49eac7..55b259d7ece 100644 Binary files a/media/inf/battery.inf and b/media/inf/battery.inf differ diff --git a/media/inf/bth.inf b/media/inf/bth.inf index 4a61fae886c..bff8acc1da9 100644 Binary files a/media/inf/bth.inf and b/media/inf/bth.inf differ diff --git a/media/inf/cdrom.inf b/media/inf/cdrom.inf index 967b5ff4f45..7e50b19e420 100644 Binary files a/media/inf/cdrom.inf and b/media/inf/cdrom.inf differ diff --git a/media/inf/disk.inf b/media/inf/disk.inf index 7650e5f4809..e580e93dda0 100644 Binary files a/media/inf/disk.inf and b/media/inf/disk.inf differ diff --git a/media/inf/display.inf b/media/inf/display.inf index c9fa74f06de..abff97025b8 100644 Binary files a/media/inf/display.inf and b/media/inf/display.inf differ diff --git a/media/inf/flpydisk.inf b/media/inf/flpydisk.inf index 6a1aeebf05c..a6e0177e440 100644 Binary files a/media/inf/flpydisk.inf and b/media/inf/flpydisk.inf differ diff --git a/media/inf/hal.inf b/media/inf/hal.inf index 25f902d1df8..2686870749f 100644 Binary files a/media/inf/hal.inf and b/media/inf/hal.inf differ diff --git a/media/inf/hdc.inf b/media/inf/hdc.inf index d72b07fa01a..98738ebaff5 100644 Binary files a/media/inf/hdc.inf and b/media/inf/hdc.inf differ diff --git a/media/inf/input.inf b/media/inf/input.inf index f1e79d101fd..789bef3b926 100644 Binary files a/media/inf/input.inf and b/media/inf/input.inf differ diff --git a/media/inf/keyboard.inf b/media/inf/keyboard.inf index 93d08dccba7..8fe2e0b3f89 100644 Binary files a/media/inf/keyboard.inf and b/media/inf/keyboard.inf differ diff --git a/media/inf/legcydrv.inf b/media/inf/legcydrv.inf index f2296d12895..a30b2daa5ed 100644 Binary files a/media/inf/legcydrv.inf and b/media/inf/legcydrv.inf differ diff --git a/media/inf/machine.inf b/media/inf/machine.inf index e64177f9b96..8938bd8dc0f 100644 Binary files a/media/inf/machine.inf and b/media/inf/machine.inf differ diff --git a/media/inf/monitor.inf b/media/inf/monitor.inf index 491693922ec..4415a116376 100644 Binary files a/media/inf/monitor.inf and b/media/inf/monitor.inf differ diff --git a/media/inf/shortcuts.inf b/media/inf/shortcuts.inf index 013a54e5672..8d7ff549a89 100644 Binary files a/media/inf/shortcuts.inf and b/media/inf/shortcuts.inf differ diff --git a/media/inf/unknown.inf b/media/inf/unknown.inf index 6a32d97aa43..9bc33cedfe5 100644 Binary files a/media/inf/unknown.inf and b/media/inf/unknown.inf differ diff --git a/media/inf/usb.inf b/media/inf/usb.inf index 75b348c6736..e7e701f5e78 100644 Binary files a/media/inf/usb.inf and b/media/inf/usb.inf differ diff --git a/ntoskrnl/ex/event.c b/ntoskrnl/ex/event.c index 4238a82115f..26cbda90f34 100644 --- a/ntoskrnl/ex/event.c +++ b/ntoskrnl/ex/event.c @@ -19,7 +19,7 @@ /* GLOBALS *******************************************************************/ -POBJECT_TYPE _ExEventObjectType = NULL; +POBJECT_TYPE ExEventObjectType = NULL; GENERIC_MAPPING ExpEventMapping = { diff --git a/ntoskrnl/ex/sem.c b/ntoskrnl/ex/sem.c index 7b07b906a0d..98464685589 100644 --- a/ntoskrnl/ex/sem.c +++ b/ntoskrnl/ex/sem.c @@ -19,7 +19,7 @@ /* GLOBALS ******************************************************************/ -POBJECT_TYPE _ExSemaphoreObjectType; +POBJECT_TYPE ExSemaphoreObjectType; GENERIC_MAPPING ExSemaphoreMapping = { diff --git a/ntoskrnl/ex/sysinfo.c b/ntoskrnl/ex/sysinfo.c index 0fa37b675ea..88178addb5d 100644 --- a/ntoskrnl/ex/sysinfo.c +++ b/ntoskrnl/ex/sysinfo.c @@ -1964,7 +1964,7 @@ QSI_DEF(SystemLookasideInformation) } /* Acquire spinlock for ExpNonPagedLookasideListHead */ - OldIrql = KfAcquireSpinLock(&ExpNonPagedLookasideListLock); + KeAcquireSpinLock(&ExpNonPagedLookasideListLock, &OldIrql); /* Copy info from non-paged lookaside lists */ ExpCopyLookasideInformation(&Info, @@ -1973,7 +1973,7 @@ QSI_DEF(SystemLookasideInformation) TRUE); /* Release spinlock for ExpNonPagedLookasideListHead */ - KfReleaseSpinLock(&ExpNonPagedLookasideListLock, OldIrql); + KeReleaseSpinLock(&ExpNonPagedLookasideListLock, OldIrql); if (Remaining == 0) { @@ -1981,7 +1981,7 @@ QSI_DEF(SystemLookasideInformation) } /* Acquire spinlock for ExpPagedLookasideListHead */ - OldIrql = KfAcquireSpinLock(&ExpPagedLookasideListLock); + KeAcquireSpinLock(&ExpPagedLookasideListLock, &OldIrql); /* Copy info from paged lookaside lists */ ExpCopyLookasideInformation(&Info, @@ -1990,7 +1990,7 @@ QSI_DEF(SystemLookasideInformation) TRUE); /* Release spinlock for ExpPagedLookasideListHead */ - KfReleaseSpinLock(&ExpPagedLookasideListLock, OldIrql); + KeReleaseSpinLock(&ExpPagedLookasideListLock, OldIrql); Leave: diff --git a/ntoskrnl/fsrtl/fsrtlpc.c b/ntoskrnl/fsrtl/fsrtlpc.c index b5a68a4075e..0150a5582ee 100644 --- a/ntoskrnl/fsrtl/fsrtlpc.c +++ b/ntoskrnl/fsrtl/fsrtlpc.c @@ -18,7 +18,7 @@ PERESOURCE FsRtlPagingIoResources; ULONG FsRtlPagingIoResourceSelector; NTSTATUS NTAPI INIT_FUNCTION FsRtlInitializeWorkerThread(VOID); -static UCHAR LegalAnsiCharacterArray[] = +static const UCHAR LegalAnsiCharacterArray[] = { 0, /* CTRL+@, 0x00 */ 0, /* CTRL+A, 0x01 */ @@ -150,7 +150,7 @@ static UCHAR LegalAnsiCharacterArray[] = FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL /* 0x7f */ }; -PUCHAR FsRtlLegalAnsiCharacterArray = LegalAnsiCharacterArray; +const UCHAR * const FsRtlLegalAnsiCharacterArray = LegalAnsiCharacterArray; /* PRIVATE FUNCTIONS *********************************************************/ diff --git a/ntoskrnl/include/internal/amd64/mm.h b/ntoskrnl/include/internal/amd64/mm.h index 0021a0569a2..09049141e51 100644 --- a/ntoskrnl/include/internal/amd64/mm.h +++ b/ntoskrnl/include/internal/amd64/mm.h @@ -296,7 +296,7 @@ MI_IS_MAPPED_PTE(PMMPTE PointerPte) { /// FIXME __debugbreak(); - return (PointerPte->u.Long & 0xFFFFFC01 != 0); + return ((PointerPte->u.Long & 0xFFFFFC01) != 0); } VOID diff --git a/ntoskrnl/include/internal/fsrtl.h b/ntoskrnl/include/internal/fsrtl.h index cca4e8faeb1..86ce04e840a 100644 --- a/ntoskrnl/include/internal/fsrtl.h +++ b/ntoskrnl/include/internal/fsrtl.h @@ -133,5 +133,4 @@ FsRtlInitSystem( // Global data inside the File System Runtime Library // extern PERESOURCE FsRtlPagingIoResources; -extern PUCHAR _FsRtlLegalAnsiCharacterArray; extern PAGED_LOOKASIDE_LIST FsRtlFileLockLookasideList; diff --git a/ntoskrnl/include/internal/kd.h b/ntoskrnl/include/internal/kd.h index 0943e546962..3bb0dc3e59c 100644 --- a/ntoskrnl/include/internal/kd.h +++ b/ntoskrnl/include/internal/kd.h @@ -2,18 +2,11 @@ #include -#ifdef _M_PPC -#define KdDebuggerEnabled _KdDebuggerEnabled -#define KdDebuggerNotPresent _KdDebuggerNotPresent -#endif - // // Kernel Debugger Port Definition // struct _KD_DISPATCH_TABLE; extern CPPORT GdbPortInfo; -extern BOOLEAN _KdDebuggerEnabled; -extern BOOLEAN _KdDebuggerNotPresent; extern BOOLEAN KdBreakAfterSymbolLoad; extern BOOLEAN KdPitchDebugger; extern BOOLEAN KdIgnoreUmExceptions; diff --git a/ntoskrnl/include/internal/kd64.h b/ntoskrnl/include/internal/kd64.h index 444afbb51df..9cae4fa60c4 100644 --- a/ntoskrnl/include/internal/kd64.h +++ b/ntoskrnl/include/internal/kd64.h @@ -494,8 +494,6 @@ extern PKDEBUG_ROUTINE KiDebugRoutine; extern PKDEBUG_SWITCH_ROUTINE KiDebugSwitchRoutine; extern BOOLEAN KdBreakAfterSymbolLoad; extern BOOLEAN KdPitchDebugger; -extern BOOLEAN _KdDebuggerNotPresent; -extern BOOLEAN _KdDebuggerEnabled; extern BOOLEAN KdAutoEnableOnEvent; extern BOOLEAN KdBlockEnable; extern BOOLEAN KdIgnoreUmExceptions; diff --git a/ntoskrnl/include/ntoskrnl.h b/ntoskrnl/include/ntoskrnl.h index 9e7f37dd596..dc5772c66a8 100644 --- a/ntoskrnl/include/ntoskrnl.h +++ b/ntoskrnl/include/ntoskrnl.h @@ -90,31 +90,8 @@ // // Define the internal versions of external and public global data // -#define IoFileObjectType _IoFileObjectType -#define PsThreadType _PsThreadType -#define PsProcessType _PsProcessType -#define ExEventObjectType _ExEventObjectType -#define ExSemaphoreObjectType _ExSemaphoreObjectType -#define KdDebuggerEnabled _KdDebuggerEnabled -#define KdDebuggerNotPresent _KdDebuggerNotPresent -#define NlsOemLeadByteInfo _NlsOemLeadByteInfo -extern PUSHORT _NlsOemLeadByteInfo; #define KeNumberProcessors _KeNumberProcessors extern UCHAR _KeNumberProcessors; -#define FsRtlLegalAnsiCharacterArray _FsRtlLegalAnsiCharacterArray -#undef LEGAL_ANSI_CHARACTER_ARRAY -#undef NLS_MB_CODE_PAGE_TAG -#undef NLS_OEM_LEAD_BYTE_INFO -#define LEGAL_ANSI_CHARACTER_ARRAY FsRtlLegalAnsiCharacterArray -#define NLS_MB_CODE_PAGE_TAG NlsMbOemCodePageTag -#define NLS_OEM_LEAD_BYTE_INFO _NlsOemLeadByteInfo -#undef KD_DEBUGGER_ENABLED -#undef KD_DEBUGGER_NOT_PRESENT -#define KD_DEBUGGER_ENABLED KdDebuggerEnabled -#define KD_DEBUGGER_NOT_PRESENT KdDebuggerNotPresent -#define HalDispatchTable _HalDispatchTable -#undef HALDISPATCH -#define HALDISPATCH (&HalDispatchTable) #define ExRaiseStatus RtlRaiseStatus /* Internal Headers */ diff --git a/ntoskrnl/kd64/kdapi.c b/ntoskrnl/kd64/kdapi.c index c0a1650faa4..5ea86413fd8 100644 --- a/ntoskrnl/kd64/kdapi.c +++ b/ntoskrnl/kd64/kdapi.c @@ -1903,9 +1903,7 @@ KdDisableDebuggerWithLock(IN BOOLEAN NeedLock) /* We are disabled now */ KdDebuggerEnabled = FALSE; -#undef KdDebuggerEnabled SharedUserData->KdDebuggerEnabled = FALSE; -#define KdDebuggerEnabled _KdDebuggerEnabled } } diff --git a/ntoskrnl/kd64/kddata.c b/ntoskrnl/kd64/kddata.c index d6b0107fcb9..5a1e10ea065 100644 --- a/ntoskrnl/kd64/kddata.c +++ b/ntoskrnl/kd64/kddata.c @@ -79,8 +79,8 @@ PKDEBUG_SWITCH_ROUTINE KiDebugSwitchRoutine; // BOOLEAN KdBreakAfterSymbolLoad; BOOLEAN KdPitchDebugger; -BOOLEAN _KdDebuggerNotPresent; -BOOLEAN _KdDebuggerEnabled; +BOOLEAN KdDebuggerNotPresent; +BOOLEAN KdDebuggerEnabled; BOOLEAN KdAutoEnableOnEvent; BOOLEAN KdBlockEnable; BOOLEAN KdIgnoreUmExceptions; diff --git a/ntoskrnl/kd64/kdinit.c b/ntoskrnl/kd64/kdinit.c index 89d57fb089b..723a18ca323 100644 --- a/ntoskrnl/kd64/kdinit.c +++ b/ntoskrnl/kd64/kdinit.c @@ -310,9 +310,7 @@ KdInitSystem(IN ULONG BootPhase, KdDebuggerEnabled = TRUE; /* Let user-mode know that it's enabled as well */ -#undef KdDebuggerEnabled SharedUserData->KdDebuggerEnabled = TRUE; -#define KdDebuggerEnabled _KdDebuggerEnabled /* Check if the debugger should be disabled initially */ if (DisableKdAfterInit) diff --git a/ntoskrnl/ke/time.c b/ntoskrnl/ke/time.c index 76b125321fc..f54b9258a46 100644 --- a/ntoskrnl/ke/time.c +++ b/ntoskrnl/ke/time.c @@ -78,6 +78,9 @@ KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame, /* Increase interrupt count and end the interrupt */ Prcb->InterruptCount++; KiEndInterrupt(Irql, TrapFrame); + + /* Note: non-x86 return back to the caller! */ + return; } /* Add the increment time to the shared data */ diff --git a/ntoskrnl/mm/section.c b/ntoskrnl/mm/section.c index ec3b0947678..af8719277e5 100644 --- a/ntoskrnl/mm/section.c +++ b/ntoskrnl/mm/section.c @@ -280,7 +280,14 @@ l_ReadHeaderFromFile: nStatus = ReadFileCb(File, &lnOffset, sizeof(IMAGE_NT_HEADERS64), &pData, &pBuffer, &cbReadSize); if(!NT_SUCCESS(nStatus)) - DIE(("ReadFile failed, status %08X\n", nStatus)); + { + NTSTATUS ReturnedStatus = nStatus; + + /* If it attempted to read past the end of the file, it means e_lfanew is invalid */ + if (ReturnedStatus == STATUS_END_OF_FILE) nStatus = STATUS_ROS_EXEFMT_UNKNOWN_FORMAT; + + DIE(("ReadFile failed, status %08X\n", ReturnedStatus)); + } ASSERT(pData); ASSERT(pBuffer); diff --git a/ntoskrnl/ntoskrnl.spec b/ntoskrnl/ntoskrnl.spec index e5d8eeebdf7..5f7a0725804 100644 --- a/ntoskrnl/ntoskrnl.spec +++ b/ntoskrnl/ntoskrnl.spec @@ -82,7 +82,7 @@ @ stdcall ExEnterCriticalRegionAndAcquireResourceShared(ptr) @ stdcall ExEnterCriticalRegionAndAcquireSharedWaitForExclusive(ptr) @ stdcall ExEnumHandleTable(ptr ptr ptr ptr) -@ extern ExEventObjectType _ExEventObjectType +@ extern ExEventObjectType @ stdcall ExExtendZone(ptr ptr long) @ stdcall ExFreeCacheAwareRundownProtection(ptr) @ stdcall ExFreePool(ptr) @@ -144,7 +144,7 @@ @ fastcall ExReleaseRundownProtectionEx(ptr long) ExfReleaseRundownProtectionEx @ fastcall ExRundownCompleted(ptr) ExfRundownCompleted @ fastcall ExRundownCompletedCacheAware(ptr) ExfRundownCompletedCacheAware -@ extern ExSemaphoreObjectType _ExSemaphoreObjectType +@ extern ExSemaphoreObjectType @ stdcall ExSetResourceOwnerPointer(ptr ptr) @ stdcall ExSetTimerResolution(long long) @ stdcall ExSizeOfRundownProtectionCacheAware() @@ -241,7 +241,7 @@ @ stdcall FsRtlIsNtstatusExpected(long) @ stdcall FsRtlIsPagingFile(ptr) @ stdcall FsRtlIsTotalDeviceFailure(ptr) -@ extern FsRtlLegalAnsiCharacterArray _FsRtlLegalAnsiCharacterArray +@ extern FsRtlLegalAnsiCharacterArray @ stdcall FsRtlLookupBaseMcbEntry(ptr long long ptr ptr ptr ptr ptr) @ stdcall FsRtlLookupLargeMcbEntry(ptr long long ptr ptr ptr ptr ptr) @ stdcall FsRtlLookupLastBaseMcbEntry(ptr ptr ptr) @@ -302,7 +302,7 @@ @ stdcall FsRtlUninitializeLargeMcb(ptr) @ stdcall FsRtlUninitializeMcb(ptr) @ stdcall FsRtlUninitializeOplock(ptr) -@ extern HalDispatchTable _HalDispatchTable +@ extern HalDispatchTable @ fastcall HalExamineMBR(ptr long long ptr) @ extern HalPrivateDispatchTable @ stdcall HeadlessDispatch(long ptr long ptr ptr) @@ -393,7 +393,7 @@ @ stdcall IoEnumerateDeviceObjectList(ptr ptr long ptr) @ stdcall IoEnumerateRegisteredFiltersList(ptr long ptr) @ stdcall IoFastQueryNetworkAttributes(ptr long long ptr ptr) -@ extern IoFileObjectType _IoFileObjectType +@ extern IoFileObjectType @ stdcall IoForwardAndCatchIrp(ptr ptr) IoForwardIrpSynchronously @ stdcall IoForwardIrpSynchronously(ptr ptr) @ stdcall IoFreeController(ptr) @@ -533,8 +533,8 @@ @ fastcall IofCallDriver(ptr ptr) @ fastcall IofCompleteRequest(ptr long) @ stdcall KdChangeOption(long long ptr long ptr ptr) -@ extern KdDebuggerEnabled _KdDebuggerEnabled -@ extern KdDebuggerNotPresent _KdDebuggerNotPresent +@ extern KdDebuggerEnabled +@ extern KdDebuggerNotPresent @ stdcall KdDisableDebugger() @ stdcall KdEnableDebugger() @ extern KdEnteredDebugger @@ -830,7 +830,7 @@ @ extern NlsMbCodePageTag @ extern NlsMbOemCodePageTag @ extern NlsOemCodePage -@ extern NlsOemLeadByteInfo _NlsOemLeadByteInfo +@ extern NlsOemLeadByteInfo @ stdcall NtAddAtom(wstr long ptr) @ stdcall NtAdjustPrivilegesToken(ptr long ptr long ptr ptr) @ stdcall -arch=i386,arm NtAlertThread(ptr) @@ -1011,7 +1011,7 @@ @ stdcall PsLookupProcessByProcessId(ptr ptr) @ stdcall PsLookupProcessThreadByCid(ptr ptr ptr) @ stdcall PsLookupThreadByThreadId(ptr ptr) -@ extern PsProcessType _PsProcessType +@ extern PsProcessType @ stdcall PsReferenceImpersonationToken(ptr ptr ptr ptr) @ stdcall PsReferencePrimaryToken(ptr) @ stdcall PsRemoveCreateThreadNotifyRoutine(ptr) @@ -1036,7 +1036,7 @@ @ stdcall PsSetThreadHardErrorsAreDisabled(ptr long) @ stdcall PsSetThreadWin32Thread(ptr ptr ptr) @ stdcall PsTerminateSystemThread(long) -@ extern PsThreadType _PsThreadType +@ extern PsThreadType ;PsWrapApcWow64Thread @ stdcall -arch=i386,arm READ_REGISTER_BUFFER_UCHAR(ptr ptr long) @ stdcall -arch=i386,arm READ_REGISTER_BUFFER_ULONG(ptr ptr long) diff --git a/ntoskrnl/ps/quota.c b/ntoskrnl/ps/quota.c index 42899ddb3db..beba4d0b368 100644 --- a/ntoskrnl/ps/quota.c +++ b/ntoskrnl/ps/quota.c @@ -132,9 +132,9 @@ PspInsertQuotaBlock( { KIRQL OldIrql; - OldIrql = KfAcquireSpinLock(&PspQuotaLock); + KeAcquireSpinLock(&PspQuotaLock, &OldIrql); InsertTailList(&PspQuotaBlockList, &QuotaBlock->QuotaList); - KfReleaseSpinLock(&PspQuotaLock, OldIrql); + KeReleaseSpinLock(&PspQuotaLock, OldIrql); } VOID @@ -147,9 +147,9 @@ PspDestroyQuotaBlock(PEPROCESS Process) if (QuotaBlock != &PspDefaultQuotaBlock && InterlockedDecrementUL(&QuotaBlock->ReferenceCount) == 0) { - OldIrql = KfAcquireSpinLock(&PspQuotaLock); + KeAcquireSpinLock(&PspQuotaLock, &OldIrql); RemoveEntryList(&QuotaBlock->QuotaList); - KfReleaseSpinLock(&PspQuotaLock, OldIrql); + KeReleaseSpinLock(&PspQuotaLock, OldIrql); ExFreePool(QuotaBlock); } } diff --git a/subsystems/CMakeLists.txt b/subsystems/CMakeLists.txt index 52d10bc85fc..230e58c9ace 100644 --- a/subsystems/CMakeLists.txt +++ b/subsystems/CMakeLists.txt @@ -1,6 +1,4 @@ -if(ARCH STREQUAL "i386") - add_subdirectory(ntvdm) -endif() +add_subdirectory(ntvdm) add_subdirectory(win) add_subdirectory(win32) diff --git a/subsystems/ntvdm/CMakeLists.txt b/subsystems/ntvdm/CMakeLists.txt index 7a1c6aa155d..2ee9f55eaad 100644 --- a/subsystems/ntvdm/CMakeLists.txt +++ b/subsystems/ntvdm/CMakeLists.txt @@ -1,11 +1,43 @@ -include_directories(.) +include_directories( + ${REACTOS_SOURCE_DIR}/include/reactos/libs/fast486 + ntvdm) -add_executable(ntvdm +spec2def(ntvdm.exe ntvdm.spec) + +list(APPEND SOURCE + bios/bios32/bios32.c + bios/bios32/kbdbios32.c + bios/bios32/vidbios32.c + bios/bios.c + bios/kbdbios.c + bios/rom.c + bios/vidbios.c + hardware/cmos.c + hardware/pic.c + hardware/ps2.c + hardware/speaker.c + hardware/timer.c + hardware/vga.c + dos/dos32krnl/bios.c + dos/dos32krnl/dos.c + dos/dos32krnl/dosfiles.c + dos/dem.c + bop.c + callback.c + clock.c + emulator.c + io.c + registers.c + utils.c + vddsup.c ntvdm.c - ntvdm.rc) + ntvdm.rc + ${CMAKE_CURRENT_BINARY_DIR}/ntvdm.def) -set_module_type(ntvdm win32cui) -add_importlibs(ntvdm ntdll user32 gdi32 advapi32 msvcrt kernel32) -add_dependencies(ntvdm ndk bugcodes) +add_executable(ntvdm ${SOURCE}) +set_module_type(ntvdm win32cui UNICODE) +set_image_base(ntvdm 0x0F000000) +target_link_libraries(ntvdm fast486) +add_importlibs(ntvdm user32 gdi32 advapi32 msvcrt kernel32 ntdll) add_cd_file(TARGET ntvdm DESTINATION reactos/system32 FOR all) diff --git a/subsystems/ntvdm/bios/bios.c b/subsystems/ntvdm/bios/bios.c new file mode 100644 index 00000000000..12066b53dd3 --- /dev/null +++ b/subsystems/ntvdm/bios/bios.c @@ -0,0 +1,211 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: bios.c + * PURPOSE: VDM BIOS Support Library + * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "callback.h" +#include "bop.h" + +#include "bios.h" +#include "bios32/bios32.h" + +#include "rom.h" + +#include "io.h" +#include "hardware/cmos.h" + +/* DEFINES ********************************************************************/ + +/* BOP Identifiers */ +#define BOP_BIOSINIT 0x00 // Windows NTVDM (SoftPC) BIOS calls BOP 0x00 + // to let the virtual machine initialize itself + // the IVT and its hardware. +#define BOP_EQUIPLIST 0x11 +#define BOP_GETMEMSIZE 0x12 + +/* PRIVATE VARIABLES **********************************************************/ + +static BOOLEAN Bios32Loaded = FALSE; + +static CALLBACK16 __BiosContext; +PBIOS_DATA_AREA Bda; + +/* PRIVATE FUNCTIONS **********************************************************/ + +static VOID WINAPI BiosInitBop(LPWORD Stack) +{ + BOOLEAN Success; + + /* Load the second part of the Windows NTVDM BIOS image */ + LPCSTR BiosFileName = "bios1.rom"; + PVOID BiosLocation = (PVOID)TO_LINEAR(BIOS_SEGMENT, 0x0000); + DWORD BiosSize = 0; + + /* Disable interrupts */ + setIF(0); + + DisplayMessage(L"You are loading Windows NTVDM BIOS!\n"); + + /* Initialize a private callback context */ + InitializeContext(&__BiosContext, BIOS_SEGMENT, 0x0000); + + Success = LoadRom(BiosFileName, BiosLocation, &BiosSize); + DPRINT1("BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError()); + + if (Success == FALSE) + { + /* Stop the VDM */ + EmulatorTerminate(); + return; + } + + // DisplayMessage(L"First bytes at 0x%p: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n" + // L"3 last bytes at 0x%p: 0x%02x 0x%02x 0x%02x", + // BiosLocation, + // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 0), + // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 1), + // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 2), + // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 3), + // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 4), + // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 5), + // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 6), + // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 7), + // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 8), + // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 9), + + // (PVOID)((ULONG_PTR)BiosLocation + BiosSize - 2), + // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 2), + // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 1), + // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 0)); + + /* Initialize IVT and hardware */ + + /* Initialize the Keyboard and Video BIOS */ + if (!KbdBiosInitialize() || !VidBiosInitialize()) + { + /* Stop the VDM */ + EmulatorTerminate(); + return; + } + + /* Load VGA BIOS */ + // Success = LoadRom("v7vga.rom", (PVOID)0xC0000, &BiosSize); + // DPRINT1("VGA BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError()); + + /* Enable interrupts */ + setIF(1); + + ///////////// MUST BE DONE AFTER IVT INITIALIZATION !! ///////////////////// + + /* Load some ROMs */ + // Success = LoadRom("boot.bin", (PVOID)0xE0000, &BiosSize); + // DPRINT1("Test ROM loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError()); + + SearchAndInitRoms(&__BiosContext); +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID WINAPI BiosEquipmentService(LPWORD Stack) +{ + /* Return the equipment list */ + setAX(Bda->EquipmentList); +} + +VOID WINAPI BiosGetMemorySize(LPWORD Stack) +{ + /* Return the conventional memory size in kB, typically 640 kB */ + setAX(Bda->MemorySize); +} + +BOOLEAN +BiosInitialize(IN LPCSTR BiosFileName) +{ + BOOLEAN Success = FALSE; + + /* Disable interrupts */ + setIF(0); + + /* Initialize the BDA pointer */ + Bda = (PBIOS_DATA_AREA)SEG_OFF_TO_PTR(BDA_SEGMENT, 0); + + /* Register the BIOS support BOPs */ + RegisterBop(BOP_BIOSINIT , BiosInitBop); + RegisterBop(BOP_EQUIPLIST , BiosEquipmentService); + RegisterBop(BOP_GETMEMSIZE, BiosGetMemorySize); + + if (BiosFileName) + { + PVOID BiosLocation = NULL; + DWORD BiosSize = 0; + + Success = LoadBios(BiosFileName, &BiosLocation, &BiosSize); + DPRINT1("BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError()); + + if (!Success) return FALSE; + + DisplayMessage(L"First bytes at 0x%p: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n" + L"3 last bytes at 0x%p: 0x%02x 0x%02x 0x%02x", + BiosLocation, + *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 0), + *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 1), + *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 2), + *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 3), + *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 4), + *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 5), + *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 6), + *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 7), + *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 8), + *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 9), + + (PVOID)((ULONG_PTR)BiosLocation + BiosSize - 2), + *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 2), + *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 1), + *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 0)); + + DisplayMessage(L"POST at 0x%p: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", + TO_LINEAR(getCS(), getIP()), + *(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 0), + *(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 1), + *(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 2), + *(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 3), + *(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 4)); + + /* Boot it up */ + + /* + * The CPU is already in reset-mode so that + * CS:IP points to F000:FFF0 as required. + */ + DisplayMessage(L"CS=0x%p ; IP=0x%p", getCS(), getIP()); + // setCS(0xF000); + // setIP(0xFFF0); + + Success = TRUE; + } + else + { + Success = Bios32Loaded = Bios32Initialize(); + } + + /* Enable interrupts */ + setIF(1); + + return Success; +} + +VOID +BiosCleanup(VOID) +{ + if (Bios32Loaded) Bios32Cleanup(); +} + +/* EOF */ diff --git a/subsystems/ntvdm/bios/bios.h b/subsystems/ntvdm/bios/bios.h new file mode 100644 index 00000000000..cc1bb94b803 --- /dev/null +++ b/subsystems/ntvdm/bios/bios.h @@ -0,0 +1,118 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: bios.h + * PURPOSE: VDM BIOS Support Library + * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +#ifndef _BIOS_H_ +#define _BIOS_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" +#include "kbdbios.h" +#include "vidbios.h" + +/* DEFINES ********************************************************************/ + +#define BDA_SEGMENT 0x40 +#define BIOS_SEGMENT 0xF000 + +#define BIOS_EQUIPMENT_LIST 0x2C // HACK: Disable FPU for now + +/* + * BIOS Data Area at 0040:XXXX + * + * See: http://webpages.charter.net/danrollins/techhelp/0093.HTM + * and: http://www.bioscentral.com/misc/bda.htm + * for more information. + */ +#pragma pack(push, 1) +typedef struct +{ + WORD SerialPorts[4]; // 0x00 + WORD ParallelPorts[3]; // 0x08 + WORD EbdaSegment; // 0x0e - ParallelPort in PC/XT + WORD EquipmentList; // 0x10 + BYTE Reserved0; // 0x12 - Errors in PCjr infrared keyboard link + WORD MemorySize; // 0x13 + WORD Reserved1; // 0x15 - Scratch pad for manufacturing error tests + WORD KeybdShiftFlags; // 0x17 + BYTE AlternateKeypad; // 0x19 + WORD KeybdBufferHead; // 0x1a + WORD KeybdBufferTail; // 0x1c + WORD KeybdBuffer[BIOS_KBD_BUFFER_SIZE]; // 0x1e + BYTE DriveRecalibrate; // 0x3e + BYTE DriveMotorStatus; // 0x3f + BYTE MotorShutdownCounter; // 0x40 + BYTE LastDisketteOperation; // 0x41 + BYTE Reserved2[7]; // 0x42 + BYTE VideoMode; // 0x49 + WORD ScreenColumns; // 0x4a + WORD VideoPageSize; // 0x4c + WORD VideoPageOffset; // 0x4e + WORD CursorPosition[BIOS_MAX_PAGES]; // 0x50 + BYTE CursorEndLine; // 0x60 + BYTE CursorStartLine; // 0x61 + BYTE VideoPage; // 0x62 + WORD CrtBasePort; // 0x63 + BYTE CrtModeControl; // 0x65 + BYTE CrtColorPaletteMask; // 0x66 + BYTE CassetteData[5]; // 0x67 + DWORD TickCounter; // 0x6c + BYTE MidnightPassed; // 0x70 + BYTE BreakFlag; // 0x71 + WORD SoftReset; // 0x72 + BYTE LastDiskOperation; // 0x74 + BYTE NumDisks; // 0x75 + BYTE DriveControlByte; // 0x76 + BYTE DiskPortOffset; // 0x77 + BYTE LptTimeOut[4]; // 0x78 + BYTE ComTimeOut[4]; // 0x7c + WORD KeybdBufferStart; // 0x80 + WORD KeybdBufferEnd; // 0x82 + BYTE ScreenRows; // 0x84 + WORD CharacterHeight; // 0x85 + BYTE EGAFlags[2]; // 0x87 + BYTE VGAFlags[2]; // 0x89 + DWORD Reserved3; // 0x8b + BYTE Reserved4; // 0x8f + BYTE Reserved5[2]; // 0x90 + BYTE Reserved6[2]; // 0x92 + BYTE Reserved7[2]; // 0x94 + WORD Reserved8; // 0x96 + DWORD Reserved9; // 0x98 + DWORD Reserved10; // 0x9c + DWORD Reserved11[2]; // 0xa0 + DWORD EGAPtr; // 0xa8 + BYTE Reserved12[68]; // 0xac + BYTE Reserved13[16]; // 0xf0 + + DWORD Reserved14; // 0x100 + BYTE Reserved15[12]; // 0x104 + BYTE Reserved16[17]; // 0x110 + BYTE Reserved17[15]; // 0x121 + BYTE Reserved18[3]; // 0x130 +} BIOS_DATA_AREA, *PBIOS_DATA_AREA; +#pragma pack(pop) + +C_ASSERT(sizeof(BIOS_DATA_AREA) == 0x133); + +/* FUNCTIONS ******************************************************************/ + +extern PBIOS_DATA_AREA Bda; + +VOID WINAPI BiosEquipmentService(LPWORD Stack); +VOID WINAPI BiosGetMemorySize(LPWORD Stack); + +BOOLEAN +BiosInitialize(IN LPCSTR BiosFileName); + +VOID +BiosCleanup(VOID); + +#endif // _BIOS_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/bios/bios32/bios32.c b/subsystems/ntvdm/bios/bios32/bios32.c new file mode 100644 index 00000000000..fc272826242 --- /dev/null +++ b/subsystems/ntvdm/bios/bios32/bios32.c @@ -0,0 +1,403 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: bios32.c + * PURPOSE: VDM 32-bit BIOS + * PROGRAMMERS: Aleksandar Andrejevic + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "callback.h" +#include "bop.h" + +#include "../bios.h" +#include "../rom.h" +#include "bios32.h" +#include "bios32p.h" +#include "kbdbios32.h" +#include "vidbios32.h" + +#include "io.h" +#include "hardware/cmos.h" +#include "hardware/pic.h" +#include "hardware/timer.h" + +/* PRIVATE VARIABLES **********************************************************/ + +CALLBACK16 BiosContext; + +/* PRIVATE FUNCTIONS **********************************************************/ + +static VOID WINAPI BiosException(LPWORD Stack) +{ + /* Get the exception number and call the emulator API */ + BYTE ExceptionNumber = LOBYTE(Stack[STACK_INT_NUM]); + EmulatorException(ExceptionNumber, Stack); +} + +static VOID WINAPI BiosMiscService(LPWORD Stack) +{ + switch (getAH()) + { + /* Wait */ + case 0x86: + { + /* + * Interval in microseconds in CX:DX + * See Ralf Brown: http://www.ctyme.com/intr/rb-1525.htm + * for more information. + */ + Sleep(MAKELONG(getDX(), getCX())); + + /* Clear CF */ + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + + break; + } + + /* Copy Extended Memory */ + case 0x87: + { + DWORD Count = (DWORD)getCX() * 2; + PFAST486_GDT_ENTRY Gdt = (PFAST486_GDT_ENTRY)SEG_OFF_TO_PTR(getES(), getSI()); + DWORD SourceBase = Gdt[2].Base + (Gdt[2].BaseMid << 16) + (Gdt[2].BaseHigh << 24); + DWORD SourceLimit = Gdt[2].Limit + (Gdt[2].LimitHigh << 16); + DWORD DestBase = Gdt[3].Base + (Gdt[3].BaseMid << 16) + (Gdt[3].BaseHigh << 24); + DWORD DestLimit = Gdt[3].Limit + (Gdt[3].LimitHigh << 16); + + /* Check for flags */ + if (Gdt[2].Granularity) SourceLimit = (SourceLimit << 12) | 0xFFF; + if (Gdt[3].Granularity) DestLimit = (DestLimit << 12) | 0xFFF; + + if ((Count > SourceLimit) || (Count > DestLimit)) + { + setAX(0x80); + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + + break; + } + + /* Copy */ + RtlMoveMemory((PVOID)((ULONG_PTR)BaseAddress + DestBase), + (PVOID)((ULONG_PTR)BaseAddress + SourceBase), + Count); + + setAX(ERROR_SUCCESS); + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + break; + } + + /* Get Extended Memory Size */ + case 0x88: + { + UCHAR Low, High; + + /* + * Return the (usable) extended memory (after 1 MB) + * size in kB from CMOS. + */ + IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_ACTUAL_EXT_MEMORY_LOW); + Low = IOReadB(CMOS_DATA_PORT); + IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_ACTUAL_EXT_MEMORY_HIGH); + High = IOReadB(CMOS_DATA_PORT); + setAX(MAKEWORD(Low, High)); + + /* Clear CF */ + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + + break; + } + + default: + { + DPRINT1("BIOS Function INT 15h, AH = 0x%02X NOT IMPLEMENTED\n", + getAH()); + } + } +} + +static VOID WINAPI BiosTimeService(LPWORD Stack) +{ + switch (getAH()) + { + case 0x00: + { + /* Set AL to 1 if midnight had passed, 0 otherwise */ + setAL(Bda->MidnightPassed ? 0x01 : 0x00); + + /* Return the tick count in CX:DX */ + setCX(HIWORD(Bda->TickCounter)); + setDX(LOWORD(Bda->TickCounter)); + + /* Reset the midnight flag */ + Bda->MidnightPassed = FALSE; + + break; + } + + case 0x01: + { + /* Set the tick count to CX:DX */ + Bda->TickCounter = MAKELONG(getDX(), getCX()); + + /* Reset the midnight flag */ + Bda->MidnightPassed = FALSE; + + break; + } + + default: + { + DPRINT1("BIOS Function INT 1Ah, AH = 0x%02X NOT IMPLEMENTED\n", + getAH()); + } + } +} + +static VOID WINAPI BiosSystemTimerInterrupt(LPWORD Stack) +{ + /* Increase the system tick count */ + Bda->TickCounter++; +} + + +// From SeaBIOS +static VOID PicSetIRQMask(USHORT off, USHORT on) +{ + UCHAR pic1off = off, pic1on = on, pic2off = off>>8, pic2on = on>>8; + IOWriteB(PIC_MASTER_DATA, (IOReadB(PIC_MASTER_DATA) & ~pic1off) | pic1on); + IOWriteB(PIC_SLAVE_DATA , (IOReadB(PIC_SLAVE_DATA ) & ~pic2off) | pic2on); +} + +// From SeaBIOS +VOID EnableHwIRQ(UCHAR hwirq, EMULATOR_INT32_PROC func) +{ + UCHAR vector; + + PicSetIRQMask(1 << hwirq, 0); + if (hwirq < 8) + vector = BIOS_PIC_MASTER_INT + hwirq; + else + vector = BIOS_PIC_SLAVE_INT + hwirq - 8; + + RegisterBiosInt32(vector, func); +} + + +VOID PicIRQComplete(LPWORD Stack) +{ + /* Get the interrupt number */ + BYTE IntNum = LOBYTE(Stack[STACK_INT_NUM]); + + /* + * If this was a PIC IRQ, send an End-of-Interrupt to the PIC. + */ + + if (IntNum >= BIOS_PIC_MASTER_INT && IntNum < BIOS_PIC_MASTER_INT + 8) + { + /* It was an IRQ from the master PIC */ + IOWriteB(PIC_MASTER_CMD, PIC_OCW2_EOI); + } + else if (IntNum >= BIOS_PIC_SLAVE_INT && IntNum < BIOS_PIC_SLAVE_INT + 8) + { + /* It was an IRQ from the slave PIC */ + IOWriteB(PIC_SLAVE_CMD , PIC_OCW2_EOI); + IOWriteB(PIC_MASTER_CMD, PIC_OCW2_EOI); + } +} + +static VOID WINAPI BiosHandleMasterPicIRQ(LPWORD Stack) +{ + BYTE IrqNumber; + + IOWriteB(PIC_MASTER_CMD, PIC_OCW3_READ_ISR /* == 0x0B */); + IrqNumber = IOReadB(PIC_MASTER_CMD); + + DPRINT("Master - IrqNumber = 0x%x\n", IrqNumber); + + PicIRQComplete(Stack); +} + +static VOID WINAPI BiosHandleSlavePicIRQ(LPWORD Stack) +{ + BYTE IrqNumber; + + IOWriteB(PIC_SLAVE_CMD, PIC_OCW3_READ_ISR /* == 0x0B */); + IrqNumber = IOReadB(PIC_SLAVE_CMD); + + DPRINT("Slave - IrqNumber = 0x%x\n", IrqNumber); + + PicIRQComplete(Stack); +} + +// Timer IRQ 0 +static VOID WINAPI BiosTimerIrq(LPWORD Stack) +{ + /* + * Perform the system timer interrupt. + * + * Do not call directly BiosSystemTimerInterrupt(Stack); + * because some programs may hook only BIOS_SYS_TIMER_INTERRUPT + * for their purpose... + */ + /** EmulatorInterrupt(BIOS_SYS_TIMER_INTERRUPT); **/ + Int32Call(&BiosContext, BIOS_SYS_TIMER_INTERRUPT); + PicIRQComplete(Stack); +} + + +static VOID BiosHwSetup(VOID) +{ + /* Initialize the master and the slave PICs (cascade mode) */ + IOWriteB(PIC_MASTER_CMD, PIC_ICW1 | PIC_ICW1_ICW4); + IOWriteB(PIC_SLAVE_CMD , PIC_ICW1 | PIC_ICW1_ICW4); + + /* + * Set the interrupt vector offsets for each PIC + * (base IRQs: 0x08-0x0F for IRQ 0-7, 0x70-0x77 for IRQ 8-15) + */ + IOWriteB(PIC_MASTER_DATA, BIOS_PIC_MASTER_INT); + IOWriteB(PIC_SLAVE_DATA , BIOS_PIC_SLAVE_INT ); + + /* Tell the master PIC that there is a slave PIC at IRQ 2 */ + IOWriteB(PIC_MASTER_DATA, 1 << 2); + /* Tell the slave PIC its cascade identity */ + IOWriteB(PIC_SLAVE_DATA , 2); + + /* Make sure both PICs are in 8086 mode */ + IOWriteB(PIC_MASTER_DATA, PIC_ICW4_8086); + IOWriteB(PIC_SLAVE_DATA , PIC_ICW4_8086); + + /* Clear the masks for both PICs */ + // IOWriteB(PIC_MASTER_DATA, 0x00); + // IOWriteB(PIC_SLAVE_DATA , 0x00); + /* Disable all IRQs */ + IOWriteB(PIC_MASTER_DATA, 0xFF); + IOWriteB(PIC_SLAVE_DATA , 0xFF); + + + /* Initialize PIT Counter 0 */ + IOWriteB(PIT_COMMAND_PORT, 0x34); + IOWriteB(PIT_DATA_PORT(0), 0x00); + IOWriteB(PIT_DATA_PORT(0), 0x00); + + /* Initialize PIT Counter 1 */ + IOWriteB(PIT_COMMAND_PORT, 0x74); + IOWriteB(PIT_DATA_PORT(1), 0x00); + IOWriteB(PIT_DATA_PORT(1), 0x00); + + /* Initialize PIT Counter 2 */ + IOWriteB(PIT_COMMAND_PORT, 0xB4); + IOWriteB(PIT_DATA_PORT(2), 0x00); + IOWriteB(PIT_DATA_PORT(2), 0x00); + + EnableHwIRQ(0, BiosTimerIrq); +} + +static VOID InitializeBiosInt32(VOID) +{ + USHORT i; + // USHORT Offset = 0; + + /* Initialize the callback context */ + InitializeContext(&BiosContext, BIOS_SEGMENT, 0x0000); + + /* Register the BIOS 32-bit Interrupts */ + for (i = 0x00; i <= 0xFF; i++) + { + // Offset += RegisterInt32(MAKELONG(Offset, BIOS_SEGMENT), i, NULL, NULL); + BiosContext.NextOffset += RegisterInt32(MAKELONG(BiosContext.NextOffset, + BiosContext.Segment), + i, NULL, NULL); + } + + /* Initialize the exception vector interrupts to a default Exception handler */ + for (i = 0; i < 8; i++) + RegisterBiosInt32(i, BiosException); + + /* Initialize HW vector interrupts to a default HW handler */ + for (i = BIOS_PIC_MASTER_INT; i < BIOS_PIC_MASTER_INT + 8; i++) + RegisterBiosInt32(i, BiosHandleMasterPicIRQ); + for (i = BIOS_PIC_SLAVE_INT ; i < BIOS_PIC_SLAVE_INT + 8; i++) + RegisterBiosInt32(i, BiosHandleSlavePicIRQ); + + /* Initialize software vector handlers */ + RegisterBiosInt32(BIOS_EQUIPMENT_INTERRUPT, BiosEquipmentService ); + RegisterBiosInt32(BIOS_MEMORY_SIZE , BiosGetMemorySize ); + RegisterBiosInt32(BIOS_MISC_INTERRUPT , BiosMiscService ); + RegisterBiosInt32(BIOS_TIME_INTERRUPT , BiosTimeService ); + RegisterBiosInt32(BIOS_SYS_TIMER_INTERRUPT, BiosSystemTimerInterrupt); + + /* Some interrupts are in fact addresses to tables */ + ((PULONG)BaseAddress)[0x1E] = (ULONG)NULL; + ((PULONG)BaseAddress)[0x41] = (ULONG)NULL; + ((PULONG)BaseAddress)[0x46] = (ULONG)NULL; + ((PULONG)BaseAddress)[0x48] = (ULONG)NULL; + ((PULONG)BaseAddress)[0x49] = (ULONG)NULL; +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +/* + * The BIOS POST (Power On-Self Test) + */ +BOOLEAN Bios32Initialize(VOID) +{ + BOOLEAN Success; + UCHAR Low, High; + + /* Initialize the stack */ + // That's what says IBM... (stack at 30:00FF going downwards) + // setSS(0x0000); + // setSP(0x0400); + setSS(0x0050); // Stack at 50:0400, going downwards + setSP(0x0400); + + /* Set data segment */ + setDS(BDA_SEGMENT); + + /* Initialize the BDA contents */ + Bda->EquipmentList = BIOS_EQUIPMENT_LIST; + + /* + * Retrieve the conventional memory size + * in kB from CMOS, typically 640 kB. + */ + IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_BASE_MEMORY_LOW); + Low = IOReadB(CMOS_DATA_PORT); + IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_BASE_MEMORY_HIGH); + High = IOReadB(CMOS_DATA_PORT); + Bda->MemorySize = MAKEWORD(Low, High); + + /* Register the BIOS 32-bit Interrupts */ + InitializeBiosInt32(); + + /* Initialize platform hardware (PIC/PIT chips, ...) */ + BiosHwSetup(); + + /* Initialize the Keyboard and Video BIOS */ + if (!KbdBios32Initialize() || !VidBios32Initialize()) return FALSE; + + ///////////// MUST BE DONE AFTER IVT INITIALIZATION !! ///////////////////// + + /* Load some ROMs */ + Success = LoadRom("boot.bin", (PVOID)0xE0000, NULL); + DPRINT1("Test ROM loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError()); + + SearchAndInitRoms(&BiosContext); + + /* We are done */ + return TRUE; +} + +VOID Bios32Cleanup(VOID) +{ + VidBios32Cleanup(); + KbdBios32Cleanup(); +} + +/* EOF */ diff --git a/subsystems/ntvdm/bios/bios32/bios32.h b/subsystems/ntvdm/bios/bios32/bios32.h new file mode 100644 index 00000000000..4bd5d30b15c --- /dev/null +++ b/subsystems/ntvdm/bios/bios32/bios32.h @@ -0,0 +1,32 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: bios32.h + * PURPOSE: VDM 32-bit BIOS + * PROGRAMMERS: Aleksandar Andrejevic + */ + +#ifndef _BIOS32_H_ +#define _BIOS32_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" +// #include "../bios.h" + +/* DEFINES ********************************************************************/ + +// #define BIOS_EQUIPMENT_INTERRUPT 0x11 +// #define BIOS_MEMORY_SIZE 0x12 +// #define BIOS_MISC_INTERRUPT 0x15 +// #define BIOS_TIME_INTERRUPT 0x1A +// #define BIOS_SYS_TIMER_INTERRUPT 0x1C + +/* FUNCTIONS ******************************************************************/ + +BOOLEAN Bios32Initialize(VOID); +VOID Bios32Cleanup(VOID); + +#endif // _BIOS32_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/bios/bios32/bios32p.h b/subsystems/ntvdm/bios/bios32/bios32p.h new file mode 100644 index 00000000000..604fda30cc7 --- /dev/null +++ b/subsystems/ntvdm/bios/bios32/bios32p.h @@ -0,0 +1,45 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: bios32.h + * PURPOSE: VDM 32-bit BIOS + * PROGRAMMERS: Aleksandar Andrejevic + */ + +#ifndef _BIOS32P_H_ +#define _BIOS32P_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" +#include "../bios.h" + +/**/ #include "callback.h" /**/ + +/* DEFINES ********************************************************************/ + +#define BIOS_PIC_MASTER_INT 0x08 +#define BIOS_PIC_SLAVE_INT 0x70 + +#define BIOS_EQUIPMENT_INTERRUPT 0x11 +#define BIOS_MEMORY_SIZE 0x12 +#define BIOS_MISC_INTERRUPT 0x15 +#define BIOS_TIME_INTERRUPT 0x1A +#define BIOS_SYS_TIMER_INTERRUPT 0x1C + +/* FUNCTIONS ******************************************************************/ + +extern CALLBACK16 BiosContext; +#define RegisterBiosInt32(IntNumber, IntHandler) \ +do { \ + BiosContext.NextOffset += RegisterInt32(MAKELONG(BiosContext.NextOffset, \ + BiosContext.Segment), \ + (IntNumber), (IntHandler), NULL); \ +} while(0); + +VOID EnableHwIRQ(UCHAR hwirq, EMULATOR_INT32_PROC func); +VOID PicIRQComplete(LPWORD Stack); + +#endif // _BIOS32P_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/bios/bios32/kbdbios32.c b/subsystems/ntvdm/bios/bios32/kbdbios32.c new file mode 100644 index 00000000000..716af1f50d7 --- /dev/null +++ b/subsystems/ntvdm/bios/bios32/kbdbios32.c @@ -0,0 +1,294 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: kbdbios32.c + * PURPOSE: VDM Keyboard 32-bit BIOS + * PROGRAMMERS: Aleksandar Andrejevic + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "callback.h" + +#include "kbdbios32.h" +#include "../kbdbios.h" +#include "bios32p.h" + +#include "io.h" +#include "hardware/ps2.h" + +/* PRIVATE VARIABLES **********************************************************/ + +static BYTE BiosKeyboardMap[256]; + +/* PRIVATE FUNCTIONS **********************************************************/ + +static BOOLEAN BiosKbdBufferPush(WORD Data) +{ + /* Get the location of the element after the tail */ + WORD NextElement = Bda->KeybdBufferTail + sizeof(WORD); + + /* Wrap it around if it's at or beyond the end */ + if (NextElement >= Bda->KeybdBufferEnd) NextElement = Bda->KeybdBufferStart; + + /* If it's full, fail */ + if (NextElement == Bda->KeybdBufferHead) return FALSE; + + /* Put the value in the queue */ + *((LPWORD)((ULONG_PTR)Bda + Bda->KeybdBufferTail)) = Data; + Bda->KeybdBufferTail += sizeof(WORD); + + /* Check if we are at, or have passed, the end of the buffer */ + if (Bda->KeybdBufferTail >= Bda->KeybdBufferEnd) + { + /* Return it to the beginning */ + Bda->KeybdBufferTail = Bda->KeybdBufferStart; + } + + /* Return success */ + return TRUE; +} + +static BOOLEAN BiosKbdBufferTop(LPWORD Data) +{ + /* If it's empty, fail */ + if (Bda->KeybdBufferHead == Bda->KeybdBufferTail) return FALSE; + + /* Otherwise, get the value and return success */ + *Data = *((LPWORD)((ULONG_PTR)Bda + Bda->KeybdBufferHead)); + + return TRUE; +} + +static BOOLEAN BiosKbdBufferPop(VOID) +{ + /* If it's empty, fail */ + if (Bda->KeybdBufferHead == Bda->KeybdBufferTail) return FALSE; + + /* Remove the value from the queue */ + Bda->KeybdBufferHead += sizeof(WORD); + + /* Check if we are at, or have passed, the end of the buffer */ + if (Bda->KeybdBufferHead >= Bda->KeybdBufferEnd) + { + /* Return it to the beginning */ + Bda->KeybdBufferHead = Bda->KeybdBufferStart; + } + + /* Return success */ + return TRUE; +} + +static WORD BiosPeekCharacter(VOID) +{ + WORD CharacterData = 0; + + /* Get the key from the queue, but don't remove it */ + if (BiosKbdBufferTop(&CharacterData)) return CharacterData; + else return 0xFFFF; +} + +static WORD BiosGetCharacter(VOID) +{ + WORD CharacterData = 0; + + /* Check if there is a key available, and if so, remove it from the queue */ + if (BiosKbdBufferTop(&CharacterData)) BiosKbdBufferPop(); + else CharacterData = 0xFFFF; + + return CharacterData; +} + +static VOID WINAPI BiosKeyboardService(LPWORD Stack) +{ + switch (getAH()) + { + /* Wait for keystroke and read */ + case 0x00: + /* Wait for extended keystroke and read */ + case 0x10: // FIXME: Temporarily do the same as INT 16h, 00h + { + /* Read the character (and wait if necessary) */ + WORD Character = BiosGetCharacter(); + + if (Character == 0xFFFF) + { + /* No key available. Set the handler CF to repeat the BOP */ + setCF(1); + break; + } + + setAX(Character); + + break; + } + + /* Get keystroke status */ + case 0x01: + /* Get extended keystroke status */ + case 0x11: // FIXME: Temporarily do the same as INT 16h, 01h + { + WORD Character = BiosPeekCharacter(); + + if (Character != 0xFFFF) + { + /* There is a character, clear ZF and return it */ + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_ZF; + setAX(Character); + } + else + { + /* No character, set ZF */ + Stack[STACK_FLAGS] |= EMULATOR_FLAG_ZF; + } + + break; + } + + /* Get shift status */ + case 0x02: + { + /* Return the lower byte of the keyboard shift status word */ + setAL(LOBYTE(Bda->KeybdShiftFlags)); + break; + } + + /* Reserved */ + case 0x04: + { + DPRINT1("BIOS Function INT 16h, AH = 0x04 is RESERVED\n"); + break; + } + + /* Push keystroke */ + case 0x05: + { + /* Return 0 if success, 1 if failure */ + setAL(BiosKbdBufferPush(getCX()) == FALSE); + break; + } + + /* Get extended shift status */ + case 0x12: + { + /* + * Be careful! The returned word is similar to Bda->KeybdShiftFlags + * but the high byte is organized differently: + * the bytes 2 and 3 of the high byte are not the same... + */ + WORD KeybdShiftFlags = (Bda->KeybdShiftFlags & 0xF3FF); + + /* Return the extended keyboard shift status word */ + setAX(KeybdShiftFlags); + break; + } + + default: + { + DPRINT1("BIOS Function INT 16h, AH = 0x%02X NOT IMPLEMENTED\n", + getAH()); + } + } +} + +// Keyboard IRQ 1 +static VOID WINAPI BiosKeyboardIrq(LPWORD Stack) +{ + BYTE ScanCode, VirtualKey; + WORD Character; + + /* Get the scan code and virtual key code */ + ScanCode = IOReadB(PS2_DATA_PORT); + VirtualKey = MapVirtualKey(ScanCode & 0x7F, MAPVK_VSC_TO_VK); + + /* Check if this is a key press or release */ + if (!(ScanCode & (1 << 7))) + { + /* Key press */ + if (VirtualKey == VK_NUMLOCK || + VirtualKey == VK_CAPITAL || + VirtualKey == VK_SCROLL || + VirtualKey == VK_INSERT) + { + /* For toggle keys, toggle the lowest bit in the keyboard map */ + BiosKeyboardMap[VirtualKey] ^= ~(1 << 0); + } + + /* Set the highest bit */ + BiosKeyboardMap[VirtualKey] |= (1 << 7); + + /* Find out which character this is */ + Character = 0; + if (ToAscii(VirtualKey, ScanCode, BiosKeyboardMap, &Character, 0) == 0) + { + /* Not ASCII */ + Character = 0; + } + + /* Push it onto the BIOS keyboard queue */ + BiosKbdBufferPush(MAKEWORD(Character, ScanCode)); + } + else + { + /* Key release, unset the highest bit */ + BiosKeyboardMap[VirtualKey] &= ~(1 << 7); + } + + /* Clear the keyboard flags */ + Bda->KeybdShiftFlags = 0; + + /* Set the appropriate flags based on the state */ + if (BiosKeyboardMap[VK_RSHIFT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_RSHIFT; + if (BiosKeyboardMap[VK_LSHIFT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_LSHIFT; + if (BiosKeyboardMap[VK_CONTROL] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_CTRL; + if (BiosKeyboardMap[VK_MENU] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_ALT; + if (BiosKeyboardMap[VK_SCROLL] & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_SCROLL_ON; + if (BiosKeyboardMap[VK_NUMLOCK] & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_NUMLOCK_ON; + if (BiosKeyboardMap[VK_CAPITAL] & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_CAPSLOCK_ON; + if (BiosKeyboardMap[VK_INSERT] & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_INSERT_ON; + if (BiosKeyboardMap[VK_RMENU] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_RALT; + if (BiosKeyboardMap[VK_LMENU] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_LALT; + if (BiosKeyboardMap[VK_SNAPSHOT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_SYSRQ; + if (BiosKeyboardMap[VK_PAUSE] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_PAUSE; + if (BiosKeyboardMap[VK_SCROLL] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_SCROLL; + if (BiosKeyboardMap[VK_NUMLOCK] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_NUMLOCK; + if (BiosKeyboardMap[VK_CAPITAL] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_CAPSLOCK; + if (BiosKeyboardMap[VK_INSERT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_INSERT; + + PicIRQComplete(Stack); +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +BOOLEAN KbdBios32Initialize(VOID) +{ + /* Initialize the common Keyboard BIOS Support Library */ + if (!KbdBiosInitialize()) return FALSE; + + /* Initialize the BDA */ + Bda->KeybdBufferStart = FIELD_OFFSET(BIOS_DATA_AREA, KeybdBuffer); + Bda->KeybdBufferEnd = Bda->KeybdBufferStart + BIOS_KBD_BUFFER_SIZE * sizeof(WORD); + Bda->KeybdBufferHead = Bda->KeybdBufferTail = 0; + + /* Register the BIOS 32-bit Interrupts */ + + /* Initialize software vector handlers */ + RegisterBiosInt32(BIOS_KBD_INTERRUPT, BiosKeyboardService); + + /* Set up the HW vector interrupts */ + EnableHwIRQ(1, BiosKeyboardIrq); + // EnableHwIRQ(12, BiosMouseIrq); + + return TRUE; +} + +VOID KbdBios32Cleanup(VOID) +{ + /* Cleanup the common Keyboard BIOS Support Library */ + KbdBiosCleanup(); +} + +/* EOF */ diff --git a/subsystems/ntvdm/bios/bios32/kbdbios32.h b/subsystems/ntvdm/bios/bios32/kbdbios32.h new file mode 100644 index 00000000000..b5f9c145a12 --- /dev/null +++ b/subsystems/ntvdm/bios/bios32/kbdbios32.h @@ -0,0 +1,46 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: kbdbios32.h + * PURPOSE: VDM Keyboard 32-bit BIOS + * PROGRAMMERS: Aleksandar Andrejevic + */ + +#ifndef _KBDBIOS32_H_ +#define _KBDBIOS32_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" + +/* DEFINES ********************************************************************/ + +// #define BIOS_KBD_INTERRUPT 0x16 + +#define BIOS_KBD_BUFFER_SIZE 16 + +#define BDA_KBDFLAG_RSHIFT (1 << 0) +#define BDA_KBDFLAG_LSHIFT (1 << 1) +#define BDA_KBDFLAG_CTRL (1 << 2) +#define BDA_KBDFLAG_ALT (1 << 3) +#define BDA_KBDFLAG_SCROLL_ON (1 << 4) +#define BDA_KBDFLAG_NUMLOCK_ON (1 << 5) +#define BDA_KBDFLAG_CAPSLOCK_ON (1 << 6) +#define BDA_KBDFLAG_INSERT_ON (1 << 7) +#define BDA_KBDFLAG_RALT (1 << 8) +#define BDA_KBDFLAG_LALT (1 << 9) +#define BDA_KBDFLAG_SYSRQ (1 << 10) +#define BDA_KBDFLAG_PAUSE (1 << 11) +#define BDA_KBDFLAG_SCROLL (1 << 12) +#define BDA_KBDFLAG_NUMLOCK (1 << 13) +#define BDA_KBDFLAG_CAPSLOCK (1 << 14) +#define BDA_KBDFLAG_INSERT (1 << 15) + +/* FUNCTIONS ******************************************************************/ + +BOOLEAN KbdBios32Initialize(VOID); +VOID KbdBios32Cleanup(VOID); + +#endif // _KBDBIOS32_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/bios/bios32/vidbios32.c b/subsystems/ntvdm/bios/bios32/vidbios32.c new file mode 100644 index 00000000000..732776c2db6 --- /dev/null +++ b/subsystems/ntvdm/bios/bios32/vidbios32.c @@ -0,0 +1,41 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: vidbios32.c + * PURPOSE: VDM Video 32-bit BIOS + * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr) + * + * NOTE: All of the real code is in bios/vidbios.c + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "callback.h" + +#include "vidbios32.h" +#include "../vidbios.h" +#include "bios32p.h" + +/* PUBLIC FUNCTIONS ***********************************************************/ + +BOOLEAN VidBios32Initialize(VOID) +{ + /* Initialize the common Video BIOS Support Library */ + if (!VidBiosInitialize()) return FALSE; + + /* Register the BIOS 32-bit Interrupts */ + RegisterBiosInt32(BIOS_VIDEO_INTERRUPT, VidBiosVideoService); + + return TRUE; +} + +VOID VidBios32Cleanup(VOID) +{ + /* Cleanup the common Video BIOS Support Library */ + VidBiosCleanup(); +} + +/* EOF */ diff --git a/subsystems/ntvdm/bios/bios32/vidbios32.h b/subsystems/ntvdm/bios/bios32/vidbios32.h new file mode 100644 index 00000000000..46b853bb61e --- /dev/null +++ b/subsystems/ntvdm/bios/bios32/vidbios32.h @@ -0,0 +1,29 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: vidbios32.h + * PURPOSE: VDM Video 32-bit BIOS + * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr) + * + * NOTE: All of the real code is in bios/vidbios.c + */ + +#ifndef _VIDBIOS32_H_ +#define _VIDBIOS32_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" + +/* DEFINES ********************************************************************/ + +// #define BIOS_VIDEO_INTERRUPT 0x10 + +/* FUNCTIONS ******************************************************************/ + +BOOLEAN VidBios32Initialize(VOID); +VOID VidBios32Cleanup(VOID); + +#endif // _VIDBIOS32_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/bios/kbdbios.c b/subsystems/ntvdm/bios/kbdbios.c new file mode 100644 index 00000000000..72550869f9d --- /dev/null +++ b/subsystems/ntvdm/bios/kbdbios.c @@ -0,0 +1,51 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: kbdbios.c + * PURPOSE: VDM Keyboard BIOS Support Library + * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "callback.h" +#include "bop.h" + +#include "bios.h" +// #include "kbdbios.h" + +/* DEFINES ********************************************************************/ + +/* BOP Identifiers */ +#define BOP_KBD_IRQ 0x09 +#define BOP_KBD_INT 0x16 + +/* PUBLIC FUNCTIONS ***********************************************************/ + +static VOID WINAPI KbdBiosIRQ(LPWORD Stack) +{ + DPRINT1("KbdBiosIRQ is UNIMPLEMENTED\n"); +} + +static VOID WINAPI KbdBiosINT(LPWORD Stack) +{ + DPRINT1("KbdBiosINT is UNIMPLEMENTED\n"); +} + +BOOLEAN KbdBiosInitialize(VOID) +{ + /* Register the BIOS support BOPs */ + RegisterBop(BOP_KBD_IRQ, KbdBiosIRQ); + RegisterBop(BOP_KBD_INT, KbdBiosINT); + + return TRUE; +} + +VOID KbdBiosCleanup(VOID) +{ +} + +/* EOF */ diff --git a/subsystems/ntvdm/bios/kbdbios.h b/subsystems/ntvdm/bios/kbdbios.h new file mode 100644 index 00000000000..1d8798ac763 --- /dev/null +++ b/subsystems/ntvdm/bios/kbdbios.h @@ -0,0 +1,29 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: kbdbios.h + * PURPOSE: VDM Keyboard BIOS Support Library + * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +#ifndef _KBDBIOS_H_ +#define _KBDBIOS_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" + +/* DEFINES ********************************************************************/ + +#define BIOS_KBD_INTERRUPT 0x16 + +#define BIOS_KBD_BUFFER_SIZE 16 + +/* FUNCTIONS ******************************************************************/ + +BOOLEAN KbdBiosInitialize(VOID); +VOID KbdBiosCleanup(VOID); + +#endif // _KBDBIOS_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/bios/rom.c b/subsystems/ntvdm/bios/rom.c new file mode 100644 index 00000000000..e4dbc6bf5f6 --- /dev/null +++ b/subsystems/ntvdm/bios/rom.c @@ -0,0 +1,227 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: rom.c + * PURPOSE: ROM Support Functions + * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "callback.h" +#include "utils.h" + +#include "rom.h" + +/* PRIVATE FUNCTIONS **********************************************************/ + +static HANDLE +OpenRomFile(IN PCSTR RomFileName, + OUT PULONG RomSize OPTIONAL) +{ + HANDLE hRomFile; + ULONG ulRomSize = 0; + + /* Open the ROM image file */ + hRomFile = FileOpen(RomFileName, &ulRomSize); + + /* If we failed, bail out */ + if (hRomFile == NULL) return NULL; + + /* + * The size of the ROM image file is at most 256kB. For instance, + * the SeaBIOS image, which includes also expansion ROMs inside it, + * covers the range C000:0000 to F000:FFFF . + */ + if (ulRomSize > 0x40000) + { + /* We failed, bail out */ + DPRINT1("ROM image size 0x%lx too large, expected at most 0x40000 (256kB)", ulRomSize); + FileClose(hRomFile); + return NULL; + } + + /* Success, return file handle and size if needed */ + if (RomSize) *RomSize = ulRomSize; + return hRomFile; +} + +static BOOLEAN +LoadRomFileByHandle(IN HANDLE RomFileHandle, + IN PVOID RomLocation, + IN ULONG RomSize, + OUT PULONG BytesRead) +{ + /* + * The size of the ROM image file is at most 256kB. For instance, + * the SeaBIOS image, which includes also expansion ROMs inside it, + * covers the range C000:0000 to F000:FFFF . + */ + if (RomSize > 0x40000) + { + DPRINT1("ROM image size 0x%lx too large, expected at most 0x40000 (256kB)", RomSize); + return FALSE; + } + + /* Attempt to load the ROM image file into memory */ + return FileLoadByHandle(RomFileHandle, + REAL_TO_PHYS(RomLocation), + RomSize, + BytesRead); +} + +static UCHAR +ComputeChecksum(IN ULONG RomLocation, + IN ULONG RomSize) +{ + ULONG RomLastAddress = RomLocation + RomSize; + UCHAR Sum = 0x00; // Using a UCHAR guarantees that we wrap at 0xFF i.e. we do a sum modulo 0x100. + + while (RomLocation < RomLastAddress) + { + Sum += *(PUCHAR)REAL_TO_PHYS(RomLocation); + ++RomLocation; + } + + return Sum; +} + +static VOID +InitRomRange(IN PCALLBACK16 Context, + IN ULONG Start, + IN ULONG End, + IN ULONG Increment) +{ + ULONG Address, AddressBoot; + ULONG RomSize; + UCHAR Checksum; + + for (Address = Start; Address < End; Address += Increment) + { + /* Does the ROM have a valid signature? */ + if (*(PUSHORT)REAL_TO_PHYS(Address) == OPTION_ROM_SIGNATURE) + { + /* Check the control sum of the ROM */ + + /* + * If this is an adapter ROM (Start: C8000, End: E0000), its + * reported size is stored in byte 2 of the ROM. + * + * If this is an expansion ROM (Start: E0000, End: F0000), + * its real length is 64kB. + */ + RomSize = *(PUCHAR)REAL_TO_PHYS(Address + 2) * 512; + if (Address >= 0xE0000) RomSize = 0x10000; + + Checksum = ComputeChecksum(Address, RomSize); + if (Checksum == 0x00) + { + AddressBoot = Address + 3; + DPRINT1("Going to run @ address 0x%p\n", AddressBoot); + + AddressBoot = MAKELONG((AddressBoot & 0xFFFF), (AddressBoot & 0xF0000) >> 4); + // setDS((Address & 0xF0000) >> 4); + setDS((Address & 0xFF000) >> 4); + RunCallback16(Context, AddressBoot); + // Call16((AddressBoot & 0xF0000) >> 4, (AddressBoot & 0xFFFF)); + + DPRINT1("Rom @ address 0x%p initialized\n", Address); + } + else + { + DPRINT1("Rom @ address 0x%p has invalid checksum of 0x%02x\n", Address, Checksum); + } + } + } +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +BOOLEAN +LoadBios(IN PCSTR BiosFileName, + OUT PVOID* BiosLocation OPTIONAL, + OUT PULONG BiosSize OPTIONAL) +{ + BOOLEAN Success; + HANDLE hBiosFile; + ULONG ulBiosSize = 0; + PVOID pBiosLocation; + + /* Open the BIOS image file */ + hBiosFile = OpenRomFile(BiosFileName, &ulBiosSize); + + /* If we failed, bail out */ + if (hBiosFile == NULL) return FALSE; + + /* BIOS location needs to be aligned on 32-bit boundary */ + // (PVOID)((ULONG_PTR)BaseAddress + ROM_AREA_END + 1 - ulBiosSize) + pBiosLocation = MEM_ALIGN_DOWN(TO_LINEAR(0xF000, 0xFFFF) + 1 - ulBiosSize, sizeof(ULONG)); + + /* Attempt to load the BIOS image file into memory */ + Success = LoadRomFileByHandle(hBiosFile, + pBiosLocation, + ulBiosSize, + &ulBiosSize); + DPRINT1("BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError()); + + /* Close the BIOS image file */ + FileClose(hBiosFile); + + /* In case of success, return BIOS location and size if needed */ + if (Success) + { + if (BiosLocation) *BiosLocation = pBiosLocation; + if (BiosSize) *BiosSize = ulBiosSize; + } + + return Success; +} + +BOOLEAN +LoadRom(IN PCSTR RomFileName, + IN PVOID RomLocation, + OUT PULONG RomSize OPTIONAL) +{ + BOOLEAN Success; + HANDLE hRomFile; + ULONG ulRomSize = 0; + + /* Open the ROM image file */ + hRomFile = OpenRomFile(RomFileName, &ulRomSize); + + /* If we failed, bail out */ + if (hRomFile == NULL) return FALSE; + + /* Attempt to load the ROM image file into memory */ + Success = LoadRomFileByHandle(hRomFile, + RomLocation, + ulRomSize, + &ulRomSize); + DPRINT1("ROM loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError()); + + /* Close the ROM image file and return */ + FileClose(hRomFile); + + /* In case of success, return ROM size if needed */ + if (Success) + { + if (RomSize) *RomSize = ulRomSize; + } + + return Success; +} + +VOID +SearchAndInitRoms(IN PCALLBACK16 Context) +{ + /* Adapters ROMs -- Start: C8000, End: E0000, 2kB blocks */ + InitRomRange(Context, 0xC8000, 0xE0000, 0x0800); + + /* Expansion ROM -- Start: E0000, End: F0000, 64kB block */ + InitRomRange(Context, 0xE0000, 0xEFFFF, 0x10000); +} + +/* EOF */ diff --git a/subsystems/ntvdm/bios/rom.h b/subsystems/ntvdm/bios/rom.h new file mode 100644 index 00000000000..01f95e85dc8 --- /dev/null +++ b/subsystems/ntvdm/bios/rom.h @@ -0,0 +1,40 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: rom.h + * PURPOSE: ROM Support Functions + * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +#ifndef _ROM_H_ +#define _ROM_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" + +/* DEFINES ********************************************************************/ + +#define ROM_AREA_START 0xE0000 +#define ROM_AREA_END 0xFFFFF + +#define OPTION_ROM_SIGNATURE 0xAA55 + +/* FUNCTIONS ******************************************************************/ + +BOOLEAN +LoadBios(IN PCSTR BiosFileName, + OUT PVOID* BiosLocation OPTIONAL, + OUT PULONG BiosSize OPTIONAL); + +BOOLEAN +LoadRom(IN PCSTR RomFileName, + IN PVOID RomLocation, + OUT PULONG RomSize OPTIONAL); + +VOID +SearchAndInitRoms(IN PCALLBACK16 Context); + +#endif // _ROM_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/bios/vidbios.c b/subsystems/ntvdm/bios/vidbios.c new file mode 100644 index 00000000000..41d22d3b1a6 --- /dev/null +++ b/subsystems/ntvdm/bios/vidbios.c @@ -0,0 +1,1600 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: vidbios.c + * PURPOSE: VDM Video BIOS Support Library + * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "callback.h" +#include "bop.h" + +#include "bios.h" +// #include "vidbios.h" + +#include "io.h" +#include "hardware/vga.h" + +/* DEFINES ********************************************************************/ + +/* BOP Identifiers */ +#define BOP_VIDEO_INT 0x10 + +/* MACROS *********************************************************************/ + +// +// These macros are defined for ease-of-use of some VGA I/O ports +// whose addresses depend whether we are in Monochrome or Colour mode. +// +#define VGA_INSTAT1_READ Bda->CrtBasePort + 6 // VGA_INSTAT1_READ_MONO or VGA_INSTAT1_READ_COLOR +#define VGA_CRTC_INDEX Bda->CrtBasePort // VGA_CRTC_INDEX_MONO or VGA_CRTC_INDEX_COLOR +#define VGA_CRTC_DATA Bda->CrtBasePort + 1 // VGA_CRTC_DATA_MONO or VGA_CRTC_DATA_COLOR + +/* PRIVATE VARIABLES **********************************************************/ + +/* + * VGA Register Configurations for BIOS Video Modes + * The configurations come from DOSBox. + */ +static VGA_REGISTERS VideoMode_40x25_text = +{ + /* Miscellaneous Register */ + 0x67, + + /* Sequencer Registers */ + {0x00, 0x08, 0x03, 0x00, 0x07}, + + /* CRTC Registers */ + {0x2D, 0x27, 0x28, 0x90, 0x2B, 0xA0, 0xBF, 0x1F, 0x00, 0x4F, 0x0D, 0x0E, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x1F, 0x96, 0xB9, 0xA3, + 0xFF}, + + /* GC Registers */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x0F, 0xFF}, + + /* AC Registers */ + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B, + 0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x00, 0x0F, 0x08, 0x00} +}; + +static VGA_REGISTERS VideoMode_80x25_text = +{ + /* Miscellaneous Register */ + 0x67, + + /* Sequencer Registers */ + {0x00, 0x00, 0x03, 0x00, 0x07}, + + /* CRTC Registers */ + {0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81, 0xBF, 0x1F, 0x00, 0x4F, 0x0D, 0x0E, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x1F, 0x96, 0xB9, 0xA3, + 0xFF}, + + /* GC Registers */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x0F, 0xFF}, + + /* AC Registers */ + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B, + 0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x00, 0x0F, 0x08, 0x00} +}; + +static VGA_REGISTERS VideoMode_320x200_4color = +{ + /* Miscellaneous Register */ + 0x63, + + /* Sequencer Registers */ + {0x00, 0x09, 0x03, 0x00, 0x02}, + + /* CRTC Registers */ + {0x2D, 0x27, 0x28, 0x90, 0x2B, 0x80, 0xBF, 0x1F, 0x00, 0xC1, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x00, 0x96, 0xB9, 0xA2, + 0xFF}, + + /* GC Registers */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0F, 0x0F, 0xFF}, + + /* AC Registers */ + {0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x0F, 0x00, 0x00} +}; + +static VGA_REGISTERS VideoMode_640x200_2color = +{ + /* Miscellaneous Register */ + 0x63, + + /* Sequencer Registers */ + {0x00, 0x09, 0x0F, 0x00, 0x02}, + + /* CRTC Registers */ + {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0xC1, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x00, 0x96, 0xB9, 0xC2, + 0xFF}, + + /* GC Registers */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0xFF}, + + /* AC Registers */ + {0x00, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x01, 0x00, 0x01, 0x00, 0x00} +}; + +static VGA_REGISTERS VideoMode_320x200_16color = +{ + /* Miscellaneous Register */ + 0x63, + + /* Sequencer Registers */ + {0x00, 0x09, 0x0F, 0x00, 0x02}, + + /* CRTC Registers */ + {0x2D, 0x27, 0x28, 0x90, 0x2B, 0x80, 0xBF, 0x1F, 0x00, 0xC0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x00, 0x96, 0xB9, 0xE3, + 0xFF}, + + /* GC Registers */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF}, + + /* AC Registers */ +// {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B, +// 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00} + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x0F, 0x00, 0x00} +}; + +static VGA_REGISTERS VideoMode_640x200_16color = +{ + /* Miscellaneous Register */ + 0x63, + + /* Sequencer Registers */ + {0x00, 0x01, 0x0F, 0x00, 0x02}, + + /* CRTC Registers */ + {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0xC0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x00, 0x96, 0xB9, 0xE3, + 0xFF}, + + /* GC Registers */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF}, + + /* AC Registers */ +// {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B, +// 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00} + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x0F, 0x00, 0x00} +}; + +static VGA_REGISTERS VideoMode_640x350_16color = +{ + /* Miscellaneous Register */ + 0xA3, + + /* Sequencer Registers */ + {0x00, 0x01, 0x0F, 0x00, 0x02}, + + /* CRTC Registers */ + {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x83, 0x85, 0x5D, 0x28, 0x0F, 0x63, 0xBA, 0xE3, + 0xFF}, + + /* GC Registers */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF}, + + /* AC Registers */ + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B, + 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00} +}; + +static VGA_REGISTERS VideoMode_640x480_2color = +{ + /* Miscellaneous Register */ + 0xE3, + + /* Sequencer Registers */ + {0x00, 0x01, 0x0F, 0x00, 0x02}, + + /* CRTC Registers */ + {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xC3, + 0xFF}, + + /* GC Registers */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF}, + + /* AC Registers */ + {0x00, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00} +}; + +static VGA_REGISTERS VideoMode_640x480_16color = +{ + /* Miscellaneous Register */ + 0xE3, + + /* Sequencer Registers */ + {0x00, 0x01, 0x0F, 0x00, 0x02}, + + /* CRTC Registers */ + {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xE3, + 0xFF}, + + /* GC Registers */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF}, + + /* AC Registers */ + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B, + 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00} +}; + +static VGA_REGISTERS VideoMode_320x200_256color = +{ + /* Miscellaneous Register */ + 0x63, + + /* Sequencer Registers */ + {0x00, 0x01, 0x0F, 0x00, 0x0E}, + + /* CRTC Registers */ + {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x41, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3, + 0xFF}, + + /* GC Registers */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF}, + + /* AC Registers */ + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00} +}; + +/* See http://wiki.osdev.org/Drawing_In_Protected_Mode#Locating_Video_Memory */ +static PVGA_REGISTERS VideoModes[BIOS_MAX_VIDEO_MODE + 1] = +{ + &VideoMode_40x25_text, /* Mode 00h */ // 16 color (mono) + &VideoMode_40x25_text, /* Mode 01h */ // 16 color + &VideoMode_80x25_text, /* Mode 02h */ // 16 color (mono) + &VideoMode_80x25_text, /* Mode 03h */ // 16 color + &VideoMode_320x200_4color, /* Mode 04h */ // CGA 4 color + &VideoMode_320x200_4color, /* Mode 05h */ // CGA same (m) + &VideoMode_640x200_2color, /* Mode 06h */ // CGA 640*200 2 color + NULL, /* Mode 07h */ // MDA monochrome text 80*25 + NULL, /* Mode 08h */ // PCjr + NULL, /* Mode 09h */ // PCjr + NULL, /* Mode 0Ah */ // PCjr + NULL, /* Mode 0Bh */ // Reserved + NULL, /* Mode 0Ch */ // Reserved + &VideoMode_320x200_16color, /* Mode 0Dh */ // EGA 320*200 16 color + &VideoMode_640x200_16color, /* Mode 0Eh */ // EGA 640*200 16 color + NULL, /* Mode 0Fh */ // EGA 640*350 mono + &VideoMode_640x350_16color, /* Mode 10h */ // EGA 640*350 HiRes 16 color + &VideoMode_640x480_2color, /* Mode 11h */ // VGA 640*480 mono + &VideoMode_640x480_16color, /* Mode 12h */ // VGA + &VideoMode_320x200_256color, /* Mode 13h */ // VGA +}; + +// FIXME: Are they computable with the previous data ?? +// Values taken from DOSBox. +static WORD VideoModePageSize[BIOS_MAX_VIDEO_MODE + 1] = +{ + 0x0800, 0x0800, 0x1000, 0x1000, + 0x4000, 0x4000, 0x4000, 0x1000, + 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x2000, 0x4000, 0x8000, + 0x8000, 0xA000, 0xA000, 0x2000 +}; + +/* + * BIOS Mode Palettes + * + * Many people have different versions of those palettes + * (e.g. DOSBox, http://www.brokenthorn.com/Resources/OSDevVid2.html , + * etc...) A choice should be made at some point. + */ + +// This is the same as EgaPalette__HiRes +static CONST COLORREF TextPalette[VGA_MAX_COLORS / 4] = +{ + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA), + RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0xAA, 0x00), RGB(0xAA, 0xAA, 0xAA), + RGB(0x00, 0x00, 0x55), RGB(0x00, 0x00, 0xFF), RGB(0x00, 0xAA, 0x55), RGB(0x00, 0xAA, 0xFF), + RGB(0xAA, 0x00, 0x55), RGB(0xAA, 0x00, 0xFF), RGB(0xAA, 0xAA, 0x55), RGB(0xAA, 0xAA, 0xFF), + + RGB(0x00, 0x55, 0x00), RGB(0x00, 0x55, 0xAA), RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0xAA), + RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0x55, 0xAA), RGB(0xAA, 0xFF, 0x00), RGB(0xAA, 0xFF, 0xAA), + RGB(0x00, 0x55, 0x55), RGB(0x00, 0x55, 0xFF), RGB(0x00, 0xFF, 0x55), RGB(0x00, 0xFF, 0xFF), + RGB(0xAA, 0x55, 0x55), RGB(0xAA, 0x55, 0xFF), RGB(0xAA, 0xFF, 0x55), RGB(0xAA, 0xFF, 0xFF), + + + RGB(0x55, 0x00, 0x00), RGB(0x55, 0x00, 0xAA), RGB(0x55, 0xAA, 0x00), RGB(0x55, 0xAA, 0xAA), + RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x00, 0xAA), RGB(0xFF, 0xAA, 0x00), RGB(0xFF, 0xAA, 0xAA), + RGB(0x55, 0x00, 0x55), RGB(0x55, 0x00, 0xFF), RGB(0x55, 0xAA, 0x55), RGB(0x55, 0xAA, 0xFF), + RGB(0xFF, 0x00, 0x55), RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0xAA, 0x55), RGB(0xFF, 0xAA, 0xFF), + + RGB(0x55, 0x55, 0x00), RGB(0x55, 0x55, 0xAA), RGB(0x55, 0xFF, 0x00), RGB(0x55, 0xFF, 0xAA), + RGB(0xFF, 0x55, 0x00), RGB(0xFF, 0x55, 0xAA), RGB(0xFF, 0xFF, 0x00), RGB(0xFF, 0xFF, 0xAA), + RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF), + RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF) +}; + +// Unused at the moment +static CONST COLORREF mtext_palette[64] = +{ + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), + RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), + RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), + RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), + RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), + + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), + RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), + RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), + RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), + RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF) +}; + +// Unused at the moment +static CONST COLORREF mtext_s3_palette[64] = +{ + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), + RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), + RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), + RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), + RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), + RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), + RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), + + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), + RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), + RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), + RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), + RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), + RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), + RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF) +}; + +// Unused at the moment +static CONST COLORREF CgaPalette[16] = +{ + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA), + RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA), + RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF), + RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF) +}; + +// Unused at the moment +static CONST COLORREF CgaPalette2[VGA_MAX_COLORS / 4] = +{ + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA), + RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA), + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA), + RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA), + RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF), + RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF), + RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF), + RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF), + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA), + RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA), + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA), + RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA), + RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF), + RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF), + RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF), + RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF) +}; + +static CONST COLORREF EgaPalette___16ColorFixed_DOSBox[VGA_MAX_COLORS / 4] = +{ + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA), + RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA), + + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA), + RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA), + + + RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF), + RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF), + + RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF), + RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF), + + + + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA), + RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA), + + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA), + RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA), + + + RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF), + RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF), + + RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF), + RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF) +}; + +// This is the same as TextPalette +static CONST COLORREF EgaPalette__HiRes[VGA_MAX_COLORS / 4] = +{ + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA), + RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0xAA, 0x00), RGB(0xAA, 0xAA, 0xAA), + RGB(0x00, 0x00, 0x55), RGB(0x00, 0x00, 0xFF), RGB(0x00, 0xAA, 0x55), RGB(0x00, 0xAA, 0xFF), + RGB(0xAA, 0x00, 0x55), RGB(0xAA, 0x00, 0xFF), RGB(0xAA, 0xAA, 0x55), RGB(0xAA, 0xAA, 0xFF), + + RGB(0x00, 0x55, 0x00), RGB(0x00, 0x55, 0xAA), RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0xAA), + RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0x55, 0xAA), RGB(0xAA, 0xFF, 0x00), RGB(0xAA, 0xFF, 0xAA), + RGB(0x00, 0x55, 0x55), RGB(0x00, 0x55, 0xFF), RGB(0x00, 0xFF, 0x55), RGB(0x00, 0xFF, 0xFF), + RGB(0xAA, 0x55, 0x55), RGB(0xAA, 0x55, 0xFF), RGB(0xAA, 0xFF, 0x55), RGB(0xAA, 0xFF, 0xFF), + + + RGB(0x55, 0x00, 0x00), RGB(0x55, 0x00, 0xAA), RGB(0x55, 0xAA, 0x00), RGB(0x55, 0xAA, 0xAA), + RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x00, 0xAA), RGB(0xFF, 0xAA, 0x00), RGB(0xFF, 0xAA, 0xAA), + RGB(0x55, 0x00, 0x55), RGB(0x55, 0x00, 0xFF), RGB(0x55, 0xAA, 0x55), RGB(0x55, 0xAA, 0xFF), + RGB(0xFF, 0x00, 0x55), RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0xAA, 0x55), RGB(0xFF, 0xAA, 0xFF), + + RGB(0x55, 0x55, 0x00), RGB(0x55, 0x55, 0xAA), RGB(0x55, 0xFF, 0x00), RGB(0x55, 0xFF, 0xAA), + RGB(0xFF, 0x55, 0x00), RGB(0xFF, 0x55, 0xAA), RGB(0xFF, 0xFF, 0x00), RGB(0xFF, 0xFF, 0xAA), + RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF), + RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF) +}; + +#define USE_REACTOS_COLORS +// #define USE_DOSBOX_COLORS + +/* + * Same palette as the default one 'VgaDefaultPalette' in vga.c + */ +#if defined(USE_REACTOS_COLORS) + +// ReactOS colors +static CONST COLORREF VgaPalette[VGA_MAX_COLORS] = +{ + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA), + RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA), + RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF), + RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF), + RGB(0x00, 0x00, 0x00), RGB(0x10, 0x10, 0x10), RGB(0x20, 0x20, 0x20), RGB(0x35, 0x35, 0x35), + RGB(0x45, 0x45, 0x45), RGB(0x55, 0x55, 0x55), RGB(0x65, 0x65, 0x65), RGB(0x75, 0x75, 0x75), + RGB(0x8A, 0x8A, 0x8A), RGB(0x9A, 0x9A, 0x9A), RGB(0xAA, 0xAA, 0xAA), RGB(0xBA, 0xBA, 0xBA), + RGB(0xCA, 0xCA, 0xCA), RGB(0xDF, 0xDF, 0xDF), RGB(0xEF, 0xEF, 0xEF), RGB(0xFF, 0xFF, 0xFF), + RGB(0x00, 0x00, 0xFF), RGB(0x41, 0x00, 0xFF), RGB(0x82, 0x00, 0xFF), RGB(0xBE, 0x00, 0xFF), + RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0x00, 0xBE), RGB(0xFF, 0x00, 0x82), RGB(0xFF, 0x00, 0x41), + RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x41, 0x00), RGB(0xFF, 0x82, 0x00), RGB(0xFF, 0xBE, 0x00), + RGB(0xFF, 0xFF, 0x00), RGB(0xBE, 0xFF, 0x00), RGB(0x82, 0xFF, 0x00), RGB(0x41, 0xFF, 0x00), + RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0x41), RGB(0x00, 0xFF, 0x82), RGB(0x00, 0xFF, 0xBE), + RGB(0x00, 0xFF, 0xFF), RGB(0x00, 0xBE, 0xFF), RGB(0x00, 0x82, 0xFF), RGB(0x00, 0x41, 0xFF), + RGB(0x82, 0x82, 0xFF), RGB(0x9E, 0x82, 0xFF), RGB(0xBE, 0x82, 0xFF), RGB(0xDF, 0x82, 0xFF), + RGB(0xFF, 0x82, 0xFF), RGB(0xFF, 0x82, 0xDF), RGB(0xFF, 0x82, 0xBE), RGB(0xFF, 0x82, 0x9E), + RGB(0xFF, 0x82, 0x82), RGB(0xFF, 0x9E, 0x82), RGB(0xFF, 0xBE, 0x82), RGB(0xFF, 0xDF, 0x82), + RGB(0xFF, 0xFF, 0x82), RGB(0xDF, 0xFF, 0x82), RGB(0xBE, 0xFF, 0x82), RGB(0x9E, 0xFF, 0x82), + RGB(0x82, 0xFF, 0x82), RGB(0x82, 0xFF, 0x9E), RGB(0x82, 0xFF, 0xBE), RGB(0x82, 0xFF, 0xDF), + RGB(0x82, 0xFF, 0xFF), RGB(0x82, 0xDF, 0xFF), RGB(0x82, 0xBE, 0xFF), RGB(0x82, 0x9E, 0xFF), + RGB(0xBA, 0xBA, 0xFF), RGB(0xCA, 0xBA, 0xFF), RGB(0xDF, 0xBA, 0xFF), RGB(0xEF, 0xBA, 0xFF), + RGB(0xFF, 0xBA, 0xFF), RGB(0xFF, 0xBA, 0xEF), RGB(0xFF, 0xBA, 0xDF), RGB(0xFF, 0xBA, 0xCA), + RGB(0xFF, 0xBA, 0xBA), RGB(0xFF, 0xCA, 0xBA), RGB(0xFF, 0xDF, 0xBA), RGB(0xFF, 0xEF, 0xBA), + RGB(0xFF, 0xFF, 0xBA), RGB(0xEF, 0xFF, 0xBA), RGB(0xDF, 0xFF, 0xBA), RGB(0xCA, 0xFF, 0xBA), + RGB(0xBA, 0xFF, 0xBA), RGB(0xBA, 0xFF, 0xCA), RGB(0xBA, 0xFF, 0xDF), RGB(0xBA, 0xFF, 0xEF), + RGB(0xBA, 0xFF, 0xFF), RGB(0xBA, 0xEF, 0xFF), RGB(0xBA, 0xDF, 0xFF), RGB(0xBA, 0xCA, 0xFF), + RGB(0x00, 0x00, 0x71), RGB(0x1C, 0x00, 0x71), RGB(0x39, 0x00, 0x71), RGB(0x55, 0x00, 0x71), + RGB(0x71, 0x00, 0x71), RGB(0x71, 0x00, 0x55), RGB(0x71, 0x00, 0x39), RGB(0x71, 0x00, 0x1C), + RGB(0x71, 0x00, 0x00), RGB(0x71, 0x1C, 0x00), RGB(0x71, 0x39, 0x00), RGB(0x71, 0x55, 0x00), + RGB(0x71, 0x71, 0x00), RGB(0x55, 0x71, 0x00), RGB(0x39, 0x71, 0x00), RGB(0x1C, 0x71, 0x00), + RGB(0x00, 0x71, 0x00), RGB(0x00, 0x71, 0x1C), RGB(0x00, 0x71, 0x39), RGB(0x00, 0x71, 0x55), + RGB(0x00, 0x71, 0x71), RGB(0x00, 0x55, 0x71), RGB(0x00, 0x39, 0x71), RGB(0x00, 0x1C, 0x71), + RGB(0x39, 0x39, 0x71), RGB(0x45, 0x39, 0x71), RGB(0x55, 0x39, 0x71), RGB(0x61, 0x39, 0x71), + RGB(0x71, 0x39, 0x71), RGB(0x71, 0x39, 0x61), RGB(0x71, 0x39, 0x55), RGB(0x71, 0x39, 0x45), + RGB(0x71, 0x39, 0x39), RGB(0x71, 0x45, 0x39), RGB(0x71, 0x55, 0x39), RGB(0x71, 0x61, 0x39), + RGB(0x71, 0x71, 0x39), RGB(0x61, 0x71, 0x39), RGB(0x55, 0x71, 0x39), RGB(0x45, 0x71, 0x39), + RGB(0x39, 0x71, 0x39), RGB(0x39, 0x71, 0x45), RGB(0x39, 0x71, 0x55), RGB(0x39, 0x71, 0x61), + RGB(0x39, 0x71, 0x71), RGB(0x39, 0x61, 0x71), RGB(0x39, 0x55, 0x71), RGB(0x39, 0x45, 0x71), + RGB(0x51, 0x51, 0x71), RGB(0x59, 0x51, 0x71), RGB(0x61, 0x51, 0x71), RGB(0x69, 0x51, 0x71), + RGB(0x71, 0x51, 0x71), RGB(0x71, 0x51, 0x69), RGB(0x71, 0x51, 0x61), RGB(0x71, 0x51, 0x59), + RGB(0x71, 0x51, 0x51), RGB(0x71, 0x59, 0x51), RGB(0x71, 0x61, 0x51), RGB(0x71, 0x69, 0x51), + RGB(0x71, 0x71, 0x51), RGB(0x69, 0x71, 0x51), RGB(0x61, 0x71, 0x51), RGB(0x59, 0x71, 0x51), + RGB(0x51, 0x71, 0x51), RGB(0x51, 0x71, 0x59), RGB(0x51, 0x71, 0x61), RGB(0x51, 0x71, 0x69), + RGB(0x51, 0x71, 0x71), RGB(0x51, 0x69, 0x71), RGB(0x51, 0x61, 0x71), RGB(0x51, 0x59, 0x71), + RGB(0x00, 0x00, 0x41), RGB(0x10, 0x00, 0x41), RGB(0x20, 0x00, 0x41), RGB(0x31, 0x00, 0x41), + RGB(0x41, 0x00, 0x41), RGB(0x41, 0x00, 0x31), RGB(0x41, 0x00, 0x20), RGB(0x41, 0x00, 0x10), + RGB(0x41, 0x00, 0x00), RGB(0x41, 0x10, 0x00), RGB(0x41, 0x20, 0x00), RGB(0x41, 0x31, 0x00), + RGB(0x41, 0x41, 0x00), RGB(0x31, 0x41, 0x00), RGB(0x20, 0x41, 0x00), RGB(0x10, 0x41, 0x00), + RGB(0x00, 0x41, 0x00), RGB(0x00, 0x41, 0x10), RGB(0x00, 0x41, 0x20), RGB(0x00, 0x41, 0x31), + RGB(0x00, 0x41, 0x41), RGB(0x00, 0x31, 0x41), RGB(0x00, 0x20, 0x41), RGB(0x00, 0x10, 0x41), + RGB(0x20, 0x20, 0x41), RGB(0x28, 0x20, 0x41), RGB(0x31, 0x20, 0x41), RGB(0x39, 0x20, 0x41), + RGB(0x41, 0x20, 0x41), RGB(0x41, 0x20, 0x39), RGB(0x41, 0x20, 0x31), RGB(0x41, 0x20, 0x28), + RGB(0x41, 0x20, 0x20), RGB(0x41, 0x28, 0x20), RGB(0x41, 0x31, 0x20), RGB(0x41, 0x39, 0x20), + RGB(0x41, 0x41, 0x20), RGB(0x39, 0x41, 0x20), RGB(0x31, 0x41, 0x20), RGB(0x28, 0x41, 0x20), + RGB(0x20, 0x41, 0x20), RGB(0x20, 0x41, 0x28), RGB(0x20, 0x41, 0x31), RGB(0x20, 0x41, 0x39), + RGB(0x20, 0x41, 0x41), RGB(0x20, 0x39, 0x41), RGB(0x20, 0x31, 0x41), RGB(0x20, 0x28, 0x41), + RGB(0x2D, 0x2D, 0x41), RGB(0x31, 0x2D, 0x41), RGB(0x35, 0x2D, 0x41), RGB(0x3D, 0x2D, 0x41), + RGB(0x41, 0x2D, 0x41), RGB(0x41, 0x2D, 0x3D), RGB(0x41, 0x2D, 0x35), RGB(0x41, 0x2D, 0x31), + RGB(0x41, 0x2D, 0x2D), RGB(0x41, 0x31, 0x2D), RGB(0x41, 0x35, 0x2D), RGB(0x41, 0x3D, 0x2D), + RGB(0x41, 0x41, 0x2D), RGB(0x3D, 0x41, 0x2D), RGB(0x35, 0x41, 0x2D), RGB(0x31, 0x41, 0x2D), + RGB(0x2D, 0x41, 0x2D), RGB(0x2D, 0x41, 0x31), RGB(0x2D, 0x41, 0x35), RGB(0x2D, 0x41, 0x3D), + RGB(0x2D, 0x41, 0x41), RGB(0x2D, 0x3D, 0x41), RGB(0x2D, 0x35, 0x41), RGB(0x2D, 0x31, 0x41), + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00) +}; + +#elif defined(USE_DOSBOX_COLORS) + +// DOSBox colors +static CONST COLORREF VgaPalette[VGA_MAX_COLORS] = +{ + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA), + RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA), + RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF), + RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF), + RGB(0x00, 0x00, 0x00), RGB(0x14, 0x14, 0x14), RGB(0x20, 0x20, 0x20), RGB(0x2C, 0x2C, 0x2C), + RGB(0x38, 0x38, 0x38), RGB(0x45, 0x45, 0x45), RGB(0x51, 0x51, 0x51), RGB(0x61, 0x61, 0x61), + RGB(0x71, 0x71, 0x71), RGB(0x82, 0x82, 0x82), RGB(0x92, 0x92, 0x92), RGB(0xA2, 0xA2, 0xA2), + RGB(0xB6, 0xB6, 0xB6), RGB(0xCB, 0xCB, 0xCB), RGB(0xE3, 0xE3, 0xE3), RGB(0xFF, 0xFF, 0xFF), + RGB(0x00, 0x00, 0xFF), RGB(0x41, 0x00, 0xFF), RGB(0x7D, 0x00, 0xFF), RGB(0xBE, 0x00, 0xFF), + RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0x00, 0xBE), RGB(0xFF, 0x00, 0x7D), RGB(0xFF, 0x00, 0x41), + RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x41, 0x00), RGB(0xFF, 0x7D, 0x00), RGB(0xFF, 0xBE, 0x00), + RGB(0xFF, 0xFF, 0x00), RGB(0xBE, 0xFF, 0x00), RGB(0x7D, 0xFF, 0x00), RGB(0x41, 0xFF, 0x00), + RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0x41), RGB(0x00, 0xFF, 0x7D), RGB(0x00, 0xFF, 0xBE), + RGB(0x00, 0xFF, 0xFF), RGB(0x00, 0xBE, 0xFF), RGB(0x00, 0x7D, 0xFF), RGB(0x00, 0x41, 0xFF), + RGB(0x7D, 0x7D, 0xFF), RGB(0x9E, 0x7D, 0xFF), RGB(0xBE, 0x7D, 0xFF), RGB(0xDF, 0x7D, 0xFF), + RGB(0xFF, 0x7D, 0xFF), RGB(0xFF, 0x7D, 0xDF), RGB(0xFF, 0x7D, 0xBE), RGB(0xFF, 0x7D, 0x9E), + + RGB(0xFF, 0x7D, 0x7D), RGB(0xFF, 0x9E, 0x7D), RGB(0xFF, 0xBE, 0x7D), RGB(0xFF, 0xDF, 0x7D), + RGB(0xFF, 0xFF, 0x7D), RGB(0xDF, 0xFF, 0x7D), RGB(0xBE, 0xFF, 0x7D), RGB(0x9E, 0xFF, 0x7D), + RGB(0x7D, 0xFF, 0x7D), RGB(0x7D, 0xFF, 0x9E), RGB(0x7D, 0xFF, 0xBE), RGB(0x7D, 0xFF, 0xDF), + RGB(0x7D, 0xFF, 0xFF), RGB(0x7D, 0xDF, 0xFF), RGB(0x7D, 0xBE, 0xFF), RGB(0x7D, 0x9E, 0xFF), + RGB(0xB6, 0xB6, 0xFF), RGB(0xC7, 0xB6, 0xFF), RGB(0xDB, 0xB6, 0xFF), RGB(0xEB, 0xB6, 0xFF), + RGB(0xFF, 0xB6, 0xFF), RGB(0xFF, 0xB6, 0xEB), RGB(0xFF, 0xB6, 0xDB), RGB(0xFF, 0xB6, 0xC7), + RGB(0xFF, 0xB6, 0xB6), RGB(0xFF, 0xC7, 0xB6), RGB(0xFF, 0xDB, 0xB6), RGB(0xFF, 0xEB, 0xB6), + RGB(0xFF, 0xFF, 0xB6), RGB(0xEB, 0xFF, 0xB6), RGB(0xDB, 0xFF, 0xB6), RGB(0xC7, 0xFF, 0xB6), + RGB(0xB6, 0xFF, 0xB6), RGB(0xB6, 0xFF, 0xC7), RGB(0xB6, 0xFF, 0xDB), RGB(0xB6, 0xFF, 0xEB), + RGB(0xB6, 0xFF, 0xFF), RGB(0xB6, 0xEB, 0xFF), RGB(0xB6, 0xDB, 0xFF), RGB(0xB6, 0xC7, 0xFF), + RGB(0x00, 0x00, 0x71), RGB(0x1C, 0x00, 0x71), RGB(0x38, 0x00, 0x71), RGB(0x55, 0x00, 0x71), + RGB(0x71, 0x00, 0x71), RGB(0x71, 0x00, 0x55), RGB(0x71, 0x00, 0x38), RGB(0x71, 0x00, 0x1C), + RGB(0x71, 0x00, 0x00), RGB(0x71, 0x1C, 0x00), RGB(0x71, 0x38, 0x00), RGB(0x71, 0x55, 0x00), + RGB(0x71, 0x71, 0x00), RGB(0x55, 0x71, 0x00), RGB(0x38, 0x71, 0x00), RGB(0x1C, 0x71, 0x00), + RGB(0x00, 0x71, 0x00), RGB(0x00, 0x71, 0x1C), RGB(0x00, 0x71, 0x38), RGB(0x00, 0x71, 0x55), + RGB(0x00, 0x71, 0x71), RGB(0x00, 0x55, 0x71), RGB(0x00, 0x38, 0x71), RGB(0x00, 0x1C, 0x71), + + RGB(0x38, 0x38, 0x71), RGB(0x45, 0x38, 0x71), RGB(0x55, 0x38, 0x71), RGB(0x61, 0x38, 0x71), + RGB(0x71, 0x38, 0x71), RGB(0x71, 0x38, 0x61), RGB(0x71, 0x38, 0x55), RGB(0x71, 0x38, 0x45), + RGB(0x71, 0x38, 0x38), RGB(0x71, 0x45, 0x38), RGB(0x71, 0x55, 0x38), RGB(0x71, 0x61, 0x38), + RGB(0x71, 0x71, 0x38), RGB(0x61, 0x71, 0x38), RGB(0x55, 0x71, 0x38), RGB(0x45, 0x71, 0x38), + RGB(0x38, 0x71, 0x38), RGB(0x38, 0x71, 0x45), RGB(0x38, 0x71, 0x55), RGB(0x38, 0x71, 0x61), + RGB(0x38, 0x71, 0x71), RGB(0x38, 0x61, 0x71), RGB(0x38, 0x55, 0x71), RGB(0x38, 0x45, 0x71), + RGB(0x51, 0x51, 0x71), RGB(0x59, 0x51, 0x71), RGB(0x61, 0x51, 0x71), RGB(0x69, 0x51, 0x71), + RGB(0x71, 0x51, 0x71), RGB(0x71, 0x51, 0x69), RGB(0x71, 0x51, 0x61), RGB(0x71, 0x51, 0x59), + RGB(0x71, 0x51, 0x51), RGB(0x71, 0x59, 0x51), RGB(0x71, 0x61, 0x51), RGB(0x71, 0x69, 0x51), + RGB(0x71, 0x71, 0x51), RGB(0x69, 0x71, 0x51), RGB(0x61, 0x71, 0x51), RGB(0x59, 0x71, 0x51), + RGB(0x51, 0x71, 0x51), RGB(0x51, 0x71, 0x59), RGB(0x51, 0x71, 0x61), RGB(0x51, 0x71, 0x69), + RGB(0x51, 0x71, 0x71), RGB(0x51, 0x69, 0x71), RGB(0x51, 0x61, 0x71), RGB(0x51, 0x59, 0x71), + RGB(0x00, 0x00, 0x41), RGB(0x10, 0x00, 0x41), RGB(0x20, 0x00, 0x41), RGB(0x30, 0x00, 0x41), + RGB(0x41, 0x00, 0x41), RGB(0x41, 0x00, 0x30), RGB(0x41, 0x00, 0x20), RGB(0x41, 0x00, 0x10), + RGB(0x41, 0x00, 0x00), RGB(0x41, 0x10, 0x00), RGB(0x41, 0x20, 0x00), RGB(0x41, 0x30, 0x00), + RGB(0x41, 0x41, 0x00), RGB(0x30, 0x41, 0x00), RGB(0x20, 0x41, 0x00), RGB(0x10, 0x41, 0x00), + + RGB(0x00, 0x41, 0x00), RGB(0x00, 0x41, 0x10), RGB(0x00, 0x41, 0x20), RGB(0x00, 0x41, 0x30), + RGB(0x00, 0x41, 0x41), RGB(0x00, 0x30, 0x41), RGB(0x00, 0x20, 0x41), RGB(0x00, 0x10, 0x41), + RGB(0x20, 0x20, 0x41), RGB(0x28, 0x20, 0x41), RGB(0x30, 0x20, 0x41), RGB(0x38, 0x20, 0x41), + RGB(0x41, 0x20, 0x41), RGB(0x41, 0x20, 0x38), RGB(0x41, 0x20, 0x30), RGB(0x41, 0x20, 0x28), + RGB(0x41, 0x20, 0x20), RGB(0x41, 0x28, 0x20), RGB(0x41, 0x30, 0x20), RGB(0x41, 0x38, 0x20), + RGB(0x41, 0x41, 0x20), RGB(0x38, 0x41, 0x20), RGB(0x30, 0x41, 0x20), RGB(0x28, 0x41, 0x20), + RGB(0x20, 0x41, 0x20), RGB(0x20, 0x41, 0x28), RGB(0x20, 0x41, 0x30), RGB(0x20, 0x41, 0x38), + RGB(0x20, 0x41, 0x41), RGB(0x20, 0x38, 0x41), RGB(0x20, 0x30, 0x41), RGB(0x20, 0x28, 0x41), + RGB(0x2C, 0x2C, 0x41), RGB(0x30, 0x2C, 0x41), RGB(0x34, 0x2C, 0x41), RGB(0x3C, 0x2C, 0x41), + RGB(0x41, 0x2C, 0x41), RGB(0x41, 0x2C, 0x3C), RGB(0x41, 0x2C, 0x34), RGB(0x41, 0x2C, 0x30), + RGB(0x41, 0x2C, 0x2C), RGB(0x41, 0x30, 0x2C), RGB(0x41, 0x34, 0x2C), RGB(0x41, 0x3C, 0x2C), + RGB(0x41, 0x41, 0x2C), RGB(0x3C, 0x41, 0x2C), RGB(0x34, 0x41, 0x2C), RGB(0x30, 0x41, 0x2C), + RGB(0x2C, 0x41, 0x2C), RGB(0x2C, 0x41, 0x30), RGB(0x2C, 0x41, 0x34), RGB(0x2C, 0x41, 0x3C), + RGB(0x2C, 0x41, 0x41), RGB(0x2C, 0x3C, 0x41), RGB(0x2C, 0x34, 0x41), RGB(0x2C, 0x30, 0x41), + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00) +}; + +#endif + +/* PRIVATE FUNCTIONS **********************************************************/ + +static VOID VidBiosReadWindow(LPWORD Buffer, SMALL_RECT Rectangle, BYTE Page) +{ + INT i, j; + INT Counter = 0; + WORD Character; + DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Page * Bda->VideoPageSize); + + for (i = Rectangle.Top; i <= Rectangle.Bottom; i++) + { + for (j = Rectangle.Left; j <= Rectangle.Right; j++) + { + /* Read from video memory */ + EmulatorReadMemory(&EmulatorContext, + VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD), + (LPVOID)&Character, + sizeof(WORD)); + + /* Write the data to the buffer in row order */ + Buffer[Counter++] = Character; + } + } +} + +static VOID VidBiosWriteWindow(LPWORD Buffer, SMALL_RECT Rectangle, BYTE Page) +{ + INT i, j; + INT Counter = 0; + WORD Character; + DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Page * Bda->VideoPageSize); + + for (i = Rectangle.Top; i <= Rectangle.Bottom; i++) + { + for (j = Rectangle.Left; j <= Rectangle.Right; j++) + { + Character = Buffer[Counter++]; + + /* Write to video memory */ + EmulatorWriteMemory(&EmulatorContext, + VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD), + (LPVOID)&Character, + sizeof(WORD)); + } + } +} + +static BOOLEAN VidBiosScrollWindow(INT Direction, + DWORD Amount, + SMALL_RECT Rectangle, + BYTE Page, + BYTE FillAttribute) +{ + DWORD i; + LPWORD WindowData; + WORD WindowWidth = Rectangle.Right - Rectangle.Left + 1; + WORD WindowHeight = Rectangle.Bottom - Rectangle.Top + 1; + DWORD WindowSize = WindowWidth * WindowHeight; + + /* Allocate a buffer for the window */ + WindowData = (LPWORD)HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + WindowSize * sizeof(WORD)); + if (WindowData == NULL) return FALSE; + + /* Read the window data */ + VidBiosReadWindow(WindowData, Rectangle, Page); + + if ((Amount == 0) + || (((Direction == SCROLL_DIRECTION_UP) + || (Direction == SCROLL_DIRECTION_DOWN)) + && (Amount >= WindowHeight)) + || (((Direction == SCROLL_DIRECTION_LEFT) + || (Direction == SCROLL_DIRECTION_RIGHT)) + && (Amount >= WindowWidth))) + { + /* Fill the window */ + for (i = 0; i < WindowSize; i++) + { + WindowData[i] = MAKEWORD(' ', FillAttribute); + } + + goto Done; + } + + switch (Direction) + { + case SCROLL_DIRECTION_UP: + { + RtlMoveMemory(WindowData, + &WindowData[WindowWidth * Amount], + (WindowSize - WindowWidth * Amount) * sizeof(WORD)); + + for (i = 0; i < Amount * WindowWidth; i++) + { + WindowData[WindowSize - i - 1] = MAKEWORD(' ', FillAttribute); + } + + break; + } + + case SCROLL_DIRECTION_DOWN: + { + RtlMoveMemory(&WindowData[WindowWidth * Amount], + WindowData, + (WindowSize - WindowWidth * Amount) * sizeof(WORD)); + + for (i = 0; i < Amount * WindowWidth; i++) + { + WindowData[i] = MAKEWORD(' ', FillAttribute); + } + + break; + } + + default: + { + // TODO: NOT IMPLEMENTED! + UNIMPLEMENTED; + } + } + +Done: + /* Write back the window data */ + VidBiosWriteWindow(WindowData, Rectangle, Page); + + /* Free the window buffer */ + HeapFree(GetProcessHeap(), 0, WindowData); + + return TRUE; +} + +static BOOLEAN VgaSetRegisters(PVGA_REGISTERS Registers) +{ + INT i; + + if (Registers == NULL) return FALSE; + + /* Disable interrupts */ + setIF(0); + + /* + * Set the CRT base address according to the selected mode, + * monochrome or color. The following macros: + * VGA_INSTAT1_READ, VGA_CRTC_INDEX and VGA_CRTC_DATA are then + * used to access the correct VGA I/O ports. + */ + Bda->CrtBasePort = (Registers->Misc & 0x01) ? VGA_CRTC_INDEX_COLOR + : VGA_CRTC_INDEX_MONO; + + /* Write the misc register */ + IOWriteB(VGA_MISC_WRITE, Registers->Misc); + + /* Synchronous reset on */ + IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_RESET_REG); + IOWriteB(VGA_SEQ_DATA , VGA_SEQ_RESET_AR); + + /* Write the sequencer registers */ + for (i = 1; i < VGA_SEQ_MAX_REG; i++) + { + IOWriteB(VGA_SEQ_INDEX, i); + IOWriteB(VGA_SEQ_DATA, Registers->Sequencer[i]); + } + + /* Synchronous reset off */ + IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_RESET_REG); + IOWriteB(VGA_SEQ_DATA , VGA_SEQ_RESET_SR | VGA_SEQ_RESET_AR); + + /* Unlock CRTC registers 0-7 */ + IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_END_HORZ_BLANKING_REG); + IOWriteB(VGA_CRTC_DATA, IOReadB(VGA_CRTC_DATA) | 0x80); + IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_VERT_RETRACE_END_REG); + IOWriteB(VGA_CRTC_DATA, IOReadB(VGA_CRTC_DATA) & ~0x80); + // Make sure they remain unlocked + Registers->CRT[VGA_CRTC_END_HORZ_BLANKING_REG] |= 0x80; + Registers->CRT[VGA_CRTC_VERT_RETRACE_END_REG] &= ~0x80; + + /* Write the CRTC registers */ + for (i = 0; i < VGA_CRTC_MAX_REG; i++) + { + IOWriteB(VGA_CRTC_INDEX, i); + IOWriteB(VGA_CRTC_DATA, Registers->CRT[i]); + } + + /* Write the GC registers */ + for (i = 0; i < VGA_GC_MAX_REG; i++) + { + IOWriteB(VGA_GC_INDEX, i); + IOWriteB(VGA_GC_DATA, Registers->Graphics[i]); + } + + /* Write the AC registers */ + // DbgPrint("\n"); + for (i = 0; i < VGA_AC_MAX_REG; i++) + { + IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state + IOWriteB(VGA_AC_INDEX, i); + IOWriteB(VGA_AC_WRITE, Registers->Attribute[i]); + // DbgPrint("Registers->Attribute[%d] = %d\n", i, Registers->Attribute[i]); + } + // DbgPrint("\n"); + + /* Set the PEL mask */ + IOWriteB(VGA_DAC_MASK, 0xFF); + + /* Enable screen and disable palette access */ + IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state + IOWriteB(VGA_AC_INDEX, 0x20); + + /* Enable interrupts */ + setIF(1); + + return TRUE; +} + +static VOID VgaSetPalette(const COLORREF* Palette, ULONG Size) +{ + ULONG i; + + // /* Disable screen and enable palette access */ + // IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state + // IOWriteB(VGA_AC_INDEX, 0x00); + + for (i = 0; i < Size; i++) + { + IOWriteB(VGA_DAC_WRITE_INDEX, i); + IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(GetRValue(Palette[i]))); + IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(GetGValue(Palette[i]))); + IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(GetBValue(Palette[i]))); + } + + /* The following step might be optional */ + for (i = Size; i < VGA_MAX_COLORS; i++) + { + IOWriteB(VGA_DAC_WRITE_INDEX, i); + IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(0x00)); + IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(0x00)); + IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(0x00)); + } + + /* Enable screen and disable palette access */ + // IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state + // IOWriteB(VGA_AC_INDEX, 0x20); +} + +static VOID VgaChangePalette(BYTE ModeNumber) +{ + const COLORREF* Palette; + ULONG Size; + + if (ModeNumber >= 0x13) + { + /* VGA modes */ + Palette = VgaPalette; + Size = sizeof(VgaPalette)/sizeof(VgaPalette[0]); + } + else if (ModeNumber == 0x10) + { + /* EGA HiRes mode */ + Palette = EgaPalette__HiRes; + Size = sizeof(EgaPalette__HiRes)/sizeof(EgaPalette__HiRes[0]); + } + else // if ((ModeNumber == 0x0D) || (ModeNumber == 0x0E)) + { + /* EGA modes */ + Palette = EgaPalette___16ColorFixed_DOSBox; + Size = sizeof(EgaPalette___16ColorFixed_DOSBox)/sizeof(EgaPalette___16ColorFixed_DOSBox[0]); + } + + VgaSetPalette(Palette, Size); +} + +static VOID VidBiosGetCursorPosition(PBYTE Row, PBYTE Column, BYTE Page) +{ + /* Make sure the selected video page is valid */ + if (Page >= BIOS_MAX_PAGES) return; + + /* Get the cursor location */ + *Row = HIBYTE(Bda->CursorPosition[Page]); + *Column = LOBYTE(Bda->CursorPosition[Page]); +} + +static VOID VidBiosSetCursorPosition(BYTE Row, BYTE Column, BYTE Page) +{ + /* Make sure the selected video page is valid */ + if (Page >= BIOS_MAX_PAGES) return; + + /* Update the position in the BDA */ + Bda->CursorPosition[Page] = MAKEWORD(Column, Row); + + /* Check if this is the current video page */ + if (Page == Bda->VideoPage) + { + WORD Offset = Row * Bda->ScreenColumns + Column; + + /* Modify the CRTC registers */ + IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_LOW_REG); + IOWriteB(VGA_CRTC_DATA , LOBYTE(Offset)); + IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_HIGH_REG); + IOWriteB(VGA_CRTC_DATA , HIBYTE(Offset)); + } +} + +VOID VidBiosSyncCursorPosition(VOID) +{ + BYTE Row, Column; + BYTE Low, High; + SHORT ScreenColumns = VgaGetDisplayResolution().X; + WORD Offset; + + /* Get the cursor location */ + IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_LOW_REG); + Low = IOReadB(VGA_CRTC_DATA); + IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_HIGH_REG); + High = IOReadB(VGA_CRTC_DATA); + + Offset = MAKEWORD(Low, High); + + Row = (BYTE)(Offset / ScreenColumns); + Column = (BYTE)(Offset % ScreenColumns); + + /* Synchronize our cursor position with VGA */ + VidBiosSetCursorPosition(Row, Column, Bda->VideoPage); +} + +BYTE VidBiosGetVideoMode(VOID) +{ + return Bda->VideoMode; +} + +static BOOLEAN VidBiosSetVideoMode(BYTE ModeNumber) +{ + BYTE Page; + + COORD Resolution; + PVGA_REGISTERS VgaMode = VideoModes[ModeNumber]; + + DPRINT1("Switching to mode %Xh; VgaMode = 0x%p\n", ModeNumber, VgaMode); + + if (!VgaSetRegisters(VgaMode)) return FALSE; + + VgaChangePalette(ModeNumber); + + /* + * IBM standard modes do not clear the screen if the + * high bit of AL is set (EGA or higher only). + * See Ralf Brown: http://www.ctyme.com/intr/rb-0069.htm + * for more information. + */ + // if ((ModeNumber & 0x08) == 0) VgaClearMemory(); + VgaClearMemory(); + + // Bda->CrtModeControl; + // Bda->CrtColorPaletteMask; + // Bda->EGAFlags; + // Bda->VGAFlags; + + /* Update the values in the BDA */ + Bda->VideoMode = ModeNumber; + Bda->VideoPageSize = VideoModePageSize[ModeNumber]; + Bda->VideoPage = 0; + Bda->VideoPageOffset = Bda->VideoPage * Bda->VideoPageSize; + + /* Set the start address in the CRTC */ + IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_LOW_REG); + IOWriteB(VGA_CRTC_DATA , LOBYTE(Bda->VideoPageOffset)); + IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_HIGH_REG); + IOWriteB(VGA_CRTC_DATA , HIBYTE(Bda->VideoPageOffset)); + + /* Update the character height */ + IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_MAX_SCAN_LINE_REG); + Bda->CharacterHeight = 1 + (IOReadB(VGA_CRTC_DATA) & 0x1F); + + /* Update the screen size */ + Resolution = VgaGetDisplayResolution(); + Bda->ScreenColumns = Resolution.X; + Bda->ScreenRows = Resolution.Y - 1; + + /* Set the cursor position for each page */ + for (Page = 0; Page < BIOS_MAX_PAGES; ++Page) + VidBiosSetCursorPosition(0, 0, Page); + + /* Refresh display */ + VgaRefreshDisplay(); + + return TRUE; +} + +static BOOLEAN VidBiosSetVideoPage(BYTE PageNumber) +{ + BYTE Row, Column; + + /* Check if the page exists */ + if (PageNumber >= BIOS_MAX_PAGES) return FALSE; + + /* Check if this is the same page */ + if (PageNumber == Bda->VideoPage) return TRUE; + + /* Update the values in the BDA */ + Bda->VideoPage = PageNumber; + Bda->VideoPageOffset = Bda->VideoPage * Bda->VideoPageSize; + + /* Set the start address in the CRTC */ + IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_LOW_REG); + IOWriteB(VGA_CRTC_DATA , LOBYTE(Bda->VideoPageOffset)); + IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_HIGH_REG); + IOWriteB(VGA_CRTC_DATA , HIBYTE(Bda->VideoPageOffset)); + + /* + * Get the cursor location (we don't update anything on the BIOS side + * but we update the cursor location on the VGA side). + */ + VidBiosGetCursorPosition(&Row, &Column, PageNumber); + VidBiosSetCursorPosition(Row, Column, PageNumber); + + return TRUE; +} + +static VOID VidBiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page) +{ + WORD CharData = MAKEWORD(Character, Attribute); + BYTE Row, Column; + + /* Make sure the page exists */ + if (Page >= BIOS_MAX_PAGES) return; + + /* Get the cursor location */ + VidBiosGetCursorPosition(&Row, &Column, Page); + + if (Character == '\a') + { + /* Bell control character */ + // NOTE: We may use what the terminal emulator offers to us... + Beep(800, 200); + return; + } + else if (Character == '\b') + { + /* Backspace control character */ + if (Column > 0) + { + Column--; + } + else if (Row > 0) + { + Column = Bda->ScreenColumns - 1; + Row--; + } + + /* Erase the existing character */ + CharData = MAKEWORD(' ', Attribute); + EmulatorWriteMemory(&EmulatorContext, + TO_LINEAR(TEXT_VIDEO_SEG, + Page * Bda->VideoPageSize + + (Row * Bda->ScreenColumns + Column) * sizeof(WORD)), + (LPVOID)&CharData, + sizeof(WORD)); + } + else if (Character == '\t') + { + /* Horizontal Tabulation control character */ + do + { + // Taken from DOSBox + VidBiosPrintCharacter(' ', Attribute, Page); + VidBiosGetCursorPosition(&Row, &Column, Page); + } while (Column % 8); + } + else if (Character == '\n') + { + /* Line Feed control character */ + Row++; + } + else if (Character == '\r') + { + /* Carriage Return control character */ + Column = 0; + } + else + { + /* Default character */ + + /* Write the character */ + EmulatorWriteMemory(&EmulatorContext, + TO_LINEAR(TEXT_VIDEO_SEG, + Page * Bda->VideoPageSize + + (Row * Bda->ScreenColumns + Column) * sizeof(WORD)), + (LPVOID)&CharData, + sizeof(WORD)); + + /* Advance the cursor */ + Column++; + } + + /* Check if it passed the end of the row */ + if (Column >= Bda->ScreenColumns) + { + /* Return to the first column and go to the next line */ + Column = 0; + Row++; + } + + /* Scroll the screen up if needed */ + if (Row > Bda->ScreenRows) + { + /* The screen must be scrolled up */ + SMALL_RECT Rectangle = { 0, 0, Bda->ScreenColumns - 1, Bda->ScreenRows }; + + VidBiosScrollWindow(SCROLL_DIRECTION_UP, + 1, + Rectangle, + Page, + DEFAULT_ATTRIBUTE); + + Row--; + } + + /* Set the cursor position */ + VidBiosSetCursorPosition(Row, Column, Page); +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID WINAPI VidBiosVideoService(LPWORD Stack) +{ + switch (getAH()) + { + /* Set Video Mode */ + case 0x00: + { + VidBiosSetVideoMode(getAL()); + break; + } + + /* Set Text-Mode Cursor Shape */ + case 0x01: + { + /* Update the BDA */ + Bda->CursorStartLine = getCH(); + Bda->CursorEndLine = getCL(); + + /* Modify the CRTC registers */ + IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_START_REG); + IOWriteB(VGA_CRTC_DATA , Bda->CursorStartLine); + IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_END_REG); + IOWriteB(VGA_CRTC_DATA , Bda->CursorEndLine); + + break; + } + + /* Set Cursor Position */ + case 0x02: + { + VidBiosSetCursorPosition(getDH(), getDL(), getBH()); + break; + } + + /* Get Cursor Position and Shape */ + case 0x03: + { + /* Make sure the selected video page exists */ + if (getBH() >= BIOS_MAX_PAGES) break; + + /* Return the result */ + setAX(0); + setCX(MAKEWORD(Bda->CursorEndLine, Bda->CursorStartLine)); + setDX(Bda->CursorPosition[getBH()]); + break; + } + + /* Query Light Pen */ + case 0x04: + { + /* + * On modern BIOSes, this function returns 0 + * so that we can ignore the other registers. + */ + setAX(0); + break; + } + + /* Select Active Display Page */ + case 0x05: + { + VidBiosSetVideoPage(getAL()); + break; + } + + /* Scroll Window Up/Down */ + case 0x06: + case 0x07: + { + SMALL_RECT Rectangle = { getCL(), getCH(), getDL(), getDH() }; + + /* Call the internal function */ + VidBiosScrollWindow((getAH() == 0x06) ? SCROLL_DIRECTION_UP + : SCROLL_DIRECTION_DOWN, + getAL(), + Rectangle, + Bda->VideoPage, + getBH()); + + break; + } + + /* Read Character and Attribute at Cursor Position */ + case 0x08: + { + WORD CharacterData; + BYTE Page = getBH(); + DWORD Offset; + + /* Check if the page exists */ + if (Page >= BIOS_MAX_PAGES) break; + + /* Find the offset of the character */ + Offset = Page * Bda->VideoPageSize + + (HIBYTE(Bda->CursorPosition[Page]) * Bda->ScreenColumns + + LOBYTE(Bda->CursorPosition[Page])) * 2; + + /* Read from the video memory */ + EmulatorReadMemory(&EmulatorContext, + TO_LINEAR(TEXT_VIDEO_SEG, Offset), + (LPVOID)&CharacterData, + sizeof(WORD)); + + /* Return the character data in AX */ + setAX(CharacterData); + + break; + } + + /* Write Character and Attribute at Cursor Position */ + case 0x09: + /* Write Character only (PCjr: + Attribute) at Cursor Position */ + case 0x0A: + { + WORD CharacterData = MAKEWORD(getAL(), getBL()); + BYTE Page = getBH(); + DWORD Offset, Counter = getCX(); + + /* Check if the page exists */ + if (Page >= BIOS_MAX_PAGES) break; + + /* Find the offset of the character */ + Offset = Page * Bda->VideoPageSize + + (HIBYTE(Bda->CursorPosition[Page]) * Bda->ScreenColumns + + LOBYTE(Bda->CursorPosition[Page])) * 2; + + /* Write to video memory a certain number of times */ + while (Counter > 0) + { + EmulatorWriteMemory(&EmulatorContext, + TO_LINEAR(TEXT_VIDEO_SEG, Offset), + (LPVOID)&CharacterData, + (getAH() == 0x09) ? sizeof(WORD) : sizeof(BYTE)); + Offset += 2; + Counter--; + } + + break; + } + + /* Teletype Output */ + case 0x0E: + { + VidBiosPrintCharacter(getAL(), getBL(), getBH()); + break; + } + + /* Get Current Video Mode */ + case 0x0F: + { + setAX(MAKEWORD(Bda->VideoMode, Bda->ScreenColumns)); + setBX(MAKEWORD(getBL(), Bda->VideoPage)); + break; + } + + /* Palette Control */ + case 0x10: + { + switch (getAL()) + { + /* Set Single Palette Register */ + case 0x00: + { + /* Write the index */ + IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state + IOWriteB(VGA_AC_INDEX, getBL()); + + /* Write the data */ + IOWriteB(VGA_AC_WRITE, getBH()); + + /* Enable screen and disable palette access */ + IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state + IOWriteB(VGA_AC_INDEX, 0x20); + break; + } + + /* Set Overscan Color */ + case 0x01: + { + /* Write the index */ + IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state + IOWriteB(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG); + + /* Write the data */ + IOWriteB(VGA_AC_WRITE, getBH()); + + /* Enable screen and disable palette access */ + IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state + IOWriteB(VGA_AC_INDEX, 0x20); + break; + } + + /* Set All Palette Registers */ + case 0x02: + { + INT i; + LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX()); + + /* Set the palette registers */ + for (i = 0; i <= VGA_AC_PAL_F_REG; i++) + { + /* Write the index */ + IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state + IOWriteB(VGA_AC_INDEX, i); + + /* Write the data */ + IOWriteB(VGA_AC_WRITE, Buffer[i]); + } + + /* Set the overscan register */ + IOWriteB(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG); + IOWriteB(VGA_AC_WRITE, Buffer[VGA_AC_PAL_F_REG + 1]); + + /* Enable screen and disable palette access */ + IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state + IOWriteB(VGA_AC_INDEX, 0x20); + break; + } + + /* Get Single Palette Register */ + case 0x07: + { + /* Write the index */ + IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state + IOWriteB(VGA_AC_INDEX, getBL()); + + /* Read the data */ + setBH(IOReadB(VGA_AC_READ)); + + /* Enable screen and disable palette access */ + IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state + IOWriteB(VGA_AC_INDEX, 0x20); + break; + } + + /* Get Overscan Color */ + case 0x08: + { + /* Write the index */ + IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state + IOWriteB(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG); + + /* Read the data */ + setBH(IOReadB(VGA_AC_READ)); + + /* Enable screen and disable palette access */ + IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state + IOWriteB(VGA_AC_INDEX, 0x20); + break; + } + + /* Get All Palette Registers */ + case 0x09: + { + INT i; + LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX()); + + /* Get the palette registers */ + for (i = 0; i <= VGA_AC_PAL_F_REG; i++) + { + /* Write the index */ + IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state + IOWriteB(VGA_AC_INDEX, i); + + /* Read the data */ + Buffer[i] = IOReadB(VGA_AC_READ); + } + + /* Get the overscan register */ + IOWriteB(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG); + Buffer[VGA_AC_PAL_F_REG + 1] = IOReadB(VGA_AC_READ); + + /* Enable screen and disable palette access */ + IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state + IOWriteB(VGA_AC_INDEX, 0x20); + break; + } + + /* Set Individual DAC Register */ + case 0x10: + { + /* Write the index */ + // Certainly in BL and not in BX as said by Ralf Brown... + IOWriteB(VGA_DAC_WRITE_INDEX, getBL()); + + /* Write the data in this order: Red, Green, Blue */ + IOWriteB(VGA_DAC_DATA, getDH()); + IOWriteB(VGA_DAC_DATA, getCH()); + IOWriteB(VGA_DAC_DATA, getCL()); + + break; + } + + /* Set Block of DAC Registers */ + case 0x12: + { + INT i; + LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX()); + + /* Write the index */ + // Certainly in BL and not in BX as said by Ralf Brown... + IOWriteB(VGA_DAC_WRITE_INDEX, getBL()); + + for (i = 0; i < getCX(); i++) + { + /* Write the data in this order: Red, Green, Blue */ + IOWriteB(VGA_DAC_DATA, *Buffer++); + IOWriteB(VGA_DAC_DATA, *Buffer++); + IOWriteB(VGA_DAC_DATA, *Buffer++); + } + + break; + } + + /* Get Individual DAC Register */ + case 0x15: + { + /* Write the index */ + IOWriteB(VGA_DAC_READ_INDEX, getBL()); + + /* Read the data in this order: Red, Green, Blue */ + setDH(IOReadB(VGA_DAC_DATA)); + setCH(IOReadB(VGA_DAC_DATA)); + setCL(IOReadB(VGA_DAC_DATA)); + + break; + } + + /* Get Block of DAC Registers */ + case 0x17: + { + INT i; + LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX()); + + /* Write the index */ + // Certainly in BL and not in BX as said by Ralf Brown... + IOWriteB(VGA_DAC_READ_INDEX, getBL()); + + for (i = 0; i < getCX(); i++) + { + /* Write the data in this order: Red, Green, Blue */ + *Buffer++ = IOReadB(VGA_DAC_DATA); + *Buffer++ = IOReadB(VGA_DAC_DATA); + *Buffer++ = IOReadB(VGA_DAC_DATA); + } + + break; + } + + default: + { + DPRINT1("BIOS Palette Control Sub-command AL = 0x%02X NOT IMPLEMENTED\n", + getAL()); + break; + } + } + + break; + } + + /* Alternate Function Select */ + case 0x12: + { + DPRINT1("BIOS Function INT 12h (Alternate Function Select), BX = 0x%04X NOT IMPLEMENTED\n", + getBX()); + break; + } + + /* Write String */ + case 0x13: + { + DPRINT1("BIOS Function INT 13h (Write String) is UNIMPLEMENTED\n"); + break; + } + + /* Display combination code */ + case 0x1A: + { + switch(getAL()) + { + case 0x00: /* Get Display combiantion code */ + setAX(MAKEWORD(0x1A, 0x1A)); + setBX(MAKEWORD(0x08, 0x00)); /* VGA w/ color analog display */ + break; + case 0x01: /* Set Display combination code */ + DPRINT1("Set Display combination code - Unsupported\n"); + break; + default: + break; + } + break; + } + + default: + { + DPRINT1("BIOS Function INT 10h, AH = 0x%02X NOT IMPLEMENTED\n", + getAH()); + } + } +} + + +/* + * Those attach / detach functions are work-in-progress + */ + +static BOOL Attached = TRUE; + +VOID VidBiosAttachToConsole(VOID) +{ + // VgaRefreshDisplay(); + if (!Attached) + { + VgaAttachToConsole(); + Attached = TRUE; + } + + VgaRefreshDisplay(); + VidBiosSyncCursorPosition(); +} + +VOID VidBiosDetachFromConsole(VOID) +{ + /* Perform another screen refresh */ + VgaRefreshDisplay(); + + /* Detach from the console */ + VgaDetachFromConsole(FALSE); + Attached = FALSE; +} + + +BOOLEAN VidBiosInitialize(VOID) +{ + /* Some interrupts are in fact addresses to tables */ + ((PULONG)BaseAddress)[0x1D] = (ULONG)NULL; + ((PULONG)BaseAddress)[0x1F] = (ULONG)NULL; + // ((PULONG)BaseAddress)[0x42] = (ULONG)NULL; + ((PULONG)BaseAddress)[0x43] = (ULONG)NULL; + ((PULONG)BaseAddress)[0x44] = (ULONG)NULL; + + // + // FIXME: At the moment we always set a VGA mode. In the future, + // we should set this mode **only** when: + // - an app starts to use directly the video memory + // (that should be done in emulator.c) + // - or starts to use non-stream I/O interrupts + // (that should be done here, or maybe in VGA ??) + // + + /* Set the default video mode */ + VidBiosSetVideoMode(BIOS_DEFAULT_VIDEO_MODE); + + /* Synchronize our cursor position with VGA */ + VidBiosSyncCursorPosition(); + + /* Register the BIOS support BOPs */ + RegisterBop(BOP_VIDEO_INT, VidBiosVideoService); + + return TRUE; +} + +VOID VidBiosCleanup(VOID) +{ +} + +/* EOF */ diff --git a/subsystems/ntvdm/bios/vidbios.h b/subsystems/ntvdm/bios/vidbios.h new file mode 100644 index 00000000000..5e291471115 --- /dev/null +++ b/subsystems/ntvdm/bios/vidbios.h @@ -0,0 +1,52 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: vidbios.h + * PURPOSE: VDM Video BIOS Support Library + * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +#ifndef _VIDBIOS_H_ +#define _VIDBIOS_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" + +/* DEFINES ********************************************************************/ + +#define BIOS_VIDEO_INTERRUPT 0x10 + +#define CONSOLE_FONT_HEIGHT 8 +#define BIOS_DEFAULT_VIDEO_MODE 0x03 +#define BIOS_MAX_PAGES 8 +#define BIOS_MAX_VIDEO_MODE 0x13 +#define DEFAULT_ATTRIBUTE 0x07 + +#define GRAPHICS_VIDEO_SEG 0xA000 +#define TEXT_VIDEO_SEG 0xB800 + +enum +{ + SCROLL_DIRECTION_UP, + SCROLL_DIRECTION_DOWN, + SCROLL_DIRECTION_LEFT, + SCROLL_DIRECTION_RIGHT +}; + +/* FUNCTIONS ******************************************************************/ + +VOID VidBiosSyncCursorPosition(VOID); + +VOID WINAPI VidBiosVideoService(LPWORD Stack); + +VOID VidBiosDetachFromConsole(VOID); +VOID VidBiosAttachToConsole(VOID); + +BOOLEAN VidBiosInitialize(VOID); +VOID VidBiosCleanup(VOID); + +#endif // _VIDBIOS_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/bop.c b/subsystems/ntvdm/bop.c new file mode 100644 index 00000000000..407004290b7 --- /dev/null +++ b/subsystems/ntvdm/bop.c @@ -0,0 +1,50 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: bop.c + * PURPOSE: BIOS Operation Handlers + * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +/* INCLUDES *******************************************************************/ + +// #define NDEBUG + +#include "emulator.h" +#include "bop.h" + +/* PRIVATE VARIABLES **********************************************************/ + +/* + * This is the list of registered BOP handlers. + */ +EMULATOR_BOP_PROC BopProc[EMULATOR_MAX_BOP_NUM] = { NULL }; + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID RegisterBop(BYTE BopCode, EMULATOR_BOP_PROC BopHandler) +{ + BopProc[BopCode] = BopHandler; +} + +VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode) +{ + WORD StackSegment, StackPointer; + LPWORD Stack; + + /* Get the SS:SP */ + StackSegment = State->SegmentRegs[FAST486_REG_SS].Selector; + StackPointer = State->GeneralRegs[FAST486_REG_ESP].LowWord; + + /* Get the stack */ + Stack = (LPWORD)SEG_OFF_TO_PTR(StackSegment, StackPointer); + + /* Call the BOP handler */ + if (BopProc[BopCode] != NULL) + BopProc[BopCode](Stack); + else + DPRINT("Invalid BOP code: 0x%02X\n", BopCode); +} + +/* EOF */ diff --git a/subsystems/ntvdm/bop.h b/subsystems/ntvdm/bop.h new file mode 100644 index 00000000000..a936d1f25cb --- /dev/null +++ b/subsystems/ntvdm/bop.h @@ -0,0 +1,28 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: bop.h + * PURPOSE: BIOS Operation Handlers + * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +#ifndef _BOP_H_ +#define _BOP_H_ + +/* DEFINES ********************************************************************/ + +/* BOP Identifiers */ +#define EMULATOR_BOP 0xC4C4 +#define EMULATOR_MAX_BOP_NUM 0xFF + 1 + +/* FUNCTIONS ******************************************************************/ + +typedef VOID (WINAPI *EMULATOR_BOP_PROC)(LPWORD Stack); + +VOID RegisterBop(BYTE BopCode, EMULATOR_BOP_PROC BopHandler); +VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode); + +#endif // _BOP_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/callback.c b/subsystems/ntvdm/callback.c new file mode 100644 index 00000000000..0cffdfd105a --- /dev/null +++ b/subsystems/ntvdm/callback.c @@ -0,0 +1,296 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: callback.c + * PURPOSE: 16 and 32-bit Callbacks Support + * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "callback.h" + +#include "bop.h" +#include + +/* PRIVATE VARIABLES **********************************************************/ + +/* + * This is the list of registered 32-bit Interrupt handlers. + */ +EMULATOR_INT32_PROC Int32Proc[EMULATOR_MAX_INT32_NUM] = { NULL }; + +/* BOP Identifiers */ +#define BOP_CONTROL 0xFF // Control BOP Handler + #define BOP_CONTROL_DEFFUNC 0x00 // Default Control BOP Function + +/* 32-bit Interrupt dispatcher function code for the Control BOP Handler */ +#define BOP_CONTROL_INT32 0xFF + + +#define BOP(num) LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), (num) +#define UnSimulate16(trap) \ +do { \ + *(PUSHORT)(trap) = EMULATOR_BOP; \ + (trap) += sizeof(USHORT); \ + *(trap) = BOP_UNSIMULATE; \ +} while(0) +// #define UnSimulate16 MAKELONG(EMULATOR_BOP, BOP_UNSIMULATE) // BOP(BOP_UNSIMULATE) + +#define CALL16_TRAMPOLINE_SIZE (1 * sizeof(ULONGLONG)) +#define INT16_TRAMPOLINE_SIZE (1 * sizeof(ULONGLONG)) + +// +// WARNING WARNING!! +// +// If you modify the code stubs here, think also +// about updating them in int32.c too!! +// + +/* 16-bit generic interrupt code for calling a 32-bit interrupt handler */ +BYTE Int16To32[] = +{ + 0xFA, // cli + + /* Push the value of the interrupt to be called */ + 0x6A, 0xFF, // push i (patchable to 0x6A, 0xIntNum) + + /* The BOP Sequence */ +// BOP_SEQ: + 0xF8, // clc + BOP(BOP_CONTROL), // Control BOP + BOP_CONTROL_INT32, // 32-bit Interrupt dispatcher + + 0x73, 0x04, // jnc EXIT (offset +4) + + 0xFB, // sti + + // HACK: The following instruction should be HLT! + 0x90, // nop + + 0xEB, 0xF5, // jmp BOP_SEQ (offset -11) + +// EXIT: + 0x44, 0x44, // inc sp, inc sp + 0xCF, // iret +}; + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID +InitializeContext(IN PCALLBACK16 Context, + IN USHORT Segment, + IN USHORT Offset) +{ + Context->TrampolineFarPtr = MAKELONG(Offset, Segment); + Context->Segment = Segment; + Context->NextOffset = Offset + max(CALL16_TRAMPOLINE_SIZE, + INT16_TRAMPOLINE_SIZE); +} + +VOID +Call16(IN USHORT Segment, + IN USHORT Offset) +{ + /* Save CS:IP */ + USHORT OrgCS = getCS(); + USHORT OrgIP = getIP(); + + /* Set the new CS:IP */ + setCS(Segment); + setIP(Offset); + + DPRINT("Call16(%04X:%04X)\n", Segment, Offset); + + /* Start CPU simulation */ + EmulatorSimulate(); + + /* Restore CS:IP */ + setCS(OrgCS); + setIP(OrgIP); +} + + + +ULONG +RegisterCallback16(IN ULONG FarPtr, + IN LPBYTE CallbackCode, + IN SIZE_T CallbackSize, + OUT PSIZE_T CodeSize OPTIONAL) +{ + LPBYTE CodeStart = (LPBYTE)FAR_POINTER(FarPtr); + LPBYTE Code = CodeStart; + + SIZE_T OurCodeSize = CallbackSize; + + if (CallbackCode == NULL) CallbackSize = 0; + + if (CallbackCode) + { + /* 16-bit interrupt code */ + RtlCopyMemory(Code, CallbackCode, CallbackSize); + Code += CallbackSize; + } + + /* Return the real size of the code if needed */ + if (CodeSize) *CodeSize = OurCodeSize; // == (ULONG_PTR)Code - (ULONG_PTR)CodeStart; + + // /* Return the entry-point address for 32-bit calls */ + // return (ULONG_PTR)(CodeStart + CallbackSize); + return OurCodeSize; +} + +VOID +RunCallback16(IN PCALLBACK16 Context, + IN ULONG FarPtr) +{ + PUCHAR TrampolineBase = (PUCHAR)FAR_POINTER(Context->TrampolineFarPtr); + PUCHAR Trampoline = TrampolineBase; + UCHAR OldTrampoline[CALL16_TRAMPOLINE_SIZE]; + + /* Save the old trampoline */ + ((PULONGLONG)&OldTrampoline)[0] = ((PULONGLONG)TrampolineBase)[0]; + + DPRINT1("RunCallback16(0x%p)\n", FarPtr); + + /* Build the generic entry-point for 16-bit far calls */ + *Trampoline++ = 0x9A; // Call far seg:off + *(PULONG)Trampoline = FarPtr; + Trampoline += sizeof(ULONG); + UnSimulate16(Trampoline); + + /* Perform the call */ + Call16(HIWORD(Context->TrampolineFarPtr), + LOWORD(Context->TrampolineFarPtr)); + + /* Restore the old trampoline */ + ((PULONGLONG)TrampolineBase)[0] = ((PULONGLONG)&OldTrampoline)[0]; +} + + + +ULONG +RegisterInt16(IN ULONG FarPtr, + IN BYTE IntNumber, + IN LPBYTE CallbackCode, + IN SIZE_T CallbackSize, + OUT PSIZE_T CodeSize OPTIONAL) +{ + /* Get a pointer to the IVT and set the corresponding entry (far pointer) */ + LPDWORD IntVecTable = (LPDWORD)SEG_OFF_TO_PTR(0x0000, 0x0000); + IntVecTable[IntNumber] = FarPtr; + + /* Register the 16-bit callback */ + return RegisterCallback16(FarPtr, + CallbackCode, + CallbackSize, + CodeSize); +} + +ULONG +RegisterInt32(IN ULONG FarPtr, + IN BYTE IntNumber, + IN EMULATOR_INT32_PROC IntHandler, + OUT PSIZE_T CodeSize OPTIONAL) +{ + /* Array for holding our copy of the 16-bit interrupt callback */ + BYTE IntCallback[sizeof(Int16To32)/sizeof(BYTE)]; + + /* Check whether the 32-bit interrupt was already registered */ +#if 0 + if (Int32Proc[IntNumber] != NULL) + { + DPRINT1("RegisterInt32: Interrupt 0x%X already registered!\n", IntNumber); + return 0; + } +#endif + + /* Register the 32-bit interrupt handler */ + Int32Proc[IntNumber] = IntHandler; + + /* Copy the generic 16-bit interrupt callback and patch it */ + RtlCopyMemory(IntCallback, Int16To32, sizeof(Int16To32)); + IntCallback[2] = IntNumber; + + /* Register the 16-bit interrupt callback */ + return RegisterInt16(FarPtr, + IntNumber, + IntCallback, + sizeof(IntCallback), + CodeSize); +} + +VOID +Int32Call(IN PCALLBACK16 Context, + IN BYTE IntNumber) +{ + PUCHAR TrampolineBase = (PUCHAR)FAR_POINTER(Context->TrampolineFarPtr); + PUCHAR Trampoline = TrampolineBase; + UCHAR OldTrampoline[INT16_TRAMPOLINE_SIZE]; + + DPRINT("Int32Call(0x%X)\n", IntNumber); + + /* Save the old trampoline */ + ((PULONGLONG)&OldTrampoline)[0] = ((PULONGLONG)TrampolineBase)[0]; + + /* Build the generic entry-point for 16-bit calls */ + if (IntNumber == 0x03) + { + /* We are redefining for INT 03h */ + *Trampoline++ = 0xCC; // Call INT 03h + /** *Trampoline++ = 0x90; // nop **/ + } + else + { + /* Normal interrupt */ + *Trampoline++ = 0xCD; // Call INT XXh + *Trampoline++ = IntNumber; + } + UnSimulate16(Trampoline); + + /* Perform the call */ + Call16(HIWORD(Context->TrampolineFarPtr), + LOWORD(Context->TrampolineFarPtr)); + + /* Restore the old trampoline */ + ((PULONGLONG)TrampolineBase)[0] = ((PULONGLONG)&OldTrampoline)[0]; +} + + + +VOID WINAPI Int32Dispatch(LPWORD Stack) +{ + /* Get the interrupt number */ + BYTE IntNum = LOBYTE(Stack[STACK_INT_NUM]); + + /* Call the 32-bit Interrupt handler */ + if (Int32Proc[IntNum] != NULL) + Int32Proc[IntNum](Stack); + else + DPRINT1("Unhandled 32-bit interrupt: 0x%02X, AX = 0x%04X\n", IntNum, getAX()); +} + +static VOID WINAPI ControlBop(LPWORD Stack) +{ + /* Get the Function Number and skip it */ + BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP()); + setIP(getIP() + 1); + + if (FuncNum == BOP_CONTROL_INT32) + Int32Dispatch(Stack); + else + // DPRINT1("Unassigned Control BOP Function: 0x%02X\n", FuncNum); + DisplayMessage(L"Unassigned Control BOP Function: 0x%02X\n", FuncNum); +} + +VOID InitializeCallbacks(VOID) +{ + /* Register the Control BOP */ + RegisterBop(BOP_CONTROL, ControlBop); +} + +/* EOF */ diff --git a/subsystems/ntvdm/callback.h b/subsystems/ntvdm/callback.h new file mode 100644 index 00000000000..c29ef9cb687 --- /dev/null +++ b/subsystems/ntvdm/callback.h @@ -0,0 +1,75 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: callback.h + * PURPOSE: 32-bit Interrupt Handlers + * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +#ifndef _CALLBACK_H_ +#define _CALLBACK_H_ + +/* DEFINES ********************************************************************/ + +/* 32-bit Interrupt Identifiers */ +#define EMULATOR_MAX_INT32_NUM 0xFF + 1 + +#define INT_HANDLER_OFFSET 0x1000 +#define COMMON_STUB_OFFSET 0x2000 + + +typedef struct _CALLBACK16 +{ + ULONG TrampolineFarPtr; // Where the trampoline zone is placed + USHORT Segment; + USHORT NextOffset; +} CALLBACK16, *PCALLBACK16; + + +/* FUNCTIONS ******************************************************************/ + +typedef VOID (WINAPI *EMULATOR_INT32_PROC)(LPWORD Stack); + +VOID +InitializeContext(IN PCALLBACK16 Context, + IN USHORT Segment, + IN USHORT Offset); + +VOID +Call16(IN USHORT Segment, + IN USHORT Offset); + +ULONG +RegisterCallback16(IN ULONG FarPtr, + IN LPBYTE CallbackCode, + IN SIZE_T CallbackSize, + OUT PSIZE_T CodeSize OPTIONAL); + +VOID +RunCallback16(IN PCALLBACK16 Context, + IN ULONG FarPtr); + +ULONG +RegisterInt16(IN ULONG FarPtr, + IN BYTE IntNumber, + IN LPBYTE CallbackCode, + IN SIZE_T CallbackSize, + OUT PSIZE_T CodeSize OPTIONAL); + +ULONG +RegisterInt32(IN ULONG FarPtr, + IN BYTE IntNumber, + IN EMULATOR_INT32_PROC IntHandler, + OUT PSIZE_T CodeSize OPTIONAL); + +VOID +Int32Call(IN PCALLBACK16 Context, + IN BYTE IntNumber); + +VOID WINAPI Int32Dispatch(LPWORD Stack); +VOID InitializeCallbacks(VOID); + +#endif // _CALLBACK_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/clock.c b/subsystems/ntvdm/clock.c new file mode 100644 index 00000000000..74e1fe4b4f5 --- /dev/null +++ b/subsystems/ntvdm/clock.c @@ -0,0 +1,173 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: clock.c + * PURPOSE: Clock for VDM + * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" + +// #include "clock.h" + +#include "hardware/cmos.h" +#include "hardware/ps2.h" +#include "hardware/timer.h" +#include "hardware/vga.h" + +/* DEFINES ********************************************************************/ + +/* + * Activate IPS_DISPLAY if you want to display the + * number of instructions per second, as well as + * the computed number of ticks for the PIT. + */ +// #define IPS_DISPLAY + +/* + * Activate WORKING_TIMER when the PIT timing problem is fixed. + */ +// #define WORKING_TIMER + + +/* Processor speed */ +#define STEPS_PER_CYCLE 256 +#define KBD_INT_CYCLES 16 + +/* VARIABLES ******************************************************************/ + +LARGE_INTEGER StartPerfCount, Frequency; + +LARGE_INTEGER LastTimerTick, LastRtcTick, Counter; +LONGLONG TimerTicks; +DWORD StartTickCount, CurrentTickCount; +DWORD LastClockUpdate; +DWORD LastVerticalRefresh; +INT KeyboardIntCounter = 0; + +#ifdef IPS_DISPLAY + DWORD LastCyclePrintout; + DWORD Cycles = 0; +#endif + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID ClockUpdate(VOID) +{ + extern BOOLEAN CpuSimulate; + UINT i; + +#ifdef WORKING_TIMER + DWORD PitResolution = PitGetResolution(); +#endif + DWORD RtcFrequency = RtcGetTicksPerSecond(); + + /* Get the current number of ticks */ + CurrentTickCount = GetTickCount(); + +#ifdef WORKING_TIMER + if ((PitResolution <= 1000) && (RtcFrequency <= 1000)) + { + /* Calculate the approximate performance counter value instead */ + Counter.QuadPart = StartPerfCount.QuadPart + + (CurrentTickCount - StartTickCount) + * (Frequency.QuadPart / 1000); + } + else +#endif + { + /* Get the current performance counter value */ + QueryPerformanceCounter(&Counter); + } + + /* Get the number of PIT ticks that have passed */ + TimerTicks = ((Counter.QuadPart - LastTimerTick.QuadPart) + * PIT_BASE_FREQUENCY) / Frequency.QuadPart; + + /* Update the PIT */ + if (TimerTicks > 0) + { + PitClock(TimerTicks); + LastTimerTick = Counter; + } + + /* Check for RTC update */ + if ((CurrentTickCount - LastClockUpdate) >= 1000) + { + RtcTimeUpdate(); + LastClockUpdate = CurrentTickCount; + } + + /* Check for RTC periodic tick */ + if ((Counter.QuadPart - LastRtcTick.QuadPart) + >= (Frequency.QuadPart / (LONGLONG)RtcFrequency)) + { + RtcPeriodicTick(); + LastRtcTick = Counter; + } + + /* Check for vertical retrace */ + if ((CurrentTickCount - LastVerticalRefresh) >= 15) + { + VgaRefreshDisplay(); + LastVerticalRefresh = CurrentTickCount; + } + + if (++KeyboardIntCounter == KBD_INT_CYCLES) + { + GenerateKeyboardInterrupts(); + KeyboardIntCounter = 0; + } + + /* Horizontal retrace occurs as fast as possible */ + VgaHorizontalRetrace(); + + /* Continue CPU emulation */ + for (i = 0; VdmRunning && CpuSimulate && (i < STEPS_PER_CYCLE); i++) + { + EmulatorStep(); +#ifdef IPS_DISPLAY + Cycles++; +#endif + } + +#ifdef IPS_DISPLAY + if ((CurrentTickCount - LastCyclePrintout) >= 1000) + { + DPRINT1("NTVDM: %lu Instructions Per Second; TimerTicks = %I64d\n", Cycles, TimerTicks); + LastCyclePrintout = CurrentTickCount; + Cycles = 0; + } +#endif +} + +BOOLEAN ClockInitialize(VOID) +{ + /* Initialize the performance counter (needed for hardware timers) */ + if (!QueryPerformanceFrequency(&Frequency)) + { + wprintf(L"FATAL: Performance counter not available\n"); + return FALSE; + } + + /* Find the starting performance and tick count */ + StartTickCount = GetTickCount(); + QueryPerformanceCounter(&StartPerfCount); + + /* Set the different last counts to the starting count */ + LastClockUpdate = LastVerticalRefresh = +#ifdef IPS_DISPLAY + LastCyclePrintout = +#endif + StartTickCount; + + /* Set the last timer ticks to the current time */ + LastTimerTick = LastRtcTick = StartPerfCount; + + return TRUE; +} diff --git a/subsystems/ntvdm/clock.h b/subsystems/ntvdm/clock.h new file mode 100644 index 00000000000..53927d2b257 --- /dev/null +++ b/subsystems/ntvdm/clock.h @@ -0,0 +1,20 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: clock.h + * PURPOSE: Clock for VDM + * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +#ifndef _CLOCK_H_ +#define _CLOCK_H_ + +/* FUNCTIONS ******************************************************************/ + +VOID ClockUpdate(VOID); +BOOLEAN ClockInitialize(VOID); + +#endif // _CLOCK_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/dos/dem.c b/subsystems/ntvdm/dos/dem.c new file mode 100644 index 00000000000..f0b251d2e03 --- /dev/null +++ b/subsystems/ntvdm/dos/dem.c @@ -0,0 +1,371 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: dem.c + * PURPOSE: DOS 32-bit Emulation Support Library - + * This library is used by the built-in NTVDM DOS32 and by + * the NT 16-bit DOS in Windows (via BOPs). It also exposes + * exported functions that can be used by VDDs. + * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "utils.h" + +#include "dem.h" +#include "bop.h" + +#include "bios/bios.h" + +/* Extra PSDK/NDK Headers */ +#include + +/* PRIVATE VARIABLES **********************************************************/ + +/**/extern BYTE CurrentDrive;/**/ + +/* DEFINES ********************************************************************/ + +/* BOP Identifiers */ +#define BOP_DOS 0x50 // DOS System BOP (for NTIO.SYS and NTDOS.SYS) +#define BOP_CMD 0x54 // DOS Command Interpreter BOP (for COMMAND.COM) + +/* PRIVATE FUNCTIONS **********************************************************/ + +static VOID WINAPI DosSystemBop(LPWORD Stack) +{ + /* Get the Function Number and skip it */ + BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP()); + setIP(getIP() + 1); + + switch (FuncNum) + { + case 0x11: // Load the DOS kernel + { + BOOLEAN Success; + HANDLE hDosKernel; + ULONG ulDosKernelSize = 0; + + DPRINT1("You are loading Windows NT DOS!\n"); + + /* Open the DOS kernel file */ + hDosKernel = FileOpen("ntdos.sys", &ulDosKernelSize); + + /* If we failed, bail out */ + if (hDosKernel == NULL) goto Quit; + + /* + * Attempt to load the DOS kernel into memory. + * The segment where to load the DOS kernel is defined + * by the DOS BIOS and is found in DI:0000 . + */ + Success = FileLoadByHandle(hDosKernel, + REAL_TO_PHYS(TO_LINEAR(getDI(), 0x0000)), + ulDosKernelSize, + &ulDosKernelSize); + + DPRINT1("Windows NT DOS loading %s at 0x%04X:0x%04X, size 0x%x ; GetLastError() = %u\n", + (Success ? "succeeded" : "failed"), + getDI(), 0x0000, + ulDosKernelSize, + GetLastError()); + + /* Close the DOS kernel file */ + FileClose(hDosKernel); + +Quit: + if (!Success) + { + /* We failed everything, stop the VDM */ + EmulatorTerminate(); + } + + break; + } + + default: + { + + DPRINT1("Unknown DOS System BOP Function: 0x%02X\n", FuncNum); + // setCF(1); // Disable, otherwise we enter an infinite loop + break; + } + } +} + +static VOID WINAPI DosCmdInterpreterBop(LPWORD Stack) +{ + /* Get the Function Number and skip it */ + BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP()); + setIP(getIP() + 1); + + switch (FuncNum) + { + case 0x08: // Launch external command + { +#define CMDLINE_LENGTH 1024 + + BOOL Result; + DWORD dwExitCode; + + LPSTR Command = (LPSTR)SEG_OFF_TO_PTR(getDS(), getSI()); + LPSTR CmdPtr = Command; + CHAR CommandLine[CMDLINE_LENGTH] = ""; + STARTUPINFOA StartupInfo; + PROCESS_INFORMATION ProcessInformation; + + /* NULL-terminate the command by removing the return carriage character */ + while (*CmdPtr != '\r') CmdPtr++; + *CmdPtr = '\0'; + + DPRINT1("CMD Run Command '%s'\n", Command); + + /* Spawn a user-defined 32-bit command preprocessor */ + + /* Build the command line */ + // FIXME: Use COMSPEC env var!! + strcpy(CommandLine, "cmd.exe /c "); + strcat(CommandLine, Command); + + ZeroMemory(&StartupInfo, sizeof(StartupInfo)); + ZeroMemory(&ProcessInformation, sizeof(ProcessInformation)); + + StartupInfo.cb = sizeof(StartupInfo); + + VidBiosDetachFromConsole(); + + Result = CreateProcessA(NULL, + CommandLine, + NULL, + NULL, + TRUE, + 0, + NULL, + NULL, + &StartupInfo, + &ProcessInformation); + if (Result) + { + DPRINT1("Command '%s' launched successfully\n", Command); + + /* Wait for process termination */ + WaitForSingleObject(ProcessInformation.hProcess, INFINITE); + + /* Get the exit code */ + GetExitCodeProcess(ProcessInformation.hProcess, &dwExitCode); + + /* Close handles */ + CloseHandle(ProcessInformation.hThread); + CloseHandle(ProcessInformation.hProcess); + } + else + { + DPRINT1("Failed when launched command '%s'\n"); + dwExitCode = GetLastError(); + } + + VidBiosAttachToConsole(); + + setAL((UCHAR)dwExitCode); + + break; + } + + default: + { + DPRINT1("Unknown DOS CMD Interpreter BOP Function: 0x%02X\n", FuncNum); + // setCF(1); // Disable, otherwise we enter an infinite loop + break; + } + } +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +BOOLEAN DosInitialize(IN LPCSTR DosKernelFileName) +{ + /* Register the DOS BOPs */ + RegisterBop(BOP_DOS, DosSystemBop ); + RegisterBop(BOP_CMD, DosCmdInterpreterBop); + + if (DosKernelFileName) + { + BOOLEAN Success; + HANDLE hDosBios; + ULONG ulDosBiosSize = 0; + + /* Open the DOS BIOS file */ + hDosBios = FileOpen(DosKernelFileName, &ulDosBiosSize); + + /* If we failed, bail out */ + if (hDosBios == NULL) return FALSE; + + /* Attempt to load the DOS BIOS into memory */ + Success = FileLoadByHandle(hDosBios, + REAL_TO_PHYS(TO_LINEAR(0x0070, 0x0000)), + ulDosBiosSize, + &ulDosBiosSize); + + DPRINT1("DOS BIOS loading %s at 0x%04X:0x%04X, size 0x%x ; GetLastError() = %u\n", + (Success ? "succeeded" : "failed"), + 0x0070, 0x0000, + ulDosBiosSize, + GetLastError()); + + /* Close the DOS BIOS file */ + FileClose(hDosBios); + + if (Success) + { + /* Position execution pointers and return */ + setCS(0x0070); + setIP(0x0000); + } + + return Success; + } + else + { + BOOLEAN Result; + + Result = DosBIOSInitialize(); + // Result &= DosKRNLInitialize(); + + return Result; + } +} + +/* PUBLIC EXPORTED APIS *******************************************************/ + +// demLFNCleanup +// demLFNGetCurrentDirectory + +// demGetFileTimeByHandle_WOW +// demWOWLFNAllocateSearchHandle +// demWOWLFNCloseSearchHandle +// demWOWLFNEntry +// demWOWLFNGetSearchHandle +// demWOWLFNInit + +DWORD +WINAPI +demClientErrorEx(IN HANDLE FileHandle, + IN CHAR Unknown, + IN BOOL Flag) +{ + UNIMPLEMENTED; + return GetLastError(); +} + +DWORD +WINAPI +demFileDelete(IN LPCSTR FileName) +{ + if (DeleteFileA(FileName)) SetLastError(ERROR_SUCCESS); + + return GetLastError(); +} + +DWORD +WINAPI +demFileFindFirst(OUT PVOID lpFindFileData, + IN LPCSTR FileName, + IN WORD AttribMask) +{ + BOOLEAN Success = TRUE; + WIN32_FIND_DATAA FindData; + PDOS_FIND_FILE_BLOCK FindFileBlock = (PDOS_FIND_FILE_BLOCK)lpFindFileData; + + /* Fill the block */ + FindFileBlock->DriveLetter = CurrentDrive + 'A'; + FindFileBlock->AttribMask = AttribMask; + FindFileBlock->SearchHandle = FindFirstFileA(FileName, &FindData); + if (FindFileBlock->SearchHandle == INVALID_HANDLE_VALUE) return GetLastError(); + + do + { + /* Check the attributes */ + if (!((FindData.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | + FILE_ATTRIBUTE_SYSTEM | + FILE_ATTRIBUTE_DIRECTORY)) + & ~AttribMask)) + { + break; + } + } + while ((Success = FindNextFileA(FindFileBlock->SearchHandle, &FindData))); + + if (!Success) return GetLastError(); + + FindFileBlock->Attributes = LOBYTE(FindData.dwFileAttributes); + FileTimeToDosDateTime(&FindData.ftLastWriteTime, + &FindFileBlock->FileDate, + &FindFileBlock->FileTime); + FindFileBlock->FileSize = FindData.nFileSizeHigh ? 0xFFFFFFFF + : FindData.nFileSizeLow; + strcpy(FindFileBlock->FileName, FindData.cAlternateFileName); + + return ERROR_SUCCESS; +} + +DWORD +WINAPI +demFileFindNext(OUT PVOID lpFindFileData) +{ + WIN32_FIND_DATAA FindData; + PDOS_FIND_FILE_BLOCK FindFileBlock = (PDOS_FIND_FILE_BLOCK)lpFindFileData; + + do + { + if (!FindNextFileA(FindFileBlock->SearchHandle, &FindData)) + return GetLastError(); + + /* Update the block */ + FindFileBlock->Attributes = LOBYTE(FindData.dwFileAttributes); + FileTimeToDosDateTime(&FindData.ftLastWriteTime, + &FindFileBlock->FileDate, + &FindFileBlock->FileTime); + FindFileBlock->FileSize = FindData.nFileSizeHigh ? 0xFFFFFFFF + : FindData.nFileSizeLow; + strcpy(FindFileBlock->FileName, FindData.cAlternateFileName); + } + while((FindData.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | + FILE_ATTRIBUTE_SYSTEM | + FILE_ATTRIBUTE_DIRECTORY)) + & ~FindFileBlock->AttribMask); + + return ERROR_SUCCESS; +} + +UCHAR +WINAPI +demGetPhysicalDriveType(IN UCHAR DriveNumber) +{ + UNIMPLEMENTED; + return DOSDEVICE_DRIVE_UNKNOWN; +} + +BOOL +WINAPI +demIsShortPathName(IN LPCSTR Path, + IN BOOL Unknown) +{ + UNIMPLEMENTED; + return FALSE; +} + +DWORD +WINAPI +demSetCurrentDirectoryGetDrive(IN LPCSTR CurrentDirectory, + OUT PUCHAR DriveNumber) +{ + UNIMPLEMENTED; + return ERROR_SUCCESS; +} + +/* EOF */ diff --git a/subsystems/ntvdm/dos/dem.h b/subsystems/ntvdm/dos/dem.h new file mode 100644 index 00000000000..1e5f2de1b05 --- /dev/null +++ b/subsystems/ntvdm/dos/dem.h @@ -0,0 +1,82 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: dem.h + * PURPOSE: DOS 32-bit Emulation Support Library - + * This library is used by the built-in NTVDM DOS32 and by + * the NT 16-bit DOS in Windows (via BOPs). It also exposes + * exported functions that can be used by VDDs. + * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +#ifndef _DEM_H_ +#define _DEM_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" +#include "dos32krnl/dos.h" + +/* FUNCTIONS ******************************************************************/ + +BOOLEAN DosInitialize(IN LPCSTR DosKernelFileNames); + +DWORD +WINAPI +demClientErrorEx +( + IN HANDLE FileHandle, + IN CHAR Unknown, + IN BOOL Flag +); + +DWORD +WINAPI +demFileDelete +( + IN LPCSTR FileName +); + +DWORD +WINAPI +demFileFindFirst +( + OUT PVOID lpFindFileData, + IN LPCSTR FileName, + IN WORD AttribMask +); + +DWORD +WINAPI +demFileFindNext +( + OUT PVOID lpFindFileData +); + +UCHAR +WINAPI +demGetPhysicalDriveType +( + IN UCHAR DriveNumber +); + +BOOL +WINAPI +demIsShortPathName +( + IN LPCSTR Path, + IN BOOL Unknown +); + +DWORD +WINAPI +demSetCurrentDirectoryGetDrive +( + IN LPCSTR CurrentDirectory, + OUT PUCHAR DriveNumber +); + +#endif // _DEM_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/dos/dos32krnl/bios.c b/subsystems/ntvdm/dos/dos32krnl/bios.c new file mode 100644 index 00000000000..32057e51f4b --- /dev/null +++ b/subsystems/ntvdm/dos/dos32krnl/bios.c @@ -0,0 +1,223 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: dos.c + * PURPOSE: VDM DOS Kernel + * PROGRAMMERS: Aleksandar Andrejevic + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "callback.h" + +#include "dos.h" + +#include "bios/bios.h" + +/* PRIVATE VARIABLES **********************************************************/ + +// static BYTE CurrentDrive; +// static CHAR CurrentDirectories[NUM_DRIVES][DOS_DIR_LENGTH]; + +/* PRIVATE FUNCTIONS **********************************************************/ + +/* PUBLIC FUNCTIONS ***********************************************************/ + +CHAR DosReadCharacter(WORD FileHandle) +{ + CHAR Character = '\0'; + WORD BytesRead; + + /* Use the file reading function */ + DosReadFile(FileHandle, &Character, 1, &BytesRead); + + return Character; +} + +BOOLEAN DosCheckInput(VOID) +{ + HANDLE Handle = DosGetRealHandle(DOS_INPUT_HANDLE); + + if (IsConsoleHandle(Handle)) + { + /* Save AX */ + USHORT AX = getAX(); + + /* Call the BIOS */ + setAH(0x01); // or 0x11 for enhanced, but what to choose? + Int32Call(&DosContext, BIOS_KBD_INTERRUPT); + + /* Restore AX */ + setAX(AX); + + /* Return keyboard status */ + return (getZF() == 0); + } + else + { + DWORD FileSizeHigh; + DWORD FileSize = GetFileSize(Handle, &FileSizeHigh); + LONG LocationHigh = 0; + DWORD Location = SetFilePointer(Handle, 0, &LocationHigh, FILE_CURRENT); + + return ((Location != FileSize) || (LocationHigh != FileSizeHigh)); + } +} + +VOID DosPrintCharacter(WORD FileHandle, CHAR Character) +{ + WORD BytesWritten; + + /* Use the file writing function */ + DosWriteFile(FileHandle, &Character, 1, &BytesWritten); +} + +BOOLEAN DosBIOSInitialize(VOID) +{ + PDOS_MCB Mcb = SEGMENT_TO_MCB(FIRST_MCB_SEGMENT); + + LPWSTR SourcePtr, Environment; + LPSTR AsciiString; + DWORD AsciiSize; + LPSTR DestPtr = (LPSTR)SEG_OFF_TO_PTR(SYSTEM_ENV_BLOCK, 0); + +#if 0 + UCHAR i; + CHAR CurrentDirectory[MAX_PATH]; + CHAR DosDirectory[DOS_DIR_LENGTH]; + LPSTR Path; + + FILE *Stream; + WCHAR Buffer[256]; +#endif + + /* Initialize the MCB */ + Mcb->BlockType = 'Z'; + Mcb->Size = USER_MEMORY_SIZE; + Mcb->OwnerPsp = 0; + + /* Initialize the link MCB to the UMB area */ + Mcb = SEGMENT_TO_MCB(FIRST_MCB_SEGMENT + USER_MEMORY_SIZE + 1); + Mcb->BlockType = 'M'; + Mcb->Size = UMB_START_SEGMENT - FIRST_MCB_SEGMENT - USER_MEMORY_SIZE - 2; + Mcb->OwnerPsp = SYSTEM_PSP; + + /* Initialize the UMB area */ + Mcb = SEGMENT_TO_MCB(UMB_START_SEGMENT); + Mcb->BlockType = 'Z'; + Mcb->Size = UMB_END_SEGMENT - UMB_START_SEGMENT; + Mcb->OwnerPsp = 0; + + /* Get the environment strings */ + SourcePtr = Environment = GetEnvironmentStringsW(); + if (Environment == NULL) return FALSE; + + /* Fill the DOS system environment block */ + while (*SourcePtr) + { + /* Get the size of the ASCII string */ + AsciiSize = WideCharToMultiByte(CP_ACP, + 0, + SourcePtr, + -1, + NULL, + 0, + NULL, + NULL); + + /* Allocate memory for the ASCII string */ + AsciiString = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, AsciiSize); + if (AsciiString == NULL) + { + FreeEnvironmentStringsW(Environment); + return FALSE; + } + + /* Convert to ASCII */ + WideCharToMultiByte(CP_ACP, + 0, + SourcePtr, + -1, + AsciiString, + AsciiSize, + NULL, + NULL); + + /* Copy the string into DOS memory */ + strcpy(DestPtr, AsciiString); + + /* Move to the next string */ + SourcePtr += wcslen(SourcePtr) + 1; + DestPtr += strlen(AsciiString); + *(DestPtr++) = 0; + + /* Free the memory */ + HeapFree(GetProcessHeap(), 0, AsciiString); + } + *DestPtr = 0; + + /* Free the memory allocated for environment strings */ + FreeEnvironmentStringsW(Environment); + + +#if 0 + + /* Clear the current directory buffer */ + ZeroMemory(CurrentDirectories, sizeof(CurrentDirectories)); + + /* Get the current directory */ + if (!GetCurrentDirectoryA(MAX_PATH, CurrentDirectory)) + { + // TODO: Use some kind of default path? + return FALSE; + } + + /* Convert that to a DOS path */ + if (!GetShortPathNameA(CurrentDirectory, DosDirectory, DOS_DIR_LENGTH)) + { + // TODO: Use some kind of default path? + return FALSE; + } + + /* Set the drive */ + CurrentDrive = DosDirectory[0] - 'A'; + + /* Get the directory part of the path */ + Path = strchr(DosDirectory, '\\'); + if (Path != NULL) + { + /* Skip the backslash */ + Path++; + } + + /* Set the directory */ + if (Path != NULL) + { + strncpy(CurrentDirectories[CurrentDrive], Path, DOS_DIR_LENGTH); + } + + /* Read CONFIG.SYS */ + Stream = _wfopen(DOS_CONFIG_PATH, L"r"); + if (Stream != NULL) + { + while (fgetws(Buffer, sizeof(Buffer)/sizeof(Buffer[0]), Stream)) + { + // TODO: Parse the line + } + fclose(Stream); + } + +#endif + + + /* Register the DOS 32-bit Interrupts */ + // RegisterDosInt32(0x20, DosInt20h); + + /* Initialize the DOS kernel */ + return DosKRNLInitialize(); +} + +/* EOF */ diff --git a/subsystems/ntvdm/dos/dos32krnl/dos.c b/subsystems/ntvdm/dos/dos32krnl/dos.c new file mode 100644 index 00000000000..6ce7e3faf76 --- /dev/null +++ b/subsystems/ntvdm/dos/dos32krnl/dos.c @@ -0,0 +1,2581 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: dos/dos32krnl/dos.c + * PURPOSE: VDM DOS Kernel + * PROGRAMMERS: Aleksandar Andrejevic + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "callback.h" + +#include "dos.h" +#include "dos/dem.h" + +#include "bios/bios.h" +#include "registers.h" + +/* PRIVATE VARIABLES **********************************************************/ + +CALLBACK16 DosContext; + +static WORD CurrentPsp = SYSTEM_PSP; +static WORD DosLastError = 0; +static DWORD DiskTransferArea; +/*static*/ BYTE CurrentDrive; +static CHAR LastDrive = 'E'; +static CHAR CurrentDirectories[NUM_DRIVES][DOS_DIR_LENGTH]; + +static struct +{ + HANDLE Handle; + WORD RefCount; +} DosSystemFileTable[DOS_SFT_SIZE]; + +static BYTE DosAllocStrategy = DOS_ALLOC_BEST_FIT; +static BOOLEAN DosUmbLinked = FALSE; +static WORD DosErrorLevel = 0x0000; + +/* PRIVATE FUNCTIONS **********************************************************/ + +/* + * Memory management functions + */ +static VOID DosCombineFreeBlocks(WORD StartBlock) +{ + PDOS_MCB CurrentMcb = SEGMENT_TO_MCB(StartBlock), NextMcb; + + /* If this is the last block or it's not free, quit */ + if (CurrentMcb->BlockType == 'Z' || CurrentMcb->OwnerPsp != 0) return; + + while (TRUE) + { + /* Get a pointer to the next MCB */ + NextMcb = SEGMENT_TO_MCB(StartBlock + CurrentMcb->Size + 1); + + /* Check if the next MCB is free */ + if (NextMcb->OwnerPsp == 0) + { + /* Combine them */ + CurrentMcb->Size += NextMcb->Size + 1; + CurrentMcb->BlockType = NextMcb->BlockType; + NextMcb->BlockType = 'I'; + } + else + { + /* No more adjoining free blocks */ + break; + } + } +} + +static WORD DosAllocateMemory(WORD Size, WORD *MaxAvailable) +{ + WORD Result = 0, Segment = FIRST_MCB_SEGMENT, MaxSize = 0; + PDOS_MCB CurrentMcb, NextMcb; + BOOLEAN SearchUmb = FALSE; + + DPRINT("DosAllocateMemory: Size 0x%04X\n", Size); + + if (DosUmbLinked && (DosAllocStrategy & (DOS_ALLOC_HIGH | DOS_ALLOC_HIGH_LOW))) + { + /* Search UMB first */ + Segment = UMB_START_SEGMENT; + SearchUmb = TRUE; + } + + while (TRUE) + { + /* Get a pointer to the MCB */ + CurrentMcb = SEGMENT_TO_MCB(Segment); + + /* Make sure it's valid */ + if (CurrentMcb->BlockType != 'M' && CurrentMcb->BlockType != 'Z') + { + DPRINT("The DOS memory arena is corrupted!\n"); + DosLastError = ERROR_ARENA_TRASHED; + return 0; + } + + /* Only check free blocks */ + if (CurrentMcb->OwnerPsp != 0) goto Next; + + /* Combine this free block with adjoining free blocks */ + DosCombineFreeBlocks(Segment); + + /* Update the maximum block size */ + if (CurrentMcb->Size > MaxSize) MaxSize = CurrentMcb->Size; + + /* Check if this block is big enough */ + if (CurrentMcb->Size < Size) goto Next; + + switch (DosAllocStrategy & 0x3F) + { + case DOS_ALLOC_FIRST_FIT: + { + /* For first fit, stop immediately */ + Result = Segment; + goto Done; + } + + case DOS_ALLOC_BEST_FIT: + { + /* For best fit, update the smallest block found so far */ + if ((Result == 0) || (CurrentMcb->Size < SEGMENT_TO_MCB(Result)->Size)) + { + Result = Segment; + } + + break; + } + + case DOS_ALLOC_LAST_FIT: + { + /* For last fit, make the current block the result, but keep searching */ + Result = Segment; + break; + } + } + +Next: + /* If this was the last MCB in the chain, quit */ + if (CurrentMcb->BlockType == 'Z') + { + /* Check if nothing was found while searching through UMBs */ + if ((Result == 0) && SearchUmb && (DosAllocStrategy & DOS_ALLOC_HIGH_LOW)) + { + /* Search low memory */ + Segment = FIRST_MCB_SEGMENT; + continue; + } + + break; + } + + /* Otherwise, update the segment and continue */ + Segment += CurrentMcb->Size + 1; + } + +Done: + + /* If we didn't find a free block, return 0 */ + if (Result == 0) + { + DosLastError = ERROR_NOT_ENOUGH_MEMORY; + if (MaxAvailable) *MaxAvailable = MaxSize; + return 0; + } + + /* Get a pointer to the MCB */ + CurrentMcb = SEGMENT_TO_MCB(Result); + + /* Check if the block is larger than requested */ + if (CurrentMcb->Size > Size) + { + /* It is, split it into two blocks */ + NextMcb = SEGMENT_TO_MCB(Result + Size + 1); + + /* Initialize the new MCB structure */ + NextMcb->BlockType = CurrentMcb->BlockType; + NextMcb->Size = CurrentMcb->Size - Size - 1; + NextMcb->OwnerPsp = 0; + + /* Update the current block */ + CurrentMcb->BlockType = 'M'; + CurrentMcb->Size = Size; + } + + /* Take ownership of the block */ + CurrentMcb->OwnerPsp = CurrentPsp; + + /* Return the segment of the data portion of the block */ + return Result + 1; +} + +static BOOLEAN DosResizeMemory(WORD BlockData, WORD NewSize, WORD *MaxAvailable) +{ + BOOLEAN Success = TRUE; + WORD Segment = BlockData - 1, ReturnSize = 0, NextSegment; + PDOS_MCB Mcb = SEGMENT_TO_MCB(Segment), NextMcb; + + DPRINT("DosResizeMemory: BlockData 0x%04X, NewSize 0x%04X\n", + BlockData, + NewSize); + + /* Make sure this is a valid, allocated block */ + if ((Mcb->BlockType != 'M' && Mcb->BlockType != 'Z') || Mcb->OwnerPsp == 0) + { + Success = FALSE; + DosLastError = ERROR_INVALID_HANDLE; + goto Done; + } + + ReturnSize = Mcb->Size; + + /* Check if we need to expand or contract the block */ + if (NewSize > Mcb->Size) + { + /* We can't expand the last block */ + if (Mcb->BlockType != 'M') + { + Success = FALSE; + goto Done; + } + + /* Get the pointer and segment of the next MCB */ + NextSegment = Segment + Mcb->Size + 1; + NextMcb = SEGMENT_TO_MCB(NextSegment); + + /* Make sure the next segment is free */ + if (NextMcb->OwnerPsp != 0) + { + DPRINT("Cannot expand memory block: next segment is not free!\n"); + DosLastError = ERROR_NOT_ENOUGH_MEMORY; + Success = FALSE; + goto Done; + } + + /* Combine this free block with adjoining free blocks */ + DosCombineFreeBlocks(NextSegment); + + /* Set the maximum possible size of the block */ + ReturnSize += NextMcb->Size + 1; + + /* Maximize the current block */ + Mcb->Size = ReturnSize; + Mcb->BlockType = NextMcb->BlockType; + + /* Invalidate the next block */ + NextMcb->BlockType = 'I'; + + /* Check if the block is larger than requested */ + if (Mcb->Size > NewSize) + { + DPRINT("Block too large, reducing size from 0x%04X to 0x%04X\n", + Mcb->Size, + NewSize); + + /* It is, split it into two blocks */ + NextMcb = SEGMENT_TO_MCB(Segment + NewSize + 1); + + /* Initialize the new MCB structure */ + NextMcb->BlockType = Mcb->BlockType; + NextMcb->Size = Mcb->Size - NewSize - 1; + NextMcb->OwnerPsp = 0; + + /* Update the current block */ + Mcb->BlockType = 'M'; + Mcb->Size = NewSize; + } + } + else if (NewSize < Mcb->Size) + { + DPRINT("Shrinking block from 0x%04X to 0x%04X\n", + Mcb->Size, + NewSize); + + /* Just split the block */ + NextMcb = SEGMENT_TO_MCB(Segment + NewSize + 1); + NextMcb->BlockType = Mcb->BlockType; + NextMcb->Size = Mcb->Size - NewSize - 1; + NextMcb->OwnerPsp = 0; + + /* Update the MCB */ + Mcb->BlockType = 'M'; + Mcb->Size = NewSize; + } + +Done: + /* Check if the operation failed */ + if (!Success) + { + DPRINT("DosResizeMemory FAILED. Maximum available: 0x%04X\n", + ReturnSize); + + /* Return the maximum possible size */ + if (MaxAvailable) *MaxAvailable = ReturnSize; + } + + return Success; +} + +static BOOLEAN DosFreeMemory(WORD BlockData) +{ + PDOS_MCB Mcb = SEGMENT_TO_MCB(BlockData - 1); + + DPRINT("DosFreeMemory: BlockData 0x%04X\n", BlockData); + + /* Make sure the MCB is valid */ + if (Mcb->BlockType != 'M' && Mcb->BlockType != 'Z') + { + DPRINT("MCB block type '%c' not valid!\n", Mcb->BlockType); + return FALSE; + } + + /* Mark the block as free */ + Mcb->OwnerPsp = 0; + + return TRUE; +} + +static BOOLEAN DosLinkUmb(VOID) +{ + DWORD Segment = FIRST_MCB_SEGMENT; + PDOS_MCB Mcb = SEGMENT_TO_MCB(Segment); + + DPRINT("Linking UMB\n"); + + /* Check if UMBs are already linked */ + if (DosUmbLinked) return FALSE; + + /* Find the last block */ + while ((Mcb->BlockType == 'M') && (Segment <= 0xFFFF)) + { + Segment += Mcb->Size + 1; + Mcb = SEGMENT_TO_MCB(Segment); + } + + /* Make sure it's valid */ + if (Mcb->BlockType != 'Z') return FALSE; + + /* Connect the MCB with the UMB chain */ + Mcb->BlockType = 'M'; + + DosUmbLinked = TRUE; + return TRUE; +} + +static BOOLEAN DosUnlinkUmb(VOID) +{ + DWORD Segment = FIRST_MCB_SEGMENT; + PDOS_MCB Mcb = SEGMENT_TO_MCB(Segment); + + DPRINT("Unlinking UMB\n"); + + /* Check if UMBs are already unlinked */ + if (!DosUmbLinked) return FALSE; + + /* Find the block preceding the MCB that links it with the UMB chain */ + while (Segment <= 0xFFFF) + { + if ((Segment + Mcb->Size) == (FIRST_MCB_SEGMENT + USER_MEMORY_SIZE)) + { + /* This is the last non-UMB segment */ + break; + } + + /* Advance to the next MCB */ + Segment += Mcb->Size + 1; + Mcb = SEGMENT_TO_MCB(Segment); + } + + /* Mark the MCB as the last MCB */ + Mcb->BlockType = 'Z'; + + DosUmbLinked = FALSE; + return TRUE; +} + +static VOID DosChangeMemoryOwner(WORD Segment, WORD NewOwner) +{ + PDOS_MCB Mcb = SEGMENT_TO_MCB(Segment - 1); + + /* Just set the owner */ + Mcb->OwnerPsp = NewOwner; +} + +static WORD DosCopyEnvironmentBlock(LPCVOID Environment, LPCSTR ProgramName) +{ + PCHAR Ptr, DestBuffer = NULL; + ULONG TotalSize = 0; + WORD DestSegment; + + Ptr = (PCHAR)Environment; + + /* Calculate the size of the environment block */ + while (*Ptr) + { + TotalSize += strlen(Ptr) + 1; + Ptr += strlen(Ptr) + 1; + } + TotalSize++; + + /* Add the string buffer size */ + TotalSize += strlen(ProgramName) + 1; + + /* Allocate the memory for the environment block */ + DestSegment = DosAllocateMemory((WORD)((TotalSize + 0x0F) >> 4), NULL); + if (!DestSegment) return 0; + + Ptr = (PCHAR)Environment; + + DestBuffer = (PCHAR)SEG_OFF_TO_PTR(DestSegment, 0); + while (*Ptr) + { + /* Copy the string */ + strcpy(DestBuffer, Ptr); + + /* Advance to the next string */ + DestBuffer += strlen(Ptr); + Ptr += strlen(Ptr) + 1; + + /* Put a zero after the string */ + *(DestBuffer++) = 0; + } + + /* Set the final zero */ + *(DestBuffer++) = 0; + + /* Copy the program name after the environment block */ + strcpy(DestBuffer, ProgramName); + + return DestSegment; +} + + + + + + +/* Taken from base/shell/cmd/console.c */ +BOOL IsConsoleHandle(HANDLE hHandle) +{ + DWORD dwMode; + + /* Check whether the handle may be that of a console... */ + if ((GetFileType(hHandle) & FILE_TYPE_CHAR) == 0) return FALSE; + + /* + * It may be. Perform another test... The idea comes from the + * MSDN description of the WriteConsole API: + * + * "WriteConsole fails if it is used with a standard handle + * that is redirected to a file. If an application processes + * multilingual output that can be redirected, determine whether + * the output handle is a console handle (one method is to call + * the GetConsoleMode function and check whether it succeeds). + * If the handle is a console handle, call WriteConsole. If the + * handle is not a console handle, the output is redirected and + * you should call WriteFile to perform the I/O." + */ + return GetConsoleMode(hHandle, &dwMode); +} + +WORD DosOpenHandle(HANDLE Handle) +{ + BYTE i; + WORD DosHandle; + PDOS_PSP PspBlock; + LPBYTE HandleTable; + + /* The system PSP has no handle table */ + if (CurrentPsp == SYSTEM_PSP) return INVALID_DOS_HANDLE; + + /* Get a pointer to the handle table */ + PspBlock = SEGMENT_TO_PSP(CurrentPsp); + HandleTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr); + + /* Find a free entry in the JFT */ + for (DosHandle = 0; DosHandle < PspBlock->HandleTableSize; DosHandle++) + { + if (HandleTable[DosHandle] == 0xFF) break; + } + + /* If there are no free entries, fail */ + if (DosHandle == PspBlock->HandleTableSize) return INVALID_DOS_HANDLE; + + /* Check if the handle is already in the SFT */ + for (i = 0; i < DOS_SFT_SIZE; i++) + { + /* Check if this is the same handle */ + if (DosSystemFileTable[i].Handle != Handle) continue; + + /* Already in the table, reference it */ + DosSystemFileTable[i].RefCount++; + + /* Set the JFT entry to that SFT index */ + HandleTable[DosHandle] = i; + + /* Return the new handle */ + return DosHandle; + } + + /* Add the handle to the SFT */ + for (i = 0; i < DOS_SFT_SIZE; i++) + { + /* Make sure this is an empty table entry */ + if (DosSystemFileTable[i].Handle != INVALID_HANDLE_VALUE) continue; + + /* Initialize the empty table entry */ + DosSystemFileTable[i].Handle = Handle; + DosSystemFileTable[i].RefCount = 1; + + /* Set the JFT entry to that SFT index */ + HandleTable[DosHandle] = i; + + /* Return the new handle */ + return DosHandle; + } + + /* The SFT is full */ + return INVALID_DOS_HANDLE; +} + +HANDLE DosGetRealHandle(WORD DosHandle) +{ + PDOS_PSP PspBlock; + LPBYTE HandleTable; + + /* The system PSP has no handle table */ + if (CurrentPsp == SYSTEM_PSP) return INVALID_HANDLE_VALUE; + + /* Get a pointer to the handle table */ + PspBlock = SEGMENT_TO_PSP(CurrentPsp); + HandleTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr); + + /* Make sure the handle is open */ + if (HandleTable[DosHandle] == 0xFF) return INVALID_HANDLE_VALUE; + + /* Return the Win32 handle */ + return DosSystemFileTable[HandleTable[DosHandle]].Handle; +} + +static VOID DosCopyHandleTable(LPBYTE DestinationTable) +{ + INT i; + PDOS_PSP PspBlock; + LPBYTE SourceTable; + + /* Clear the table first */ + for (i = 0; i < 20; i++) DestinationTable[i] = 0xFF; + + /* Check if this is the initial process */ + if (CurrentPsp == SYSTEM_PSP) + { + /* Set up the standard I/O devices */ + for (i = 0; i <= 2; i++) + { + /* Set the index in the SFT */ + DestinationTable[i] = (BYTE)i; + + /* Increase the reference count */ + DosSystemFileTable[i].RefCount++; + } + + /* Done */ + return; + } + + /* Get the parent PSP block and handle table */ + PspBlock = SEGMENT_TO_PSP(CurrentPsp); + SourceTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr); + + /* Copy the first 20 handles into the new table */ + for (i = 0; i < 20; i++) + { + DestinationTable[i] = SourceTable[i]; + + /* Increase the reference count */ + DosSystemFileTable[SourceTable[i]].RefCount++; + } +} + +static BOOLEAN DosCloseHandle(WORD DosHandle) +{ + BYTE SftIndex; + PDOS_PSP PspBlock; + LPBYTE HandleTable; + + DPRINT("DosCloseHandle: DosHandle 0x%04X\n", DosHandle); + + /* The system PSP has no handle table */ + if (CurrentPsp == SYSTEM_PSP) return FALSE; + + /* Get a pointer to the handle table */ + PspBlock = SEGMENT_TO_PSP(CurrentPsp); + HandleTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr); + + /* Make sure the handle is open */ + if (HandleTable[DosHandle] == 0xFF) return FALSE; + + /* Decrement the reference count of the SFT entry */ + SftIndex = HandleTable[DosHandle]; + DosSystemFileTable[SftIndex].RefCount--; + + /* Check if the reference count fell to zero */ + if (!DosSystemFileTable[SftIndex].RefCount) + { + /* Close the file, it's no longer needed */ + CloseHandle(DosSystemFileTable[SftIndex].Handle); + + /* Clear the handle */ + DosSystemFileTable[SftIndex].Handle = INVALID_HANDLE_VALUE; + } + + /* Clear the entry in the JFT */ + HandleTable[DosHandle] = 0xFF; + + return TRUE; +} + +static BOOLEAN DosDuplicateHandle(WORD OldHandle, WORD NewHandle) +{ + BYTE SftIndex; + PDOS_PSP PspBlock; + LPBYTE HandleTable; + + DPRINT("DosDuplicateHandle: OldHandle 0x%04X, NewHandle 0x%04X\n", + OldHandle, + NewHandle); + + /* The system PSP has no handle table */ + if (CurrentPsp == SYSTEM_PSP) return FALSE; + + /* Get a pointer to the handle table */ + PspBlock = SEGMENT_TO_PSP(CurrentPsp); + HandleTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr); + + /* Make sure the old handle is open */ + if (HandleTable[OldHandle] == 0xFF) return FALSE; + + /* Check if the new handle is open */ + if (HandleTable[NewHandle] != 0xFF) + { + /* Close it */ + DosCloseHandle(NewHandle); + } + + /* Increment the reference count of the SFT entry */ + SftIndex = HandleTable[OldHandle]; + DosSystemFileTable[SftIndex].RefCount++; + + /* Make the new handle point to that SFT entry */ + HandleTable[NewHandle] = SftIndex; + + /* Return success */ + return TRUE; +} + + + + + + + +static BOOLEAN DosChangeDrive(BYTE Drive) +{ + WCHAR DirectoryPath[DOS_CMDLINE_LENGTH]; + + /* Make sure the drive exists */ + if (Drive > (LastDrive - 'A')) return FALSE; + + /* Find the path to the new current directory */ + swprintf(DirectoryPath, L"%c\\%S", Drive + 'A', CurrentDirectories[Drive]); + + /* Change the current directory of the process */ + if (!SetCurrentDirectory(DirectoryPath)) return FALSE; + + /* Set the current drive */ + CurrentDrive = Drive; + + /* Return success */ + return TRUE; +} + +static BOOLEAN DosChangeDirectory(LPSTR Directory) +{ + BYTE DriveNumber; + DWORD Attributes; + LPSTR Path; + + /* Make sure the directory path is not too long */ + if (strlen(Directory) >= DOS_DIR_LENGTH) + { + DosLastError = ERROR_PATH_NOT_FOUND; + return FALSE; + } + + /* Get the drive number */ + DriveNumber = Directory[0] - 'A'; + + /* Make sure the drive exists */ + if (DriveNumber > (LastDrive - 'A')) + { + DosLastError = ERROR_PATH_NOT_FOUND; + return FALSE; + } + + /* Get the file attributes */ + Attributes = GetFileAttributesA(Directory); + + /* Make sure the path exists and is a directory */ + if ((Attributes == INVALID_FILE_ATTRIBUTES) + || !(Attributes & FILE_ATTRIBUTE_DIRECTORY)) + { + DosLastError = ERROR_PATH_NOT_FOUND; + return FALSE; + } + + /* Check if this is the current drive */ + if (DriveNumber == CurrentDrive) + { + /* Change the directory */ + if (!SetCurrentDirectoryA(Directory)) + { + DosLastError = LOWORD(GetLastError()); + return FALSE; + } + } + + /* Get the directory part of the path */ + Path = strchr(Directory, '\\'); + if (Path != NULL) + { + /* Skip the backslash */ + Path++; + } + + /* Set the directory for the drive */ + if (Path != NULL) + { + strncpy(CurrentDirectories[DriveNumber], Path, DOS_DIR_LENGTH); + } + else + { + CurrentDirectories[DriveNumber][0] = '\0'; + } + + /* Return success */ + return TRUE; +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID DosInitializePsp(WORD PspSegment, LPCSTR CommandLine, WORD ProgramSize, WORD Environment) +{ + PDOS_PSP PspBlock = SEGMENT_TO_PSP(PspSegment); + LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress); + + ZeroMemory(PspBlock, sizeof(DOS_PSP)); + + /* Set the exit interrupt */ + PspBlock->Exit[0] = 0xCD; // int 0x20 + PspBlock->Exit[1] = 0x20; + + /* Set the number of the last paragraph */ + PspBlock->LastParagraph = PspSegment + ProgramSize - 1; + + /* Save the interrupt vectors */ + PspBlock->TerminateAddress = IntVecTable[0x22]; + PspBlock->BreakAddress = IntVecTable[0x23]; + PspBlock->CriticalAddress = IntVecTable[0x24]; + + /* Set the parent PSP */ + PspBlock->ParentPsp = CurrentPsp; + + /* Copy the parent handle table */ + DosCopyHandleTable(PspBlock->HandleTable); + + /* Set the environment block */ + PspBlock->EnvBlock = Environment; + + /* Set the handle table pointers to the internal handle table */ + PspBlock->HandleTableSize = 20; + PspBlock->HandleTablePtr = MAKELONG(0x18, PspSegment); + + /* Set the DOS version */ + PspBlock->DosVersion = DOS_VERSION; + + /* Set the far call opcodes */ + PspBlock->FarCall[0] = 0xCD; // int 0x21 + PspBlock->FarCall[1] = 0x21; + PspBlock->FarCall[2] = 0xCB; // retf + + /* Set the command line */ + PspBlock->CommandLineSize = (BYTE)min(strlen(CommandLine), DOS_CMDLINE_LENGTH - 1); + RtlCopyMemory(PspBlock->CommandLine, CommandLine, PspBlock->CommandLineSize); + PspBlock->CommandLine[PspBlock->CommandLineSize] = '\r'; +} + +DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType, + IN LPCSTR ExecutablePath, + IN LPCSTR CommandLine, + IN PVOID Environment, + OUT PDWORD StackLocation OPTIONAL, + OUT PDWORD EntryPoint OPTIONAL) +{ + DWORD Result = ERROR_SUCCESS; + HANDLE FileHandle = INVALID_HANDLE_VALUE, FileMapping = NULL; + LPBYTE Address = NULL; + WORD Segment = 0; + WORD EnvBlock = 0; + WORD MaxAllocSize; + DWORD i, FileSize, ExeSize; + PIMAGE_DOS_HEADER Header; + PDWORD RelocationTable; + PWORD RelocWord; + + DPRINT1("DosLoadExecutable(%d, %s, %s, %s, 0x%08X, 0x%08X)\n", + LoadType, + ExecutablePath, + CommandLine, + Environment, + StackLocation, + EntryPoint); + + if (LoadType == DOS_LOAD_OVERLAY) + { + DPRINT1("Overlay loading is not supported yet.\n"); + return ERROR_NOT_SUPPORTED; + } + + /* Open a handle to the executable */ + FileHandle = CreateFileA(ExecutablePath, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (FileHandle == INVALID_HANDLE_VALUE) + { + Result = GetLastError(); + goto Cleanup; + } + + /* Get the file size */ + FileSize = GetFileSize(FileHandle, NULL); + + /* Create a mapping object for the file */ + FileMapping = CreateFileMapping(FileHandle, + NULL, + PAGE_READONLY, + 0, + 0, + NULL); + if (FileMapping == NULL) + { + Result = GetLastError(); + goto Cleanup; + } + + /* Map the file into memory */ + Address = (LPBYTE)MapViewOfFile(FileMapping, FILE_MAP_READ, 0, 0, 0); + if (Address == NULL) + { + Result = GetLastError(); + goto Cleanup; + } + + /* Copy the environment block to DOS memory */ + EnvBlock = DosCopyEnvironmentBlock(Environment, ExecutablePath); + if (EnvBlock == 0) + { + Result = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + /* Check if this is an EXE file or a COM file */ + if (Address[0] == 'M' && Address[1] == 'Z') + { + /* EXE file */ + + /* Get the MZ header */ + Header = (PIMAGE_DOS_HEADER)Address; + + /* Get the base size of the file, in paragraphs (rounded up) */ + ExeSize = (((Header->e_cp - 1) * 512) + Header->e_cblp + 0x0F) >> 4; + + /* Add the PSP size, in paragraphs */ + ExeSize += sizeof(DOS_PSP) >> 4; + + /* Add the maximum size that should be allocated */ + ExeSize += Header->e_maxalloc; + + /* Make sure it does not pass 0xFFFF */ + if (ExeSize > 0xFFFF) ExeSize = 0xFFFF; + + /* Reduce the size one by one until the allocation is successful */ + for (i = Header->e_maxalloc; i >= Header->e_minalloc; i--, ExeSize--) + { + /* Try to allocate that much memory */ + Segment = DosAllocateMemory((WORD)ExeSize, NULL); + if (Segment != 0) break; + } + + /* Check if at least the lowest allocation was successful */ + if (Segment == 0) + { + Result = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + /* Initialize the PSP */ + DosInitializePsp(Segment, + CommandLine, + (WORD)ExeSize, + EnvBlock); + + /* The process owns its own memory */ + DosChangeMemoryOwner(Segment, Segment); + DosChangeMemoryOwner(EnvBlock, Segment); + + /* Copy the program to Segment:0100 */ + RtlCopyMemory(SEG_OFF_TO_PTR(Segment, 0x100), + Address + (Header->e_cparhdr << 4), + min(FileSize - (Header->e_cparhdr << 4), + (ExeSize << 4) - sizeof(DOS_PSP))); + + /* Get the relocation table */ + RelocationTable = (PDWORD)(Address + Header->e_lfarlc); + + /* Perform relocations */ + for (i = 0; i < Header->e_crlc; i++) + { + /* Get a pointer to the word that needs to be patched */ + RelocWord = (PWORD)SEG_OFF_TO_PTR(Segment + HIWORD(RelocationTable[i]), + 0x100 + LOWORD(RelocationTable[i])); + + /* Add the number of the EXE segment to it */ + *RelocWord += Segment + (sizeof(DOS_PSP) >> 4); + } + + if (LoadType == DOS_LOAD_AND_EXECUTE) + { + /* Set the initial segment registers */ + setDS(Segment); + setES(Segment); + + /* Set the stack to the location from the header */ + EmulatorSetStack(Segment + (sizeof(DOS_PSP) >> 4) + Header->e_ss, + Header->e_sp); + + /* Execute */ + CurrentPsp = Segment; + DiskTransferArea = MAKELONG(0x80, Segment); + EmulatorExecute(Segment + Header->e_cs + (sizeof(DOS_PSP) >> 4), + Header->e_ip); + } + } + else + { + /* COM file */ + + /* Find the maximum amount of memory that can be allocated */ + DosAllocateMemory(0xFFFF, &MaxAllocSize); + + /* Make sure it's enough for the whole program and the PSP */ + if (((DWORD)MaxAllocSize << 4) < (FileSize + sizeof(DOS_PSP))) + { + Result = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + /* Allocate all of it */ + Segment = DosAllocateMemory(MaxAllocSize, NULL); + if (Segment == 0) + { + Result = ERROR_ARENA_TRASHED; + goto Cleanup; + } + + /* The process owns its own memory */ + DosChangeMemoryOwner(Segment, Segment); + DosChangeMemoryOwner(EnvBlock, Segment); + + /* Copy the program to Segment:0100 */ + RtlCopyMemory(SEG_OFF_TO_PTR(Segment, 0x100), + Address, + FileSize); + + /* Initialize the PSP */ + DosInitializePsp(Segment, + CommandLine, + MaxAllocSize, + EnvBlock); + + if (LoadType == DOS_LOAD_AND_EXECUTE) + { + /* Set the initial segment registers */ + setDS(Segment); + setES(Segment); + + /* Set the stack to the last word of the segment */ + EmulatorSetStack(Segment, 0xFFFE); + + /* + * Set the value on the stack to 0, so that a near return + * jumps to PSP:0000 which has the exit code. + */ + *((LPWORD)SEG_OFF_TO_PTR(Segment, 0xFFFE)) = 0; + + /* Execute */ + CurrentPsp = Segment; + DiskTransferArea = MAKELONG(0x80, Segment); + EmulatorExecute(Segment, 0x100); + } + } + +Cleanup: + if (Result != ERROR_SUCCESS) + { + /* It was not successful, cleanup the DOS memory */ + if (EnvBlock) DosFreeMemory(EnvBlock); + if (Segment) DosFreeMemory(Segment); + } + + /* Unmap the file*/ + if (Address != NULL) UnmapViewOfFile(Address); + + /* Close the file mapping object */ + if (FileMapping != NULL) CloseHandle(FileMapping); + + /* Close the file handle */ + if (FileHandle != INVALID_HANDLE_VALUE) CloseHandle(FileHandle); + + return Result; +} + +DWORD DosStartProcess(IN LPCSTR ExecutablePath, + IN LPCSTR CommandLine, + IN PVOID Environment) +{ + DWORD Result; + + Result = DosLoadExecutable(DOS_LOAD_AND_EXECUTE, + ExecutablePath, + CommandLine, + Environment, + NULL, + NULL); + + if (Result != ERROR_SUCCESS) goto Quit; + + /* Attach to the console */ + VidBiosAttachToConsole(); // FIXME: And in fact, attach the full NTVDM UI to the console + + /* Start simulation */ + SetEvent(VdmTaskEvent); + EmulatorSimulate(); + + /* Detach from the console */ + VidBiosDetachFromConsole(); // FIXME: And in fact, detach the full NTVDM UI from the console + +Quit: + return Result; +} + +#ifndef STANDALONE +WORD DosCreateProcess(DOS_EXEC_TYPE LoadType, + LPCSTR ProgramName, + PDOS_EXEC_PARAM_BLOCK Parameters) +{ + DWORD Result; + DWORD BinaryType; + LPVOID Environment = NULL; + VDM_COMMAND_INFO CommandInfo; + CHAR CmdLine[MAX_PATH]; + CHAR AppName[MAX_PATH]; + CHAR PifFile[MAX_PATH]; + CHAR Desktop[MAX_PATH]; + CHAR Title[MAX_PATH]; + CHAR Env[MAX_PATH]; + STARTUPINFOA StartupInfo; + PROCESS_INFORMATION ProcessInfo; + + /* Get the binary type */ + if (!GetBinaryTypeA(ProgramName, &BinaryType)) return GetLastError(); + + /* Did the caller specify an environment segment? */ + if (Parameters->Environment) + { + /* Yes, use it instead of the parent one */ + Environment = SEG_OFF_TO_PTR(Parameters->Environment, 0); + } + + /* Set up the startup info structure */ + ZeroMemory(&StartupInfo, sizeof(STARTUPINFOA)); + StartupInfo.cb = sizeof(STARTUPINFOA); + + /* Create the process */ + if (!CreateProcessA(ProgramName, + FAR_POINTER(Parameters->CommandLine), + NULL, + NULL, + FALSE, + 0, + Environment, + NULL, + &StartupInfo, + &ProcessInfo)) + { + return GetLastError(); + } + + /* Check the type of the program */ + switch (BinaryType) + { + /* These are handled by NTVDM */ + case SCS_DOS_BINARY: + case SCS_WOW_BINARY: + { + /* Clear the structure */ + ZeroMemory(&CommandInfo, sizeof(CommandInfo)); + + /* Initialize the structure members */ + CommandInfo.TaskId = SessionId; + CommandInfo.VDMState = VDM_FLAG_NESTED_TASK | VDM_FLAG_DONT_WAIT; + CommandInfo.CmdLine = CmdLine; + CommandInfo.CmdLen = sizeof(CmdLine); + CommandInfo.AppName = AppName; + CommandInfo.AppLen = sizeof(AppName); + CommandInfo.PifFile = PifFile; + CommandInfo.PifLen = sizeof(PifFile); + CommandInfo.Desktop = Desktop; + CommandInfo.DesktopLen = sizeof(Desktop); + CommandInfo.Title = Title; + CommandInfo.TitleLen = sizeof(Title); + CommandInfo.Env = Env; + CommandInfo.EnvLen = sizeof(Env); + + /* Get the VDM command information */ + if (!GetNextVDMCommand(&CommandInfo)) + { + /* Shouldn't happen */ + ASSERT(FALSE); + } + + /* Increment the re-entry count */ + CommandInfo.VDMState = VDM_INC_REENTER_COUNT; + GetNextVDMCommand(&CommandInfo); + + /* Load the executable */ + Result = DosLoadExecutable(LoadType, + AppName, + CmdLine, + Env, + &Parameters->StackLocation, + &Parameters->EntryPoint); + if (Result != ERROR_SUCCESS) + { + DisplayMessage(L"Could not load '%S'. Error: %u", AppName, Result); + // FIXME: Decrement the reenter count. Or, instead, just increment + // the VDM reenter count *only* if this call succeeds... + } + + break; + } + + /* Not handled by NTVDM */ + default: + { + /* Wait for the process to finish executing */ + WaitForSingleObject(ProcessInfo.hProcess, INFINITE); + } + } + + /* Close the handles */ + CloseHandle(ProcessInfo.hProcess); + CloseHandle(ProcessInfo.hThread); + + return ERROR_SUCCESS; +} +#endif + +VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode) +{ + WORD i; + WORD McbSegment = FIRST_MCB_SEGMENT; + PDOS_MCB CurrentMcb; + LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress); + PDOS_PSP PspBlock = SEGMENT_TO_PSP(Psp); + + DPRINT("DosTerminateProcess: Psp 0x%04X, ReturnCode 0x%02X\n", + Psp, + ReturnCode); + + /* Check if this PSP is it's own parent */ + if (PspBlock->ParentPsp == Psp) goto Done; + + for (i = 0; i < PspBlock->HandleTableSize; i++) + { + /* Close the handle */ + DosCloseHandle(i); + } + + /* Free the memory used by the process */ + while (TRUE) + { + /* Get a pointer to the MCB */ + CurrentMcb = SEGMENT_TO_MCB(McbSegment); + + /* Make sure the MCB is valid */ + if (CurrentMcb->BlockType != 'M' && CurrentMcb->BlockType !='Z') break; + + /* If this block was allocated by the process, free it */ + if (CurrentMcb->OwnerPsp == Psp) DosFreeMemory(McbSegment + 1); + + /* If this was the last block, quit */ + if (CurrentMcb->BlockType == 'Z') break; + + /* Update the segment and continue */ + McbSegment += CurrentMcb->Size + 1; + } + +Done: + /* Restore the interrupt vectors */ + IntVecTable[0x22] = PspBlock->TerminateAddress; + IntVecTable[0x23] = PspBlock->BreakAddress; + IntVecTable[0x24] = PspBlock->CriticalAddress; + + /* Update the current PSP */ + if (Psp == CurrentPsp) + { + CurrentPsp = PspBlock->ParentPsp; + if (CurrentPsp == SYSTEM_PSP) + { + ResetEvent(VdmTaskEvent); + EmulatorUnsimulate(); + } + } + +#ifndef STANDALONE + // FIXME: This is probably not the best way to do it + /* Check if this was a nested DOS task */ + if (CurrentPsp != SYSTEM_PSP) + { + VDM_COMMAND_INFO CommandInfo; + + /* Decrement the re-entry count */ + CommandInfo.TaskId = SessionId; + CommandInfo.VDMState = VDM_DEC_REENTER_COUNT; + GetNextVDMCommand(&CommandInfo); + + /* Clear the structure */ + ZeroMemory(&CommandInfo, sizeof(CommandInfo)); + + /* Update the VDM state of the task */ + CommandInfo.TaskId = SessionId; + CommandInfo.VDMState = VDM_FLAG_DONT_WAIT; + GetNextVDMCommand(&CommandInfo); + } +#endif + + /* Save the return code - Normal termination */ + DosErrorLevel = MAKEWORD(ReturnCode, 0x00); + + /* Return control to the parent process */ + EmulatorExecute(HIWORD(PspBlock->TerminateAddress), + LOWORD(PspBlock->TerminateAddress)); +} + +BOOLEAN DosHandleIoctl(BYTE ControlCode, WORD FileHandle) +{ + HANDLE Handle = DosGetRealHandle(FileHandle); + + if (Handle == INVALID_HANDLE_VALUE) + { + /* Doesn't exist */ + DosLastError = ERROR_FILE_NOT_FOUND; + return FALSE; + } + + switch (ControlCode) + { + /* Get Device Information */ + case 0x00: + { + WORD InfoWord = 0; + + /* + * See Ralf Brown: http://www.ctyme.com/intr/rb-2820.htm + * for a list of possible flags. + */ + + if (Handle == DosSystemFileTable[DOS_INPUT_HANDLE].Handle) + { + /* Console input */ + InfoWord |= 1 << 0; + } + else if (Handle == DosSystemFileTable[DOS_OUTPUT_HANDLE].Handle) + { + /* Console output */ + InfoWord |= 1 << 1; + } + + /* It is a device */ + InfoWord |= 1 << 7; + + /* Return the device information word */ + setDX(InfoWord); + return TRUE; + } + + /* Unsupported control code */ + default: + { + DPRINT1("Unsupported IOCTL: 0x%02X\n", ControlCode); + + DosLastError = ERROR_INVALID_PARAMETER; + return FALSE; + } + } +} + +VOID WINAPI DosInt20h(LPWORD Stack) +{ + /* This is the exit interrupt */ + DosTerminateProcess(Stack[STACK_CS], 0); +} + +VOID WINAPI DosInt21h(LPWORD Stack) +{ + BYTE Character; + SYSTEMTIME SystemTime; + PCHAR String; + PDOS_INPUT_BUFFER InputBuffer; + + /* Check the value in the AH register */ + switch (getAH()) + { + /* Terminate Program */ + case 0x00: + { + DosTerminateProcess(Stack[STACK_CS], 0); + break; + } + + /* Read Character from STDIN with Echo */ + case 0x01: + { + // FIXME: Under DOS 2+, input / output handle may be redirected!!!! + Character = DosReadCharacter(DOS_INPUT_HANDLE); + DosPrintCharacter(DOS_OUTPUT_HANDLE, Character); + + // /* Let the BOP repeat if needed */ + // if (getCF()) break; + + setAL(Character); + break; + } + + /* Write Character to STDOUT */ + case 0x02: + { + // FIXME: Under DOS 2+, output handle may be redirected!!!! + Character = getDL(); + DosPrintCharacter(DOS_OUTPUT_HANDLE, Character); + + /* + * We return the output character (DOS 2.1+). + * Also, if we're going to output a TAB, then + * don't return a TAB but a SPACE instead. + * See Ralf Brown: http://www.ctyme.com/intr/rb-2554.htm + * for more information. + */ + setAL(Character == '\t' ? ' ' : Character); + break; + } + + /* Read Character from STDAUX */ + case 0x03: + { + // FIXME: Really read it from STDAUX! + DPRINT1("INT 16h, 03h: Read character from STDAUX is HALFPLEMENTED\n"); + // setAL(DosReadCharacter()); + break; + } + + /* Write Character to STDAUX */ + case 0x04: + { + // FIXME: Really write it to STDAUX! + DPRINT1("INT 16h, 04h: Write character to STDAUX is HALFPLEMENTED\n"); + // DosPrintCharacter(getDL()); + break; + } + + /* Write Character to Printer */ + case 0x05: + { + // FIXME: Really write it to printer! + DPRINT1("INT 16h, 05h: Write character to printer is HALFPLEMENTED -\n\n"); + DPRINT1("0x%p\n", getDL()); + DPRINT1("\n\n-----------\n\n"); + break; + } + + /* Direct Console I/O */ + case 0x06: + { + Character = getDL(); + + // FIXME: Under DOS 2+, output handle may be redirected!!!! + + if (Character != 0xFF) + { + /* Output */ + DosPrintCharacter(DOS_OUTPUT_HANDLE, Character); + + /* + * We return the output character (DOS 2.1+). + * See Ralf Brown: http://www.ctyme.com/intr/rb-2558.htm + * for more information. + */ + setAL(Character); + } + else + { + /* Input */ + if (DosCheckInput()) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_ZF; + setAL(DosReadCharacter(DOS_INPUT_HANDLE)); + } + else + { + /* No character available */ + Stack[STACK_FLAGS] |= EMULATOR_FLAG_ZF; + setAL(0x00); + } + } + + break; + } + + /* Character Input without Echo */ + case 0x07: + case 0x08: + { + // FIXME: Under DOS 2+, input handle may be redirected!!!! + Character = DosReadCharacter(DOS_INPUT_HANDLE); + + // FIXME: For 0x07, do not check Ctrl-C/Break. + // For 0x08, do check those control sequences and if needed, + // call INT 0x23. + + // /* Let the BOP repeat if needed */ + // if (getCF()) break; + + setAL(Character); + break; + } + + /* Write string to STDOUT */ + case 0x09: + { + String = (PCHAR)SEG_OFF_TO_PTR(getDS(), getDX()); + + while (*String != '$') + { + DosPrintCharacter(DOS_OUTPUT_HANDLE, *String); + String++; + } + + /* + * We return the terminating character (DOS 2.1+). + * See Ralf Brown: http://www.ctyme.com/intr/rb-2562.htm + * for more information. + */ + setAL('$'); + break; + } + + /* Read Buffered Input */ + case 0x0A: + { + WORD Count = 0; + InputBuffer = (PDOS_INPUT_BUFFER)SEG_OFF_TO_PTR(getDS(), getDX()); + + DPRINT1("Read Buffered Input\n"); + + while (Count < InputBuffer->MaxLength) + { + /* Try to read a character (wait) */ + Character = DosReadCharacter(DOS_INPUT_HANDLE); + + /* Echo the character and append it to the buffer */ + DosPrintCharacter(DOS_OUTPUT_HANDLE, Character); + InputBuffer->Buffer[Count] = Character; + + if (Character == '\r') break; + Count++; + } + + /* Update the length */ + InputBuffer->Length = Count; + + break; + } + + /* Get STDIN Status */ + case 0x0B: + { + setAL(DosCheckInput() ? 0xFF : 0x00); + break; + } + + /* Flush Buffer and Read STDIN */ + case 0x0C: + { + BYTE InputFunction = getAL(); + + /* Flush STDIN buffer */ + DosFlushFileBuffers(DOS_INPUT_HANDLE); + + /* + * If the input function number contained in AL is valid, i.e. + * AL == 0x01 or 0x06 or 0x07 or 0x08 or 0x0A, call ourselves + * recursively with AL == AH. + */ + if (InputFunction == 0x01 || InputFunction == 0x06 || + InputFunction == 0x07 || InputFunction == 0x08 || + InputFunction == 0x0A) + { + setAH(InputFunction); + /* + * Instead of calling ourselves really recursively as in: + * DosInt21h(Stack); + * prefer resetting the CF flag to let the BOP repeat. + */ + setCF(1); + } + break; + } + + /* Disk Reset */ + case 0x0D: + { + PDOS_PSP PspBlock = SEGMENT_TO_PSP(CurrentPsp); + + // TODO: Flush what's needed. + DPRINT1("INT 21h, 0Dh is UNIMPLEMENTED\n"); + + /* Clear CF in DOS 6 only */ + if (PspBlock->DosVersion == 0x0006) + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + + break; + } + + /* Set Default Drive */ + case 0x0E: + { + DosChangeDrive(getDL()); + setAL(LastDrive - 'A' + 1); + break; + } + + /* NULL Function for CP/M Compatibility */ + case 0x18: + { + /* + * This function corresponds to the CP/M BDOS function + * "get bit map of logged drives", which is meaningless + * under MS-DOS. + * + * For: PTS-DOS 6.51 & S/DOS 1.0 - EXTENDED RENAME FILE USING FCB + * See Ralf Brown: http://www.ctyme.com/intr/rb-2584.htm + * for more information. + */ + setAL(0x00); + break; + } + + /* Get Default Drive */ + case 0x19: + { + setAL(CurrentDrive); + break; + } + + /* Set Disk Transfer Area */ + case 0x1A: + { + DiskTransferArea = MAKELONG(getDX(), getDS()); + break; + } + + /* NULL Function for CP/M Compatibility */ + case 0x1D: + case 0x1E: + { + /* + * Function 0x1D corresponds to the CP/M BDOS function + * "get bit map of read-only drives", which is meaningless + * under MS-DOS. + * See Ralf Brown: http://www.ctyme.com/intr/rb-2592.htm + * for more information. + * + * Function 0x1E corresponds to the CP/M BDOS function + * "set file attributes", which was meaningless under MS-DOS 1.x. + * See Ralf Brown: http://www.ctyme.com/intr/rb-2593.htm + * for more information. + */ + setAL(0x00); + break; + } + + /* NULL Function for CP/M Compatibility */ + case 0x20: + { + /* + * This function corresponds to the CP/M BDOS function + * "get/set default user (sublibrary) number", which is meaningless + * under MS-DOS. + * + * For: S/DOS 1.0+ & PTS-DOS 6.51+ - GET OEM REVISION + * See Ralf Brown: http://www.ctyme.com/intr/rb-2596.htm + * for more information. + */ + setAL(0x00); + break; + } + + /* Set Interrupt Vector */ + case 0x25: + { + ULONG FarPointer = MAKELONG(getDX(), getDS()); + DPRINT1("Setting interrupt 0x%x ...\n", getAL()); + + /* Write the new far pointer to the IDT */ + ((PULONG)BaseAddress)[getAL()] = FarPointer; + break; + } + + /* Create New PSP */ + case 0x26: + { + DPRINT1("INT 21h, 26h - Create New PSP is UNIMPLEMENTED\n"); + break; + } + + /* Get System Date */ + case 0x2A: + { + GetLocalTime(&SystemTime); + setCX(SystemTime.wYear); + setDX(MAKEWORD(SystemTime.wDay, SystemTime.wMonth)); + setAL(SystemTime.wDayOfWeek); + break; + } + + /* Set System Date */ + case 0x2B: + { + GetLocalTime(&SystemTime); + SystemTime.wYear = getCX(); + SystemTime.wMonth = getDH(); + SystemTime.wDay = getDL(); + + /* Return success or failure */ + setAL(SetLocalTime(&SystemTime) ? 0x00 : 0xFF); + break; + } + + /* Get System Time */ + case 0x2C: + { + GetLocalTime(&SystemTime); + setCX(MAKEWORD(SystemTime.wMinute, SystemTime.wHour)); + setDX(MAKEWORD(SystemTime.wMilliseconds / 10, SystemTime.wSecond)); + break; + } + + /* Set System Time */ + case 0x2D: + { + GetLocalTime(&SystemTime); + SystemTime.wHour = getCH(); + SystemTime.wMinute = getCL(); + SystemTime.wSecond = getDH(); + SystemTime.wMilliseconds = getDL() * 10; // In hundredths of seconds + + /* Return success or failure */ + setAL(SetLocalTime(&SystemTime) ? 0x00 : 0xFF); + break; + } + + /* Get Disk Transfer Area */ + case 0x2F: + { + setES(HIWORD(DiskTransferArea)); + setBX(LOWORD(DiskTransferArea)); + break; + } + + /* Get DOS Version */ + case 0x30: + { + PDOS_PSP PspBlock = SEGMENT_TO_PSP(CurrentPsp); + + /* + * DOS 2+ - GET DOS VERSION + * See Ralf Brown: http://www.ctyme.com/intr/rb-2711.htm + * for more information. + */ + + if (LOBYTE(PspBlock->DosVersion) < 5 || getAL() == 0x00) + { + /* + * Return DOS OEM number: + * 0x00 for IBM PC-DOS + * 0x02 for packaged MS-DOS + */ + setBH(0x02); + } + + if (LOBYTE(PspBlock->DosVersion) >= 5 && getAL() == 0x01) + { + /* + * Return version flag: + * 1 << 3 if DOS is in ROM, + * 0 (reserved) if not. + */ + setBH(0x00); + } + + /* Return DOS 24-bit user serial number in BL:CX */ + setBL(0x00); + setCX(0x0000); + + /* + * Return DOS version: Minor:Major in AH:AL + * The Windows NT DOS box returns version 5.00, subject to SETVER. + */ + setAX(PspBlock->DosVersion); + + break; + } + + /* Extended functionalities */ + case 0x33: + { + if (getAL() == 0x06) + { + /* + * DOS 5+ - GET TRUE VERSION NUMBER + * This function always returns the true version number, unlike + * AH=30h, whose return value may be changed with SETVER. + * See Ralf Brown: http://www.ctyme.com/intr/rb-2730.htm + * for more information. + */ + + /* + * Return the true DOS version: Minor:Major in BH:BL + * The Windows NT DOS box returns BX=3205h (version 5.50). + */ + setBX(NTDOS_VERSION); + + /* DOS revision 0 */ + setDL(0x00); + + /* Unpatched DOS */ + setDH(0x00); + } + // else + // { + // /* Invalid subfunction */ + // setAL(0xFF); + // } + + break; + } + + /* Get Interrupt Vector */ + case 0x35: + { + DWORD FarPointer = ((PDWORD)BaseAddress)[getAL()]; + + /* Read the address from the IDT into ES:BX */ + setES(HIWORD(FarPointer)); + setBX(LOWORD(FarPointer)); + break; + } + + /* SWITCH character - AVAILDEV */ + case 0x37: + { + if (getAL() == 0x00) + { + /* + * DOS 2+ - "SWITCHAR" - GET SWITCH CHARACTER + * This setting is ignored by MS-DOS 4.0+. + * MS-DOS 5+ always return AL=00h/DL=2Fh. + * See Ralf Brown: http://www.ctyme.com/intr/rb-2752.htm + * for more information. + */ + setDL('/'); + setAL(0x00); + } + else if (getAL() == 0x01) + { + /* + * DOS 2+ - "SWITCHAR" - SET SWITCH CHARACTER + * This setting is ignored by MS-DOS 5+. + * See Ralf Brown: http://www.ctyme.com/intr/rb-2753.htm + * for more information. + */ + // getDL(); + setAL(0xFF); + } + else if (getAL() == 0x02) + { + /* + * DOS 2.x and 3.3+ only - "AVAILDEV" - SPECIFY \DEV\ PREFIX USE + * See Ralf Brown: http://www.ctyme.com/intr/rb-2754.htm + * for more information. + */ + // setDL(); + setAL(0xFF); + } + else if (getAL() == 0x03) + { + /* + * DOS 2.x and 3.3+ only - "AVAILDEV" - SPECIFY \DEV\ PREFIX USE + * See Ralf Brown: http://www.ctyme.com/intr/rb-2754.htm + * for more information. + */ + // getDL(); + setAL(0xFF); + } + else + { + /* Invalid subfunction */ + setAL(0xFF); + } + + break; + } + + /* Create Directory */ + case 0x39: + { + String = (PCHAR)SEG_OFF_TO_PTR(getDS(), getDX()); + + if (CreateDirectoryA(String, NULL)) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(LOWORD(GetLastError())); + } + + break; + } + + /* Remove Directory */ + case 0x3A: + { + String = (PCHAR)SEG_OFF_TO_PTR(getDS(), getDX()); + + if (RemoveDirectoryA(String)) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(LOWORD(GetLastError())); + } + + break; + } + + /* Set Current Directory */ + case 0x3B: + { + String = (PCHAR)SEG_OFF_TO_PTR(getDS(), getDX()); + + if (DosChangeDirectory(String)) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(DosLastError); + } + + break; + } + + /* Create File */ + case 0x3C: + { + WORD FileHandle; + WORD ErrorCode = DosCreateFile(&FileHandle, + (LPCSTR)SEG_OFF_TO_PTR(getDS(), getDX()), + getCX()); + + if (ErrorCode == 0) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + setAX(FileHandle); + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(ErrorCode); + } + + break; + } + + /* Open File */ + case 0x3D: + { + WORD FileHandle; + WORD ErrorCode = DosOpenFile(&FileHandle, + (LPCSTR)SEG_OFF_TO_PTR(getDS(), getDX()), + getAL()); + + if (ErrorCode == 0) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + setAX(FileHandle); + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(ErrorCode); + } + + break; + } + + /* Close File */ + case 0x3E: + { + if (DosCloseHandle(getBX())) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(ERROR_INVALID_HANDLE); + } + + break; + } + + /* Read from File or Device */ + case 0x3F: + { + WORD BytesRead = 0; + WORD ErrorCode = DosReadFile(getBX(), + SEG_OFF_TO_PTR(getDS(), getDX()), + getCX(), + &BytesRead); + + if (ErrorCode == ERROR_SUCCESS) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + setAX(BytesRead); + } + else if (ErrorCode != ERROR_NOT_READY) + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(ErrorCode); + } + + break; + } + + /* Write to File or Device */ + case 0x40: + { + WORD BytesWritten = 0; + WORD ErrorCode = DosWriteFile(getBX(), + SEG_OFF_TO_PTR(getDS(), getDX()), + getCX(), + &BytesWritten); + + if (ErrorCode == ERROR_SUCCESS) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + setAX(BytesWritten); + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(ErrorCode); + } + + break; + } + + /* Delete File */ + case 0x41: + { + LPSTR FileName = (LPSTR)SEG_OFF_TO_PTR(getDS(), getDX()); + + if (demFileDelete(FileName) == ERROR_SUCCESS) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + /* + * See Ralf Brown: http://www.ctyme.com/intr/rb-2797.htm + * "AX destroyed (DOS 3.3) AL seems to be drive of deleted file." + */ + setAL(FileName[0] - 'A'); + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(GetLastError()); + } + + break; + } + + /* Seek File */ + case 0x42: + { + DWORD NewLocation; + WORD ErrorCode = DosSeekFile(getBX(), + MAKELONG(getDX(), getCX()), + getAL(), + &NewLocation); + + if (ErrorCode == ERROR_SUCCESS) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + + /* Return the new offset in DX:AX */ + setDX(HIWORD(NewLocation)); + setAX(LOWORD(NewLocation)); + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(ErrorCode); + } + + break; + } + + /* Get/Set File Attributes */ + case 0x43: + { + DWORD Attributes; + LPSTR FileName = (LPSTR)SEG_OFF_TO_PTR(getDS(), getDX()); + + if (getAL() == 0x00) + { + /* Get the attributes */ + Attributes = GetFileAttributesA(FileName); + + /* Check if it failed */ + if (Attributes == INVALID_FILE_ATTRIBUTES) + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(GetLastError()); + } + else + { + /* Return the attributes that DOS can understand */ + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + setCX(Attributes & 0x00FF); + } + } + else if (getAL() == 0x01) + { + /* Try to set the attributes */ + if (SetFileAttributesA(FileName, getCL())) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(GetLastError()); + } + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(ERROR_INVALID_FUNCTION); + } + + break; + } + + /* IOCTL */ + case 0x44: + { + if (DosHandleIoctl(getAL(), getBX())) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(DosLastError); + } + + break; + } + + /* Duplicate Handle */ + case 0x45: + { + WORD NewHandle; + HANDLE Handle = DosGetRealHandle(getBX()); + + if (Handle == INVALID_HANDLE_VALUE) + { + /* The handle is invalid */ + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(ERROR_INVALID_HANDLE); + break; + } + + /* Open a new handle to the same entry */ + NewHandle = DosOpenHandle(Handle); + + if (NewHandle == INVALID_DOS_HANDLE) + { + /* Too many files open */ + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(ERROR_TOO_MANY_OPEN_FILES); + break; + } + + /* Return the result */ + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + setAX(NewHandle); + break; + } + + /* Force Duplicate Handle */ + case 0x46: + { + if (DosDuplicateHandle(getBX(), getCX())) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(ERROR_INVALID_HANDLE); + } + + break; + } + + /* Get Current Directory */ + case 0x47: + { + BYTE DriveNumber = getDL(); + String = (PCHAR)SEG_OFF_TO_PTR(getDS(), getSI()); + + /* Get the real drive number */ + if (DriveNumber == 0) + { + DriveNumber = CurrentDrive; + } + else + { + /* Decrement DriveNumber since it was 1-based */ + DriveNumber--; + } + + if (DriveNumber <= LastDrive - 'A') + { + /* + * Copy the current directory into the target buffer. + * It doesn't contain the drive letter and the backslash. + */ + strncpy(String, CurrentDirectories[DriveNumber], DOS_DIR_LENGTH); + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + setAX(0x0100); // Undocumented, see Ralf Brown: http://www.ctyme.com/intr/rb-2933.htm + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(ERROR_INVALID_DRIVE); + } + + break; + } + + /* Allocate Memory */ + case 0x48: + { + WORD MaxAvailable = 0; + WORD Segment = DosAllocateMemory(getBX(), &MaxAvailable); + + if (Segment != 0) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + setAX(Segment); + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(DosLastError); + setBX(MaxAvailable); + } + + break; + } + + /* Free Memory */ + case 0x49: + { + if (DosFreeMemory(getES())) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(ERROR_ARENA_TRASHED); + } + + break; + } + + /* Resize Memory Block */ + case 0x4A: + { + WORD Size; + + if (DosResizeMemory(getES(), getBX(), &Size)) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(DosLastError); + setBX(Size); + } + + break; + } + +#ifndef STANDALONE + /* Execute */ + case 0x4B: + { + DOS_EXEC_TYPE LoadType = (DOS_EXEC_TYPE)getAL(); + LPSTR ProgramName = SEG_OFF_TO_PTR(getDS(), getDX()); + PDOS_EXEC_PARAM_BLOCK ParamBlock = SEG_OFF_TO_PTR(getES(), getBX()); + WORD ErrorCode = DosCreateProcess(LoadType, ProgramName, ParamBlock); + + if (ErrorCode == ERROR_SUCCESS) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(ErrorCode); + } + + break; + } +#endif + + /* Terminate With Return Code */ + case 0x4C: + { + DosTerminateProcess(CurrentPsp, getAL()); + break; + } + + /* Get Return Code (ERRORLEVEL) */ + case 0x4D: + { + /* + * According to Ralf Brown: http://www.ctyme.com/intr/rb-2976.htm + * DosErrorLevel is cleared after being read by this function. + */ + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + setAX(DosErrorLevel); + DosErrorLevel = 0x0000; // Clear it + break; + } + + /* Find First File */ + case 0x4E: + { + WORD Result = (WORD)demFileFindFirst(FAR_POINTER(DiskTransferArea), + SEG_OFF_TO_PTR(getDS(), getDX()), + getCX()); + + setAX(Result); + + if (Result == ERROR_SUCCESS) + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + else + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + + break; + } + + /* Find Next File */ + case 0x4F: + { + WORD Result = (WORD)demFileFindNext(FAR_POINTER(DiskTransferArea)); + + setAX(Result); + + if (Result == ERROR_SUCCESS) + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + else + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + + break; + } + + /* Internal - Set Current Process ID (Set PSP Address) */ + case 0x50: + { + // FIXME: Is it really what it's done ?? + CurrentPsp = getBX(); + break; + } + + /* Internal - Get Current Process ID (Get PSP Address) */ + case 0x51: + /* Get Current PSP Address */ + case 0x62: + { + /* + * Undocumented AH=51h is identical to the documented AH=62h. + * See Ralf Brown: http://www.ctyme.com/intr/rb-2982.htm + * and http://www.ctyme.com/intr/rb-3140.htm + * for more information. + */ + setBX(CurrentPsp); + break; + } + + /* Internal - Get "List of lists" (SYSVARS) */ + case 0x52: + { + /* + * On return, ES points at the DOS data segment (see also INT 2F/AX=1203h). + * See Ralf Brown: http://www.ctyme.com/intr/rb-2983.htm + * for more information. + */ + + /* Return the DOS "list of lists" in ES:BX */ + setES(0x0000); + setBX(0x0000); + + DisplayMessage(L"Required for AARD code, do you remember? :P"); + break; + } + + /* Get/Set Memory Management Options */ + case 0x58: + { + if (getAL() == 0x00) + { + /* Get allocation strategy */ + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + setAX(DosAllocStrategy); + } + else if (getAL() == 0x01) + { + /* Set allocation strategy */ + + if ((getBL() & (DOS_ALLOC_HIGH | DOS_ALLOC_HIGH_LOW)) + == (DOS_ALLOC_HIGH | DOS_ALLOC_HIGH_LOW)) + { + /* Can't set both */ + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(ERROR_INVALID_PARAMETER); + break; + } + + if ((getBL() & 0x3F) > DOS_ALLOC_LAST_FIT) + { + /* Invalid allocation strategy */ + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(ERROR_INVALID_PARAMETER); + break; + } + + DosAllocStrategy = getBL(); + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else if (getAL() == 0x02) + { + /* Get UMB link state */ + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + setAL(DosUmbLinked ? 0x01 : 0x00); + } + else if (getAL() == 0x03) + { + /* Set UMB link state */ + if (getBX()) DosLinkUmb(); + else DosUnlinkUmb(); + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else + { + /* Invalid or unsupported function */ + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(ERROR_INVALID_FUNCTION); + } + + break; + } + + /* Unsupported */ + default: + { + DPRINT1("DOS Function INT 0x21, AH = %xh, AL = %xh NOT IMPLEMENTED!\n", + getAH(), getAL()); + + setAL(0); // Some functions expect AL to be 0 when it's not supported. + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + } + } +} + +VOID WINAPI DosBreakInterrupt(LPWORD Stack) +{ + UNREFERENCED_PARAMETER(Stack); + + /* Stop the VDM task */ + ResetEvent(VdmTaskEvent); + EmulatorUnsimulate(); +} + +VOID WINAPI DosFastConOut(LPWORD Stack) +{ + /* + * This is the DOS 2+ Fast Console Output Interrupt. + * See Ralf Brown: http://www.ctyme.com/intr/rb-4124.htm + * for more information. + */ + + /* Save AX and BX */ + USHORT AX = getAX(); + USHORT BX = getBX(); + + /* Set the parameters (AL = character, already set) */ + setBL(DOS_CHAR_ATTRIBUTE); + setBH(Bda->VideoPage); + + /* Call the BIOS INT 10h, AH=0Eh "Teletype Output" */ + setAH(0x0E); + Int32Call(&DosContext, BIOS_VIDEO_INTERRUPT); + + /* Restore AX and BX */ + setBX(BX); + setAX(AX); +} + +VOID WINAPI DosInt2Fh(LPWORD Stack) +{ + DPRINT1("DOS Internal System Function INT 0x2F, AH = %xh, AL = %xh NOT IMPLEMENTED!\n", + getAH(), getAL()); + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; +} + +BOOLEAN DosKRNLInitialize(VOID) +{ + +#if 1 + + UCHAR i; + CHAR CurrentDirectory[MAX_PATH]; + CHAR DosDirectory[DOS_DIR_LENGTH]; + LPSTR Path; + + FILE *Stream; + WCHAR Buffer[256]; + + /* Clear the current directory buffer */ + ZeroMemory(CurrentDirectories, sizeof(CurrentDirectories)); + + /* Get the current directory */ + if (!GetCurrentDirectoryA(MAX_PATH, CurrentDirectory)) + { + // TODO: Use some kind of default path? + return FALSE; + } + + /* Convert that to a DOS path */ + if (!GetShortPathNameA(CurrentDirectory, DosDirectory, DOS_DIR_LENGTH)) + { + // TODO: Use some kind of default path? + return FALSE; + } + + /* Set the drive */ + CurrentDrive = DosDirectory[0] - 'A'; + + /* Get the directory part of the path */ + Path = strchr(DosDirectory, '\\'); + if (Path != NULL) + { + /* Skip the backslash */ + Path++; + } + + /* Set the directory */ + if (Path != NULL) + { + strncpy(CurrentDirectories[CurrentDrive], Path, DOS_DIR_LENGTH); + } + + /* Read CONFIG.SYS */ + Stream = _wfopen(DOS_CONFIG_PATH, L"r"); + if (Stream != NULL) + { + while (fgetws(Buffer, 256, Stream)) + { + // TODO: Parse the line + } + fclose(Stream); + } + + /* Initialize the SFT */ + for (i = 0; i < DOS_SFT_SIZE; i++) + { + DosSystemFileTable[i].Handle = INVALID_HANDLE_VALUE; + DosSystemFileTable[i].RefCount = 0; + } + + /* Get handles to standard I/O devices */ + DosSystemFileTable[0].Handle = GetStdHandle(STD_INPUT_HANDLE); + DosSystemFileTable[1].Handle = GetStdHandle(STD_OUTPUT_HANDLE); + DosSystemFileTable[2].Handle = GetStdHandle(STD_ERROR_HANDLE); + + /* Initialize the reference counts */ + DosSystemFileTable[0].RefCount = + DosSystemFileTable[1].RefCount = + DosSystemFileTable[2].RefCount = 1; + +#endif + + /* Initialize the callback context */ + InitializeContext(&DosContext, 0x0070, 0x0000); + + /* Register the DOS 32-bit Interrupts */ + RegisterDosInt32(0x20, DosInt20h ); + RegisterDosInt32(0x21, DosInt21h ); +// RegisterDosInt32(0x22, DosInt22h ); // Termination + RegisterDosInt32(0x23, DosBreakInterrupt); // Ctrl-C / Ctrl-Break +// RegisterDosInt32(0x24, DosInt24h ); // Critical Error + RegisterDosInt32(0x29, DosFastConOut ); // DOS 2+ Fast Console Output + RegisterDosInt32(0x2F, DosInt2Fh ); + + return TRUE; +} + +/* EOF */ diff --git a/subsystems/ntvdm/dos/dos32krnl/dos.h b/subsystems/ntvdm/dos/dos32krnl/dos.h new file mode 100644 index 00000000000..f3e9140fec3 --- /dev/null +++ b/subsystems/ntvdm/dos/dos32krnl/dos.h @@ -0,0 +1,228 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: dos.h + * PURPOSE: VDM DOS Kernel + * PROGRAMMERS: Aleksandar Andrejevic + */ + +#ifndef _DOS_H_ +#define _DOS_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" + +/**/ #include "callback.h" /**/ + +/* DEFINES ********************************************************************/ + +// +// We are DOS 5.00 (reported by INT 21h, AH=30h) +// and DOS 5.50 (reported by INT 21h, AX=3306h) for Windows NT Compatibility +// +#define DOS_VERSION MAKEWORD(5, 00) +#define NTDOS_VERSION MAKEWORD(5, 50) + +#define DOS_CONFIG_PATH L"%SystemRoot%\\system32\\CONFIG.NT" +#define DOS_COMMAND_INTERPRETER L"%SystemRoot%\\system32\\COMMAND.COM /k %SystemRoot%\\system32\\AUTOEXEC.NT" +#define FIRST_MCB_SEGMENT 0x1000 +#define USER_MEMORY_SIZE 0x8FFE +#define SYSTEM_PSP 0x08 +#define SYSTEM_ENV_BLOCK 0x800 + +#define INVALID_DOS_HANDLE 0xFFFF +#define DOS_INPUT_HANDLE 0 +#define DOS_OUTPUT_HANDLE 1 +#define DOS_ERROR_HANDLE 2 + +#define DOS_SFT_SIZE 255 +#define SEGMENT_TO_MCB(seg) ((PDOS_MCB)((ULONG_PTR)BaseAddress + TO_LINEAR((seg), 0))) +#define SEGMENT_TO_PSP(seg) ((PDOS_PSP)((ULONG_PTR)BaseAddress + TO_LINEAR((seg), 0))) +#define UMB_START_SEGMENT 0xC000 +#define UMB_END_SEGMENT 0xDFFF +#define DOS_ALLOC_HIGH 0x40 +#define DOS_ALLOC_HIGH_LOW 0x80 +#define DOS_CMDLINE_LENGTH 127 +#define DOS_DIR_LENGTH 64 +#define NUM_DRIVES ('Z' - 'A' + 1) +#define DOS_CHAR_ATTRIBUTE 0x07 + +enum DOS_ALLOC_STRATEGY +{ + DOS_ALLOC_FIRST_FIT, + DOS_ALLOC_BEST_FIT, + DOS_ALLOC_LAST_FIT +}; + +typedef enum +{ + DOS_LOAD_AND_EXECUTE = 0x00, + DOS_LOAD_ONLY = 0x01, + DOS_LOAD_OVERLAY = 0x03 +} DOS_EXEC_TYPE; + +#pragma pack(push, 1) + +typedef struct _DOS_MCB +{ + CHAR BlockType; + WORD OwnerPsp; + WORD Size; + BYTE Unused[3]; + CHAR Name[8]; +} DOS_MCB, *PDOS_MCB; + +typedef struct _DOS_FCB +{ + BYTE DriveNumber; + CHAR FileName[8]; + CHAR FileExt[3]; + WORD BlockNumber; + WORD RecordSize; + DWORD FileSize; + WORD LastWriteDate; + WORD LastWriteTime; + BYTE Reserved[8]; + BYTE BlockRecord; + BYTE RecordNumber[3]; +} DOS_FCB, *PDOS_FCB; + +typedef struct _DOS_PSP +{ + BYTE Exit[2]; + WORD LastParagraph; + BYTE Reserved0[6]; + DWORD TerminateAddress; + DWORD BreakAddress; + DWORD CriticalAddress; + WORD ParentPsp; + BYTE HandleTable[20]; + WORD EnvBlock; + DWORD LastStack; + WORD HandleTableSize; + DWORD HandleTablePtr; + DWORD PreviousPsp; + DWORD Reserved1; + WORD DosVersion; + BYTE Reserved2[14]; + BYTE FarCall[3]; + BYTE Reserved3[9]; + DOS_FCB Fcb; + BYTE CommandLineSize; + CHAR CommandLine[DOS_CMDLINE_LENGTH]; +} DOS_PSP, *PDOS_PSP; + +typedef struct _DOS_INPUT_BUFFER +{ + BYTE MaxLength; + BYTE Length; + CHAR Buffer[ANYSIZE_ARRAY]; +} DOS_INPUT_BUFFER, *PDOS_INPUT_BUFFER; + +typedef struct _DOS_DRIVER_HEADER +{ + DWORD NextDriver; + WORD Attributes; + WORD StrategyEntry; + WORD InterruptEntry; + CHAR DeviceName[8]; +} DOS_DRIVER_HEADER, *PDOS_DRIVER_HEADER; + +typedef struct _DOS_FIND_FILE_BLOCK +{ + CHAR DriveLetter; + CHAR Pattern[11]; + UCHAR AttribMask; + DWORD Unused; + HANDLE SearchHandle; + + /* The following part of the structure is documented */ + UCHAR Attributes; + WORD FileTime; + WORD FileDate; + DWORD FileSize; + CHAR FileName[13]; +} DOS_FIND_FILE_BLOCK, *PDOS_FIND_FILE_BLOCK; + +typedef struct _DOS_EXEC_PARAM_BLOCK +{ + /* Input variables */ + WORD Environment; + DWORD CommandLine; + DWORD FirstFcb; + DWORD SecondFcb; + + /* Output variables */ + DWORD StackLocation; + DWORD EntryPoint; +} DOS_EXEC_PARAM_BLOCK, *PDOS_EXEC_PARAM_BLOCK; + +#pragma pack(pop) + +/* FUNCTIONS ******************************************************************/ + +extern CALLBACK16 DosContext; +#define RegisterDosInt32(IntNumber, IntHandler) \ +do { \ + DosContext.NextOffset += RegisterInt32(MAKELONG(DosContext.NextOffset, \ + DosContext.Segment), \ + (IntNumber), (IntHandler), NULL); \ +} while(0); + +/* + * DOS BIOS Functions + * See bios.c + */ +CHAR DosReadCharacter(WORD FileHandle); +BOOLEAN DosCheckInput(VOID); +VOID DosPrintCharacter(WORD FileHandle, CHAR Character); + +BOOLEAN DosBIOSInitialize(VOID); + + +/* + * DOS Kernel Functions + * See dos.c + */ +BOOL IsConsoleHandle(HANDLE hHandle); +WORD DosOpenHandle(HANDLE Handle); +HANDLE DosGetRealHandle(WORD DosHandle); + +WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD Attributes); +WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessMode); +WORD DosReadFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesRead); +WORD DosWriteFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesWritten); +WORD DosSeekFile(WORD FileHandle, LONG Offset, BYTE Origin, LPDWORD NewOffset); +BOOL DosFlushFileBuffers(WORD FileHandle); + +VOID DosInitializePsp(WORD PspSegment, LPCSTR CommandLine, WORD ProgramSize, WORD Environment); +DWORD DosLoadExecutable( + IN DOS_EXEC_TYPE LoadType, + IN LPCSTR ExecutablePath, + IN LPCSTR CommandLine, + IN PVOID Environment, + OUT PDWORD StackLocation OPTIONAL, + OUT PDWORD EntryPoint OPTIONAL +); +WORD DosCreateProcess( + DOS_EXEC_TYPE LoadType, + LPCSTR ProgramName, + PDOS_EXEC_PARAM_BLOCK Parameters +); +DWORD DosStartProcess(IN LPCSTR ExecutablePath, + IN LPCSTR CommandLine, + IN PVOID Environment); +VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode); +BOOLEAN DosHandleIoctl(BYTE ControlCode, WORD FileHandle); + +VOID WINAPI DosInt20h(LPWORD Stack); +VOID WINAPI DosInt21h(LPWORD Stack); +VOID WINAPI DosBreakInterrupt(LPWORD Stack); +VOID WINAPI DosInt2Fh(LPWORD Stack); + +BOOLEAN DosKRNLInitialize(VOID); + +#endif // _DOS_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/dos/dos32krnl/dosfiles.c b/subsystems/ntvdm/dos/dos32krnl/dosfiles.c new file mode 100644 index 00000000000..03a5df83847 --- /dev/null +++ b/subsystems/ntvdm/dos/dos32krnl/dosfiles.c @@ -0,0 +1,331 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: dos/dos32krnl/dosfiles.c + * PURPOSE: DOS Files + * PROGRAMMERS: Aleksandar Andrejevic + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +// #include "callback.h" + +#include "dos.h" +#include "dos/dem.h" + +#include "bios/bios.h" + +/* PRIVATE VARIABLES **********************************************************/ + +/* PUBLIC FUNCTIONS ***********************************************************/ + +WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD Attributes) +{ + HANDLE FileHandle; + WORD DosHandle; + + DPRINT("DosCreateFile: FilePath \"%s\", Attributes 0x%04X\n", + FilePath, + Attributes); + + /* Create the file */ + FileHandle = CreateFileA(FilePath, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + CREATE_ALWAYS, + Attributes, + NULL); + + if (FileHandle == INVALID_HANDLE_VALUE) + { + /* Return the error code */ + return (WORD)GetLastError(); + } + + /* Open the DOS handle */ + DosHandle = DosOpenHandle(FileHandle); + + if (DosHandle == INVALID_DOS_HANDLE) + { + /* Close the handle */ + CloseHandle(FileHandle); + + /* Return the error code */ + return ERROR_TOO_MANY_OPEN_FILES; + } + + /* It was successful */ + *Handle = DosHandle; + return ERROR_SUCCESS; +} + +WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessMode) +{ + HANDLE FileHandle; + ACCESS_MASK Access = 0; + WORD DosHandle; + + DPRINT("DosOpenFile: FilePath \"%s\", AccessMode 0x%04X\n", + FilePath, + AccessMode); + + /* Parse the access mode */ + switch (AccessMode & 3) + { + case 0: + { + /* Read-only */ + Access = GENERIC_READ; + break; + } + + case 1: + { + /* Write only */ + Access = GENERIC_WRITE; + break; + } + + case 2: + { + /* Read and write */ + Access = GENERIC_READ | GENERIC_WRITE; + break; + } + + default: + { + /* Invalid */ + return ERROR_INVALID_PARAMETER; + } + } + + /* Open the file */ + FileHandle = CreateFileA(FilePath, + Access, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (FileHandle == INVALID_HANDLE_VALUE) + { + /* Return the error code */ + return (WORD)GetLastError(); + } + + /* Open the DOS handle */ + DosHandle = DosOpenHandle(FileHandle); + + if (DosHandle == INVALID_DOS_HANDLE) + { + /* Close the handle */ + CloseHandle(FileHandle); + + /* Return the error code */ + return ERROR_TOO_MANY_OPEN_FILES; + } + + /* It was successful */ + *Handle = DosHandle; + return ERROR_SUCCESS; +} + +WORD DosReadFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesRead) +{ + WORD Result = ERROR_SUCCESS; + DWORD BytesRead32 = 0; + HANDLE Handle = DosGetRealHandle(FileHandle); + + DPRINT1("DosReadFile: FileHandle 0x%04X, Count 0x%04X\n", FileHandle, Count); + + /* Make sure the handle is valid */ + if (Handle == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE; + + if (IsConsoleHandle(Handle)) + { + CHAR Character; + + /* + * Use BIOS Get Keystroke function + */ + + /* Save AX */ + USHORT AX = getAX(); + + for (BytesRead32 = 0; BytesRead32 < Count; BytesRead32++) + { + /* Call the BIOS INT 16h, AH=00h "Get Keystroke" */ + setAH(0x00); + Int32Call(&DosContext, BIOS_KBD_INTERRUPT); + + /* Retrieve the character in AL (scan code is in AH) */ + Character = getAL(); + + // FIXME: Sometimes we need echo, some other times not. + // DosPrintCharacter(DOS_OUTPUT_HANDLE, Character); + + ((PCHAR)Buffer)[BytesRead32] = Character; + + /* Stop on first carriage return */ + if (Character == '\r') + { + // DosPrintCharacter(DOS_OUTPUT_HANDLE, '\n'); + break; + } + + // BytesRead32++; + } + + /* Restore AX */ + setAX(AX); + } + else + { + /* Read the file */ + if (!ReadFile(Handle, Buffer, Count /* * sizeof(CHAR) */, &BytesRead32, NULL)) + { + /* Store the error code */ + Result = (WORD)GetLastError(); + } + } + + /* The number of bytes read is always 16-bit */ + *BytesRead = LOWORD(BytesRead32); + + /* Return the error code */ + return Result; +} + +WORD DosWriteFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesWritten) +{ + WORD Result = ERROR_SUCCESS; + DWORD BytesWritten32 = 0; + HANDLE Handle = DosGetRealHandle(FileHandle); + + DPRINT1("DosWriteFile: FileHandle 0x%04X, Count 0x%04X\n", + FileHandle, + Count); + + /* Make sure the handle is valid */ + if (Handle == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE; + + if (IsConsoleHandle(Handle)) + { + /* + * Use BIOS Teletype function + */ + + /* Save AX and BX */ + USHORT AX = getAX(); + USHORT BX = getBX(); + + // FIXME: Use BIOS Write String function INT 10h, AH=13h ?? + + for (BytesWritten32 = 0; BytesWritten32 < Count; BytesWritten32++) + { + /* Set the parameters */ + setAL(((PCHAR)Buffer)[BytesWritten32]); + setBL(DOS_CHAR_ATTRIBUTE); + setBH(Bda->VideoPage); + + /* Call the BIOS INT 10h, AH=0Eh "Teletype Output" */ + setAH(0x0E); + Int32Call(&DosContext, BIOS_VIDEO_INTERRUPT); + + // BytesWritten32++; + } + + /* Restore AX and BX */ + setBX(BX); + setAX(AX); + } + else + { + /* Write the file */ + if (!WriteFile(Handle, Buffer, Count /* * sizeof(CHAR) */, &BytesWritten32, NULL)) + { + /* Store the error code */ + Result = (WORD)GetLastError(); + } + } + + /* The number of bytes written is always 16-bit */ + *BytesWritten = LOWORD(BytesWritten32); + + /* Return the error code */ + return Result; +} + +WORD DosSeekFile(WORD FileHandle, LONG Offset, BYTE Origin, LPDWORD NewOffset) +{ + WORD Result = ERROR_SUCCESS; + DWORD FilePointer; + HANDLE Handle = DosGetRealHandle(FileHandle); + + DPRINT("DosSeekFile: FileHandle 0x%04X, Offset 0x%08X, Origin 0x%02X\n", + FileHandle, + Offset, + Origin); + + /* Make sure the handle is valid */ + if (Handle == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE; + + /* Check if the origin is valid */ + if (Origin != FILE_BEGIN && Origin != FILE_CURRENT && Origin != FILE_END) + { + return ERROR_INVALID_FUNCTION; + } + + /* Move the file pointer */ + if (IsConsoleHandle(Handle)) + { + /* Always succeeds when seeking a console handle */ + FilePointer = 0; + Result = ERROR_SUCCESS; + } + else + { + FilePointer = SetFilePointer(Handle, Offset, NULL, Origin); + } + + /* Check if there's a possibility the operation failed */ + if (FilePointer == INVALID_SET_FILE_POINTER) + { + /* Get the real error code */ + Result = (WORD)GetLastError(); + } + + if (Result != ERROR_SUCCESS) + { + /* The operation did fail */ + return Result; + } + + /* Return the file pointer, if requested */ + if (NewOffset) *NewOffset = FilePointer; + + /* Return success */ + return ERROR_SUCCESS; +} + +// This function is almost exclusively used as a DosFlushInputBuffer +BOOL DosFlushFileBuffers(WORD FileHandle) +{ + HANDLE Handle = DosGetRealHandle(FileHandle); + + /* Make sure the handle is valid */ + if (Handle == INVALID_HANDLE_VALUE) return FALSE; + + /* + * No need to check whether the handle is a console handle since + * FlushFileBuffers() automatically does this check and calls + * FlushConsoleInputBuffer() for us. + */ + return FlushFileBuffers(Handle); +} diff --git a/subsystems/ntvdm/emulator.c b/subsystems/ntvdm/emulator.c new file mode 100644 index 00000000000..094d156df7d --- /dev/null +++ b/subsystems/ntvdm/emulator.c @@ -0,0 +1,526 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: emulator.c + * PURPOSE: Minimal x86 machine emulator for the VDM + * PROGRAMMERS: Aleksandar Andrejevic + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "callback.h" + +#include "clock.h" +#include "bios/rom.h" +#include "hardware/cmos.h" +#include "hardware/pic.h" +#include "hardware/ps2.h" +#include "hardware/speaker.h" +#include "hardware/timer.h" +#include "hardware/vga.h" + +#include "bop.h" +#include "vddsup.h" +#include "io.h" + +#include + +/* PRIVATE VARIABLES **********************************************************/ + +FAST486_STATE EmulatorContext; +BOOLEAN CpuSimulate = FALSE; + +/* No more than 'MaxCpuCallLevel' recursive CPU calls are allowed */ +static const INT MaxCpuCallLevel = 32; +static INT CpuCallLevel = 0; + +LPVOID BaseAddress = NULL; +BOOLEAN VdmRunning = TRUE; + +static BOOLEAN A20Line = FALSE; +static BYTE Port61hState = 0x00; + +static HANDLE InputThread = NULL; + +LPCWSTR ExceptionName[] = +{ + L"Division By Zero", + L"Debug", + L"Unexpected Error", + L"Breakpoint", + L"Integer Overflow", + L"Bound Range Exceeded", + L"Invalid Opcode", + L"FPU Not Available" +}; + +/* BOP Identifiers */ +#define BOP_DEBUGGER 0x56 // Break into the debugger from a 16-bit app + +/* PRIVATE FUNCTIONS **********************************************************/ + +VOID WINAPI EmulatorReadMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size) +{ + UNREFERENCED_PARAMETER(State); + + // BIG HACK!!!! To make BIOS images working correctly, + // until Aleksander rewrites memory management!! + if (Address >= 0xFFFFFFF0) Address -= 0xFFF00000; + + /* If the A20 line is disabled, mask bit 20 */ + if (!A20Line) Address &= ~(1 << 20); + + /* Make sure the requested address is valid */ + if ((Address + Size) >= MAX_ADDRESS) return; + + /* + * Check if we are going to read the VGA memory and + * copy it into the virtual address space if needed. + */ + if (((Address + Size) >= VgaGetVideoBaseAddress()) + && (Address < VgaGetVideoLimitAddress())) + { + DWORD VgaAddress = max(Address, VgaGetVideoBaseAddress()); + DWORD ActualSize = min(Address + Size - 1, VgaGetVideoLimitAddress()) + - VgaAddress + 1; + LPBYTE DestBuffer = (LPBYTE)REAL_TO_PHYS(VgaAddress); + + /* Read from the VGA memory */ + VgaReadMemory(VgaAddress, DestBuffer, ActualSize); + } + + /* Read the data from the virtual address space and store it in the buffer */ + RtlCopyMemory(Buffer, REAL_TO_PHYS(Address), Size); +} + +VOID WINAPI EmulatorWriteMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size) +{ + UNREFERENCED_PARAMETER(State); + + // BIG HACK!!!! To make BIOS images working correctly, + // until Aleksander rewrites memory management!! + if (Address >= 0xFFFFFFF0) Address -= 0xFFF00000; + + /* If the A20 line is disabled, mask bit 20 */ + if (!A20Line) Address &= ~(1 << 20); + + /* Make sure the requested address is valid */ + if ((Address + Size) >= MAX_ADDRESS) return; + + /* Make sure we don't write to the ROM area */ + if ((Address + Size) >= ROM_AREA_START && (Address < ROM_AREA_END)) return; + + /* Read the data from the buffer and store it in the virtual address space */ + RtlCopyMemory(REAL_TO_PHYS(Address), Buffer, Size); + + /* + * Check if we modified the VGA memory. + */ + if (((Address + Size) >= VgaGetVideoBaseAddress()) + && (Address < VgaGetVideoLimitAddress())) + { + DWORD VgaAddress = max(Address, VgaGetVideoBaseAddress()); + DWORD ActualSize = min(Address + Size - 1, VgaGetVideoLimitAddress()) + - VgaAddress + 1; + LPBYTE SrcBuffer = (LPBYTE)REAL_TO_PHYS(VgaAddress); + + /* Write to the VGA memory */ + VgaWriteMemory(VgaAddress, SrcBuffer, ActualSize); + } +} + +UCHAR WINAPI EmulatorIntAcknowledge(PFAST486_STATE State) +{ + UNREFERENCED_PARAMETER(State); + + /* Get the interrupt number from the PIC */ + return PicGetInterrupt(); +} + +VOID EmulatorException(BYTE ExceptionNumber, LPWORD Stack) +{ + WORD CodeSegment, InstructionPointer; + PBYTE Opcode; + + ASSERT(ExceptionNumber < 8); + + /* Get the CS:IP */ + InstructionPointer = Stack[STACK_IP]; + CodeSegment = Stack[STACK_CS]; + Opcode = (PBYTE)SEG_OFF_TO_PTR(CodeSegment, InstructionPointer); + + /* Display a message to the user */ + DisplayMessage(L"Exception: %s occured at %04X:%04X\n" + L"Opcode: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", + ExceptionName[ExceptionNumber], + CodeSegment, + InstructionPointer, + Opcode[0], + Opcode[1], + Opcode[2], + Opcode[3], + Opcode[4], + Opcode[5], + Opcode[6], + Opcode[7], + Opcode[8], + Opcode[9]); + + /* Stop the VDM */ + EmulatorTerminate(); + return; +} + +// FIXME: This function assumes 16-bit mode!!! +VOID EmulatorExecute(WORD Segment, WORD Offset) +{ + /* Tell Fast486 to move the instruction pointer */ + Fast486ExecuteAt(&EmulatorContext, Segment, Offset); +} + +VOID EmulatorStep(VOID) +{ + /* Dump the state for debugging purposes */ + // Fast486DumpState(&EmulatorContext); + + /* Execute the next instruction */ + Fast486StepInto(&EmulatorContext); +} + +VOID EmulatorSimulate(VOID) +{ + if (CpuCallLevel > MaxCpuCallLevel) + { + DisplayMessage(L"Too many CPU levels of recursion (%d, expected maximum %d)", + CpuCallLevel, MaxCpuCallLevel); + + /* Stop the VDM */ + EmulatorTerminate(); + return; + } + CpuCallLevel++; + + CpuSimulate = TRUE; + while (VdmRunning && CpuSimulate) ClockUpdate(); + + CpuCallLevel--; + if (CpuCallLevel < 0) CpuCallLevel = 0; + + /* This takes into account for reentrance */ + CpuSimulate = TRUE; +} + +VOID EmulatorUnsimulate(VOID) +{ + /* Stop simulation */ + CpuSimulate = FALSE; +} + +VOID EmulatorTerminate(VOID) +{ + /* Stop the VDM */ + VdmRunning = FALSE; +} + +VOID EmulatorInterrupt(BYTE Number) +{ + /* Call the Fast486 API */ + Fast486Interrupt(&EmulatorContext, Number); +} + +VOID EmulatorInterruptSignal(VOID) +{ + /* Call the Fast486 API */ + Fast486InterruptSignal(&EmulatorContext); +} + +VOID EmulatorSetA20(BOOLEAN Enabled) +{ + A20Line = Enabled; +} + +static VOID WINAPI EmulatorDebugBreakBop(LPWORD Stack) +{ + DPRINT1("NTVDM: BOP_DEBUGGER\n"); + DebugBreak(); +} + +static VOID WINAPI EmulatorUnsimulateBop(LPWORD Stack) +{ + EmulatorUnsimulate(); +} + +static BYTE WINAPI Port61hRead(ULONG Port) +{ + return Port61hState; +} + +static VOID WINAPI Port61hWrite(ULONG Port, BYTE Data) +{ + // BOOLEAN SpeakerChange = FALSE; + BYTE OldPort61hState = Port61hState; + + /* Only the four lowest bytes can be written */ + Port61hState = (Port61hState & 0xF0) | (Data & 0x0F); + + if ((OldPort61hState ^ Port61hState) & 0x01) + { + DPRINT("PIT 2 Gate %s\n", Port61hState & 0x01 ? "on" : "off"); + // SpeakerChange = TRUE; + } + + PitSetGate(2, !!(Port61hState & 0x01)); + + if ((OldPort61hState ^ Port61hState) & 0x02) + { + /* There were some change for the speaker... */ + DPRINT("Speaker %s\n", Port61hState & 0x02 ? "on" : "off"); + // SpeakerChange = TRUE; + } + // if (SpeakerChange) SpeakerChange(); + SpeakerChange(); +} + +static VOID WINAPI PitChan0Out(LPVOID Param, BOOLEAN State) +{ + if (State) + { + DPRINT("PicInterruptRequest\n"); + PicInterruptRequest(0); // Raise IRQ 0 + } + // else < Lower IRQ 0 > +} + +static VOID WINAPI PitChan1Out(LPVOID Param, BOOLEAN State) +{ +#if 0 + if (State) + { + /* Set bit 4 of Port 61h */ + Port61hState |= 1 << 4; + } + else + { + /* Clear bit 4 of Port 61h */ + Port61hState &= ~(1 << 4); + } +#else + Port61hState = (Port61hState & 0xEF) | (State << 4); +#endif +} + +static VOID WINAPI PitChan2Out(LPVOID Param, BOOLEAN State) +{ + // BYTE OldPort61hState = Port61hState; + +#if 0 + if (State) + { + /* Set bit 5 of Port 61h */ + Port61hState |= 1 << 5; + } + else + { + /* Clear bit 5 of Port 61h */ + Port61hState &= ~(1 << 5); + } +#else + Port61hState = (Port61hState & 0xDF) | (State << 5); +#endif + DPRINT("Speaker PIT out\n"); + // if ((OldPort61hState ^ Port61hState) & 0x20) + // SpeakerChange(); +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +DWORD WINAPI PumpConsoleInput(LPVOID Parameter); + +BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput) +{ + /* Allocate memory for the 16-bit address space */ + BaseAddress = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_ADDRESS); + if (BaseAddress == NULL) + { + wprintf(L"FATAL: Failed to allocate VDM memory.\n"); + return FALSE; + } + + /* Initialize I/O ports */ + /* Initialize RAM */ + + /* Initialize the internal clock */ + if (!ClockInitialize()) + { + wprintf(L"FATAL: Failed to initialize the clock\n"); + return FALSE; + } + + /* Initialize the CPU */ + Fast486Initialize(&EmulatorContext, + EmulatorReadMemory, + EmulatorWriteMemory, + EmulatorReadIo, + EmulatorWriteIo, + NULL, + EmulatorBiosOperation, + EmulatorIntAcknowledge, + NULL /* TODO: Use a TLB */); + + /* Initialize DMA */ + + /* Initialize the PIC, the PIT, the CMOS and the PC Speaker */ + PicInitialize(); + PitInitialize(); + CmosInitialize(); + SpeakerInitialize(); + + /* Set output functions */ + PitSetOutFunction(0, NULL, PitChan0Out); + PitSetOutFunction(1, NULL, PitChan1Out); + PitSetOutFunction(2, NULL, PitChan2Out); + + /* Register the I/O Ports */ + RegisterIoPort(CONTROL_SYSTEM_PORT61H, Port61hRead, Port61hWrite); + + /* Set the console input mode */ + // FIXME: Activate ENABLE_WINDOW_INPUT when we will want to perform actions + // upon console window events (screen buffer resize, ...). + SetConsoleMode(ConsoleInput, ENABLE_PROCESSED_INPUT /* | ENABLE_WINDOW_INPUT */); + // SetConsoleMode(ConsoleOutput, ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT); + + /* Initialize the PS2 port */ + PS2Initialize(ConsoleInput); + + /**************** ATTACH INPUT WITH CONSOLE *****************/ + /* Start the input thread */ + InputThread = CreateThread(NULL, 0, &PumpConsoleInput, ConsoleInput, 0, NULL); + if (InputThread == NULL) + { + DisplayMessage(L"Failed to create the console input thread."); + return FALSE; + } + /************************************************************/ + + /* Initialize the VGA */ + if (!VgaInitialize(ConsoleOutput)) + { + DisplayMessage(L"Failed to initialize VGA support."); + return FALSE; + } + + /* Initialize the software callback system and register the emulator BOPs */ + InitializeCallbacks(); + RegisterBop(BOP_DEBUGGER , EmulatorDebugBreakBop); + RegisterBop(BOP_UNSIMULATE, EmulatorUnsimulateBop); + + /* Initialize VDD support */ + VDDSupInitialize(); + + return TRUE; +} + +VOID EmulatorCleanup(VOID) +{ + VgaCleanup(); + + /* Close the input thread handle */ + if (InputThread != NULL) CloseHandle(InputThread); + InputThread = NULL; + + PS2Cleanup(); + + SpeakerCleanup(); + CmosCleanup(); + // PitCleanup(); + // PicCleanup(); + + // Fast486Cleanup(); + + /* Free the memory allocated for the 16-bit address space */ + if (BaseAddress != NULL) HeapFree(GetProcessHeap(), 0, BaseAddress); +} + + + +VOID +WINAPI +VDDSimulate16(VOID) +{ + EmulatorSimulate(); +} + +VOID +WINAPI +VDDTerminateVDM(VOID) +{ + /* Stop the VDM */ + EmulatorTerminate(); +} + +PBYTE +WINAPI +Sim32pGetVDMPointer(IN ULONG Address, + IN BOOLEAN ProtectedMode) +{ + // FIXME + UNREFERENCED_PARAMETER(ProtectedMode); + + /* + * HIWORD(Address) == Segment (if ProtectedMode == FALSE) + * or Selector (if ProtectedMode == TRUE ) + * LOWORD(Address) == Offset + */ + return (PBYTE)FAR_POINTER(Address); +} + +PBYTE +WINAPI +MGetVdmPointer(IN ULONG Address, + IN ULONG Size, + IN BOOLEAN ProtectedMode) +{ + UNREFERENCED_PARAMETER(Size); + return Sim32pGetVDMPointer(Address, ProtectedMode); +} + +PVOID +WINAPI +VdmMapFlat(IN USHORT Segment, + IN ULONG Offset, + IN VDM_MODE Mode) +{ + // FIXME + UNREFERENCED_PARAMETER(Mode); + + return SEG_OFF_TO_PTR(Segment, Offset); +} + +BOOL +WINAPI +VdmFlushCache(IN USHORT Segment, + IN ULONG Offset, + IN ULONG Size, + IN VDM_MODE Mode) +{ + // FIXME + UNIMPLEMENTED; + return TRUE; +} + +BOOL +WINAPI +VdmUnmapFlat(IN USHORT Segment, + IN ULONG Offset, + IN PVOID Buffer, + IN VDM_MODE Mode) +{ + // FIXME + UNIMPLEMENTED; + return TRUE; +} + +/* EOF */ diff --git a/subsystems/ntvdm/emulator.h b/subsystems/ntvdm/emulator.h new file mode 100644 index 00000000000..1b1337f3726 --- /dev/null +++ b/subsystems/ntvdm/emulator.h @@ -0,0 +1,139 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: emulator.h + * PURPOSE: Minimal x86 machine emulator for the VDM + * PROGRAMMERS: Aleksandar Andrejevic + */ + +#ifndef _EMULATOR_H_ +#define _EMULATOR_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" +#include + +/* DEFINES ********************************************************************/ + +/* FLAGS */ +#define EMULATOR_FLAG_CF (1 << 0) +#define EMULATOR_FLAG_PF (1 << 2) +#define EMULATOR_FLAG_AF (1 << 4) +#define EMULATOR_FLAG_ZF (1 << 6) +#define EMULATOR_FLAG_SF (1 << 7) +#define EMULATOR_FLAG_TF (1 << 8) +#define EMULATOR_FLAG_IF (1 << 9) +#define EMULATOR_FLAG_DF (1 << 10) +#define EMULATOR_FLAG_OF (1 << 11) +#define EMULATOR_FLAG_NT (1 << 14) +#define EMULATOR_FLAG_RF (1 << 16) +#define EMULATOR_FLAG_VM (1 << 17) +#define EMULATOR_FLAG_AC (1 << 18) +#define EMULATOR_FLAG_VIF (1 << 19) +#define EMULATOR_FLAG_VIP (1 << 20) +#define EMULATOR_FLAG_ID (1 << 21) + +// +// WARNING WARNING!! +// If you're changing the indices here, you then need to +// also fix the BOP code in callback.c !!!!!!!!!!!!!!!!! +// +#define STACK_INT_NUM 0 +#define STACK_IP 1 +#define STACK_CS 2 +#define STACK_FLAGS 3 + + +/* Basic Memory Management */ +#define MEM_ALIGN_UP(ptr, align) MEM_ALIGN_DOWN((ULONG_PTR)(ptr) + (align) - 1l, (align)) +#define MEM_ALIGN_DOWN(ptr, align) (PVOID)((ULONG_PTR)(ptr) & ~((align) - 1l)) + +#define TO_LINEAR(seg, off) (((seg) << 4) + (off)) +#define MAX_SEGMENT 0xFFFF +#define MAX_OFFSET 0xFFFF +#define MAX_ADDRESS 0x1000000 // 16 MB of RAM + +#define FAR_POINTER(x) \ + (PVOID)((ULONG_PTR)BaseAddress + TO_LINEAR(HIWORD(x), LOWORD(x))) + +#define SEG_OFF_TO_PTR(seg, off) \ + (PVOID)((ULONG_PTR)BaseAddress + TO_LINEAR((seg), (off))) + +#define REAL_TO_PHYS(ptr) (PVOID)((ULONG_PTR)(ptr) + (ULONG_PTR)BaseAddress) +#define PHYS_TO_REAL(ptr) (PVOID)((ULONG_PTR)(ptr) - (ULONG_PTR)BaseAddress) + + +/* BCD-Binary conversion */ +#define BINARY_TO_BCD(x) ((((x) / 1000) << 12) + (((x) / 100) << 8) + (((x) / 10) << 4) + ((x) % 10)) +#define BCD_TO_BINARY(x) (((x) >> 12) * 1000 + ((x) >> 8) * 100 + ((x) >> 4) * 10 + ((x) & 0x0F)) + + +/* System I/O ports */ +#define CONTROL_SYSTEM_PORT61H 0x61 + + +enum +{ + EMULATOR_EXCEPTION_DIVISION_BY_ZERO, + EMULATOR_EXCEPTION_DEBUG, + EMULATOR_EXCEPTION_NMI, + EMULATOR_EXCEPTION_BREAKPOINT, + EMULATOR_EXCEPTION_OVERFLOW, + EMULATOR_EXCEPTION_BOUND, + EMULATOR_EXCEPTION_INVALID_OPCODE, + EMULATOR_EXCEPTION_NO_FPU, + EMULATOR_EXCEPTION_DOUBLE_FAULT, + EMULATOR_EXCEPTION_FPU_SEGMENT, + EMULATOR_EXCEPTION_INVALID_TSS, + EMULATOR_EXCEPTION_NO_SEGMENT, + EMULATOR_EXCEPTION_STACK_SEGMENT, + EMULATOR_EXCEPTION_GPF, + EMULATOR_EXCEPTION_PAGE_FAULT +}; + +extern FAST486_STATE EmulatorContext; +extern LPVOID BaseAddress; +extern BOOLEAN VdmRunning; + +/* FUNCTIONS ******************************************************************/ + +VOID WINAPI EmulatorReadMemory +( + PFAST486_STATE State, + ULONG Address, + PVOID Buffer, + ULONG Size +); + +VOID WINAPI EmulatorWriteMemory +( + PFAST486_STATE State, + ULONG Address, + PVOID Buffer, + ULONG Size +); + +UCHAR WINAPI EmulatorIntAcknowledge +( + PFAST486_STATE State +); + +VOID EmulatorException(BYTE ExceptionNumber, LPWORD Stack); + +VOID EmulatorExecute(WORD Segment, WORD Offset); +VOID EmulatorStep(VOID); +VOID EmulatorSimulate(VOID); +VOID EmulatorUnsimulate(VOID); +VOID EmulatorTerminate(VOID); + +VOID EmulatorInterrupt(BYTE Number); +VOID EmulatorInterruptSignal(VOID); +VOID EmulatorSetA20(BOOLEAN Enabled); + +BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput); +VOID EmulatorCleanup(VOID); + +#endif // _EMULATOR_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/hardware/cmos.c b/subsystems/ntvdm/hardware/cmos.c new file mode 100644 index 00000000000..4f86467249b --- /dev/null +++ b/subsystems/ntvdm/hardware/cmos.c @@ -0,0 +1,478 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: cmos.c + * PURPOSE: CMOS Real Time Clock emulation + * PROGRAMMERS: Aleksandar Andrejevic + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "cmos.h" + +#include "io.h" +#include "pic.h" + +/* PRIVATE VARIABLES **********************************************************/ + +static HANDLE hCmosRam = INVALID_HANDLE_VALUE; +static CMOS_MEMORY CmosMemory; + +static BOOLEAN NmiEnabled = TRUE; +static CMOS_REGISTERS SelectedRegister = CMOS_REG_STATUS_D; + +/* PUBLIC FUNCTIONS ***********************************************************/ + +BOOLEAN IsNmiEnabled(VOID) +{ + return NmiEnabled; +} + +VOID CmosWriteAddress(BYTE Value) +{ + /* Update the NMI enabled flag */ + NmiEnabled = !(Value & CMOS_DISABLE_NMI); + + /* Get the register number */ + Value &= ~CMOS_DISABLE_NMI; + + if (Value < CMOS_REG_MAX) + { + /* Select the new register */ + SelectedRegister = Value; + } + else + { + /* Default to Status Register D */ + SelectedRegister = CMOS_REG_STATUS_D; + } +} + +BYTE CmosReadData(VOID) +{ + SYSTEMTIME CurrentTime; + + /* Get the current time */ + GetLocalTime(&CurrentTime); + + switch (SelectedRegister) + { + case CMOS_REG_SECONDS: + return READ_CMOS_DATA(CmosMemory, CurrentTime.wSecond); + + case CMOS_REG_ALARM_SEC: + return READ_CMOS_DATA(CmosMemory, CmosMemory.AlarmSecond); + + case CMOS_REG_MINUTES: + return READ_CMOS_DATA(CmosMemory, CurrentTime.wMinute); + + case CMOS_REG_ALARM_MIN: + return READ_CMOS_DATA(CmosMemory, CmosMemory.AlarmMinute); + + case CMOS_REG_HOURS: + { + BOOLEAN Afternoon = FALSE; + BYTE Value = CurrentTime.wHour; + + if (!(CmosMemory.StatusRegB & CMOS_STB_24HOUR) && (Value >= 12)) + { + Value -= 12; + Afternoon = TRUE; + } + + Value = READ_CMOS_DATA(CmosMemory, Value); + + /* Convert to 12-hour */ + if (Afternoon) Value |= 0x80; + + return Value; + } + + case CMOS_REG_ALARM_HRS: + { + BOOLEAN Afternoon = FALSE; + BYTE Value = CmosMemory.AlarmHour; + + if (!(CmosMemory.StatusRegB & CMOS_STB_24HOUR) && (Value >= 12)) + { + Value -= 12; + Afternoon = TRUE; + } + + Value = READ_CMOS_DATA(CmosMemory, Value); + + /* Convert to 12-hour */ + if (Afternoon) Value |= 0x80; + + return Value; + } + + case CMOS_REG_DAY_OF_WEEK: + /* + * The CMOS value is 1-based but the + * GetLocalTime API value is 0-based. + * Correct it. + */ + return READ_CMOS_DATA(CmosMemory, CurrentTime.wDayOfWeek + 1); + + case CMOS_REG_DAY: + return READ_CMOS_DATA(CmosMemory, CurrentTime.wDay); + + case CMOS_REG_MONTH: + return READ_CMOS_DATA(CmosMemory, CurrentTime.wMonth); + + case CMOS_REG_YEAR: + return READ_CMOS_DATA(CmosMemory, CurrentTime.wYear % 100); + + case CMOS_REG_STATUS_C: + { + BYTE Value = CmosMemory.StatusRegC; + + /* Clear status register C */ + CmosMemory.StatusRegC = 0x00; + + /* Return the old value */ + return Value; + } + + case CMOS_REG_STATUS_A: + case CMOS_REG_STATUS_B: + case CMOS_REG_STATUS_D: + case CMOS_REG_DIAGNOSTICS: + case CMOS_REG_SHUTDOWN_STATUS: + default: + { + // ASSERT(SelectedRegister < CMOS_REG_MAX); + return CmosMemory.Regs[SelectedRegister]; + } + } + + /* Return to Status Register D */ + SelectedRegister = CMOS_REG_STATUS_D; +} + +VOID CmosWriteData(BYTE Value) +{ + BOOLEAN ChangeTime = FALSE; + SYSTEMTIME CurrentTime; + + /* Get the current time */ + GetLocalTime(&CurrentTime); + + switch (SelectedRegister) + { + case CMOS_REG_SECONDS: + { + ChangeTime = TRUE; + CurrentTime.wSecond = WRITE_CMOS_DATA(CmosMemory, Value); + break; + } + + case CMOS_REG_ALARM_SEC: + { + CmosMemory.AlarmSecond = WRITE_CMOS_DATA(CmosMemory, Value); + break; + } + + case CMOS_REG_MINUTES: + { + ChangeTime = TRUE; + CurrentTime.wMinute = WRITE_CMOS_DATA(CmosMemory, Value); + break; + } + + case CMOS_REG_ALARM_MIN: + { + CmosMemory.AlarmMinute = WRITE_CMOS_DATA(CmosMemory, Value); + break; + } + + case CMOS_REG_HOURS: + { + BOOLEAN Afternoon = FALSE; + + ChangeTime = TRUE; + + if (!(CmosMemory.StatusRegB & CMOS_STB_24HOUR) && (Value & 0x80)) + { + Value &= ~0x80; + Afternoon = TRUE; + } + + CurrentTime.wHour = WRITE_CMOS_DATA(CmosMemory, Value); + + /* Convert to 24-hour format */ + if (Afternoon) CurrentTime.wHour += 12; + + break; + } + + case CMOS_REG_ALARM_HRS: + { + BOOLEAN Afternoon = FALSE; + + if (!(CmosMemory.StatusRegB & CMOS_STB_24HOUR) && (Value & 0x80)) + { + Value &= ~0x80; + Afternoon = TRUE; + } + + CmosMemory.AlarmHour = WRITE_CMOS_DATA(CmosMemory, Value); + + /* Convert to 24-hour format */ + if (Afternoon) CmosMemory.AlarmHour += 12; + + break; + } + + case CMOS_REG_DAY_OF_WEEK: + { + ChangeTime = TRUE; + /* + * The CMOS value is 1-based but the + * SetLocalTime API value is 0-based. + * Correct it. + */ + Value -= 1; + CurrentTime.wDayOfWeek = WRITE_CMOS_DATA(CmosMemory, Value); + break; + } + + case CMOS_REG_DAY: + { + ChangeTime = TRUE; + CurrentTime.wDay = WRITE_CMOS_DATA(CmosMemory, Value); + break; + } + + case CMOS_REG_MONTH: + { + ChangeTime = TRUE; + CurrentTime.wMonth = WRITE_CMOS_DATA(CmosMemory, Value); + break; + } + + case CMOS_REG_YEAR: + { + ChangeTime = TRUE; + + /* Clear everything except the century */ + CurrentTime.wYear = (CurrentTime.wYear / 100) * 100; + + CurrentTime.wYear += WRITE_CMOS_DATA(CmosMemory, Value); + break; + } + + case CMOS_REG_STATUS_A: + { + CmosMemory.StatusRegA = Value & 0x7F; // Bit 7 is read-only + break; + } + + case CMOS_REG_STATUS_B: + { + CmosMemory.StatusRegB = Value; + break; + } + + case CMOS_REG_STATUS_C: + case CMOS_REG_STATUS_D: + // Status registers C and D are read-only + break; + + /* Is the following correct? */ + case CMOS_REG_EXT_MEMORY_LOW: + case CMOS_REG_ACTUAL_EXT_MEMORY_LOW: + { + /* Sync EMS and UMS */ + CmosMemory.Regs[CMOS_REG_EXT_MEMORY_LOW] = + CmosMemory.Regs[CMOS_REG_ACTUAL_EXT_MEMORY_LOW] = Value; + break; + } + + /* Is the following correct? */ + case CMOS_REG_EXT_MEMORY_HIGH: + case CMOS_REG_ACTUAL_EXT_MEMORY_HIGH: + { + /* Sync EMS and UMS */ + CmosMemory.Regs[CMOS_REG_EXT_MEMORY_HIGH] = + CmosMemory.Regs[CMOS_REG_ACTUAL_EXT_MEMORY_HIGH] = Value; + break; + } + + default: + { + CmosMemory.Regs[SelectedRegister] = Value; + } + } + + if (ChangeTime) SetLocalTime(&CurrentTime); + + /* Return to Status Register D */ + SelectedRegister = CMOS_REG_STATUS_D; +} + +BYTE WINAPI CmosReadPort(ULONG Port) +{ + ASSERT(Port == CMOS_DATA_PORT); + return CmosReadData(); +} + +VOID WINAPI CmosWritePort(ULONG Port, BYTE Data) +{ + if (Port == CMOS_ADDRESS_PORT) + CmosWriteAddress(Data); + else if (Port == CMOS_DATA_PORT) + CmosWriteData(Data); +} + +DWORD RtcGetTicksPerSecond(VOID) +{ + BYTE RateSelect = CmosMemory.StatusRegB & 0x0F; + + if (RateSelect == 0) + { + /* No periodic interrupt */ + return 0; + } + + /* 1 and 2 act like 8 and 9 */ + if (RateSelect <= 2) RateSelect += 7; + + return 1 << (16 - RateSelect); +} + +VOID RtcPeriodicTick(VOID) +{ + /* Set PF */ + CmosMemory.StatusRegC |= CMOS_STC_PF; + + /* Check if there should be an interrupt on a periodic timer tick */ + if (CmosMemory.StatusRegB & CMOS_STB_INT_PERIODIC) + { + CmosMemory.StatusRegC |= CMOS_STC_IRQF; + + /* Interrupt! */ + PicInterruptRequest(RTC_IRQ_NUMBER); + } +} + +/* Should be called every second */ +VOID RtcTimeUpdate(VOID) +{ + SYSTEMTIME CurrentTime; + + /* Get the current time */ + GetLocalTime(&CurrentTime); + + /* Set UF */ + CmosMemory.StatusRegC |= CMOS_STC_UF; + + /* Check if the time matches the alarm time */ + if ((CurrentTime.wHour == CmosMemory.AlarmHour ) && + (CurrentTime.wMinute == CmosMemory.AlarmMinute) && + (CurrentTime.wSecond == CmosMemory.AlarmSecond)) + { + /* Set the alarm flag */ + CmosMemory.StatusRegC |= CMOS_STC_AF; + + /* Set IRQF if there should be an interrupt */ + if (CmosMemory.StatusRegB & CMOS_STB_INT_ON_ALARM) CmosMemory.StatusRegC |= CMOS_STC_IRQF; + } + + /* Check if there should be an interrupt on update */ + if (CmosMemory.StatusRegB & CMOS_STB_INT_ON_UPDATE) CmosMemory.StatusRegC |= CMOS_STC_IRQF; + + if (CmosMemory.StatusRegC & CMOS_STC_IRQF) + { + /* Interrupt! */ + PicInterruptRequest(RTC_IRQ_NUMBER); + } +} + +VOID CmosInitialize(VOID) +{ + DWORD CmosSize = sizeof(CmosMemory); + + /* File must not be opened before */ + ASSERT(hCmosRam == INVALID_HANDLE_VALUE); + + /* Clear the CMOS memory */ + ZeroMemory(&CmosMemory, sizeof(CmosMemory)); + + /* Always open (and if needed, create) a RAM file with shared access */ + SetLastError(0); // For debugging purposes + hCmosRam = CreateFileW(L"cmos.ram", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + DPRINT1("CMOS opening %s ; GetLastError() = %u\n", hCmosRam != INVALID_HANDLE_VALUE ? "succeeded" : "failed", GetLastError()); + + if (hCmosRam != INVALID_HANDLE_VALUE) + { + BOOL Success; + + /* Attempt to fill the CMOS memory with the RAM file */ + SetLastError(0); // For debugging purposes + Success = ReadFile(hCmosRam, &CmosMemory, CmosSize, &CmosSize, NULL); + if (CmosSize != sizeof(CmosMemory)) + { + /* Bad CMOS Ram file. Reinitialize the CMOS memory. */ + DPRINT1("Invalid CMOS file, read bytes %u, expected bytes %u\n", CmosSize, sizeof(CmosMemory)); + ZeroMemory(&CmosMemory, sizeof(CmosMemory)); + } + DPRINT1("CMOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError()); + SetFilePointer(hCmosRam, 0, NULL, FILE_BEGIN); + } + + /* Overwrite some registers with default values */ + CmosMemory.StatusRegA = CMOS_DEFAULT_STA; + CmosMemory.StatusRegB = CMOS_DEFAULT_STB; + CmosMemory.StatusRegC = 0x00; + CmosMemory.StatusRegD = CMOS_BATTERY_OK; // Our CMOS battery works perfectly forever. + CmosMemory.Diagnostics = 0x00; // Diagnostics must not find any errors. + CmosMemory.ShutdownStatus = 0x00; + + /* Memory settings */ + + /* + * Conventional memory size is 640 kB, + * see: http://webpages.charter.net/danrollins/techhelp/0184.HTM + * and see Ralf Brown: http://www.ctyme.com/intr/rb-0598.htm + * for more information. + */ + CmosMemory.Regs[CMOS_REG_BASE_MEMORY_LOW ] = LOBYTE(0x0280); + CmosMemory.Regs[CMOS_REG_BASE_MEMORY_HIGH] = HIBYTE(0x0280); + + CmosMemory.Regs[CMOS_REG_EXT_MEMORY_LOW] = + CmosMemory.Regs[CMOS_REG_ACTUAL_EXT_MEMORY_LOW] = LOBYTE((MAX_ADDRESS - 0x100000) / 1024); + + CmosMemory.Regs[CMOS_REG_EXT_MEMORY_HIGH] = + CmosMemory.Regs[CMOS_REG_ACTUAL_EXT_MEMORY_HIGH] = HIBYTE((MAX_ADDRESS - 0x100000) / 1024); + + /* Register the I/O Ports */ + RegisterIoPort(CMOS_ADDRESS_PORT, NULL , CmosWritePort); + RegisterIoPort(CMOS_DATA_PORT , CmosReadPort, CmosWritePort); +} + +VOID CmosCleanup(VOID) +{ + DWORD CmosSize = sizeof(CmosMemory); + + if (hCmosRam == INVALID_HANDLE_VALUE) return; + + /* Flush the CMOS memory back to the RAM file and close it */ + SetFilePointer(hCmosRam, 0, NULL, FILE_BEGIN); + WriteFile(hCmosRam, &CmosMemory, CmosSize, &CmosSize, NULL); + + CloseHandle(hCmosRam); + hCmosRam = INVALID_HANDLE_VALUE; +} + +/* EOF */ diff --git a/subsystems/ntvdm/hardware/cmos.h b/subsystems/ntvdm/hardware/cmos.h new file mode 100644 index 00000000000..f84d27ccc28 --- /dev/null +++ b/subsystems/ntvdm/hardware/cmos.h @@ -0,0 +1,139 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: cmos.h + * PURPOSE: CMOS Real Time Clock emulation + * PROGRAMMERS: Aleksandar Andrejevic + */ + +#ifndef _CMOS_H_ +#define _CMOS_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" + +/* DEFINES ********************************************************************/ + +#define RTC_IRQ_NUMBER 8 +#define CMOS_ADDRESS_PORT 0x70 +#define CMOS_DATA_PORT 0x71 +#define CMOS_DISABLE_NMI (1 << 7) +#define CMOS_BATTERY_OK 0x80 + +/* Status Register B flags */ +#define CMOS_STB_24HOUR (1 << 1) +#define CMOS_STB_BINARY (1 << 2) +#define CMOS_STB_SQUARE_WAVE (1 << 3) +#define CMOS_STB_INT_ON_UPDATE (1 << 4) +#define CMOS_STB_INT_ON_ALARM (1 << 5) +#define CMOS_STB_INT_PERIODIC (1 << 6) + +/* Status Register C flags */ +#define CMOS_STC_UF CMOS_STB_INT_ON_UPDATE +#define CMOS_STC_AF CMOS_STB_INT_ON_ALARM +#define CMOS_STC_PF CMOS_STB_INT_PERIODIC +#define CMOS_STC_IRQF (1 << 7) + +/* Default register values */ +#define CMOS_DEFAULT_STA 0x26 +#define CMOS_DEFAULT_STB CMOS_STB_24HOUR + +#define WRITE_CMOS_DATA(Cmos, Value) \ + ((Cmos).StatusRegB & CMOS_STB_BINARY) ? (Value) : BCD_TO_BINARY(Value) + +#define READ_CMOS_DATA(Cmos, Value) \ + ((Cmos).StatusRegB & CMOS_STB_BINARY) ? (Value) : BINARY_TO_BCD(Value) + +typedef enum _CMOS_REGISTERS +{ + CMOS_REG_SECONDS, + CMOS_REG_ALARM_SEC, + CMOS_REG_MINUTES, + CMOS_REG_ALARM_MIN, + CMOS_REG_HOURS, + CMOS_REG_ALARM_HRS, + CMOS_REG_DAY_OF_WEEK, + CMOS_REG_DAY, + CMOS_REG_MONTH, + CMOS_REG_YEAR, + CMOS_REG_STATUS_A, + CMOS_REG_STATUS_B, + CMOS_REG_STATUS_C, + CMOS_REG_STATUS_D, + CMOS_REG_DIAGNOSTICS, + CMOS_REG_SHUTDOWN_STATUS, + CMOS_REG_BASE_MEMORY_LOW = 0x15, + CMOS_REG_BASE_MEMORY_HIGH = 0x16, + CMOS_REG_EXT_MEMORY_LOW = 0x17, + CMOS_REG_EXT_MEMORY_HIGH = 0x18, + CMOS_REG_ACTUAL_EXT_MEMORY_LOW = 0x30, + CMOS_REG_ACTUAL_EXT_MEMORY_HIGH = 0x31, + CMOS_REG_MAX = 0x40 +} CMOS_REGISTERS, *PCMOS_REGISTERS; + +/* + * CMOS Memory Map + * + * See the following documentation for more information: + * http://www.intel-assembler.it/portale/5/cmos-memory-map-123/cmos-memory-map-123.asp + * http://wiki.osdev.org/CMOS + * http://www.walshcomptech.com/ohlandl/config/cmos_registers.html + * http://www.fysnet.net/cmosinfo.htm + * http://www.bioscentral.com/misc/cmosmap.htm + */ +#pragma pack(push, 1) +typedef struct +{ + BYTE Second; // 0x00 + BYTE AlarmSecond; // 0x01 + BYTE Minute; // 0x02 + BYTE AlarmMinute; // 0x03 + BYTE Hour; // 0x04 + BYTE AlarmHour; // 0x05 + BYTE DayOfWeek; // 0x06 + BYTE Day; // 0x07 + BYTE Month; // 0x08 + BYTE Year; // 0x09 + + BYTE StatusRegA; // 0x0a + BYTE StatusRegB; // 0x0b +} CMOS_CLOCK, *PCMOS_CLOCK; + +typedef struct +{ + union + { + struct + { + CMOS_CLOCK; // 0x00 - 0x0b + BYTE StatusRegC; // 0x0c + BYTE StatusRegD; // 0x0d + BYTE Diagnostics; // 0x0e + BYTE ShutdownStatus; // 0x0f + }; + BYTE Regs1[0x10]; // 0x00 - 0x0f + BYTE Regs [0x40]; // 0x00 - 0x3f + }; + + /* + * Extended information 0x40 - 0x7f + */ +} CMOS_MEMORY, *PCMOS_MEMORY; +#pragma pack(pop) + +C_ASSERT(sizeof(CMOS_MEMORY) == 0x40); + +/* FUNCTIONS ******************************************************************/ + +BOOLEAN IsNmiEnabled(VOID); +DWORD RtcGetTicksPerSecond(VOID); +VOID RtcPeriodicTick(VOID); +VOID RtcTimeUpdate(VOID); + +VOID CmosInitialize(VOID); +VOID CmosCleanup(VOID); + +#endif // _CMOS_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/hardware/pic.c b/subsystems/ntvdm/hardware/pic.c new file mode 100644 index 00000000000..a5b068c270e --- /dev/null +++ b/subsystems/ntvdm/hardware/pic.c @@ -0,0 +1,342 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: pic.c + * PURPOSE: Programmable Interrupt Controller emulation + * (Interrupt Controller Adapter (ICA) in Windows terminology) + * PROGRAMMERS: Aleksandar Andrejevic + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "io.h" +#include "pic.h" + +/* PRIVATE VARIABLES **********************************************************/ + +static PIC MasterPic, SlavePic; + +/* PRIVATE FUNCTIONS **********************************************************/ + +static BYTE PicReadCommand(BYTE Port) +{ + PPIC Pic; + + /* Which PIC are we accessing? */ + if (Port == PIC_MASTER_CMD) Pic = &MasterPic; + else Pic = &SlavePic; + + if (Pic->ReadIsr) + { + /* Read the in-service register */ + Pic->ReadIsr = FALSE; + return Pic->InServiceRegister; + } + else + { + /* Read the interrupt request register */ + return Pic->IntRequestRegister; + } +} + +static VOID PicWriteCommand(BYTE Port, BYTE Value) +{ + PPIC Pic; + + /* Which PIC are we accessing? */ + if (Port == PIC_MASTER_CMD) Pic = &MasterPic; + else Pic = &SlavePic; + + if (Value & PIC_ICW1) + { + /* Start initialization */ + Pic->Initialization = TRUE; + Pic->IntOffset = 0xFF; + Pic->CascadeRegisterSet = FALSE; + Pic->ConfigRegister = Value; + return; + } + + if (Value & PIC_OCW3) + { + /* This is an OCR3 */ + if (Value == PIC_OCW3_READ_ISR) + { + /* Return the ISR on next read from command port */ + Pic->ReadIsr = TRUE; + } + + return; + } + + /* This is an OCW2 */ + if (Value & PIC_OCW2_EOI) + { + if (Value & PIC_OCW2_SL) + { + /* If the SL bit is set, clear a specific IRQ */ + Pic->InServiceRegister &= ~(1 << (Value & PIC_OCW2_NUM_MASK)); + } + else + { + /* Otherwise, clear all of them */ + Pic->InServiceRegister = 0; + } + } +} + +static BYTE PicReadData(BYTE Port) +{ + /* Read the mask register */ + if (Port == PIC_MASTER_DATA) return MasterPic.MaskRegister; + else return SlavePic.MaskRegister; +} + +static VOID PicWriteData(BYTE Port, BYTE Value) +{ + PPIC Pic; + + /* Which PIC are we accessing? */ + if (Port == PIC_MASTER_DATA) Pic = &MasterPic; + else Pic = &SlavePic; + + /* Is the PIC ready? */ + if (!Pic->Initialization) + { + /* Yes, this is an OCW1 */ + Pic->MaskRegister = Value; + return; + } + + /* Has the interrupt offset been set? */ + if (Pic->IntOffset == 0xFF) + { + /* This is an ICW2, set the offset (last three bits always zero) */ + Pic->IntOffset = Value & 0xF8; + + /* Check if we are in single mode and don't need an ICW4 */ + if ((Pic->ConfigRegister & PIC_ICW1_SINGLE) + && !(Pic->ConfigRegister & PIC_ICW1_ICW4)) + { + /* Yes, done initializing */ + Pic->Initialization = FALSE; + } + return; + } + + /* Check if we are in cascade mode and the cascade register was not set */ + if (!(Pic->ConfigRegister & PIC_ICW1_SINGLE) && !Pic->CascadeRegisterSet) + { + /* This is an ICW3 */ + Pic->CascadeRegister = Value; + Pic->CascadeRegisterSet = TRUE; + + /* Check if we need an ICW4 */ + if (!(Pic->ConfigRegister & PIC_ICW1_ICW4)) + { + /* No, done initializing */ + Pic->Initialization = FALSE; + } + return; + } + + /* This must be an ICW4, we will ignore the 8086 bit (assume always set) */ + if (Value & PIC_ICW4_AEOI) + { + /* Use automatic end-of-interrupt */ + Pic->AutoEoi = TRUE; + } + + /* Done initializing */ + Pic->Initialization = FALSE; +} + +static BYTE WINAPI PicReadPort(ULONG Port) +{ + switch (Port) + { + case PIC_MASTER_CMD: + case PIC_SLAVE_CMD: + { + return PicReadCommand(Port); + } + + case PIC_MASTER_DATA: + case PIC_SLAVE_DATA: + { + return PicReadData(Port); + } + } + + return 0; +} + +static VOID WINAPI PicWritePort(ULONG Port, BYTE Data) +{ + switch (Port) + { + case PIC_MASTER_CMD: + case PIC_SLAVE_CMD: + { + PicWriteCommand(Port, Data); + break; + } + + case PIC_MASTER_DATA: + case PIC_SLAVE_DATA: + { + PicWriteData(Port, Data); + break; + } + } +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID PicInterruptRequest(BYTE Number) +{ + BYTE i; + + if (/* Number >= 0 && */ Number < 8) + { + /* Check if any of the higher-priority interrupts are busy */ + for (i = 0; i <= Number; i++) + { + if (MasterPic.InServiceRegister & (1 << Number)) return; + } + + /* Check if the interrupt is masked */ + if (MasterPic.MaskRegister & (1 << Number)) return; + + /* Set the appropriate bit in the IRR and interrupt the CPU */ + MasterPic.IntRequestRegister |= 1 << Number; + EmulatorInterruptSignal(); + } + else if (Number >= 8 && Number < 16) + { + Number -= 8; + + /* + * The slave PIC is connected to IRQ 2, always! If the master PIC + * was misconfigured, don't do anything. + */ + if (!(MasterPic.CascadeRegister & (1 << 2)) + || SlavePic.CascadeRegister != 2) + { + return; + } + + /* Check if any of the higher-priority interrupts are busy */ + if (MasterPic.InServiceRegister != 0) return; + for (i = 0; i <= Number; i++) + { + if (SlavePic.InServiceRegister & (1 << Number)) return; + } + + /* Check if the interrupt is masked */ + if (SlavePic.MaskRegister & (1 << Number)) return; + + /* Set the IRQ 2 bit in the master ISR */ + if (!MasterPic.AutoEoi) MasterPic.InServiceRegister |= (1 << 2); + + /* Set the appropriate bit in the IRR and interrupt the CPU */ + SlavePic.IntRequestRegister |= 1 << Number; + EmulatorInterruptSignal(); + } +} + +BYTE PicGetInterrupt(VOID) +{ + INT i, j; + + /* Search interrupts by priority */ + for (i = 0; i < 8; i++) + { + /* Check if this line is cascaded to the slave PIC */ + if ((i == 2) + && MasterPic.CascadeRegister & (1 << 2) + && SlavePic.Slave + && (SlavePic.CascadeRegister == 2)) + { + /* Search the slave PIC interrupts by priority */ + for (j = 0; j < 8; j++) if ((j != 1) && SlavePic.IntRequestRegister & (1 << j)) + { + /* Clear the IRR flag */ + SlavePic.IntRequestRegister &= ~(1 << j); + + /* Set the ISR flag, unless AEOI is enabled */ + if (!SlavePic.AutoEoi) SlavePic.InServiceRegister |= (1 << j); + + /* Return the interrupt number */ + return SlavePic.IntOffset + j; + } + } + + if (MasterPic.IntRequestRegister & (1 << i)) + { + /* Clear the IRR flag */ + MasterPic.IntRequestRegister &= ~(1 << i); + + /* Set the ISR flag, unless AEOI is enabled */ + if (!MasterPic.AutoEoi) MasterPic.InServiceRegister |= (1 << i); + + /* Return the interrupt number */ + return MasterPic.IntOffset + i; + } + } + + /* Spurious interrupt */ + if (MasterPic.InServiceRegister & (1 << 2)) return SlavePic.IntOffset + 7; + else return MasterPic.IntOffset + 7; +} + +VOID PicInitialize(VOID) +{ + /* Register the I/O Ports */ + RegisterIoPort(PIC_MASTER_CMD , PicReadPort, PicWritePort); + RegisterIoPort(PIC_SLAVE_CMD , PicReadPort, PicWritePort); + RegisterIoPort(PIC_MASTER_DATA, PicReadPort, PicWritePort); + RegisterIoPort(PIC_SLAVE_DATA , PicReadPort, PicWritePort); +} + + + +VOID +WINAPI +call_ica_hw_interrupt(INT ms, + BYTE line, + INT count) +{ + BYTE InterruptNumber = line; + + /* Check for PIC validity */ + if (ms != ICA_MASTER && ms != ICA_SLAVE) return; + + /* + * Adjust the interrupt request number according to the parameters, + * by adding an offset == 8 to the interrupt number. + * + * Indeed VDDs calling this function usually subtracts 8 so that they give: + * + * ms | line | corresponding interrupt number + * ------------+--------+-------------------------------- + * ICA_MASTER | 0 -- 7 | 0 -- 7 + * ICA_SLAVE | 0 -- 7 | 8 -- 15 + * + * and PicInterruptRequest subtracts again 8 to the interrupt number + * if it is greater or equal than 8 (so that it determines which PIC + * to use via the interrupt number). + */ + if (ms == ICA_SLAVE) InterruptNumber += 8; + + /* Send the specified number of interrupt requests */ + while (count-- > 0) + { + PicInterruptRequest(InterruptNumber); + } +} + +/* EOF */ diff --git a/subsystems/ntvdm/hardware/pic.h b/subsystems/ntvdm/hardware/pic.h new file mode 100644 index 00000000000..03d7dd1738e --- /dev/null +++ b/subsystems/ntvdm/hardware/pic.h @@ -0,0 +1,61 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: pic.h + * PURPOSE: Programmable Interrupt Controller emulation + * (Interrupt Controller Adapter (ICA) in Windows terminology) + * PROGRAMMERS: Aleksandar Andrejevic + */ + +#ifndef _PIC_H_ +#define _PIC_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" + +/* DEFINES ********************************************************************/ + +#define PIC_MASTER_CMD 0x20 +#define PIC_MASTER_DATA 0x21 +#define PIC_SLAVE_CMD 0xA0 +#define PIC_SLAVE_DATA 0xA1 + +#define PIC_ICW1 0x10 +#define PIC_ICW1_ICW4 (1 << 0) +#define PIC_ICW1_SINGLE (1 << 1) +#define PIC_ICW4_8086 (1 << 0) +#define PIC_ICW4_AEOI (1 << 1) + +#define PIC_OCW2_NUM_MASK 0x07 +#define PIC_OCW2_EOI (1 << 5) +#define PIC_OCW2_SL (1 << 6) + +#define PIC_OCW3 (1 << 3) +#define PIC_OCW3_READ_ISR 0x0B + +typedef struct _PIC +{ + BOOLEAN Initialization; + BYTE MaskRegister; + BYTE IntRequestRegister; + BYTE InServiceRegister; + BYTE IntOffset; + BYTE ConfigRegister; + BYTE CascadeRegister; + BOOLEAN CascadeRegisterSet; + BOOLEAN AutoEoi; + BOOLEAN Slave; + BOOLEAN ReadIsr; +} PIC, *PPIC; + +/* FUNCTIONS ******************************************************************/ + +VOID PicInterruptRequest(BYTE Number); +BYTE PicGetInterrupt(VOID); + +VOID PicInitialize(VOID); + +#endif // _PIC_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/hardware/ps2.c b/subsystems/ntvdm/hardware/ps2.c new file mode 100644 index 00000000000..c98d32e76df --- /dev/null +++ b/subsystems/ntvdm/hardware/ps2.c @@ -0,0 +1,365 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: ps2.c + * PURPOSE: PS/2 controller emulation + * PROGRAMMERS: Aleksandar Andrejevic + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "io.h" +#include "ps2.h" +#include "pic.h" + +/* PRIVATE VARIABLES **********************************************************/ + +static BYTE KeyboardQueue[KEYBOARD_BUFFER_SIZE]; +static BOOLEAN KeyboardQueueEmpty = TRUE; +static UINT KeyboardQueueStart = 0; +static UINT KeyboardQueueEnd = 0; +static BYTE KeyboardData = 0, KeyboardResponse = 0; +static BOOLEAN KeyboardReadResponse = FALSE, KeyboardWriteResponse = FALSE; +static BYTE KeyboardConfig = PS2_DEFAULT_CONFIG; +static HANDLE QueueMutex = NULL; + +/* PRIVATE FUNCTIONS **********************************************************/ + +static BOOLEAN KeyboardQueuePush(BYTE ScanCode) +{ + BOOLEAN Result = TRUE; + + WaitForSingleObject(QueueMutex, INFINITE); + + /* Check if the keyboard queue is full */ + if (!KeyboardQueueEmpty && (KeyboardQueueStart == KeyboardQueueEnd)) + { + Result = FALSE; + goto Done; + } + + /* Insert the value in the queue */ + KeyboardQueue[KeyboardQueueEnd] = ScanCode; + KeyboardQueueEnd++; + KeyboardQueueEnd %= KEYBOARD_BUFFER_SIZE; + + /* Since we inserted a value, it's not empty anymore */ + KeyboardQueueEmpty = FALSE; + +Done: + ReleaseMutex(QueueMutex); + return Result; +} + +static BOOLEAN KeyboardQueuePop(BYTE *ScanCode) +{ + BOOLEAN Result = TRUE; + + /* Make sure the keyboard queue is not empty (fast check) */ + if (KeyboardQueueEmpty) return FALSE; + + WaitForSingleObject(QueueMutex, INFINITE); + + /* + * Recheck whether keyboard queue is not empty (it + * may have changed after having grabbed the mutex). + */ + if (KeyboardQueueEmpty) + { + Result = FALSE; + goto Done; + } + + /* Get the scan code */ + *ScanCode = KeyboardQueue[KeyboardQueueStart]; + + /* Remove the value from the queue */ + KeyboardQueueStart++; + KeyboardQueueStart %= KEYBOARD_BUFFER_SIZE; + + /* Check if the queue is now empty */ + if (KeyboardQueueStart == KeyboardQueueEnd) + { + KeyboardQueueEmpty = TRUE; + } + +Done: + ReleaseMutex(QueueMutex); + return Result; +} + +static BYTE WINAPI PS2ReadPort(ULONG Port) +{ + if (Port == PS2_CONTROL_PORT) + { + BYTE Status = 0; + + /* Set the first bit if the data can be read */ + if (KeyboardReadResponse || !KeyboardQueueEmpty) Status |= 1 << 0; + + /* Always set bit 2 */ + Status |= 1 << 2; + + /* Set bit 3 if the next byte goes to the controller */ + if (KeyboardWriteResponse) Status |= 1 << 3; + + return Status; + } + else if (Port == PS2_DATA_PORT) + { + /* If there was a response byte from the controller, return it */ + if (KeyboardReadResponse) + { + KeyboardReadResponse = FALSE; + KeyboardData = KeyboardResponse; + } + + return KeyboardData; + } + else return 0; +} + +static VOID WINAPI PS2WritePort(ULONG Port, BYTE Data) +{ + if (Port == PS2_CONTROL_PORT) + { + switch (Data) + { + /* Read configuration byte */ + case 0x20: + { + KeyboardResponse = KeyboardConfig; + KeyboardReadResponse = TRUE; + break; + } + + /* Write configuration byte */ + case 0x60: + /* Write controller output port */ + case 0xD1: + /* Write keyboard output buffer */ + case 0xD2: + /* Write mouse output buffer */ + case 0xD3: + /* Write mouse input buffer */ + case 0xD4: + { + /* These commands require a response */ + KeyboardResponse = Data; + KeyboardWriteResponse = TRUE; + break; + } + + /* Disable mouse */ + case 0xA7: + { + // TODO: Mouse support + break; + } + + /* Enable mouse */ + case 0xA8: + { + // TODO: Mouse support + break; + } + + /* Test mouse port */ + case 0xA9: + { + KeyboardResponse = 0; + KeyboardReadResponse = TRUE; + break; + } + + /* Test PS/2 controller */ + case 0xAA: + { + KeyboardResponse = 0x55; + KeyboardReadResponse = TRUE; + break; + } + + /* Disable keyboard */ + case 0xAD: + { + // TODO: Not implemented + break; + } + + /* Enable keyboard */ + case 0xAE: + { + // TODO: Not implemented + break; + } + + /* Read controller output port */ + case 0xD0: + { + // TODO: Not implemented + break; + } + + /* CPU Reset */ + case 0xF0: + case 0xF2: + case 0xF4: + case 0xF6: + case 0xF8: + case 0xFA: + case 0xFC: + case 0xFE: + { + /* Stop the VDM */ + EmulatorTerminate(); + break; + } + } + } + else if (Port == PS2_DATA_PORT) + { + /* Check if the controller is waiting for a response */ + if (KeyboardWriteResponse) + { + KeyboardWriteResponse = FALSE; + + /* Check which command it was */ + switch (KeyboardResponse) + { + /* Write configuration byte */ + case 0x60: + { + KeyboardConfig = Data; + break; + } + + /* Write controller output */ + case 0xD1: + { + /* Check if bit 0 is unset */ + if (!(Data & (1 << 0))) + { + /* CPU disabled - Stop the VDM */ + EmulatorTerminate(); + } + + /* Update the A20 line setting */ + EmulatorSetA20(Data & (1 << 1)); + + break; + } + + case 0xD2: + { + /* Push the data byte to the keyboard queue */ + KeyboardQueuePush(Data); + break; + } + + case 0xD3: + { + // TODO: Mouse support + break; + } + + case 0xD4: + { + // TODO: Mouse support + break; + } + } + + return; + } + + // TODO: Implement PS/2 device commands + } +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID PS2Dispatch(PINPUT_RECORD InputRecord) +{ + /* Check the event type */ + switch (InputRecord->EventType) + { + case KEY_EVENT: + { + WORD i; + BYTE ScanCode = (BYTE)InputRecord->Event.KeyEvent.wVirtualScanCode; + + /* If this is a key release, set the highest bit in the scan code */ + if (!InputRecord->Event.KeyEvent.bKeyDown) ScanCode |= 0x80; + + /* Push the scan code onto the keyboard queue */ + for (i = 0; i < InputRecord->Event.KeyEvent.wRepeatCount; i++) + { + KeyboardQueuePush(ScanCode); + } + + break; + } + + case MOUSE_EVENT: + { + // TODO: NOT IMPLEMENTED + UNIMPLEMENTED; + break; + } + + /* We ignore all the rest */ + default: + break; + } +} + +VOID GenerateKeyboardInterrupts(VOID) +{ + /* Generate an IRQ 1 if there is a key ready in the queue */ + if (KeyboardQueuePop(&KeyboardData)) PicInterruptRequest(1); +} + +BOOLEAN PS2Initialize(HANDLE ConsoleInput) +{ +#if 0 + DWORD ConInMode; +#endif + + /* Create the mutex */ + QueueMutex = CreateMutex(NULL, FALSE, NULL); + + /* Register the I/O Ports */ + RegisterIoPort(PS2_CONTROL_PORT, PS2ReadPort, PS2WritePort); + RegisterIoPort(PS2_DATA_PORT , PS2ReadPort, PS2WritePort); + +#if 0 + if (GetConsoleMode(ConsoleInput, &ConInMode)) + { + if (MousePresent) + { + /* Support mouse input events if there is a mouse on the system */ + ConInMode |= ENABLE_MOUSE_INPUT; + } + else + { + /* Do not support mouse input events if there is no mouse on the system */ + ConInMode &= ~ENABLE_MOUSE_INPUT; + } + + SetConsoleMode(ConsoleInput, ConInMode); + } +#endif + + return TRUE; +} + +VOID PS2Cleanup(VOID) +{ + CloseHandle(QueueMutex); +} + +/* EOF */ diff --git a/subsystems/ntvdm/hardware/ps2.h b/subsystems/ntvdm/hardware/ps2.h new file mode 100644 index 00000000000..119e9bdc471 --- /dev/null +++ b/subsystems/ntvdm/hardware/ps2.h @@ -0,0 +1,35 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: ps2.h + * PURPOSE: PS/2 controller emulation + * PROGRAMMERS: Aleksandar Andrejevic + */ + +#ifndef _PS2_H_ +#define _PS2_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" + +/* DEFINES ********************************************************************/ + +#define KEYBOARD_BUFFER_SIZE 32 +#define PS2_DATA_PORT 0x60 +#define PS2_CONTROL_PORT 0x64 +#define PS2_DEFAULT_CONFIG 0x05 +#define KEYBOARD_ACK 0xFA +#define KEYBOARD_RESEND 0xFE + +/* FUNCTIONS ******************************************************************/ + +VOID PS2Dispatch(PINPUT_RECORD InputRecord); +VOID GenerateKeyboardInterrupts(VOID); + +BOOLEAN PS2Initialize(HANDLE ConsoleInput); +VOID PS2Cleanup(VOID); + +#endif // _PS2_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/hardware/speaker.c b/subsystems/ntvdm/hardware/speaker.c new file mode 100644 index 00000000000..03bf25cc84a --- /dev/null +++ b/subsystems/ntvdm/hardware/speaker.c @@ -0,0 +1,145 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: speaker.c + * PURPOSE: PC Speaker emulation + * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "speaker.h" +#include "io.h" +#include "timer.h" + +/* Extra PSDK/NDK Headers */ +#include +#include +#include + +/* DDK Driver Headers */ +#include + +/* PRIVATE VARIABLES **********************************************************/ + +static HANDLE hBeep = NULL; + +/* PRIVATE FUNCTIONS **********************************************************/ + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID SpeakerChange(VOID) +{ + BYTE Port61hState = IOReadB(CONTROL_SYSTEM_PORT61H); + BOOLEAN IsConnectedToPITChannel2 = !!(Port61hState & 0x01); + BOOLEAN SpeakerDataOn = !!(Port61hState & 0x02); + + if (PitChannel2 && IsConnectedToPITChannel2 && SpeakerDataOn) + { + /* Start beeping - Adapted from kernel32:Beep() */ + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + BEEP_SET_PARAMETERS BeepSetParameters; + + DWORD PitChannel2ReloadValue = PitChannel2->ReloadValue; + if (PitChannel2ReloadValue == 0) PitChannel2ReloadValue = 65536; + + /* Set beep data */ + BeepSetParameters.Frequency = (PIT_BASE_FREQUENCY / PitChannel2ReloadValue) * + (PitChannel2->Mode == PIT_MODE_SQUARE_WAVE ? 2 : 1); + BeepSetParameters.Duration = INFINITE; + + /* Send the beep */ + Status = NtDeviceIoControlFile(hBeep, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_BEEP_SET, + &BeepSetParameters, + sizeof(BeepSetParameters), + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Beep (%lu, %lu) failed, Status 0x%08lx\n", + BeepSetParameters.Frequency, + BeepSetParameters.Duration, + Status); + } + } + else + { + /* Stop beeping */ + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + BEEP_SET_PARAMETERS BeepSetParameters; + + /* Set beep data */ + BeepSetParameters.Frequency = 0x00; + BeepSetParameters.Duration = 0x00; + + /* Send the beep */ + Status = NtDeviceIoControlFile(hBeep, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_BEEP_SET, + &BeepSetParameters, + sizeof(BeepSetParameters), + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Beep (%lu, %lu) failed, Status 0x%08lx\n", + BeepSetParameters.Frequency, + BeepSetParameters.Duration, + Status); + } + } +} + +VOID SpeakerInitialize(VOID) +{ + NTSTATUS Status; + UNICODE_STRING BeepDevice; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + + /* Adapted from kernel32:Beep() */ + + // + // On TS systems, we need to Load Winsta.dll and call WinstationBeepOpen + // after doing a GetProcAddress for it + // + + /* Open the device */ + RtlInitUnicodeString(&BeepDevice, L"\\Device\\Beep"); + InitializeObjectAttributes(&ObjectAttributes, &BeepDevice, 0, NULL, NULL); + Status = NtCreateFile(&hBeep, + FILE_READ_DATA | FILE_WRITE_DATA, + &ObjectAttributes, + &IoStatusBlock, + NULL, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN_IF, + 0, + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to open Beep driver, Status 0x%08lx\n", Status); + } +} + +VOID SpeakerCleanup(VOID) +{ + NtClose(hBeep); +} + +/* EOF */ diff --git a/subsystems/ntvdm/hardware/speaker.h b/subsystems/ntvdm/hardware/speaker.h new file mode 100644 index 00000000000..94c9fc07db5 --- /dev/null +++ b/subsystems/ntvdm/hardware/speaker.h @@ -0,0 +1,27 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: speaker.h + * PURPOSE: PC Speaker emulation + * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +#ifndef _SPEAKER_H_ +#define _SPEAKER_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" + +/* DEFINES ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +VOID SpeakerChange(VOID); + +VOID SpeakerInitialize(VOID); +VOID SpeakerCleanup(VOID); + +#endif // _SPEAKER_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/hardware/timer.c b/subsystems/ntvdm/hardware/timer.c new file mode 100644 index 00000000000..87f68634479 --- /dev/null +++ b/subsystems/ntvdm/hardware/timer.c @@ -0,0 +1,522 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: timer.c + * PURPOSE: Programmable Interval Timer emulation - + * i82C54/8254 compatible + * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "io.h" +#include "timer.h" +#include "pic.h" + +/* PRIVATE VARIABLES **********************************************************/ + +static PIT_CHANNEL PitChannels[PIT_CHANNELS]; +PPIT_CHANNEL PitChannel2 = &PitChannels[2]; + +/* PRIVATE FUNCTIONS **********************************************************/ + +static VOID PitLatchChannelStatus(BYTE Channel) +{ + if (Channel >= PIT_CHANNELS) return; + + /* + * A given counter can be latched only one time until it gets unlatched. + * If the counter is latched and then is latched again later before the + * value is read, then this last latch command is ignored and the value + * will be the value at the time the first command was issued. + */ + if (PitChannels[Channel].LatchStatusSet == FALSE) + { + BYTE StatusLatch = 0; + /** HACK!! **/BYTE NullCount = 0;/** HACK!! **/ + + StatusLatch = PitChannels[Channel].Out << 7 | NullCount << 6; + StatusLatch |= (PitChannels[Channel].ReadWriteMode & 0x03) << 4; + StatusLatch |= (PitChannels[Channel].Mode & 0x07) << 1; + StatusLatch |= (PitChannels[Channel].Bcd & 0x01); + + /* Latch the counter's status */ + PitChannels[Channel].LatchStatusSet = TRUE; + PitChannels[Channel].StatusLatch = StatusLatch; + } +} + +static VOID PitLatchChannelCount(BYTE Channel) +{ + if (Channel >= PIT_CHANNELS) return; + + /* + * A given counter can be latched only one time until it gets unlatched. + * If the counter is latched and then is latched again later before the + * value is read, then this last latch command is ignored and the value + * will be the value at the time the first command was issued. + */ + if (PitChannels[Channel].ReadStatus == 0x00) + { + /* Latch the counter's value */ + PitChannels[Channel].ReadStatus = PitChannels[Channel].ReadWriteMode; + + /* Convert the current value to BCD if needed */ + PitChannels[Channel].OutputLatch = + READ_PIT_VALUE(PitChannels[Channel], PitChannels[Channel].CurrentValue); + } +} + +static VOID PitSetOut(PPIT_CHANNEL Channel, BOOLEAN State) +{ + /** HACK!! **\ if (State == Channel->Out) return; \** HACK!! **/ + + /* Set the new state of the OUT pin */ + Channel->Out = State; + + /* Call the callback */ + if (Channel->OutFunction) Channel->OutFunction(Channel->OutParam, State); +} + +static VOID PitInitCounter(PPIT_CHANNEL Channel) +{ + switch (Channel->Mode) + { + case PIT_MODE_INT_ON_TERMINAL_COUNT: + PitSetOut(Channel, FALSE); + break; + + case PIT_MODE_HARDWARE_ONE_SHOT: + case PIT_MODE_RATE_GENERATOR: + case PIT_MODE_SQUARE_WAVE: + case PIT_MODE_SOFTWARE_STROBE: + case PIT_MODE_HARDWARE_STROBE: + PitSetOut(Channel, TRUE); + break; + } +} + +static VOID PitWriteCommand(BYTE Value) +{ + BYTE Channel = (Value >> 6) & 0x03; + BYTE ReadWriteMode = (Value >> 4) & 0x03; + BYTE Mode = (Value >> 1) & 0x07; + BOOLEAN IsBcd = Value & 0x01; + + /* + * Check for valid PIT channel - Possible values: 0, 1, 2. + * A value of 3 is for Read-Back Command. + */ + if (Channel > PIT_CHANNELS) return; + + /* Read-Back Command */ + if (Channel == PIT_CHANNELS) + { + if ((Value & 0x20) == 0) // Bit 5 (Count) == 0: We latch multiple counters' counts + { + if (Value & 0x02) PitLatchChannelCount(0); + if (Value & 0x04) PitLatchChannelCount(1); + if (Value & 0x08) PitLatchChannelCount(2); + } + if ((Value & 0x10) == 0) // Bit 4 (Status) == 0: We latch multiple counters' statuses + { + if (Value & 0x02) PitLatchChannelStatus(0); + if (Value & 0x04) PitLatchChannelStatus(1); + if (Value & 0x08) PitLatchChannelStatus(2); + } + return; + } + + /* Check if this is a counter latch command... */ + if (ReadWriteMode == 0) + { + PitLatchChannelCount(Channel); + return; + } + + /* ... otherwise, set the modes and reset flip-flops */ + PitChannels[Channel].ReadWriteMode = ReadWriteMode; + PitChannels[Channel].ReadStatus = 0x00; + PitChannels[Channel].WriteStatus = 0x00; + + PitChannels[Channel].LatchStatusSet = FALSE; + PitChannels[Channel].StatusLatch = 0x00; + + PitChannels[Channel].CountRegister = 0x00; + PitChannels[Channel].OutputLatch = 0x00; + + /** HACK!! **/PitChannels[Channel].FlipFlop = FALSE;/** HACK!! **/ + + /* Fix the current value if we switch to BCD counting */ + PitChannels[Channel].Bcd = IsBcd; + if (IsBcd && PitChannels[Channel].CurrentValue > 9999) + PitChannels[Channel].CurrentValue = 9999; + + switch (Mode) + { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + { + PitChannels[Channel].Mode = Mode; + break; + } + + case 6: + case 7: + { + /* + * Modes 6 and 7 become PIT_MODE_RATE_GENERATOR + * and PIT_MODE_SQUARE_WAVE respectively. + */ + PitChannels[Channel].Mode = Mode - 4; + break; + } + } + + PitInitCounter(&PitChannels[Channel]); +} + +static BYTE PitReadData(BYTE Channel) +{ + LPBYTE ReadWriteMode = NULL; + LPWORD CurrentValue = NULL; + + /* + * If the status was latched, the first read operation will return the + * latched status, whichever value (count or status) was latched first. + */ + if (PitChannels[Channel].LatchStatusSet) + { + PitChannels[Channel].LatchStatusSet = FALSE; + return PitChannels[Channel].StatusLatch; + } + + /* To be able to read the count asynchronously, latch it first if needed */ + if (PitChannels[Channel].ReadStatus == 0) PitLatchChannelCount(Channel); + + /* The count is now latched */ + ASSERT(PitChannels[Channel].ReadStatus != 0); + + ReadWriteMode = &PitChannels[Channel].ReadStatus ; + CurrentValue = &PitChannels[Channel].OutputLatch; + + if (*ReadWriteMode & 1) + { + /* Read LSB */ + *ReadWriteMode &= ~1; + return LOBYTE(*CurrentValue); + } + + if (*ReadWriteMode & 2) + { + /* Read MSB */ + *ReadWriteMode &= ~2; + return HIBYTE(*CurrentValue); + } + + /* Shouldn't get here */ + ASSERT(FALSE); + return 0; +} + +static VOID PitWriteData(BYTE Channel, BYTE Value) +{ + LPBYTE ReadWriteMode = NULL; + + if (PitChannels[Channel].WriteStatus == 0x00) + { + PitChannels[Channel].WriteStatus = PitChannels[Channel].ReadWriteMode; + } + + ASSERT(PitChannels[Channel].WriteStatus != 0); + + ReadWriteMode = &PitChannels[Channel].WriteStatus; + + if (*ReadWriteMode & 1) + { + /* Write LSB */ + *ReadWriteMode &= ~1; + PitChannels[Channel].CountRegister &= 0xFF00; + PitChannels[Channel].CountRegister |= Value; + } + else if (*ReadWriteMode & 2) + { + /* Write MSB */ + *ReadWriteMode &= ~2; + PitChannels[Channel].CountRegister &= 0x00FF; + PitChannels[Channel].CountRegister |= Value << 8; + } + + /* ReadWriteMode went to zero: we are going to load the new count */ + if (*ReadWriteMode == 0x00) + { + if (PitChannels[Channel].CountRegister == 0x0000) + { + /* Wrap around to the highest count */ + if (PitChannels[Channel].Bcd) + PitChannels[Channel].CountRegister = 9999; + else + PitChannels[Channel].CountRegister = 0xFFFF; // 0x10000; // 65536 + } + + /* Convert the current value from BCD if needed */ + PitChannels[Channel].CountRegister = + WRITE_PIT_VALUE(PitChannels[Channel], PitChannels[Channel].CountRegister); + PitChannels[Channel].ReloadValue = PitChannels[Channel].CountRegister; + } +} + +static BYTE WINAPI PitReadPort(ULONG Port) +{ + switch (Port) + { + case PIT_DATA_PORT(0): + case PIT_DATA_PORT(1): + case PIT_DATA_PORT(2): + { + return PitReadData(Port - PIT_DATA_PORT(0)); + } + } + + return 0; +} + +static VOID WINAPI PitWritePort(ULONG Port, BYTE Data) +{ + switch (Port) + { + case PIT_COMMAND_PORT: + { + PitWriteCommand(Data); + break; + } + + case PIT_DATA_PORT(0): + case PIT_DATA_PORT(1): + case PIT_DATA_PORT(2): + { + PitWriteData(Port - PIT_DATA_PORT(0), Data); + break; + } + } +} + +static VOID PitDecrementCount(PPIT_CHANNEL Channel, DWORD Count) +{ + if (Count == 0) return; + + switch (Channel->Mode) + { + case PIT_MODE_INT_ON_TERMINAL_COUNT: + { + /* Decrement the value */ + if (Count > Channel->CurrentValue) + { + /* The value does not reload in this case */ + Channel->CurrentValue = 0; + } + else Channel->CurrentValue -= Count; + + /* Did it fall to the terminal count? */ + if (Channel->CurrentValue == 0 && !Channel->Out) + { + /* Yes, raise the output line */ + PitSetOut(Channel, TRUE); + } + break; + } + + case PIT_MODE_RATE_GENERATOR: + { + BOOLEAN Reloaded = FALSE; + + while (Count) + { + if ((Count > Channel->CurrentValue) + && (Channel->CurrentValue != 0)) + { + /* Decrement the count */ + Count -= Channel->CurrentValue; + + /* Reload the value */ + Channel->CurrentValue = Channel->ReloadValue; + + /* Set the flag */ + Reloaded = TRUE; + } + else + { + /* Decrement the value */ + Channel->CurrentValue -= Count; + + /* Clear the count */ + Count = 0; + + /* Did it fall to zero? */ + if (Channel->CurrentValue == 0) + { + Channel->CurrentValue = Channel->ReloadValue; + Reloaded = TRUE; + } + } + } + + /* If there was a reload, raise the output line */ + if (Reloaded) PitSetOut(Channel, TRUE); + + break; + } + + case PIT_MODE_SQUARE_WAVE: + { + INT ReloadCount = 0; + WORD ReloadValue = Channel->ReloadValue; + + /* The reload value must be even */ + ReloadValue &= ~1; + + while (Count) + { + if (((Count * 2) > Channel->CurrentValue) + && (Channel->CurrentValue != 0)) + { + /* Decrement the count */ + Count -= Channel->CurrentValue / 2; + + /* Reload the value */ + Channel->CurrentValue = ReloadValue; + + /* Increment the reload count */ + ReloadCount++; + } + else + { + /* Decrement the value */ + Channel->CurrentValue -= Count * 2; + + /* Clear the count */ + Count = 0; + + /* Did it fall to zero? */ + if (Channel->CurrentValue == 0) + { + /* Reload the value */ + Channel->CurrentValue = ReloadValue; + + /* Increment the reload count */ + ReloadCount++; + } + } + } + + if (ReloadCount == 0) break; + + /* Toggle the flip-flop if the number of reloads was odd */ + if (ReloadCount & 1) + { + Channel->FlipFlop = !Channel->FlipFlop; + // PitSetOut(Channel, !Channel->Out); + } + + /* Was there any rising edge? */ + if ((Channel->FlipFlop && (ReloadCount == 1)) || (ReloadCount > 1)) + { + /* Yes, raise the output line */ + PitSetOut(Channel, TRUE); + } + + break; + } + + case PIT_MODE_SOFTWARE_STROBE: + { + // TODO: NOT IMPLEMENTED + break; + } + + case PIT_MODE_HARDWARE_ONE_SHOT: + case PIT_MODE_HARDWARE_STROBE: + { + /* These modes do not work on x86 PCs */ + break; + } + } +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID PitSetOutFunction(BYTE Channel, LPVOID Param, PIT_OUT_FUNCTION OutFunction) +{ + if (Channel >= PIT_CHANNELS) return; + + PitChannels[Channel].OutParam = Param; + PitChannels[Channel].OutFunction = OutFunction; +} + +VOID PitSetGate(BYTE Channel, BOOLEAN State) +{ + if (Channel >= PIT_CHANNELS) return; + if (State == PitChannels[Channel].Gate) return; + + /* UNIMPLEMENTED */ + PitChannels[Channel].Gate = State; +} + +VOID PitClock(DWORD Count) +{ + UINT i; + + if (Count == 0) return; + + for (i = 0; i < PIT_CHANNELS; i++) + { + // if (!PitChannels[i].Counting) continue; + PitDecrementCount(&PitChannels[i], Count); + } +} + +DWORD PitGetResolution(VOID) +{ + INT i; + DWORD MinReloadValue = 65536; + + for (i = 0; i < PIT_CHANNELS; i++) + { + DWORD ReloadValue = PitChannels[i].ReloadValue; + + /* 0 means 65536 */ + if (ReloadValue == 0) ReloadValue = 65536; + + if (ReloadValue < MinReloadValue) MinReloadValue = ReloadValue; + } + + /* Return the frequency resolution */ + return PIT_BASE_FREQUENCY / MinReloadValue; +} + +VOID PitInitialize(VOID) +{ + /* Set up the timers to their default value */ + PitSetOutFunction(0, NULL, NULL); + PitSetGate(0, TRUE); + PitSetOutFunction(1, NULL, NULL); + PitSetGate(1, TRUE); + PitSetOutFunction(2, NULL, NULL); + PitSetGate(2, FALSE); + + /* Register the I/O Ports */ + RegisterIoPort(PIT_COMMAND_PORT, NULL , PitWritePort); + RegisterIoPort(PIT_DATA_PORT(0), PitReadPort, PitWritePort); + RegisterIoPort(PIT_DATA_PORT(1), PitReadPort, PitWritePort); + RegisterIoPort(PIT_DATA_PORT(2), PitReadPort, PitWritePort); +} + +/* EOF */ diff --git a/subsystems/ntvdm/hardware/timer.h b/subsystems/ntvdm/hardware/timer.h new file mode 100644 index 00000000000..21f7f8ee379 --- /dev/null +++ b/subsystems/ntvdm/hardware/timer.h @@ -0,0 +1,90 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: timer.h + * PURPOSE: Programmable Interval Timer emulation - + * i82C54/8254 compatible + * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +#ifndef _TIMER_H_ +#define _TIMER_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" + +/* DEFINES ********************************************************************/ + +#define PIT_CHANNELS 3 +#define PIT_BASE_FREQUENCY 1193182LL +#define PIT_DATA_PORT(x) (0x40 + (x)) +#define PIT_COMMAND_PORT 0x43 + +#define WRITE_PIT_VALUE(PitChannel, Value) \ + (PitChannel).Bcd ? BCD_TO_BINARY(Value) : (Value) + +#define READ_PIT_VALUE(PitChannel, Value) \ + (PitChannel).Bcd ? BINARY_TO_BCD(Value) : (Value) + +typedef enum _PIT_MODE +{ + PIT_MODE_INT_ON_TERMINAL_COUNT, + PIT_MODE_HARDWARE_ONE_SHOT, + PIT_MODE_RATE_GENERATOR, + PIT_MODE_SQUARE_WAVE, + PIT_MODE_SOFTWARE_STROBE, + PIT_MODE_HARDWARE_STROBE +} PIT_MODE, *PPIT_MODE; + +typedef VOID (WINAPI *PIT_OUT_FUNCTION)(LPVOID Param, BOOLEAN State); + +typedef struct _PIT_CHANNEL +{ + /* PIT Status fields */ + PIT_MODE Mode; + BOOLEAN Bcd; + BYTE ReadWriteMode; // 0 --> Counter Latch ; 1 --> LSB R/W ; 2 --> MSB R/W ; 3 --> LSB then MSB R/W + + /* For interleaved reading and writing in 2-byte RW mode */ + BYTE ReadStatus; // Same convention as ReadWriteMode + BYTE WriteStatus; // Same convention as ReadWriteMode + + /* For reading the PIT status byte */ + BOOLEAN LatchStatusSet; + BYTE StatusLatch; + + /* Counting */ + BOOLEAN Gate; + + /**/WORD CountRegister;/**/ // Our ReloadValue ??? + WORD OutputLatch; + /*******************************/ + + WORD ReloadValue; // Max value of the counter + WORD CurrentValue; // Real value of the counter + + /* PIT Output */ + BOOLEAN Out; // 0: Low ; 1: High + /** HACK!! **/BOOLEAN FlipFlop;/** HACK!! **/ + LPVOID OutParam; + PIT_OUT_FUNCTION OutFunction; + +} PIT_CHANNEL, *PPIT_CHANNEL; + +extern PPIT_CHANNEL PitChannel2; // Needed for PC Speaker + +/* FUNCTIONS ******************************************************************/ + +VOID PitSetOutFunction(BYTE Channel, LPVOID Param, PIT_OUT_FUNCTION OutFunction); +VOID PitSetGate(BYTE Channel, BOOLEAN State); + +VOID PitClock(DWORD Count); +DWORD PitGetResolution(VOID); + +VOID PitInitialize(VOID); + +#endif // _TIMER_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/hardware/vga.c b/subsystems/ntvdm/hardware/vga.c new file mode 100644 index 00000000000..590ff058407 --- /dev/null +++ b/subsystems/ntvdm/hardware/vga.c @@ -0,0 +1,1970 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: vga.c + * PURPOSE: VGA hardware emulation + * PROGRAMMERS: Aleksandar Andrejevic + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "vga.h" +#include "../bios/vidbios.h" + +#include "io.h" + +/* PRIVATE VARIABLES **********************************************************/ + +static CONST DWORD MemoryBase[] = { 0xA0000, 0xA0000, 0xB0000, 0xB8000 }; +static CONST DWORD MemoryLimit[] = { 0xAFFFF, 0xAFFFF, 0xB7FFF, 0xBFFFF }; + +#define USE_REACTOS_COLORS +// #define USE_DOSBOX_COLORS + +#if defined(USE_REACTOS_COLORS) + +// ReactOS colors +static CONST COLORREF VgaDefaultPalette[VGA_MAX_COLORS] = +{ + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA), + RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA), + RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF), + RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF), + RGB(0x00, 0x00, 0x00), RGB(0x10, 0x10, 0x10), RGB(0x20, 0x20, 0x20), RGB(0x35, 0x35, 0x35), + RGB(0x45, 0x45, 0x45), RGB(0x55, 0x55, 0x55), RGB(0x65, 0x65, 0x65), RGB(0x75, 0x75, 0x75), + RGB(0x8A, 0x8A, 0x8A), RGB(0x9A, 0x9A, 0x9A), RGB(0xAA, 0xAA, 0xAA), RGB(0xBA, 0xBA, 0xBA), + RGB(0xCA, 0xCA, 0xCA), RGB(0xDF, 0xDF, 0xDF), RGB(0xEF, 0xEF, 0xEF), RGB(0xFF, 0xFF, 0xFF), + RGB(0x00, 0x00, 0xFF), RGB(0x41, 0x00, 0xFF), RGB(0x82, 0x00, 0xFF), RGB(0xBE, 0x00, 0xFF), + RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0x00, 0xBE), RGB(0xFF, 0x00, 0x82), RGB(0xFF, 0x00, 0x41), + RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x41, 0x00), RGB(0xFF, 0x82, 0x00), RGB(0xFF, 0xBE, 0x00), + RGB(0xFF, 0xFF, 0x00), RGB(0xBE, 0xFF, 0x00), RGB(0x82, 0xFF, 0x00), RGB(0x41, 0xFF, 0x00), + RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0x41), RGB(0x00, 0xFF, 0x82), RGB(0x00, 0xFF, 0xBE), + RGB(0x00, 0xFF, 0xFF), RGB(0x00, 0xBE, 0xFF), RGB(0x00, 0x82, 0xFF), RGB(0x00, 0x41, 0xFF), + RGB(0x82, 0x82, 0xFF), RGB(0x9E, 0x82, 0xFF), RGB(0xBE, 0x82, 0xFF), RGB(0xDF, 0x82, 0xFF), + RGB(0xFF, 0x82, 0xFF), RGB(0xFF, 0x82, 0xDF), RGB(0xFF, 0x82, 0xBE), RGB(0xFF, 0x82, 0x9E), + RGB(0xFF, 0x82, 0x82), RGB(0xFF, 0x9E, 0x82), RGB(0xFF, 0xBE, 0x82), RGB(0xFF, 0xDF, 0x82), + RGB(0xFF, 0xFF, 0x82), RGB(0xDF, 0xFF, 0x82), RGB(0xBE, 0xFF, 0x82), RGB(0x9E, 0xFF, 0x82), + RGB(0x82, 0xFF, 0x82), RGB(0x82, 0xFF, 0x9E), RGB(0x82, 0xFF, 0xBE), RGB(0x82, 0xFF, 0xDF), + RGB(0x82, 0xFF, 0xFF), RGB(0x82, 0xDF, 0xFF), RGB(0x82, 0xBE, 0xFF), RGB(0x82, 0x9E, 0xFF), + RGB(0xBA, 0xBA, 0xFF), RGB(0xCA, 0xBA, 0xFF), RGB(0xDF, 0xBA, 0xFF), RGB(0xEF, 0xBA, 0xFF), + RGB(0xFF, 0xBA, 0xFF), RGB(0xFF, 0xBA, 0xEF), RGB(0xFF, 0xBA, 0xDF), RGB(0xFF, 0xBA, 0xCA), + RGB(0xFF, 0xBA, 0xBA), RGB(0xFF, 0xCA, 0xBA), RGB(0xFF, 0xDF, 0xBA), RGB(0xFF, 0xEF, 0xBA), + RGB(0xFF, 0xFF, 0xBA), RGB(0xEF, 0xFF, 0xBA), RGB(0xDF, 0xFF, 0xBA), RGB(0xCA, 0xFF, 0xBA), + RGB(0xBA, 0xFF, 0xBA), RGB(0xBA, 0xFF, 0xCA), RGB(0xBA, 0xFF, 0xDF), RGB(0xBA, 0xFF, 0xEF), + RGB(0xBA, 0xFF, 0xFF), RGB(0xBA, 0xEF, 0xFF), RGB(0xBA, 0xDF, 0xFF), RGB(0xBA, 0xCA, 0xFF), + RGB(0x00, 0x00, 0x71), RGB(0x1C, 0x00, 0x71), RGB(0x39, 0x00, 0x71), RGB(0x55, 0x00, 0x71), + RGB(0x71, 0x00, 0x71), RGB(0x71, 0x00, 0x55), RGB(0x71, 0x00, 0x39), RGB(0x71, 0x00, 0x1C), + RGB(0x71, 0x00, 0x00), RGB(0x71, 0x1C, 0x00), RGB(0x71, 0x39, 0x00), RGB(0x71, 0x55, 0x00), + RGB(0x71, 0x71, 0x00), RGB(0x55, 0x71, 0x00), RGB(0x39, 0x71, 0x00), RGB(0x1C, 0x71, 0x00), + RGB(0x00, 0x71, 0x00), RGB(0x00, 0x71, 0x1C), RGB(0x00, 0x71, 0x39), RGB(0x00, 0x71, 0x55), + RGB(0x00, 0x71, 0x71), RGB(0x00, 0x55, 0x71), RGB(0x00, 0x39, 0x71), RGB(0x00, 0x1C, 0x71), + RGB(0x39, 0x39, 0x71), RGB(0x45, 0x39, 0x71), RGB(0x55, 0x39, 0x71), RGB(0x61, 0x39, 0x71), + RGB(0x71, 0x39, 0x71), RGB(0x71, 0x39, 0x61), RGB(0x71, 0x39, 0x55), RGB(0x71, 0x39, 0x45), + RGB(0x71, 0x39, 0x39), RGB(0x71, 0x45, 0x39), RGB(0x71, 0x55, 0x39), RGB(0x71, 0x61, 0x39), + RGB(0x71, 0x71, 0x39), RGB(0x61, 0x71, 0x39), RGB(0x55, 0x71, 0x39), RGB(0x45, 0x71, 0x39), + RGB(0x39, 0x71, 0x39), RGB(0x39, 0x71, 0x45), RGB(0x39, 0x71, 0x55), RGB(0x39, 0x71, 0x61), + RGB(0x39, 0x71, 0x71), RGB(0x39, 0x61, 0x71), RGB(0x39, 0x55, 0x71), RGB(0x39, 0x45, 0x71), + RGB(0x51, 0x51, 0x71), RGB(0x59, 0x51, 0x71), RGB(0x61, 0x51, 0x71), RGB(0x69, 0x51, 0x71), + RGB(0x71, 0x51, 0x71), RGB(0x71, 0x51, 0x69), RGB(0x71, 0x51, 0x61), RGB(0x71, 0x51, 0x59), + RGB(0x71, 0x51, 0x51), RGB(0x71, 0x59, 0x51), RGB(0x71, 0x61, 0x51), RGB(0x71, 0x69, 0x51), + RGB(0x71, 0x71, 0x51), RGB(0x69, 0x71, 0x51), RGB(0x61, 0x71, 0x51), RGB(0x59, 0x71, 0x51), + RGB(0x51, 0x71, 0x51), RGB(0x51, 0x71, 0x59), RGB(0x51, 0x71, 0x61), RGB(0x51, 0x71, 0x69), + RGB(0x51, 0x71, 0x71), RGB(0x51, 0x69, 0x71), RGB(0x51, 0x61, 0x71), RGB(0x51, 0x59, 0x71), + RGB(0x00, 0x00, 0x41), RGB(0x10, 0x00, 0x41), RGB(0x20, 0x00, 0x41), RGB(0x31, 0x00, 0x41), + RGB(0x41, 0x00, 0x41), RGB(0x41, 0x00, 0x31), RGB(0x41, 0x00, 0x20), RGB(0x41, 0x00, 0x10), + RGB(0x41, 0x00, 0x00), RGB(0x41, 0x10, 0x00), RGB(0x41, 0x20, 0x00), RGB(0x41, 0x31, 0x00), + RGB(0x41, 0x41, 0x00), RGB(0x31, 0x41, 0x00), RGB(0x20, 0x41, 0x00), RGB(0x10, 0x41, 0x00), + RGB(0x00, 0x41, 0x00), RGB(0x00, 0x41, 0x10), RGB(0x00, 0x41, 0x20), RGB(0x00, 0x41, 0x31), + RGB(0x00, 0x41, 0x41), RGB(0x00, 0x31, 0x41), RGB(0x00, 0x20, 0x41), RGB(0x00, 0x10, 0x41), + RGB(0x20, 0x20, 0x41), RGB(0x28, 0x20, 0x41), RGB(0x31, 0x20, 0x41), RGB(0x39, 0x20, 0x41), + RGB(0x41, 0x20, 0x41), RGB(0x41, 0x20, 0x39), RGB(0x41, 0x20, 0x31), RGB(0x41, 0x20, 0x28), + RGB(0x41, 0x20, 0x20), RGB(0x41, 0x28, 0x20), RGB(0x41, 0x31, 0x20), RGB(0x41, 0x39, 0x20), + RGB(0x41, 0x41, 0x20), RGB(0x39, 0x41, 0x20), RGB(0x31, 0x41, 0x20), RGB(0x28, 0x41, 0x20), + RGB(0x20, 0x41, 0x20), RGB(0x20, 0x41, 0x28), RGB(0x20, 0x41, 0x31), RGB(0x20, 0x41, 0x39), + RGB(0x20, 0x41, 0x41), RGB(0x20, 0x39, 0x41), RGB(0x20, 0x31, 0x41), RGB(0x20, 0x28, 0x41), + RGB(0x2D, 0x2D, 0x41), RGB(0x31, 0x2D, 0x41), RGB(0x35, 0x2D, 0x41), RGB(0x3D, 0x2D, 0x41), + RGB(0x41, 0x2D, 0x41), RGB(0x41, 0x2D, 0x3D), RGB(0x41, 0x2D, 0x35), RGB(0x41, 0x2D, 0x31), + RGB(0x41, 0x2D, 0x2D), RGB(0x41, 0x31, 0x2D), RGB(0x41, 0x35, 0x2D), RGB(0x41, 0x3D, 0x2D), + RGB(0x41, 0x41, 0x2D), RGB(0x3D, 0x41, 0x2D), RGB(0x35, 0x41, 0x2D), RGB(0x31, 0x41, 0x2D), + RGB(0x2D, 0x41, 0x2D), RGB(0x2D, 0x41, 0x31), RGB(0x2D, 0x41, 0x35), RGB(0x2D, 0x41, 0x3D), + RGB(0x2D, 0x41, 0x41), RGB(0x2D, 0x3D, 0x41), RGB(0x2D, 0x35, 0x41), RGB(0x2D, 0x31, 0x41), + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00) +}; + +#elif defined(USE_DOSBOX_COLORS) + +// DOSBox colors +static CONST COLORREF VgaDefaultPalette[VGA_MAX_COLORS] = +{ + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA), + RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA), + RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF), + RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF), + RGB(0x00, 0x00, 0x00), RGB(0x14, 0x14, 0x14), RGB(0x20, 0x20, 0x20), RGB(0x2C, 0x2C, 0x2C), + RGB(0x38, 0x38, 0x38), RGB(0x45, 0x45, 0x45), RGB(0x51, 0x51, 0x51), RGB(0x61, 0x61, 0x61), + RGB(0x71, 0x71, 0x71), RGB(0x82, 0x82, 0x82), RGB(0x92, 0x92, 0x92), RGB(0xA2, 0xA2, 0xA2), + RGB(0xB6, 0xB6, 0xB6), RGB(0xCB, 0xCB, 0xCB), RGB(0xE3, 0xE3, 0xE3), RGB(0xFF, 0xFF, 0xFF), + RGB(0x00, 0x00, 0xFF), RGB(0x41, 0x00, 0xFF), RGB(0x7D, 0x00, 0xFF), RGB(0xBE, 0x00, 0xFF), + RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0x00, 0xBE), RGB(0xFF, 0x00, 0x7D), RGB(0xFF, 0x00, 0x41), + RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x41, 0x00), RGB(0xFF, 0x7D, 0x00), RGB(0xFF, 0xBE, 0x00), + RGB(0xFF, 0xFF, 0x00), RGB(0xBE, 0xFF, 0x00), RGB(0x7D, 0xFF, 0x00), RGB(0x41, 0xFF, 0x00), + RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0x41), RGB(0x00, 0xFF, 0x7D), RGB(0x00, 0xFF, 0xBE), + RGB(0x00, 0xFF, 0xFF), RGB(0x00, 0xBE, 0xFF), RGB(0x00, 0x7D, 0xFF), RGB(0x00, 0x41, 0xFF), + RGB(0x7D, 0x7D, 0xFF), RGB(0x9E, 0x7D, 0xFF), RGB(0xBE, 0x7D, 0xFF), RGB(0xDF, 0x7D, 0xFF), + RGB(0xFF, 0x7D, 0xFF), RGB(0xFF, 0x7D, 0xDF), RGB(0xFF, 0x7D, 0xBE), RGB(0xFF, 0x7D, 0x9E), + + RGB(0xFF, 0x7D, 0x7D), RGB(0xFF, 0x9E, 0x7D), RGB(0xFF, 0xBE, 0x7D), RGB(0xFF, 0xDF, 0x7D), + RGB(0xFF, 0xFF, 0x7D), RGB(0xDF, 0xFF, 0x7D), RGB(0xBE, 0xFF, 0x7D), RGB(0x9E, 0xFF, 0x7D), + RGB(0x7D, 0xFF, 0x7D), RGB(0x7D, 0xFF, 0x9E), RGB(0x7D, 0xFF, 0xBE), RGB(0x7D, 0xFF, 0xDF), + RGB(0x7D, 0xFF, 0xFF), RGB(0x7D, 0xDF, 0xFF), RGB(0x7D, 0xBE, 0xFF), RGB(0x7D, 0x9E, 0xFF), + RGB(0xB6, 0xB6, 0xFF), RGB(0xC7, 0xB6, 0xFF), RGB(0xDB, 0xB6, 0xFF), RGB(0xEB, 0xB6, 0xFF), + RGB(0xFF, 0xB6, 0xFF), RGB(0xFF, 0xB6, 0xEB), RGB(0xFF, 0xB6, 0xDB), RGB(0xFF, 0xB6, 0xC7), + RGB(0xFF, 0xB6, 0xB6), RGB(0xFF, 0xC7, 0xB6), RGB(0xFF, 0xDB, 0xB6), RGB(0xFF, 0xEB, 0xB6), + RGB(0xFF, 0xFF, 0xB6), RGB(0xEB, 0xFF, 0xB6), RGB(0xDB, 0xFF, 0xB6), RGB(0xC7, 0xFF, 0xB6), + RGB(0xB6, 0xFF, 0xB6), RGB(0xB6, 0xFF, 0xC7), RGB(0xB6, 0xFF, 0xDB), RGB(0xB6, 0xFF, 0xEB), + RGB(0xB6, 0xFF, 0xFF), RGB(0xB6, 0xEB, 0xFF), RGB(0xB6, 0xDB, 0xFF), RGB(0xB6, 0xC7, 0xFF), + RGB(0x00, 0x00, 0x71), RGB(0x1C, 0x00, 0x71), RGB(0x38, 0x00, 0x71), RGB(0x55, 0x00, 0x71), + RGB(0x71, 0x00, 0x71), RGB(0x71, 0x00, 0x55), RGB(0x71, 0x00, 0x38), RGB(0x71, 0x00, 0x1C), + RGB(0x71, 0x00, 0x00), RGB(0x71, 0x1C, 0x00), RGB(0x71, 0x38, 0x00), RGB(0x71, 0x55, 0x00), + RGB(0x71, 0x71, 0x00), RGB(0x55, 0x71, 0x00), RGB(0x38, 0x71, 0x00), RGB(0x1C, 0x71, 0x00), + RGB(0x00, 0x71, 0x00), RGB(0x00, 0x71, 0x1C), RGB(0x00, 0x71, 0x38), RGB(0x00, 0x71, 0x55), + RGB(0x00, 0x71, 0x71), RGB(0x00, 0x55, 0x71), RGB(0x00, 0x38, 0x71), RGB(0x00, 0x1C, 0x71), + + RGB(0x38, 0x38, 0x71), RGB(0x45, 0x38, 0x71), RGB(0x55, 0x38, 0x71), RGB(0x61, 0x38, 0x71), + RGB(0x71, 0x38, 0x71), RGB(0x71, 0x38, 0x61), RGB(0x71, 0x38, 0x55), RGB(0x71, 0x38, 0x45), + RGB(0x71, 0x38, 0x38), RGB(0x71, 0x45, 0x38), RGB(0x71, 0x55, 0x38), RGB(0x71, 0x61, 0x38), + RGB(0x71, 0x71, 0x38), RGB(0x61, 0x71, 0x38), RGB(0x55, 0x71, 0x38), RGB(0x45, 0x71, 0x38), + RGB(0x38, 0x71, 0x38), RGB(0x38, 0x71, 0x45), RGB(0x38, 0x71, 0x55), RGB(0x38, 0x71, 0x61), + RGB(0x38, 0x71, 0x71), RGB(0x38, 0x61, 0x71), RGB(0x38, 0x55, 0x71), RGB(0x38, 0x45, 0x71), + RGB(0x51, 0x51, 0x71), RGB(0x59, 0x51, 0x71), RGB(0x61, 0x51, 0x71), RGB(0x69, 0x51, 0x71), + RGB(0x71, 0x51, 0x71), RGB(0x71, 0x51, 0x69), RGB(0x71, 0x51, 0x61), RGB(0x71, 0x51, 0x59), + RGB(0x71, 0x51, 0x51), RGB(0x71, 0x59, 0x51), RGB(0x71, 0x61, 0x51), RGB(0x71, 0x69, 0x51), + RGB(0x71, 0x71, 0x51), RGB(0x69, 0x71, 0x51), RGB(0x61, 0x71, 0x51), RGB(0x59, 0x71, 0x51), + RGB(0x51, 0x71, 0x51), RGB(0x51, 0x71, 0x59), RGB(0x51, 0x71, 0x61), RGB(0x51, 0x71, 0x69), + RGB(0x51, 0x71, 0x71), RGB(0x51, 0x69, 0x71), RGB(0x51, 0x61, 0x71), RGB(0x51, 0x59, 0x71), + RGB(0x00, 0x00, 0x41), RGB(0x10, 0x00, 0x41), RGB(0x20, 0x00, 0x41), RGB(0x30, 0x00, 0x41), + RGB(0x41, 0x00, 0x41), RGB(0x41, 0x00, 0x30), RGB(0x41, 0x00, 0x20), RGB(0x41, 0x00, 0x10), + RGB(0x41, 0x00, 0x00), RGB(0x41, 0x10, 0x00), RGB(0x41, 0x20, 0x00), RGB(0x41, 0x30, 0x00), + RGB(0x41, 0x41, 0x00), RGB(0x30, 0x41, 0x00), RGB(0x20, 0x41, 0x00), RGB(0x10, 0x41, 0x00), + + RGB(0x00, 0x41, 0x00), RGB(0x00, 0x41, 0x10), RGB(0x00, 0x41, 0x20), RGB(0x00, 0x41, 0x30), + RGB(0x00, 0x41, 0x41), RGB(0x00, 0x30, 0x41), RGB(0x00, 0x20, 0x41), RGB(0x00, 0x10, 0x41), + RGB(0x20, 0x20, 0x41), RGB(0x28, 0x20, 0x41), RGB(0x30, 0x20, 0x41), RGB(0x38, 0x20, 0x41), + RGB(0x41, 0x20, 0x41), RGB(0x41, 0x20, 0x38), RGB(0x41, 0x20, 0x30), RGB(0x41, 0x20, 0x28), + RGB(0x41, 0x20, 0x20), RGB(0x41, 0x28, 0x20), RGB(0x41, 0x30, 0x20), RGB(0x41, 0x38, 0x20), + RGB(0x41, 0x41, 0x20), RGB(0x38, 0x41, 0x20), RGB(0x30, 0x41, 0x20), RGB(0x28, 0x41, 0x20), + RGB(0x20, 0x41, 0x20), RGB(0x20, 0x41, 0x28), RGB(0x20, 0x41, 0x30), RGB(0x20, 0x41, 0x38), + RGB(0x20, 0x41, 0x41), RGB(0x20, 0x38, 0x41), RGB(0x20, 0x30, 0x41), RGB(0x20, 0x28, 0x41), + RGB(0x2C, 0x2C, 0x41), RGB(0x30, 0x2C, 0x41), RGB(0x34, 0x2C, 0x41), RGB(0x3C, 0x2C, 0x41), + RGB(0x41, 0x2C, 0x41), RGB(0x41, 0x2C, 0x3C), RGB(0x41, 0x2C, 0x34), RGB(0x41, 0x2C, 0x30), + RGB(0x41, 0x2C, 0x2C), RGB(0x41, 0x30, 0x2C), RGB(0x41, 0x34, 0x2C), RGB(0x41, 0x3C, 0x2C), + RGB(0x41, 0x41, 0x2C), RGB(0x3C, 0x41, 0x2C), RGB(0x34, 0x41, 0x2C), RGB(0x30, 0x41, 0x2C), + RGB(0x2C, 0x41, 0x2C), RGB(0x2C, 0x41, 0x30), RGB(0x2C, 0x41, 0x34), RGB(0x2C, 0x41, 0x3C), + RGB(0x2C, 0x41, 0x41), RGB(0x2C, 0x3C, 0x41), RGB(0x2C, 0x34, 0x41), RGB(0x2C, 0x30, 0x41), + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00) +}; + +#endif + +/* + * Console interface -- VGA-mode-agnostic + */ +typedef struct _CHAR_CELL +{ + CHAR Char; + BYTE Attributes; +} CHAR_CELL, *PCHAR_CELL; +C_ASSERT(sizeof(CHAR_CELL) == 2); + +static LPVOID ConsoleFramebuffer = NULL; // Active framebuffer, points to + // either TextFramebuffer or a valid + // graphics framebuffer. +static HPALETTE PaletteHandle = NULL; + +static HANDLE StartEvent = NULL; +static HANDLE EndEvent = NULL; +static HANDLE AnotherEvent = NULL; + +static CONSOLE_CURSOR_INFO OrgConsoleCursorInfo; +static CONSOLE_SCREEN_BUFFER_INFO OrgConsoleBufferInfo; + + +/* + * Text mode -- we always keep a valid text mode framebuffer + * even if we are in graphics mode. This is needed in order to + * keep a consistent VGA state. + */ +static CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo; +static COORD TextResolution = {0}; +static PCHAR_CELL TextFramebuffer = NULL; +static HANDLE TextConsoleBuffer = NULL; + +/* Graphics mode */ +static HANDLE GraphicsConsoleBuffer = NULL; +static HANDLE ConsoleMutex = NULL; +static BOOLEAN DoubleVision = FALSE; + +/* + * VGA Hardware + */ +static BYTE VgaMemory[VGA_NUM_BANKS * VGA_BANK_SIZE]; + +static BYTE VgaLatchRegisters[VGA_NUM_BANKS] = {0, 0, 0, 0}; + +static BYTE VgaMiscRegister; +static BYTE VgaFeatureRegister; + +static BYTE VgaSeqIndex = VGA_SEQ_RESET_REG; +static BYTE VgaSeqRegisters[VGA_SEQ_MAX_REG]; + +static BYTE VgaCrtcIndex = VGA_CRTC_HORZ_TOTAL_REG; +static BYTE VgaCrtcRegisters[VGA_CRTC_MAX_REG]; + +static BYTE VgaGcIndex = VGA_GC_RESET_REG; +static BYTE VgaGcRegisters[VGA_GC_MAX_REG]; + +static BOOLEAN VgaAcLatch = FALSE; +static BOOLEAN VgaAcPalDisable = TRUE; +static BYTE VgaAcIndex = VGA_AC_PAL_0_REG; +static BYTE VgaAcRegisters[VGA_AC_MAX_REG]; + +// static VGA_REGISTERS VgaRegisters; + +static BYTE VgaDacMask = 0xFF; +static WORD VgaDacIndex = 0; +static BOOLEAN VgaDacReadWrite = FALSE; +static BYTE VgaDacRegisters[VGA_PALETTE_SIZE]; + +static BOOLEAN InVerticalRetrace = FALSE; +static BOOLEAN InHorizontalRetrace = FALSE; + +static BOOLEAN NeedsUpdate = FALSE; +static BOOLEAN ModeChanged = FALSE; +static BOOLEAN CursorMoved = FALSE; +static BOOLEAN PaletteChanged = FALSE; + +static +enum SCREEN_MODE +{ + TEXT_MODE, + GRAPHICS_MODE +} ScreenMode = TEXT_MODE; + +static SMALL_RECT UpdateRectangle = { 0, 0, 0, 0 }; + +/* RegisterConsoleVDM EMULATION ***********************************************/ + +#include + +typedef +BOOL +(WINAPI *pRegisterConsoleVDM) +( + BOOL IsDosVDM_flag, + HANDLE EventHandle_1, + HANDLE EventHandle_2, + HANDLE EventHandle_3, + int Unused1, + PVOID returned_val_1, + PVOID *returned_val_2, + PVOID lpUnknownBuffer, + DWORD theUnknownBufferLength, + COORD theVDMBufferSize, + PCHAR *lpVDMBuffer +); + +#if 0 +BOOL +WINAPI +RegisterConsoleVDM +( + BOOL IsDosVDM_flag, + HANDLE EventHandle_1, + HANDLE EventHandle_2, + HANDLE EventHandle_3, + int Unused1, + PVOID returned_val_1, + PVOID *returned_val_2, + PVOID lpUnknownBuffer, + DWORD theUnknownBufferLength, + COORD theVDMBufferSize, + PVOID *lpVDMBuffer +); + +HMODULE hKernel32 = NULL; +pRegisterConsoleVDM RegisterConsoleVDM = NULL; +#endif + +/* + * This private buffer, per-console, is used by + * RegisterConsoleVDM and InvalidateConsoleDIBits. + */ +static COORD VDMBufferSize = {0}; +static PCHAR_CELL VDMBuffer = NULL; + +static PCHAR_INFO CharBuff = NULL; // This is a hack, which is unneeded + // for the real RegisterConsoleVDM and + // InvalidateConsoleDIBits + +BOOL +WINAPI +__RegisterConsoleVDM(BOOL IsDosVDM_flag, + HANDLE EventHandle_1, + HANDLE EventHandle_2, + HANDLE EventHandle_3, + int Unused1, + PVOID returned_val_1, + PVOID *returned_val_2, + PVOID lpUnknownBuffer, + DWORD theUnknownBufferLength, + COORD theVDMBufferSize, + PCHAR *lpVDMBuffer) +{ + UNREFERENCED_PARAMETER(EventHandle_3); + UNREFERENCED_PARAMETER(Unused1); + UNREFERENCED_PARAMETER(returned_val_1); + UNREFERENCED_PARAMETER(returned_val_2); + UNREFERENCED_PARAMETER(lpUnknownBuffer); + UNREFERENCED_PARAMETER(theUnknownBufferLength); + + SetLastError(0); + DPRINT1("__RegisterConsoleVDM(%d)\n", IsDosVDM_flag); + + if (lpVDMBuffer == NULL) return FALSE; + + if (IsDosVDM_flag) + { + // if (EventHandle_1 == NULL || EventHandle_2 == NULL) return FALSE; + if (VDMBuffer != NULL) return FALSE; + + VDMBufferSize = theVDMBufferSize; + + /* HACK: Cache -- to be removed in the real implementation */ + CharBuff = HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + theVDMBufferSize.X * theVDMBufferSize.Y + * sizeof(CHAR_INFO)); + ASSERT(CharBuff); + + VDMBuffer = HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + theVDMBufferSize.X * theVDMBufferSize.Y + * sizeof(CHAR_CELL)); + *lpVDMBuffer = (PCHAR)VDMBuffer; + return (VDMBuffer != NULL); + } + else + { + /* HACK: Cache -- to be removed in the real implementation */ + if (CharBuff) HeapFree(GetProcessHeap(), 0, CharBuff); + CharBuff = NULL; + + if (VDMBuffer) HeapFree(GetProcessHeap(), 0, VDMBuffer); + VDMBuffer = NULL; + + VDMBufferSize.X = VDMBufferSize.Y = 0; + + return TRUE; + } +} + +BOOL +__InvalidateConsoleDIBits(IN HANDLE hConsoleOutput, + IN PSMALL_RECT lpRect) +{ + if ((hConsoleOutput == TextConsoleBuffer) && (VDMBuffer != NULL)) + { + /* HACK: Write the cached data to the console */ + + COORD Origin = { lpRect->Left, lpRect->Top }; + SHORT i, j; + + ASSERT(CharBuff); + + for (i = 0; i < VDMBufferSize.Y; i++) + { + for (j = 0; j < VDMBufferSize.X; j++) + { + CharBuff[i * VDMBufferSize.X + j].Char.AsciiChar = VDMBuffer[i * VDMBufferSize.X + j].Char; + CharBuff[i * VDMBufferSize.X + j].Attributes = VDMBuffer[i * VDMBufferSize.X + j].Attributes; + } + } + + WriteConsoleOutputA(hConsoleOutput, + CharBuff, + VDMBufferSize, + Origin, + lpRect); + } + + return InvalidateConsoleDIBits(hConsoleOutput, lpRect); +} + +/* PRIVATE FUNCTIONS **********************************************************/ + +static inline DWORD VgaGetAddressSize(VOID); +static VOID VgaUpdateTextCursor(VOID); + +static VOID VgaUpdateCursorPosition(VOID) +{ + /* + * Update the cursor position in the VGA registers. + */ + WORD Offset = ConsoleInfo.dwCursorPosition.Y * TextResolution.X + + ConsoleInfo.dwCursorPosition.X; + + VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_LOW_REG] = LOBYTE(Offset); + VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_HIGH_REG] = HIBYTE(Offset); + + // VidBiosSyncCursorPosition(); + VgaUpdateTextCursor(); +} + +static BOOL VgaAttachToConsoleInternal(PCOORD Resolution) +{ + BOOL Success; + ULONG Length = 0; + PVIDEO_HARDWARE_STATE_HEADER State; + + SHORT i, j; + DWORD AddressSize, ScanlineSize; + DWORD Address = 0; + DWORD CurrentAddr; + SMALL_RECT ConRect; + COORD Origin = { 0, 0 }; + + ASSERT(TextFramebuffer == NULL); + + TextResolution = *Resolution; + + /* + * Windows 2k3 winsrv.dll calls NtVdmControl(VdmQueryVdmProcess == 14, &ConsoleHandle); + * in the two following APIs: + * SrvRegisterConsoleVDM (corresponding win32 API: RegisterConsoleVDM) + * SrvVDMConsoleOperation (corresponding Win32 API: ) + * to check whether the current process is a VDM process, and fails otherwise with the + * error 0xC0000022 (). + * + * It is worth it to notice that also basesrv.dll does the same only for the + * BaseSrvIsFirstVDM API... + */ + + Success = + __RegisterConsoleVDM(1, + StartEvent, + EndEvent, + AnotherEvent, // NULL, + 0, + &Length, // NULL, <-- putting this (and null in the next var) makes the API returning error 12 "ERROR_INVALID_ACCESS" + (PVOID*)&State, // NULL, + NULL, + 0, + TextResolution, + (PCHAR*)&TextFramebuffer); + if (!Success) + { + DisplayMessage(L"RegisterConsoleVDM failed with error %d\n", GetLastError()); + EmulatorTerminate(); + return FALSE; + } + + /* + * Resize the console + */ + ConRect.Left = 0; + ConRect.Top = ConsoleInfo.srWindow.Top; + ConRect.Right = ConRect.Left + Resolution->X - 1; + ConRect.Bottom = ConRect.Top + Resolution->Y - 1; + /* + * Use this trick to effectively resize the console buffer and window, + * because: + * - SetConsoleScreenBufferSize fails if the new console screen buffer size + * is smaller than the current console window size, and: + * - SetConsoleWindowInfo fails if the new console window size is larger + * than the current console screen buffer size. + */ + SetConsoleScreenBufferSize(TextConsoleBuffer, *Resolution); + SetConsoleWindowInfo(TextConsoleBuffer, TRUE, &ConRect); + SetConsoleScreenBufferSize(TextConsoleBuffer, *Resolution); + /* Update the saved console information */ + GetConsoleScreenBufferInfo(TextConsoleBuffer, &ConsoleInfo); + + /* + * Copy console data into VGA memory + */ + + /* Get the data */ + AddressSize = VgaGetAddressSize(); + ConRect.Left = ConRect.Top = 0; + ConRect.Right = TextResolution.X; + ConRect.Bottom = TextResolution.Y; + ScanlineSize = (DWORD)VgaCrtcRegisters[VGA_CRTC_OFFSET_REG] * 2; + + /* Read the data from the console into the framebuffer... */ + ReadConsoleOutputA(TextConsoleBuffer, + CharBuff, + TextResolution, + Origin, + &ConRect); + + /* ... and copy the framebuffer into the VGA memory */ + + /* Loop through the scanlines */ + for (i = 0; i < TextResolution.Y; i++) + { + /* Loop through the characters */ + for (j = 0; j < TextResolution.X; j++) + { + CurrentAddr = LOWORD((Address + j) * AddressSize); + + /* Store the character in plane 0 */ + VgaMemory[CurrentAddr] = CharBuff[i * TextResolution.X + j].Char.AsciiChar; + + /* Store the attribute in plane 1 */ + VgaMemory[CurrentAddr + VGA_BANK_SIZE] = (BYTE)CharBuff[i * TextResolution.X + j].Attributes; + } + + /* Move to the next scanline */ + Address += ScanlineSize; + } + + VgaUpdateCursorPosition(); + + return TRUE; +} + +static BOOL IsConsoleHandle(HANDLE hHandle) +{ + DWORD dwMode; + + /* Check whether the handle may be that of a console... */ + if ((GetFileType(hHandle) & ~FILE_TYPE_REMOTE) != FILE_TYPE_CHAR) + return FALSE; + + /* + * It may be. Perform another test... The idea comes from the + * MSDN description of the WriteConsole API: + * + * "WriteConsole fails if it is used with a standard handle + * that is redirected to a file. If an application processes + * multilingual output that can be redirected, determine whether + * the output handle is a console handle (one method is to call + * the GetConsoleMode function and check whether it succeeds). + * If the handle is a console handle, call WriteConsole. If the + * handle is not a console handle, the output is redirected and + * you should call WriteFile to perform the I/O." + */ + return GetConsoleMode(hHandle, &dwMode); +} + +static inline DWORD VgaGetAddressSize(VOID) +{ + if (VgaCrtcRegisters[VGA_CRTC_UNDERLINE_REG] & VGA_CRTC_UNDERLINE_DWORD) + { + /* Double-word addressing */ + return 4; // sizeof(DWORD) + } + else if (VgaCrtcRegisters[VGA_CRTC_MODE_CONTROL_REG] & VGA_CRTC_MODE_CONTROL_BYTE) + { + /* Byte addressing */ + return 1; // sizeof(BYTE) + } + else + { + /* Word addressing */ + return 2; // sizeof(WORD) + } +} + +static inline DWORD VgaTranslateReadAddress(DWORD Address) +{ + DWORD Offset = Address - VgaGetVideoBaseAddress(); + BYTE Plane; + + /* Check for chain-4 and odd-even mode */ + if (VgaSeqRegisters[VGA_SEQ_MEM_REG] & VGA_SEQ_MEM_C4) + { + /* The lowest two bits are the plane number */ + Plane = Offset & 3; + Offset >>= 2; + } + else if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_OE) + { + /* The LSB is the plane number */ + Plane = Offset & 1; + Offset >>= 1; + } + else + { + /* Use the read mode */ + Plane = VgaGcRegisters[VGA_GC_READ_MAP_SEL_REG] & 0x03; + } + + /* Multiply the offset by the address size */ + Offset *= VgaGetAddressSize(); + + return Offset + Plane * VGA_BANK_SIZE; +} + +static inline DWORD VgaTranslateWriteAddress(DWORD Address) +{ + DWORD Offset = Address - VgaGetVideoBaseAddress(); + + /* Check for chain-4 and odd-even mode */ + if (VgaSeqRegisters[VGA_SEQ_MEM_REG] & VGA_SEQ_MEM_C4) + { + /* Shift the offset to the right by 2 */ + Offset >>= 2; + } + else if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_OE) + { + /* Shift the offset to the right by 1 */ + Offset >>= 1; + } + + /* Multiply the offset by the address size */ + Offset *= VgaGetAddressSize(); + + /* Return the offset on plane 0 */ + return Offset; +} + +static inline BYTE VgaTranslateByteForWriting(BYTE Data, BYTE Plane) +{ + BYTE WriteMode = VgaGcRegisters[VGA_GC_MODE_REG] & 3; + BYTE BitMask = VgaGcRegisters[VGA_GC_BITMASK_REG]; + + if (WriteMode == 1) + { + /* In write mode 1 just return the latch register */ + return VgaLatchRegisters[Plane]; + } + + if (WriteMode != 2) + { + /* Write modes 0 and 3 rotate the data to the right first */ + BYTE RotateCount = VgaGcRegisters[VGA_GC_ROTATE_REG] & 7; + Data = LOBYTE(((DWORD)Data >> RotateCount) | ((DWORD)Data << (8 - RotateCount))); + } + else + { + /* Write mode 2 expands the appropriate bit to all 8 bits */ + Data = (Data & (1 << Plane)) ? 0xFF : 0x00; + } + + if (WriteMode == 0) + { + /* + * In write mode 0, the enable set/reset register decides if the + * set/reset bit should be expanded to all 8 bits. + */ + if (VgaGcRegisters[VGA_GC_ENABLE_RESET_REG] & (1 << Plane)) + { + /* Copy the bit from the set/reset register to all 8 bits */ + Data = (VgaGcRegisters[VGA_GC_RESET_REG] & (1 << Plane)) ? 0xFF : 0x00; + } + } + + if (WriteMode != 3) + { + /* Write modes 0 and 2 then perform a logical operation on the data and latch */ + BYTE LogicalOperation = (VgaGcRegisters[VGA_GC_ROTATE_REG] >> 3) & 3; + + if (LogicalOperation == 1) Data &= VgaLatchRegisters[Plane]; + else if (LogicalOperation == 2) Data |= VgaLatchRegisters[Plane]; + else if (LogicalOperation == 3) Data ^= VgaLatchRegisters[Plane]; + } + else + { + /* For write mode 3, we AND the bitmask with the data, which is used as the new bitmask */ + BitMask &= Data; + + /* Then we expand the bit in the set/reset field */ + Data = (VgaGcRegisters[VGA_GC_RESET_REG] & (1 << Plane)) ? 0xFF : 0x00; + } + + /* Bits cleared in the bitmask are replaced with latch register bits */ + Data = (Data & BitMask) | (VgaLatchRegisters[Plane] & (~BitMask)); + + /* Return the byte */ + return Data; +} + +static inline VOID VgaMarkForUpdate(SHORT Row, SHORT Column) +{ + /* Check if this is the first time the rectangle is updated */ + if (!NeedsUpdate) + { + UpdateRectangle.Left = UpdateRectangle.Top = MAXSHORT; + UpdateRectangle.Right = UpdateRectangle.Bottom = MINSHORT; + } + + /* Expand the rectangle to include the point */ + UpdateRectangle.Left = min(UpdateRectangle.Left, Column); + UpdateRectangle.Right = max(UpdateRectangle.Right, Column); + UpdateRectangle.Top = min(UpdateRectangle.Top, Row); + UpdateRectangle.Bottom = max(UpdateRectangle.Bottom, Row); + + /* Set the update request flag */ + NeedsUpdate = TRUE; +} + +static VOID VgaWriteSequencer(BYTE Data) +{ + ASSERT(VgaSeqIndex < VGA_SEQ_MAX_REG); + + /* Save the value */ + VgaSeqRegisters[VgaSeqIndex] = Data; +} + +static VOID VgaWriteGc(BYTE Data) +{ + ASSERT(VgaGcIndex < VGA_GC_MAX_REG); + + /* Save the value */ + VgaGcRegisters[VgaGcIndex] = Data; + + /* Check the index */ + switch (VgaGcIndex) + { + case VGA_GC_MISC_REG: + { + /* The GC misc register decides if it's text or graphics mode */ + ModeChanged = TRUE; + break; + } + } +} + +static VOID VgaWriteCrtc(BYTE Data) +{ + ASSERT(VgaGcIndex < VGA_CRTC_MAX_REG); + + /* Save the value */ + VgaCrtcRegisters[VgaCrtcIndex] = Data; + + /* Check the index */ + switch (VgaCrtcIndex) + { + case VGA_CRTC_END_HORZ_DISP_REG: + case VGA_CRTC_VERT_DISP_END_REG: + case VGA_CRTC_OVERFLOW_REG: + { + /* The video mode has changed */ + ModeChanged = TRUE; + break; + } + + case VGA_CRTC_CURSOR_LOC_LOW_REG: + case VGA_CRTC_CURSOR_LOC_HIGH_REG: + case VGA_CRTC_CURSOR_START_REG: + case VGA_CRTC_CURSOR_END_REG: + { + /* Set the cursor moved flag */ + CursorMoved = TRUE; + break; + } + } +} + +static VOID VgaWriteDac(BYTE Data) +{ + INT PaletteIndex; + PALETTEENTRY Entry; + + /* Set the value */ + VgaDacRegisters[VgaDacIndex] = Data; + + /* Find the palette index */ + PaletteIndex = VgaDacIndex / 3; + + /* Fill the entry structure */ + Entry.peRed = VGA_DAC_TO_COLOR(VgaDacRegisters[PaletteIndex * 3]); + Entry.peGreen = VGA_DAC_TO_COLOR(VgaDacRegisters[PaletteIndex * 3 + 1]); + Entry.peBlue = VGA_DAC_TO_COLOR(VgaDacRegisters[PaletteIndex * 3 + 2]); + Entry.peFlags = 0; + + /* Update the palette entry and set the palette change flag */ + SetPaletteEntries(PaletteHandle, PaletteIndex, 1, &Entry); + PaletteChanged = TRUE; + + /* Update the index */ + VgaDacIndex++; + VgaDacIndex %= VGA_PALETTE_SIZE; +} + +static VOID VgaWriteAc(BYTE Data) +{ + ASSERT(VgaAcIndex < VGA_AC_MAX_REG); + + /* Save the value */ + if (VgaAcIndex <= VGA_AC_PAL_F_REG) + { + if (VgaAcPalDisable) return; + + // DbgPrint(" AC Palette Writing %d to index %d\n", Data, VgaAcIndex); + if (VgaAcRegisters[VgaAcIndex] != Data) + { + /* Update the AC register and set the palette change flag */ + VgaAcRegisters[VgaAcIndex] = Data; + PaletteChanged = TRUE; + } + } + else + { + VgaAcRegisters[VgaAcIndex] = Data; + } +} + +static VOID VgaRestoreDefaultPalette(PPALETTEENTRY Entries, USHORT NumOfEntries) +{ + USHORT i; + + /* Copy the colors of the default palette to the DAC and console palette */ + for (i = 0; i < NumOfEntries; i++) + { + /* Set the palette entries */ + Entries[i].peRed = GetRValue(VgaDefaultPalette[i]); + Entries[i].peGreen = GetGValue(VgaDefaultPalette[i]); + Entries[i].peBlue = GetBValue(VgaDefaultPalette[i]); + Entries[i].peFlags = 0; + + /* Set the DAC registers */ + VgaDacRegisters[i * 3] = VGA_COLOR_TO_DAC(GetRValue(VgaDefaultPalette[i])); + VgaDacRegisters[i * 3 + 1] = VGA_COLOR_TO_DAC(GetGValue(VgaDefaultPalette[i])); + VgaDacRegisters[i * 3 + 2] = VGA_COLOR_TO_DAC(GetBValue(VgaDefaultPalette[i])); + } +} + +static BOOLEAN VgaInitializePalette(VOID) +{ + LPLOGPALETTE Palette; + + /* Allocate storage space for the palette */ + Palette = (LPLOGPALETTE)HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(LOGPALETTE) + + VGA_MAX_COLORS * sizeof(PALETTEENTRY)); + if (Palette == NULL) return FALSE; + + /* Initialize the palette */ + Palette->palVersion = 0x0300; + Palette->palNumEntries = VGA_MAX_COLORS; + + /* Restore the default palette */ + VgaRestoreDefaultPalette(Palette->palPalEntry, Palette->palNumEntries); + + /* Create the palette */ + PaletteHandle = CreatePalette(Palette); + + /* Free the palette */ + HeapFree(GetProcessHeap(), 0, Palette); + + /* Fail if the palette wasn't successfully created... */ + if (PaletteHandle == NULL) return FALSE; + + /* ... otherwise return success */ + return TRUE; +} + +static BOOL VgaEnterGraphicsMode(PCOORD Resolution) +{ + DWORD i; + CONSOLE_GRAPHICS_BUFFER_INFO GraphicsBufferInfo; + BYTE BitmapInfoBuffer[VGA_BITMAP_INFO_SIZE]; + LPBITMAPINFO BitmapInfo = (LPBITMAPINFO)BitmapInfoBuffer; + LPWORD PaletteIndex = (LPWORD)(BitmapInfo->bmiColors); + + LONG Width = Resolution->X; + LONG Height = Resolution->Y; + + /* Use DoubleVision mode if the resolution is too small */ + if (Width < VGA_MINIMUM_WIDTH && Height < VGA_MINIMUM_HEIGHT) + { + DoubleVision = TRUE; + Width *= 2; + Height *= 2; + } + else + { + DoubleVision = FALSE; + } + + /* Fill the bitmap info header */ + ZeroMemory(&BitmapInfo->bmiHeader, sizeof(BITMAPINFOHEADER)); + BitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + BitmapInfo->bmiHeader.biWidth = Width; + BitmapInfo->bmiHeader.biHeight = Height; + BitmapInfo->bmiHeader.biBitCount = 8; + BitmapInfo->bmiHeader.biPlanes = 1; + BitmapInfo->bmiHeader.biCompression = BI_RGB; + BitmapInfo->bmiHeader.biSizeImage = Width * Height /* * 1 == biBitCount / 8 */; + + /* Fill the palette data */ + for (i = 0; i < (VGA_PALETTE_SIZE / 3); i++) PaletteIndex[i] = (WORD)i; + + /* Fill the console graphics buffer info */ + GraphicsBufferInfo.dwBitMapInfoLength = VGA_BITMAP_INFO_SIZE; + GraphicsBufferInfo.lpBitMapInfo = BitmapInfo; + GraphicsBufferInfo.dwUsage = DIB_PAL_COLORS; + + /* Create the buffer */ + GraphicsConsoleBuffer = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + CONSOLE_GRAPHICS_BUFFER, + &GraphicsBufferInfo); + if (GraphicsConsoleBuffer == INVALID_HANDLE_VALUE) return FALSE; + + /* Save the framebuffer address and mutex */ + ConsoleFramebuffer = GraphicsBufferInfo.lpBitMap; + ConsoleMutex = GraphicsBufferInfo.hMutex; + + /* Clear the framebuffer */ + ZeroMemory(ConsoleFramebuffer, BitmapInfo->bmiHeader.biSizeImage); + + /* Set the active buffer */ + SetConsoleActiveScreenBuffer(GraphicsConsoleBuffer); + + /* Set the graphics mode palette */ + SetConsolePalette(GraphicsConsoleBuffer, + PaletteHandle, + SYSPAL_NOSTATIC256); + + /* Set the screen mode flag */ + ScreenMode = GRAPHICS_MODE; + + return TRUE; +} + +static VOID VgaLeaveGraphicsMode(VOID) +{ + /* Release the console framebuffer mutex */ + ReleaseMutex(ConsoleMutex); + + /* Switch back to the default console text buffer */ + // SetConsoleActiveScreenBuffer(TextConsoleBuffer); + + /* Cleanup the video data */ + CloseHandle(ConsoleMutex); + ConsoleMutex = NULL; + ConsoleFramebuffer = NULL; + CloseHandle(GraphicsConsoleBuffer); + GraphicsConsoleBuffer = NULL; + DoubleVision = FALSE; +} + +static BOOL VgaEnterTextMode(PCOORD Resolution) +{ + DPRINT1("VgaEnterTextMode\n"); + + /* Switch to the text buffer */ + SetConsoleActiveScreenBuffer(TextConsoleBuffer); + + /* Adjust the text framebuffer if we changed the resolution */ + if (TextResolution.X != Resolution->X || + TextResolution.Y != Resolution->Y) + { + VgaDetachFromConsole(TRUE); + + /* + * VgaAttachToConsoleInternal sets TextResolution to the + * new resolution and updates ConsoleInfo. + */ + if (!VgaAttachToConsoleInternal(Resolution)) + { + DisplayMessage(L"An unexpected error occurred!\n"); + EmulatorTerminate(); + return FALSE; + } + } + else + { + VgaUpdateCursorPosition(); + } + + /* The active framebuffer is now the text framebuffer */ + ConsoleFramebuffer = TextFramebuffer; + + /* + * Set the text mode palette. + * + * WARNING: This call should fail on Windows (and therefore + * we get the default palette and our external behaviour is + * just like Windows' one), but it should success on ReactOS + * (so that we get console palette changes even for text-mode + * screen-buffers, which is a new feature on ReactOS). + */ + SetConsolePalette(TextConsoleBuffer, + PaletteHandle, + SYSPAL_NOSTATIC256); + + /* Set the screen mode flag */ + ScreenMode = TEXT_MODE; + + return TRUE; +} + +static VOID VgaLeaveTextMode(VOID) +{ + /* Reset the active framebuffer */ + ConsoleFramebuffer = NULL; +} + +static VOID VgaChangeMode(VOID) +{ + COORD Resolution = VgaGetDisplayResolution(); + + if (ScreenMode == GRAPHICS_MODE) + { + /* Leave the current graphics mode */ + VgaLeaveGraphicsMode(); + } + else + { + /* Leave the current text mode */ + VgaLeaveTextMode(); + } + + /* Check if the new mode is alphanumeric */ + if (!(VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA)) + { + /* Enter new text mode */ + if (!VgaEnterTextMode(&Resolution)) + { + DisplayMessage(L"An unexpected VGA error occurred while switching into text mode."); + EmulatorTerminate(); + return; + } + } + else + { + /* Enter graphics mode */ + if (!VgaEnterGraphicsMode(&Resolution)) + { + DisplayMessage(L"An unexpected VGA error occurred while switching into graphics mode."); + EmulatorTerminate(); + return; + } + } + + /* Trigger a full update of the screen */ + NeedsUpdate = TRUE; + UpdateRectangle.Left = 0; + UpdateRectangle.Top = 0; + UpdateRectangle.Right = Resolution.X; + UpdateRectangle.Bottom = Resolution.Y; + + /* Reset the mode change flag */ + ModeChanged = FALSE; +} + +static VOID VgaUpdateFramebuffer(VOID) +{ + SHORT i, j, k; + COORD Resolution = VgaGetDisplayResolution(); + DWORD AddressSize = VgaGetAddressSize(); + DWORD Address = MAKEWORD(VgaCrtcRegisters[VGA_CRTC_START_ADDR_LOW_REG], + VgaCrtcRegisters[VGA_CRTC_START_ADDR_HIGH_REG]); + DWORD ScanlineSize = (DWORD)VgaCrtcRegisters[VGA_CRTC_OFFSET_REG] * 2; + + /* + * If console framebuffer is NULL, that means something went wrong + * earlier and this is the final display refresh. + */ + if (ConsoleFramebuffer == NULL) return; + + /* Check if this is text mode or graphics mode */ + if (VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA) + { + /* Graphics mode */ + PBYTE GraphicsBuffer = (PBYTE)ConsoleFramebuffer; + DWORD InterlaceHighBit = VGA_INTERLACE_HIGH_BIT; + + /* + * Synchronize access to the graphics framebuffer + * with the console framebuffer mutex. + */ + WaitForSingleObject(ConsoleMutex, INFINITE); + + /* Shift the high bit right by 1 in odd/even mode */ + if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_OE) + { + InterlaceHighBit >>= 1; + } + + /* Loop through the scanlines */ + for (i = 0; i < Resolution.Y; i++) + { + if ((VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_OE) && (i & 1)) + { + /* Odd-numbered line in interlaced mode - set the high bit */ + Address |= InterlaceHighBit; + } + + /* Loop through the pixels */ + for (j = 0; j < Resolution.X; j++) + { + BYTE PixelData = 0; + + /* Check the shifting mode */ + if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_SHIFT256) + { + /* 4 bits shifted from each plane */ + + /* Check if this is 16 or 256 color mode */ + if (VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT) + { + /* One byte per pixel */ + PixelData = VgaMemory[(j % VGA_NUM_BANKS) * VGA_BANK_SIZE + + (Address + (j / VGA_NUM_BANKS)) + * AddressSize]; + } + else + { + /* 4-bits per pixel */ + + PixelData = VgaMemory[(j % VGA_NUM_BANKS) * VGA_BANK_SIZE + + (Address + (j / (VGA_NUM_BANKS * 2))) + * AddressSize]; + + /* Check if we should use the highest 4 bits or lowest 4 */ + if (((j / VGA_NUM_BANKS) % 2) == 0) + { + /* Highest 4 */ + PixelData >>= 4; + } + else + { + /* Lowest 4 */ + PixelData &= 0x0F; + } + } + } + else if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_SHIFTREG) + { + /* Check if this is 16 or 256 color mode */ + if (VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT) + { + // TODO: NOT IMPLEMENTED + DPRINT1("8-bit interleaved mode is not implemented!\n"); + } + else + { + /* + * 2 bits shifted from plane 0 and 2 for the first 4 pixels, + * then 2 bits shifted from plane 1 and 3 for the next 4 + */ + DWORD BankNumber = (j / 4) % 2; + DWORD Offset = Address + (j / 8); + BYTE LowPlaneData = VgaMemory[BankNumber * VGA_BANK_SIZE + Offset * AddressSize]; + BYTE HighPlaneData = VgaMemory[(BankNumber + 2) * VGA_BANK_SIZE + Offset * AddressSize]; + + /* Extract the two bits from each plane */ + LowPlaneData = (LowPlaneData >> (6 - ((j % 4) * 2))) & 3; + HighPlaneData = (HighPlaneData >> (6 - ((j % 4) * 2))) & 3; + + /* Combine them into the pixel */ + PixelData = LowPlaneData | (HighPlaneData << 2); + } + } + else + { + /* 1 bit shifted from each plane */ + + /* Check if this is 16 or 256 color mode */ + if (VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT) + { + /* 8 bits per pixel, 2 on each plane */ + + for (k = 0; k < VGA_NUM_BANKS; k++) + { + /* The data is on plane k, 4 pixels per byte */ + BYTE PlaneData = VgaMemory[k * VGA_BANK_SIZE + + (Address + (j / VGA_NUM_BANKS)) + * AddressSize]; + + /* The mask of the first bit in the pair */ + BYTE BitMask = 1 << (((3 - (j % VGA_NUM_BANKS)) * 2) + 1); + + /* Bits 0, 1, 2 and 3 come from the first bit of the pair */ + if (PlaneData & BitMask) PixelData |= 1 << k; + + /* Bits 4, 5, 6 and 7 come from the second bit of the pair */ + if (PlaneData & (BitMask >> 1)) PixelData |= 1 << (k + 4); + } + } + else + { + /* 4 bits per pixel, 1 on each plane */ + + for (k = 0; k < VGA_NUM_BANKS; k++) + { + BYTE PlaneData = VgaMemory[k * VGA_BANK_SIZE + + (Address + (j / (VGA_NUM_BANKS * 2))) + * AddressSize]; + + /* If the bit on that plane is set, set it */ + if (PlaneData & (1 << (7 - (j % 8)))) PixelData |= 1 << k; + } + } + } + + if (!(VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT)) + { + /* + * In 16 color mode, the value is an index to the AC registers + * if external palette access is disabled, otherwise (in case + * of palette loading) it is a blank pixel. + */ + PixelData = (VgaAcPalDisable ? VgaAcRegisters[PixelData & 0x0F] + : 0); + } + + /* Take into account DoubleVision mode when checking for pixel updates */ + if (DoubleVision) + { + /* Now check if the resulting pixel data has changed */ + if (GraphicsBuffer[(i * Resolution.X * 4) + (j * 2)] != PixelData) + { + /* Yes, write the new value */ + GraphicsBuffer[(i * Resolution.X * 4) + (j * 2)] = PixelData; + GraphicsBuffer[(i * Resolution.X * 4) + (j * 2 + 1)] = PixelData; + GraphicsBuffer[((i * 2 + 1) * Resolution.X * 2) + (j * 2)] = PixelData; + GraphicsBuffer[((i * 2 + 1) * Resolution.X * 2) + (j * 2 + 1)] = PixelData; + + /* Mark the specified pixel as changed */ + VgaMarkForUpdate(i, j); + } + } + else + { + /* Now check if the resulting pixel data has changed */ + if (GraphicsBuffer[i * Resolution.X + j] != PixelData) + { + /* Yes, write the new value */ + GraphicsBuffer[i * Resolution.X + j] = PixelData; + + /* Mark the specified pixel as changed */ + VgaMarkForUpdate(i, j); + } + } + } + + if ((VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_OE) && (i & 1)) + { + /* Clear the high bit */ + Address &= ~InterlaceHighBit; + } + + if (!(VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_OE) || (i & 1)) + { + /* Move to the next scanline */ + Address += ScanlineSize; + } + } + + /* + * Release the console framebuffer mutex + * so that we allow for repainting. + */ + ReleaseMutex(ConsoleMutex); + } + else + { + /* Text mode */ + DWORD CurrentAddr; + PCHAR_CELL CharBuffer = (PCHAR_CELL)ConsoleFramebuffer; + CHAR_CELL CharInfo; + + /* Loop through the scanlines */ + for (i = 0; i < Resolution.Y; i++) + { + /* Loop through the characters */ + for (j = 0; j < Resolution.X; j++) + { + CurrentAddr = LOWORD((Address + j) * AddressSize); + + /* Plane 0 holds the character itself */ + CharInfo.Char = VgaMemory[CurrentAddr]; + + /* Plane 1 holds the attribute */ + CharInfo.Attributes = VgaMemory[CurrentAddr + VGA_BANK_SIZE]; + + /* Now check if the resulting character data has changed */ + if ((CharBuffer[i * Resolution.X + j].Char != CharInfo.Char) || + (CharBuffer[i * Resolution.X + j].Attributes != CharInfo.Attributes)) + { + /* Yes, write the new value */ + CharBuffer[i * Resolution.X + j] = CharInfo; + + /* Mark the specified cell as changed */ + VgaMarkForUpdate(i, j); + } + } + + /* Move to the next scanline */ + Address += ScanlineSize; + } + } +} + +static VOID VgaUpdateTextCursor(VOID) +{ + COORD Position; + CONSOLE_CURSOR_INFO CursorInfo; + BYTE CursorStart = VgaCrtcRegisters[VGA_CRTC_CURSOR_START_REG] & 0x3F; + BYTE CursorEnd = VgaCrtcRegisters[VGA_CRTC_CURSOR_END_REG] & 0x1F; + DWORD ScanlineSize = (DWORD)VgaCrtcRegisters[VGA_CRTC_OFFSET_REG] * 2; + BYTE TextSize = 1 + (VgaCrtcRegisters[VGA_CRTC_MAX_SCAN_LINE_REG] & 0x1F); + WORD Location = MAKEWORD(VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_LOW_REG], + VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_HIGH_REG]); + + /* Just return if we are not in text mode */ + if (VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA) return; + + if (CursorStart < CursorEnd) + { + /* Visible cursor */ + CursorInfo.bVisible = TRUE; + CursorInfo.dwSize = (100 * (CursorEnd - CursorStart)) / TextSize; + } + else + { + /* No cursor */ + CursorInfo.bVisible = FALSE; + CursorInfo.dwSize = 0; + } + + /* Add the cursor skew to the location */ + Location += (VgaCrtcRegisters[VGA_CRTC_CURSOR_END_REG] >> 5) & 3; + + /* Find the coordinates of the new position */ + Position.X = (SHORT)(Location % ScanlineSize); + Position.Y = (SHORT)(Location / ScanlineSize); + + DPRINT1("VgaUpdateTextCursor: X = %d ; Y = %d\n", Position.X, Position.Y); + + /* Update the physical cursor */ + SetConsoleCursorInfo(TextConsoleBuffer, &CursorInfo); + SetConsoleCursorPosition(TextConsoleBuffer, Position); + + /* Reset the cursor move flag */ + CursorMoved = FALSE; +} + +static BYTE WINAPI VgaReadPort(ULONG Port) +{ + DPRINT("VgaReadPort: Port 0x%X\n", Port); + + switch (Port) + { + case VGA_MISC_READ: + return VgaMiscRegister; + + case VGA_INSTAT0_READ: + return 0; // Not implemented + + case VGA_INSTAT1_READ_MONO: + case VGA_INSTAT1_READ_COLOR: + { + BYTE Result = 0; + + /* Reset the AC latch */ + VgaAcLatch = FALSE; + + /* Set a flag if there is a vertical or horizontal retrace */ + if (InVerticalRetrace || InHorizontalRetrace) Result |= VGA_STAT_DD; + + /* Set an additional flag if there was a vertical retrace */ + if (InVerticalRetrace) Result |= VGA_STAT_VRETRACE; + + /* Clear the flags */ + InHorizontalRetrace = InVerticalRetrace = FALSE; + + return Result; + } + + case VGA_FEATURE_READ: + return VgaFeatureRegister; + + case VGA_AC_INDEX: + return VgaAcIndex; + + case VGA_AC_READ: + return VgaAcRegisters[VgaAcIndex]; + + case VGA_SEQ_INDEX: + return VgaSeqIndex; + + case VGA_SEQ_DATA: + return VgaSeqRegisters[VgaSeqIndex]; + + case VGA_DAC_MASK: + return VgaDacMask; + + case VGA_DAC_READ_INDEX: + /* This returns the read/write state */ + return (VgaDacReadWrite ? 0 : 3); + + case VGA_DAC_WRITE_INDEX: + return (VgaDacIndex / 3); + + case VGA_DAC_DATA: + { + /* Ignore reads in write mode */ + if (!VgaDacReadWrite) + { + BYTE Data = VgaDacRegisters[VgaDacIndex++]; + VgaDacIndex %= VGA_PALETTE_SIZE; + return Data; + } + + break; + } + + case VGA_CRTC_INDEX_MONO: + case VGA_CRTC_INDEX_COLOR: + return VgaCrtcIndex; + + case VGA_CRTC_DATA_MONO: + case VGA_CRTC_DATA_COLOR: + return VgaCrtcRegisters[VgaCrtcIndex]; + + case VGA_GC_INDEX: + return VgaGcIndex; + + case VGA_GC_DATA: + return VgaGcRegisters[VgaGcIndex]; + + default: + DPRINT1("VgaReadPort: Unknown port 0x%X\n", Port); + break; + } + + return 0; +} + +static VOID WINAPI VgaWritePort(ULONG Port, BYTE Data) +{ + DPRINT("VgaWritePort: Port 0x%X, Data 0x%02X\n", Port, Data); + + switch (Port) + { + case VGA_MISC_WRITE: + { + VgaMiscRegister = Data; + + if (VgaMiscRegister & 0x01) + { + /* Color emulation */ + DPRINT1("Color emulation\n"); + + /* Register the new I/O Ports */ + RegisterIoPort(0x3D4, VgaReadPort, VgaWritePort); // VGA_CRTC_INDEX_COLOR + RegisterIoPort(0x3D5, VgaReadPort, VgaWritePort); // VGA_CRTC_DATA_COLOR + RegisterIoPort(0x3DA, VgaReadPort, VgaWritePort); // VGA_INSTAT1_READ_COLOR, VGA_FEATURE_WRITE_COLOR + + /* Unregister the old ones */ + UnregisterIoPort(0x3B4); // VGA_CRTC_INDEX_MONO + UnregisterIoPort(0x3B5); // VGA_CRTC_DATA_MONO + UnregisterIoPort(0x3BA); // VGA_INSTAT1_READ_MONO, VGA_FEATURE_WRITE_MONO + } + else + { + /* Monochrome emulation */ + DPRINT1("Monochrome emulation\n"); + + /* Register the new I/O Ports */ + RegisterIoPort(0x3B4, VgaReadPort, VgaWritePort); // VGA_CRTC_INDEX_MONO + RegisterIoPort(0x3B5, VgaReadPort, VgaWritePort); // VGA_CRTC_DATA_MONO + RegisterIoPort(0x3BA, VgaReadPort, VgaWritePort); // VGA_INSTAT1_READ_MONO, VGA_FEATURE_WRITE_MONO + + /* Unregister the old ones */ + UnregisterIoPort(0x3D4); // VGA_CRTC_INDEX_COLOR + UnregisterIoPort(0x3D5); // VGA_CRTC_DATA_COLOR + UnregisterIoPort(0x3DA); // VGA_INSTAT1_READ_COLOR, VGA_FEATURE_WRITE_COLOR + } + + // if (VgaMiscRegister & 0x02) { /* Enable RAM access */ } else { /* Disable RAM access */ } + break; + } + + case VGA_FEATURE_WRITE_MONO: + case VGA_FEATURE_WRITE_COLOR: + { + VgaFeatureRegister = Data; + break; + } + + case VGA_AC_INDEX: + // case VGA_AC_WRITE: + { + if (!VgaAcLatch) + { + /* Change the index */ + BYTE Index = Data & 0x1F; + if (Index < VGA_AC_MAX_REG) VgaAcIndex = Index; + + /* + * Change palette protection by checking for + * the Palette Address Source bit. + */ + VgaAcPalDisable = (Data & 0x20) ? TRUE : FALSE; + } + else + { + /* Write the data */ + VgaWriteAc(Data); + } + + /* Toggle the latch */ + VgaAcLatch = !VgaAcLatch; + break; + } + + case VGA_SEQ_INDEX: + { + /* Set the sequencer index register */ + if (Data < VGA_SEQ_MAX_REG) VgaSeqIndex = Data; + break; + } + + case VGA_SEQ_DATA: + { + /* Call the sequencer function */ + VgaWriteSequencer(Data); + break; + } + + case VGA_DAC_MASK: + { + VgaDacMask = Data; + break; + } + + case VGA_DAC_READ_INDEX: + { + VgaDacReadWrite = FALSE; + VgaDacIndex = Data * 3; + break; + } + + case VGA_DAC_WRITE_INDEX: + { + VgaDacReadWrite = TRUE; + VgaDacIndex = Data * 3; + break; + } + + case VGA_DAC_DATA: + { + /* Ignore writes in read mode */ + if (VgaDacReadWrite) VgaWriteDac(Data & 0x3F); + break; + } + + case VGA_CRTC_INDEX_MONO: + case VGA_CRTC_INDEX_COLOR: + { + /* Set the CRTC index register */ + if (Data < VGA_CRTC_MAX_REG) VgaCrtcIndex = Data; + break; + } + + case VGA_CRTC_DATA_MONO: + case VGA_CRTC_DATA_COLOR: + { + /* Call the CRTC function */ + VgaWriteCrtc(Data); + break; + } + + case VGA_GC_INDEX: + { + /* Set the GC index register */ + if (Data < VGA_GC_MAX_REG) VgaGcIndex = Data; + break; + } + + case VGA_GC_DATA: + { + /* Call the GC function */ + VgaWriteGc(Data); + break; + } + + default: + DPRINT1("VgaWritePort: Unknown port 0x%X\n", Port); + break; + } +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +DWORD VgaGetVideoBaseAddress(VOID) +{ + return MemoryBase[(VgaGcRegisters[VGA_GC_MISC_REG] >> 2) & 0x03]; +} + +DWORD VgaGetVideoLimitAddress(VOID) +{ + return MemoryLimit[(VgaGcRegisters[VGA_GC_MISC_REG] >> 2) & 0x03]; +} + +COORD VgaGetDisplayResolution(VOID) +{ + COORD Resolution; + BYTE MaximumScanLine = 1 + (VgaCrtcRegisters[VGA_CRTC_MAX_SCAN_LINE_REG] & 0x1F); + + /* The low 8 bits are in the display registers */ + Resolution.X = VgaCrtcRegisters[VGA_CRTC_END_HORZ_DISP_REG]; + Resolution.Y = VgaCrtcRegisters[VGA_CRTC_VERT_DISP_END_REG]; + + /* Set the top bits from the overflow register */ + if (VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] & VGA_CRTC_OVERFLOW_VDE8) + { + Resolution.Y |= 1 << 8; + } + if (VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] & VGA_CRTC_OVERFLOW_VDE9) + { + Resolution.Y |= 1 << 9; + } + + /* Increase the values by 1 */ + Resolution.X++; + Resolution.Y++; + + if (VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA) + { + /* Multiply the horizontal resolution by the 9/8 dot mode */ + Resolution.X *= (VgaSeqRegisters[VGA_SEQ_CLOCK_REG] & VGA_SEQ_CLOCK_98DM) + ? 8 : 9; + + /* The horizontal resolution is halved in 8-bit mode */ + if (VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT) Resolution.X /= 2; + } + + if (VgaCrtcRegisters[VGA_CRTC_MAX_SCAN_LINE_REG] & VGA_CRTC_MAXSCANLINE_DOUBLE) + { + /* Halve the vertical resolution */ + Resolution.Y >>= 1; + } + else + { + /* Divide the vertical resolution by the maximum scan line (== font size in text mode) */ + Resolution.Y /= MaximumScanLine; + } + + /* Return the resolution */ + return Resolution; +} + +VOID VgaRefreshDisplay(VOID) +{ + HANDLE ConsoleBufferHandle = NULL; + COORD Resolution; + + /* Set the vertical retrace flag */ + InVerticalRetrace = TRUE; + + /* If nothing has changed, just return */ + // if (!ModeChanged && !CursorMoved && !PaletteChanged && !NeedsUpdate) + // return; + + /* Change the display mode */ + if (ModeChanged) VgaChangeMode(); + + /* Change the text cursor location */ + if (CursorMoved) VgaUpdateTextCursor(); + + /* Retrieve the current resolution */ + Resolution = VgaGetDisplayResolution(); + + if (PaletteChanged) + { + /* Trigger a full update of the screen */ + NeedsUpdate = TRUE; + UpdateRectangle.Left = 0; + UpdateRectangle.Top = 0; + UpdateRectangle.Right = Resolution.X; + UpdateRectangle.Bottom = Resolution.Y; + + PaletteChanged = FALSE; + } + + /* Update the contents of the framebuffer */ + VgaUpdateFramebuffer(); + + /* Ignore if there's nothing to update */ + if (!NeedsUpdate) return; + + DPRINT("Updating screen rectangle (%d, %d, %d, %d)\n", + UpdateRectangle.Left, + UpdateRectangle.Top, + UpdateRectangle.Right, + UpdateRectangle.Bottom); + + /* Check if this is text mode or graphics mode */ + if (VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA) + { + /* Graphics mode */ + ConsoleBufferHandle = GraphicsConsoleBuffer; + + /* In DoubleVision mode, scale the update rectangle */ + if (DoubleVision) + { + UpdateRectangle.Left *= 2; + UpdateRectangle.Top *= 2; + UpdateRectangle.Right = UpdateRectangle.Right * 2 + 1; + UpdateRectangle.Bottom = UpdateRectangle.Bottom * 2 + 1; + } + } + else + { + /* Text mode */ + ConsoleBufferHandle = TextConsoleBuffer; + } + + /* Redraw the screen */ + __InvalidateConsoleDIBits(ConsoleBufferHandle, &UpdateRectangle); + + /* Clear the update flag */ + NeedsUpdate = FALSE; +} + +VOID VgaHorizontalRetrace(VOID) +{ + /* Set the flag */ + InHorizontalRetrace = TRUE; +} + +VOID VgaReadMemory(DWORD Address, LPBYTE Buffer, DWORD Size) +{ + DWORD i; + DWORD VideoAddress; + + DPRINT("VgaReadMemory: Address 0x%08X, Size %lu\n", Address, Size); + + /* Ignore if video RAM access is disabled */ + if ((VgaMiscRegister & VGA_MISC_RAM_ENABLED) == 0) return; + + /* Loop through each byte */ + for (i = 0; i < Size; i++) + { + VideoAddress = VgaTranslateReadAddress(Address + i); + + /* Load the latch registers */ + VgaLatchRegisters[0] = VgaMemory[LOWORD(VideoAddress)]; + VgaLatchRegisters[1] = VgaMemory[VGA_BANK_SIZE + LOWORD(VideoAddress)]; + VgaLatchRegisters[2] = VgaMemory[(2 * VGA_BANK_SIZE) + LOWORD(VideoAddress)]; + VgaLatchRegisters[3] = VgaMemory[(3 * VGA_BANK_SIZE) + LOWORD(VideoAddress)]; + + /* Copy the value to the buffer */ + Buffer[i] = VgaMemory[VideoAddress]; + } +} + +VOID VgaWriteMemory(DWORD Address, LPBYTE Buffer, DWORD Size) +{ + DWORD i, j; + DWORD VideoAddress; + + DPRINT("VgaWriteMemory: Address 0x%08X, Size %lu\n", Address, Size); + + /* Ignore if video RAM access is disabled */ + if ((VgaMiscRegister & VGA_MISC_RAM_ENABLED) == 0) return; + + /* Also ignore if write access to all planes is disabled */ + if ((VgaSeqRegisters[VGA_SEQ_MASK_REG] & 0x0F) == 0x00) return; + + /* Loop through each byte */ + for (i = 0; i < Size; i++) + { + VideoAddress = VgaTranslateWriteAddress(Address + i); + + for (j = 0; j < VGA_NUM_BANKS; j++) + { + /* Make sure the page is writeable */ + if (!(VgaSeqRegisters[VGA_SEQ_MASK_REG] & (1 << j))) continue; + + /* Check if this is chain-4 mode */ + if (VgaSeqRegisters[VGA_SEQ_MEM_REG] & VGA_SEQ_MEM_C4) + { + if (((Address + i) & 3) != j) + { + /* This plane will not be accessed */ + continue; + } + } + + /* Check if this is odd-even mode */ + if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_OE) + { + if (((Address + i) & 1) != (j & 1)) + { + /* This plane will not be accessed */ + continue; + } + } + + /* Copy the value to the VGA memory */ + VgaMemory[VideoAddress + j * VGA_BANK_SIZE] = VgaTranslateByteForWriting(Buffer[i], j); + } + } +} + +VOID VgaClearMemory(VOID) +{ + ZeroMemory(VgaMemory, sizeof(VgaMemory)); +} + +VOID VgaResetPalette(VOID) +{ + PALETTEENTRY Entries[VGA_MAX_COLORS]; + + /* Restore the default palette */ + VgaRestoreDefaultPalette(Entries, VGA_MAX_COLORS); + SetPaletteEntries(PaletteHandle, 0, VGA_MAX_COLORS, Entries); + PaletteChanged = TRUE; +} + + + + +BOOL VgaAttachToConsole(VOID) +{ + // + // FIXME: We should go back to the saved screen state + // + if (TextResolution.X == 0 || TextResolution.Y == 0) + DPRINT1("VgaAttachToConsole -- TextResolution uninitialized\n"); + + if (TextResolution.X == 0) TextResolution.X = 80; + if (TextResolution.Y == 0) TextResolution.Y = 25; + + return VgaAttachToConsoleInternal(&TextResolution); +} + +VOID VgaDetachFromConsole(BOOL ChangingMode) +{ + ULONG dummyLength; + PVOID dummyPtr; + COORD dummySize = {0}; + + // + // FIXME: We should save the screen state + // + + __RegisterConsoleVDM(0, + NULL, + NULL, + NULL, + 0, + &dummyLength, + &dummyPtr, + NULL, + 0, + dummySize, + (PCHAR*)&dummyPtr); + + TextFramebuffer = NULL; + + if (!ChangingMode) + { + SMALL_RECT ConRect; + + /* Restore the old screen buffer */ + SetConsoleActiveScreenBuffer(TextConsoleBuffer); + + /* Restore the original console size */ + ConRect.Left = 0; + ConRect.Top = 0; + ConRect.Right = ConRect.Left + OrgConsoleBufferInfo.srWindow.Right - OrgConsoleBufferInfo.srWindow.Left; + ConRect.Bottom = ConRect.Top + OrgConsoleBufferInfo.srWindow.Bottom - OrgConsoleBufferInfo.srWindow.Top ; + /* + * See the following trick explanation in VgaAttachToConsoleInternal. + */ + SetConsoleScreenBufferSize(TextConsoleBuffer, OrgConsoleBufferInfo.dwSize); + SetConsoleWindowInfo(TextConsoleBuffer, TRUE, &ConRect); + SetConsoleScreenBufferSize(TextConsoleBuffer, OrgConsoleBufferInfo.dwSize); + + /* Restore the original cursor shape */ + SetConsoleCursorInfo(TextConsoleBuffer, &OrgConsoleCursorInfo); + } +} + +BOOLEAN VgaInitialize(HANDLE TextHandle) +{ + /* Save the default text-mode console output handle */ + if (!IsConsoleHandle(TextHandle)) return FALSE; + TextConsoleBuffer = TextHandle; + + /* Save the original cursor and console screen buffer information */ + if (!GetConsoleCursorInfo(TextConsoleBuffer, &OrgConsoleCursorInfo) || + !GetConsoleScreenBufferInfo(TextConsoleBuffer, &OrgConsoleBufferInfo)) + { + return FALSE; + } + ConsoleInfo = OrgConsoleBufferInfo; + + /* Initialize the VGA palette and fail if it isn't successfully created */ + if (!VgaInitializePalette()) return FALSE; + /***/ VgaResetPalette(); /***/ + + /* Switch to the text buffer */ + SetConsoleActiveScreenBuffer(TextConsoleBuffer); + + /* Clear the VGA memory */ + VgaClearMemory(); + + /* Register the I/O Ports */ + RegisterIoPort(0x3CC, VgaReadPort, NULL); // VGA_MISC_READ + RegisterIoPort(0x3C2, VgaReadPort, VgaWritePort); // VGA_MISC_WRITE, VGA_INSTAT0_READ + RegisterIoPort(0x3CA, VgaReadPort, NULL); // VGA_FEATURE_READ + RegisterIoPort(0x3C0, VgaReadPort, VgaWritePort); // VGA_AC_INDEX, VGA_AC_WRITE + RegisterIoPort(0x3C1, VgaReadPort, NULL); // VGA_AC_READ + RegisterIoPort(0x3C4, VgaReadPort, VgaWritePort); // VGA_SEQ_INDEX + RegisterIoPort(0x3C5, VgaReadPort, VgaWritePort); // VGA_SEQ_DATA + RegisterIoPort(0x3C6, VgaReadPort, VgaWritePort); // VGA_DAC_MASK + RegisterIoPort(0x3C7, VgaReadPort, VgaWritePort); // VGA_DAC_READ_INDEX + RegisterIoPort(0x3C8, VgaReadPort, VgaWritePort); // VGA_DAC_WRITE_INDEX + RegisterIoPort(0x3C9, VgaReadPort, VgaWritePort); // VGA_DAC_DATA + RegisterIoPort(0x3CE, VgaReadPort, VgaWritePort); // VGA_GC_INDEX + RegisterIoPort(0x3CF, VgaReadPort, VgaWritePort); // VGA_GC_DATA + + /* Return success */ + return TRUE; +} + +VOID VgaCleanup(VOID) +{ + if (ScreenMode == GRAPHICS_MODE) + { + /* Leave the current graphics mode */ + VgaLeaveGraphicsMode(); + } + else + { + /* Leave the current text mode */ + VgaLeaveTextMode(); + } + + VgaDetachFromConsole(FALSE); + + CloseHandle(AnotherEvent); + CloseHandle(EndEvent); + CloseHandle(StartEvent); + +#if 0 + RegisterConsoleVDM = NULL; + FreeLibrary(hKernel32); +#endif +} + +/* EOF */ diff --git a/subsystems/ntvdm/hardware/vga.h b/subsystems/ntvdm/hardware/vga.h new file mode 100644 index 00000000000..ca6de8d4bb2 --- /dev/null +++ b/subsystems/ntvdm/hardware/vga.h @@ -0,0 +1,270 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: vga.h + * PURPOSE: VGA hardware emulation + * PROGRAMMERS: Aleksandar Andrejevic + */ + +#ifndef _VGA_H_ +#define _VGA_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" + +/* DEFINES ********************************************************************/ + +#define VGA_NUM_BANKS 4 +#define VGA_BANK_SIZE 0x10000 +#define VGA_MAX_COLORS 256 +#define VGA_PALETTE_SIZE (VGA_MAX_COLORS * 3) +#define VGA_BITMAP_INFO_SIZE (sizeof(BITMAPINFOHEADER) + 2 * (VGA_PALETTE_SIZE / 3)) +#define VGA_MINIMUM_WIDTH 400 +#define VGA_MINIMUM_HEIGHT 300 +#define VGA_DAC_TO_COLOR(x) (((x) << 2) | ((x) >> 4)) +#define VGA_COLOR_TO_DAC(x) ((x) >> 2) +#define VGA_INTERLACE_HIGH_BIT (1 << 13) + + +/* Register I/O ports */ + +#define VGA_MISC_READ 0x3CC +#define VGA_MISC_WRITE 0x3C2 + +#define VGA_INSTAT0_READ 0x3C2 + +#define VGA_INSTAT1_READ_MONO 0x3BA +#define VGA_INSTAT1_READ_COLOR 0x3DA + +#define VGA_FEATURE_READ 0x3CA +#define VGA_FEATURE_WRITE_MONO 0x3BA +#define VGA_FEATURE_WRITE_COLOR 0x3DA + +#define VGA_AC_INDEX 0x3C0 +#define VGA_AC_WRITE 0x3C0 +#define VGA_AC_READ 0x3C1 + +#define VGA_SEQ_INDEX 0x3C4 +#define VGA_SEQ_DATA 0x3C5 + +#define VGA_DAC_MASK 0x3C6 +#define VGA_DAC_READ_INDEX 0x3C7 +#define VGA_DAC_WRITE_INDEX 0x3C8 +#define VGA_DAC_DATA 0x3C9 + +#define VGA_CRTC_INDEX_MONO 0x3B4 +#define VGA_CRTC_DATA_MONO 0x3B5 +#define VGA_CRTC_INDEX_COLOR 0x3D4 +#define VGA_CRTC_DATA_COLOR 0x3D5 + +#define VGA_GC_INDEX 0x3CE +#define VGA_GC_DATA 0x3CF + + + +// +// Miscellaneous and Status Registers +// + +/* Miscellaneous register bits */ +#define VGA_MISC_COLOR (1 << 0) +#define VGA_MISC_RAM_ENABLED (1 << 1) +// #define VGA_MISC_CSEL1 (1 << 2) +// #define VGA_MISC_CSEL2 (1 << 3) +#define VGA_MISC_OE_INVERT (1 << 5) +#define VGA_MISC_HSYNCP (1 << 6) +#define VGA_MISC_VSYNCP (1 << 7) + +/* Status register flags */ +#define VGA_STAT_DD (1 << 0) +#define VGA_STAT_VRETRACE (1 << 3) + + +// +// Sequencer Registers +// + +/* Sequencer reset register bits */ +#define VGA_SEQ_RESET_AR (1 << 0) +#define VGA_SEQ_RESET_SR (1 << 1) + +/* Sequencer clock register bits */ +#define VGA_SEQ_CLOCK_98DM (1 << 0) +#define VGA_SEQ_CLOCK_SLR (1 << 2) +#define VGA_SEQ_CLOCK_DCR (1 << 3) +#define VGA_SEQ_CLOCK_S4 (1 << 4) +#define VGA_SEQ_CLOCK_SD (1 << 5) + +/* Sequencer memory register bits */ +#define VGA_SEQ_MEM_EXT (1 << 1) +#define VGA_SEQ_MEM_OE (1 << 2) +#define VGA_SEQ_MEM_C4 (1 << 3) + +enum +{ + VGA_SEQ_RESET_REG, + VGA_SEQ_CLOCK_REG, + VGA_SEQ_MASK_REG, + VGA_SEQ_CHAR_REG, + VGA_SEQ_MEM_REG, + VGA_SEQ_MAX_REG +}; + + +// +// CRT Controller Registers +// + +/* CRTC overflow register bits */ +#define VGA_CRTC_OVERFLOW_VT8 (1 << 0) +#define VGA_CRTC_OVERFLOW_VDE8 (1 << 1) +#define VGA_CRTC_OVERFLOW_VRS8 (1 << 2) +#define VGA_CRTC_OVERFLOW_SVB8 (1 << 3) +#define VGA_CRTC_OVERFLOW_LC8 (1 << 4) +#define VGA_CRTC_OVERFLOW_VT9 (1 << 5) +#define VGA_CRTC_OVERFLOW_VDE9 (1 << 6) +#define VGA_CRTC_OVERFLOW_VRS9 (1 << 7) + +/* CRTC underline register bits */ +#define VGA_CRTC_UNDERLINE_DWORD (1 << 6) + +/* CRTC max scanline register bits */ +#define VGA_CRTC_MAXSCANLINE_DOUBLE (1 << 7) + +/* CRTC mode control register bits */ +#define VGA_CRTC_MODE_CONTROL_WRAP (1 << 5) +#define VGA_CRTC_MODE_CONTROL_BYTE (1 << 6) +#define VGA_CRTC_MODE_CONTROL_SYNC (1 << 7) + +enum +{ + VGA_CRTC_HORZ_TOTAL_REG, + VGA_CRTC_END_HORZ_DISP_REG, + VGA_CRTC_START_HORZ_BLANKING_REG, + VGA_CRTC_END_HORZ_BLANKING_REG, + VGA_CRTC_START_HORZ_RETRACE_REG, + VGA_CRTC_END_HORZ_RETRACE_REG, + VGA_CRTC_VERT_TOTAL_REG, + VGA_CRTC_OVERFLOW_REG, + VGA_CRTC_PRESET_ROW_SCAN_REG, + VGA_CRTC_MAX_SCAN_LINE_REG, + VGA_CRTC_CURSOR_START_REG, + VGA_CRTC_CURSOR_END_REG, + VGA_CRTC_START_ADDR_HIGH_REG, + VGA_CRTC_START_ADDR_LOW_REG, + VGA_CRTC_CURSOR_LOC_HIGH_REG, + VGA_CRTC_CURSOR_LOC_LOW_REG, + VGA_CRTC_VERT_RETRACE_START_REG, + VGA_CRTC_VERT_RETRACE_END_REG, + VGA_CRTC_VERT_DISP_END_REG, + VGA_CRTC_OFFSET_REG, + VGA_CRTC_UNDERLINE_REG, + VGA_CRTC_START_VERT_BLANKING_REG, + VGA_CRTC_END_VERT_BLANKING, + VGA_CRTC_MODE_CONTROL_REG, + VGA_CRTC_LINE_COMPARE_REG, + VGA_CRTC_MAX_REG +}; + + +// +// Graphics Controller Registers +// + +/* Graphics controller mode register bits */ +#define VGA_GC_MODE_READ (1 << 3) +#define VGA_GC_MODE_OE (1 << 4) +#define VGA_GC_MODE_SHIFTREG (1 << 5) +#define VGA_GC_MODE_SHIFT256 (1 << 6) + +/* Graphics controller miscellaneous register bits */ +#define VGA_GC_MISC_NOALPHA (1 << 0) +#define VGA_GC_MISC_OE (1 << 1) + +enum +{ + VGA_GC_RESET_REG, + VGA_GC_ENABLE_RESET_REG, + VGA_GC_COLOR_COMPARE_REG, + VGA_GC_ROTATE_REG, + VGA_GC_READ_MAP_SEL_REG, + VGA_GC_MODE_REG, + VGA_GC_MISC_REG, + VGA_GC_COLOR_IGNORE_REG, + VGA_GC_BITMASK_REG, + VGA_GC_MAX_REG +}; + + +// +// Attribute Controller Registers +// They are a relinquish of the CGA/EGA era. +// + +/* AC mode control register bits */ +#define VGA_AC_CONTROL_ATGE (1 << 0) +#define VGA_AC_CONTROL_MONO (1 << 1) +#define VGA_AC_CONTROL_LGE (1 << 2) +#define VGA_AC_CONTROL_BLINK (1 << 3) +#define VGA_AC_CONTROL_PPM (1 << 5) +#define VGA_AC_CONTROL_8BIT (1 << 6) +#define VGA_AC_CONTROL_P54S (1 << 7) + +enum +{ + VGA_AC_PAL_0_REG, + VGA_AC_PAL_1_REG, + VGA_AC_PAL_2_REG, + VGA_AC_PAL_3_REG, + VGA_AC_PAL_4_REG, + VGA_AC_PAL_5_REG, + VGA_AC_PAL_6_REG, + VGA_AC_PAL_7_REG, + VGA_AC_PAL_8_REG, + VGA_AC_PAL_9_REG, + VGA_AC_PAL_A_REG, + VGA_AC_PAL_B_REG, + VGA_AC_PAL_C_REG, + VGA_AC_PAL_D_REG, + VGA_AC_PAL_E_REG, + VGA_AC_PAL_F_REG, + VGA_AC_CONTROL_REG, + VGA_AC_OVERSCAN_REG, + VGA_AC_COLOR_PLANE_REG, + VGA_AC_HORZ_PANNING_REG, + VGA_AC_COLOR_SEL_REG, + VGA_AC_MAX_REG +}; + + +typedef struct _VGA_REGISTERS +{ + UCHAR Misc; + UCHAR Sequencer[VGA_SEQ_MAX_REG]; + UCHAR CRT[VGA_CRTC_MAX_REG]; + UCHAR Graphics[VGA_GC_MAX_REG]; + UCHAR Attribute[VGA_AC_MAX_REG]; +} VGA_REGISTERS, *PVGA_REGISTERS; + + +/* FUNCTIONS ******************************************************************/ + +BOOL VgaAttachToConsole(VOID); +VOID VgaDetachFromConsole(BOOL ChangeMode); + +DWORD VgaGetVideoBaseAddress(VOID); +DWORD VgaGetVideoLimitAddress(VOID); +COORD VgaGetDisplayResolution(VOID); +VOID VgaRefreshDisplay(VOID); +VOID VgaHorizontalRetrace(VOID); +VOID VgaReadMemory(DWORD Address, LPBYTE Buffer, DWORD Size); +VOID VgaWriteMemory(DWORD Address, LPBYTE Buffer, DWORD Size); +VOID VgaClearMemory(VOID); + +BOOLEAN VgaInitialize(HANDLE TextHandle); +VOID VgaCleanup(VOID); + +#endif // _VGA_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/int32.c b/subsystems/ntvdm/int32.c new file mode 100644 index 00000000000..e139c85d44f --- /dev/null +++ b/subsystems/ntvdm/int32.c @@ -0,0 +1,128 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: int32.c + * PURPOSE: 32-bit Interrupt Handlers + * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +/* INCLUDES *******************************************************************/ + +// #define NDEBUG + +#include "emulator.h" +#include "int32.h" + +#include "bop.h" + +/* PRIVATE VARIABLES **********************************************************/ + +/* + * This is the list of registered 32-bit Interrupt handlers. + */ +EMULATOR_INT32_PROC Int32Proc[EMULATOR_MAX_INT32_NUM] = { NULL }; + +/* BOP Identifiers */ +#define BOP_CONTROL 0xFF // Control BOP Handler + #define BOP_CONTROL_DEFFUNC 0x00 // Default Control BOP Function + +/* 32-bit Interrupt dispatcher function code for the Control BOP Handler */ +#define BOP_CONTROL_INT32 0xFF + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID WINAPI Int32Dispatch(LPWORD Stack) +{ + /* Get the interrupt number */ + BYTE IntNum = LOBYTE(Stack[STACK_INT_NUM]); + + /* Call the 32-bit Interrupt handler */ + if (Int32Proc[IntNum] != NULL) + Int32Proc[IntNum](Stack); + else + DPRINT("Unhandled 32-bit interrupt: 0x%02X, AX = 0x%04X\n", IntNum, getAX()); +} + +VOID WINAPI ControlBop(LPWORD Stack) +{ + /* Get the Function Number and skip it */ + BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP()); + setIP(getIP() + 1); + + if (FuncNum == BOP_CONTROL_INT32) + Int32Dispatch(Stack); + else + DPRINT("Unassigned Control BOP Function: 0x%02X\n", FuncNum); +} + +VOID InitializeInt32(WORD BiosSegment) +{ + // + // WARNING WARNING!! + // + // If you modify the code stubs here, think also + // about updating them in callback.c too!! + // + + LPDWORD IntVecTable = (LPDWORD)BaseAddress; + LPBYTE BiosCode = (LPBYTE)SEG_OFF_TO_PTR(BiosSegment, 0); + USHORT i; + WORD BopSeqOffset, Offset = 0; + + /* Generate ISR stubs and fill the IVT */ + for (i = 0x00; i <= 0xFF; i++) + { + Offset = INT_HANDLER_OFFSET + (i << 4); + IntVecTable[i] = MAKELONG(Offset, BiosSegment); + + BiosCode[Offset++] = 0xFA; // cli + + BiosCode[Offset++] = 0x6A; // push i + BiosCode[Offset++] = (UCHAR)i; + + BopSeqOffset = COMMON_STUB_OFFSET - (Offset + 3); + + BiosCode[Offset++] = 0xE9; // jmp near BOP_SEQ + BiosCode[Offset++] = LOBYTE(BopSeqOffset); + BiosCode[Offset++] = HIBYTE(BopSeqOffset); + } + + /* Write the common stub code */ + Offset = COMMON_STUB_OFFSET; + +// BOP_SEQ: + BiosCode[Offset++] = 0xF8; // clc + + BiosCode[Offset++] = LOBYTE(EMULATOR_BOP); // BOP sequence + BiosCode[Offset++] = HIBYTE(EMULATOR_BOP); + BiosCode[Offset++] = BOP_CONTROL; // Control BOP + BiosCode[Offset++] = BOP_CONTROL_INT32; // 32-bit Interrupt dispatcher + + BiosCode[Offset++] = 0x73; // jnc EXIT (offset +4) + BiosCode[Offset++] = 0x04; + + BiosCode[Offset++] = 0xFB; // sti + + // HACK: The following instruction should be HLT! + BiosCode[Offset++] = 0x90; // nop + + BiosCode[Offset++] = 0xEB; // jmp BOP_SEQ (offset -11) + BiosCode[Offset++] = 0xF5; + +// EXIT: + BiosCode[Offset++] = 0x44; // inc sp + BiosCode[Offset++] = 0x44; // inc sp + + BiosCode[Offset++] = 0xCF; // iret + + /* Register the Control BOP */ + RegisterBop(BOP_CONTROL, ControlBop); +} + +VOID RegisterInt32(BYTE IntNumber, EMULATOR_INT32_PROC IntHandler) +{ + Int32Proc[IntNumber] = IntHandler; +} + +/* EOF */ diff --git a/subsystems/ntvdm/int32.h b/subsystems/ntvdm/int32.h new file mode 100644 index 00000000000..d6cced23348 --- /dev/null +++ b/subsystems/ntvdm/int32.h @@ -0,0 +1,31 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: int32.h + * PURPOSE: 32-bit Interrupt Handlers + * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +#ifndef _INT32_H_ +#define _INT32_H_ + +/* DEFINES ********************************************************************/ + +/* 32-bit Interrupt Identifiers */ +#define EMULATOR_MAX_INT32_NUM 0xFF + 1 + +#define INT_HANDLER_OFFSET 0x1000 +#define COMMON_STUB_OFFSET 0x2000 + +/* FUNCTIONS ******************************************************************/ + +typedef VOID (WINAPI *EMULATOR_INT32_PROC)(LPWORD Stack); + +VOID WINAPI Int32Dispatch(LPWORD Stack); +VOID InitializeInt32(WORD BiosSegment); +VOID RegisterInt32(BYTE IntNumber, EMULATOR_INT32_PROC IntHandler); + +#endif // _INT32_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/io.c b/subsystems/ntvdm/io.c new file mode 100644 index 00000000000..9a85a114cf5 --- /dev/null +++ b/subsystems/ntvdm/io.c @@ -0,0 +1,605 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: io.c + * PURPOSE: I/O Port Handlers + * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "io.h" + +/* PRIVATE VARIABLES **********************************************************/ + +typedef struct _EMULATOR_IO_HANDLERS +{ + EMULATOR_INB_PROC InB; + EMULATOR_INW_PROC InW; + EMULATOR_IND_PROC InD; + + EMULATOR_INSB_PROC InsB; + EMULATOR_INSW_PROC InsW; + EMULATOR_INSD_PROC InsD; + + EMULATOR_OUTB_PROC OutB; + EMULATOR_OUTW_PROC OutW; + EMULATOR_OUTD_PROC OutD; + + EMULATOR_OUTSB_PROC OutsB; + EMULATOR_OUTSW_PROC OutsW; + EMULATOR_OUTSD_PROC OutsD; +} EMULATOR_IO_HANDLERS, *PEMULATOR_IO_HANDLERS; + +typedef struct _EMULATOR_IOPORT_HANDLERS +{ + HANDLE hVdd; // == 0 if unused, + // INVALID_HANDLE_VALUE if handled internally, + // a valid VDD handle if handled externally. + union + { + /* For Windows compatibility only, not used internally... */ + VDD_IO_HANDLERS VddIoHandlers; + + /* ... we use these members internally */ + EMULATOR_IO_HANDLERS IoHandlers; + }; +} EMULATOR_IOPORT_HANDLERS, *PEMULATOR_IOPORT_HANDLERS; + +/* + * This is the list of registered I/O Port handlers. + */ +EMULATOR_IOPORT_HANDLERS IoPortProc[EMULATOR_MAX_IOPORTS_NUM] = {{NULL}}; + +/* PUBLIC FUNCTIONS ***********************************************************/ + +UCHAR +IOReadB(ULONG Port) +{ + if (IoPortProc[Port].hVdd == INVALID_HANDLE_VALUE && + IoPortProc[Port].IoHandlers.InB) + { + return IoPortProc[Port].IoHandlers.InB(Port); + } + else if (IoPortProc[Port].hVdd > 0 && + IoPortProc[Port].VddIoHandlers.inb_handler) + { + UCHAR Data; + ASSERT(Port <= MAXWORD); + IoPortProc[Port].VddIoHandlers.inb_handler((WORD)Port, &Data); + return Data; + } + else + { + /* Return an empty port byte value */ + DPRINT("Read from unknown port: 0x%X\n", Port); + return 0xFF; + } +} + +VOID +IOReadStrB(ULONG Port, + PUCHAR Buffer, + ULONG Count) +{ + if (IoPortProc[Port].hVdd == INVALID_HANDLE_VALUE && + IoPortProc[Port].IoHandlers.InsB) + { + IoPortProc[Port].IoHandlers.InsB(Port, Buffer, Count); + } + else if (IoPortProc[Port].hVdd > 0 && + IoPortProc[Port].VddIoHandlers.insb_handler) + { + ASSERT(Port <= MAXWORD); + ASSERT(Count <= MAXWORD); + IoPortProc[Port].VddIoHandlers.insb_handler((WORD)Port, Buffer, (WORD)Count); + } + else + { + while (Count--) + *Buffer++ = IOReadB(Port); + } +} + +VOID +IOWriteB(ULONG Port, + UCHAR Buffer) +{ + if (IoPortProc[Port].hVdd == INVALID_HANDLE_VALUE && + IoPortProc[Port].IoHandlers.OutB) + { + IoPortProc[Port].IoHandlers.OutB(Port, Buffer); + } + else if (IoPortProc[Port].hVdd > 0 && + IoPortProc[Port].VddIoHandlers.outb_handler) + { + ASSERT(Port <= MAXWORD); + IoPortProc[Port].VddIoHandlers.outb_handler((WORD)Port, Buffer); + } + else + { + /* Do nothing */ + DPRINT("Write to unknown port: 0x%X\n", Port); + } +} + +VOID +IOWriteStrB(ULONG Port, + PUCHAR Buffer, + ULONG Count) +{ + if (IoPortProc[Port].hVdd == INVALID_HANDLE_VALUE && + IoPortProc[Port].IoHandlers.OutsB) + { + IoPortProc[Port].IoHandlers.OutsB(Port, Buffer, Count); + } + else if (IoPortProc[Port].hVdd > 0 && + IoPortProc[Port].VddIoHandlers.outsb_handler) + { + ASSERT(Port <= MAXWORD); + ASSERT(Count <= MAXWORD); + IoPortProc[Port].VddIoHandlers.outsb_handler((WORD)Port, Buffer, (WORD)Count); + } + else + { + while (Count--) IOWriteB(Port, *Buffer++); + } +} + +USHORT +IOReadW(ULONG Port) +{ + if (IoPortProc[Port].hVdd == INVALID_HANDLE_VALUE && + IoPortProc[Port].IoHandlers.InW) + { + return IoPortProc[Port].IoHandlers.InW(Port); + } + else if (IoPortProc[Port].hVdd > 0 && + IoPortProc[Port].VddIoHandlers.inw_handler) + { + USHORT Data; + ASSERT(Port <= MAXWORD); + IoPortProc[Port].VddIoHandlers.inw_handler((WORD)Port, &Data); + return Data; + } + else + { + UCHAR Low, High; + + // FIXME: Is it ok on Little endian and Big endian ?? + Low = IOReadB(Port); + High = IOReadB(Port + sizeof(UCHAR)); + return MAKEWORD(Low, High); + } +} + +VOID +IOReadStrW(ULONG Port, + PUSHORT Buffer, + ULONG Count) +{ + if (IoPortProc[Port].hVdd == INVALID_HANDLE_VALUE && + IoPortProc[Port].IoHandlers.InsW) + { + IoPortProc[Port].IoHandlers.InsW(Port, Buffer, Count); + } + else if (IoPortProc[Port].hVdd > 0 && + IoPortProc[Port].VddIoHandlers.insw_handler) + { + ASSERT(Port <= MAXWORD); + ASSERT(Count <= MAXWORD); + IoPortProc[Port].VddIoHandlers.insw_handler((WORD)Port, Buffer, (WORD)Count); + } + else + { + while (Count--) + *Buffer++ = IOReadW(Port); + } +} + +VOID +IOWriteW(ULONG Port, + USHORT Buffer) +{ + if (IoPortProc[Port].hVdd == INVALID_HANDLE_VALUE && + IoPortProc[Port].IoHandlers.OutW) + { + IoPortProc[Port].IoHandlers.OutW(Port, Buffer); + } + else if (IoPortProc[Port].hVdd > 0 && + IoPortProc[Port].VddIoHandlers.outw_handler) + { + ASSERT(Port <= MAXWORD); + IoPortProc[Port].VddIoHandlers.outw_handler((WORD)Port, Buffer); + } + else + { + // FIXME: Is it ok on Little endian and Big endian ?? + IOWriteB(Port, LOBYTE(Buffer)); + IOWriteB(Port + sizeof(UCHAR), HIBYTE(Buffer)); + } +} + +VOID +IOWriteStrW(ULONG Port, + PUSHORT Buffer, + ULONG Count) +{ + if (IoPortProc[Port].hVdd == INVALID_HANDLE_VALUE && + IoPortProc[Port].IoHandlers.OutsW) + { + IoPortProc[Port].IoHandlers.OutsW(Port, Buffer, Count); + } + else if (IoPortProc[Port].hVdd > 0 && + IoPortProc[Port].VddIoHandlers.outsw_handler) + { + ASSERT(Port <= MAXWORD); + ASSERT(Count <= MAXWORD); + IoPortProc[Port].VddIoHandlers.outsw_handler((WORD)Port, Buffer, (WORD)Count); + } + else + { + while (Count--) IOWriteW(Port, *Buffer++); + } +} + +ULONG +IOReadD(ULONG Port) +{ + if (IoPortProc[Port].hVdd == INVALID_HANDLE_VALUE && + IoPortProc[Port].IoHandlers.InD) + { + return IoPortProc[Port].IoHandlers.InD(Port); + } + else + { + USHORT Low, High; + + // FIXME: Is it ok on Little endian and Big endian ?? + Low = IOReadW(Port); + High = IOReadW(Port + sizeof(USHORT)); + return MAKELONG(Low, High); + } +} + +VOID +IOReadStrD(ULONG Port, + PULONG Buffer, + ULONG Count) +{ + if (IoPortProc[Port].hVdd == INVALID_HANDLE_VALUE && + IoPortProc[Port].IoHandlers.InsD) + { + IoPortProc[Port].IoHandlers.InsD(Port, Buffer, Count); + } + else + { + while (Count--) + *Buffer++ = IOReadD(Port); + } +} + +VOID +IOWriteD(ULONG Port, + ULONG Buffer) +{ + if (IoPortProc[Port].hVdd == INVALID_HANDLE_VALUE && + IoPortProc[Port].IoHandlers.OutD) + { + IoPortProc[Port].IoHandlers.OutD(Port, Buffer); + } + else + { + // FIXME: Is it ok on Little endian and Big endian ?? + IOWriteW(Port, LOWORD(Buffer)); + IOWriteW(Port + sizeof(USHORT), HIWORD(Buffer)); + } +} + +VOID +IOWriteStrD(ULONG Port, + PULONG Buffer, + ULONG Count) +{ + if (IoPortProc[Port].hVdd == INVALID_HANDLE_VALUE && + IoPortProc[Port].IoHandlers.OutsD) + { + IoPortProc[Port].IoHandlers.OutsD(Port, Buffer, Count); + } + else + { + while (Count--) IOWriteD(Port, *Buffer++); + } +} + + +VOID RegisterIoPort(ULONG Port, + EMULATOR_INB_PROC InHandler, + EMULATOR_OUTB_PROC OutHandler) +{ + if (IoPortProc[Port].IoHandlers.InB == NULL) + IoPortProc[Port].IoHandlers.InB = InHandler; + else + DPRINT1("IoPortProc[0x%X].IoHandlers.InB already registered\n", Port); + + if (IoPortProc[Port].IoHandlers.OutB == NULL) + IoPortProc[Port].IoHandlers.OutB = OutHandler; + else + DPRINT1("IoPortProc[0x%X].IoHandlers.OutB already registered\n", Port); + + /* We hold the I/O port internally */ + IoPortProc[Port].hVdd = INVALID_HANDLE_VALUE; +} + +VOID UnregisterIoPort(ULONG Port) +{ + /* + * Put automagically all the fields to zero: + * the hVdd gets unregistered as well as all the handlers. + */ + // IoPortProc[Port] = {NULL}; + ZeroMemory(&IoPortProc[Port], sizeof(IoPortProc[Port])); +} + +VOID WINAPI +EmulatorReadIo(PFAST486_STATE State, + ULONG Port, + PVOID Buffer, + ULONG DataCount, + UCHAR DataSize) +{ + UNREFERENCED_PARAMETER(State); + + if (DataSize == 0 || DataCount == 0) return; + + if (DataSize == sizeof(UCHAR)) + { + if (DataCount == 1) + *(PUCHAR)Buffer = IOReadB(Port); + else + IOReadStrB(Port, Buffer, DataCount); + } + else if (DataSize == sizeof(USHORT)) + { + if (DataCount == 1) + *(PUSHORT)Buffer = IOReadW(Port); + else + IOReadStrW(Port, Buffer, DataCount); + } + else if (DataSize == sizeof(ULONG)) + { + if (DataCount == 1) + *(PULONG)Buffer = IOReadD(Port); + else + IOReadStrD(Port, Buffer, DataCount); + } + else + { + PBYTE Address = (PBYTE)Buffer; + + while (DataCount--) + { + ULONG CurrentPort = Port; + ULONG Count; + UCHAR NewDataSize = DataSize; + + /* Read dword */ + Count = NewDataSize / sizeof(ULONG); + NewDataSize = NewDataSize % sizeof(ULONG); + while (Count--) + { + *(PULONG)Address = IOReadD(CurrentPort); + CurrentPort += sizeof(ULONG); + Address += sizeof(ULONG); + } + + /* Read word */ + Count = NewDataSize / sizeof(USHORT); + NewDataSize = NewDataSize % sizeof(USHORT); + while (Count--) + { + *(PUSHORT)Address = IOReadW(CurrentPort); + CurrentPort += sizeof(USHORT); + Address += sizeof(USHORT); + } + + /* Read byte */ + Count = NewDataSize / sizeof(UCHAR); + NewDataSize = NewDataSize % sizeof(UCHAR); + while (Count--) + { + *(PUCHAR)Address = IOReadB(CurrentPort); + CurrentPort += sizeof(UCHAR); + Address += sizeof(UCHAR); + } + + ASSERT(Count == 0); + ASSERT(NewDataSize == 0); + } + } +} + +VOID WINAPI +EmulatorWriteIo(PFAST486_STATE State, + ULONG Port, + PVOID Buffer, + ULONG DataCount, + UCHAR DataSize) +{ + UNREFERENCED_PARAMETER(State); + + if (DataSize == 0 || DataCount == 0) return; + + if (DataSize == sizeof(UCHAR)) + { + if (DataCount == 1) + IOWriteB(Port, *(PUCHAR)Buffer); + else + IOWriteStrB(Port, Buffer, DataCount); + } + else if (DataSize == sizeof(USHORT)) + { + if (DataCount == 1) + IOWriteW(Port, *(PUSHORT)Buffer); + else + IOWriteStrW(Port, Buffer, DataCount); + } + else if (DataSize == sizeof(ULONG)) + { + if (DataCount == 1) + IOWriteD(Port, *(PULONG)Buffer); + else + IOWriteStrD(Port, Buffer, DataCount); + } + else + { + PBYTE Address = (PBYTE)Buffer; + + while (DataCount--) + { + ULONG CurrentPort = Port; + ULONG Count; + UCHAR NewDataSize = DataSize; + + /* Write dword */ + Count = NewDataSize / sizeof(ULONG); + NewDataSize = NewDataSize % sizeof(ULONG); + while (Count--) + { + IOWriteD(CurrentPort, *(PULONG)Address); + CurrentPort += sizeof(ULONG); + Address += sizeof(ULONG); + } + + /* Write word */ + Count = NewDataSize / sizeof(USHORT); + NewDataSize = NewDataSize % sizeof(USHORT); + while (Count--) + { + IOWriteW(CurrentPort, *(PUSHORT)Address); + CurrentPort += sizeof(USHORT); + Address += sizeof(USHORT); + } + + /* Write byte */ + Count = NewDataSize / sizeof(UCHAR); + NewDataSize = NewDataSize % sizeof(UCHAR); + while (Count--) + { + IOWriteB(CurrentPort, *(PUCHAR)Address); + CurrentPort += sizeof(UCHAR); + Address += sizeof(UCHAR); + } + + ASSERT(Count == 0); + ASSERT(NewDataSize == 0); + } + } +} + + + +BOOL +WINAPI +VDDInstallIOHook(HANDLE hVdd, + WORD cPortRange, + PVDD_IO_PORTRANGE pPortRange, + PVDD_IO_HANDLERS IOhandler) +{ + /* Check possible validity of the VDD handle */ + if (hVdd == 0 || hVdd == INVALID_HANDLE_VALUE) return FALSE; + + /* Loop for each range of I/O ports */ + while (cPortRange--) + { + WORD i; + + /* Register the range of I/O ports */ + for (i = pPortRange->First; i <= pPortRange->Last; ++i) + { + /* + * Don't do anything if the I/O port is already + * handled internally or externally. + */ + if (IoPortProc[i].hVdd != 0) + { + DPRINT1("IoPortProc[0x%X] already registered\n", i); + continue; + } + + /* Register wrt. the VDD */ + IoPortProc[i].hVdd = hVdd; + + /* Disable the internal handlers */ + IoPortProc[i].IoHandlers.InB = NULL; + IoPortProc[i].IoHandlers.InW = NULL; + IoPortProc[i].IoHandlers.InD = NULL; + + IoPortProc[i].IoHandlers.InsB = NULL; + IoPortProc[i].IoHandlers.InsW = NULL; + IoPortProc[i].IoHandlers.InsD = NULL; + + IoPortProc[i].IoHandlers.OutB = NULL; + IoPortProc[i].IoHandlers.OutW = NULL; + IoPortProc[i].IoHandlers.OutD = NULL; + + IoPortProc[i].IoHandlers.OutsB = NULL; + IoPortProc[i].IoHandlers.OutsW = NULL; + IoPortProc[i].IoHandlers.OutsD = NULL; + + /* Save our handlers */ + IoPortProc[i].VddIoHandlers = *IOhandler; + } + + /* Go to the next range */ + ++pPortRange; + ++IOhandler; + } + + return TRUE; +} + +VOID +WINAPI +VDDDeInstallIOHook(HANDLE hVdd, + WORD cPortRange, + PVDD_IO_PORTRANGE pPortRange) +{ + /* Check possible validity of the VDD handle */ + if (hVdd == 0 || hVdd == INVALID_HANDLE_VALUE) return; + + /* Loop for each range of I/O ports */ + while (cPortRange--) + { + WORD i; + + /* Unregister the range of I/O ports */ + for (i = pPortRange->First; i <= pPortRange->Last; ++i) + { + /* + * Don't do anything if we don't own the I/O port. + */ + if (IoPortProc[i].hVdd != hVdd) + { + DPRINT1("IoPortProc[0x%X] owned by somebody else\n", i); + continue; + } + + /* + * Put automagically all the fields to zero: + * the hVdd gets unregistered as well as all the handlers. + */ + // IoPortProc[i] = {NULL}; + ZeroMemory(&IoPortProc[i], sizeof(IoPortProc[i])); + } + + /* Go to the next range */ + ++pPortRange; + } +} + +/* EOF */ diff --git a/subsystems/ntvdm/io.h b/subsystems/ntvdm/io.h new file mode 100644 index 00000000000..9ed80ec794b --- /dev/null +++ b/subsystems/ntvdm/io.h @@ -0,0 +1,108 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: io.c + * PURPOSE: I/O Port Handlers + * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +#ifndef _IO_H_ +#define _IO_H_ + +/* DEFINES ********************************************************************/ + +#define EMULATOR_MAX_IOPORTS_NUM 0x10000 + +/* FUNCTIONS ******************************************************************/ + +typedef UCHAR (WINAPI *EMULATOR_INB_PROC)(ULONG Port); +typedef USHORT (WINAPI *EMULATOR_INW_PROC)(ULONG Port); +typedef ULONG (WINAPI *EMULATOR_IND_PROC)(ULONG Port); + +typedef VOID (WINAPI *EMULATOR_INSB_PROC)(ULONG Port, PUCHAR Buffer, ULONG Count); +typedef VOID (WINAPI *EMULATOR_INSW_PROC)(ULONG Port, PUSHORT Buffer, ULONG Count); +typedef VOID (WINAPI *EMULATOR_INSD_PROC)(ULONG Port, PULONG Buffer, ULONG Count); + +typedef VOID (WINAPI *EMULATOR_OUTB_PROC)(ULONG Port, UCHAR Data); +typedef VOID (WINAPI *EMULATOR_OUTW_PROC)(ULONG Port, USHORT Data); +typedef VOID (WINAPI *EMULATOR_OUTD_PROC)(ULONG Port, ULONG Data); + +typedef VOID (WINAPI *EMULATOR_OUTSB_PROC)(ULONG Port, PUCHAR Buffer, ULONG Count); +typedef VOID (WINAPI *EMULATOR_OUTSW_PROC)(ULONG Port, PUSHORT Buffer, ULONG Count); +typedef VOID (WINAPI *EMULATOR_OUTSD_PROC)(ULONG Port, PULONG Buffer, ULONG Count); + + +UCHAR +IOReadB(ULONG Port); +VOID +IOReadStrB(ULONG Port, + PUCHAR Buffer, + ULONG Count); + +VOID +IOWriteB(ULONG Port, + UCHAR Buffer); +VOID +IOWriteStrB(ULONG Port, + PUCHAR Buffer, + ULONG Count); + +USHORT +IOReadW(ULONG Port); +VOID +IOReadStrW(ULONG Port, + PUSHORT Buffer, + ULONG Count); + +VOID +IOWriteW(ULONG Port, + USHORT Buffer); +VOID +IOWriteStrW(ULONG Port, + PUSHORT Buffer, + ULONG Count); + +ULONG +IOReadD(ULONG Port); +VOID +IOReadStrD(ULONG Port, + PULONG Buffer, + ULONG Count); + +VOID +IOWriteD(ULONG Port, + ULONG Buffer); +VOID +IOWriteStrD(ULONG Port, + PULONG Buffer, + ULONG Count); + + +VOID RegisterIoPort(ULONG Port, + EMULATOR_INB_PROC InHandler, + EMULATOR_OUTB_PROC OutHandler); + +VOID UnregisterIoPort(ULONG Port); + +VOID WINAPI EmulatorReadIo +( + PFAST486_STATE State, + ULONG Port, + PVOID Buffer, + ULONG DataCount, + UCHAR DataSize +); + +VOID WINAPI EmulatorWriteIo +( + PFAST486_STATE State, + ULONG Port, + PVOID Buffer, + ULONG DataCount, + UCHAR DataSize +); + +#endif // _IO_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/lang/bg-BG.rc b/subsystems/ntvdm/lang/bg-BG.rc deleted file mode 100644 index aea51c6a350..00000000000 --- a/subsystems/ntvdm/lang/bg-BG.rc +++ /dev/null @@ -1,7 +0,0 @@ -LANGUAGE LANG_BULGARIAN, SUBLANG_DEFAULT - -STRINGTABLE -BEGIN - STRING_WelcomeMsg "Поддръжка на РеактОС за привидна ДОС машина.\n" - STRING_PromptMsg "Напишете r за пускане, s за спиране или q за изход." -END diff --git a/subsystems/ntvdm/lang/cs-CZ.rc b/subsystems/ntvdm/lang/cs-CZ.rc index e4dd3a52b1b..b620634924c 100644 --- a/subsystems/ntvdm/lang/cs-CZ.rc +++ b/subsystems/ntvdm/lang/cs-CZ.rc @@ -1,12 +1,19 @@ -/* FILE: subsystems/ntvdm/lang/cs-CZ.rc +/* + * FILE: subsystems/ntvdm/lang/cs-CZ.rc * TRANSLATOR: Radek Liska aka Black_Fox (radekliska at gmail dot com) - * UPDATED: 2008-06-24 + * UPDATED: 2014-02-01 */ - + LANGUAGE LANG_CZECH, SUBLANG_DEFAULT STRINGTABLE BEGIN - STRING_WelcomeMsg "ReactOS podpora virtuálního DOS stroje.\n" - STRING_PromptMsg "Napište r pro spuštìní, s pro vypnutí nebo q pro ukonèení." + IDS_HIDE_MOUSE, "&Skrýt ukazatel myši" + IDS_SHOW_MOUSE, "&Zobrazit ukazatel myši" + IDS_VDM_MENU , "ReactOS &VDM" +END + +STRINGTABLE +BEGIN + IDS_VDM_QUIT, "&Ukončit ReactOS VDM" END diff --git a/subsystems/ntvdm/lang/de-DE.rc b/subsystems/ntvdm/lang/de-DE.rc index e8007f8efe1..1f56de3559c 100644 --- a/subsystems/ntvdm/lang/de-DE.rc +++ b/subsystems/ntvdm/lang/de-DE.rc @@ -1,13 +1,13 @@ -/* - * German translate - * By Rouven Wessling 2005 pentiumforever@gmail.com - * 2008 dark_shadow@gmx.at - */ - LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL STRINGTABLE BEGIN - STRING_WelcomeMsg "ReactOS virtuelle DOS-Unterstützung.\n" - STRING_PromptMsg "Drücken Sie r zum Starten, s zum Herunterfahren oder q zum Beenden." + IDS_HIDE_MOUSE, "Mauszeiger &verstecken" + IDS_SHOW_MOUSE, "Mauszeiger &anzeigen" + IDS_VDM_MENU , "&ReactOS VDM" +END + +STRINGTABLE +BEGIN + IDS_VDM_QUIT, "ReactOS VDM b&eenden" END diff --git a/subsystems/ntvdm/lang/en-US.rc b/subsystems/ntvdm/lang/en-US.rc index cdb7f06e726..4ec9d710cbb 100644 --- a/subsystems/ntvdm/lang/en-US.rc +++ b/subsystems/ntvdm/lang/en-US.rc @@ -2,6 +2,12 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US STRINGTABLE BEGIN - STRING_WelcomeMsg "ReactOS Virtual DOS Machine support.\n" - STRING_PromptMsg "Type r to run, s to shutdown or q to quit now." + IDS_HIDE_MOUSE, "&Hide Mouse Pointer" + IDS_SHOW_MOUSE, "&Display Mouse Pointer" + IDS_VDM_MENU , "ReactOS &VDM" +END + +STRINGTABLE +BEGIN + IDS_VDM_QUIT, "&Quit the ReactOS VDM" END diff --git a/subsystems/ntvdm/lang/es-ES.rc b/subsystems/ntvdm/lang/es-ES.rc index d5b7d15291c..19d0591e7b8 100644 --- a/subsystems/ntvdm/lang/es-ES.rc +++ b/subsystems/ntvdm/lang/es-ES.rc @@ -1,9 +1,13 @@ -/* Spanish translation by Samuel Serapion */ - LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL STRINGTABLE BEGIN - STRING_WelcomeMsg "Maquina virtual de DOS en ReactOS.\n" - STRING_PromptMsg "Escriba r para correr, s para desactivar or q para salir ahora." + IDS_HIDE_MOUSE, "&Ocultar puntero del ratón" + IDS_SHOW_MOUSE, "&Mostrar puntero del ratón" + IDS_VDM_MENU , "ReactOS &VDM" +END + +STRINGTABLE +BEGIN + IDS_VDM_QUIT, "&Salir de ReactOS VDM" END diff --git a/subsystems/ntvdm/lang/fr-FR.rc b/subsystems/ntvdm/lang/fr-FR.rc index 702f95a7506..853aa5271a9 100644 --- a/subsystems/ntvdm/lang/fr-FR.rc +++ b/subsystems/ntvdm/lang/fr-FR.rc @@ -2,6 +2,12 @@ LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL STRINGTABLE BEGIN - STRING_WelcomeMsg "Aide de la Machine DOS Virtuel de ReactOS.\n" - STRING_PromptMsg "Taper r pour démarrer, s pour éteindre ou q pour quitter maintenant." + IDS_HIDE_MOUSE, "Mas&quer le pointeur de la souris" + IDS_SHOW_MOUSE, "&Afficher le pointeur de la souris" + IDS_VDM_MENU , "ReactOS &VDM" +END + +STRINGTABLE +BEGIN + IDS_VDM_QUIT, "&Quitter la ReactOS VDM" END diff --git a/subsystems/ntvdm/lang/hu-HU.rc b/subsystems/ntvdm/lang/hu-HU.rc deleted file mode 100644 index c25b7fbbe6f..00000000000 --- a/subsystems/ntvdm/lang/hu-HU.rc +++ /dev/null @@ -1,9 +0,0 @@ -/* Hungarian translation by Robert Horvath 2005 - talley at cubeclub.hu */ - -LANGUAGE LANG_HUNGARIAN, SUBLANG_DEFAULT - -STRINGTABLE -BEGIN - STRING_WelcomeMsg "ReactOS Virtuális DOS Gép támogatás.\n" - STRING_PromptMsg "Futtatáshoz nyomd meg a r, leállításhoz a s vagy kilépéshez a q gombot." -END diff --git a/subsystems/ntvdm/lang/id-ID.rc b/subsystems/ntvdm/lang/id-ID.rc deleted file mode 100644 index be7b06c9b83..00000000000 --- a/subsystems/ntvdm/lang/id-ID.rc +++ /dev/null @@ -1,7 +0,0 @@ -LANGUAGE LANG_INDONESIAN, SUBLANG_DEFAULT - -STRINGTABLE -BEGIN - STRING_WelcomeMsg "Dukungan ReactOS Virtual DOS Machine.\n" - STRING_PromptMsg "Ketik r untuk menjalankan, s untuk mematikan atau q untuk keluar sekarang." -END diff --git a/subsystems/ntvdm/lang/it-IT.rc b/subsystems/ntvdm/lang/it-IT.rc index 305c91418cc..ff3a0960de5 100644 --- a/subsystems/ntvdm/lang/it-IT.rc +++ b/subsystems/ntvdm/lang/it-IT.rc @@ -1,15 +1,13 @@ -/* -* PROJECT: ReactOS Virtual DOS Machine -* LICENSE: GPL - See COPYING in the top level directory -* FILE: subsystems/ntvdm/it-IT.rc -* PURPOSE: Italian Translation of subsystems/ntvdm/en-US.rc -* TRANSLATOR: Daniele Forsi (dforsi at gmail.com) -*/ - LANGUAGE LANG_ITALIAN, SUBLANG_NEUTRAL STRINGTABLE BEGIN - STRING_WelcomeMsg "Supporto di ReactOS per la macchina virtuale DOS.\n" - STRING_PromptMsg "Digitare r per avviare, s per arrestare o q per abbandonare ora." + IDS_HIDE_MOUSE, "&Nascondi il mouse" + IDS_SHOW_MOUSE, "&Mostra il mouse" + IDS_VDM_MENU , "ReactOS &VDM" +END + +STRINGTABLE +BEGIN + IDS_VDM_QUIT, "&Esci da ReactOS VDM" END diff --git a/subsystems/ntvdm/lang/ja-JP.rc b/subsystems/ntvdm/lang/ja-JP.rc deleted file mode 100644 index 7a5bfcf4943..00000000000 --- a/subsystems/ntvdm/lang/ja-JP.rc +++ /dev/null @@ -1,7 +0,0 @@ -LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT - -STRINGTABLE -BEGIN - STRING_WelcomeMsg "ReactOS Virtual DOS Machine support.\n" - STRING_PromptMsg "起動するには r を、シャットダウンするには s を、今すぐ終了させるには q を入力してください。" -END diff --git a/subsystems/ntvdm/lang/no-NO.rc b/subsystems/ntvdm/lang/no-NO.rc deleted file mode 100644 index 421dcd515aa..00000000000 --- a/subsystems/ntvdm/lang/no-NO.rc +++ /dev/null @@ -1,7 +0,0 @@ -LANGUAGE LANG_NORWEGIAN, SUBLANG_NEUTRAL - -STRINGTABLE -BEGIN - STRING_WelcomeMsg "ReactOS Vituell DOS Maskin støtte.\n" - STRING_PromptMsg "Skriv r for å kjøre, s å avslutte eller q for å slutte nå." -END diff --git a/subsystems/ntvdm/lang/pl-PL.rc b/subsystems/ntvdm/lang/pl-PL.rc index 689cf0dcb6e..e23ee40e887 100644 --- a/subsystems/ntvdm/lang/pl-PL.rc +++ b/subsystems/ntvdm/lang/pl-PL.rc @@ -1,14 +1,15 @@ -/* - * Translated by xrogers - * xxrogers@users.sourceforge.net - * https://sourceforge.net/projects/reactospl - * UTF-8 conversion by Caemyr (May, 2011) - */ - +// Created by wojo664 - Saved in UTF-8 encoding + LANGUAGE LANG_POLISH, SUBLANG_DEFAULT STRINGTABLE BEGIN - STRING_WelcomeMsg "Wirtualna maszyna DOS dla ReactOS.\n" - STRING_PromptMsg "Wciśnij r aby uruchomić, s aby wyłączyć lub q, aby zakończyć." + IDS_HIDE_MOUSE, "&Ukryj Wskaźnik Myszki" + IDS_SHOW_MOUSE, "&Pokaż Wskaźnik Myszki" + IDS_VDM_MENU , "ReactOS &VDM" +END + +STRINGTABLE +BEGIN + IDS_VDM_QUIT, "&Wyjdź z ReactOS VDM" END diff --git a/subsystems/ntvdm/lang/pt-BR.rc b/subsystems/ntvdm/lang/pt-BR.rc deleted file mode 100644 index 5f68fc7842c..00000000000 --- a/subsystems/ntvdm/lang/pt-BR.rc +++ /dev/null @@ -1,7 +0,0 @@ -LANGUAGE LANG_PORTUGUESE, SUBLANG_NEUTRAL - -STRINGTABLE -BEGIN - STRING_WelcomeMsg "ReactOS subsistema para suporte DOS de 16 bits.\n" - STRING_PromptMsg "Digite r para executar, s para desligar ou q para sair." -END diff --git a/subsystems/ntvdm/lang/ro-RO.rc b/subsystems/ntvdm/lang/ro-RO.rc deleted file mode 100644 index d8c65c6b75e..00000000000 --- a/subsystems/ntvdm/lang/ro-RO.rc +++ /dev/null @@ -1,14 +0,0 @@ -/* - * FILE: subsystems/ntvdm/lang/ro-RO.rc - * ReactOS Project (http://www.reactos.org) - * TRANSLATOR: Fulea Ștefan (PM on ReactOS Forum at fulea.stefan) - * CHANGE LOG: 2011-10-16 initial translation - */ - -LANGUAGE LANG_ROMANIAN, SUBLANG_NEUTRAL - -STRINGTABLE -BEGIN - STRING_WelcomeMsg "Asistență pentru mașina virtuală DOS.\n" - STRING_PromptMsg "Tastați r pentru a executa, s pentru a închide sau q pentru a ieși imediat." -END diff --git a/subsystems/ntvdm/lang/ru-RU.rc b/subsystems/ntvdm/lang/ru-RU.rc deleted file mode 100644 index 5a2f3aa122d..00000000000 --- a/subsystems/ntvdm/lang/ru-RU.rc +++ /dev/null @@ -1,7 +0,0 @@ -LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT - -STRINGTABLE -BEGIN - STRING_WelcomeMsg "Виртуальная машина поддержки DOS для ReactOS.\n" - STRING_PromptMsg "Введите r для запуска, s для выключения или q выхода." -END diff --git a/subsystems/ntvdm/lang/sk-SK.rc b/subsystems/ntvdm/lang/sk-SK.rc deleted file mode 100644 index cf72455ad0e..00000000000 --- a/subsystems/ntvdm/lang/sk-SK.rc +++ /dev/null @@ -1,11 +0,0 @@ -/* TRANSLATOR: Mário Kaèmár /Mario Kacmar/ aka Kario (kario@szm.sk) - * DATE OF TR: 12-02-2008 - */ - -LANGUAGE LANG_SLOVAK, SUBLANG_DEFAULT - -STRINGTABLE -BEGIN - STRING_WelcomeMsg "Podpora virtuálneho DOSového stroja v systéme ReactOS.\n" - STRING_PromptMsg "Napíšte r pre spustenie, s pre vypnutie alebo q pre okamžité skonèenie." -END diff --git a/subsystems/ntvdm/lang/th-TH.rc b/subsystems/ntvdm/lang/th-TH.rc deleted file mode 100644 index acaa6872338..00000000000 --- a/subsystems/ntvdm/lang/th-TH.rc +++ /dev/null @@ -1,7 +0,0 @@ -LANGUAGE LANG_THAI, SUBLANG_DEFAULT - -STRINGTABLE -BEGIN - STRING_WelcomeMsg "รองรับการทำงานระบบดอสเสมือนของ ReactOS\n" - STRING_PromptMsg "แบบ r เพื่อทำงาน, s เพื่อปิดระบบหรือ q เพื่อออกทันที" -END diff --git a/subsystems/ntvdm/lang/uk-UA.rc b/subsystems/ntvdm/lang/uk-UA.rc deleted file mode 100644 index ed8fc7307c1..00000000000 --- a/subsystems/ntvdm/lang/uk-UA.rc +++ /dev/null @@ -1,15 +0,0 @@ -/* - * PROJECT: Virtual DOS Machine - * LICENSE: GPL - See COPYING in the top level directory - * FILE: subsystems/ntvdm/Uk.rc - * PURPOSE: Ukraianian Language File for Virtual DOS Machine - * TRANSLATOR: Artem Reznikov - */ - -LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT - -STRINGTABLE -BEGIN - STRING_WelcomeMsg "Підтримка віртуальної машини DOS у ReactOS.\n" - STRING_PromptMsg "Введіть r для запуску, s для закриття або q, щоб вийти зараз." -END diff --git a/subsystems/ntvdm/lang/zh-CN.rc b/subsystems/ntvdm/lang/zh-CN.rc deleted file mode 100644 index 89dbafa96fb..00000000000 --- a/subsystems/ntvdm/lang/zh-CN.rc +++ /dev/null @@ -1,7 +0,0 @@ -LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED - -STRINGTABLE -BEGIN - STRING_WelcomeMsg "ReactOS 虚拟 DOS 机支持。\n" - STRING_PromptMsg "输入 r 以便运行,s 以便关闭或者 q 以便立即退出。" -END diff --git a/subsystems/ntvdm/lang/zh-TW.rc b/subsystems/ntvdm/lang/zh-TW.rc deleted file mode 100644 index 9a7790b4f3c..00000000000 --- a/subsystems/ntvdm/lang/zh-TW.rc +++ /dev/null @@ -1,7 +0,0 @@ -LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL - -STRINGTABLE -BEGIN - STRING_WelcomeMsg "ReactOS 虛擬 DOS 機支援。\n" - STRING_PromptMsg "鍵入 r 以便運行, s 以便關閉或者 q 以便立即退出。" -END diff --git a/subsystems/ntvdm/ntvdm.c b/subsystems/ntvdm/ntvdm.c index 29cf5734bd2..1239defc765 100644 --- a/subsystems/ntvdm/ntvdm.c +++ b/subsystems/ntvdm/ntvdm.c @@ -1,375 +1,575 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: subsys/ntvdm/ntvdm->c + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: ntvdm.c * PURPOSE: Virtual DOS Machine - * PROGRAMMER: Robert Dickenson (robd@mok.lvcm.com) - * UPDATE HISTORY: - * Created 23/10/2002 + * PROGRAMMERS: Aleksandar Andrejevic */ -/* INCLUDES *****************************************************************/ +/* INCLUDES *******************************************************************/ -#include -#define WIN32_NO_STATUS -#include -#include -#include -#include -#include +#define NDEBUG + +#include "ntvdm.h" +#include "emulator.h" + +#include "clock.h" +#include "hardware/ps2.h" +#include "hardware/vga.h" +#include "bios/bios.h" +#include "dos/dem.h" #include "resource.h" -#define NDEBUG -#include +/* VARIABLES ******************************************************************/ -/* GLOBALS ******************************************************************/ +static HANDLE ConsoleInput = INVALID_HANDLE_VALUE; +static HANDLE ConsoleOutput = INVALID_HANDLE_VALUE; +static DWORD OrgConsoleInputMode, OrgConsoleOutputMode; +static BOOLEAN AcceptCommands = TRUE; +static HANDLE CommandThread = NULL; +static HMENU hConsoleMenu = NULL; +static INT VdmMenuPos = -1; +static BOOLEAN ShowPointer = FALSE; -/* FUNCTIONS *****************************************************************/ +#ifndef STANDALONE +ULONG SessionId = 0; +#endif -void PrintString(char* fmt,...) -{ - char buffer[512]; - va_list ap; - - va_start(ap, fmt); - vsprintf(buffer, fmt, ap); - va_end(ap); - - OutputDebugStringA(buffer); -} +HANDLE VdmTaskEvent = NULL; /* -GetVersion -GetVolumeInformationW -GetWindowsDirectoryA -GlobalMemoryStatus -HeapAlloc -HeapCreate -HeapDestroy -HeapFree -HeapReAlloc - -GetNextVDMCommand -ExitVDM -RegisterConsoleVDM -SetVDMCurrentDirectories -VDMConsoleOperation -WriteConsoleInputVDMW - -NtSetLdtEntries -NtTerminateProcess - -NtMapViewOfSection -NtUnmapViewOfSection - -NtVdmControl + * Those menu helpers were taken from the GUI frontend in winsrv.dll */ -typedef struct tag_VDM_CONFIG { - int dos_options; - int files; - int buffers; - WCHAR** device_list; -//dos=high, umb -//device=%SystemRoot%\system32\himem.sys -//files=40 -} VDM_CONFIG, *PVDM_CONFIG; - -typedef struct tag_VDM_AUTOEXEC { - WCHAR** load_list; -//lh %SystemRoot%\system32\mscdexnt.exe -//lh %SystemRoot%\system32\redir -//lh %SystemRoot%\system32\dosx -} VDM_AUTOEXEC, *PVDM_AUTOEXEC; - -typedef struct tag_VDM_CONTROL_BLOCK { - HANDLE hHeap; - PVOID ImageMem; - VDM_CONFIG vdmConfig; - VDM_AUTOEXEC vdmAutoexec; - PROCESS_INFORMATION ProcessInformation; - CHAR CommandLine[MAX_PATH]; - CHAR CurrentDirectory[MAX_PATH]; - -} VDM_CONTROL_BLOCK, *PVDM_CONTROL_BLOCK; - - -BOOL -StartVDM(PVDM_CONTROL_BLOCK vdm) +typedef struct _VDM_MENUITEM { - BOOL Result; - STARTUPINFOA StartupInfo; + UINT uID; + const struct _VDM_MENUITEM *SubMenu; + WORD wCmdID; +} VDM_MENUITEM, *PVDM_MENUITEM; - StartupInfo.cb = sizeof(StartupInfo); - StartupInfo.lpReserved = NULL; - StartupInfo.lpDesktop = NULL; - StartupInfo.lpTitle = NULL; - StartupInfo.dwFlags = 0; - StartupInfo.cbReserved2 = 0; - StartupInfo.lpReserved2 = 0; - - Result = CreateProcessA(vdm->CommandLine, - NULL, - NULL, - NULL, - FALSE, - DETACHED_PROCESS, - NULL, - NULL, - &StartupInfo, - &vdm->ProcessInformation); - if (!Result) { - PrintString("VDM: Failed to execute target process\n"); - return FALSE; - } - WaitForSingleObject(vdm->ProcessInformation.hProcess, INFINITE); - CloseHandle(vdm->ProcessInformation.hProcess); - CloseHandle(vdm->ProcessInformation.hThread); - return TRUE; -} - -BOOL -ShutdownVDM(PVDM_CONTROL_BLOCK vdm) +static const VDM_MENUITEM VdmMenuItems[] = { - BOOL result = TRUE; + { IDS_VDM_QUIT, NULL, ID_VDM_QUIT }, - return result; -} + { 0, NULL, 0 } /* End of list */ +}; -BOOL ReadConfigForVDM(PVDM_CONTROL_BLOCK vdm) +static const VDM_MENUITEM VdmMainMenuItems[] = { - BOOL result = TRUE; - DWORD dwError; - HANDLE hFile; + { -1, NULL, 0 }, /* Separator */ + { IDS_HIDE_MOUSE, NULL, ID_SHOWHIDE_MOUSE }, /* Hide mouse; can be renamed to Show mouse */ + { IDS_VDM_MENU , VdmMenuItems, 0 }, /* ReactOS VDM Menu */ - hFile = CreateFileW(L"\\system32\\config.nt", - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_ALWAYS /*OPEN_EXISTING*/, - FILE_ATTRIBUTE_NORMAL, - 0); - dwError = GetLastError(); - if (hFile == INVALID_HANDLE_VALUE) { - // error with file path or system problem? - } else { - if (dwError == 0L) { - // we just created a new file, perhaps we should set/write some defaults? - } - if (dwError == ERROR_ALREADY_EXISTS) { - // read the line entries and cache in some struct... - } - CloseHandle(hFile); - } + { 0, NULL, 0 } /* End of list */ +}; - hFile = CreateFileW(L"\\system32\\autoexec.nt", - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - 0); - dwError = GetLastError(); - if (hFile == INVALID_HANDLE_VALUE) { - // error with file path or system problem? - } else { - if (dwError == 0L) { - // we just created a new file, perhaps we should set/write some defaults? - } - if (dwError == ERROR_ALREADY_EXISTS) { - // read the line entries and cache in some struct... - } - CloseHandle(hFile); - } - - return result; -} - -BOOL -LoadConfigDriversForVDM(PVDM_CONFIG vdmConfig) +static VOID +AppendMenuItems(HMENU hMenu, + const VDM_MENUITEM *Items) { - BOOL result = TRUE; + UINT i = 0; + WCHAR szMenuString[255]; + HMENU hSubMenu; - return result; -} + do + { + if (Items[i].uID != (UINT)-1) + { + if (LoadStringW(GetModuleHandle(NULL), + Items[i].uID, + szMenuString, + sizeof(szMenuString) / sizeof(szMenuString[0])) > 0) + { + if (Items[i].SubMenu != NULL) + { + hSubMenu = CreatePopupMenu(); + if (hSubMenu != NULL) + { + AppendMenuItems(hSubMenu, Items[i].SubMenu); -BOOL -SetConfigOptionsForVDM(PVDM_AUTOEXEC vdmAutoexec) -{ - BOOL result = TRUE; - - return result; -} - -BOOL -CreateVDM(PVDM_CONTROL_BLOCK vdm) -{ -// BOOL result = TRUE; - SYSTEM_INFO inf; - MEMORYSTATUS stat; - - - GlobalMemoryStatus(&stat); - if (stat.dwLength != sizeof(MEMORYSTATUS)) { - printf("WARNING: GlobalMemoryStatus() returned unknown structure version, size %ld, expected %d.\n", stat.dwLength, sizeof(stat)); - } else { - printf("Memory Load: %ld percent in use.\n", stat.dwMemoryLoad); - printf("\t%ld total bytes physical memory.\n", stat.dwTotalPhys); - printf("\t%ld available physical memory.\n", stat.dwAvailPhys); - printf("\t%ld total bytes paging file.\n", stat.dwTotalPageFile); - printf("\t%ld available paging file.\n", stat.dwAvailPageFile); - printf("\t%lx total bytes virtual memory.\n", stat.dwTotalVirtual); - printf("\t%lx available bytes virtual memory.\n", stat.dwAvailVirtual); - -#define OUT_OF_HEADROOM 90 - if (stat.dwMemoryLoad > OUT_OF_HEADROOM) { - DPRINT("VDM: system resources deemed to low to start VDM.\n"); - //SetLastError(); - return FALSE; - } - - } - - GetSystemInfo(&inf); - vdm->hHeap = HeapCreate(0, inf.dwAllocationGranularity, 0); - if (vdm->hHeap == NULL) { - DPRINT("VDM: failed to create heap.\n"); - return FALSE; - } - -#define DEFAULT_VDM_IMAGE_SIZE 2000000 - vdm->ImageMem = HeapAlloc(vdm->hHeap, 0, DEFAULT_VDM_IMAGE_SIZE); - if (vdm->ImageMem == NULL) { - DPRINT("VDM: failed to allocate image memory from heap %x.\n", vdm->hHeap); - HeapDestroy(vdm->hHeap); - vdm->hHeap = NULL; - return FALSE; - } - return TRUE; -} - -BOOL -DestroyVDM(PVDM_CONTROL_BLOCK vdm) -{ - BOOL result = TRUE; - - if (vdm->ImageMem != NULL) { - if (HeapFree(vdm->hHeap, 0, vdm->ImageMem) != FALSE) { - DPRINT("VDM: failed to free memory from heap %x.\n", vdm->hHeap); - result = FALSE; - } - vdm->ImageMem = NULL; - } - if (vdm->hHeap != NULL) { - if (!HeapDestroy(vdm->hHeap)) { - DPRINT("VDM: failed to destroy heap %x.\n", vdm->hHeap); - result = FALSE; - } - vdm->hHeap = NULL; - } - return result; -} - -int WINAPI -WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) -{ - VDM_CONTROL_BLOCK VdmCB; - DWORD Result; - ULONG i; - BOOL vdmStarted = FALSE; - - WCHAR WelcomeMsg[RC_STRING_MAX_SIZE]; - WCHAR PromptMsg[RC_STRING_MAX_SIZE]; - CHAR InputBuffer[255]; - - LoadStringW( GetModuleHandle(NULL), STRING_WelcomeMsg, WelcomeMsg,sizeof(WelcomeMsg) / sizeof(WelcomeMsg[0])); - LoadStringW( GetModuleHandle(NULL), STRING_PromptMsg, PromptMsg ,sizeof(PromptMsg) / sizeof(PromptMsg[0])); - - AllocConsole(); - SetConsoleTitleW(L"ntvdm"); - - WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), - WelcomeMsg, lstrlenW(WelcomeMsg), // wcslen(WelcomeMsg), - &Result, NULL); - - if (!CreateVDM(&VdmCB)) { - DPRINT("VDM: failed to create VDM.\n"); - //SetLastError(); - return 2; - } - - ReadConfigForVDM(&VdmCB); - - if (!LoadConfigDriversForVDM(&(VdmCB.vdmConfig))) { - DPRINT("VDM: failed to load configuration drivers.\n"); - //SetLastError(); - return 2; - } - if (!SetConfigOptionsForVDM(&(VdmCB.vdmAutoexec))) { - DPRINT("VDM: failed to set configuration options.\n"); - //SetLastError(); - return 3; - } - - GetSystemDirectoryA(VdmCB.CommandLine, MAX_PATH); - strcat(VdmCB.CommandLine, "\\hello.exe"); - GetWindowsDirectoryA(VdmCB.CurrentDirectory, MAX_PATH); - - for (;;) { - WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), - PromptMsg, lstrlenW(PromptMsg), // wcslen(PromptMsg), - &Result, NULL); - i = 0; - do { - ReadConsoleA(GetStdHandle(STD_INPUT_HANDLE), - &InputBuffer[i], 1, - &Result, NULL); - if (++i >= (sizeof(InputBuffer) - 1)) { - break; - } - } while (InputBuffer[i - 1] != '\n'); - InputBuffer[i - 1] = '\0'; - - if (InputBuffer[0] == 'r' || InputBuffer[0] == 'R') { - if (!vdmStarted) { - if (StartVDM(&VdmCB)) { - vdmStarted = TRUE; - } else { - DPRINT("VDM: failed to start.\n"); + if (!AppendMenuW(hMenu, + MF_STRING | MF_POPUP, + (UINT_PTR)hSubMenu, + szMenuString)) + { + DestroyMenu(hSubMenu); + } + } } - } else { - DPRINT("VDM: already started.\n"); - } - } - if (InputBuffer[0] == 's' || InputBuffer[0] == 'S') { - if (vdmStarted) { - if (ShutdownVDM(&VdmCB)) { - vdmStarted = FALSE; - } else { - DPRINT("VDM: failed to shutdown.\n"); + else + { + AppendMenuW(hMenu, + MF_STRING, + Items[i].wCmdID, + szMenuString); } - } else { - DPRINT("VDM: not started.\n"); } } - if (InputBuffer[0] == 'q' || InputBuffer[0] == 'Q') { + else + { + AppendMenuW(hMenu, + MF_SEPARATOR, + 0, + NULL); + } + i++; + } while (!(Items[i].uID == 0 && Items[i].SubMenu == NULL && Items[i].wCmdID == 0)); +} + +static VOID +CreateVdmMenu(HANDLE ConOutHandle) +{ + hConsoleMenu = ConsoleMenuControl(ConOutHandle, + ID_SHOWHIDE_MOUSE, + ID_VDM_QUIT); + if (hConsoleMenu == NULL) return; + + VdmMenuPos = GetMenuItemCount(hConsoleMenu); + AppendMenuItems(hConsoleMenu, VdmMainMenuItems); + DrawMenuBar(GetConsoleWindow()); +} + +static VOID +DestroyVdmMenu(VOID) +{ + UINT i = 0; + const VDM_MENUITEM *Items = VdmMainMenuItems; + + do + { + DeleteMenu(hConsoleMenu, VdmMenuPos, MF_BYPOSITION); + i++; + } while (!(Items[i].uID == 0 && Items[i].SubMenu == NULL && Items[i].wCmdID == 0)); + + DrawMenuBar(GetConsoleWindow()); +} + +static VOID ShowHideMousePointer(HANDLE ConOutHandle, BOOLEAN ShowPtr) +{ + WCHAR szMenuString[255] = L""; + + if (ShowPtr) + { + /* Be sure the cursor will be shown */ + while (ShowConsoleCursor(ConOutHandle, TRUE) < 0) ; + } + else + { + /* Be sure the cursor will be hidden */ + while (ShowConsoleCursor(ConOutHandle, FALSE) >= 0) ; + } + + if (LoadStringW(GetModuleHandle(NULL), + (!ShowPtr ? IDS_SHOW_MOUSE : IDS_HIDE_MOUSE), + szMenuString, + sizeof(szMenuString) / sizeof(szMenuString[0])) > 0) + { + ModifyMenu(hConsoleMenu, ID_SHOWHIDE_MOUSE, + MF_BYCOMMAND, ID_SHOWHIDE_MOUSE, szMenuString); + } +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID +DisplayMessage(LPCWSTR Format, ...) +{ + WCHAR Buffer[256]; + va_list Parameters; + + va_start(Parameters, Format); + _vsnwprintf(Buffer, 256, Format, Parameters); + DPRINT1("\n\nNTVDM Subsystem\n%S\n\n", Buffer); + MessageBoxW(NULL, Buffer, L"NTVDM Subsystem", MB_OK); + va_end(Parameters); +} + +static BOOL +WINAPI +ConsoleCtrlHandler(DWORD ControlType) +{ + switch (ControlType) + { + case CTRL_C_EVENT: + case CTRL_BREAK_EVENT: + { + /* Call INT 23h */ + EmulatorInterrupt(0x23); break; } + case CTRL_LAST_CLOSE_EVENT: + { + if (WaitForSingleObject(VdmTaskEvent, 0) == WAIT_TIMEOUT) + { + /* Exit immediately */ + if (CommandThread) TerminateThread(CommandThread, 0); + EmulatorTerminate(); + } + else + { + /* Stop accepting new commands */ + AcceptCommands = FALSE; + } + + break; + } + default: + { + /* Stop the VDM if the user logs out or closes the console */ + EmulatorTerminate(); + } + } + return TRUE; +} + +static VOID +ConsoleInitUI(VOID) +{ + CreateVdmMenu(ConsoleOutput); +} + +static VOID +ConsoleCleanupUI(VOID) +{ + /* Display again properly the mouse pointer */ + if (ShowPointer) ShowHideMousePointer(ConsoleOutput, ShowPointer); + + DestroyVdmMenu(); +} + +static BOOL +ConsoleAttach(VOID) +{ + /* Save the original input and output console modes */ + if (!GetConsoleMode(ConsoleInput , &OrgConsoleInputMode ) || + !GetConsoleMode(ConsoleOutput, &OrgConsoleOutputMode)) + { + CloseHandle(ConsoleOutput); + CloseHandle(ConsoleInput); + wprintf(L"FATAL: Cannot save console in/out modes\n"); + // return FALSE; } - if (!ShutdownVDM(&VdmCB)) { - DPRINT("VDM: failed to cleanly shutdown VDM.\n"); - //SetLastError(); - return 5; + /* Initialize the UI */ + ConsoleInitUI(); + + return TRUE; +} + +static VOID +ConsoleDetach(VOID) +{ + /* Restore the original input and output console modes */ + SetConsoleMode(ConsoleOutput, OrgConsoleOutputMode); + SetConsoleMode(ConsoleInput , OrgConsoleInputMode ); + + /* Cleanup the UI */ + ConsoleCleanupUI(); +} + +static BOOL +ConsoleInit(VOID) +{ + /* Set the handler routine */ + SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE); + + /* Enable the CTRL_LAST_CLOSE_EVENT */ + SetLastConsoleEventActive(); + + /* + * NOTE: The CONIN$ and CONOUT$ "virtual" files + * always point to non-redirected console handles. + */ + + /* Get the input handle to the real console, and check for success */ + ConsoleInput = CreateFileW(L"CONIN$", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL); + if (ConsoleInput == INVALID_HANDLE_VALUE) + { + wprintf(L"FATAL: Cannot retrieve a handle to the console input\n"); + return FALSE; } - if (!DestroyVDM(&VdmCB)) { - DPRINT("VDM: failed to cleanly destroy VDM.\n"); - //SetLastError(); - return 6; + /* Get the output handle to the real console, and check for success */ + ConsoleOutput = CreateFileW(L"CONOUT$", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL); + if (ConsoleOutput == INVALID_HANDLE_VALUE) + { + CloseHandle(ConsoleInput); + wprintf(L"FATAL: Cannot retrieve a handle to the console output\n"); + return FALSE; + } + + /* Effectively attach to the console */ + return ConsoleAttach(); +} + +static VOID +ConsoleCleanup(VOID) +{ + /* Detach from the console */ + ConsoleDetach(); + + /* Close the console handles */ + if (ConsoleOutput != INVALID_HANDLE_VALUE) CloseHandle(ConsoleOutput); + if (ConsoleInput != INVALID_HANDLE_VALUE) CloseHandle(ConsoleInput); +} + +DWORD +WINAPI +PumpConsoleInput(LPVOID Parameter) +{ + HANDLE ConsoleInput = (HANDLE)Parameter; + INPUT_RECORD InputRecord; + DWORD Count; + + while (VdmRunning) + { + /* Make sure the task event is signaled */ + WaitForSingleObject(VdmTaskEvent, INFINITE); + + /* Wait for an input record */ + if (!ReadConsoleInput(ConsoleInput, &InputRecord, 1, &Count)) + { + DWORD LastError = GetLastError(); + DPRINT1("Error reading console input (0x%p, %lu) - Error %lu\n", ConsoleInput, Count, LastError); + return LastError; + } + + ASSERT(Count != 0); + + /* Check the event type */ + switch (InputRecord.EventType) + { + case KEY_EVENT: + case MOUSE_EVENT: + /* Send it to the PS/2 controller */ + PS2Dispatch(&InputRecord); + break; + + case MENU_EVENT: + { + switch (InputRecord.Event.MenuEvent.dwCommandId) + { + case ID_SHOWHIDE_MOUSE: + ShowHideMousePointer(ConsoleOutput, ShowPointer); + ShowPointer = !ShowPointer; + break; + + case ID_VDM_QUIT: + /* Stop the VDM */ + EmulatorTerminate(); + break; + + default: + break; + } + + break; + } + + default: + break; + } } - ExitProcess(0); return 0; } + +#ifndef STANDALONE +static DWORD +WINAPI +CommandThreadProc(LPVOID Parameter) +{ + BOOLEAN First = TRUE; + DWORD Result; + VDM_COMMAND_INFO CommandInfo; + CHAR CmdLine[MAX_PATH]; + CHAR AppName[MAX_PATH]; + CHAR PifFile[MAX_PATH]; + CHAR Desktop[MAX_PATH]; + CHAR Title[MAX_PATH]; + CHAR Env[MAX_PATH]; + + UNREFERENCED_PARAMETER(Parameter); + + do + { + /* Clear the structure */ + ZeroMemory(&CommandInfo, sizeof(CommandInfo)); + + /* Initialize the structure members */ + CommandInfo.TaskId = SessionId; + CommandInfo.VDMState = VDM_FLAG_DOS; + CommandInfo.CmdLine = CmdLine; + CommandInfo.CmdLen = sizeof(CmdLine); + CommandInfo.AppName = AppName; + CommandInfo.AppLen = sizeof(AppName); + CommandInfo.PifFile = PifFile; + CommandInfo.PifLen = sizeof(PifFile); + CommandInfo.Desktop = Desktop; + CommandInfo.DesktopLen = sizeof(Desktop); + CommandInfo.Title = Title; + CommandInfo.TitleLen = sizeof(Title); + CommandInfo.Env = Env; + CommandInfo.EnvLen = sizeof(Env); + + if (First) CommandInfo.VDMState |= VDM_FLAG_FIRST_TASK; + + /* Wait for the next available VDM */ + if (!GetNextVDMCommand(&CommandInfo)) break; + + /* Start the process from the command line */ + DPRINT1("Starting '%s' ('%s')...\n", AppName, CmdLine); + Result = DosStartProcess(AppName, CmdLine, Env); + if (Result != ERROR_SUCCESS) + { + DisplayMessage(L"Could not start '%S'. Error: %u", AppName, Result); + // break; + continue; + } + + First = FALSE; + } + while (AcceptCommands); + + return 0; +} +#endif + +INT +wmain(INT argc, WCHAR *argv[]) +{ +#ifdef STANDALONE + + DWORD Result; + CHAR ApplicationName[MAX_PATH]; + CHAR CommandLine[DOS_CMDLINE_LENGTH]; + + if (argc >= 2) + { + WideCharToMultiByte(CP_ACP, 0, argv[1], -1, ApplicationName, sizeof(ApplicationName), NULL, NULL); + + if (argc >= 3) WideCharToMultiByte(CP_ACP, 0, argv[2], -1, CommandLine, sizeof(CommandLine), NULL, NULL); + else strcpy(CommandLine, ""); + } + else + { + wprintf(L"\nReactOS Virtual DOS Machine\n\n" + L"Usage: NTVDM []\n"); + return 0; + } + +#else + + INT i; + WCHAR *endptr; + + /* Parse the command line arguments */ + for (i = 1; i < argc; i++) + { + if (wcsncmp(argv[i], L"-i", 2) == 0) + { + /* This is the session ID */ + SessionId = wcstoul(argv[i] + 2, &endptr, 10); + + /* The VDM hasn't been started from a console, so quit when the task is done */ + AcceptCommands = FALSE; + } + } + +#endif + + DPRINT1("\n\n\nNTVDM - Starting...\n\n\n"); + + /* Create the task event */ + VdmTaskEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + ASSERT(VdmTaskEvent != NULL); + + /* Initialize the console */ + if (!ConsoleInit()) + { + wprintf(L"FATAL: A problem occurred when trying to initialize the console\n"); + goto Cleanup; + } + + /* Initialize the emulator */ + if (!EmulatorInitialize(ConsoleInput, ConsoleOutput)) + { + wprintf(L"FATAL: Failed to initialize the emulator\n"); + goto Cleanup; + } + + /* Initialize the system BIOS */ + if (!BiosInitialize(NULL)) + { + wprintf(L"FATAL: Failed to initialize the VDM BIOS.\n"); + goto Cleanup; + } + + /* Initialize the VDM DOS kernel */ + if (!DosInitialize(NULL)) + { + wprintf(L"FATAL: Failed to initialize the VDM DOS kernel.\n"); + goto Cleanup; + } + +#ifndef STANDALONE + + /* Create the GetNextVDMCommand thread */ + CommandThread = CreateThread(NULL, 0, &CommandThreadProc, NULL, 0, NULL); + if (CommandThread == NULL) + { + wprintf(L"FATAL: Failed to create the command processing thread: %d\n", GetLastError()); + goto Cleanup; + } + + /* Wait for the command thread to exit */ + WaitForSingleObject(CommandThread, INFINITE); + + /* Close the thread handle */ + CloseHandle(CommandThread); + +#else + + /* Start the process from the command line */ + DPRINT1("Starting '%s' ('%s')...\n", ApplicationName, CommandLine); + Result = DosStartProcess(ApplicationName, + CommandLine, + GetEnvironmentStrings()); + if (Result != ERROR_SUCCESS) + { + DisplayMessage(L"Could not start '%S'. Error: %u", ApplicationName, Result); + goto Cleanup; + } + +#endif + +Cleanup: + BiosCleanup(); + EmulatorCleanup(); + ConsoleCleanup(); + +#ifndef STANDALONE + ExitVDM(FALSE, 0); +#endif + + /* Quit the VDM */ + DPRINT1("\n\n\nNTVDM - Exiting...\n\n\n"); + + return 0; +} + +/* EOF */ diff --git a/subsystems/ntvdm/ntvdm.h b/subsystems/ntvdm/ntvdm.h new file mode 100644 index 00000000000..4686c05e77d --- /dev/null +++ b/subsystems/ntvdm/ntvdm.h @@ -0,0 +1,53 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: ntvdm.h + * PURPOSE: Header file to define commonly used stuff + * PROGRAMMERS: Aleksandar Andrejevic + */ + +#ifndef _NTVDM_H_ +#define _NTVDM_H_ + +/* INCLUDES *******************************************************************/ + +#include +#include +#include +#include + +#define WIN32_NO_STATUS +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +DWORD WINAPI SetLastConsoleEventActive(VOID); + +#include + +/* + * Activate this line if you want to run NTVDM in standalone mode with: + * ntvdm.exe + */ +// #define STANDALONE + +/* FUNCTIONS ******************************************************************/ + +#ifndef STANDALONE +extern ULONG SessionId; +#endif + +extern HANDLE VdmTaskEvent; + +VOID DisplayMessage(LPCWSTR Format, ...); + +#endif // _NTVDM_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/ntvdm.rc b/subsystems/ntvdm/ntvdm.rc index 6542cc225a9..bb78cedd6a3 100644 --- a/subsystems/ntvdm/ntvdm.rc +++ b/subsystems/ntvdm/ntvdm.rc @@ -1,32 +1,39 @@ #include +#include +// #include #include "resource.h" -#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Virtual DOS Machine" -#define REACTOS_STR_INTERNAL_NAME "ntvdm" -#define REACTOS_STR_ORIGINAL_FILENAME "ntvdm.exe" +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL + +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Virtual DOS Machine" +#define REACTOS_STR_INTERNAL_NAME "ntvdm" +#define REACTOS_STR_ORIGINAL_FILENAME "ntvdm.exe" #include +IDI_APPICON ICON "res/ntvdm.ico" + /* UTF-8 */ #pragma code_page(65001) -#include "lang/bg-BG.rc" -#include "lang/cs-CZ.rc" -#include "lang/de-DE.rc" -#include "lang/en-US.rc" -#include "lang/es-ES.rc" -#include "lang/fr-FR.rc" -#include "lang/hu-HU.rc" -#include "lang/id-ID.rc" -#include "lang/it-IT.rc" -#include "lang/ja-JP.rc" -#include "lang/no-NO.rc" -#include "lang/pl-PL.rc" -#include "lang/pt-BR.rc" -#include "lang/ro-RO.rc" -#include "lang/ru-RU.rc" -#include "lang/sk-SK.rc" -#include "lang/th-TH.rc" -#include "lang/uk-UA.rc" -#include "lang/zh-CN.rc" -#include "lang/zh-TW.rc" +#ifdef LANGUAGE_CS_CZ + #include "lang/cs-CZ.rc" +#endif +#ifdef LANGUAGE_DE_DE + #include "lang/de-DE.rc" +#endif +#ifdef LANGUAGE_EN_US + #include "lang/en-US.rc" +#endif +#ifdef LANGUAGE_ES_ES + #include "lang/es-ES.rc" +#endif +#ifdef LANGUAGE_FR_FR + #include "lang/fr-FR.rc" +#endif +#ifdef LANGUAGE_IT_IT + #include "lang/it-IT.rc" +#endif +#ifdef LANGUAGE_PL_PL + #include "lang/pl-PL.rc" +#endif diff --git a/subsystems/ntvdm/ntvdm.spec b/subsystems/ntvdm/ntvdm.spec new file mode 100644 index 00000000000..244bda9200f --- /dev/null +++ b/subsystems/ntvdm/ntvdm.spec @@ -0,0 +1,220 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; NTVDM Registers exports ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +@ stdcall getAF() +@ stdcall getAH() +@ stdcall getAL() +@ stdcall getAX() +@ stdcall getBH() +@ stdcall getBL() +@ stdcall getBP() +@ stdcall getBX() +@ stdcall getCF() +@ stdcall getCH() +@ stdcall getCL() +@ stdcall getCS() +@ stdcall getCX() +@ stdcall getDF() +@ stdcall getDH() +@ stdcall getDI() +@ stdcall getDL() +@ stdcall getDS() +@ stdcall getDX() +@ stdcall getEAX() +@ stdcall getEBP() +@ stdcall getEBX() +@ stdcall getECX() +@ stdcall getEDI() +@ stdcall getEDX() +@ stdcall getEFLAGS() +@ stdcall getEIP() +@ stdcall getES() +@ stdcall getESI() +@ stdcall getESP() +@ stdcall getFS() +@ stdcall getGS() +@ stdcall getIF() +@ stdcall getIntelRegistersPointer() +@ stdcall getIP() +@ stdcall getMSW() +@ stdcall getOF() +@ stdcall getPF() +@ stdcall getSF() +@ stdcall getSI() +@ stdcall getSP() +@ stdcall getSS() +@ stdcall getZF() + +@ stdcall setAF(long) +@ stdcall setAH(long) +@ stdcall setAL(long) +@ stdcall setAX(long) +@ stdcall setBH(long) +@ stdcall setBL(long) +@ stdcall setBP(long) +@ stdcall setBX(long) +@ stdcall setCF(long) +@ stdcall setCH(long) +@ stdcall setCL(long) +@ stdcall setCS(long) +@ stdcall setCX(long) +@ stdcall setDF(long) +@ stdcall setDH(long) +@ stdcall setDI(long) +@ stdcall setDL(long) +@ stdcall setDS(long) +@ stdcall setDX(long) +@ stdcall setEAX(long) +@ stdcall setEBP(long) +@ stdcall setEBX(long) +@ stdcall setECX(long) +@ stdcall setEDI(long) +@ stdcall setEDX(long) +@ stdcall setEFLAGS(long) +@ stdcall setEIP(long) +@ stdcall setES(long) +@ stdcall setESI(long) +@ stdcall setESP(long) +@ stdcall setFS(long) +@ stdcall setGS(long) +@ stdcall setIF(long) +@ stdcall setIP(long) +@ stdcall setMSW(long) +@ stdcall setOF(long) +@ stdcall setPF(long) +@ stdcall setSF(long) +@ stdcall setSI(long) +@ stdcall setSP(long) +@ stdcall setSS(long) +@ stdcall setZF(long) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; NTVDM CCPU MIPS exports ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +@ stdcall c_getAF() getAF +@ stdcall c_getAH() getAH +@ stdcall c_getAL() getAL +@ stdcall c_getAX() getAX +@ stdcall c_getBH() getBH +@ stdcall c_getBL() getBL +@ stdcall c_getBP() getBP +@ stdcall c_getBX() getBX +@ stdcall c_getCF() getCF +@ stdcall c_getCH() getCH +@ stdcall c_getCL() getCL +@ stdcall c_getCS() getCS +@ stdcall c_getCX() getCX +@ stdcall c_getDF() getDF +@ stdcall c_getDH() getDH +@ stdcall c_getDI() getDI +@ stdcall c_getDL() getDL +@ stdcall c_getDS() getDS +@ stdcall c_getDX() getDX +@ stdcall c_getEAX() getEAX +@ stdcall c_getEBP() getEBP +@ stdcall c_getEBX() getEBX +@ stdcall c_getECX() getECX +@ stdcall c_getEDI() getEDI +@ stdcall c_getEDX() getEDX +@ stdcall c_getEIP() getEIP +@ stdcall c_getES() getES +@ stdcall c_getESI() getESI +@ stdcall c_getESP() getESP +@ stdcall c_getFS() getFS +@ stdcall c_getGS() getGS +@ stdcall c_getIF() getIF +@ stdcall c_getIP() getIP +@ stdcall c_getMSW() getMSW +@ stdcall c_getOF() getOF +@ stdcall c_getPF() getPF +@ stdcall c_getSF() getSF +@ stdcall c_getSI() getSI +@ stdcall c_getSP() getSP +@ stdcall c_getSS() getSS +@ stdcall c_getZF() getZF + +@ stdcall c_setAF(long) setAF +@ stdcall c_setAH(long) setAH +@ stdcall c_setAL(long) setAL +@ stdcall c_setAX(long) setAX +@ stdcall c_setBH(long) setBH +@ stdcall c_setBL(long) setBL +@ stdcall c_setBP(long) setBP +@ stdcall c_setBX(long) setBX +@ stdcall c_setCF(long) setCF +@ stdcall c_setCH(long) setCH +@ stdcall c_setCL(long) setCL +@ stdcall c_setCS(long) setCS +@ stdcall c_setCX(long) setCX +@ stdcall c_setDF(long) setDF +@ stdcall c_setDH(long) setDH +@ stdcall c_setDI(long) setDI +@ stdcall c_setDL(long) setDL +@ stdcall c_setDS(long) setDS +@ stdcall c_setDX(long) setDX +@ stdcall c_setEAX(long) setEAX +@ stdcall c_setEBP(long) setEBP +@ stdcall c_setEBX(long) setEBX +@ stdcall c_setECX(long) setECX +@ stdcall c_setEDI(long) setEDI +@ stdcall c_setEDX(long) setEDX +@ stdcall c_setEIP(long) setEIP +@ stdcall c_setES(long) setES +@ stdcall c_setESI(long) setESI +@ stdcall c_setESP(long) setESP +@ stdcall c_setFS(long) setFS +@ stdcall c_setGS(long) setGS +@ stdcall c_setIF(long) setIF +@ stdcall c_setIP(long) setIP +@ stdcall c_setMSW(long) setMSW +@ stdcall c_setOF(long) setOF +@ stdcall c_setPF(long) setPF +@ stdcall c_setSF(long) setSF +@ stdcall c_setSI(long) setSI +@ stdcall c_setSP(long) setSP +@ stdcall c_setSS(long) setSS +@ stdcall c_setZF(long) setZF + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; NTVDM DOS-32 Emulation exports ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +@ stdcall demClientErrorEx(long long long) +@ stdcall demFileDelete(ptr) +@ stdcall demFileFindFirst(ptr ptr long) +@ stdcall demFileFindNext(ptr) +;@ stdcall demGetFileTimeByHandle_WOW +@ stdcall demGetPhysicalDriveType(long) +@ stdcall demIsShortPathName(ptr long) +;@ stdcall demLFNCleanup +;@ stdcall demLFNGetCurrentDirectory +@ stdcall demSetCurrentDirectoryGetDrive(ptr ptr) +;@ stdcall demWOWLFNAllocateSearchHandle +;@ stdcall demWOWLFNCloseSearchHandle +;@ stdcall demWOWLFNEntry +;@ stdcall demWOWLFNGetSearchHandle +;@ stdcall demWOWLFNInit + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; NTVDM Miscellaneous exports ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +@ stdcall MGetVdmPointer(long long long) +@ stdcall Sim32pGetVDMPointer(long long) + +;@ stdcall VdmFlushCache(long long long long) ; Not exported on x86 +@ stdcall VdmMapFlat(long long long) +;@ stdcall VdmUnmapFlat(long long ptr long) ; Not exported on x86 + +@ stdcall call_ica_hw_interrupt(long long long) +@ stdcall VDDInstallIOHook(long long ptr ptr) +@ stdcall VDDDeInstallIOHook(long long ptr) + +@ stdcall VDDSimulate16() +@ stdcall host_simulate() VDDSimulate16 +@ stdcall VDDTerminateVDM() diff --git a/subsystems/ntvdm/registers.c b/subsystems/ntvdm/registers.c new file mode 100644 index 00000000000..d3d5ce16675 --- /dev/null +++ b/subsystems/ntvdm/registers.c @@ -0,0 +1,683 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: registers.c + * PURPOSE: Exported functions for manipulating registers + * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" + +/* PUBLIC FUNCTIONS ***********************************************************/ + +static inline BOOLEAN EmulatorGetFlag(ULONG Flag) +{ + return (EmulatorContext.Flags.Long & Flag) ? TRUE : FALSE; +} + +static inline VOID EmulatorSetFlag(ULONG Flag) +{ + EmulatorContext.Flags.Long |= Flag; +} + +static inline VOID EmulatorClearFlag(ULONG Flag) +{ + EmulatorContext.Flags.Long &= ~Flag; +} + +VOID EmulatorSetStack(WORD Segment, DWORD Offset) +{ + Fast486SetStack(&EmulatorContext, Segment, Offset); +} + + + +PVOID +WINAPI +getIntelRegistersPointer(VOID) +{ + UNIMPLEMENTED; + return NULL; +} + +ULONG +WINAPI +getEAX(VOID) +{ + return EmulatorContext.GeneralRegs[FAST486_REG_EAX].Long; +} + +VOID +WINAPI +setEAX(ULONG Value) +{ + EmulatorContext.GeneralRegs[FAST486_REG_EAX].Long = Value; +} + +USHORT +WINAPI +getAX(VOID) +{ + return EmulatorContext.GeneralRegs[FAST486_REG_EAX].LowWord; +} + +VOID +WINAPI +setAX(USHORT Value) +{ + EmulatorContext.GeneralRegs[FAST486_REG_EAX].LowWord = Value; +} + +UCHAR +WINAPI +getAH(VOID) +{ + return EmulatorContext.GeneralRegs[FAST486_REG_EAX].HighByte; +} + +VOID +WINAPI +setAH(UCHAR Value) +{ + EmulatorContext.GeneralRegs[FAST486_REG_EAX].HighByte = Value; +} + +UCHAR +WINAPI +getAL(VOID) +{ + return EmulatorContext.GeneralRegs[FAST486_REG_EAX].LowByte; +} + +VOID +WINAPI +setAL(UCHAR Value) +{ + EmulatorContext.GeneralRegs[FAST486_REG_EAX].LowByte = Value; +} + +ULONG +WINAPI +getEBX(VOID) +{ + return EmulatorContext.GeneralRegs[FAST486_REG_EBX].Long; +} + +VOID +WINAPI +setEBX(ULONG Value) +{ + EmulatorContext.GeneralRegs[FAST486_REG_EBX].Long = Value; +} + +USHORT +WINAPI +getBX(VOID) +{ + return EmulatorContext.GeneralRegs[FAST486_REG_EBX].LowWord; +} + +VOID +WINAPI +setBX(USHORT Value) +{ + EmulatorContext.GeneralRegs[FAST486_REG_EBX].LowWord = Value; +} + +UCHAR +WINAPI +getBH(VOID) +{ + return EmulatorContext.GeneralRegs[FAST486_REG_EBX].HighByte; +} + +VOID +WINAPI +setBH(UCHAR Value) +{ + EmulatorContext.GeneralRegs[FAST486_REG_EBX].HighByte = Value; +} + +UCHAR +WINAPI +getBL(VOID) +{ + return EmulatorContext.GeneralRegs[FAST486_REG_EBX].LowByte; +} + +VOID +WINAPI +setBL(UCHAR Value) +{ + EmulatorContext.GeneralRegs[FAST486_REG_EBX].LowByte = Value; +} + + + +ULONG +WINAPI +getECX(VOID) +{ + return EmulatorContext.GeneralRegs[FAST486_REG_ECX].Long; +} + +VOID +WINAPI +setECX(ULONG Value) +{ + EmulatorContext.GeneralRegs[FAST486_REG_ECX].Long = Value; +} + +USHORT +WINAPI +getCX(VOID) +{ + return EmulatorContext.GeneralRegs[FAST486_REG_ECX].LowWord; +} + +VOID +WINAPI +setCX(USHORT Value) +{ + EmulatorContext.GeneralRegs[FAST486_REG_ECX].LowWord = Value; +} + +UCHAR +WINAPI +getCH(VOID) +{ + return EmulatorContext.GeneralRegs[FAST486_REG_ECX].HighByte; +} + +VOID +WINAPI +setCH(UCHAR Value) +{ + EmulatorContext.GeneralRegs[FAST486_REG_ECX].HighByte = Value; +} + +UCHAR +WINAPI +getCL(VOID) +{ + return EmulatorContext.GeneralRegs[FAST486_REG_ECX].LowByte; +} + +VOID +WINAPI +setCL(UCHAR Value) +{ + EmulatorContext.GeneralRegs[FAST486_REG_ECX].LowByte = Value; +} + + + +ULONG +WINAPI +getEDX(VOID) +{ + return EmulatorContext.GeneralRegs[FAST486_REG_EDX].Long; +} + +VOID +WINAPI +setEDX(ULONG Value) +{ + EmulatorContext.GeneralRegs[FAST486_REG_EDX].Long = Value; +} + +USHORT +WINAPI +getDX(VOID) +{ + return EmulatorContext.GeneralRegs[FAST486_REG_EDX].LowWord; +} + +VOID +WINAPI +setDX(USHORT Value) +{ + EmulatorContext.GeneralRegs[FAST486_REG_EDX].LowWord = Value; +} + +UCHAR +WINAPI +getDH(VOID) +{ + return EmulatorContext.GeneralRegs[FAST486_REG_EDX].HighByte; +} + +VOID +WINAPI +setDH(UCHAR Value) +{ + EmulatorContext.GeneralRegs[FAST486_REG_EDX].HighByte = Value; +} + +UCHAR +WINAPI +getDL(VOID) +{ + return EmulatorContext.GeneralRegs[FAST486_REG_EDX].LowByte; +} + +VOID +WINAPI +setDL(UCHAR Value) +{ + EmulatorContext.GeneralRegs[FAST486_REG_EDX].LowByte = Value; +} + + + +ULONG +WINAPI +getESP(VOID) +{ + return EmulatorContext.GeneralRegs[FAST486_REG_ESP].Long; +} + +VOID +WINAPI +setESP(ULONG Value) +{ + EmulatorSetStack(getSS(), Value); +} + +USHORT +WINAPI +getSP(VOID) +{ + return EmulatorContext.GeneralRegs[FAST486_REG_ESP].LowWord; +} + +VOID +WINAPI +setSP(USHORT Value) +{ + EmulatorSetStack(getSS(), Value); +} + + + +ULONG +WINAPI +getEBP(VOID) +{ + return EmulatorContext.GeneralRegs[FAST486_REG_EBP].Long; +} + +VOID +WINAPI +setEBP(ULONG Value) +{ + EmulatorContext.GeneralRegs[FAST486_REG_EBP].Long = Value; +} + +USHORT +WINAPI +getBP(VOID) +{ + return EmulatorContext.GeneralRegs[FAST486_REG_EBP].LowWord; +} + +VOID +WINAPI +setBP(USHORT Value) +{ + EmulatorContext.GeneralRegs[FAST486_REG_EBP].LowWord = Value; +} + + + +ULONG +WINAPI +getESI(VOID) +{ + return EmulatorContext.GeneralRegs[FAST486_REG_ESI].Long; +} + +VOID +WINAPI +setESI(ULONG Value) +{ + EmulatorContext.GeneralRegs[FAST486_REG_ESI].Long = Value; +} + +USHORT +WINAPI +getSI(VOID) +{ + return EmulatorContext.GeneralRegs[FAST486_REG_ESI].LowWord; +} + +VOID +WINAPI +setSI(USHORT Value) +{ + EmulatorContext.GeneralRegs[FAST486_REG_ESI].LowWord = Value; +} + + + +ULONG +WINAPI +getEDI(VOID) +{ + return EmulatorContext.GeneralRegs[FAST486_REG_EDI].Long; +} + +VOID +WINAPI +setEDI(ULONG Value) +{ + EmulatorContext.GeneralRegs[FAST486_REG_EDI].Long = Value; +} + +USHORT +WINAPI +getDI(VOID) +{ + return EmulatorContext.GeneralRegs[FAST486_REG_EDI].LowWord; +} + +VOID +WINAPI +setDI(USHORT Value) +{ + EmulatorContext.GeneralRegs[FAST486_REG_EDI].LowWord = Value; +} + + + +ULONG +WINAPI +getEIP(VOID) +{ + return EmulatorContext.InstPtr.Long; +} + +VOID +WINAPI +setEIP(ULONG Value) +{ + EmulatorExecute(getCS(), Value); +} + +USHORT +WINAPI +getIP(VOID) +{ + return EmulatorContext.InstPtr.LowWord; +} + +VOID +WINAPI +setIP(USHORT Value) +{ + EmulatorExecute(getCS(), Value); +} + + + +USHORT +WINAPI +getCS(VOID) +{ + return EmulatorContext.SegmentRegs[FAST486_REG_CS].Selector; +} + +VOID +WINAPI +setCS(USHORT Value) +{ + Fast486SetSegment(&EmulatorContext, FAST486_REG_CS, Value); +} + +USHORT +WINAPI +getSS(VOID) +{ + return EmulatorContext.SegmentRegs[FAST486_REG_SS].Selector; +} + +VOID +WINAPI +setSS(USHORT Value) +{ + Fast486SetSegment(&EmulatorContext, FAST486_REG_SS, Value); +} + +USHORT +WINAPI +getDS(VOID) +{ + return EmulatorContext.SegmentRegs[FAST486_REG_DS].Selector; +} + +VOID +WINAPI +setDS(USHORT Value) +{ + Fast486SetSegment(&EmulatorContext, FAST486_REG_DS, Value); +} + +USHORT +WINAPI +getES(VOID) +{ + return EmulatorContext.SegmentRegs[FAST486_REG_ES].Selector; +} + +VOID +WINAPI +setES(USHORT Value) +{ + Fast486SetSegment(&EmulatorContext, FAST486_REG_ES, Value); +} + +USHORT +WINAPI +getFS(VOID) +{ + return EmulatorContext.SegmentRegs[FAST486_REG_FS].Selector; +} + +VOID +WINAPI +setFS(USHORT Value) +{ + Fast486SetSegment(&EmulatorContext, FAST486_REG_FS, Value); +} + +USHORT +WINAPI +getGS(VOID) +{ + return EmulatorContext.SegmentRegs[FAST486_REG_GS].Selector; +} + +VOID +WINAPI +setGS(USHORT Value) +{ + Fast486SetSegment(&EmulatorContext, FAST486_REG_GS, Value); +} + + + +ULONG +WINAPI +getCF(VOID) +{ + return EmulatorGetFlag(EMULATOR_FLAG_CF); +} + +VOID +WINAPI +setCF(ULONG Flag) +{ + if (Flag & 1) + EmulatorSetFlag(EMULATOR_FLAG_CF); + else + EmulatorClearFlag(EMULATOR_FLAG_CF); +} + +ULONG +WINAPI +getPF(VOID) +{ + return EmulatorGetFlag(EMULATOR_FLAG_PF); +} + +VOID +WINAPI +setPF(ULONG Flag) +{ + if (Flag & 1) + EmulatorSetFlag(EMULATOR_FLAG_PF); + else + EmulatorClearFlag(EMULATOR_FLAG_PF); +} + +ULONG +WINAPI +getAF(VOID) +{ + return EmulatorGetFlag(EMULATOR_FLAG_AF); +} + +VOID +WINAPI +setAF(ULONG Flag) +{ + if (Flag & 1) + EmulatorSetFlag(EMULATOR_FLAG_AF); + else + EmulatorClearFlag(EMULATOR_FLAG_AF); +} + +ULONG +WINAPI +getZF(VOID) +{ + return EmulatorGetFlag(EMULATOR_FLAG_ZF); +} + +VOID +WINAPI +setZF(ULONG Flag) +{ + if (Flag & 1) + EmulatorSetFlag(EMULATOR_FLAG_ZF); + else + EmulatorClearFlag(EMULATOR_FLAG_ZF); +} + +ULONG +WINAPI +getSF(VOID) +{ + return EmulatorGetFlag(EMULATOR_FLAG_SF); +} + +VOID +WINAPI +setSF(ULONG Flag) +{ + if (Flag & 1) + EmulatorSetFlag(EMULATOR_FLAG_SF); + else + EmulatorClearFlag(EMULATOR_FLAG_SF); +} + +ULONG +WINAPI +getIF(VOID) +{ + return EmulatorGetFlag(EMULATOR_FLAG_IF); +} + +VOID +WINAPI +setIF(ULONG Flag) +{ + if (Flag & 1) + EmulatorSetFlag(EMULATOR_FLAG_IF); + else + EmulatorClearFlag(EMULATOR_FLAG_IF); +} + +ULONG +WINAPI +getDF(VOID) +{ + return EmulatorGetFlag(EMULATOR_FLAG_DF); +} + +VOID +WINAPI +setDF(ULONG Flag) +{ + if (Flag & 1) + EmulatorSetFlag(EMULATOR_FLAG_DF); + else + EmulatorClearFlag(EMULATOR_FLAG_DF); +} + +ULONG +WINAPI +getOF(VOID) +{ + return EmulatorGetFlag(EMULATOR_FLAG_OF); +} + +VOID +WINAPI +setOF(ULONG Flag) +{ + if (Flag & 1) + EmulatorSetFlag(EMULATOR_FLAG_OF); + else + EmulatorClearFlag(EMULATOR_FLAG_OF); +} + + + +ULONG +WINAPI +getEFLAGS(VOID) +{ + return EmulatorContext.Flags.Long; +} + +VOID +WINAPI +setEFLAGS(ULONG Flags) +{ + EmulatorContext.Flags.Long = Flags; +} + + + +USHORT +WINAPI +getMSW(VOID) +{ + return LOWORD(EmulatorContext.ControlRegisters[FAST486_REG_CR0]); +} + +VOID +WINAPI +setMSW(USHORT Value) +{ + /* Set the lower 16 bits (Machine Status Word) of CR0 */ + EmulatorContext.ControlRegisters[FAST486_REG_CR0] &= 0xFFFF0000; + EmulatorContext.ControlRegisters[FAST486_REG_CR0] |= Value & 0xFFFF; +} + +/* EOF */ diff --git a/subsystems/ntvdm/registers.h b/subsystems/ntvdm/registers.h new file mode 100644 index 00000000000..09568f3b7a8 --- /dev/null +++ b/subsystems/ntvdm/registers.h @@ -0,0 +1,123 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: registers.c + * PURPOSE: Exported functions for manipulating registers + * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +#ifndef _REGISTERS_H_ +#define _REGISTERS_H_ + +/* INCLUDES *******************************************************************/ + +VOID EmulatorSetStack(WORD Segment, DWORD Offset); + +#if 0 // Those function prototypes are already included via ddk/vddsvc.h + +PVOID WINAPI getIntelRegistersPointer(VOID); + +ULONG WINAPI getEAX(VOID); +VOID WINAPI setEAX(ULONG); +USHORT WINAPI getAX(VOID); +VOID WINAPI setAX(USHORT); +UCHAR WINAPI getAH(VOID); +VOID WINAPI setAH(UCHAR); +UCHAR WINAPI getAL(VOID); +VOID WINAPI setAL(UCHAR); + +ULONG WINAPI getEBX(VOID); +VOID WINAPI setEBX(ULONG); +USHORT WINAPI getBX(VOID); +VOID WINAPI setBX(USHORT); +UCHAR WINAPI getBH(VOID); +VOID WINAPI setBH(UCHAR); +UCHAR WINAPI getBL(VOID); +VOID WINAPI setBL(UCHAR); + +ULONG WINAPI getECX(VOID); +VOID WINAPI setECX(ULONG); +USHORT WINAPI getCX(VOID); +VOID WINAPI setCX(USHORT); +UCHAR WINAPI getCH(VOID); +VOID WINAPI setCH(UCHAR); +UCHAR WINAPI getCL(VOID); +VOID WINAPI setCL(UCHAR); + +ULONG WINAPI getEDX(VOID); +VOID WINAPI setEDX(ULONG); +USHORT WINAPI getDX(VOID); +VOID WINAPI setDX(USHORT); +UCHAR WINAPI getDH(VOID); +VOID WINAPI setDH(UCHAR); +UCHAR WINAPI getDL(VOID); +VOID WINAPI setDL(UCHAR); + + + +ULONG WINAPI getESP(VOID); +VOID WINAPI setESP(ULONG); +USHORT WINAPI getSP(VOID); +VOID WINAPI setSP(USHORT); + +ULONG WINAPI getEBP(VOID); +VOID WINAPI setEBP(ULONG); +USHORT WINAPI getBP(VOID); +VOID WINAPI setBP(USHORT); + +ULONG WINAPI getESI(VOID); +VOID WINAPI setESI(ULONG); +USHORT WINAPI getSI(VOID); +VOID WINAPI setSI(USHORT); + +ULONG WINAPI getEDI(VOID); +VOID WINAPI setEDI(ULONG); +USHORT WINAPI getDI(VOID); +VOID WINAPI setDI(USHORT); + +ULONG WINAPI getEIP(VOID); +VOID WINAPI setEIP(ULONG); +USHORT WINAPI getIP(VOID); +VOID WINAPI setIP(USHORT); + +USHORT WINAPI getCS(VOID); +VOID WINAPI setCS(USHORT); +USHORT WINAPI getSS(VOID); +VOID WINAPI setSS(USHORT); +USHORT WINAPI getDS(VOID); +VOID WINAPI setDS(USHORT); +USHORT WINAPI getES(VOID); +VOID WINAPI setES(USHORT); +USHORT WINAPI getFS(VOID); +VOID WINAPI setFS(USHORT); +USHORT WINAPI getGS(VOID); +VOID WINAPI setGS(USHORT); + +ULONG WINAPI getCF(VOID); +VOID WINAPI setCF(ULONG); +ULONG WINAPI getPF(VOID); +VOID WINAPI setPF(ULONG); +ULONG WINAPI getAF(VOID); +VOID WINAPI setAF(ULONG); +ULONG WINAPI getZF(VOID); +VOID WINAPI setZF(ULONG); +ULONG WINAPI getSF(VOID); +VOID WINAPI setSF(ULONG); +ULONG WINAPI getIF(VOID); +VOID WINAPI setIF(ULONG); +ULONG WINAPI getDF(VOID); +VOID WINAPI setDF(ULONG); +ULONG WINAPI getOF(VOID); +VOID WINAPI setOF(ULONG); + +ULONG WINAPI getEFLAGS(VOID); +VOID WINAPI setEFLAGS(ULONG); + +USHORT WINAPI getMSW(VOID); +VOID WINAPI setMSW(USHORT); + +#endif + +#endif // _REGISTERS_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/res/ntvdm.ico b/subsystems/ntvdm/res/ntvdm.ico new file mode 100644 index 00000000000..161c1b07a9a Binary files /dev/null and b/subsystems/ntvdm/res/ntvdm.ico differ diff --git a/subsystems/ntvdm/resource.h b/subsystems/ntvdm/resource.h index e7572adbb7b..f7a6f3c2a1b 100644 --- a/subsystems/ntvdm/resource.h +++ b/subsystems/ntvdm/resource.h @@ -1,5 +1,14 @@ #pragma once -#define RC_STRING_MAX_SIZE 2048 -#define STRING_WelcomeMsg 100 -#define STRING_PromptMsg 101 +#define ID_SHOWHIDE_MOUSE 1000 +#define ID_VDM_QUIT 1001 + +#define IDS_HIDE_MOUSE 100 +#define IDS_SHOW_MOUSE 101 +#define IDS_VDM_MENU 102 + +#define IDS_VDM_QUIT 200 + +#define IDI_APPICON 1 + +/* EOF */ diff --git a/subsystems/ntvdm/utils.c b/subsystems/ntvdm/utils.c new file mode 100644 index 00000000000..0619376ee98 --- /dev/null +++ b/subsystems/ntvdm/utils.c @@ -0,0 +1,87 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: utils.c + * PURPOSE: Utility Functions + * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" + +/* PRIVATE FUNCTIONS **********************************************************/ + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID +FileClose(IN HANDLE FileHandle) +{ + CloseHandle(FileHandle); +} + +HANDLE +FileOpen(IN PCSTR FileName, + OUT PULONG FileSize OPTIONAL) +{ + HANDLE hFile; + ULONG ulFileSize; + + /* Open the file */ + SetLastError(0); // For debugging purposes + hFile = CreateFileA(FileName, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + DPRINT1("File '%s' opening %s ; GetLastError() = %u\n", + FileName, hFile != INVALID_HANDLE_VALUE ? "succeeded" : "failed", GetLastError()); + + /* If we failed, bail out */ + if (hFile == INVALID_HANDLE_VALUE) return NULL; + + /* OK, we have a handle to the file */ + + /* + * Retrieve the size of the file. In NTVDM we will handle files + * of maximum 1Mb so we can largely use GetFileSize only. + */ + ulFileSize = GetFileSize(hFile, NULL); + if (ulFileSize == INVALID_FILE_SIZE && GetLastError() != ERROR_SUCCESS) + { + /* We failed, bail out */ + DPRINT1("Error when retrieving file size, or size too large (%d)\n", ulFileSize); + FileClose(hFile); + return NULL; + } + + /* Success, return file handle and size if needed */ + if (FileSize) *FileSize = ulFileSize; + return hFile; +} + +BOOLEAN +FileLoadByHandle(IN HANDLE FileHandle, + IN PVOID Location, + IN ULONG FileSize, + OUT PULONG BytesRead) +{ + BOOLEAN Success; + + /* Attempt to load the file into memory */ + SetLastError(0); // For debugging purposes + Success = !!ReadFile(FileHandle, + Location, // REAL_TO_PHYS(LocationRealPtr), + FileSize, + BytesRead, + NULL); + DPRINT1("File loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError()); + + return Success; +} + +/* EOF */ diff --git a/subsystems/ntvdm/utils.h b/subsystems/ntvdm/utils.h new file mode 100644 index 00000000000..98ce0936a96 --- /dev/null +++ b/subsystems/ntvdm/utils.h @@ -0,0 +1,33 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: utils.h + * PURPOSE: Utility Functions + * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +#ifndef _UTILS_H_ +#define _UTILS_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" + +/* FUNCTIONS ******************************************************************/ + +VOID +FileClose(IN HANDLE FileHandle); + +HANDLE +FileOpen(IN PCSTR FileName, + OUT PULONG FileSize OPTIONAL); + +BOOLEAN +FileLoadByHandle(IN HANDLE FileHandle, + IN PVOID Location, + IN ULONG FileSize, + OUT PULONG BytesRead); + +#endif // _UTILS_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/vddsup.c b/subsystems/ntvdm/vddsup.c new file mode 100644 index 00000000000..92a0ff1ac3b --- /dev/null +++ b/subsystems/ntvdm/vddsup.c @@ -0,0 +1,358 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: vddsup.c + * PURPOSE: Virtual Device Drivers (VDD) Support + * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "vddsup.h" + +#include "bop.h" + +#include + +typedef VOID (WINAPI *VDD_PROC)(VOID); + +typedef struct _VDD_MODULE +{ + HMODULE hDll; + VDD_PROC DispatchRoutine; +} VDD_MODULE, *PVDD_MODULE; + +/* PRIVATE VARIABLES **********************************************************/ + +// TODO: Maybe use a linked list. +// But the number of elements must be <= MAXUSHORT (MAXWORD) +#define MAX_VDD_MODULES 0xFF + 1 +VDD_MODULE VDDList[MAX_VDD_MODULES] = {{NULL}}; + +// Valid handles of VDD DLLs start at 1 and finish at MAX_VDD_MODULES +#define ENTRY_TO_HANDLE(Entry) ((Entry) + 1) +#define HANDLE_TO_ENTRY(Handle) ((Handle) - 1) +#define IS_VALID_HANDLE(Handle) ((Handle) > 0 && (Handle) <= MAX_VDD_MODULES) + +/* PRIVATE FUNCTIONS **********************************************************/ + +USHORT GetNextFreeVDDEntry(VOID) +{ + USHORT Entry = MAX_VDD_MODULES; + for (Entry = 0; Entry < sizeof(VDDList)/sizeof(VDDList[0]); ++Entry) + { + if (VDDList[Entry].hDll == NULL) break; + } + return Entry; +} + +VOID WINAPI ThirdPartyVDDBop(LPWORD Stack) +{ + /* Get the Function Number and skip it */ + BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP()); + setIP(getIP() + 1); + + switch (FuncNum) + { + /* RegisterModule */ + case 0: + { + BOOL Success = TRUE; + WORD RetVal = 0; + WORD Entry = 0; + LPCSTR DllName = NULL, + InitRoutineName = NULL, + DispatchRoutineName = NULL; + HMODULE hDll = NULL; + VDD_PROC InitRoutine = NULL, + DispatchRoutine = NULL; + + DPRINT("RegisterModule() called\n"); + + /* Clear the Carry Flag (no error happened so far) */ + setCF(0); + + /* Retrieve the next free entry in the table (used later on) */ + Entry = GetNextFreeVDDEntry(); + if (Entry >= MAX_VDD_MODULES) + { + DPRINT1("Failed to create a new VDD module entry\n"); + Success = FALSE; + RetVal = 4; + goto Quit; + } + + /* Retrieve the VDD name in DS:SI */ + DllName = (LPCSTR)SEG_OFF_TO_PTR(getDS(), getSI()); + + /* Retrieve the initialization routine API name in ES:DI (optional --> ES=DI=0) */ + if (TO_LINEAR(getES(), getDI()) != 0) + InitRoutineName = (LPCSTR)SEG_OFF_TO_PTR(getES(), getDI()); + + /* Retrieve the dispatch routine API name in DS:BX */ + DispatchRoutineName = (LPCSTR)SEG_OFF_TO_PTR(getDS(), getBX()); + + DPRINT1("DllName = '%s' - InitRoutineName = '%s' - DispatchRoutineName = '%s'\n", + (DllName ? DllName : "n/a"), + (InitRoutineName ? InitRoutineName : "n/a"), + (DispatchRoutineName ? DispatchRoutineName : "n/a")); + + /* Load the VDD DLL */ + hDll = LoadLibraryA(DllName); + if (hDll == NULL) + { + DWORD LastError = GetLastError(); + Success = FALSE; + + if (LastError == ERROR_NOT_ENOUGH_MEMORY) + { + DPRINT1("Not enough memory to load DLL '%s'\n", DllName); + RetVal = 4; + goto Quit; + } + else + { + DPRINT1("Failed to load DLL '%s'; last error = %d\n", DllName, LastError); + RetVal = 1; + goto Quit; + } + } + + /* Load the initialization routine if needed */ + if (InitRoutineName) + { + InitRoutine = (VDD_PROC)GetProcAddress(hDll, InitRoutineName); + if (InitRoutine == NULL) + { + DPRINT1("Failed to load the initialization routine '%s'\n", InitRoutineName); + Success = FALSE; + RetVal = 3; + goto Quit; + } + } + + /* Load the dispatch routine */ + DispatchRoutine = (VDD_PROC)GetProcAddress(hDll, DispatchRoutineName); + if (DispatchRoutine == NULL) + { + DPRINT1("Failed to load the dispatch routine '%s'\n", DispatchRoutineName); + Success = FALSE; + RetVal = 2; + goto Quit; + } + + /* If we arrived there, that means everything is OK */ + + /* Register the VDD DLL */ + VDDList[Entry].hDll = hDll; + VDDList[Entry].DispatchRoutine = DispatchRoutine; + + /* Call the initialization routine if needed */ + if (InitRoutine) InitRoutine(); + + /* We succeeded. RetVal will contain a valid VDD DLL handle */ + Success = TRUE; + RetVal = ENTRY_TO_HANDLE(Entry); // Convert the entry to a valid handle + +Quit: + if (!Success) + { + /* Unload the VDD DLL */ + if (hDll) FreeLibrary(hDll); + + /* Set the Carry Flag to indicate that an error happened */ + setCF(1); + } + // else + // { + // /* Clear the Carry Flag (success) */ + // setCF(0); + // } + setAX(RetVal); + break; + } + + /* UnRegisterModule */ + case 1: + { + WORD Handle = getAX(); + WORD Entry = HANDLE_TO_ENTRY(Handle); // Convert the handle to a valid entry + + DPRINT("UnRegisterModule() called\n"); + + /* Sanity checks */ + if (!IS_VALID_HANDLE(Handle) || VDDList[Entry].hDll == NULL) + { + DPRINT1("Invalid VDD DLL Handle: %d\n", Entry); + /* Stop the VDM */ + EmulatorTerminate(); + return; + } + + /* Unregister the VDD DLL */ + FreeLibrary(VDDList[Entry].hDll); + VDDList[Entry].hDll = NULL; + VDDList[Entry].DispatchRoutine = NULL; + break; + } + + /* DispatchCall */ + case 2: + { + WORD Handle = getAX(); + WORD Entry = HANDLE_TO_ENTRY(Handle); // Convert the handle to a valid entry + + DPRINT("DispatchCall() called\n"); + + /* Sanity checks */ + if (!IS_VALID_HANDLE(Handle) || + VDDList[Entry].hDll == NULL || + VDDList[Entry].DispatchRoutine == NULL) + { + DPRINT1("Invalid VDD DLL Handle: %d\n", Entry); + /* Stop the VDM */ + EmulatorTerminate(); + return; + } + + /* Call the dispatch routine */ + VDDList[Entry].DispatchRoutine(); + break; + } + + default: + { + DPRINT1("Unknown 3rd-party VDD BOP Function: 0x%02X\n", FuncNum); + setCF(1); + break; + } + } +} + +BOOL LoadInstallableVDD(VOID) +{ +#define ERROR_MEMORYVDD L"Insufficient memory to load installable Virtual Device Drivers." +#define ERROR_REGVDD L"Virtual Device Driver format in the registry is invalid." +#define ERROR_LOADVDD L"An installable Virtual Device Driver failed Dll initialization." + + BOOL Success = TRUE; + LONG Error = 0; + DWORD Type = 0; + DWORD BufSize = 0; + + HKEY hVDDKey; + LPCWSTR VDDKeyName = L"SYSTEM\\CurrentControlSet\\Control\\VirtualDeviceDrivers"; + LPWSTR VDDValueName = L"VDD"; + LPWSTR VDDList = NULL; + + HANDLE hVDD; + + /* Try to open the VDD registry key */ + Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + VDDKeyName, + 0, + KEY_QUERY_VALUE, + &hVDDKey); + if (Error == ERROR_FILE_NOT_FOUND) + { + /* If the key just doesn't exist, don't do anything else */ + return TRUE; + } + else if (Error != ERROR_SUCCESS) + { + /* The key exists but there was an access error: display an error and quit */ + DisplayMessage(ERROR_REGVDD); + return FALSE; + } + + /* + * Retrieve the size of the VDD registry value + * and check that it's of REG_MULTI_SZ type. + */ + Error = RegQueryValueExW(hVDDKey, + VDDValueName, + NULL, + &Type, + NULL, + &BufSize); + if (Error == ERROR_FILE_NOT_FOUND) + { + /* If the value just doesn't exist, don't do anything else */ + Success = TRUE; + goto Quit; + } + else if (Error != ERROR_SUCCESS || Type != REG_MULTI_SZ) + { + /* + * The value exists but there was an access error or + * is of the wrong type: display an error and quit. + */ + DisplayMessage(ERROR_REGVDD); + Success = FALSE; + goto Quit; + } + + /* Allocate the buffer */ + BufSize = (BufSize < 2*sizeof(WCHAR) ? 2*sizeof(WCHAR) : BufSize); + VDDList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, BufSize); + if (VDDList == NULL) + { + DisplayMessage(ERROR_MEMORYVDD); + Success = FALSE; + goto Quit; + } + + /* Retrieve the list of VDDs to load */ + if (RegQueryValueExW(hVDDKey, + VDDValueName, + NULL, + NULL, + (LPBYTE)VDDList, + &BufSize) != ERROR_SUCCESS) + { + DisplayMessage(ERROR_REGVDD); + Success = FALSE; + goto Quit; + } + + /* Load the VDDs */ + VDDValueName = VDDList; + while (*VDDList) + { + DPRINT1("Loading VDD '%S'...", VDDList); + hVDD = LoadLibraryW(VDDList); + if (hVDD == NULL) + { + DbgPrint("Failed\n"); + DisplayMessage(ERROR_LOADVDD); + } + else + { + DbgPrint("Succeeded\n"); + } + /* Go to next string */ + VDDList += wcslen(VDDList) + 1; + } + VDDList = VDDValueName; + +Quit: + if (VDDList) HeapFree(GetProcessHeap(), 0, VDDList); + RegCloseKey(hVDDKey); + return Success; +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID VDDSupInitialize(VOID) +{ + /* Register the 3rd-party VDD BOP Handler */ + RegisterBop(BOP_3RDPARTY, ThirdPartyVDDBop); + + /* Load the installable VDDs from the registry */ + LoadInstallableVDD(); +} + +/* EOF */ diff --git a/subsystems/ntvdm/vddsup.h b/subsystems/ntvdm/vddsup.h new file mode 100644 index 00000000000..4de9178a3ea --- /dev/null +++ b/subsystems/ntvdm/vddsup.h @@ -0,0 +1,20 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: vddsup.h + * PURPOSE: Virtual Device Drivers (VDD) Support + * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +#ifndef _VDDSUP_H_ +#define _VDDSUP_H_ + +/* DEFINES ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +VOID VDDSupInitialize(VOID); + +#endif // _VDDSUP_H_ + +/* EOF */ diff --git a/subsystems/win/basesrv/basesrv.h b/subsystems/win/basesrv/basesrv.h index 66e4efcdcf4..881156d2a30 100644 --- a/subsystems/win/basesrv/basesrv.h +++ b/subsystems/win/basesrv/basesrv.h @@ -22,6 +22,7 @@ #include #include #include +#include /* PSEH for SEH Support */ #include diff --git a/subsystems/win/basesrv/init.c b/subsystems/win/basesrv/init.c index 49e9485304c..ef98ed3f6ff 100644 --- a/subsystems/win/basesrv/init.c +++ b/subsystems/win/basesrv/init.c @@ -9,6 +9,7 @@ /* INCLUDES *******************************************************************/ #include "basesrv.h" +#include "vdm.h" #include @@ -569,6 +570,14 @@ BaseInitializeStaticServerData(IN PCSR_SERVER_DLL LoadedServerDll) LoadedServerDll->SharedSection = BaseStaticServerData; } +VOID +NTAPI +BaseSrvDisconnect(PCSR_PROCESS Process) +{ + /* Cleanup the VDM console records */ + BaseSrvCleanupVdmRecords(HandleToUlong(Process->ClientId.UniqueProcess)); +} + CSR_SERVER_DLL_INIT(ServerDllInitialization) { /* Setup the DLL Object */ @@ -581,7 +590,7 @@ CSR_SERVER_DLL_INIT(ServerDllInitialization) #endif LoadedServerDll->SizeOfProcessData = 0; LoadedServerDll->ConnectCallback = NULL; - LoadedServerDll->DisconnectCallback = NULL; + LoadedServerDll->DisconnectCallback = BaseSrvDisconnect; LoadedServerDll->ShutdownProcessCallback = NULL; BaseSrvDllInstance = LoadedServerDll->ServerHandle; @@ -591,6 +600,9 @@ CSR_SERVER_DLL_INIT(ServerDllInitialization) /* Initialize DOS devices management */ BaseInitDefineDosDevice(); + /* Initialize VDM support */ + BaseInitializeVDM(); + /* All done */ return STATUS_SUCCESS; } diff --git a/subsystems/win/basesrv/proc.c b/subsystems/win/basesrv/proc.c index e61405c0f0e..53113f7edda 100644 --- a/subsystems/win/basesrv/proc.c +++ b/subsystems/win/basesrv/proc.c @@ -9,6 +9,7 @@ /* INCLUDES *******************************************************************/ #include "basesrv.h" +#include "vdm.h" #define NDEBUG #include @@ -167,7 +168,30 @@ CSR_API(BaseSrvCreateProcess) /* FIXME: Should notify user32 */ - /* FIXME: VDM vodoo */ + /* Check if this is a VDM process */ + if (CreateProcessRequest->VdmBinaryType) + { + PVDM_CONSOLE_RECORD ConsoleRecord; + + if (CreateProcessRequest->VdmTask != 0) + { + /* Get the console record using the task ID */ + Status = GetConsoleRecordBySessionId(CreateProcessRequest->VdmTask, + &ConsoleRecord); + } + else + { + /* Get the console record using the console handle */ + Status = BaseSrvGetConsoleRecord(CreateProcessRequest->hVDM, + &ConsoleRecord); + } + + /* Check if it failed */ + if (!NT_SUCCESS(Status)) return Status; + + /* Store the process ID of the VDM in the console record */ + ConsoleRecord->ProcessId = HandleToUlong(CreateProcessRequest->ClientId.UniqueProcess); + } /* Return the result of this operation */ return Status; diff --git a/subsystems/win/basesrv/vdm.c b/subsystems/win/basesrv/vdm.c index 2ac45655e8e..782918c48ce 100644 --- a/subsystems/win/basesrv/vdm.c +++ b/subsystems/win/basesrv/vdm.c @@ -4,69 +4,1330 @@ * FILE: subsystems/win/basesrv/vdm.c * PURPOSE: Virtual DOS Machines (VDM) Support * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr) + * Aleksandar Andrejevic */ /* INCLUDES *******************************************************************/ #include "basesrv.h" +#include "vdm.h" #define NDEBUG #include +/* GLOBALS ********************************************************************/ + +BOOLEAN FirstVDM = TRUE; +LIST_ENTRY VDMConsoleListHead; +RTL_CRITICAL_SECTION DosCriticalSection; +RTL_CRITICAL_SECTION WowCriticalSection; + +/* FUNCTIONS ******************************************************************/ + +NTSTATUS NTAPI BaseSrvGetConsoleRecord(HANDLE ConsoleHandle, PVDM_CONSOLE_RECORD *Record) +{ + PLIST_ENTRY i; + PVDM_CONSOLE_RECORD CurrentRecord = NULL; + + /* NULL is not a valid console handle */ + if (ConsoleHandle == NULL) return STATUS_INVALID_PARAMETER; + + /* Search for a record that has the same console handle */ + for (i = VDMConsoleListHead.Flink; i != &VDMConsoleListHead; i = i->Flink) + { + CurrentRecord = CONTAINING_RECORD(i, VDM_CONSOLE_RECORD, Entry); + if (CurrentRecord->ConsoleHandle == ConsoleHandle) break; + } + + /* Check if nothing was found */ + if (i == &VDMConsoleListHead) CurrentRecord = NULL; + + *Record = CurrentRecord; + return CurrentRecord ? STATUS_SUCCESS : STATUS_NOT_FOUND; +} + +NTSTATUS NTAPI GetConsoleRecordBySessionId(ULONG TaskId, PVDM_CONSOLE_RECORD *Record) +{ + PLIST_ENTRY i; + PVDM_CONSOLE_RECORD CurrentRecord = NULL; + + /* Search for a record that has the same console handle */ + for (i = VDMConsoleListHead.Flink; i != &VDMConsoleListHead; i = i->Flink) + { + CurrentRecord = CONTAINING_RECORD(i, VDM_CONSOLE_RECORD, Entry); + if (CurrentRecord->SessionId == TaskId) break; + } + + /* Check if nothing was found */ + if (i == &VDMConsoleListHead) CurrentRecord = NULL; + + *Record = CurrentRecord; + return CurrentRecord ? STATUS_SUCCESS : STATUS_NOT_FOUND; +} + +ULONG NTAPI GetNextDosSesId(VOID) +{ + ULONG SessionId; + PLIST_ENTRY i; + PVDM_CONSOLE_RECORD CurrentRecord = NULL; + BOOLEAN Found; + + /* Search for an available session ID */ + for (SessionId = 1; SessionId != 0; SessionId++) + { + Found = FALSE; + + /* Check if the ID is already in use */ + for (i = VDMConsoleListHead.Flink; i != &VDMConsoleListHead; i = i->Flink) + { + CurrentRecord = CONTAINING_RECORD(i, VDM_CONSOLE_RECORD, Entry); + if (CurrentRecord->SessionId == SessionId) Found = TRUE; + } + + /* If not, we found one */ + if (!Found) break; + } + + ASSERT(SessionId != 0); + + /* Return the session ID */ + return SessionId; +} + +BOOLEAN NTAPI BaseSrvIsVdmAllowed(VOID) +{ + NTSTATUS Status; + BOOLEAN VdmAllowed = TRUE; + HANDLE RootKey, KeyHandle; + UNICODE_STRING KeyName, ValueName, MachineKeyName; + OBJECT_ATTRIBUTES Attributes; + UCHAR ValueBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)]; + PKEY_VALUE_PARTIAL_INFORMATION ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer; + ULONG ActualSize; + + /* Initialize the unicode strings */ + RtlInitUnicodeString(&MachineKeyName, L"\\Registry\\Machine"); + RtlInitUnicodeString(&KeyName, VDM_POLICY_KEY_NAME); + RtlInitUnicodeString(&ValueName, VDM_DISALLOWED_VALUE_NAME); + + InitializeObjectAttributes(&Attributes, + &MachineKeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + /* Open the local machine key */ + Status = NtOpenKey(&RootKey, KEY_READ, &Attributes); + if (!NT_SUCCESS(Status)) return FALSE; + + InitializeObjectAttributes(&Attributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + RootKey, + NULL); + + /* Open the policy key in the local machine hive, if it exists */ + if (NT_SUCCESS(NtOpenKey(&KeyHandle, KEY_READ, &Attributes))) + { + /* Read the value, if it's set */ + if (NT_SUCCESS(NtQueryValueKey(KeyHandle, + &ValueName, + KeyValuePartialInformation, + ValueInfo, + sizeof(ValueBuffer), + &ActualSize))) + { + if (*((PULONG)ValueInfo->Data)) + { + /* The VDM has been disabled in the registry */ + VdmAllowed = FALSE; + } + } + + NtClose(KeyHandle); + } + + /* Close the local machine key */ + NtClose(RootKey); + + /* If it's disabled system-wide, there's no need to check the user key */ + if (!VdmAllowed) return FALSE; + + /* Open the current user key of the client */ + if (!CsrImpersonateClient(NULL)) return VdmAllowed; + Status = RtlOpenCurrentUser(KEY_READ, &RootKey); + CsrRevertToSelf(); + + /* If that fails, return the system-wide setting */ + if (!NT_SUCCESS(Status)) return VdmAllowed; + + InitializeObjectAttributes(&Attributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + RootKey, + NULL); + + /* Open the policy key in the current user hive, if it exists */ + if (NT_SUCCESS(NtOpenKey(&KeyHandle, KEY_READ, &Attributes))) + { + /* Read the value, if it's set */ + if (NT_SUCCESS(NtQueryValueKey(KeyHandle, + &ValueName, + KeyValuePartialInformation, + ValueInfo, + sizeof(ValueBuffer), + &ActualSize))) + { + if (*((PULONG)ValueInfo->Data)) + { + /* The VDM has been disabled in the registry */ + VdmAllowed = FALSE; + } + } + + NtClose(KeyHandle); + } + + return VdmAllowed; +} + +NTSTATUS NTAPI BaseSrvCreatePairWaitHandles(PHANDLE ServerEvent, PHANDLE ClientEvent) +{ + NTSTATUS Status; + + /* Create the event */ + Status = NtCreateEvent(ServerEvent, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE); + if (!NT_SUCCESS(Status)) return Status; + + /* Duplicate the event into the client process */ + Status = NtDuplicateObject(NtCurrentProcess(), + *ServerEvent, + CsrGetClientThread()->Process->ProcessHandle, + ClientEvent, + 0, + 0, + DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_SAME_ACCESS); + + if (!NT_SUCCESS(Status)) NtClose(*ServerEvent); + return Status; +} + +VOID NTAPI BaseSrvFreeVDMInfo(PVDM_COMMAND_INFO CommandInfo) +{ + /* Free the allocated structure members */ + if (CommandInfo->CmdLine != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->CmdLine); + if (CommandInfo->AppName != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->AppName); + if (CommandInfo->PifFile != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->PifFile); + if (CommandInfo->CurDirectory != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->CurDirectory); + if (CommandInfo->Env != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->Env); + if (CommandInfo->Desktop != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->Desktop); + if (CommandInfo->Title != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->Title); + if (CommandInfo->Reserved != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->Reserved); + + /* Free the structure itself */ + RtlFreeHeap(BaseSrvHeap, 0, CommandInfo); +} + +VOID NTAPI BaseSrvCleanupVdmRecords(ULONG ProcessId) +{ + PLIST_ENTRY i; + PVDM_CONSOLE_RECORD ConsoleRecord = NULL; + PVDM_DOS_RECORD DosRecord; + + /* Enter the critical section */ + RtlEnterCriticalSection(&DosCriticalSection); + + /* Search for a record that has the same process handle */ + for (i = VDMConsoleListHead.Flink; i != &VDMConsoleListHead; i = i->Flink) + { + ConsoleRecord = CONTAINING_RECORD(i, VDM_CONSOLE_RECORD, Entry); + + if (ConsoleRecord->ProcessId == ProcessId) + { + /* Cleanup the DOS records */ + while (ConsoleRecord->DosListHead.Flink != &ConsoleRecord->DosListHead) + { + DosRecord = CONTAINING_RECORD(ConsoleRecord->DosListHead.Flink, + VDM_DOS_RECORD, + Entry); + + /* Set the event and close it */ + NtSetEvent(DosRecord->ServerEvent, NULL); + NtClose(DosRecord->ServerEvent); + + /* Remove the DOS entry */ + if (DosRecord->CommandInfo) BaseSrvFreeVDMInfo(DosRecord->CommandInfo); + RemoveEntryList(&DosRecord->Entry); + RtlFreeHeap(BaseSrvHeap, 0, DosRecord); + } + + if (ConsoleRecord->CurrentDirs != NULL) + { + /* Free the current directories */ + RtlFreeHeap(BaseSrvHeap, 0, ConsoleRecord->CurrentDirs); + ConsoleRecord->CurrentDirs = NULL; + ConsoleRecord->CurDirsLength = 0; + } + + /* Close the process handle */ + if (ConsoleRecord->ProcessHandle) NtClose(ConsoleRecord->ProcessHandle); + + /* Close the event handle */ + if (ConsoleRecord->ServerEvent) NtClose(ConsoleRecord->ServerEvent); + + /* Remove the console record */ + i = i->Blink; + RemoveEntryList(&ConsoleRecord->Entry); + RtlFreeHeap(BaseSrvHeap, 0, ConsoleRecord); + } + } + + /* Leave the critical section */ + RtlLeaveCriticalSection(&DosCriticalSection); +} + +BOOLEAN NTAPI BaseSrvCopyCommand(PBASE_CHECK_VDM CheckVdmRequest, PVDM_DOS_RECORD DosRecord) +{ + BOOLEAN Success = FALSE; + PVDM_COMMAND_INFO CommandInfo = NULL; + + /* Allocate the command information structure */ + CommandInfo = (PVDM_COMMAND_INFO)RtlAllocateHeap(BaseSrvHeap, + HEAP_ZERO_MEMORY, + sizeof(VDM_COMMAND_INFO)); + if (CommandInfo == NULL) return FALSE; + + /* Fill the structure */ + CommandInfo->TaskId = CheckVdmRequest->iTask; + CommandInfo->ExitCode = DosRecord->ExitCode; + CommandInfo->CodePage = CheckVdmRequest->CodePage; + CommandInfo->StdIn = CheckVdmRequest->StdIn; + CommandInfo->StdOut = CheckVdmRequest->StdOut; + CommandInfo->StdErr = CheckVdmRequest->StdErr; + + /* Allocate memory for the command line */ + CommandInfo->CmdLine = RtlAllocateHeap(BaseSrvHeap, + HEAP_ZERO_MEMORY, + CheckVdmRequest->CmdLen); + if (CommandInfo->CmdLine == NULL) goto Cleanup; + + /* Copy the command line */ + RtlMoveMemory(CommandInfo->CmdLine, CheckVdmRequest->CmdLine, CheckVdmRequest->CmdLen); + + /* Allocate memory for the application name */ + CommandInfo->AppName = RtlAllocateHeap(BaseSrvHeap, + HEAP_ZERO_MEMORY, + CheckVdmRequest->AppLen); + if (CommandInfo->AppName == NULL) goto Cleanup; + + /* Copy the application name */ + RtlMoveMemory(CommandInfo->AppName, CheckVdmRequest->AppName, CheckVdmRequest->AppLen); + + /* Allocate memory for the PIF file name */ + if (CheckVdmRequest->PifLen != 0) + { + CommandInfo->PifFile = RtlAllocateHeap(BaseSrvHeap, + HEAP_ZERO_MEMORY, + CheckVdmRequest->PifLen); + if (CommandInfo->PifFile == NULL) goto Cleanup; + + /* Copy the PIF file name */ + RtlMoveMemory(CommandInfo->PifFile, CheckVdmRequest->PifFile, CheckVdmRequest->PifLen); + } + else CommandInfo->PifFile = NULL; + + /* Allocate memory for the current directory */ + if (CheckVdmRequest->CurDirectoryLen != 0) + { + CommandInfo->CurDirectory = RtlAllocateHeap(BaseSrvHeap, + HEAP_ZERO_MEMORY, + CheckVdmRequest->CurDirectoryLen); + if (CommandInfo->CurDirectory == NULL) goto Cleanup; + + /* Copy the current directory */ + RtlMoveMemory(CommandInfo->CurDirectory, + CheckVdmRequest->CurDirectory, + CheckVdmRequest->CurDirectoryLen); + } + else CommandInfo->CurDirectory = NULL; + + /* Allocate memory for the environment block */ + CommandInfo->Env = RtlAllocateHeap(BaseSrvHeap, + HEAP_ZERO_MEMORY, + CheckVdmRequest->EnvLen); + if (CommandInfo->Env == NULL) goto Cleanup; + + /* Copy the environment block */ + RtlMoveMemory(CommandInfo->Env, CheckVdmRequest->Env, CheckVdmRequest->EnvLen); + + CommandInfo->EnvLen = CheckVdmRequest->EnvLen; + RtlMoveMemory(&CommandInfo->StartupInfo, + CheckVdmRequest->StartupInfo, + sizeof(STARTUPINFOA)); + + /* Allocate memory for the desktop */ + if (CheckVdmRequest->DesktopLen != 0) + { + CommandInfo->Desktop = RtlAllocateHeap(BaseSrvHeap, + HEAP_ZERO_MEMORY, + CheckVdmRequest->DesktopLen); + if (CommandInfo->Desktop == NULL) goto Cleanup; + + /* Copy the desktop name */ + RtlMoveMemory(CommandInfo->Desktop, CheckVdmRequest->Desktop, CheckVdmRequest->DesktopLen); + } + else CommandInfo->Desktop = NULL; + + CommandInfo->DesktopLen = CheckVdmRequest->DesktopLen; + + /* Allocate memory for the title */ + if (CheckVdmRequest->TitleLen != 0) + { + CommandInfo->Title = RtlAllocateHeap(BaseSrvHeap, + HEAP_ZERO_MEMORY, + CheckVdmRequest->TitleLen); + if (CommandInfo->Title == NULL) goto Cleanup; + + /* Copy the title */ + RtlMoveMemory(CommandInfo->Title, CheckVdmRequest->Title, CheckVdmRequest->TitleLen); + } + else CommandInfo->Title = NULL; + + CommandInfo->TitleLen = CheckVdmRequest->TitleLen; + + /* Allocate memory for the reserved field */ + if (CheckVdmRequest->ReservedLen != 0) + { + CommandInfo->Reserved = RtlAllocateHeap(BaseSrvHeap, + HEAP_ZERO_MEMORY, + CheckVdmRequest->ReservedLen); + if (CommandInfo->Reserved == NULL) goto Cleanup; + + /* Copy the reserved field */ + RtlMoveMemory(CommandInfo->Reserved, + CheckVdmRequest->Reserved, + CheckVdmRequest->ReservedLen); + } + else CommandInfo->Reserved = NULL; + + CommandInfo->ReservedLen = CheckVdmRequest->ReservedLen; + + CommandInfo->CmdLen = CheckVdmRequest->CmdLen; + CommandInfo->AppLen = CheckVdmRequest->AppLen; + CommandInfo->PifLen = CheckVdmRequest->PifLen; + CommandInfo->CurDirectoryLen = CheckVdmRequest->CurDirectoryLen; + CommandInfo->VDMState = DosRecord->State; + // TODO: Set CommandInfo->CurrentDrive + // TODO: Set CommandInfo->ComingFromBat + + /* Set the DOS record's command structure */ + DosRecord->CommandInfo = CommandInfo; + + /* The operation was successful */ + Success = TRUE; + +Cleanup: + /* If it wasn't successful, free the memory */ + if (!Success) BaseSrvFreeVDMInfo(CommandInfo); + + return Success; +} + +NTSTATUS NTAPI BaseSrvFillCommandInfo(PVDM_COMMAND_INFO CommandInfo, + PBASE_GET_NEXT_VDM_COMMAND Message) +{ + /* Copy the data */ + Message->iTask = CommandInfo->TaskId; + Message->StdIn = CommandInfo->StdIn; + Message->StdOut = CommandInfo->StdOut; + Message->StdErr = CommandInfo->StdErr; + Message->CodePage = CommandInfo->CodePage; + Message->dwCreationFlags = CommandInfo->CreationFlags; + Message->ExitCode = CommandInfo->ExitCode; + Message->CurrentDrive = CommandInfo->CurrentDrive; + Message->VDMState = CommandInfo->VDMState; + Message->fComingFromBat = CommandInfo->ComingFromBat; + + if (CommandInfo->CmdLen && Message->CmdLen) + { + if (Message->CmdLen < CommandInfo->CmdLen) return STATUS_BUFFER_TOO_SMALL; + + /* Copy the command line */ + RtlMoveMemory(Message->CmdLine, CommandInfo->CmdLine, CommandInfo->CmdLen); + Message->CmdLen = CommandInfo->CmdLen; + } + + if (CommandInfo->AppLen && Message->AppLen) + { + if (Message->AppLen < CommandInfo->CmdLen) return STATUS_BUFFER_TOO_SMALL; + + /* Copy the application name */ + RtlMoveMemory(Message->AppName, CommandInfo->AppName, CommandInfo->AppLen); + Message->AppLen = CommandInfo->AppLen; + } + + if (CommandInfo->PifLen && Message->PifLen) + { + if (Message->PifLen < CommandInfo->PifLen) return STATUS_BUFFER_TOO_SMALL; + + /* Copy the PIF file name */ + RtlMoveMemory(Message->PifFile, CommandInfo->PifFile, CommandInfo->PifLen); + Message->PifLen = CommandInfo->PifLen; + } + + if (CommandInfo->CurDirectoryLen && Message->CurDirectoryLen) + { + if (Message->CurDirectoryLen < CommandInfo->CurDirectoryLen) return STATUS_BUFFER_TOO_SMALL; + + /* Copy the current directory */ + RtlMoveMemory(Message->CurDirectory, CommandInfo->CurDirectory, CommandInfo->CurDirectoryLen); + Message->CurDirectoryLen = CommandInfo->CurDirectoryLen; + } + + if (CommandInfo->EnvLen && Message->EnvLen) + { + if (Message->EnvLen < CommandInfo->EnvLen) return STATUS_BUFFER_TOO_SMALL; + + /* Copy the environment */ + RtlMoveMemory(Message->Env, CommandInfo->Env, CommandInfo->EnvLen); + Message->EnvLen = CommandInfo->EnvLen; + } + + /* Copy the startup info */ + RtlMoveMemory(Message->StartupInfo, + &CommandInfo->StartupInfo, + sizeof(STARTUPINFOA)); + + if (CommandInfo->DesktopLen && Message->DesktopLen) + { + if (Message->DesktopLen < CommandInfo->DesktopLen) return STATUS_BUFFER_TOO_SMALL; + + /* Copy the desktop name */ + RtlMoveMemory(Message->Desktop, CommandInfo->Desktop, CommandInfo->DesktopLen); + Message->DesktopLen = CommandInfo->DesktopLen; + } + + if (CommandInfo->TitleLen && Message->TitleLen) + { + if (Message->TitleLen < CommandInfo->TitleLen) return STATUS_BUFFER_TOO_SMALL; + + /* Copy the title */ + RtlMoveMemory(Message->Title, CommandInfo->Title, CommandInfo->TitleLen); + Message->TitleLen = CommandInfo->TitleLen; + } + + if (CommandInfo->ReservedLen && Message->ReservedLen) + { + if (Message->ReservedLen < CommandInfo->ReservedLen) return STATUS_BUFFER_TOO_SMALL; + + /* Copy the reserved parameter */ + RtlMoveMemory(Message->Reserved, CommandInfo->Reserved, CommandInfo->ReservedLen); + Message->ReservedLen = CommandInfo->ReservedLen; + } + + return STATUS_SUCCESS; +} + +VOID NTAPI BaseInitializeVDM(VOID) +{ + /* Initialize the list head */ + InitializeListHead(&VDMConsoleListHead); + + /* Initialize the critical section */ + RtlInitializeCriticalSection(&DosCriticalSection); + RtlInitializeCriticalSection(&WowCriticalSection); +} + /* PUBLIC SERVER APIS *********************************************************/ CSR_API(BaseSrvCheckVDM) { - DPRINT1("%s not yet implemented\n", __FUNCTION__); - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + PBASE_CHECK_VDM CheckVdmRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.CheckVDMRequest; + PRTL_CRITICAL_SECTION CriticalSection = NULL; + PVDM_CONSOLE_RECORD ConsoleRecord = NULL; + PVDM_DOS_RECORD DosRecord = NULL; + BOOLEAN NewConsoleRecord = FALSE; + + /* Don't do anything if the VDM has been disabled in the registry */ + if (!BaseSrvIsVdmAllowed()) return STATUS_ACCESS_DENIED; + + /* Validate the message buffers */ + if (!CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&CheckVdmRequest->CmdLine, + CheckVdmRequest->CmdLen, + sizeof(*CheckVdmRequest->CmdLine)) + || !CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&CheckVdmRequest->AppName, + CheckVdmRequest->AppLen, + sizeof(*CheckVdmRequest->AppName)) + || !CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&CheckVdmRequest->PifFile, + CheckVdmRequest->PifLen, + sizeof(*CheckVdmRequest->PifFile)) + || !CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&CheckVdmRequest->CurDirectory, + CheckVdmRequest->CurDirectoryLen, + sizeof(*CheckVdmRequest->CurDirectory)) + || !CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&CheckVdmRequest->Desktop, + CheckVdmRequest->DesktopLen, + sizeof(*CheckVdmRequest->Desktop)) + || !CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&CheckVdmRequest->Title, + CheckVdmRequest->TitleLen, + sizeof(*CheckVdmRequest->Title)) + || !CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&CheckVdmRequest->Reserved, + CheckVdmRequest->ReservedLen, + sizeof(*CheckVdmRequest->Reserved))) + { + return STATUS_INVALID_PARAMETER; + } + + CriticalSection = (CheckVdmRequest->BinaryType != BINARY_TYPE_SEPARATE_WOW) + ? &DosCriticalSection + : &WowCriticalSection; + + /* Enter the critical section */ + RtlEnterCriticalSection(CriticalSection); + + /* Check if this is a DOS or WOW VDM */ + if (CheckVdmRequest->BinaryType != BINARY_TYPE_SEPARATE_WOW) + { + /* Get the console record */ + Status = BaseSrvGetConsoleRecord(CheckVdmRequest->ConsoleHandle, + &ConsoleRecord); + + if (!NT_SUCCESS(Status)) + { + /* Allocate a new console record */ + ConsoleRecord = (PVDM_CONSOLE_RECORD)RtlAllocateHeap(BaseSrvHeap, + HEAP_ZERO_MEMORY, + sizeof(VDM_CONSOLE_RECORD)); + if (ConsoleRecord == NULL) + { + Status = STATUS_NO_MEMORY; + goto Cleanup; + } + + /* Remember that the console record was allocated here */ + NewConsoleRecord = TRUE; + + /* Initialize the console record */ + ConsoleRecord->ConsoleHandle = CheckVdmRequest->ConsoleHandle; + ConsoleRecord->ProcessHandle = NULL; + ConsoleRecord->ServerEvent = ConsoleRecord->ClientEvent = NULL; + ConsoleRecord->ReenterCount = 0; + ConsoleRecord->CurrentDirs = NULL; + ConsoleRecord->CurDirsLength = 0; + ConsoleRecord->SessionId = GetNextDosSesId(); + InitializeListHead(&ConsoleRecord->DosListHead); + } + + /* Allocate a new DOS record */ + DosRecord = (PVDM_DOS_RECORD)RtlAllocateHeap(BaseSrvHeap, + HEAP_ZERO_MEMORY, + sizeof(VDM_DOS_RECORD)); + if (DosRecord == NULL) + { + Status = STATUS_NO_MEMORY; + goto Cleanup; + } + + /* Initialize the DOS record */ + DosRecord->State = VDM_NOT_LOADED; + DosRecord->ExitCode = 0; + + Status = BaseSrvCreatePairWaitHandles(&DosRecord->ServerEvent, &DosRecord->ClientEvent); + if (!NT_SUCCESS(Status)) goto Cleanup; + + /* Return the client event handle */ + CheckVdmRequest->WaitObjectForParent = DosRecord->ClientEvent; + + /* Translate the input structure into a VDM command structure and set it in the DOS record */ + if (!BaseSrvCopyCommand(CheckVdmRequest, DosRecord)) + { + /* The only possibility is that an allocation failure occurred */ + Status = STATUS_NO_MEMORY; + goto Cleanup; + } + + /* Add the DOS record */ + InsertHeadList(&ConsoleRecord->DosListHead, &DosRecord->Entry); + + if (ConsoleRecord->ServerEvent) + { + /* Signal the session event */ + NtSetEvent(ConsoleRecord->ServerEvent, NULL); + } + + if (NewConsoleRecord) + { + /* Add the console record */ + InsertTailList(&VDMConsoleListHead, &ConsoleRecord->Entry); + } + + if (ConsoleRecord->ConsoleHandle == NULL) + { + /* The parent doesn't have a console, so return the session ID */ + CheckVdmRequest->iTask = ConsoleRecord->SessionId; + } + else CheckVdmRequest->iTask = 0; + + CheckVdmRequest->VDMState = NewConsoleRecord ? VDM_NOT_LOADED : VDM_READY; + Status = STATUS_SUCCESS; + } + else + { + // TODO: NOT IMPLEMENTED + UNIMPLEMENTED; + Status = STATUS_NOT_IMPLEMENTED; + } + +Cleanup: + /* Check if it failed */ + if (!NT_SUCCESS(Status)) + { + /* Free the DOS record */ + if (DosRecord != NULL) + { + if (DosRecord->ServerEvent) NtClose(DosRecord->ServerEvent); + if (DosRecord->ClientEvent) + { + /* Close the remote handle */ + NtDuplicateObject(CsrGetClientThread()->Process->ProcessHandle, + DosRecord->ClientEvent, + NULL, + NULL, + 0, + 0, + DUPLICATE_CLOSE_SOURCE); + } + + RtlFreeHeap(BaseSrvHeap, 0, DosRecord); + DosRecord = NULL; + } + + /* Free the console record if it was allocated here */ + if (NewConsoleRecord) + { + RtlFreeHeap(BaseSrvHeap, 0, ConsoleRecord); + ConsoleRecord = NULL; + } + } + + /* Leave the critical section */ + RtlLeaveCriticalSection(CriticalSection); + + return Status; } CSR_API(BaseSrvUpdateVDMEntry) { - DPRINT1("%s not yet implemented\n", __FUNCTION__); - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + PBASE_UPDATE_VDM_ENTRY UpdateVdmEntryRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.UpdateVDMEntryRequest; + PRTL_CRITICAL_SECTION CriticalSection = NULL; + PVDM_CONSOLE_RECORD ConsoleRecord = NULL; + PVDM_DOS_RECORD DosRecord = NULL; + + CriticalSection = (UpdateVdmEntryRequest->BinaryType != BINARY_TYPE_SEPARATE_WOW) + ? &DosCriticalSection + : &WowCriticalSection; + + /* Enter the critical section */ + RtlEnterCriticalSection(CriticalSection); + + /* Check if this is a DOS or WOW VDM */ + if (UpdateVdmEntryRequest->BinaryType != BINARY_TYPE_SEPARATE_WOW) + { + if (UpdateVdmEntryRequest->iTask != 0) + { + /* Get the console record using the task ID */ + Status = GetConsoleRecordBySessionId(UpdateVdmEntryRequest->iTask, + &ConsoleRecord); + } + else + { + /* Get the console record using the console handle */ + Status = BaseSrvGetConsoleRecord(UpdateVdmEntryRequest->ConsoleHandle, + &ConsoleRecord); + } + + if (!NT_SUCCESS(Status)) goto Cleanup; + + /* Get the primary DOS record */ + DosRecord = (PVDM_DOS_RECORD)CONTAINING_RECORD(ConsoleRecord->DosListHead.Flink, + VDM_DOS_RECORD, + Entry); + + switch (UpdateVdmEntryRequest->EntryIndex) + { + case VdmEntryUndo: + { + /* Close the server event handle, the client will close the client handle */ + NtClose(DosRecord->ServerEvent); + DosRecord->ServerEvent = DosRecord->ClientEvent = NULL; + + if (UpdateVdmEntryRequest->VDMCreationState & (VDM_UNDO_PARTIAL | VDM_UNDO_FULL)) + { + /* Remove the DOS record */ + if (DosRecord->CommandInfo) BaseSrvFreeVDMInfo(DosRecord->CommandInfo); + RemoveEntryList(&DosRecord->Entry); + RtlFreeHeap(BaseSrvHeap, 0, DosRecord); + + /* + * Since this is an undo, if that was the only DOS record the VDM + * won't even start, so the console record should be removed too. + */ + if (ConsoleRecord->DosListHead.Flink == &ConsoleRecord->DosListHead) + { + if (ConsoleRecord->ProcessHandle) NtClose(ConsoleRecord->ProcessHandle); + if (ConsoleRecord->ServerEvent) NtClose(ConsoleRecord->ServerEvent); + RemoveEntryList(&ConsoleRecord->Entry); + RtlFreeHeap(BaseSrvHeap, 0, ConsoleRecord); + } + } + + /* It was successful */ + Status = STATUS_SUCCESS; + + break; + } + + case VdmEntryUpdateProcess: + { + /* Duplicate the VDM process handle */ + Status = NtDuplicateObject(CsrGetClientThread()->Process->ProcessHandle, + UpdateVdmEntryRequest->VDMProcessHandle, + NtCurrentProcess(), + &ConsoleRecord->ProcessHandle, + 0, + 0, + DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_SAME_ACCESS); + if (!NT_SUCCESS(Status)) goto Cleanup; + + /* Create a pair of handles to one event object */ + Status = BaseSrvCreatePairWaitHandles(&DosRecord->ServerEvent, + &DosRecord->ClientEvent); + if (!NT_SUCCESS(Status)) goto Cleanup; + + /* Return the client event handle */ + UpdateVdmEntryRequest->WaitObjectForParent = DosRecord->ClientEvent; + + break; + } + + case VdmEntryUpdateControlCHandler: + { + // TODO: NOT IMPLEMENTED + DPRINT1("BaseSrvUpdateVDMEntry: VdmEntryUpdateControlCHandler not implemented!"); + Status = STATUS_NOT_IMPLEMENTED; + + break; + } + + default: + { + /* Invalid */ + Status = STATUS_INVALID_PARAMETER; + } + } + } + else + { + // TODO: NOT IMPLEMENTED + UNIMPLEMENTED; + Status = STATUS_NOT_IMPLEMENTED; + } + +Cleanup: + /* Leave the critical section */ + RtlLeaveCriticalSection(CriticalSection); + + return Status; } CSR_API(BaseSrvGetNextVDMCommand) { - DPRINT1("%s not yet implemented\n", __FUNCTION__); - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + PBASE_GET_NEXT_VDM_COMMAND GetNextVdmCommandRequest = + &((PBASE_API_MESSAGE)ApiMessage)->Data.GetNextVDMCommandRequest; + PRTL_CRITICAL_SECTION CriticalSection; + PLIST_ENTRY i = NULL; + PVDM_CONSOLE_RECORD ConsoleRecord = NULL; + PVDM_DOS_RECORD DosRecord = NULL; + + /* Validate the message buffers */ + if (!CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&GetNextVdmCommandRequest->CmdLine, + GetNextVdmCommandRequest->CmdLen, + sizeof(*GetNextVdmCommandRequest->CmdLine)) + || !CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&GetNextVdmCommandRequest->AppName, + GetNextVdmCommandRequest->AppLen, + sizeof(*GetNextVdmCommandRequest->AppName)) + || !CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&GetNextVdmCommandRequest->PifFile, + GetNextVdmCommandRequest->PifLen, + sizeof(*GetNextVdmCommandRequest->PifFile)) + || !CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&GetNextVdmCommandRequest->CurDirectory, + GetNextVdmCommandRequest->CurDirectoryLen, + sizeof(*GetNextVdmCommandRequest->CurDirectory)) + || !CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&GetNextVdmCommandRequest->Env, + GetNextVdmCommandRequest->EnvLen, + sizeof(*GetNextVdmCommandRequest->Env)) + || !CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&GetNextVdmCommandRequest->Desktop, + GetNextVdmCommandRequest->DesktopLen, + sizeof(*GetNextVdmCommandRequest->Desktop)) + || !CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&GetNextVdmCommandRequest->Title, + GetNextVdmCommandRequest->TitleLen, + sizeof(*GetNextVdmCommandRequest->Title)) + || !CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&GetNextVdmCommandRequest->Reserved, + GetNextVdmCommandRequest->ReservedLen, + sizeof(*GetNextVdmCommandRequest->Reserved)) + || !CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&GetNextVdmCommandRequest->StartupInfo, + 1, + sizeof(STARTUPINFOA))) + { + return STATUS_INVALID_PARAMETER; + } + + CriticalSection = (GetNextVdmCommandRequest->VDMState & VDM_FLAG_WOW) + ? &WowCriticalSection + : &DosCriticalSection; + + /* Enter the critical section */ + RtlEnterCriticalSection(CriticalSection); + + if (!(GetNextVdmCommandRequest->VDMState & VDM_FLAG_WOW)) + { + if (GetNextVdmCommandRequest->iTask != 0) + { + /* Get the console record using the task ID */ + Status = GetConsoleRecordBySessionId(GetNextVdmCommandRequest->iTask, + &ConsoleRecord); + } + else + { + /* Get the console record using the console handle */ + Status = BaseSrvGetConsoleRecord(GetNextVdmCommandRequest->ConsoleHandle, + &ConsoleRecord); + } + + /* Make sure we found the console record */ + if (!NT_SUCCESS(Status)) goto Cleanup; + + /* Return the session ID */ + GetNextVdmCommandRequest->iTask = ConsoleRecord->SessionId; + GetNextVdmCommandRequest->WaitObjectForVDM = NULL; + + if (GetNextVdmCommandRequest->VDMState & VDM_GET_FIRST_COMMAND) + { + /* Check if the DOS record list is empty */ + if (ConsoleRecord->DosListHead.Flink == &ConsoleRecord->DosListHead) + { + Status = STATUS_INVALID_PARAMETER; + goto Cleanup; + } + + /* Get the first DOS record */ + DosRecord = CONTAINING_RECORD(ConsoleRecord->DosListHead.Flink, VDM_DOS_RECORD, Entry); + + /* Make sure its command information is still there */ + if (DosRecord->CommandInfo == NULL) + { + Status = STATUS_INVALID_PARAMETER; + goto Cleanup; + } + + /* Fill the command information */ + Status = BaseSrvFillCommandInfo(DosRecord->CommandInfo, GetNextVdmCommandRequest); + goto Cleanup; + } + + /* Check if we should set the state of a running DOS record to ready */ + if (!(GetNextVdmCommandRequest->VDMState + & (VDM_FLAG_FIRST_TASK | VDM_FLAG_RETRY | VDM_FLAG_NESTED_TASK))) + { + /* Search for a DOS record that is currently running */ + for (i = ConsoleRecord->DosListHead.Flink; i != &ConsoleRecord->DosListHead; i = i->Flink) + { + DosRecord = CONTAINING_RECORD(i, VDM_DOS_RECORD, Entry); + if (DosRecord->State == VDM_NOT_READY) break; + } + + /* Check if we found any */ + if (i == &ConsoleRecord->DosListHead) + { + Status = STATUS_INVALID_PARAMETER; + goto Cleanup; + } + + /* Set the exit code */ + DosRecord->ExitCode = GetNextVdmCommandRequest->ExitCode; + + /* Update the VDM state */ + DosRecord->State = VDM_READY; + + /* Notify all waiting threads that the task is finished */ + NtSetEvent(DosRecord->ServerEvent, NULL); + NtClose(DosRecord->ServerEvent); + DosRecord->ServerEvent = NULL; + } + + /* Search for a DOS record that isn't loaded yet */ + for (i = ConsoleRecord->DosListHead.Flink; i != &ConsoleRecord->DosListHead; i = i->Flink) + { + DosRecord = CONTAINING_RECORD(i, VDM_DOS_RECORD, Entry); + if (DosRecord->State == VDM_NOT_LOADED) break; + } + + if (i != &ConsoleRecord->DosListHead) + { + /* DOS tasks which haven't been loaded yet should have a command info structure */ + ASSERT(DosRecord->CommandInfo != NULL); + + /* Check if the caller only wants environment data */ + if (GetNextVdmCommandRequest->VDMState & VDM_GET_ENVIRONMENT) + { + if (GetNextVdmCommandRequest->EnvLen < DosRecord->CommandInfo->EnvLen) + { + /* Not enough space was reserved */ + GetNextVdmCommandRequest->EnvLen = DosRecord->CommandInfo->EnvLen; + Status = STATUS_BUFFER_OVERFLOW; + goto Cleanup; + } + + /* Copy the environment data */ + RtlMoveMemory(GetNextVdmCommandRequest->Env, + DosRecord->CommandInfo->Env, + DosRecord->CommandInfo->EnvLen); + + /* Return the actual size to the caller */ + GetNextVdmCommandRequest->EnvLen = DosRecord->CommandInfo->EnvLen; + } + else + { + /* Fill the command information */ + Status = BaseSrvFillCommandInfo(DosRecord->CommandInfo, GetNextVdmCommandRequest); + + /* Free the command information, it's no longer needed */ + BaseSrvFreeVDMInfo(DosRecord->CommandInfo); + DosRecord->CommandInfo = NULL; + + /* Update the VDM state */ + GetNextVdmCommandRequest->VDMState = DosRecord->State = VDM_NOT_READY; + } + + Status = STATUS_SUCCESS; + goto Cleanup; + } + } + else + { + // TODO: WOW SUPPORT NOT IMPLEMENTED + Status = STATUS_NOT_IMPLEMENTED; + goto Cleanup; + } + + /* There is no command yet */ + if ((GetNextVdmCommandRequest->VDMState & (VDM_FLAG_DONT_WAIT | VDM_FLAG_RETRY)) + != (VDM_FLAG_DONT_WAIT | VDM_FLAG_RETRY)) + { + if (ConsoleRecord->ServerEvent) + { + /* Reset the event */ + NtResetEvent(ConsoleRecord->ServerEvent, NULL); + } + else + { + /* Create a pair of wait handles */ + Status = BaseSrvCreatePairWaitHandles(&ConsoleRecord->ServerEvent, + &ConsoleRecord->ClientEvent); + if (!NT_SUCCESS(Status)) goto Cleanup; + } + + /* Return the client event handle */ + GetNextVdmCommandRequest->WaitObjectForVDM = ConsoleRecord->ClientEvent; + } + +Cleanup: + /* Leave the critical section */ + RtlLeaveCriticalSection(CriticalSection); + + return Status; } CSR_API(BaseSrvExitVDM) { - DPRINT1("%s not yet implemented\n", __FUNCTION__); - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + PBASE_EXIT_VDM ExitVdmRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.ExitVDMRequest; + PRTL_CRITICAL_SECTION CriticalSection = NULL; + PVDM_CONSOLE_RECORD ConsoleRecord = NULL; + PVDM_DOS_RECORD DosRecord; + + CriticalSection = (ExitVdmRequest->iWowTask == 0) + ? &DosCriticalSection + : &WowCriticalSection; + + /* Enter the critical section */ + RtlEnterCriticalSection(CriticalSection); + + if (ExitVdmRequest->iWowTask == 0) + { + /* Get the console record */ + Status = BaseSrvGetConsoleRecord(ExitVdmRequest->ConsoleHandle, &ConsoleRecord); + if (!NT_SUCCESS(Status)) goto Cleanup; + + /* Cleanup the DOS records */ + while (ConsoleRecord->DosListHead.Flink != &ConsoleRecord->DosListHead) + { + DosRecord = CONTAINING_RECORD(ConsoleRecord->DosListHead.Flink, + VDM_DOS_RECORD, + Entry); + + /* Set the event and close it */ + NtSetEvent(DosRecord->ServerEvent, NULL); + NtClose(DosRecord->ServerEvent); + + /* Remove the DOS entry */ + if (DosRecord->CommandInfo) BaseSrvFreeVDMInfo(DosRecord->CommandInfo); + RemoveEntryList(&DosRecord->Entry); + RtlFreeHeap(BaseSrvHeap, 0, DosRecord); + } + + if (ConsoleRecord->CurrentDirs != NULL) + { + /* Free the current directories */ + RtlFreeHeap(BaseSrvHeap, 0, ConsoleRecord->CurrentDirs); + ConsoleRecord->CurrentDirs = NULL; + ConsoleRecord->CurDirsLength = 0; + } + + /* Close the event handle */ + if (ConsoleRecord->ServerEvent) NtClose(ConsoleRecord->ServerEvent); + + /* Remove the console record */ + RemoveEntryList(&ConsoleRecord->Entry); + RtlFreeHeap(BaseSrvHeap, 0, ConsoleRecord); + } + else + { + // TODO: NOT IMPLEMENTED + UNIMPLEMENTED; + Status = STATUS_NOT_IMPLEMENTED; + } + +Cleanup: + /* Leave the critical section */ + RtlLeaveCriticalSection(CriticalSection); + + return Status; } CSR_API(BaseSrvIsFirstVDM) { - DPRINT1("%s not yet implemented\n", __FUNCTION__); - return STATUS_NOT_IMPLEMENTED; + PBASE_IS_FIRST_VDM IsFirstVDMRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.IsFirstVDMRequest; + + /* Return the result */ + IsFirstVDMRequest->FirstVDM = FirstVDM; + + /* Clear the first VDM flag */ + FirstVDM = FALSE; + + return STATUS_SUCCESS; } CSR_API(BaseSrvGetVDMExitCode) { - DPRINT1("%s not yet implemented\n", __FUNCTION__); - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + PBASE_GET_VDM_EXIT_CODE GetVDMExitCodeRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.GetVDMExitCodeRequest; + PLIST_ENTRY i = NULL; + PVDM_CONSOLE_RECORD ConsoleRecord = NULL; + PVDM_DOS_RECORD DosRecord = NULL; + + /* Enter the critical section */ + RtlEnterCriticalSection(&DosCriticalSection); + + /* Get the console record */ + Status = BaseSrvGetConsoleRecord(GetVDMExitCodeRequest->ConsoleHandle, &ConsoleRecord); + if (!NT_SUCCESS(Status)) goto Cleanup; + + /* Search for a DOS record that has the same parent process handle */ + for (i = ConsoleRecord->DosListHead.Flink; i != &ConsoleRecord->DosListHead; i = i->Flink) + { + DosRecord = CONTAINING_RECORD(i, VDM_DOS_RECORD, Entry); + if (DosRecord->ClientEvent == GetVDMExitCodeRequest->hParent) break; + } + + /* Check if no DOS record was found */ + if (i == &ConsoleRecord->DosListHead) + { + Status = STATUS_NOT_FOUND; + goto Cleanup; + } + + /* Check if this task is still running */ + if (DosRecord->State == VDM_READY) + { + GetVDMExitCodeRequest->ExitCode = STATUS_PENDING; + goto Cleanup; + } + + /* Return the exit code */ + GetVDMExitCodeRequest->ExitCode = DosRecord->ExitCode; + + /* Since this is a zombie task record, remove it */ + if (DosRecord->CommandInfo) BaseSrvFreeVDMInfo(DosRecord->CommandInfo); + RemoveEntryList(&DosRecord->Entry); + RtlFreeHeap(BaseSrvHeap, 0, DosRecord); + +Cleanup: + /* Leave the critical section */ + RtlLeaveCriticalSection(&DosCriticalSection); + + return Status; } CSR_API(BaseSrvSetReenterCount) { - DPRINT1("%s not yet implemented\n", __FUNCTION__); - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status = STATUS_SUCCESS; + PBASE_SET_REENTER_COUNT SetReenterCountRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.SetReenterCountRequest; + PVDM_CONSOLE_RECORD ConsoleRecord; + + /* Enter the critical section */ + RtlEnterCriticalSection(&DosCriticalSection); + + /* Get the console record */ + Status = BaseSrvGetConsoleRecord(SetReenterCountRequest->ConsoleHandle, &ConsoleRecord); + if (!NT_SUCCESS(Status)) goto Cleanup; + + if (SetReenterCountRequest->fIncDec == VDM_INC_REENTER_COUNT) ConsoleRecord->ReenterCount++; + else if (SetReenterCountRequest->fIncDec == VDM_DEC_REENTER_COUNT) + { + ConsoleRecord->ReenterCount--; + if (ConsoleRecord->ServerEvent != NULL) NtSetEvent(ConsoleRecord->ServerEvent, NULL); + } + else Status = STATUS_INVALID_PARAMETER; + +Cleanup: + /* Leave the critical section */ + RtlLeaveCriticalSection(&DosCriticalSection); + + return Status; } CSR_API(BaseSrvSetVDMCurDirs) { - DPRINT1("%s not yet implemented\n", __FUNCTION__); - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.VDMCurrentDirsRequest; + PVDM_CONSOLE_RECORD ConsoleRecord; + PCHAR Buffer = NULL; + + /* Validate the input buffer */ + if (!CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&VDMCurrentDirsRequest->lpszzCurDirs, + VDMCurrentDirsRequest->cchCurDirs, + sizeof(*VDMCurrentDirsRequest->lpszzCurDirs))) + { + return STATUS_INVALID_PARAMETER; + } + + /* Enter the critical section */ + RtlEnterCriticalSection(&DosCriticalSection); + + /* Find the console record */ + Status = BaseSrvGetConsoleRecord(VDMCurrentDirsRequest->ConsoleHandle, &ConsoleRecord); + if (!NT_SUCCESS(Status)) goto Cleanup; + + if (ConsoleRecord->CurrentDirs == NULL) + { + /* Allocate memory for the current directory information */ + Buffer = RtlAllocateHeap(BaseSrvHeap, + HEAP_ZERO_MEMORY, + VDMCurrentDirsRequest->cchCurDirs); + } + else + { + /* Resize the amount of allocated memory */ + Buffer = RtlReAllocateHeap(BaseSrvHeap, + HEAP_ZERO_MEMORY, + ConsoleRecord->CurrentDirs, + VDMCurrentDirsRequest->cchCurDirs); + } + + if (Buffer == NULL) + { + /* Allocation failed */ + Status = STATUS_NO_MEMORY; + goto Cleanup; + } + + /* Update the console record */ + ConsoleRecord->CurrentDirs = Buffer; + ConsoleRecord->CurDirsLength = VDMCurrentDirsRequest->cchCurDirs; + + /* Copy the data */ + RtlMoveMemory(ConsoleRecord->CurrentDirs, + VDMCurrentDirsRequest->lpszzCurDirs, + VDMCurrentDirsRequest->cchCurDirs); + +Cleanup: + /* Leave the critical section */ + RtlLeaveCriticalSection(&DosCriticalSection); + + return Status; } CSR_API(BaseSrvGetVDMCurDirs) { - DPRINT1("%s not yet implemented\n", __FUNCTION__); - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.VDMCurrentDirsRequest; + PVDM_CONSOLE_RECORD ConsoleRecord; + + /* Validate the output buffer */ + if (!CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&VDMCurrentDirsRequest->lpszzCurDirs, + VDMCurrentDirsRequest->cchCurDirs, + sizeof(*VDMCurrentDirsRequest->lpszzCurDirs))) + { + return STATUS_INVALID_PARAMETER; + } + + /* Enter the critical section */ + RtlEnterCriticalSection(&DosCriticalSection); + + /* Find the console record */ + Status = BaseSrvGetConsoleRecord(VDMCurrentDirsRequest->ConsoleHandle, &ConsoleRecord); + if (!NT_SUCCESS(Status)) goto Cleanup; + + /* Return the actual size of the current directory information */ + VDMCurrentDirsRequest->cchCurDirs = ConsoleRecord->CurDirsLength; + + /* Check if the buffer is large enough */ + if (VDMCurrentDirsRequest->cchCurDirs < ConsoleRecord->CurDirsLength) + { + Status = STATUS_BUFFER_TOO_SMALL; + goto Cleanup; + } + + /* Copy the data */ + RtlMoveMemory(VDMCurrentDirsRequest->lpszzCurDirs, + ConsoleRecord->CurrentDirs, + ConsoleRecord->CurDirsLength); + +Cleanup: + /* Leave the critical section */ + RtlLeaveCriticalSection(&DosCriticalSection); + + return Status; } CSR_API(BaseSrvBatNotification) diff --git a/subsystems/win/basesrv/vdm.h b/subsystems/win/basesrv/vdm.h new file mode 100644 index 00000000000..3da59d90442 --- /dev/null +++ b/subsystems/win/basesrv/vdm.h @@ -0,0 +1,60 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Base API Server DLL + * FILE: subsystems/win/basesrv/vdm.h + * PURPOSE: VDM Definitions + * PROGRAMMERS: Aleksandar Andrejevic + */ + +#ifndef __VDM_H__ +#define __VDM_H__ + +#include + +/* DEFINITIONS ****************************************************************/ + +#define VDM_POLICY_KEY_NAME L"Software\\Policies\\Microsoft\\Windows\\AppCompat" +#define VDM_DISALLOWED_VALUE_NAME L"VDMDisallowed" + +typedef struct _VDM_CONSOLE_RECORD +{ + LIST_ENTRY Entry; + HANDLE ConsoleHandle; + HANDLE ProcessHandle; + HANDLE ServerEvent; + HANDLE ClientEvent; + ULONG ProcessId; + ULONG ReenterCount; + PCHAR CurrentDirs; + ULONG CurDirsLength; + ULONG SessionId; + LIST_ENTRY DosListHead; +} VDM_CONSOLE_RECORD, *PVDM_CONSOLE_RECORD; + +typedef struct _VDM_DOS_RECORD +{ + LIST_ENTRY Entry; + USHORT State; + ULONG ExitCode; + HANDLE ServerEvent; + HANDLE ClientEvent; + PVDM_COMMAND_INFO CommandInfo; +} VDM_DOS_RECORD, *PVDM_DOS_RECORD; + +/* FUNCTIONS ******************************************************************/ + +NTSTATUS NTAPI BaseSrvGetConsoleRecord(HANDLE ConsoleHandle, PVDM_CONSOLE_RECORD *Record); +NTSTATUS NTAPI GetConsoleRecordBySessionId(ULONG TaskId, PVDM_CONSOLE_RECORD *Record); +ULONG NTAPI GetNextDosSesId(VOID); +BOOLEAN NTAPI BaseSrvIsVdmAllowed(VOID); +NTSTATUS NTAPI BaseSrvCreatePairWaitHandles(PHANDLE ServerEvent, PHANDLE ClientEvent); +VOID NTAPI BaseSrvFreeVDMInfo(PVDM_COMMAND_INFO CommandInfo); +VOID NTAPI BaseSrvCleanupVdmRecords(ULONG ProcessId); +BOOLEAN NTAPI BaseSrvCopyCommand(PBASE_CHECK_VDM CheckVdmRequest, PVDM_DOS_RECORD DosRecord); +NTSTATUS NTAPI BaseSrvFillCommandInfo( + PVDM_COMMAND_INFO CommandInfo, + PBASE_GET_NEXT_VDM_COMMAND Message +); +VOID NTAPI BaseInitializeVDM(VOID); + +#endif // __VDM_H__ diff --git a/subsystems/win32/csrsrv/procsup.c b/subsystems/win32/csrsrv/procsup.c index d682c379388..451f2697d45 100644 --- a/subsystems/win32/csrsrv/procsup.c +++ b/subsystems/win32/csrsrv/procsup.c @@ -605,15 +605,18 @@ CsrCreateProcess(IN HANDLE hProcess, } /* Check if CreateProcess got CREATE_NEW_PROCESS_GROUP */ - if ((Flags & CsrProcessCreateNewGroup) == 0) + if (Flags & CsrProcessCreateNewGroup) { - /* Create new data */ + /* + * We create the process group leader of a new process group, therefore + * its process group ID and sequence number are its own ones. + */ CsrProcess->ProcessGroupId = HandleToUlong(ClientId->UniqueProcess); CsrProcess->ProcessGroupSequence = CsrProcess->SequenceNumber; } else { - /* Copy it from the current process */ + /* Inherit the process group ID and sequence number from the current process */ CsrProcess->ProcessGroupId = CurrentProcess->ProcessGroupId; CsrProcess->ProcessGroupSequence = CurrentProcess->ProcessGroupSequence; } diff --git a/win32ss/drivers/videoprt/child.c b/win32ss/drivers/videoprt/child.c index 96df9228212..bfca7069b1d 100644 --- a/win32ss/drivers/videoprt/child.c +++ b/win32ss/drivers/videoprt/child.c @@ -20,6 +20,7 @@ */ #include "videoprt.h" +#include #define NDEBUG #include @@ -33,30 +34,24 @@ IntVideoPortGetMonitorId( IN OUT PWCHAR Buffer) { USHORT Manufacturer, Model; - UNICODE_STRING UnicodeModelStr; /* This must be valid to call this function */ ASSERT(ChildExtension->EdidValid); /* 3 letters 5-bit ANSI manufacturer code (big endian) */ - Manufacturer = *(PUSHORT)(&ChildExtension->ChildDescriptor[8]); - /* Letters encoded as A=1 to Z=26 */ - Buffer[0] = (WCHAR)((Manufacturer & 0x7C00) + 'A' - 1); - Buffer[1] = (WCHAR)((Manufacturer & 0x03E0) + 'A' - 1); - Buffer[2] = (WCHAR)((Manufacturer & 0x001F) + 'A' - 1); + Manufacturer = *(PUSHORT)(&ChildExtension->ChildDescriptor[8]); /* Model number (16-bit little endian) */ Model = *(PUSHORT)(&ChildExtension->ChildDescriptor[10]); - /* Use Rtl helper for conversion */ - UnicodeModelStr.Buffer = &Buffer[3]; - UnicodeModelStr.Length = 0; - UnicodeModelStr.MaximumLength = 4 * sizeof(WCHAR); - RtlIntegerToUnicodeString(Model, 16, &UnicodeModelStr); - - /* Terminate it */ - Buffer[7] = UNICODE_NULL; + /* Convert the Monitor ID to a readable form */ + swprintf(Buffer, + L"%C%C%C%04hx", + (WCHAR)((Manufacturer >> 10 & 0x001F) + 'A' - 1), + (WCHAR)((Manufacturer >> 5 & 0x001F) + 'A' - 1), + (WCHAR)((Manufacturer & 0x001F) + 'A' - 1), + Model); /* And we're done */ return TRUE; diff --git a/win32ss/gdi/eng/engevent.c b/win32ss/gdi/eng/engevent.c index ab6e8acb48d..77b00a4006f 100644 --- a/win32ss/gdi/eng/engevent.c +++ b/win32ss/gdi/eng/engevent.c @@ -134,7 +134,7 @@ EngMapEvent( /* Create a handle, and have Ob fill out the pKEvent field */ Status = ObReferenceObjectByHandle(EngEvent, EVENT_ALL_ACCESS, - ExEventObjectType, + *ExEventObjectType, UserMode, &EngEvent->pKEvent, NULL); diff --git a/win32ss/gdi/eng/mem.c b/win32ss/gdi/eng/mem.c index 7d887b1247e..26f9aec6fc1 100644 --- a/win32ss/gdi/eng/mem.c +++ b/win32ss/gdi/eng/mem.c @@ -114,7 +114,7 @@ HackSecureVirtualMemory( else if (ProbeMode == PAGE_READWRITE) Operation = IoModifyAccess; else return NULL; - pmdl = IoAllocateMdl(Address, Size, FALSE, TRUE, NULL); + pmdl = IoAllocateMdl(Address, (ULONG)Size, FALSE, TRUE, NULL); if (pmdl == NULL) { return NULL; diff --git a/win32ss/include/ntuser.h b/win32ss/include/ntuser.h index e1ed1608429..fb39f5ab11d 100644 --- a/win32ss/include/ntuser.h +++ b/win32ss/include/ntuser.h @@ -329,7 +329,6 @@ typedef struct tagITEM INT cyBmp; /* Height " */ //// ReactOS UNICODE_STRING lpstr; - struct tagITEM *Next; } ITEM, *PITEM; typedef struct tagMENULIST @@ -369,7 +368,7 @@ typedef struct tagMENU DWORD dwArrowsOn:2; /* Arrows: 0 off, 1 on, 2 to the top, 3 to the bottom. */ //// ReactOS LIST_ENTRY ListEntry; - HWND hWnd; /* Window containing the menu */ + HWND hWnd; /* Window containing the menu, use POPUPMENU */ BOOL TimeToHide; } MENU, *PMENU; diff --git a/win32ss/user/ntuser/accelerator.c b/win32ss/user/ntuser/accelerator.c index f43ee5e152a..7777c509a24 100644 --- a/win32ss/user/ntuser/accelerator.c +++ b/win32ss/user/ntuser/accelerator.c @@ -99,7 +99,7 @@ co_IntTranslateAccelerator( /* Check if accelerator is associated with menu command */ hMenu = (Window->style & WS_CHILD) ? 0 : (HMENU)Window->IDMenu; hSubMenu = NULL; - MenuObject = IntGetMenuObject(hMenu); + MenuObject = UserGetMenuObject(hMenu); nPos = pAccel->cmd; if (MenuObject) { @@ -113,7 +113,7 @@ co_IntTranslateAccelerator( /* Check system menu now */ hMenu = Window->SystemMenu; hSubMenu = hMenu; /* system menu is a popup menu */ - MenuObject = IntGetMenuObject(hMenu); + MenuObject = UserGetMenuObject(hMenu); nPos = pAccel->cmd; if (MenuObject) { diff --git a/win32ss/user/ntuser/main.c b/win32ss/user/ntuser/main.c index 4485c5d4929..905fa04e503 100644 --- a/win32ss/user/ntuser/main.c +++ b/win32ss/user/ntuser/main.c @@ -320,7 +320,7 @@ UserCreateThreadInfo(struct _ETHREAD *Thread) goto error; } Status = ObReferenceObjectByHandle(ptiCurrent->hEventQueueClient, 0, - ExEventObjectType, KernelMode, + *ExEventObjectType, KernelMode, (PVOID*)&ptiCurrent->pEventQueueServer, NULL); if (!NT_SUCCESS(Status)) { diff --git a/win32ss/user/ntuser/menu.c b/win32ss/user/ntuser/menu.c index f4c4e4c71c1..f46ea919348 100644 --- a/win32ss/user/ntuser/menu.c +++ b/win32ss/user/ntuser/menu.c @@ -11,6 +11,8 @@ DBG_DEFAULT_CHANNEL(UserMenu); /* INTERNAL ******************************************************************/ +BOOL FASTCALL IntSetMenuItemInfo(PMENU, PITEM, PROSMENUITEMINFO, PUNICODE_STRING); + /* maximum allowed depth of any branch in the menu tree. * This value is slightly larger than in windows (25) to * stay on the safe side. */ @@ -23,16 +25,29 @@ DBG_DEFAULT_CHANNEL(UserMenu); MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_RADIOCHECK | \ MFT_RIGHTORDER | MFT_RIGHTJUSTIFY /* same as MF_HELP */ ) +#define TYPE_MASK (MENUITEMINFO_TYPE_MASK | MF_POPUP | MF_SYSMENU) + +#define STATE_MASK (~TYPE_MASK) + +#define MENUITEMINFO_STATE_MASK (STATE_MASK & ~(MF_BYPOSITION | MF_MOUSESELECT)) + +#define MII_STATE_MASK (MFS_GRAYED|MFS_CHECKED|MFS_HILITE|MFS_DEFAULT) + /* Maximum number of menu items a menu can contain */ #define MAX_MENU_ITEMS (0x4000) #define MAX_GOINTOSUBMENU (0x10) #define UpdateMenuItemState(state, change) \ {\ - if((change) & MFS_DISABLED) { \ - (state) |= MFS_DISABLED; \ + if((change) & MF_GRAYED) { \ + (state) |= MF_GRAYED; \ } else { \ - (state) &= ~MFS_DISABLED; \ + (state) &= ~MF_GRAYED; \ + } /* Separate the two for test_menu_resource_layout.*/ \ + if((change) & MF_DISABLED) { \ + (state) |= MF_DISABLED; \ + } else { \ + (state) &= ~MF_DISABLED; \ } \ if((change) & MFS_CHECKED) { \ (state) |= MFS_CHECKED; \ @@ -56,42 +71,12 @@ DBG_DEFAULT_CHANNEL(UserMenu); } \ } -#define FreeMenuText(Menu,MenuItem) \ -{ \ - if((MENU_ITEM_TYPE((MenuItem)->fType) == MF_STRING) && \ - (MenuItem)->lpstr.Length) { \ - DesktopHeapFree(((PMENU)Menu)->head.rpdesk, (MenuItem)->lpstr.Buffer); \ - } \ -} - - -PMENU FASTCALL UserGetMenuObject(HMENU hMenu) -{ - PMENU Menu; - - if (!hMenu) - { - EngSetLastError(ERROR_INVALID_MENU_HANDLE); - return NULL; - } - - Menu = (PMENU)UserGetObject(gHandleTable, hMenu, TYPE_MENU); - if (!Menu) - { - EngSetLastError(ERROR_INVALID_MENU_HANDLE); - return NULL; - } - - return Menu; -} - - #if 0 void FASTCALL -DumpMenuItemList(PITEM MenuItem) +DumpMenuItemList(PMENU Menu, PITEM MenuItem) { - UINT cnt = 0; - while(MenuItem) + UINT cnt = 0, i = Menu->cItems; + while(i) { if(MenuItem->lpstr.Length) DbgPrint(" %d. %wZ\n", ++cnt, &MenuItem->lpstr); @@ -132,13 +117,22 @@ DumpMenuItemList(PITEM MenuItem) if(MFS_GRAYED & MenuItem->fState) DbgPrint("MFS_GRAYED "); DbgPrint("\n wId=%d\n", MenuItem->wID); - MenuItem = MenuItem->Next; + MenuItem++; + i--; } DbgPrint("Entries: %d\n", cnt); return; } #endif +#define FreeMenuText(Menu,MenuItem) \ +{ \ + if((MENU_ITEM_TYPE((MenuItem)->fType) == MF_STRING) && \ + (MenuItem)->lpstr.Length) { \ + DesktopHeapFree(((PMENU)Menu)->head.rpdesk, (MenuItem)->lpstr.Buffer); \ + } \ +} + PMENU FASTCALL IntGetMenuObject(HMENU hMenu) { @@ -149,64 +143,68 @@ IntGetMenuObject(HMENU hMenu) return Menu; } -BOOL FASTCALL -IntFreeMenuItem(PMENU Menu, PITEM MenuItem, BOOL bRecurse) +PMENU FASTCALL VerifyMenu(PMENU pMenu) { - FreeMenuText(Menu,MenuItem); - if(bRecurse && MenuItem->spSubMenu) + HMENU hMenu; + PITEM pItem; + UINT i; + if (!pMenu) return NULL; + + ERR("VerifyMenu 1!\n"); + _SEH2_TRY { - IntDestroyMenuObject(MenuItem->spSubMenu, bRecurse, TRUE); - } - - /* Free memory */ - DesktopHeapFree(Menu->head.rpdesk, MenuItem); - - return TRUE; -} - -BOOL FASTCALL -IntRemoveMenuItem(PMENU Menu, UINT uPosition, UINT uFlags, BOOL bRecurse) -{ - PITEM PrevMenuItem, MenuItem = NULL; - if(IntGetMenuItemByFlag(Menu, uPosition, uFlags, &Menu, &MenuItem, &PrevMenuItem) > -1) - { - if(MenuItem) + hMenu = UserHMGetHandle(pMenu); + pItem = pMenu->rgItems; + if (pItem) { - if(PrevMenuItem) - PrevMenuItem->Next = MenuItem->Next; - else - { - Menu->rgItems = MenuItem->Next; - } - Menu->cItems--; - return IntFreeMenuItem(Menu, MenuItem, bRecurse); + i = pItem[0].wID; + pItem[0].wID = i; } } - return FALSE; + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + ERR("Run away LOOP!\n"); + _SEH2_YIELD(return NULL); + } + _SEH2_END + ERR("VerifyMenu 2!\n"); + if ( UserObjectInDestroy(hMenu)) + return NULL; + ERR("VerifyMenu 3!\n"); + return pMenu; } -UINT FASTCALL -IntDeleteMenuItems(PMENU Menu, BOOL bRecurse) +BOOL IntDestroyMenu( PMENU pMenu, BOOL bRecurse, BOOL RemoveFromProcess) { - UINT res = 0; - PITEM NextItem; - PITEM CurItem = Menu->rgItems; - while(CurItem && Menu->cItems) - { - Menu->cItems--; //// This is the last of this mess~! Removal requires new start up sequence. Do it like windows and wine! - //// wine MENU_CopySysPopup and ReactOS User32LoadSysMenuTemplateForKernel. - //// SC_CLOSE First and SC_CLOSED Last - //// Use menu item blocks not chain. - /// So do it like windows~! - NextItem = CurItem->Next; - IntFreeMenuItem(Menu, CurItem, bRecurse); - CurItem->Next = 0; // mark the item as end of the list!!! - CurItem = NextItem; - res++; - } - Menu->cItems = 0; - Menu->rgItems = NULL; - return res; + /* DestroyMenu should not destroy system menu popup owner */ + if ((pMenu->fFlags & (MNF_POPUP | MNF_SYSSUBMENU)) == MNF_POPUP && pMenu->hWnd) + { + //PWND pWnd = ValidateHwndNoErr(pMenu->hWnd); + ERR("FIXME Pop up menu window thing'ie\n"); + + //co_UserDestroyWindow( pWnd ); + //pMenu->hWnd = 0; + } + + if (pMenu->rgItems) /* recursively destroy submenus */ + { + int i; + ITEM *item = pMenu->rgItems; + for (i = pMenu->cItems; i > 0; i--, item++) + { + pMenu->cItems--; //// I hate recursion logic! (jt) 4/2014. See r63028 comment for IntDeleteMenuItems. + FreeMenuText(pMenu,item); + if (bRecurse && item->spSubMenu)//VerifyMenu(item->spSubMenu)) + { + IntDestroyMenu(item->spSubMenu, bRecurse, RemoveFromProcess); + item->spSubMenu = NULL; + } + } + DesktopHeapFree(pMenu->head.rpdesk, pMenu->rgItems ); + pMenu->rgItems = NULL; + pMenu->cItems = 0; //// What ever~! + } + return TRUE; } BOOL FASTCALL @@ -216,24 +214,15 @@ IntDestroyMenuObject(PMENU Menu, if(Menu) { PWND Window; - //PWINSTATION_OBJECT WindowStation; - //NTSTATUS Status; - + /* Remove all menu items */ - IntDeleteMenuItems(Menu, bRecurse); /* Do not destroy submenus */ + IntDestroyMenu( Menu, bRecurse, RemoveFromProcess); if(RemoveFromProcess) { RemoveEntryList(&Menu->ListEntry); } - /*Status = ObReferenceObjectByHandle(Menu->Process->Win32WindowStation, - 0, - ExWindowStationObjectType, - KernelMode, - (PVOID*)&WindowStation, - NULL); - if(NT_SUCCESS(Status))*/ if (PsGetCurrentProcessSessionId() == Menu->head.rpdesk->rpwinstaParent->dwSessionId) { BOOL ret; @@ -252,55 +241,32 @@ IntDestroyMenuObject(PMENU Menu, ret = UserObjectInDestroy(Menu->head.h); if (ret && EngGetLastError() == ERROR_INVALID_HANDLE) ret = FALSE; } // See test_subpopup_locked_by_menu tests.... - //ObDereferenceObject(WindowStation); return ret; } } return FALSE; } -BOOL IntDestroyMenu( PMENU pMenu, BOOL RemoveFromProcess) -{ - /* DestroyMenu should not destroy system menu popup owner */ - if ((pMenu->fFlags & (MNF_POPUP | MNF_SYSSUBMENU)) == MNF_POPUP )//&& pMenu->hWnd) - { - //DestroyWindow( pMenu->hWnd ); - //pMenu->hWnd = 0; - } - - if (pMenu->rgItems) /* recursively destroy submenus */ - { - int i; - ITEM *item = pMenu->rgItems; - for (i = pMenu->cItems; i > 0; i--, item++) - { - if (item->spSubMenu) IntDestroyMenu(item->spSubMenu, RemoveFromProcess); - //FreeMenuText(pMenu,item); - } - DesktopHeapFree(pMenu->head.rpdesk, pMenu->rgItems ); - } - //IntDestroyMenuObject(pMenu, bRecurse, RemoveFromProcess); - return TRUE; -} - /********************************************************************** * MENU_depth * * detect if there are loops in the menu tree (or the depth is too large) */ -int MENU_depth( PMENU pmenu, int depth) +int FASTCALL MENU_depth( PMENU pmenu, int depth) { UINT i; ITEM *item; int subdepth; + if (!pmenu) return depth; + depth++; if( depth > MAXMENUDEPTH) return depth; item = pmenu->rgItems; subdepth = depth; - for( i = 0; i < pmenu->cItems && subdepth <= MAXMENUDEPTH; i++, item++) + for( i = 0; item, i < pmenu->cItems && subdepth <= MAXMENUDEPTH; i++, item++) { - if( item->spSubMenu) + if( item->spSubMenu)//VerifyMenu(item->spSubMenu)) { int bdepth = MENU_depth( item->spSubMenu, depth); if( bdepth > subdepth) subdepth = bdepth; @@ -317,38 +283,29 @@ int MENU_depth( PMENU pmenu, int depth) * Find a menu item. Return a pointer on the item, and modifies *hmenu * in case the item was in a sub-menu. */ -ITEM *MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags ) +PITEM FASTCALL MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags ) { MENU *menu = *pmenu; ITEM *fallback = NULL; UINT fallback_pos = 0; UINT i; - PITEM pItem; + + if (!menu) return NULL; if (wFlags & MF_BYPOSITION) { + if (!menu->cItems) return NULL; if (*nPos >= menu->cItems) return NULL; - pItem = menu->rgItems; - //pItem = &menu->rgItems[*nPos]; - i = 0; - while(pItem) // Do this for now. - { - if (i < (INT)menu->cItems) - { - if ( *nPos == i ) return pItem; - } - pItem = pItem->Next; - i++; - } + return &menu->rgItems[*nPos]; } else { PITEM item = menu->rgItems; - for (i = 0; item ,i < menu->cItems; i++, item = item->Next)//, item++) + for (i = 0; item, i < menu->cItems; i++, item++) { if (item->spSubMenu) { - PMENU psubmenu = item->spSubMenu; + PMENU psubmenu = item->spSubMenu;//VerifyMenu(item->spSubMenu); PITEM subitem = MENU_FindItem( &psubmenu, nPos, wFlags ); if (subitem) { @@ -376,20 +333,20 @@ ITEM *MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags ) return fallback; } -BOOL IntRemoveMenu( PMENU pMenu, UINT nPos, UINT wFlags, BOOL bRecurse ) +BOOL FASTCALL +IntRemoveMenuItem( PMENU pMenu, UINT nPos, UINT wFlags, BOOL bRecurse ) { PITEM item, NewItems; TRACE("(menu=%p pos=%04x flags=%04x)\n",pMenu, nPos, wFlags); if (!(item = MENU_FindItem( &pMenu, &nPos, wFlags ))) return FALSE; - /* Remove item */ - - //FreeMenuText(pMenu,item); + /* Remove item */ + FreeMenuText(pMenu,item); if (bRecurse && item->spSubMenu) { - IntDestroyMenu(item->spSubMenu, TRUE); + IntDestroyMenuObject(item->spSubMenu, bRecurse, TRUE); } ////// Use cAlloced with inc's of 8's.... if (--pMenu->cItems == 0) @@ -413,6 +370,100 @@ BOOL IntRemoveMenu( PMENU pMenu, UINT nPos, UINT wFlags, BOOL bRecurse ) return TRUE; } +/********************************************************************** + * MENU_InsertItem + * + * Insert (allocate) a new item into a menu. + */ +ITEM *MENU_InsertItem( PMENU menu, UINT pos, UINT flags, PMENU *submenu, UINT *npos ) +{ + ITEM *newItems; + + /* Find where to insert new item */ + + if (flags & MF_BYPOSITION) { + if (pos > menu->cItems) + pos = menu->cItems; + } else { + if (!MENU_FindItem( &menu, &pos, flags )) + { + if (submenu) *submenu = menu; + if (npos) *npos = pos; + pos = menu->cItems; + } + } + + /* Make sure that MDI system buttons stay on the right side. + * Note: XP treats only bitmap handles 1 - 6 as "magic" ones + * regardless of their id. + */ + while ( pos > 0 && + (INT_PTR)menu->rgItems[pos - 1].hbmp >= (INT_PTR)HBMMENU_SYSTEM && + (INT_PTR)menu->rgItems[pos - 1].hbmp <= (INT_PTR)HBMMENU_MBAR_CLOSE_D) + pos--; + + TRACE("inserting at %u flags %x\n", pos, flags); + + /* Create new items array */ + + newItems = DesktopHeapAlloc(menu->head.rpdesk, sizeof(ITEM) * (menu->cItems+1) ); + if (!newItems) + { + WARN("allocation failed\n" ); + return NULL; + } + if (menu->cItems > 0) + { + /* Copy the old array into the new one */ + if (pos > 0) RtlCopyMemory( newItems, menu->rgItems, pos * sizeof(ITEM) ); + if (pos < menu->cItems) RtlCopyMemory( &newItems[pos+1], &menu->rgItems[pos], (menu->cItems-pos)*sizeof(ITEM) ); + DesktopHeapFree(menu->head.rpdesk, menu->rgItems ); + } + menu->rgItems = newItems; + menu->cItems++; + RtlZeroMemory( &newItems[pos], sizeof(*newItems) ); + menu->cyMenu = 0; /* force size recalculate */ + return &newItems[pos]; +} + +BOOL FASTCALL +IntInsertMenuItem( + _In_ PMENU MenuObject, + UINT uItem, + BOOL fByPosition, + PROSMENUITEMINFO ItemInfo, + PUNICODE_STRING lpstr) +{ + PITEM MenuItem; + PMENU SubMenu = NULL; + + NT_ASSERT(MenuObject != NULL); + + if (MAX_MENU_ITEMS <= MenuObject->cItems) + { + EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + SubMenu = MenuObject; + + if(!(MenuItem = MENU_InsertItem( SubMenu, uItem, fByPosition ? MF_BYPOSITION : MF_BYCOMMAND, &SubMenu, &uItem ))) return FALSE; + + if(!IntSetMenuItemInfo(SubMenu, MenuItem, ItemInfo, lpstr)) + { + IntRemoveMenuItem(SubMenu, uItem, fByPosition ? MF_BYPOSITION : MF_BYCOMMAND, FALSE); + return FALSE; + } + + /* Force size recalculation! */ + SubMenu->cyMenu = 0; + MenuItem->hbmpChecked = MenuItem->hbmpUnchecked = 0; + + TRACE("IntInsertMenuItemToList = %i %d\n", uItem, (BOOL)((INT)uItem >= 0)); + + return TRUE; +} + PMENU FASTCALL IntCreateMenu(PHANDLE Handle, BOOL IsMenuBar) { @@ -460,21 +511,21 @@ BOOL FASTCALL IntCloneMenuItems(PMENU Destination, PMENU Source) { PITEM MenuItem, NewMenuItem = NULL; - PITEM Old = NULL; + UINT i; if(!Source->cItems) return FALSE; + NewMenuItem = DesktopHeapAlloc(Destination->head.rpdesk, (Source->cItems+1) * sizeof(ITEM)); + if(!NewMenuItem) return FALSE; + + RtlZeroMemory(NewMenuItem, (Source->cItems+1) * sizeof(ITEM)); + + Destination->rgItems = NewMenuItem; + MenuItem = Source->rgItems; - while(MenuItem) + for (i = 0; i < Source->cItems; i++, MenuItem++, NewMenuItem++) { - Old = NewMenuItem; - if(NewMenuItem) - NewMenuItem->Next = MenuItem; - NewMenuItem = DesktopHeapAlloc(Destination->head.rpdesk, sizeof(ITEM)); - if(!NewMenuItem) - break; - RtlZeroMemory(NewMenuItem, sizeof(NewMenuItem)); NewMenuItem->fType = MenuItem->fType; NewMenuItem->fState = MenuItem->fState; NewMenuItem->wID = MenuItem->wID; @@ -506,16 +557,7 @@ IntCloneMenuItems(PMENU Destination, PMENU Source) NewMenuItem->lpstr.Buffer = MenuItem->lpstr.Buffer; } NewMenuItem->hbmp = MenuItem->hbmp; - - NewMenuItem->Next = NULL; - if(Old) - Old->Next = NewMenuItem; - else - Destination->rgItems = NewMenuItem; - Destination->cItems++; - MenuItem = MenuItem->Next; } - return TRUE; } @@ -547,7 +589,7 @@ IntCloneMenu(PMENU Source) Menu->spwndNotify = NULL; Menu->cyMenu = 0; Menu->cxMenu = 0; - Menu->cItems = 0; + Menu->cItems = Source->cItems; Menu->iTop = 0; Menu->iMaxTop = 0; Menu->cxTextAlign = 0; @@ -631,21 +673,13 @@ IntSetMenuInfo(PMENU Menu, PROSMENUINFO lpmi) { int i; PITEM item = Menu->rgItems; - for ( i = Menu->cItems; i; i--, item = item->Next) - { - if ( item->spSubMenu ) - { - IntSetMenuInfo( item->spSubMenu, lpmi); - } - } - /* PITEM item = Menu->rgItems; for ( i = Menu->cItems; i; i--, item++) { if ( item->spSubMenu ) { IntSetMenuInfo( item->spSubMenu, lpmi); } - }*/ + } } if (sizeof(MENUINFO) < lpmi->cbSize) { @@ -664,117 +698,6 @@ IntSetMenuInfo(PMENU Menu, PROSMENUINFO lpmi) return TRUE; } -// -// Old and yeah~..... Why start with a -1 for position search? -// -int FASTCALL -IntGetMenuItemByFlag(PMENU Menu, - UINT uSearchBy, - UINT fFlag, - PMENU *SubMenu, - PITEM *MenuItem, - PITEM *PrevMenuItem) -{ - PITEM PrevItem = NULL; - PITEM CurItem = Menu->rgItems; - int p; - int ret; - - if(MF_BYPOSITION & fFlag) - { - p = uSearchBy; - while(CurItem && (p > 0)) - { - PrevItem = CurItem; - CurItem = CurItem->Next; - p--; - } - if(CurItem) - { - if(MenuItem) - *MenuItem = CurItem; - if(PrevMenuItem) - *PrevMenuItem = PrevItem; - } - else - { - if(MenuItem) - *MenuItem = NULL; - if(PrevMenuItem) - *PrevMenuItem = NULL; /* ? */ - return -1; - } - - return uSearchBy - p; - } - else - { - p = 0; - while(CurItem) - { - if(CurItem->wID == uSearchBy) - { - if(MenuItem) - *MenuItem = CurItem; - if(PrevMenuItem) - *PrevMenuItem = PrevItem; - if(SubMenu) - *SubMenu = Menu; - - return p; - } - else - { - if(CurItem->spSubMenu) - { - ret = IntGetMenuItemByFlag(CurItem->spSubMenu, uSearchBy, fFlag, SubMenu, MenuItem, PrevMenuItem); - if(ret != -1) - { - return ret; - } - } - } - PrevItem = CurItem; - CurItem = CurItem->Next; - p++; - } - } - return -1; -} - - -int FASTCALL -IntInsertMenuItemToList(PMENU Menu, PITEM MenuItem, int pos) -{ - PITEM CurItem; - PITEM LastItem = NULL; - UINT npos = 0; - - CurItem = Menu->rgItems; - while(CurItem && (pos != 0)) - { - LastItem = CurItem; - CurItem = CurItem->Next; - pos--; - npos++; - } - - if(LastItem) - { - /* Insert the item after LastItem */ - LastItem->Next = MenuItem; - } - else - { - /* Insert at the beginning */ - Menu->rgItems = MenuItem; - } - MenuItem->Next = CurItem; - Menu->cItems++; - - return npos; -} - BOOL FASTCALL IntGetMenuItemInfo(PMENU Menu, /* UNUSED PARAM!! */ PITEM MenuItem, PROSMENUITEMINFO lpmii) @@ -850,18 +773,17 @@ BOOL FASTCALL IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUNICODE_STRING lpstr) { PMENU SubMenuObject; - UINT fTypeMask = (MFT_BITMAP | MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_OWNERDRAW | MFT_RADIOCHECK | MFT_RIGHTJUSTIFY | MFT_SEPARATOR); if(!MenuItem || !MenuObject || !lpmii) { return FALSE; } - if (lpmii->fType & ~fTypeMask) + if ( lpmii->fMask & MIIM_FTYPE ) { - ERR("IntSetMenuItemInfo invalid fType flags %x\n", lpmii->fType & ~fTypeMask); - lpmii->fMask &= ~(MIIM_TYPE | MIIM_FTYPE); + MenuItem->fType &= ~MENUITEMINFO_TYPE_MASK; + MenuItem->fType |= lpmii->fType & MENUITEMINFO_TYPE_MASK; } - if (lpmii->fMask & MIIM_TYPE) + if (lpmii->fMask & MIIM_TYPE) { #if 0 //// Done in User32. if (lpmii->fMask & ( MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP)) @@ -882,6 +804,7 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN { FreeMenuText(MenuObject,MenuItem); RtlInitUnicodeString(&MenuItem->lpstr, NULL); + MenuItem->Xlpstr = NULL; } if(lpmii->fType & MFT_BITMAP) { @@ -891,25 +814,12 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN { /* Win 9x/Me stuff */ MenuItem->hbmp = (HBITMAP)((ULONG_PTR)(LOWORD(lpmii->dwTypeData))); } + lpmii->dwTypeData = 0; } - MenuItem->fType |= lpmii->fType; - } - if (lpmii->fMask & MIIM_FTYPE ) - { - #if 0 //// ? - if(( lpmii->fType & MFT_BITMAP)) - { - ERR("IntSetMenuItemInfo: Can not use FTYPE and MFT_BITMAP.\n"); - SetLastNtError( ERROR_INVALID_PARAMETER); - return FALSE; - } - #endif - MenuItem->fType &= ~MENUITEMINFO_TYPE_MASK; - MenuItem->fType |= lpmii->fType & MENUITEMINFO_TYPE_MASK; } if(lpmii->fMask & MIIM_BITMAP) { - MenuItem->hbmp = lpmii->hbmpItem; + MenuItem->hbmp = lpmii->hbmpItem; } if(lpmii->fMask & MIIM_CHECKMARKS) { @@ -942,9 +852,14 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN SubMenuObject = UserGetMenuObject(lpmii->hSubMenu); if (SubMenuObject != NULL) { + if ( MENU_depth( SubMenuObject, 0) > MAXMENUDEPTH) + { + ERR( "Loop detected in menu hierarchy or maximum menu depth exceeded!\n"); + return FALSE; + } SubMenuObject->fFlags |= MNF_POPUP; // Now fix the test_subpopup_locked_by_menu tests.... - if (MenuItem->spSubMenu) UserDereferenceObject(MenuItem->spSubMenu); + if (MenuItem->spSubMenu) IntReleaseMenuObject(MenuItem->spSubMenu); MenuItem->spSubMenu = SubMenuObject; UserReferenceObject(SubMenuObject); } @@ -956,7 +871,7 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN } else { // If submenu just dereference it. - if (MenuItem->spSubMenu) UserDereferenceObject(MenuItem->spSubMenu); + if (MenuItem->spSubMenu) IntReleaseMenuObject(MenuItem->spSubMenu); MenuItem->spSubMenu = NULL; } } @@ -964,9 +879,12 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN if ((lpmii->fMask & MIIM_STRING) || ((lpmii->fMask & MIIM_TYPE) && (MENU_ITEM_TYPE(lpmii->fType) == MF_STRING))) { + /* free the string when used */ FreeMenuText(MenuObject,MenuItem); + RtlInitUnicodeString(&MenuItem->lpstr, NULL); + MenuItem->Xlpstr = NULL; - if(lpmii->dwTypeData && lpmii->cch) + if(lpmii->dwTypeData && lpmii->cch && lpstr && lpstr->Buffer) { UNICODE_STRING Source; @@ -984,27 +902,15 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN MenuItem->cch = MenuItem->lpstr.Length / sizeof(WCHAR); MenuItem->Xlpstr = (USHORT*)MenuItem->lpstr.Buffer; } - else - { - RtlInitUnicodeString(&MenuItem->lpstr, NULL); - MenuItem->Xlpstr = NULL; - } - } - else - { - if (0 == (MenuObject->fFlags & MNF_SYSDESKMN)) - { - MenuItem->fType |= MF_SEPARATOR; - } - RtlInitUnicodeString(&MenuItem->lpstr, NULL); } } - //if( !MenuItem->lpstr.Buffer && !(MenuItem->fType & MFT_OWNERDRAW) && !MenuItem->hbmp) - // MenuItem->fType |= MFT_SEPARATOR; break system menu..... - - /* Force size recalculation! */ - MenuObject->cyMenu = 0; + if( !(MenuObject->fFlags & MNF_SYSDESKMN) && + !MenuItem->Xlpstr && + !lpmii->dwTypeData && + !(MenuItem->fType & MFT_OWNERDRAW) && + !MenuItem->hbmp) + MenuItem->fType |= MFT_SEPARATOR; if (sizeof(ROSMENUITEMINFO) == lpmii->cbSize) { @@ -1022,130 +928,6 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN } -/********************************************************************** - * MENU_InsertItem - * - * Insert (allocate) a new item into a menu. - */ -ITEM *MENU_InsertItem( PMENU menu, UINT pos, UINT flags ) -{ - ITEM *newItems; - - /* Find where to insert new item */ - - if (flags & MF_BYPOSITION) { - if (pos > menu->cItems) - pos = menu->cItems; - } else { - if (!MENU_FindItem( &menu, &pos, flags )) - pos = menu->cItems; - } - - /* Make sure that MDI system buttons stay on the right side. - * Note: XP treats only bitmap handles 1 - 6 as "magic" ones - * regardless of their id. - */ - while ( pos > 0 && - (INT_PTR)menu->rgItems[pos - 1].hbmp >= (INT_PTR)HBMMENU_SYSTEM && - (INT_PTR)menu->rgItems[pos - 1].hbmp <= (INT_PTR)HBMMENU_MBAR_CLOSE_D) - pos--; - - TRACE("inserting at %u flags %x\n", pos, flags); - - /* Create new items array */ - - newItems = DesktopHeapAlloc(menu->head.rpdesk, sizeof(ITEM) * (menu->cItems+1) ); - if (!newItems) - { - WARN("allocation failed\n" ); - return NULL; - } - if (menu->cItems > 0) - { - /* Copy the old array into the new one */ - if (pos > 0) RtlCopyMemory( newItems, menu->rgItems, pos * sizeof(ITEM) ); - if (pos < menu->cItems) RtlCopyMemory( &newItems[pos+1], &menu->rgItems[pos], (menu->cItems-pos)*sizeof(ITEM) ); - DesktopHeapFree(menu->head.rpdesk, menu->rgItems ); - } - menu->rgItems = newItems; - menu->cItems++; - RtlZeroMemory( &newItems[pos], sizeof(*newItems) ); - menu->cyMenu = 0; /* force size recalculate */ - return &newItems[pos]; -} - -BOOL FASTCALL -IntInsertMenuItem( - _In_ PMENU MenuObject, - UINT uItem, - BOOL fByPosition, - PROSMENUITEMINFO ItemInfo) -{ - int pos; - PITEM MenuItem; - PMENU SubMenu = NULL; - - NT_ASSERT(MenuObject != NULL); - //ERR("InsertMenuItem\n"); - if (MAX_MENU_ITEMS <= MenuObject->cItems) - { - EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - if (fByPosition) - { - SubMenu = MenuObject; - /* calculate position */ - pos = (int)uItem; - if(uItem > MenuObject->cItems) - { - pos = MenuObject->cItems; - } - } - else - { - pos = IntGetMenuItemByFlag(MenuObject, uItem, MF_BYCOMMAND, &SubMenu, NULL, NULL); - } - if (SubMenu == NULL) - { - /* Default to last position of menu */ - SubMenu = MenuObject; - pos = MenuObject->cItems; - } - - - if (pos < -1) - { - pos = -1; - } - - MenuItem = DesktopHeapAlloc(MenuObject->head.rpdesk, sizeof(ITEM)); - if (NULL == MenuItem) - { - EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - RtlZeroMemory(MenuItem, sizeof(MenuItem)); - - if(!IntSetMenuItemInfo(SubMenu, MenuItem, ItemInfo, NULL)) - { - DesktopHeapFree(MenuObject->head.rpdesk, MenuItem); - return FALSE; - } - - /* Force size recalculation! */ - MenuObject->cyMenu = 0; - MenuItem->hbmpChecked = MenuItem->hbmpUnchecked = 0; - - pos = IntInsertMenuItemToList(SubMenu, MenuItem, pos); - - TRACE("IntInsertMenuItemToList = %i\n", pos); - - return (pos >= 0); -} - UINT FASTCALL IntEnableMenuItem(PMENU MenuObject, UINT uIDEnableItem, UINT uEnable) { @@ -1173,109 +955,7 @@ IntEnableMenuItem(PMENU MenuObject, UINT uIDEnableItem, UINT uEnable) } return res; } -#if 0 // Moved to User32. -DWORD FASTCALL -IntBuildMenuItemList(PMENU MenuObject, PVOID Buffer, ULONG nMax) -{ - DWORD res = 0; - ROSMENUITEMINFO mii; - PVOID Buf; - PITEM CurItem = MenuObject->rgItems; - PWCHAR StrOut; - NTSTATUS Status; - WCHAR NulByte; - if (0 != nMax) - { - if (nMax < MenuObject->cItems * sizeof(ROSMENUITEMINFO)) - { - return 0; - } - StrOut = (PWCHAR)((char *) Buffer + MenuObject->cItems - * sizeof(ROSMENUITEMINFO)); - nMax -= MenuObject->cItems * sizeof(ROSMENUITEMINFO); - Buf = Buffer; - mii.cbSize = sizeof(ROSMENUITEMINFO); - mii.fMask = 0; - NulByte = L'\0'; - - while (NULL != CurItem) - { - mii.cch = CurItem->lpstr.Length / sizeof(WCHAR); - mii.dwItemData = CurItem->dwItemData; - if (0 != CurItem->lpstr.Length) - { - mii.dwTypeData = StrOut; - } - else - { - mii.dwTypeData = NULL; - } - mii.fState = CurItem->fState; - mii.fType = CurItem->fType; - mii.wID = CurItem->wID; - mii.hbmpChecked = CurItem->hbmpChecked; - mii.hbmpItem = CurItem->hbmp; - mii.hbmpUnchecked = CurItem->hbmpUnchecked; - mii.hSubMenu = CurItem->spSubMenu ? CurItem->spSubMenu->head.h : NULL; - mii.Rect.left = CurItem->xItem; - mii.Rect.top = CurItem->yItem; - mii.Rect.right = CurItem->cxItem; // Do this for now...... - mii.Rect.bottom = CurItem->cyItem; - mii.dxTab = CurItem->dxTab; - mii.lpstr = CurItem->lpstr.Buffer; // Can be read from user side! - //mii.maxBmpSize.cx = CurItem->cxBmp; - //mii.maxBmpSize.cy = CurItem->cyBmp; - - Status = MmCopyToCaller(Buf, &mii, sizeof(ROSMENUITEMINFO)); - if (! NT_SUCCESS(Status)) - { - SetLastNtError(Status); - return 0; - } - Buf = (PVOID)((ULONG_PTR)Buf + sizeof(ROSMENUITEMINFO)); - - if (0 != CurItem->lpstr.Length - && (nMax >= CurItem->lpstr.Length + sizeof(WCHAR))) - { - /* Copy string */ - Status = MmCopyToCaller(StrOut, CurItem->lpstr.Buffer, - CurItem->lpstr.Length); - if (! NT_SUCCESS(Status)) - { - SetLastNtError(Status); - return 0; - } - StrOut += CurItem->lpstr.Length / sizeof(WCHAR); - Status = MmCopyToCaller(StrOut, &NulByte, sizeof(WCHAR)); - if (! NT_SUCCESS(Status)) - { - SetLastNtError(Status); - return 0; - } - StrOut++; - nMax -= CurItem->lpstr.Length + sizeof(WCHAR); - } - else if (0 != CurItem->lpstr.Length) - { - break; - } - - CurItem = CurItem->Next; - res++; - } - } - else - { - while (NULL != CurItem) - { - res += sizeof(ROSMENUITEMINFO) + CurItem->lpstr.Length + sizeof(WCHAR); - CurItem = CurItem->Next; - } - } - return res; -} -#endif DWORD FASTCALL IntCheckMenuItem(PMENU MenuObject, UINT uIDCheckItem, UINT uCheck) { @@ -1301,32 +981,31 @@ IntHiliteMenuItem(PWND WindowObject, if (!(MenuItem = MENU_FindItem( &MenuObject, &uItemHilite, uHilite ))) return FALSE; - if (MenuItem) + if (uHilite & MF_HILITE) { - if (uHilite & MF_HILITE) - { - MenuItem->fState |= MF_HILITE; - } - else - { - MenuItem->fState &= ~MF_HILITE; - } + MenuItem->fState |= MF_HILITE; + } + else + { + MenuItem->fState &= ~MF_HILITE; } /* FIXME: Update the window's menu */ - return TRUE; + return TRUE; // Always returns true!!!! } BOOL FASTCALL UserSetMenuDefaultItem(PMENU MenuObject, UINT uItem, UINT fByPos) { - BOOL ret = FALSE; + UINT i; PITEM MenuItem = MenuObject->rgItems; - while(MenuItem) + if (!MenuItem) return FALSE; + + /* reset all default-item flags */ + for (i = 0; MenuItem, i < MenuObject->cItems; i++, MenuItem++) { - MenuItem->fState &= ~MFS_DEFAULT; - MenuItem = MenuItem->Next; + MenuItem->fState &= ~MFS_DEFAULT; } /* no default item */ @@ -1334,90 +1013,59 @@ UserSetMenuDefaultItem(PMENU MenuObject, UINT uItem, UINT fByPos) { return TRUE; } - - if(fByPos) + MenuItem = MenuObject->rgItems; + if ( fByPos ) { - UINT pos = 0; - while(MenuItem) - { - if(pos == uItem) - { - MenuItem->fState |= MFS_DEFAULT; - ret = TRUE; - } - else - { - MenuItem->fState &= ~MFS_DEFAULT; - } - pos++; - MenuItem = MenuItem->Next; - } + if ( uItem >= MenuObject->cItems ) return FALSE; + MenuItem[uItem].fState |= MFS_DEFAULT; + return TRUE; } else { - while(MenuItem) + for (i = 0; MenuItem, i < MenuObject->cItems; i++, MenuItem++) { - if(!ret && (MenuItem->wID == uItem)) - { - MenuItem->fState |= MFS_DEFAULT; - ret = TRUE; - } - else - { - MenuItem->fState &= ~MFS_DEFAULT; - } - MenuItem = MenuItem->Next; + if (MenuItem->wID == uItem) + { + MenuItem->fState |= MFS_DEFAULT; + return TRUE; + } } + } - return ret; + return FALSE; } UINT FASTCALL -IntGetMenuDefaultItem(PMENU MenuObject, UINT fByPos, UINT gmdiFlags, - DWORD *gismc) +IntGetMenuDefaultItem(PMENU MenuObject, UINT fByPos, UINT gmdiFlags, DWORD *gismc) { - UINT x = 0; - UINT res = -1; - UINT sres; + UINT i = 0; PITEM MenuItem = MenuObject->rgItems; - while(MenuItem) + /* empty menu */ + if (!MenuItem) return -1; + + while ( !( MenuItem->fState & MFS_DEFAULT ) ) { - if(MenuItem->fState & MFS_DEFAULT) - { - - if(!(gmdiFlags & GMDI_USEDISABLED) && (MenuItem->fState & MFS_DISABLED)) - break; - - if(fByPos) - res = x; - else - res = MenuItem->wID; - - if((*gismc < MAX_GOINTOSUBMENU) && (gmdiFlags & GMDI_GOINTOPOPUPS) && - MenuItem->spSubMenu) - { - - if(MenuItem->spSubMenu == MenuObject) - break; - - (*gismc)++; - sres = IntGetMenuDefaultItem(MenuItem->spSubMenu, fByPos, gmdiFlags, gismc); - (*gismc)--; - - if(sres > (UINT)-1) - res = sres; - } - - break; - } - - MenuItem = MenuItem->Next; - x++; + i++; MenuItem++; + if (i >= MenuObject->cItems ) return -1; } - return res; + /* default: don't return disabled items */ + if ( (!(GMDI_USEDISABLED & gmdiFlags)) && (MenuItem->fState & MFS_DISABLED )) return -1; + + /* search rekursiv when needed */ + if ( (MenuItem->fType & MF_POPUP) && (gmdiFlags & GMDI_GOINTOPOPUPS) && MenuItem->spSubMenu) + { + UINT ret; + (*gismc)++; + ret = IntGetMenuDefaultItem( MenuItem->spSubMenu, fByPos, gmdiFlags, gismc ); + (*gismc)--; + if ( -1 != ret ) return ret; + + /* when item not found in submenu, return the popup item */ + } + return ( fByPos ) ? i : MenuItem->wID; } VOID FASTCALL @@ -1484,7 +1132,7 @@ IntCleanupMenus(struct _EPROCESS *Process, PPROCESSINFO Win32Process) { LastHead = Win32Process->MenuListHead.Flink; MenuObject = CONTAINING_RECORD(Win32Process->MenuListHead.Flink, MENU, ListEntry); - ERR("Menus are stuck on the process list!\n"); + TRACE("Menus are stuck on the process list!\n"); IntDestroyMenuObject(MenuObject, FALSE, TRUE); } @@ -1631,7 +1279,8 @@ UserInsertMenuItem( PMENU Menu, UINT uItem, BOOL fByPosition, - LPCMENUITEMINFOW UnsafeItemInfo) + LPCMENUITEMINFOW UnsafeItemInfo, + PUNICODE_STRING lpstr) { NTSTATUS Status; ROSMENUITEMINFO ItemInfo; @@ -1646,7 +1295,7 @@ UserInsertMenuItem( EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - return IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo); + return IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo, lpstr); } /* Try to copy without last field (not present in older versions) */ @@ -1659,7 +1308,7 @@ UserInsertMenuItem( return FALSE; } ItemInfo.hbmpItem = (HBITMAP)0; - return IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo); + return IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo, lpstr); } SetLastNtError(Status); @@ -1717,7 +1366,7 @@ UINT FASTCALL IntFindSubMenu(HMENU *hMenu, HMENU hSubTarget ) return NO_SELECTED_ITEM; item = menu->rgItems; - for (i = 0; i < menu->cItems; i++, item = item->Next)//item++) + for (i = 0; i < menu->cItems; i++, item++) { if (!item->spSubMenu) continue; @@ -1792,7 +1441,8 @@ UserMenuItemInfo( UINT Item, BOOL ByPosition, PROSMENUITEMINFO UnsafeItemInfo, - BOOL SetOrGet) + BOOL SetOrGet, + PUNICODE_STRING lpstr) { PITEM MenuItem; ROSMENUITEMINFO ItemInfo; @@ -1836,7 +1486,7 @@ UserMenuItemInfo( if (SetOrGet) { - Ret = IntSetMenuItemInfo(Menu, MenuItem, &ItemInfo, NULL); + Ret = IntSetMenuItemInfo(Menu, MenuItem, &ItemInfo, lpstr); } else { @@ -1931,7 +1581,6 @@ IntGetMenuItemRect( { LONG XMove, YMove; PITEM MenuItem; - //int p = 0; if (!pWnd) { @@ -2109,7 +1758,6 @@ BOOL FASTCALL UserDestroyMenu(HMENU hMenu) return FALSE; } - //if(Menu->Process != PsGetCurrentProcess()) if (Menu->head.rpdesk != pti->rpdesk) { EngSetLastError(ERROR_ACCESS_DENIED); @@ -2262,12 +1910,12 @@ NtUserGetMenuBarInfo( Ret = IntGetMenuItemRect(pWnd, Menu, 0, &kmbi.rcBar); kmbi.rcBar.right = kmbi.rcBar.left + Menu->cxMenu; kmbi.rcBar.bottom = kmbi.rcBar.top + Menu->cyMenu; - ERR("idItem 0 %d\n",Ret); + TRACE("idItem 0 %d\n",Ret); } else { Ret = IntGetMenuItemRect(pWnd, Menu, idItem-1, &kmbi.rcBar); - ERR("idItem X %d\n", Ret); + TRACE("idItem X %d\n", Ret); } kmbi.hMenu = hMenu; @@ -2277,15 +1925,15 @@ NtUserGetMenuBarInfo( //kmbi.fBarFocused = top_popup_hmenu == hMenu; if (idItem) { - PITEM MenuItem; - UINT nPos = idItem-1; + //PITEM MenuItem; + //UINT nPos = idItem-1; kmbi.fFocused = Menu->iItem == idItem-1; - //if (kmbi->fFocused && (Menu->rgItems[idItem - 1].spSubMenu)) - MenuItem = MENU_FindItem (&Menu, &nPos, MF_BYPOSITION); - if ( MenuItem && kmbi.fFocused && MenuItem->spSubMenu ) + if (kmbi.fFocused && (Menu->rgItems[idItem - 1].spSubMenu)) + //MenuItem = MENU_FindItem (&Menu, &nPos, MF_BYPOSITION); + //if ( MenuItem && kmbi.fFocused && MenuItem->spSubMenu ) { - //kmbi.hwndMenu = Menu->rgItems[idItem - 1].spSubMenu->hWnd; - kmbi.hwndMenu = MenuItem->spSubMenu->hWnd; + kmbi.hwndMenu = Menu->rgItems[idItem - 1].spSubMenu->hWnd; + //kmbi.hwndMenu = MenuItem->spSubMenu->hWnd; } } /* else @@ -2327,6 +1975,7 @@ NtUserGetMenuIndex( { PMENU Menu, SubMenu; PITEM MenuItem; + UINT i; DECLARE_RETURN(UINT); TRACE("Enter NtUserGetMenuIndex\n"); @@ -2337,13 +1986,11 @@ NtUserGetMenuIndex( RETURN(0xFFFFFFFF); MenuItem = Menu->rgItems; - while(MenuItem) + for (i = 0; i < Menu->cItems; i++, MenuItem++) { - if (MenuItem->spSubMenu == SubMenu) - RETURN(MenuItem->wID); - MenuItem = MenuItem->Next; + if (MenuItem->spSubMenu == SubMenu) + RETURN(MenuItem->wID); } - RETURN(0xFFFFFFFF); CLEANUP: @@ -2507,7 +2154,7 @@ NtUserMenuItemFromPoint( Y -= Window->rcWindow.top; mi = Menu->rgItems; - for (i = 0; NULL != mi; i++)//, mi++) + for (i = 0; i < Menu->cItems; i++, mi++) { RECTL Rect; Rect.left = mi->xItem; @@ -2519,7 +2166,6 @@ NtUserMenuItemFromPoint( { break; } - mi = mi->Next; } RETURN( (mi ? i : NO_SELECTED_ITEM)); @@ -2696,7 +2342,7 @@ NtUserThunkedMenuItemInfo( RETURN(FALSE); } - lstrCaption.Buffer = NULL; + RtlInitUnicodeString(&lstrCaption, 0); /* Check if we got a Caption */ if (lpszCaption && lpszCaption->Buffer) @@ -2711,12 +2357,11 @@ NtUserThunkedMenuItemInfo( SetLastNtError(Status); RETURN(FALSE); } - ///// Now use it! } - if (bInsert) RETURN( UserInsertMenuItem(Menu, uItem, fByPosition, lpmii)); + if (bInsert) RETURN( UserInsertMenuItem(Menu, uItem, fByPosition, lpmii, &lstrCaption)); - RETURN( UserMenuItemInfo(Menu, uItem, fByPosition, (PROSMENUITEMINFO)lpmii, TRUE)); + RETURN( UserMenuItemInfo(Menu, uItem, fByPosition, (PROSMENUITEMINFO)lpmii, TRUE, &lstrCaption)); CLEANUP: TRACE("Leave NtUserThunkedMenuItemInfo, ret=%i\n",_ret_); diff --git a/win32ss/user/ntuser/menu.h b/win32ss/user/ntuser/menu.h index 9ff6b0cbee0..e5830546cb5 100644 --- a/win32ss/user/ntuser/menu.h +++ b/win32ss/user/ntuser/menu.h @@ -38,8 +38,7 @@ BOOL FASTCALL IntCleanupMenus(struct _EPROCESS *Process, PPROCESSINFO Win32Process); BOOL FASTCALL -IntInsertMenuItem(_In_ PMENU MenuObject, UINT uItem, BOOL fByPosition, - PROSMENUITEMINFO ItemInfo); +IntInsertMenuItem(_In_ PMENU MenuObject, UINT uItem, BOOL fByPosition, PROSMENUITEMINFO ItemInfo, PUNICODE_STRING lpstr); PMENU FASTCALL IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu); @@ -47,4 +46,4 @@ IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu); UINT FASTCALL IntFindSubMenu(HMENU *hMenu, HMENU hSubTarget ); UINT FASTCALL IntGetMenuState( HMENU hMenu, UINT uId, UINT uFlags); BOOL FASTCALL IntRemoveMenuItem(PMENU Menu, UINT uPosition, UINT uFlags, BOOL bRecurse); -PITEM MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags ); +PITEM FASTCALL MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags ); diff --git a/win32ss/user/ntuser/message.c b/win32ss/user/ntuser/message.c index a9e2256d3eb..c458230a0c9 100644 --- a/win32ss/user/ntuser/message.c +++ b/win32ss/user/ntuser/message.c @@ -1548,7 +1548,7 @@ co_IntSendMessageWithCallBack( HWND hWnd, { RETURN(FALSE); } - + ptiSendTo = IntSendTo(Window, Win32Thread, Msg); if (Msg & 0x80000000 && @@ -2755,7 +2755,7 @@ NtUserMessageCall( HWND hWnd, ((ClientInfo->CI_flags & CI_CURTHPRHOOK) ? 1 : 0), (LPARAM)&CWP, Hook->Proc, - Hook->ihmod, + Hook->ihmod, Hook->offPfn, Hook->Ansi, &Hook->ModuleName); @@ -2774,7 +2774,7 @@ NtUserMessageCall( HWND hWnd, ((ClientInfo->CI_flags & CI_CURTHPRHOOK) ? 1 : 0), (LPARAM)&CWPR, Hook->Proc, - Hook->ihmod, + Hook->ihmod, Hook->offPfn, Hook->Ansi, &Hook->ModuleName); @@ -2833,7 +2833,7 @@ NtUserWaitForInputIdle( IN HANDLE hProcess, Status = ObReferenceObjectByHandle(hProcess, PROCESS_QUERY_INFORMATION, - PsProcessType, + *PsProcessType, UserMode, (PVOID*)&Process, NULL); diff --git a/win32ss/user/ntuser/misc.c b/win32ss/user/ntuser/misc.c index 52f0abe377c..4b64a13a89c 100644 --- a/win32ss/user/ntuser/misc.c +++ b/win32ss/user/ntuser/misc.c @@ -223,7 +223,7 @@ NtUserGetThreadState( break; case THREADSTATE_INSENDMESSAGE: { - PUSER_SENT_MESSAGE Message = + PUSER_SENT_MESSAGE Message = ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->pusmCurrent; ERR("THREADSTATE_INSENDMESSAGE\n"); @@ -243,7 +243,7 @@ NtUserGetThreadState( if (Message->QS_Flags & QS_SMRESULT) ret |= ISMEX_REPLIED; } - break; + break; } case THREADSTATE_GETMESSAGETIME: ret = ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->timeLast; @@ -289,7 +289,7 @@ NtUserSetThreadState( DWORD Ret = 0; // Test the only flags user can change. if (Set & ~(QF_FF10STATUS|QF_DIALOGACTIVE|QF_TABSWITCHING|QF_FMENUSTATUS|QF_FMENUSTATUSBREAK)) return 0; - if (Flags & ~(QF_FF10STATUS|QF_DIALOGACTIVE|QF_TABSWITCHING|QF_FMENUSTATUS|QF_FMENUSTATUSBREAK)) return 0; + if (Flags & ~(QF_FF10STATUS|QF_DIALOGACTIVE|QF_TABSWITCHING|QF_FMENUSTATUS|QF_FMENUSTATUSBREAK)) return 0; UserEnterExclusive(); pti = PsGetCurrentThreadWin32Thread(); if (pti->MessageQueue) @@ -448,7 +448,7 @@ NtUserGetGuiResources( Status = ObReferenceObjectByHandle(hProcess, PROCESS_QUERY_INFORMATION, - PsProcessType, + *PsProcessType, ExGetPreviousMode(), (PVOID*)&Process, NULL); @@ -656,7 +656,7 @@ void UserDbgAssertThreadInfo(BOOL showCaller) ASSERT(pci->ulClientDelta == DesktopHeapGetUserDelta()); if (pti->pcti && pci->pDeskInfo) ASSERT(pci->pClientThreadInfo == (PVOID)((ULONG_PTR)pti->pcti - pci->ulClientDelta)); - if (pti->KeyboardLayout) + if (pti->KeyboardLayout) ASSERT(pci->hKL == pti->KeyboardLayout->hkl); if(pti->rpdesk != NULL) ASSERT(pti->pDeskInfo == pti->rpdesk->pDeskInfo); diff --git a/win32ss/user/ntuser/misc/rtlstr.c b/win32ss/user/ntuser/misc/rtlstr.c index e4ee395c39d..73c92bf7bde 100644 --- a/win32ss/user/ntuser/misc/rtlstr.c +++ b/win32ss/user/ntuser/misc/rtlstr.c @@ -19,11 +19,11 @@ RtlInitLargeAnsiString( IN PCSZ SourceString, IN INT Unknown) { - ULONG DestSize; + USHORT DestSize; if (SourceString) { - DestSize = strlen(SourceString); + DestSize = (USHORT)strlen(SourceString); DestinationString->Length = DestSize; DestinationString->MaximumLength = DestSize + sizeof(CHAR); } @@ -44,11 +44,11 @@ RtlInitLargeUnicodeString( IN PCWSTR SourceString, IN INT Unknown) { - ULONG DestSize; + USHORT DestSize; if (SourceString) { - DestSize = wcslen(SourceString) * sizeof(WCHAR); + DestSize = (USHORT)wcslen(SourceString) * sizeof(WCHAR); DestinationString->Length = DestSize; DestinationString->MaximumLength = DestSize + sizeof(WCHAR); } diff --git a/win32ss/user/ntuser/userfuncs.h b/win32ss/user/ntuser/userfuncs.h index 96935084a42..2e45bc6e4f7 100644 --- a/win32ss/user/ntuser/userfuncs.h +++ b/win32ss/user/ntuser/userfuncs.h @@ -1,6 +1,9 @@ #pragma once -PMENU FASTCALL UserGetMenuObject(HMENU hMenu); +FORCEINLINE PMENU UserGetMenuObject(HMENU hMenu) +{ + return ValidateHandle(hMenu, TYPE_MENU); +} #define ASSERT_REFS_CO(_obj_) \ { \ diff --git a/win32ss/user/ntuser/window.c b/win32ss/user/ntuser/window.c index 6e95a3e6b8d..6259742e623 100644 --- a/win32ss/user/ntuser/window.c +++ b/win32ss/user/ntuser/window.c @@ -953,6 +953,11 @@ IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu) SysMenu->fFlags |= MNF_SYSDESKMN; SysMenu->hWnd = Window->head.h; hNewMenu = co_IntLoadSysMenuTemplate(); + //if ( Window->ExStyle & WS_EX_MDICHILD ) + //hNewMenu = co_IntCallLoadMenu( NULL, L"SYSMENUMDI"); + // else + //hNewMenu = co_IntCallLoadMenu( NULL, L"SYSMENU"); + // Do the rest in here. if(!hNewMenu) { IntReleaseMenuObject(SysMenu); @@ -985,7 +990,7 @@ IntGetSystemMenu(PWND Window, BOOL bRevert, BOOL RetMenu) ItemInfo.dwTypeData = NULL; ItemInfo.cch = 0; ItemInfo.hSubMenu = NewMenu->head.h; - IntInsertMenuItem(SysMenu, (UINT) -1, TRUE, &ItemInfo); + IntInsertMenuItem(SysMenu, (UINT) -1, TRUE, &ItemInfo, NULL); Window->SystemMenu = SysMenu->head.h; diff --git a/win32ss/user/ntuser/winpos.c b/win32ss/user/ntuser/winpos.c index 5ad490abfb6..f11f57c6553 100644 --- a/win32ss/user/ntuser/winpos.c +++ b/win32ss/user/ntuser/winpos.c @@ -1710,6 +1710,7 @@ co_WinPosSetWindowPos( RECTL valid_rects[2]; PROSRGNDATA VisRgn; HRGN VisBefore = NULL; + HRGN VisBeforeJustClient = NULL; HRGN VisAfter = NULL; HRGN DirtyRgn = NULL; HRGN ExposedRgn = NULL; @@ -1806,6 +1807,28 @@ co_WinPosSetWindowPos( RGNOBJAPI_Unlock(VisRgn); NtGdiOffsetRgn(VisBefore, -Window->rcWindow.left, -Window->rcWindow.top); } + + /* Calculate the non client area for resizes, as this is used in the copy region */ + if (!(WinPos.flags & SWP_NOSIZE)) + { + VisBeforeJustClient = VIS_ComputeVisibleRegion(Window, TRUE, FALSE, + (Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE); + VisRgn = NULL; + + if ( VisBeforeJustClient != NULL && + (VisRgn = (PROSRGNDATA)RGNOBJAPI_Lock(VisBeforeJustClient, NULL)) && + REGION_Complexity(VisRgn) == NULLREGION ) + { + RGNOBJAPI_Unlock(VisRgn); + GreDeleteObject(VisBeforeJustClient); + VisBeforeJustClient = NULL; + } + else if(VisRgn) + { + RGNOBJAPI_Unlock(VisRgn); + NtGdiOffsetRgn(VisBeforeJustClient, -Window->rcWindow.left, -Window->rcWindow.top); + } + } } } @@ -1909,8 +1932,6 @@ co_WinPosSetWindowPos( ((WinPos.flags & SWP_NOSIZE) || !(WvrFlags & WVR_REDRAW)) && !(Window->ExStyle & WS_EX_TRANSPARENT) ) { - CopyRgn = IntSysCreateRectRgn(0, 0, 0, 0); - RgnType = NtGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND); /* * If this is (also) a window resize, the whole nonclient area @@ -1920,19 +1941,14 @@ co_WinPosSetWindowPos( * we don't have to crop (can't take anything away from an empty * region...) */ - if (!(WinPos.flags & SWP_NOSIZE) && - RgnType != ERROR && - RgnType != NULLREGION ) + + CopyRgn = IntSysCreateRectRgn(0, 0, 0, 0); + if (WinPos.flags & SWP_NOSIZE) + RgnType = NtGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND); + else if (VisBeforeJustClient != NULL) { - PROSRGNDATA pCopyRgn; - RECTL ORect = OldClientRect; - RECTL NRect = NewClientRect; - RECTL_vOffsetRect(&ORect, - OldWindowRect.left, - OldWindowRect.top); - RECTL_vOffsetRect(&NRect, - NewWindowRect.left, - NewWindowRect.top); - RECTL_bIntersectRect(&CopyRect, &ORect, &NRect); - pCopyRgn = RGNOBJAPI_Lock(CopyRgn, NULL); - REGION_CropAndOffsetRegion(pCopyRgn, pCopyRgn, &CopyRect, NULL); - RGNOBJAPI_Unlock(pCopyRgn); + RgnType = NtGdiCombineRgn(CopyRgn, VisAfter, VisBeforeJustClient, RGN_AND); + GreDeleteObject(VisBeforeJustClient); } /* No use in copying bits which are in the update region. */ diff --git a/win32ss/user/user32/windows/accel.c b/win32ss/user/user32/windows/accel.c index 40db647e99a..cc25f91486e 100644 --- a/win32ss/user/user32/windows/accel.c +++ b/win32ss/user/user32/windows/accel.c @@ -344,21 +344,26 @@ HACCEL WINAPI CreateAcceleratorTableA(LPACCEL lpaccl, int cEntries) */ int WINAPI TranslateAcceleratorA(HWND hWnd, HACCEL hAccTable, LPMSG lpMsg) { - MSG mCopy = *lpMsg; - CHAR cChar; - WCHAR wChar; - NTSTATUS Status; + switch (lpMsg->message) + { + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + return TranslateAcceleratorW( hWnd, hAccTable, lpMsg ); - if(!U32IsValidAccelMessage(lpMsg->message)) return 0; + case WM_CHAR: + case WM_SYSCHAR: + { + MSG msgW = *lpMsg; + char ch = LOWORD(lpMsg->wParam); + WCHAR wch; + MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wch, 1); + msgW.wParam = MAKEWPARAM(wch, HIWORD(lpMsg->wParam)); + return TranslateAcceleratorW( hWnd, hAccTable, &msgW ); + } - Status = RtlMultiByteToUnicodeN(&wChar, sizeof(wChar), NULL, &cChar, sizeof(cChar)); - if(!NT_SUCCESS(Status)) - { - SetLastError(RtlNtStatusToDosError(Status)); - return 0; - } - - return TranslateAcceleratorW(hWnd, hAccTable, &mCopy); + default: + return 0; + } } /* EOF */ diff --git a/win32ss/user/user32/windows/mdi.c b/win32ss/user/user32/windows/mdi.c index ba844d0da22..ae867416199 100644 --- a/win32ss/user/user32/windows/mdi.c +++ b/win32ss/user/user32/windows/mdi.c @@ -897,8 +897,11 @@ static BOOL MDI_AugmentFrameMenu( HWND frame, HWND hChild ) nItems = GetMenuItemCount(menu) - 1; iId = GetMenuItemID(menu,nItems) ; if (iId == SC_RESTORE || iId == SC_CLOSE) + { + ERR("system buttons already exist\n"); return 0; - + } +//// End /* create a copy of sysmenu popup and insert it into frame menu bar */ if (!(hSysPopup = GetSystemMenu(hChild, FALSE))) { @@ -907,21 +910,14 @@ static BOOL MDI_AugmentFrameMenu( HWND frame, HWND hChild ) } AppendMenuW(menu, MF_HELP | MF_BITMAP, - SC_MINIMIZE, (LPCWSTR)HBMMENU_MBAR_MINIMIZE ) ; + SC_CLOSE, is_close_enabled(hChild, hSysPopup) ? + (LPCWSTR)HBMMENU_MBAR_CLOSE : (LPCWSTR)HBMMENU_MBAR_CLOSE_D ); AppendMenuW(menu, MF_HELP | MF_BITMAP, SC_RESTORE, (LPCWSTR)HBMMENU_MBAR_RESTORE ); AppendMenuW(menu, MF_HELP | MF_BITMAP, - SC_CLOSE, is_close_enabled(hChild, hSysPopup) ? - (LPCWSTR)HBMMENU_MBAR_CLOSE : (LPCWSTR)HBMMENU_MBAR_CLOSE_D ); + SC_MINIMIZE, (LPCWSTR)HBMMENU_MBAR_MINIMIZE ) ; /* The system menu is replaced by the child icon */ -/* hIcon = (HICON)GetClassLongPtrW(hChild, GCLP_HICONSM); - if (!hIcon) - hIcon = (HICON)GetClassLongPtrW(hChild, GCLP_HICON); - if (!hIcon) - hIcon = LoadIconW(NULL, IDI_APPLICATION); -*/ -//// End hIcon = (HICON)SendMessageW(hChild, WM_GETICON, ICON_SMALL, 0); if (!hIcon) hIcon = (HICON)SendMessageW(hChild, WM_GETICON, ICON_BIG, 0); @@ -990,7 +986,10 @@ static BOOL MDI_RestoreFrameMenu( HWND frame, HWND hChild, HBITMAP hBmpClose ) nItems = GetMenuItemCount(menu) - 1; iId = GetMenuItemID(menu,nItems) ; if( !(iId == SC_RESTORE || iId == SC_CLOSE) ) + { + ERR("no system buttons then nothing to do\n"); return 0; + } /* * Remove the system menu, If that menu is the icon of the window @@ -1534,9 +1533,7 @@ LRESULT WINAPI DefMDIChildProcA( HWND hwnd, UINT message, case WM_CHILDACTIVATE: case WM_SYSCOMMAND: case WM_SHOWWINDOW: -#ifndef __REACTOS__ case WM_SETVISIBLE: -#endif case WM_SIZE: case WM_NEXTMENU: case WM_SYSCHAR: @@ -1613,9 +1610,8 @@ LRESULT WINAPI DefMDIChildProcW( HWND hwnd, UINT message, break; case WM_SHOWWINDOW: -#ifndef __REACTOS__ case WM_SETVISIBLE: -#endif //// Commented out r57663 + //// Commented out r57663 /*if (ci->hwndChildMaximized) ci->mdiFlags &= ~MDIF_NEEDUPDATE; else*/ MDI_PostUpdate(client, ci, SB_BOTH+1); break; diff --git a/win32ss/user/user32/windows/menu.c b/win32ss/user/user32/windows/menu.c index 7470a3c8f9f..08e33325c31 100644 --- a/win32ss/user/user32/windows/menu.c +++ b/win32ss/user/user32/windows/menu.c @@ -15,6 +15,8 @@ LRESULT DefWndNCPaint(HWND hWnd, HRGN hRgn, BOOL Active); BOOL WINAPI GdiValidateHandle(HGDIOBJ hobj); +LRESULT DefWndNCHitTest(HWND hWnd, POINT Point); +void FASTCALL NcGetSysPopupPos(HWND Wnd, RECT *Rect); WINE_DEFAULT_DEBUG_CHANNEL(menu); @@ -132,7 +134,23 @@ static SIZE MenuCharSize; */ FORCEINLINE PMENU MENU_GetMenu(HMENU hMenu) { - return ValidateHandle(hMenu, TYPE_MENU); + return ValidateHandleNoErr(hMenu, TYPE_MENU); +} + +/*********************************************************************** + * get_win_sys_menu + * + * Get the system menu of a window + */ +static HMENU get_win_sys_menu( HWND hwnd ) +{ + HMENU ret = 0; + WND *win = ValidateHwnd( hwnd ); + if (win) + { + ret = win->SystemMenu; + } + return ret; } /*********************************************************************** @@ -154,22 +172,13 @@ ITEM *MENU_FindItem( HMENU *hmenu, UINT *nPos, UINT wFlags ) { if (*nPos >= menu->cItems) return NULL; pItem = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL; - //pItem = &menu->rgItems[*nPos]; - i = 0; - while(pItem) // Do this for now. - { - if (i < (INT)menu->cItems) - { - if ( *nPos == i ) return pItem; - } - pItem = pItem->Next ? DesktopPtrToUser(pItem->Next) : NULL; - i++; - } + if (pItem) pItem = &pItem[*nPos]; + return pItem; } else { PITEM item = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL; - for (i = 0; item ,i < menu->cItems; i++, item = item->Next ? DesktopPtrToUser(item->Next) : NULL)//, item++) + for (i = 0; item, i < menu->cItems; i++, item++) { if (item->spSubMenu) { @@ -206,41 +215,33 @@ ITEM *MENU_FindItem( HMENU *hmenu, UINT *nPos, UINT wFlags ) UINT FASTCALL IntGetMenuDefaultItem(PMENU Menu, BOOL fByPos, UINT gmdiFlags, DWORD *gismc) { - UINT x = 0; - UINT res = -1; - UINT sres; + UINT i = 0; PITEM Item = Menu->rgItems ? DesktopPtrToUser(Menu->rgItems) : NULL; - while(Item) + /* empty menu */ + if (!Item) return -1; + + while ( !( Item->fState & MFS_DEFAULT ) ) { - if (Item->fState & MFS_DEFAULT) - { - if (!(gmdiFlags & GMDI_USEDISABLED) && - (Item->fState & MFS_DISABLED) ) - break; - - res = fByPos ? x : Item->wID; - - if ((*gismc < MAX_GOINTOSUBMENU) && - (gmdiFlags & GMDI_GOINTOPOPUPS) && - Item->spSubMenu) - { - if (DesktopPtrToUser(Item->spSubMenu) == Menu) - break; - - (*gismc)++; - sres = IntGetMenuDefaultItem( DesktopPtrToUser(Item->spSubMenu), fByPos, gmdiFlags, gismc); - (*gismc)--; - - if(sres > (UINT)-1) - res = sres; - } - break; - } - Item = Item->Next ? DesktopPtrToUser(Item->Next) : NULL; - x++; + i++; Item++; + if (i >= Menu->cItems ) return -1; } - return res; + + /* default: don't return disabled items */ + if ( (!(GMDI_USEDISABLED & gmdiFlags)) && (Item->fState & MFS_DISABLED )) return -1; + + /* search rekursiv when needed */ + if ( (Item->fType & MF_POPUP) && (gmdiFlags & GMDI_GOINTOPOPUPS) && Item->spSubMenu) + { + UINT ret; + (*gismc)++; + ret = IntGetMenuDefaultItem( DesktopPtrToUser(Item->spSubMenu), fByPos, gmdiFlags, gismc ); + (*gismc)--; + if ( -1 != ret ) return ret; + + /* when item not found in submenu, return the popup item */ + } + return ( fByPos ) ? i : Item->wID; } static BOOL GetMenuItemInfo_common ( HMENU hmenu, @@ -256,7 +257,6 @@ static BOOL GetMenuItemInfo_common ( HMENU hmenu, if (!pItem) { SetLastError( ERROR_MENU_ITEM_NOT_FOUND); - //SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } @@ -339,7 +339,7 @@ static BOOL GetMenuItemInfo_common ( HMENU hmenu, lpmii->hbmpItem = pItem->hbmp; if (lpmii->fMask & MIIM_STATE) - lpmii->fState = pItem->fState & MII_STATE_MASK; //MENUITEMINFO_STATE_MASK; + lpmii->fState = pItem->fState & MENUITEMINFO_STATE_MASK; if (lpmii->fMask & MIIM_ID) lpmii->wID = pItem->wID; @@ -377,7 +377,7 @@ static BOOL FASTCALL MenuGetRosMenuInfo(PROSMENUINFO MenuInfo, HMENU Menu) { PMENU pMenu; - if (!(pMenu = ValidateHandle(Menu, TYPE_MENU))) return FALSE; + if (!(pMenu = ValidateHandleNoErr(Menu, TYPE_MENU))) return FALSE; MenuInfo->hbrBack = pMenu->hbrBack; MenuInfo->dwContextHelpID = pMenu->dwContextHelpId; @@ -518,6 +518,10 @@ MenuSetRosMenuItemInfo(HMENU Menu, UINT Index, PROSMENUITEMINFO ItemInfo) { ItemInfo->cch = strlenW(ItemInfo->dwTypeData); } + if (ItemInfo->hSubMenu) + { + if (!IsMenu(ItemInfo->hSubMenu)) ItemInfo->hSubMenu = NULL; + } Ret = NtUserThunkedMenuItemInfo(Menu, Index, TRUE, FALSE, (LPMENUITEMINFOW)ItemInfo, NULL); return Ret; } @@ -537,139 +541,6 @@ MenuCleanupRosMenuItemInfo(PROSMENUITEMINFO ItemInfo) } } -DWORD FASTCALL -IntBuildMenuItemList(PMENU MenuObject, PVOID Buffer, ULONG nMax) -{ - DWORD res = 0; - ROSMENUITEMINFO mii; - PVOID Buf; - PITEM CurItem = MenuObject->rgItems ? DesktopPtrToUser(MenuObject->rgItems) : NULL; - PWCHAR StrOut; - WCHAR NulByte; - - if (0 != nMax) - { - if (nMax < MenuObject->cItems * sizeof(ROSMENUITEMINFO)) - { - return 0; - } - StrOut = (PWCHAR)((char *) Buffer + MenuObject->cItems * sizeof(ROSMENUITEMINFO)); - nMax -= MenuObject->cItems * sizeof(ROSMENUITEMINFO); - Buf = Buffer; - mii.cbSize = sizeof(ROSMENUITEMINFO); - mii.fMask = 0; - NulByte = L'\0'; - - while (NULL != CurItem) - { - mii.cch = CurItem->lpstr.Length / sizeof(WCHAR); - mii.dwItemData = CurItem->dwItemData; - if (0 != CurItem->lpstr.Length) - { - mii.dwTypeData = StrOut; - } - else - { - mii.dwTypeData = NULL; - } - mii.fState = CurItem->fState; - mii.fType = CurItem->fType; - mii.wID = CurItem->wID; - mii.hbmpChecked = CurItem->hbmpChecked; - mii.hbmpItem = CurItem->hbmp; - mii.hbmpUnchecked = CurItem->hbmpUnchecked; - if (CurItem->spSubMenu) - { - PMENU pSubMenu = DesktopPtrToUser(CurItem->spSubMenu); - HMENU hSubMenu = UserHMGetHandle(pSubMenu); - mii.hSubMenu = hSubMenu; - } - else - mii.hSubMenu = NULL; - mii.Rect.left = CurItem->xItem; - mii.Rect.top = CurItem->yItem; - mii.Rect.right = CurItem->cxItem; // Do this for now...... - mii.Rect.bottom = CurItem->cyItem; - mii.dxTab = CurItem->dxTab; - mii.lpstr = CurItem->lpstr.Buffer; // Can be read from user side! - //mii.maxBmpSize.cx = CurItem->cxBmp; - //mii.maxBmpSize.cy = CurItem->cyBmp; - - RtlCopyMemory(Buf, &mii, sizeof(ROSMENUITEMINFO)); - Buf = (PVOID)((ULONG_PTR)Buf + sizeof(ROSMENUITEMINFO)); - - if (0 != CurItem->lpstr.Length && (nMax >= CurItem->lpstr.Length + sizeof(WCHAR))) - { - LPWSTR lpstr = CurItem->lpstr.Buffer ? DesktopPtrToUser(CurItem->lpstr.Buffer) : NULL; - if (lpstr) - { - /* Copy string */ - RtlCopyMemory(StrOut, lpstr, CurItem->lpstr.Length); - - StrOut += CurItem->lpstr.Length / sizeof(WCHAR); - RtlCopyMemory(StrOut, &NulByte, sizeof(WCHAR)); - StrOut++; - nMax -= CurItem->lpstr.Length + sizeof(WCHAR); - } - } - else if (0 != CurItem->lpstr.Length) - { - break; - } - - CurItem = CurItem->Next ? DesktopPtrToUser(CurItem->Next) : NULL; - res++; - } - } - else - { - while (NULL != CurItem) - { - res += sizeof(ROSMENUITEMINFO) + CurItem->lpstr.Length + sizeof(WCHAR); - CurItem = CurItem->Next ? DesktopPtrToUser(CurItem->Next) : NULL; - } - } - return res; -} - -/*********************************************************************** - * MenuGetAllRosMenuItemInfo - * - * Get full information about all menu items - */ -static INT FASTCALL -MenuGetAllRosMenuItemInfo(HMENU Menu, PROSMENUITEMINFO *ItemInfo) -{ - DWORD BufSize; - PMENU pMenu; - - if (!(pMenu = ValidateHandle(Menu, TYPE_MENU))) return -1; - - BufSize = IntBuildMenuItemList(pMenu, (PVOID)1, 0); - if (BufSize == (DWORD) -1 || BufSize == 0) - { - return -1; - } - *ItemInfo = HeapAlloc(GetProcessHeap(), 0, BufSize); - if (NULL == *ItemInfo) - { - return -1; - } - - return IntBuildMenuItemList(pMenu, (PVOID)*ItemInfo, BufSize); -} - -/*********************************************************************** - * MenuCleanupAllRosMenuItemInfo - * - * Cleanup after use of MenuGetAllRosMenuItemInfo - */ -static VOID FASTCALL -MenuCleanupAllRosMenuItemInfo(PROSMENUITEMINFO ItemInfo) -{ - HeapFree(GetProcessHeap(), 0, ItemInfo); -} - /*********************************************************************** * MenuInitSysMenuPopup * @@ -718,22 +589,27 @@ void FASTCALL MenuInitSysMenuPopup(HMENU hmenu, DWORD style, DWORD clsStyle, LON * PROSMENUINFO MenuInfo) * *****************************************************************************/ -static UINT MenuGetStartOfNextColumn( - PROSMENUINFO MenuInfo) + +static UINT MENU_GetStartOfNextColumn( + HMENU hMenu ) { - PROSMENUITEMINFO MenuItems; + MENU *menu = MENU_GetMenu(hMenu); + PITEM pItem; UINT i; - i = MenuInfo->iItem; - if ( i == NO_SELECTED_ITEM ) - return i; + if(!menu) + return NO_SELECTED_ITEM; - if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0) - return NO_SELECTED_ITEM; + i = menu->iItem + 1; + if( i == NO_SELECTED_ITEM ) + return i; - for (i++ ; i < MenuInfo->cItems; i++) - if (0 != (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK))) - return i; + pItem = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL; + if (!pItem) return NO_SELECTED_ITEM; + for( ; i < menu->cItems; ++i ) { + if (pItem[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK)) + return i; + } return NO_SELECTED_ITEM; } @@ -744,38 +620,36 @@ static UINT MenuGetStartOfNextColumn( * PROSMENUINFO MenuInfo) * *****************************************************************************/ - -static UINT FASTCALL MenuGetStartOfPrevColumn( - PROSMENUINFO MenuInfo) +static UINT MENU_GetStartOfPrevColumn( + HMENU hMenu ) { - PROSMENUITEMINFO MenuItems; - UINT i; + MENU *menu = MENU_GetMenu(hMenu); + UINT i; + PITEM pItem; - if (!MenuInfo->iItem || MenuInfo->iItem == NO_SELECTED_ITEM) - return NO_SELECTED_ITEM; + if( !menu ) + return NO_SELECTED_ITEM; - if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0) - return NO_SELECTED_ITEM; + if( menu->iItem == 0 || menu->iItem == NO_SELECTED_ITEM ) + return NO_SELECTED_ITEM; + + pItem = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL; + if (!pItem) return NO_SELECTED_ITEM; /* Find the start of the column */ - for (i = MenuInfo->iItem; - 0 != i && 0 == (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK)); - --i) - { - ; /* empty */ + + for(i = menu->iItem; i != 0 && + !(pItem[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK)); + --i); /* empty */ + + if(i == 0) + return NO_SELECTED_ITEM; + + for(--i; i != 0; --i) { + if (pItem[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK)) + break; } - if (i == 0) - { - MenuCleanupAllRosMenuItemInfo(MenuItems); - return NO_SELECTED_ITEM; - } - - for (--i; 0 != i; --i) - if (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK)) - break; - - MenuCleanupAllRosMenuItemInfo(MenuItems); TRACE("ret %d.\n", i ); return i; @@ -870,7 +744,7 @@ static UINT FASTCALL MenuFindSubMenu(HMENU *hmenu, HMENU hSubTarget ) return NO_SELECTED_ITEM; item = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL; - for (i = 0; i < menu->cItems; i++, item = item->Next ? DesktopPtrToUser(item->Next) : NULL)//item++) + for (i = 0; i < menu->cItems; i++, item++) { if (!item->spSubMenu) continue; @@ -987,58 +861,48 @@ MenuDrawPopupGlyph(HDC dc, LPRECT r, INT_PTR popupMagic, BOOL inactive, BOOL hil * Find the menu item selected by a key press. * Return item id, -1 if none, -2 if we should close the menu. */ -static UINT FASTCALL MenuFindItemByKey(HWND WndOwner, PROSMENUINFO MenuInfo, +static UINT FASTCALL MENU_FindItemByKey(HWND WndOwner, HMENU hmenu, WCHAR Key, BOOL ForceMenuChar) { - ROSMENUINFO SysMenuInfo; - PROSMENUITEMINFO Items, ItemInfo; LRESULT MenuChar; - UINT i; WORD Flags = 0; - TRACE("\tlooking for '%c' (0x%02x) in [%p]\n", (char) Key, Key, MenuInfo); + TRACE("\tlooking for '%c' (0x%02x) in [%p]\n", (char)Key, Key, hmenu ); - if (NULL == MenuInfo || ! IsMenu(MenuInfo->Self)) - { - if (MenuGetRosMenuInfo(&SysMenuInfo, GetSystemMenu(WndOwner, FALSE))) - { - MenuInfo = &SysMenuInfo; - } - else - { - MenuInfo = NULL; - } - } + if (!IsMenu( hmenu )) hmenu = GetSubMenu( get_win_sys_menu(WndOwner), 0); + if (hmenu) + { + MENU *menu = MENU_GetMenu( hmenu ); + ITEM *item = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL; - if (NULL != MenuInfo) - { - if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &Items) <= 0) - { - return -1; - } - if ( !ForceMenuChar ) - { - ItemInfo = Items; - for (i = 0; i < MenuInfo->cItems; i++, ItemInfo++) - { - if ((ItemInfo->lpstr) && NULL != ItemInfo->dwTypeData) - { - WCHAR *p = (WCHAR *) ItemInfo->dwTypeData - 2; - do - { - p = strchrW (p + 2, '&'); - } - while (p != NULL && p [1] == '&'); - if (p && (toupperW(p[1]) == toupperW(Key))) return i; - } - } - } + if( !ForceMenuChar ) + { + UINT i; + BOOL cjk = GetSystemMetrics( SM_DBCSENABLED ); - Flags |= MenuInfo->fFlags & MNF_POPUP ? MF_POPUP : 0; - Flags |= MenuInfo->fFlags & MNF_SYSDESKMN ? MF_SYSMENU : 0; + for (i = 0; i < menu->cItems; i++, item++) + { + LPWSTR text = item->Xlpstr ? DesktopPtrToUser(item->Xlpstr) : NULL; + if( text) + { + const WCHAR *p = text - 2; + do + { + const WCHAR *q = p + 2; + p = strchrW (q, '&'); + if (!p && cjk) p = strchrW (q, '\036'); /* Japanese Win16 */ + } + while (p != NULL && p [1] == '&'); + if (p && (toupperW(p[1]) == toupperW(Key))) return i; + } + } + } + + Flags |= menu->fFlags & MNF_POPUP ? MF_POPUP : 0; + Flags |= menu->fFlags & MNF_SYSDESKMN ? MF_SYSMENU : 0; MenuChar = SendMessageW(WndOwner, WM_MENUCHAR, - MAKEWPARAM(Key, Flags), (LPARAM) MenuInfo->Self); + MAKEWPARAM(Key, Flags), (LPARAM) hmenu); if (HIWORD(MenuChar) == MNC_EXECUTE) return LOWORD(MenuChar); if (HIWORD(MenuChar) == MNC_CLOSE) return (UINT)(-2); } @@ -1530,7 +1394,7 @@ static void FASTCALL MenuMenuBarCalcSize( HDC hdc, LPRECT lprect, if ((lprect == NULL) || (MenuInfo == NULL)) return; if (MenuInfo->cItems == 0) return; - TRACE("left=%ld top=%ld right=%ld bottom=%ld\n", lprect->left, lprect->top, lprect->right, lprect->bottom); + TRACE("lprect %p %s\n", lprect, wine_dbgstr_rect( lprect)); MenuInfo->cxMenu = lprect->right - lprect->left; MenuInfo->cyMenu = 0; maxY = lprect->top + 1; @@ -1689,7 +1553,6 @@ MENU_DrawScrollArrows(PROSMENUINFO lppop, HDC hdc) DeleteDC(hdcMem); } - /*********************************************************************** * MenuDrawMenuItem * @@ -1702,7 +1565,7 @@ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND Wnd PWCHAR Text; BOOL flat_menu = FALSE; int bkgnd; - PWND Wnd = ValidateHwnd(hWnd); + PWND Wnd = ValidateHwndNoErr(hWnd); if (!Wnd) return; @@ -1744,6 +1607,7 @@ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND Wnd SetBkColor( hdc, GetSysColor( bkgnd ) ); } + TRACE("rect=%s\n", wine_dbgstr_rect( &lpitem->Rect)); rect = lpitem->Rect; MENU_AdjustMenuItemRect(MenuInfo, &rect); @@ -1949,7 +1813,7 @@ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND Wnd DT_LEFT | DT_VCENTER | DT_SINGLELINE; if((MenuInfo->dwStyle & MNS_CHECKORBMP)) - rect.left += max(0, MenuInfo->cxTextAlign - GetSystemMetrics(SM_CXMENUCHECK)); + rect.left += max(0, (int)(MenuInfo->cxTextAlign - GetSystemMetrics(SM_CXMENUCHECK))); else rect.left += MenuInfo->cxTextAlign; @@ -2053,6 +1917,7 @@ static void FASTCALL MenuDrawPopupMenu(HWND hwnd, HDC hdc, HMENU hmenu ) DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT); /* draw menu items */ + //TRACE("hmenu %p Style %08x\n", hmenu, menu->dwStyle); if (MenuGetRosMenuInfo(&MenuInfo, hmenu) && MenuInfo.cItems) { UINT u; @@ -2115,6 +1980,44 @@ UINT MenuDrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd, return DrawMenuBarTemp(hwnd, hDC, lprect, hMenu, NULL); } +/*********************************************************************** + * MENU_InitPopup + * + * Popup menu initialization before WM_ENTERMENULOOP. + */ +static BOOL MENU_InitPopup( HWND hwndOwner, HMENU hmenu, UINT flags ) +{ + MENU *menu; + DWORD ex_style = 0; + ROSMENUINFO MenuInfo; + + TRACE("owner=%p hmenu=%p\n", hwndOwner, hmenu); + + if (!(menu = MENU_GetMenu( hmenu ))) return FALSE; + + /* store the owner for DrawItem */ + if (!IsWindow( hwndOwner )) + { + SetLastError( ERROR_INVALID_WINDOW_HANDLE ); + return FALSE; + } + MenuGetRosMenuInfo(&MenuInfo, menu->head.h); + //menu->hwndOwner = hwndOwner; + MenuInfo.spwndNotify = ValidateHwndNoErr( hwndOwner ); + + if (flags & TPM_LAYOUTRTL) + ex_style = WS_EX_LAYOUTRTL; + + /* NOTE: In Windows, top menu popup is not owned. */ + //menu->hWnd = CreateWindowExW( ex_style, WC_MENU, NULL, + MenuInfo.Wnd = CreateWindowExW( ex_style, WC_MENU, NULL, + WS_POPUP, 0, 0, 0, 0, + hwndOwner, 0, (HINSTANCE)GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE), + (LPVOID)hmenu ); + MenuSetRosMenuInfo(&MenuInfo); + if( !menu->hWnd ) return FALSE; + return TRUE; +} /*********************************************************************** * MenuShowPopup @@ -2130,7 +2033,6 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl POINT pt; HMONITOR monitor; MONITORINFO info; - DWORD ex_style = 0; TRACE("owner=%p hmenu=%p id=0x%04x x=0x%04x y=0x%04x xa=0x%04x ya=0x%04x\n", hwndOwner, hmenu, id, x, y, xanchor, yanchor); @@ -2149,15 +2051,9 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl MenuInfo.iItem = NO_SELECTED_ITEM; } - /* store the owner for DrawItem */ - if (!IsWindow(hwndOwner)) - { - SetLastError( ERROR_INVALID_WINDOW_HANDLE ); - return FALSE; - } - MenuInfo.spwndNotify = ValidateHwndNoErr(hwndOwner); + //menu->dwArrowsOn = 0; + MenuInfo.dwArrowsOn = 0; MenuSetRosMenuInfo(&MenuInfo); - MenuPopupMenuCalcSize(&MenuInfo, hwndOwner); /* adjust popup menu pos so that it fits within the desktop */ @@ -2173,10 +2069,8 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl GetMonitorInfoW( monitor, &info ); if (flags & TPM_LAYOUTRTL) - { - ex_style = WS_EX_LAYOUTRTL; flags ^= TPM_RIGHTALIGN; - } + if( flags & TPM_RIGHTALIGN ) x -= width; if( flags & TPM_CENTERALIGN ) x -= width / 2; @@ -2203,24 +2097,18 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl } if( y < info.rcMonitor.top ) y = info.rcMonitor.top; - /* NOTE: In Windows, top menu popup is not owned. */ - MenuInfo.Wnd = CreateWindowExW( ex_style, WC_MENU, NULL, - WS_POPUP, x, y, width, height, - hwndOwner, 0, (HINSTANCE) GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE), - (LPVOID) MenuInfo.Self); - if ( !MenuInfo.Wnd || ! MenuSetRosMenuInfo(&MenuInfo)) return FALSE; if (!top_popup) { top_popup = MenuInfo.Wnd; top_popup_hmenu = hmenu; } + /* Display the window */ + + SetWindowPos( MenuInfo.Wnd, HWND_TOPMOST, x, y, width, height, + SWP_SHOWWINDOW | SWP_NOACTIVATE); + UpdateWindow( MenuInfo.Wnd ); IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPSTART, MenuInfo.Wnd, OBJID_CLIENT, CHILDID_SELF, 0); - /* Display the window */ - - SetWindowPos( MenuInfo.Wnd, HWND_TOPMOST, 0, 0, 0, 0, - SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); - UpdateWindow( MenuInfo.Wnd ); return TRUE; } @@ -2426,7 +2314,7 @@ PopupMenuWndProcW(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam) PWND pWnd; PPOPUPMENU pPopupMenu; - pWnd = ValidateHwnd(Wnd); + pWnd = ValidateHwndNoErr(Wnd); if (pWnd) { if (!pWnd->fnid) @@ -2609,6 +2497,12 @@ PopupMenuWndProcW(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam) } break; +#ifdef __REACTOS__ + case WM_NCDESTROY: + NtUserSetWindowFNID(Wnd, FNID_DESTROY); + break; +#endif + case WM_SHOWWINDOW: if (0 != wParam) { @@ -2721,7 +2615,6 @@ static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu) return res; } - /********************************************************************** * MENUEX_ParseResource * @@ -2784,88 +2677,6 @@ static LPCSTR MENUEX_ParseResource(LPCSTR res, HMENU hMenu) return res; } -NTSTATUS WINAPI -User32LoadSysMenuTemplateForKernel(PVOID Arguments, ULONG ArgumentLength) -{ - HMENU hmenu = LoadMenuW(User32Instance, L"SYSMENU"); - LRESULT Result = (LRESULT)hmenu; - MENUINFO menuinfo = {0}; - MENUITEMINFOW info = {0}; - - // removing space for checkboxes from menu - menuinfo.cbSize = sizeof(menuinfo); - menuinfo.fMask = MIM_STYLE; - GetMenuInfo(hmenu, &menuinfo); - menuinfo.dwStyle |= MNS_CHECKORBMP; // test_menu_bmp_and_string MNS_CHECKORBMP - SetMenuInfo(hmenu, &menuinfo); - - // adding bitmaps to menu items - info.cbSize = sizeof(info); - info.fMask |= MIIM_BITMAP; - info.hbmpItem = HBMMENU_POPUP_MINIMIZE; - SetMenuItemInfoW(hmenu, SC_MINIMIZE, FALSE, &info); - info.hbmpItem = HBMMENU_POPUP_RESTORE; - SetMenuItemInfoW(hmenu, SC_RESTORE, FALSE, &info); - info.hbmpItem = HBMMENU_POPUP_MAXIMIZE; - SetMenuItemInfoW(hmenu, SC_MAXIMIZE, FALSE, &info); - info.hbmpItem = HBMMENU_POPUP_CLOSE; - SetMenuItemInfoW(hmenu, SC_CLOSE, FALSE, &info); - - return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS)); -} - - -BOOL -MenuInit(VOID) -{ - NONCLIENTMETRICSW ncm; - - /* get the menu font */ - if(!hMenuFont || !hMenuFontBold) - { - ncm.cbSize = sizeof(ncm); - if(!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0)) - { - ERR("MenuInit(): SystemParametersInfoW(SPI_GETNONCLIENTMETRICS) failed!\n"); - return FALSE; - } - - hMenuFont = CreateFontIndirectW(&ncm.lfMenuFont); - if(hMenuFont == NULL) - { - ERR("MenuInit(): CreateFontIndirectW(hMenuFont) failed!\n"); - return FALSE; - } - - ncm.lfMenuFont.lfWeight = max(ncm.lfMenuFont.lfWeight + 300, 1000); - hMenuFontBold = CreateFontIndirectW(&ncm.lfMenuFont); - if(hMenuFontBold == NULL) - { - ERR("MenuInit(): CreateFontIndirectW(hMenuFontBold) failed!\n"); - DeleteObject(hMenuFont); - hMenuFont = NULL; - return FALSE; - } - } - - return TRUE; -} - -VOID -MenuCleanup(VOID) -{ - if (hMenuFont) - { - DeleteObject(hMenuFont); - hMenuFont = NULL; - } - - if (hMenuFontBold) - { - DeleteObject(hMenuFontBold); - hMenuFontBold = NULL; - } -} /*********************************************************************** * DrawMenuBarTemp (USER32.@) @@ -2943,36 +2754,8 @@ DrawMenuBarTemp(HWND Wnd, HDC DC, LPRECT Rect, HMENU Menu, HFONT Font) return MenuInfo.cyMenu; } -#if 0 -static BOOL MENU_InitPopup( HWND hwndOwner, HMENU hmenu, UINT flags ) -{ - POPUPMENU *menu; - DWORD ex_style = 0; - TRACE("owner=%p hmenu=%p\n", hwndOwner, hmenu); - if (!(menu = MENU_GetMenu( hmenu ))) return FALSE; - - /* store the owner for DrawItem */ - if (!IsWindow( hwndOwner )) - { - SetLastError( ERROR_INVALID_WINDOW_HANDLE ); - return FALSE; - } - menu->hwndOwner = hwndOwner; - - if (flags & TPM_LAYOUTRTL) - ex_style = WS_EX_LAYOUTRTL; - - /* NOTE: In Windows, top menu popup is not owned. */ - menu->hWnd = CreateWindowExW( ex_style, (LPCWSTR)POPUPMENU_CLASS_ATOM, NULL, - WS_POPUP, 0, 0, 0, 0, - hwndOwner, 0, (HINSTANCE)GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE), - (LPVOID)hmenu ); - if( !menu->hWnd ) return FALSE; - return TRUE; -} -#endif /*********************************************************************** * MenuShowSubPopup * @@ -2982,7 +2765,6 @@ static BOOL MENU_InitPopup( HWND hwndOwner, HMENU hmenu, UINT flags ) static HMENU FASTCALL MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Flags) { - extern void FASTCALL NcGetSysPopupPos(HWND Wnd, RECT *Rect); RECT Rect; ROSMENUITEMINFO ItemInfo; ROSMENUINFO SubMenuInfo; @@ -3100,7 +2882,7 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl /* use default alignment for submenus */ Flags &= ~(TPM_CENTERALIGN | TPM_RIGHTALIGN | TPM_VCENTERALIGN | TPM_BOTTOMALIGN); - //MENU_InitPopup( WndOwner, ItemInfo.hSubMenu, Flags ); + MENU_InitPopup( WndOwner, ItemInfo.hSubMenu, Flags ); MenuShowPopup(WndOwner, ItemInfo.hSubMenu, MenuInfo->iItem, Flags, Rect.left, Rect.top, Rect.right, Rect.bottom ); @@ -3124,11 +2906,10 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl */ void MENU_EndMenu( HWND hwnd ) { - ROSMENUINFO MenuInfo; - BOOL Ret = FALSE; - if (top_popup_hmenu) - Ret = MenuGetRosMenuInfo(&MenuInfo, top_popup_hmenu); - if (Ret && hwnd == (MenuInfo.spwndNotify ? MenuInfo.spwndNotify->head.h : NULL)) EndMenu(); + MENU *menu; + menu = top_popup_hmenu ? MENU_GetMenu( top_popup_hmenu ) : NULL; + if (menu && ( hwnd == menu->hWnd || hwnd == (menu->spwndNotify ? menu->spwndNotify->head.h : NULL)) ) + EndMenu(); } /*********************************************************************** @@ -3163,13 +2944,19 @@ MenuHideSubPopups(HWND WndOwner, PROSMENUINFO MenuInfo, { MenuHideSubPopups(WndOwner, &SubMenuInfo, FALSE, wFlags); MenuSelectItem(WndOwner, &SubMenuInfo, NO_SELECTED_ITEM, SendMenuSelect, NULL); - DestroyWindow(SubMenuInfo.Wnd); - SubMenuInfo.Wnd = NULL; - MenuSetRosMenuInfo(&SubMenuInfo); + DestroyWindow(SubMenuInfo.Wnd); + /* Native returns handle to destroyed window */ if (!(wFlags & TPM_NONOTIFY)) SendMessageW( WndOwner, WM_UNINITMENUPOPUP, (WPARAM)ItemInfo.hSubMenu, MAKELPARAM(0, IS_SYSTEM_MENU(&SubMenuInfo)) ); + //// + // Call WM_UNINITMENUPOPUP FIRST before destroy!! + // Fixes todo_wine User32 test menu.c line 2233 GetMenuBarInfo callback.... + // + SubMenuInfo.Wnd = NULL; + MenuSetRosMenuInfo(&SubMenuInfo); + //// } } } @@ -3281,7 +3068,7 @@ MenuExecFocusedItem(MTRACKER *Mt, PROSMENUINFO MenuInfo, UINT Flags) * Return TRUE if we can go on with menu tracking. */ static BOOL FASTCALL -MenuButtonDown(MTRACKER* Mt, HMENU PtMenu, UINT Flags) +MENU_ButtonDown(MTRACKER* Mt, HMENU PtMenu, UINT Flags) { int Index; ROSMENUINFO MenuInfo; @@ -3344,7 +3131,7 @@ MenuButtonDown(MTRACKER* Mt, HMENU PtMenu, UINT Flags) * */ static INT FASTCALL -MenuButtonUp(MTRACKER *Mt, HMENU PtMenu, UINT Flags) +MENU_ButtonUp(MTRACKER *Mt, HMENU PtMenu, UINT Flags) { INT Id; ROSMENUINFO MenuInfo; @@ -3399,56 +3186,41 @@ MenuButtonUp(MTRACKER *Mt, HMENU PtMenu, UINT Flags) * Walks menu chain trying to find a menu pt maps to. */ static HMENU FASTCALL -MenuPtMenu(HMENU Menu, POINT Pt) +MENU_PtMenu(HMENU hMenu, POINT pt) { - extern LRESULT DefWndNCHitTest(HWND hWnd, POINT Point); - ROSMENUINFO MenuInfo; - ROSMENUITEMINFO ItemInfo; - HMENU Ret = NULL; - INT Ht; + MENU *menu; + PITEM pItem; + HMENU ret = NULL; - if (! MenuGetRosMenuInfo(&MenuInfo, Menu)) - { - return NULL; - } + menu = MENU_GetMenu( hMenu ); + if (!menu) return NULL; /* try subpopup first (if any) */ - if (NO_SELECTED_ITEM != MenuInfo.iItem) - { - MenuInitRosMenuItemInfo(&ItemInfo); - if (MenuGetRosMenuItemInfo(MenuInfo.Self, MenuInfo.iItem, &ItemInfo) && - 0 != (ItemInfo.hSubMenu) && - 0 != (ItemInfo.fState & MF_MOUSESELECT)) - { - Ret = MenuPtMenu(ItemInfo.hSubMenu, Pt); - if (NULL != Ret) - { - MenuCleanupRosMenuItemInfo(&ItemInfo); - return Ret; - } - } - MenuCleanupRosMenuItemInfo(&ItemInfo); - } + if (menu->iItem != NO_SELECTED_ITEM) + { + pItem = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL; + if ( pItem ) pItem = &pItem[menu->iItem]; + if ( pItem && pItem->spSubMenu && pItem->fState & MF_MOUSESELECT) + { + PMENU pSubMenu = DesktopPtrToUser(pItem->spSubMenu); + ret = MENU_PtMenu( UserHMGetHandle(pSubMenu), pt); + } + } /* check the current window (avoiding WM_HITTEST) */ - Ht = DefWndNCHitTest(MenuInfo.Wnd, Pt); - if (0 != (MenuInfo.fFlags & MNF_POPUP)) - { - if (HTNOWHERE != Ht && HTERROR != Ht) - { - Ret = Menu; - } - } - else if (HTSYSMENU == Ht) - { - Ret = NtUserGetSystemMenu(MenuInfo.Wnd, FALSE); - } - else if (HTMENU == Ht) - { - Ret = GetMenu(MenuInfo.Wnd); - } - - return Ret; + if (!ret) + { + INT ht = DefWndNCHitTest(menu->hWnd, pt); + if ( menu->fFlags & MNF_POPUP ) + { + if (ht != HTNOWHERE && ht != HTERROR) ret = hMenu; + } + else if (ht == HTSYSMENU) + ret = NtUserGetSystemMenu(menu->hWnd, FALSE); + else if (ht == HTMENU) + ret = GetMenu( menu->hWnd ); + } + return ret; } /*********************************************************************** @@ -3513,32 +3285,25 @@ MenuMouseMove(MTRACKER *Mt, HMENU PtMenu, UINT Flags) * * Return the handle of the selected sub-popup menu (if any). */ -static HMENU FASTCALL -MenuGetSubPopup(HMENU Menu) +static +HMENU MENU_GetSubPopup( HMENU hmenu ) { - ROSMENUINFO MenuInfo; - ROSMENUITEMINFO ItemInfo; + MENU *menu; + ITEM *item; - if (! MenuGetRosMenuInfo(&MenuInfo, Menu) - || NO_SELECTED_ITEM == MenuInfo.iItem) - { - return NULL; - } + menu = MENU_GetMenu( hmenu ); - MenuInitRosMenuItemInfo(&ItemInfo); - if (! MenuGetRosMenuItemInfo(MenuInfo.Self, MenuInfo.iItem, &ItemInfo)) - { - MenuCleanupRosMenuItemInfo(&ItemInfo); - return NULL; - } - if (0 != (ItemInfo.hSubMenu) && 0 != (ItemInfo.fState & MF_MOUSESELECT)) - { - MenuCleanupRosMenuItemInfo(&ItemInfo); - return ItemInfo.hSubMenu; - } + if ((!menu) || (menu->iItem == NO_SELECTED_ITEM)) return 0; - MenuCleanupRosMenuItemInfo(&ItemInfo); - return NULL; + //item = &menu->rgItems[menu->iItem]; + item = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL; + if (item) item = &item[menu->iItem]; + if (item && (item->spSubMenu) && (item->fState & MF_MOUSESELECT)) + { + PMENU pSubMenu = DesktopPtrToUser(item->spSubMenu); + return UserHMGetHandle(pSubMenu); + } + return 0; } /*********************************************************************** @@ -3726,7 +3491,7 @@ MenuKeyEscape(MTRACKER *Mt, UINT Flags) while (MenuTmp != Mt->CurrentMenu) { MenuPrev = MenuTmp; - MenuTmp = MenuGetSubPopup(MenuPrev); + MenuTmp = MENU_GetSubPopup(MenuPrev); } if (MenuGetRosMenuInfo(&MenuInfo, MenuPrev)) @@ -3757,13 +3522,8 @@ MenuKeyLeft(MTRACKER* Mt, UINT Flags) MenuPrev = MenuTmp = Mt->TopMenu; - if (! MenuGetRosMenuInfo(&MenuInfo, Mt->CurrentMenu)) - { - return; - } - /* Try to move 1 column left (if possible) */ - if ( (PrevCol = MenuGetStartOfPrevColumn(&MenuInfo)) != NO_SELECTED_ITEM) + if ( (PrevCol = MENU_GetStartOfPrevColumn(Mt->CurrentMenu)) != NO_SELECTED_ITEM) { if (MenuGetRosMenuInfo(&MenuInfo, Mt->CurrentMenu)) { @@ -3776,7 +3536,7 @@ MenuKeyLeft(MTRACKER* Mt, UINT Flags) while (MenuTmp != Mt->CurrentMenu) { MenuPrev = MenuTmp; - MenuTmp = MenuGetSubPopup(MenuPrev); + MenuTmp = MENU_GetSubPopup(MenuPrev); } if (! MenuGetRosMenuInfo(&PrevMenuInfo, MenuPrev)) @@ -3844,13 +3604,8 @@ static void FASTCALL MenuKeyRight(MTRACKER *Mt, UINT Flags) if (hmenutmp != Mt->CurrentMenu) return; } - if (! MenuGetRosMenuInfo(&CurrentMenuInfo, Mt->CurrentMenu)) - { - return; - } - /* Check to see if there's another column */ - if ( (NextCol = MenuGetStartOfNextColumn(&CurrentMenuInfo)) != NO_SELECTED_ITEM) + if ( (NextCol = MENU_GetStartOfNextColumn(Mt->CurrentMenu)) != NO_SELECTED_ITEM) { TRACE("Going to %d.\n", NextCol); if (MenuGetRosMenuInfo(&MenuInfo, Mt->CurrentMenu)) @@ -3899,6 +3654,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, MSG msg; ROSMENUINFO MenuInfo; ROSMENUITEMINFO ItemInfo; + PMENU menu; BOOL fRemove; INT executedMenuId = -1; MTRACKER mt; @@ -3918,12 +3674,10 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, if (!IsMenu(hmenu)) { - WARN("Invalid menu handle %p\n", hmenu); - SetLastError( ERROR_INVALID_MENU_HANDLE ); + WARN("Invalid menu handle %p\n", hmenu); // Error already set in IsMenu. return FALSE; } - fEndMenu = FALSE; if (! MenuGetRosMenuInfo(&MenuInfo, hmenu)) { return FALSE; @@ -3932,7 +3686,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, if (wFlags & TPM_BUTTONDOWN) { /* Get the result in order to start the tracking or not */ - fRemove = MenuButtonDown( &mt, hmenu, wFlags ); + fRemove = MENU_ButtonDown( &mt, hmenu, wFlags ); fEndMenu = !fRemove; } @@ -3943,10 +3697,10 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, NtUserxSetGUIThreadHandle(MSQ_STATE_MENUOWNER, capture_win); // 1 SetCapture(capture_win); // 2 - while (! fEndMenu) + while (!fEndMenu) { BOOL ErrorExit = FALSE; - PMENU menu = ValidateHandle(mt.CurrentMenu, TYPE_MENU); + menu = MENU_GetMenu( mt.CurrentMenu ); if (!menu) /* sometimes happens if I do a window manager close */ break; @@ -3964,7 +3718,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, else { /* ReactOS Check */ - if (!ValidateHwnd(mt.OwnerWnd) || !ValidateHwnd(MenuInfo.Wnd)) + if (!ValidateHwndNoErr(mt.OwnerWnd) || !ValidateHwndNoErr(MenuInfo.Wnd)) { ErrorExit = TRUE; // Do not wait on dead windows, now test_capture_4 works. break; @@ -4012,14 +3766,13 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, mt.Pt.y = (short)HIWORD(msg.lParam); /* Find a menu for this mouse event */ - hmenu = MenuPtMenu(mt.TopMenu, mt.Pt); + hmenu = MENU_PtMenu(mt.TopMenu, mt.Pt); switch(msg.message) { /* no WM_NC... messages in captured state */ case WM_RBUTTONDBLCLK: - ERR("WM_RBUTTONDBLCLK\n"); case WM_RBUTTONDOWN: if (!(wFlags & TPM_RIGHTBUTTON)) break; /* fall through */ @@ -4027,7 +3780,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, case WM_LBUTTONDOWN: /* If the message belongs to the menu, removes it from the queue */ /* Else, end menu tracking */ - fRemove = MenuButtonDown(&mt, hmenu, wFlags); + fRemove = MENU_ButtonDown(&mt, hmenu, wFlags); fEndMenu = !fRemove; break; @@ -4038,7 +3791,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, /* Check if a menu was selected by the mouse */ if (hmenu) { - executedMenuId = MenuButtonUp( &mt, hmenu, wFlags); + executedMenuId = MENU_ButtonUp( &mt, hmenu, wFlags); TRACE("executedMenuId %d\n", executedMenuId); /* End the loop if executedMenuId is an item ID */ @@ -4080,10 +3833,8 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, case VK_END: if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu)) { - MenuSelectItem(mt.OwnerWnd, &MenuInfo, - NO_SELECTED_ITEM, FALSE, 0 ); - MenuMoveSelection(mt.OwnerWnd, &MenuInfo, - VK_HOME == msg.wParam ? ITEM_NEXT : ITEM_PREV); + MenuSelectItem(mt.OwnerWnd, &MenuInfo, NO_SELECTED_ITEM, FALSE, 0 ); + MenuMoveSelection(mt.OwnerWnd, &MenuInfo, VK_HOME == msg.wParam ? ITEM_NEXT : ITEM_PREV); } break; @@ -4097,8 +3848,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, mt.CurrentMenu = MenuShowSubPopup(mt.OwnerWnd, &MenuInfo, TRUE, wFlags); } else /* otherwise try to move selection */ - MenuMoveSelection(mt.OwnerWnd, &MenuInfo, - (msg.wParam == VK_UP)? ITEM_PREV : ITEM_NEXT ); + MenuMoveSelection(mt.OwnerWnd, &MenuInfo, (msg.wParam == VK_UP)? ITEM_PREV : ITEM_NEXT ); } break; @@ -4168,14 +3918,12 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, /* We will find a better way real soon... */ if (msg.wParam < 32) break; - pos = MenuFindItemByKey(mt.OwnerWnd, &MenuInfo, - LOWORD(msg.wParam), FALSE); + pos = MENU_FindItemByKey(mt.OwnerWnd, mt.CurrentMenu, LOWORD(msg.wParam), FALSE); if (pos == (UINT)-2) fEndMenu = TRUE; else if (pos == (UINT)-1) MessageBeep(0); else { - MenuSelectItem(mt.OwnerWnd, &MenuInfo, pos, - TRUE, 0); + MenuSelectItem(mt.OwnerWnd, &MenuInfo, pos, TRUE, 0); executedMenuId = MenuExecFocusedItem(&mt, &MenuInfo, wFlags); fEndMenu = (executedMenuId != -2); } @@ -4219,6 +3967,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPEND, MenuInfo.Wnd, OBJID_CLIENT, CHILDID_SELF, 0); DestroyWindow(MenuInfo.Wnd); MenuInfo.Wnd = NULL; + MenuSetRosMenuInfo(&MenuInfo); if (!(wFlags & TPM_NONOTIFY)) SendMessageW( mt.OwnerWnd, WM_UNINITMENUPOPUP, (WPARAM)mt.TopMenu, @@ -4259,11 +4008,19 @@ static BOOL FASTCALL MenuInitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT * It also enables menus to be displayed in more than one window, * but there are some bugs left that need to be fixed in this case. */ - if (MenuGetRosMenuInfo(&MenuInfo, hMenu)) + if (!bPopup && (MenuGetRosMenuInfo(&MenuInfo, hMenu))) { MenuInfo.Wnd = hWnd; MenuSetRosMenuInfo(&MenuInfo); } + //if (!bPopup) menu->hWnd = hWnd; + if (!top_popup) + { + top_popup = MenuInfo.Wnd;//menu->hWnd; + top_popup_hmenu = hMenu; + } + + fEndMenu = FALSE; /* Send WM_ENTERMENULOOP and WM_INITMENU message only if TPM_NONOTIFY flag is not specified */ if (!(wFlags & TPM_NONOTIFY)) @@ -4294,6 +4051,7 @@ static BOOL FASTCALL MenuInitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT CHILDID_SELF, 0); return TRUE; } + /*********************************************************************** * MenuExitTracking */ @@ -4337,7 +4095,6 @@ VOID MenuTrackMouseMenuBar( HWND hWnd, ULONG ht, POINT pt) } } - /*********************************************************************** * MenuTrackKbdMenuBar * @@ -4373,6 +4130,9 @@ VOID MenuTrackKbdMenuBar(HWND hwnd, UINT wParam, WCHAR wChar) MenuInitTracking( hwnd, hTrackMenu, FALSE, wFlags ); + /* fetch the window menu again, it may have changed */ + hTrackMenu = (wParam & HTSYSMENU) ? get_win_sys_menu( hwnd ) : GetMenu( hwnd ); + if (! MenuGetRosMenuInfo(&MenuInfo, hTrackMenu)) { goto track_menu; @@ -4380,7 +4140,7 @@ VOID MenuTrackKbdMenuBar(HWND hwnd, UINT wParam, WCHAR wChar) if( wChar && wChar != ' ' ) { - uItem = MenuFindItemByKey( hwnd, &MenuInfo, wChar, (wParam & HTSYSMENU) ); + uItem = MENU_FindItemByKey( hwnd, hTrackMenu, wChar, (wParam & HTSYSMENU) ); if ( uItem >= (UINT)(-2) ) { if( uItem == (UINT)(-1) ) MessageBeep(0); @@ -4408,42 +4168,59 @@ track_menu: /********************************************************************** * TrackPopupMenuEx (USER32.@) */ -BOOL WINAPI TrackPopupMenuEx( HMENU Menu, UINT Flags, int x, int y, - HWND Wnd, LPTPMPARAMS Tpm) +BOOL WINAPI TrackPopupMenuEx( HMENU hMenu, UINT wFlags, int x, int y, + HWND hWnd, LPTPMPARAMS lpTpm) { BOOL ret = FALSE; - ROSMENUINFO MenuInfo; + MENU *menu; - if (!IsMenu(Menu)) + TRACE("hmenu %p flags %04x (%d,%d) hwnd %p lpTpm %p rect %s\n", + hMenu, wFlags, x, y, hWnd, lpTpm, + lpTpm ? wine_dbgstr_rect( &lpTpm->rcExclude) : "-" ); + + /* Parameter check */ + /* FIXME: this check is performed several times, here and in the called + functions. That could be optimized */ + if (!(menu = MENU_GetMenu( hMenu ))) { SetLastError( ERROR_INVALID_MENU_HANDLE ); return FALSE; } - /* ReactOS Check */ - if (!ValidateHwnd(Wnd)) - { - /* invalid window see wine menu.c test_menu_trackpopupmenu line 3146 */ - return FALSE; - } - - MenuGetRosMenuInfo(&MenuInfo, Menu); - if (IsWindow(MenuInfo.Wnd)) + if (IsWindow(menu->hWnd)) { SetLastError( ERROR_POPUP_ALREADY_ACTIVE ); return FALSE; } - MenuInitTracking(Wnd, Menu, TRUE, Flags); + if (MENU_InitPopup( hWnd, hMenu, wFlags )) + { + MenuInitTracking(hWnd, hMenu, TRUE, wFlags); - /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */ - if (!(Flags & TPM_NONOTIFY)) - SendMessageW(Wnd, WM_INITMENUPOPUP, (WPARAM) Menu, 0); + /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */ + if (!(wFlags & TPM_NONOTIFY)) + SendMessageW(hWnd, WM_INITMENUPOPUP, (WPARAM) hMenu, 0); - if (MenuShowPopup(Wnd, Menu, 0, Flags, x, y, 0, 0 )) - ret = MenuTrackMenu(Menu, Flags | TPM_POPUPMENU, 0, 0, Wnd, - Tpm ? &Tpm->rcExclude : NULL); - MenuExitTracking(Wnd, TRUE); + if (MenuShowPopup(hWnd, hMenu, 0, wFlags, x, y, 0, 0 )) + ret = MenuTrackMenu(hMenu, wFlags | TPM_POPUPMENU, 0, 0, hWnd, + lpTpm ? &lpTpm->rcExclude : NULL); + MenuExitTracking(hWnd, TRUE); + + if (menu->hWnd) + { + ROSMENUINFO MenuInfo; + if (IsWindow( menu->hWnd )) // wine hack around this with their destroy function. + DestroyWindow( menu->hWnd ); // Fix wrong error return. + //menu->hWnd = 0; + MenuGetRosMenuInfo(&MenuInfo, menu->head.h); + MenuInfo.Wnd = 0; + MenuSetRosMenuInfo(&MenuInfo); + + if (!(wFlags & TPM_NONOTIFY)) + SendMessageW( hWnd, WM_UNINITMENUPOPUP, (WPARAM)hMenu, + MAKELPARAM(0, IS_SYSTEM_MENU(menu)) ); + } + } return ret; } @@ -4456,164 +4233,63 @@ BOOL WINAPI TrackPopupMenu( HMENU Menu, UINT Flags, int x, int y, return TrackPopupMenuEx( Menu, Flags, x, y, Wnd, NULL); } -/* - * From MSDN: - * The MFT_BITMAP, MFT_SEPARATOR, and MFT_STRING values cannot be combined - * with one another. Also MFT_OWNERDRAW. Set fMask to MIIM_TYPE to use fType. - * - * Windows 2K/XP: fType is used only if fMask has a value of MIIM_FTYPE. - * - * MIIM_TYPE: Retrieves or sets the fType and dwTypeData members. Windows - * 2K/XP: MIIM_TYPE is replaced by MIIM_BITMAP, MIIM_FTYPE, and MIIM_STRING. - * MFT_STRING is replaced by MIIM_STRING. - * (So, I guess we should use MIIM_STRING only for strings?) - * - * MIIM_FTYPE: Windows 2K/Windows XP: Retrieves or sets the fType member. - * - * Based on wine, SetMenuItemInfo_common: - * 1) set MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP any one with MIIM_TYPE, - * it will result in a error. - * 2) set menu mask to MIIM_FTYPE and MFT_BITMAP ftype it will result in a error. - * These conditions are addressed in Win32k IntSetMenuItemInfo. +/********************************************************************** + * MENU_mnu2mnuii * + * Uses flags, id and text ptr, passed by InsertMenu() and + * ModifyMenu() to setup a MenuItemInfo structure. */ -static -BOOL -FASTCALL -MenuSetItemData( - LPMENUITEMINFOW mii, - UINT Flags, - UINT_PTR IDNewItem, - LPCWSTR NewItem, - BOOL Unicode) +static void MENU_mnu2mnuii( UINT flags, UINT_PTR id, LPCWSTR str, LPMENUITEMINFOW pmii, BOOL Unicode) { -/* - * Let us assume MIIM_FTYPE is set and building a new menu item structure. - */ - if(Flags & MF_BITMAP) - { - mii->fMask |= MIIM_BITMAP; /* Use the new way of seting hbmpItem.*/ - mii->hbmpItem = (HBITMAP) NewItem; - - if (Flags & MF_HELP) - { - /* increase ident */ - mii->fType |= MF_HELP; - } - } - else if(Flags & MF_OWNERDRAW) - { - mii->fType |= MFT_OWNERDRAW; - mii->fMask |= MIIM_DATA; - mii->dwItemData = (DWORD_PTR) NewItem; - } - else if (Flags & MF_SEPARATOR) - { - mii->fType |= MFT_SEPARATOR; - if (!(Flags & (MF_GRAYED|MF_DISABLED))) - Flags |= MF_GRAYED|MF_DISABLED; - } - else /* Default action MF_STRING. */ - { - /* Item beginning with a backspace is a help item */ - if (NewItem != NULL) - { - if (Unicode) - { - if (*NewItem == '\b') - { - mii->fType |= MF_HELP; - NewItem++; - } - } - else - { - LPCSTR NewItemA = (LPCSTR) NewItem; - if (*NewItemA == '\b') - { - mii->fType |= MF_HELP; - NewItemA++; - NewItem = (LPCWSTR) NewItemA; - } - } - - if (Flags & MF_HELP) - mii->fType |= MF_HELP; - mii->fMask |= MIIM_STRING; - mii->fType |= MFT_STRING; /* Zero */ - mii->dwTypeData = (LPWSTR)NewItem; - if (Unicode) - mii->cch = (NULL == NewItem ? 0 : strlenW(NewItem)); - else - mii->cch = (NULL == NewItem ? 0 : strlen((LPCSTR)NewItem)); + RtlZeroMemory( pmii, sizeof( MENUITEMINFOW)); + pmii->cbSize = sizeof( MENUITEMINFOW); + pmii->fMask = MIIM_STATE | MIIM_ID | MIIM_FTYPE; + /* setting bitmap clears text and vice versa */ + if( IS_STRING_ITEM(flags)) { + pmii->fMask |= MIIM_STRING | MIIM_BITMAP; + if( !str) + flags |= MF_SEPARATOR; + /* Item beginning with a backspace is a help item */ + /* FIXME: wrong place, this is only true in win16 */ + else + { + if (Unicode) + { + if (*str == '\b') + { + flags |= MF_HELP; + str++; + } + } + else + { + LPCSTR NewItemA = (LPCSTR) str; + if (*NewItemA == '\b') + { + flags |= MF_HELP; + NewItemA++; + str = (LPCWSTR) NewItemA; + } + TRACE("A cch %d\n",strlen(NewItemA)); + } + } + pmii->dwTypeData = (LPWSTR)str; + } else if( flags & MFT_BITMAP){ + pmii->fMask |= MIIM_BITMAP | MIIM_STRING; + pmii->hbmpItem = (HBITMAP)str; } - else - { - mii->fType |= MFT_SEPARATOR; - if (!(Flags & (MF_GRAYED|MF_DISABLED))) - Flags |= MF_GRAYED|MF_DISABLED; + if( flags & MF_OWNERDRAW){ + pmii->fMask |= MIIM_DATA; + pmii->dwItemData = (ULONG_PTR) str; } - } - - if(Flags & MF_RIGHTJUSTIFY) /* Same as MF_HELP */ - { - mii->fType |= MFT_RIGHTJUSTIFY; - } - - if(Flags & MF_MENUBREAK) - { - mii->fType |= MFT_MENUBREAK; - } - else if(Flags & MF_MENUBARBREAK) - { - mii->fType |= MFT_MENUBARBREAK; - } - - if(Flags & MF_GRAYED || Flags & MF_DISABLED) - { - if (Flags & MF_GRAYED) - mii->fState |= MF_GRAYED; - - if (Flags & MF_DISABLED) - mii->fState |= MF_DISABLED; - - mii->fMask |= MIIM_STATE; - } - else if (Flags & MF_HILITE) - { - mii->fState |= MF_HILITE; - mii->fMask |= MIIM_STATE; - } - else /* default state */ - { - mii->fState |= MFS_ENABLED; - mii->fMask |= MIIM_STATE; - } - - if(Flags & MF_POPUP && IsMenu((HMENU)IDNewItem)) - { - mii->fMask |= MIIM_SUBMENU; - mii->hSubMenu = (HMENU)IDNewItem; - } - mii->fMask |= MIIM_ID; - mii->wID = (UINT)IDNewItem; - return TRUE; -} - -NTSTATUS WINAPI -User32CallLoadMenuFromKernel(PVOID Arguments, ULONG ArgumentLength) -{ - PLOADMENU_CALLBACK_ARGUMENTS Common; - LRESULT Result; - - Common = (PLOADMENU_CALLBACK_ARGUMENTS) Arguments; - - Result = (LRESULT)LoadMenuW( Common->hModule, - IS_INTRESOURCE(Common->MenuName[0]) ? - MAKEINTRESOURCE(Common->MenuName[0]) : - (LPCWSTR)&Common->MenuName); - - return ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS); + if( flags & MF_POPUP && MENU_GetMenu((HMENU)id)) { + pmii->fMask |= MIIM_SUBMENU; + pmii->hSubMenu = (HMENU)id; + } + if( flags & MF_SEPARATOR) flags |= MF_GRAYED | MF_DISABLED; + pmii->fState = flags & MENUITEMINFO_STATE_MASK & ~MFS_DEFAULT; + pmii->fType = flags & MENUITEMINFO_TYPE_MASK; + pmii->wID = (UINT)id; } /********************************************************************** @@ -4670,6 +4346,104 @@ static BOOL MENU_NormalizeMenuItemInfoStruct( const MENUITEMINFOW *pmii_in, return TRUE; } +BOOL +MenuInit(VOID) +{ + NONCLIENTMETRICSW ncm; + + /* get the menu font */ + if(!hMenuFont || !hMenuFontBold) + { + ncm.cbSize = sizeof(ncm); + if(!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0)) + { + ERR("MenuInit(): SystemParametersInfoW(SPI_GETNONCLIENTMETRICS) failed!\n"); + return FALSE; + } + + hMenuFont = CreateFontIndirectW(&ncm.lfMenuFont); + if(hMenuFont == NULL) + { + ERR("MenuInit(): CreateFontIndirectW(hMenuFont) failed!\n"); + return FALSE; + } + + ncm.lfMenuFont.lfWeight = max(ncm.lfMenuFont.lfWeight + 300, 1000); + hMenuFontBold = CreateFontIndirectW(&ncm.lfMenuFont); + if(hMenuFontBold == NULL) + { + ERR("MenuInit(): CreateFontIndirectW(hMenuFontBold) failed!\n"); + DeleteObject(hMenuFont); + hMenuFont = NULL; + return FALSE; + } + } + + return TRUE; +} + +VOID +MenuCleanup(VOID) +{ + if (hMenuFont) + { + DeleteObject(hMenuFont); + hMenuFont = NULL; + } + + if (hMenuFontBold) + { + DeleteObject(hMenuFontBold); + hMenuFontBold = NULL; + } +} + +NTSTATUS WINAPI +User32LoadSysMenuTemplateForKernel(PVOID Arguments, ULONG ArgumentLength) +{ + HMENU hmenu = LoadMenuW(User32Instance, L"SYSMENU"); + LRESULT Result = (LRESULT)hmenu; + MENUINFO menuinfo = {0}; + MENUITEMINFOW info = {0}; + + // removing space for checkboxes from menu + menuinfo.cbSize = sizeof(menuinfo); + menuinfo.fMask = MIM_STYLE; + GetMenuInfo(hmenu, &menuinfo); + menuinfo.dwStyle |= MNS_CHECKORBMP; // test_menu_bmp_and_string MNS_CHECKORBMP + SetMenuInfo(hmenu, &menuinfo); + + // adding bitmaps to menu items + info.cbSize = sizeof(info); + info.fMask |= MIIM_BITMAP; + info.hbmpItem = HBMMENU_POPUP_MINIMIZE; + SetMenuItemInfoW(hmenu, SC_MINIMIZE, FALSE, &info); + info.hbmpItem = HBMMENU_POPUP_RESTORE; + SetMenuItemInfoW(hmenu, SC_RESTORE, FALSE, &info); + info.hbmpItem = HBMMENU_POPUP_MAXIMIZE; + SetMenuItemInfoW(hmenu, SC_MAXIMIZE, FALSE, &info); + info.hbmpItem = HBMMENU_POPUP_CLOSE; + SetMenuItemInfoW(hmenu, SC_CLOSE, FALSE, &info); + + return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS)); +} + +NTSTATUS WINAPI +User32CallLoadMenuFromKernel(PVOID Arguments, ULONG ArgumentLength) +{ + PLOADMENU_CALLBACK_ARGUMENTS Common; + LRESULT Result; + + Common = (PLOADMENU_CALLBACK_ARGUMENTS) Arguments; + + Result = (LRESULT)LoadMenuW( Common->hModule, + IS_INTRESOURCE(Common->MenuName[0]) ? + MAKEINTRESOURCE(Common->MenuName[0]) : + (LPCWSTR)&Common->MenuName); + + return ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS); +} + /* FUNCTIONS *****************************************************************/ @@ -4682,7 +4456,33 @@ AppendMenuA(HMENU hMenu, UINT_PTR uIDNewItem, LPCSTR lpNewItem) { - return(InsertMenuA(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem, lpNewItem)); + MENUITEMINFOW mii; + UNICODE_STRING UnicodeString; + BOOL res; + + RtlInitUnicodeString(&UnicodeString, 0); + + MENU_mnu2mnuii( uFlags, uIDNewItem, (LPCWSTR)lpNewItem, &mii, FALSE); + + /* copy the text string, it wll be one or the other */ + if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData) + { + if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)mii.dwTypeData)) + { + SetLastError (ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + mii.dwTypeData = UnicodeString.Buffer; + mii.cch = UnicodeString.Length / sizeof(WCHAR); + } + else + { + TRACE("AMA Handle bitmaps\n"); + } + ////// Answer a question, why a -1? To hunt for the end of the item list. Get it, to Append? + res = NtUserThunkedMenuItemInfo(hMenu, -1, TRUE, TRUE, &mii, &UnicodeString); + if ( UnicodeString.Buffer ) RtlFreeUnicodeString ( &UnicodeString ); + return res; } /* @@ -4694,7 +4494,23 @@ AppendMenuW(HMENU hMenu, UINT_PTR uIDNewItem, LPCWSTR lpNewItem) { - return(InsertMenuW(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem, lpNewItem)); + MENUITEMINFOW mii; + UNICODE_STRING MenuText; + BOOL res; + + RtlInitUnicodeString(&MenuText, 0); + + MENU_mnu2mnuii( uFlags, uIDNewItem, lpNewItem, &mii, TRUE); + + /* copy the text string, it wll be one or the other */ + if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData) + { + RtlInitUnicodeString(&MenuText, (PWSTR)mii.dwTypeData); + mii.dwTypeData = MenuText.Buffer; + mii.cch = MenuText.Length / sizeof(WCHAR); + } + res = NtUserThunkedMenuItemInfo(hMenu, -1, TRUE, TRUE, &mii, &MenuText); + return res; } /* @@ -4720,7 +4536,6 @@ CheckMenuItem(HMENU hmenu, return NtUserCheckMenuItem(hmenu, uIDCheckItem, uCheck); } - /* * @implemented */ @@ -4855,7 +4670,7 @@ EndMenu(VOID) /* don't end up with an orphaned menu */ PostMessageW( top_popup, WM_CANCELMODE, 0, 0); } - return TRUE; + return fEndMenu; } BOOL WINAPI HiliteMenuItem( HWND hWnd, HMENU hMenu, UINT wItemID, @@ -4891,7 +4706,6 @@ GetMenu(HWND hWnd) return UlongToHandle(Wnd->IDMenu); } - /* * @implemented */ @@ -5005,28 +4819,10 @@ UINT WINAPI GetMenuItemID(HMENU hMenu, int nPos) { - PMENU pMenu; - PITEM pItem; - INT i = 0; - - if (!(pMenu = ValidateHandle(hMenu, TYPE_MENU))) - return -1; - - pItem = pMenu->rgItems ? DesktopPtrToUser(pMenu->rgItems) : NULL; - if ( nPos >= 0 ) - { - //pItem = &menu->rgItems[nPos]; or pItem[nPos]; after dptu. - while(pItem) // Do this for now. - { - if (i < (INT)pMenu->cItems) - { - if ( nPos == i && !pItem->spSubMenu) return pItem->wID; - } - pItem = pItem->Next ? DesktopPtrToUser(pItem->Next) : NULL; - i++; - } - } - return -1; + ITEM * lpmi; + if (!(lpmi = MENU_FindItem(&hMenu,(UINT*)&nPos,MF_BYPOSITION))) return -1; + if (lpmi->spSubMenu) return -1; + return lpmi->wID; } /* @@ -5096,18 +4892,21 @@ GetMenuState( UINT uFlags) { PITEM pItem; + UINT Type = 0; TRACE("(menu=%p, id=%04x, flags=%04x);\n", hMenu, uId, uFlags); if (!(pItem = MENU_FindItem( &hMenu, &uId, uFlags ))) return -1; + if (!pItem->Xlpstr && pItem->hbmp) Type = MFT_BITMAP; + if (pItem->spSubMenu) { PMENU pSubMenu = DesktopPtrToUser(pItem->spSubMenu); HMENU hsubmenu = UserHMGetHandle(pSubMenu); if (!IsMenu(hsubmenu)) return (UINT)-1; - else return (pSubMenu->cItems << 8) | ((pItem->fState|pItem->fType) & 0xff); + else return (pSubMenu->cItems << 8) | ((pItem->fState|pItem->fType|Type) & 0xff); } else - return (pItem->fType | pItem->fState); + return (pItem->fType | pItem->fState | Type); } /* @@ -5122,18 +4921,6 @@ GetMenuStringA( int nMaxCount, UINT uFlag) { -/* MENUITEMINFOA mii; - memset( &mii, 0, sizeof(mii) ); - mii.dwTypeData = lpString; - mii.fMask = MIIM_STRING; - mii.cbSize = sizeof(MENUITEMINFOA); - mii.cch = nMaxCount; - - if(!(GetMenuItemInfoA( hMenu, uIDItem, (BOOL)(MF_BYPOSITION & uFlag),&mii))) - return 0; - else - return mii.cch; -*/ ITEM *item; LPWSTR text; ////// wine Code, seems to be faster. @@ -5153,7 +4940,7 @@ GetMenuStringA( if (!lpString || !nMaxCount) return WideCharToMultiByte( CP_ACP, 0, text, -1, NULL, 0, NULL, NULL ); if (!WideCharToMultiByte( CP_ACP, 0, text, -1, lpString, nMaxCount, NULL, NULL )) lpString[nMaxCount-1] = 0; - ERR("returning %s\n", lpString); + TRACE("A returning %s\n", lpString); return strlen(lpString); } @@ -5169,19 +4956,6 @@ GetMenuStringW( int nMaxCount, UINT uFlag) { -/* MENUITEMINFOW miiW; - memset( &miiW, 0, sizeof(miiW) ); - miiW.dwTypeData = lpString; - miiW.fMask = MIIM_STRING | MIIM_FTYPE; - miiW.fType = MFT_STRING; - miiW.cbSize = sizeof(MENUITEMINFOW); - miiW.cch = nMaxCount; - - if(!(GetMenuItemInfoW( hMenu, uIDItem, (BOOL)(MF_BYPOSITION & uFlag),&miiW))) - return 0; - else - return miiW.cch; -*/ ITEM *item; LPWSTR text; @@ -5204,7 +4978,7 @@ GetMenuStringW( return 0; } lstrcpynW( lpString, text, nMaxCount ); - ERR("returning %S\n", lpString); + TRACE("W returning %S\n", lpString); return strlenW(lpString); } @@ -5257,18 +5031,32 @@ InsertMenuA( UINT_PTR uIDNewItem, LPCSTR lpNewItem) { - MENUITEMINFOA mii; - memset( &mii, 0, sizeof(mii) ); - mii.cbSize = sizeof(MENUITEMINFOA); - mii.fMask = MIIM_FTYPE; + MENUITEMINFOW mii; + UNICODE_STRING UnicodeString; + BOOL res; - MenuSetItemData((LPMENUITEMINFOW) &mii, - uFlags, - uIDNewItem, - (LPCWSTR) lpNewItem, - FALSE); + RtlInitUnicodeString(&UnicodeString, 0); - return InsertMenuItemA(hMenu, uPosition, (BOOL)((MF_BYPOSITION & uFlags) > 0), &mii); + MENU_mnu2mnuii( uFlags, uIDNewItem, (LPCWSTR)lpNewItem, &mii, FALSE); + + /* copy the text string, it wll be one or the other */ + if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData) + { + if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)mii.dwTypeData)) + { + SetLastError (ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + mii.dwTypeData = UnicodeString.Buffer; + mii.cch = UnicodeString.Length / sizeof(WCHAR); + } + else + { + TRACE("Handle bitmaps\n"); + } + res = NtUserThunkedMenuItemInfo(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), TRUE, &mii, &UnicodeString); + if ( UnicodeString.Buffer ) RtlFreeUnicodeString ( &UnicodeString ); + return res; } /* @@ -5307,7 +5095,7 @@ InsertMenuItemA( } else { - UnicodeString.Buffer = NULL; + TRACE("Handle bitmaps\n"); } res = NtUserThunkedMenuItemInfo(hMenu, uItem, fByPosition, TRUE, &mii, &UnicodeString); if ( UnicodeString.Buffer ) RtlFreeUnicodeString ( &UnicodeString ); @@ -5365,17 +5153,22 @@ InsertMenuW( LPCWSTR lpNewItem) { MENUITEMINFOW mii; - memset( &mii, 0, sizeof(mii) ); - mii.cbSize = sizeof(MENUITEMINFOW); - mii.fMask = MIIM_FTYPE; + UNICODE_STRING MenuText; + BOOL res; - MenuSetItemData( &mii, - uFlags, - uIDNewItem, - lpNewItem, - TRUE); + RtlInitUnicodeString(&MenuText, 0); - return InsertMenuItemW(hMenu, uPosition, (BOOL)((MF_BYPOSITION & uFlags) > 0), &mii); + MENU_mnu2mnuii( uFlags, uIDNewItem, lpNewItem, &mii, TRUE); + + /* copy the text string, it wll be one or the other */ + if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData) + { + RtlInitUnicodeString(&MenuText, (PWSTR)mii.dwTypeData); + mii.dwTypeData = MenuText.Buffer; + mii.cch = MenuText.Length / sizeof(WCHAR); + } + res = NtUserThunkedMenuItemInfo(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), TRUE, &mii, &MenuText); + return res; } /* @@ -5489,30 +5282,38 @@ MenuItemFromPoint( BOOL WINAPI ModifyMenuA( - HMENU hMnu, + HMENU hMenu, UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem, LPCSTR lpNewItem) { - MENUITEMINFOA mii; - memset( &mii, 0, sizeof(mii) ); - mii.cbSize = sizeof(MENUITEMINFOA); - mii.fMask = MIIM_FTYPE; + MENUITEMINFOW mii; + UNICODE_STRING UnicodeString; + BOOL res; - MenuSetItemData((LPMENUITEMINFOW) &mii, - uFlags, - uIDNewItem, - (LPCWSTR) lpNewItem, - FALSE); + RtlInitUnicodeString(&UnicodeString, 0); - //if (mii.hSubMenu && (uFlags & MF_POPUP) && (mii.hSubMenu != (HMENU)uIDNewItem)) - // NtUserDestroyMenu( mii.hSubMenu ); /* ModifyMenu() spec */ + MENU_mnu2mnuii( uFlags, uIDNewItem, (LPCWSTR)lpNewItem, &mii, FALSE); - return SetMenuItemInfoA( hMnu, - uPosition, - (BOOL)(MF_BYPOSITION & uFlags), - &mii); + /* copy the text string, it wll be one or the other */ + if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData) + { + if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)mii.dwTypeData)) + { + SetLastError (ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + mii.dwTypeData = UnicodeString.Buffer; + mii.cch = UnicodeString.Length / sizeof(WCHAR); + } + else + { + TRACE("Handle bitmaps\n"); + } + res = NtUserThunkedMenuItemInfo(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), FALSE, &mii, &UnicodeString); + if ( UnicodeString.Buffer ) RtlFreeUnicodeString ( &UnicodeString ); + return res; } /* @@ -5521,31 +5322,33 @@ ModifyMenuA( BOOL WINAPI ModifyMenuW( - HMENU hMnu, + HMENU hMenu, UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem, LPCWSTR lpNewItem) { MENUITEMINFOW mii; - memset ( &mii, 0, sizeof(mii) ); - mii.cbSize = sizeof(MENUITEMINFOW); - mii.fMask = MIIM_FTYPE; + UNICODE_STRING MenuText; + BOOL res; - /* Init new data for this menu item */ - MenuSetItemData( &mii, - uFlags, - uIDNewItem, - lpNewItem, - TRUE); + RtlInitUnicodeString(&MenuText, 0); - //if (mii.hSubMenu && (uFlags & MF_POPUP) && (mii.hSubMenu != (HMENU)uIDNewItem)) - // NtUserDestroyMenu( mii.hSubMenu ); /* ModifyMenu() spec */ + MENU_mnu2mnuii( uFlags, uIDNewItem, lpNewItem, &mii, TRUE); - return SetMenuItemInfoW( hMnu, - uPosition, - (BOOL)(MF_BYPOSITION & uFlags), - &mii); + /* copy the text string, it wll be one or the other */ + if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData) + { + RtlInitUnicodeString(&MenuText, (PWSTR)mii.dwTypeData); + mii.dwTypeData = MenuText.Buffer; + mii.cch = MenuText.Length / sizeof(WCHAR); + } + else + { + TRACE("Handle bitmaps\n"); + } + res = NtUserThunkedMenuItemInfo(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), FALSE, &mii, &MenuText); + return res; } /* @@ -5729,8 +5532,6 @@ NEWTrackPopupMenu( NULL); // LPTPMPARAMS is null } - - /* * @unimplemented */ @@ -5756,7 +5557,6 @@ MenuWindowProcA( return FALSE; } return NtUserMessageCall(hWnd, Msg, wParam, lParam, Result, FNID_MENU, TRUE); - } /* diff --git a/win32ss/w32ksvc.h b/win32ss/w32ksvc.h index a780e82a0b0..3b6db971587 100644 --- a/win32ss/w32ksvc.h +++ b/win32ss/w32ksvc.h @@ -1,6 +1,6 @@ // SVC_(, ) // -// Funcs, order, should, match, Windows, XP, 5.1.2600, SP2) +// Funcs order should match Windows XP 5.1.2600 SP2 // SVC_(GdiAbortDoc, 1) SVC_(GdiAbortPath, 1) @@ -235,7 +235,7 @@ SVC_(GdiMonoBitmap, 1) SVC_(GdiMoveTo, 4) SVC_(GdiOffsetClipRgn, 3) SVC_(GdiOffsetRgn, 3) -SVC_(GdiOpenDCW, 8) +SVC_(GdiOpenDCW, 8) /* FIXME: 7 params on XP/2k3 */ SVC_(GdiPatBlt, 6) SVC_(GdiPolyPatBlt, 5) SVC_(GdiPathToRegion, 1) @@ -374,8 +374,7 @@ SVC_(UserEndDeferWindowPosEx, 2) SVC_(UserEndMenu, 0) SVC_(UserEndPaint, 2) SVC_(UserEnumDisplayDevices, 4) -// SVC_(UserEnumDisplayMonitors, 4, Wrong, number, of, param, ?) -SVC_(UserEnumDisplayMonitors, 5) +SVC_(UserEnumDisplayMonitors, 5) /* FIXME: 4 on XP/2k3 */ SVC_(UserEnumDisplaySettings, 4) SVC_(UserEvent, 1) SVC_(UserExcludeUpdateRgn, 2) @@ -496,7 +495,7 @@ SVC_(UserRealInternalGetMessage, 6) SVC_(UserRealWaitMessageEx, 2) SVC_(UserRedrawWindow, 4) SVC_(UserRegisterClassExWOW, 7) -SVC_(UserRegisterUserApiHook, 4) +SVC_(UserRegisterUserApiHook, 4) /* Note: 2 params on XP, 4 on 2k3 */ SVC_(UserRegisterHotKey, 4) SVC_(UserRegisterRawInputDevices, 3) SVC_(UserRegisterTasklist, 1) @@ -590,7 +589,7 @@ SVC_(UserUnregisterUserApiHook, 0) SVC_(UserUnregisterHotKey, 2) SVC_(UserUpdateInputContext, 3) SVC_(UserUpdateInstance, 3) -SVC_(UserUpdateLayeredWindow, 10) +SVC_(UserUpdateLayeredWindow, 10) /* Note: 9 params on XP, 10 on 2k3 */ SVC_(UserGetLayeredWindowAttributes, 4) SVC_(UserSetLayeredWindowAttributes, 4) SVC_(UserUpdatePerUserSystemParameters, 2)