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
* 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
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
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 */
-/* TRANSLATOR: 2013 Erdem Ersoy (eersoy93) (erdemersoy@live.com) */
+/* TRANSLATOR: 2013, 2014 Erdem Ersoy (eersoy93) (erdemersoy@live.com) */
LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT
-LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
+LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
IDR_MAINMENU MENU
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
#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
--- /dev/null
+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
--- /dev/null
+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= <own|share|interact|kernel|filesys|rec>\r\n (výchozí = own)\r\n start= <boot|system|auto|demand|disabled>\r\n (výchozí = demand) \r\n error= <normal|severe|critical|ignore>\r\n (výchozí = normal)\r\n group= <SkupinaPořadíNačtení>\r\n tag= <yes|no>\r\n depend= <Závislosti(oddělené / (lomítko))>\r\n obj= <JménoÚčtu|JménoObjektu>\r\n (výchozí = LocalSystem)\r\n password= <heslo>\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
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
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
#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
/* 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
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
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
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
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"
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"
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"
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
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = AbiWord\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = AbiWord\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Abyss Web server X1\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = AC97 Driver for VirtualBox\r
Licence = Unbekannt\r
Description = Entpacken in das "ReactOS"-Verzeichnis und ReactOS zweimal neustarten.\r
\r
+[Section.0410]\r
+Name = Driver AC97 per VirtualBox\r
+License = Sconosciuta\r
+Descrizione = Estrarre nella cartella "ReactOS" e poi riavviare ReactOs due volte.\r
+\r
[Section.040a]\r
Name = Driver AC97 para VirtualBox\r
Licence = Desconocida\r
-; UTF-8
+; UTF-8
[Section]
Name = AlReader
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.
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
Name = Ants
[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.
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Audio Grabber\r
[Section.0407]\r
Description = Ein sehr guter CD-Ripper/Audio-Datei-Konverter.\r
\r
+[Section.0410]\r
+Description = Un buon CD Ripper/Convertitore di file Audio.\r
+\r
[Section.040a]\r
Description = Un buen CD Ripper/ conversor de archivos de audio.\r
\r
-; UTF-8
+; UTF-8
[Section]
Name = BitTorrent
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
[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.
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
-; UTF-8
+; UTF-8
[Section]
Name = Bound Around (Demo)
[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ı
-; UTF-8
+; UTF-8
[Section]
Name = Christmas Bound
[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.
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
Name = Chromium B.S.U.
-; UTF-8
+; UTF-8
[Section]
Name = Click-N-Type Virtual Keyboard
-; UTF-8
+; UTF-8
[Section]
Name = Code::Blocks (no compiler)
[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.
-; UTF-8
+; UTF-8
[Section]
Name = Code::Blocks TDM-GCC (version 4.7.1, 32 bit)
[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.
-; UTF-8
+; UTF-8
[Section]
Name = Code::Blocks TDM-GCC (version 4.8.1, 32 bit)
[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.
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Microsoft Visual Basic 6.0 Common Controls\r
-; UTF-8
+; UTF-8
[Section]
Name = Orwell Dev-C++ MinGW32
[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
-; UTF-8
+; UTF-8
[Section]
Name = Orwell Dev-C++ TDM GCC x64
[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
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Diablo II\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = DosBlaster\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = DOSBox\r
-; UTF-8
+; UTF-8
[Section]
Name = Double Commander
--- /dev/null
+; 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
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
Name = DVD Write Now
-; UTF-8
+; UTF-8
[Section]
Name = Microsoft Excel Viewer
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Fox Audio Player\r
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
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
-; UTF-8
+; UTF-8
[Section]
Name = Mozilla Firefox 28
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Mozilla Firefox 2.0\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Mozilla Firefox 3.0\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Mozilla Firefox 3.6\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = FreeBASIC\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = GlidewrapZbag\r
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
Name = Globulation2
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.
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
[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.
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = IrfanView\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = IrfanView Plugins\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = K Desktop Environment\r
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
Name = Kyodai Mahjongg
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = LBreakout2\r
Size = 3,03 Mo\r
\r
[Section.0410]\r
-Description = Clone di Breakout utilizza librerie SDL.\r
+Description = Clone di Breakout che utilizza librerie SDL.\r
\r
[Section.0413]\r
Description = Breakout kloon, gebruikt SDL.\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = LGeneral\r
Size = 1,92 Mo\r
\r
[Section.0410]\r
-Description = Clone di Pansez General utilizza librerie SDL.\r
+Description = Clone di Pansez General che utilizza librerie SDL.\r
\r
[Section.0413]\r
Description = Panzer General kloon, gebruikt SDL.\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = LibreOffice\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = LMarbles\r
Size = 1,39 Mo\r
\r
[Section.0410]\r
-Description = Clone di Atomix utilizza le librerie SDL.\r
+Description = Clone di Atomix che utilizza le librerie SDL.\r
\r
[Section.0413]\r
Description = Atomix kloon, gebruikt SDL.\r
--- /dev/null
+; 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
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = OLE Viewer and Microsoft Foundation Classes version 4\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Miranda IM\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = mIRC 7\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = mIRC 6\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Mono .net Development Framework\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Media Player Classic Home Cinema\r
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
Name = Mpxplay
[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.
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Microsoft XML 3\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Microsoft .NET Framework Version 1.1 Redistributable Package\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Microsoft .NET Framework Version 2.0 Redistributable Package\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Microsoft .NET Framework Version 2.0 Service Pack 2\r
-; UTF-8
+; UTF-8
[Section]
Name = Notepad++
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Off By One Browser\r
-; UTF-8
+; UTF-8
; PL trans by wojo664
[Section]
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = OpenOffice 4.0\r
URLDownload = http://download.sourceforge.net/project/openofficeorg.mirror/4.0.1/binaries/fr/Apache_OpenOffice_4.0.1_Win_x86_install_fr.exe\r
\r
[Section.0410]\r
+Description = La suite di office Open Source.\r
URLSite = http://www.openoffice.org/it/\r
Size = 132.39 MB\r
URLDownload = http://download.sourceforge.net/project/openofficeorg.mirror/4.0.1/binaries/it/Apache_OpenOffice_4.0.1_Win_x86_install_it.exe\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = OpenOffice 2.4\r
URLDownload = http://archive.services.openoffice.org/pub/openoffice-archive/localized/fr/2.4.2/OOo_2.4.2_Win32Intel_install_fr.exe\r
\r
[Section.0410]\r
+Description = La suite di office Open Source.\r
Size = 113.79 MB\r
URLSite = http://www.openoffice.org/it/\r
URLDownload = http://archive.services.openoffice.org/pub/openoffice-archive/localized/it/2.4.3/OOo_2.4.3_Win32Intel_install_it.exe\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = OpenTTD\r
Size = 7,0 Mo\r
\r
[Section.0410]\r
-Description = Clone open source del motore di gioco di "Transport Tycoon Deluxe". Hai bisogno di una copia di Transport Tycoon.\r
+Description = Clone open source del motore di gioco di "Transport Tycoon Deluxe". Hai bisogno di una copia di Transport Tycoon.\r
\r
[Section.0413]\r
Description = Open-bron kloon van de "Transport Tycoon Deluxe" spelletjesmotor. Je hebt een kopij van Transport Tycoon nodig.\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Opera\r
Size = 12,56 Mo\r
\r
[Section.0410]\r
-Description = Il famoso browser Opera con features avanzate come un client BitTorrent integrato e la gestione delle Mail.\r
+Description = Il famoso browser Opera con funzionalità avanzate come un client BitTorrent integrato e la gestione delle Mail.\r
\r
[Section.0413]\r
Description = De populaire Opera Browser met vele gevorderde mogelijkheden, inclusief e-mail en BitTorrent afnemers.\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Opera\r
Size = 7,21 Mo\r
\r
[Section.0410]\r
-Description = Il famoso browser Opera con features avanzate come un client BitTorrent integrato e la gestione delle Mail.\r
+Description = Il famoso browser Opera con funzionalità avanzate come un client BitTorrent integrato e la gestione delle Mail.\r
\r
[Section.0413]\r
Description = De populaire Opera Browser met vele gevorderde mogelijkheden, inclusief e-mail en BitTorrent afnemers.\r
-; UTF-8
+; UTF-8
[Section]
Name = PeaZip
[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
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
Name = Pengupop
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
[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.
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
-; UTF-8
+; UTF-8
[Section]
Name = Microsoft Powerpoint Viewer
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
[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
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = PuTTY\r
-; UTF-8
+; UTF-8
[Section]
Name = Python 3
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Python 2\r
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
Name = QB64 (SDL version)
[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.
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
[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.
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = ReMooD\r
[Section.0407]\r
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.\r
\r
+[Section.0410]\r
+Description = ReMooD è un porting sorgente di Doom Legacy. Punta a provedere la classica esperienza ereditaria con nuove funzionalità e maggiore stabilità.\r
+\r
[Section.040a]\r
Description = ReMood es un port de Doom Legacy. Su fin es proporcionar la clásica experiencia anterior con nuevas características y mayor estabilidad.\r
\r
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
[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).
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
[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.
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = ReactOS Build Environment\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = ReactOS Build Environment AMD64 Addon\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = ReactOS Build Environment ARM Addon\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Samba TNG\r
Size = 2,13 Mo\r
\r
[Section.0410]\r
-Description = Questo strumento consente di accedere alle cartelle condivise di Windows / stampanti con ReactOS.\r
+Description = Questo strumento consente di accedere alle cartelle/stampanti condivise di Windows con ReactOS.\r
\r
[Section.0413]\r
Description = Maakt het mogelijk om Windows gedeelde printers te gebruiken met ReactOS.\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = SoundBlaster Driver for VMWare\r
[Section.0410]\r
Name = Driver SoundBlaster per VMWare\r
Licence = Sconosciuta\r
-Description = Unzip nella cartella "ReactOS" e riavviare ReactOS.\r
+Description = Estrarre nella cartella "ReactOS" e riavviare ReactOS due volte.\r
\r
[Section.0413]\r
Name = SoundBlaster Driver voor VMWare\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = SciTE\r
Size = 730 ko\r
\r
[Section.0410]\r
-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.\r
+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.\r
\r
[Section.0413]\r
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.\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = ScummVM\r
Version = 1.6.0\r
Licence = GPL\r
-Description = Sam and Max, Day of the Tentacle, etc on ReactOS.\r
+Description = Software that reproduce the working of graphical engine for videogames (Sam and Max, Day of the Tentacle, etc) on ReactOS.\r
Size = 6.28 MB\r
Category = 4\r
URLSite = http://scummvm.org/\r
Size = 6,28 Mo\r
\r
[Section.0410]\r
-Description = Software che riproduce il funzionamento di motori grafici per videogiochi(Sam and Max, Day of the Tentacle, etc) su ReactOS.\r
+Description = Software che riproduce il funzionamento di motori grafici per videogiochi (Sam and Max, Day of the Tentacle, etc) su ReactOS.\r
\r
[Section.0413]\r
Description = Sam and Max, Day of the Tentacle, enz. op ReactOS.\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Simple Direct Media Layer (SDL) Mixer\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Simple Direct Media Layer (SDL) Runtime\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Mozilla SeaMonkey\r
URLDownload = http://ftp.mozilla.org/pub/mozilla.org/seamonkey/releases/2.25/win32/fr/SeaMonkey%20Setup%202.25.exe\r
\r
[Section.0410]\r
-Description = Mozilla Suite è vivo. Questo è l'unico e solo Browser, Mail, Chat, e Composer di cui avrete mai bisogno...\r
+Description = Mozilla Suite è vivo. Questo è l'unico pachetto che include Browser, Mail, Chat, e Composer di cui avrete mai bisogno...\r
Size = 23.71 MB\r
URLDownload = http://ftp.mozilla.org/pub/mozilla.org/seamonkey/releases/2.25/win32/it/SeaMonkey%20Setup%202.25.exe\r
\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = SMPlayer\r
-; UTF-8
+; UTF-8
[Section]
Name = Snoopy
[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ışı.
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
[Section.0407]
Description = Ein freies Schreiblernprogramm.
+[Section.0410]
+Description = Tutore di scrittura gratuita.
+
[Section.0415]
Description = Darmowy program do nauki pisania na klawiaturze.
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = STEAM\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = SumatraPDF\r
Size = 4,0 Mo\r
\r
[Section.0410]\r
-Description = Sumatra PDF è un visualizzatore di file PDF. E' molto leggero ed è open source.\r
+Description = Sumatra PDF è un visualizzatore di file PDF, leggero e open source.\r
\r
[Section.0413]\r
Description = Sumatra PDF is een slanke, gratis, open-bron PDF lezer.\r
-; UTF-8
+; UTF-8
[Section]
Name = Summer Bound
[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.
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
Name = Super DX-Ball
[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.
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Super Finder XT\r
-; UTF-8
+; UTF-8
; PL translation by wojo664
[Section]
Name = SuperTux
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.
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Microsoft Tahoma Font\r
-; UTF-8
+; UTF-8
[Section]
Name = Mozilla Thunderbird 24
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
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Mozilla Thunderbird\r
URLDownload = http://ftp.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.20/win32/fr/Thunderbird%20Setup%203.1.20.exe\r
\r
[Section.0410]\r
-Description = Il più popolare e il migliore Clients mail gratuito.\r
+Description = Il più popolare e il migliore Client mail gratuito.\r
Size = 8.88 MB\r
URLSite = https://www.mozilla.org/it/thunderbird/\r
URLDownload = http://ftp.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.20/win32/it/Thunderbird%20Setup%203.1.20.exe\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Tile World\r
-; UTF-8
+; UTF-8
[Section]
Name = Total Commander
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = TuxPaint\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = UltraVNC\r
Size = 3,27 Mo\r
\r
[Section.0410]\r
-Description = Client/serveur VNC open source.\r
+Description = Client/server VNC open source.\r
\r
[Section.0413]\r
Description = Open-bron VNC afnemer/aanbieder.\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = µTorrent\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Microsoft Visual Basic 5 Runtime\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Microsoft Visual Basic 6 Runtime\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Microsoft Visual C++ 2005 SP1 Redistributable Package\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Microsoft Visual C++ 2008 SP1 Redistributable Package\r
-; UTF-8
+; UTF-8
[Section]
Name = Microsoft Visual C++ 2010 Redistributable Package
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Microsoft Visual C++ 6 Redistributable Package\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = VLC media player\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = WinBoard\r
-; UTF-8\r
+; UTF-8\r
\r
[Section]\r
Name = Windows Media Encoder 9\r
-; UTF-8
+; UTF-8
[Section]
Name = Microsoft Word Viewer
-; UTF-8
+; UTF-8
;PL translation by wojo664
[Section]
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
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
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
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
*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
*/
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
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
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 */
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"
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ığı"
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
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
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
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
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
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
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
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
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
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
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
#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
static
VOID
-CreateCommonFreeLoaderSections(PINICACHE IniCache)
+CreateCommonFreeLoaderSections(
+ PINICACHE IniCache)
{
PINICACHESECTION IniSection;
return Status;
}
-
/* Allocate buffer for new bootsector */
NewBootSector = (PPARTITION_SECTOR)RtlAllocateHeap(ProcessHeap,
0,
return Status;
}
+
NTSTATUS
-InstallFat12BootCodeToFloppy(PWSTR SrcPath,
- PWSTR RootPath)
+InstallFat12BootCodeToFloppy(
+ PWSTR SrcPath,
+ PWSTR RootPath)
{
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
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,
RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
return Status;
}
-
+
Status = NtReadFile(FileHandle,
NULL,
NULL,
RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
return Status;
}
-
-
+
/* Allocate buffer for new bootsector */
NewBootSector = RtlAllocateHeap(ProcessHeap,
0,
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,
RtlFreeHeap(ProcessHeap, 0, NewBootSector);
return Status;
}
-
+
Status = NtReadFile(FileHandle,
NULL,
NULL,
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,
RtlFreeHeap(ProcessHeap, 0, NewBootSector);
return Status;
}
-
+
#if 0
FilePosition.QuadPart = 0;
#endif
NULL,
NULL);
NtClose(FileHandle);
-
+
/* Free the new boot sector */
RtlFreeHeap(ProcessHeap, 0, NewBootSector);
-
+
return Status;
}
return Status;
}
-
/* Allocate buffer for new bootsector */
NewBootSector = RtlAllocateHeap(ProcessHeap,
0,
return Status;
}
+
BOOLEAN
CheckInstallFatBootcodeToPartition(
PUNICODE_STRING SystemRootPath)
#endif
}
+
NTSTATUS
InstallVBRToPartition(
PUNICODE_STRING SystemRootPath,
WCHAR SrcPath[MAX_PATH];
WCHAR DstPath[MAX_PATH];
NTSTATUS Status;
-
+
/* Format the floppy first */
Status = VfatFormat(&FloppyDevice,
FMIFS_FLOPPY,
#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 */
/* FUNCTIONS ****************************************************************/
-static BOOLEAN NTAPI
+static
+BOOLEAN
+NTAPI
ChkdskCallback(
IN CALLBACKCOMMAND Command,
IN ULONG Modifier,
return TRUE;
}
+
NTSTATUS
ChkdskPartition(
IN PUNICODE_STRING DriveRoot,
/* 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;
-
- RtlInitUnicodeString(&LinkName,
- L"\\SystemRoot");
-
- InitializeObjectAttributes(&ObjectAttributes,
- &LinkName,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- 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;
-
- Status = NtQuerySymbolicLinkObject(Handle,
- &SourceName,
- &Length);
- NtClose(Handle);
-
- if (NT_SUCCESS(Status))
+ 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");
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &LinkName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ 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;
+
+ Status = NtQuerySymbolicLinkObject(Handle,
+ &SourceName,
+ &Length);
+ NtClose(Handle);
+
+ if (NT_SUCCESS(Status))
{
- RtlCreateUnicodeString(SourcePath,
- SourceName.Buffer);
-
- /* strip trailing directory */
- Ptr = wcsrchr(SourceName.Buffer, L'\\');
- if (Ptr)
- {
- RtlCreateUnicodeString(SourceRootDir, Ptr);
- *Ptr = 0;
- }
- else
- RtlCreateUnicodeString(SourceRootDir, L"");
-
- RtlCreateUnicodeString(SourceRootPath,
- 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"");
+
+ RtlCreateUnicodeString(SourceRootPath,
+ SourceName.Buffer);
}
- NtClose(Handle);
+ NtClose(Handle);
- return(STATUS_SUCCESS);
+ return STATUS_SUCCESS;
}
-
/* EOF */
#pragma once
NTSTATUS
-GetSourcePaths(PUNICODE_STRING SourcePath,
- PUNICODE_STRING SourceRootPath,
- PUNICODE_STRING SourceRootDir);
+GetSourcePaths(
+ PUNICODE_STRING SourcePath,
+ PUNICODE_STRING SourceRootPath,
+ PUNICODE_STRING SourceRootDir);
/* EOF */
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;
-
- /* Allocate queue header */
- QueueHeader = (PFILEQUEUEHEADER)RtlAllocateHeap(ProcessHeap,
- 0,
- sizeof(FILEQUEUEHEADER));
- if (QueueHeader == NULL)
- return(NULL);
+ PFILEQUEUEHEADER QueueHeader;
- /* Initialize queue header */
- RtlZeroMemory(QueueHeader,
- sizeof(FILEQUEUEHEADER));
+ /* Allocate queue header */
+ QueueHeader = (PFILEQUEUEHEADER)RtlAllocateHeap(ProcessHeap,
+ 0,
+ sizeof(FILEQUEUEHEADER));
+ if (QueueHeader == NULL)
+ return NULL;
+ /* 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);
-
- /* 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 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);
+
+ /* 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;
-
- /* SourceCabinet may be NULL */
- if (QueueHandle == NULL ||
- SourceRootPath == NULL ||
- SourceFilename == NULL ||
- TargetDirectory == NULL)
- return(FALSE);
-
- QueueHeader = (PFILEQUEUEHEADER)QueueHandle;
-
- /* Allocate new queue entry */
- Entry = (PQUEUEENTRY)RtlAllocateHeap(ProcessHeap,
- 0,
- sizeof(QUEUEENTRY));
- if (Entry == NULL)
- return(FALSE);
-
- RtlZeroMemory(Entry,
- sizeof(QUEUEENTRY));
-
- /* Copy source cabinet if available */
- if (SourceCabinet != NULL)
+ PFILEQUEUEHEADER QueueHeader;
+ PQUEUEENTRY Entry;
+ ULONG Length;
+
+ /* SourceCabinet may be NULL */
+ if (QueueHandle == NULL ||
+ SourceRootPath == NULL ||
+ SourceFilename == NULL ||
+ TargetDirectory == NULL)
+ return FALSE;
+
+ QueueHeader = (PFILEQUEUEHEADER)QueueHandle;
+
+ /* Allocate new queue entry */
+ Entry = (PQUEUEENTRY)RtlAllocateHeap(ProcessHeap,
+ 0,
+ sizeof(QUEUEENTRY));
+ if (Entry == NULL)
+ return FALSE;
+
+ RtlZeroMemory(Entry,
+ sizeof(QUEUEENTRY));
+
+ /* 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)
+ {
+ 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)
{
- Length = wcslen(SourceCabinet);
- Entry->SourceCabinet = (WCHAR*) RtlAllocateHeap(ProcessHeap,
- 0,
- (Length + 1) * sizeof(WCHAR));
- if (Entry->SourceCabinet == 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;
+ return FALSE;
}
- else
+
+ wcsncpy(Entry->SourceRootPath, SourceRootPath, Length);
+ Entry->SourceRootPath[Length] = (WCHAR)0;
+
+ /* Copy source path */
+ if (SourcePath != NULL)
{
- Entry->SourceCabinet = NULL;
+ Length = wcslen(SourcePath);
+ Entry->SourcePath = (WCHAR*)RtlAllocateHeap(ProcessHeap,
+ 0,
+ (Length + 1) * sizeof(WCHAR));
+ if (Entry->SourcePath == NULL)
+ {
+ if (Entry->SourceCabinet != NULL)
+ {
+ RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
+ }
+
+ RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
+ RtlFreeHeap(ProcessHeap, 0, Entry);
+ return FALSE;
+ }
+
+ wcsncpy(Entry->SourcePath, SourcePath, Length);
+ Entry->SourcePath[Length] = (WCHAR)0;
}
- /* 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;
-
- /* 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 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);
- return(FALSE);
+
+ RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
+ RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath);
+ RtlFreeHeap(ProcessHeap, 0, Entry);
+ return FALSE;
}
- 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)
+
+ 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)
+ 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->SourceFilename);
+ 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);
-}
+ wcsncpy(Entry->TargetDirectory, TargetDirectory, Length);
+ Entry->TargetDirectory[Length] = (WCHAR)0;
-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 FileSrcPath[MAX_PATH];
- WCHAR FileDstPath[MAX_PATH];
-
- TargetRootPath = ((PCOPYCONTEXT)Context)->DestinationRootPath;
- TargetPath = ((PCOPYCONTEXT)Context)->InstallPath;
-
- 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'\\')
+ /* Copy optional target filename */
+ if (TargetFilename != NULL)
{
- wcscat(FileDstPath, Entry->TargetDirectory);
+ 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
{
- if (TargetPath != NULL)
- {
- if (TargetPath[0] != L'\\')
- wcscat(FileDstPath, L"\\");
- wcscat(FileDstPath, TargetPath);
- }
- wcscat(FileDstPath, L"\\");
- wcscat(FileDstPath, Entry->TargetDirectory);
+ Entry->Prev = QueueHeader->CopyTail;
+ Entry->Next = NULL;
+ QueueHeader->CopyTail->Next = Entry;
+ QueueHeader->CopyTail = Entry;
}
- /* 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);
- }
+ QueueHeader->CopyCount++;
+
+ return TRUE;
+}
+
+
+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 FileSrcPath[MAX_PATH];
+ WCHAR FileDstPath[MAX_PATH];
+
+ TargetRootPath = ((PCOPYCONTEXT)Context)->DestinationRootPath;
+ TargetPath = ((PCOPYCONTEXT)Context)->InstallPath;
+
+ if (QueueHandle == NULL)
+ return FALSE;
- /* FIXME: Do it! */
- DPRINT("'%S' ==> '%S'\n",
- FileSrcPath,
- FileDstPath);
+ QueueHeader = (PFILEQUEUEHEADER)QueueHandle;
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);
+ SPFILENOTIFY_STARTQUEUE,
+ 0,
+ 0);
- }
- else
+ MsgHandler(Context,
+ SPFILENOTIFY_STARTSUBQUEUE,
+ FILEOP_COPY,
+ QueueHeader->CopyCount);
+
+ /* Commit copy queue */
+ Entry = QueueHeader->CopyHead;
+ while (Entry != NULL)
{
- MsgHandler(Context,
- SPFILENOTIFY_ENDCOPY,
- (UINT_PTR)Entry->SourceFilename,
- FILEOP_COPY);
- }
+ wcscpy(FileSrcPath, Entry->SourceRootPath);
+ if (Entry->SourcePath != NULL)
+ wcscat(FileSrcPath, Entry->SourcePath);
+ wcscat(FileSrcPath, L"\\");
+ wcscat(FileSrcPath, Entry->SourceFilename);
- Entry = Entry->Next;
- }
+ /* 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_ENDSUBQUEUE,
- FILEOP_COPY,
- 0);
+ 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);
+ }
- MsgHandler(Context,
- SPFILENOTIFY_ENDQUEUE,
- 0,
- 0);
+ 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;
+ }
+
+ MsgHandler(Context,
+ SPFILENOTIFY_ENDSUBQUEUE,
+ FILEOP_COPY,
+ 0);
+
+ MsgHandler(Context,
+ SPFILENOTIFY_ENDQUEUE,
+ 0,
+ 0);
- return(TRUE);
+ return TRUE;
}
/* EOF */
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);
+ IN HSPFILEQ QueueHandle);
-BOOL WINAPI
+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,
+ 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
+SetupQueueCopy(
+ HSPFILEQ QueueHandle,
+ PCWSTR SourceCabinet,
+ PCWSTR SourceRootPath,
+ PCWSTR SourcePath,
+ PCWSTR SourceFilename,
+ PCWSTR TargetDirectory,
+ PCWSTR TargetFilename);
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);
+WINAPI
+SetupCommitFileQueueW(
+ HWND Owner,
+ HSPFILEQ QueueHandle,
+ PSP_FILE_CALLBACK_W MsgHandler,
+ PVOID Context);
/* EOF */
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;
-
- RtlCreateUnicodeString(&PathName,
- DirectoryName);
- if (PathName.Length > sizeof(WCHAR) &&
- PathName.Buffer[PathName.Length / sizeof(WCHAR) - 2] == L'\\' &&
- PathName.Buffer[PathName.Length / sizeof(WCHAR) - 1] == L'.')
+ 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'.')
{
- 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))
+ 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);
+ NtClose(DirectoryHandle);
}
- RtlFreeUnicodeString(&PathName);
+ RtlFreeUnicodeString(&PathName);
- return(Status);
+ 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);
-
- 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))
+ RtlInitUnicodeString(&FileName,
+ SourceFileName);
+
+ 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))
{
- 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;
+ DPRINT1("NtQueryInformationFile failed: %x\n", Status);
+ goto closesrc;
}
- Status = NtQueryInformationFile(FileHandleSource,
- &IoStatusBlock,&FileBasic,
- sizeof(FILE_BASIC_INFORMATION),
- FileBasicInformation);
- 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;
+ 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 = 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);
-
- 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))
+ RtlInitUnicodeString(&FileName,
+ DestinationFileName);
+
+ 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))
{
- 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;
+ 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))
+
+ /* 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("NtSetInformationFile failed: %x\n", Status);
+ 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))
+ /* 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);
+ DPRINT1("NtSetInformationFile failed: %x\n", Status);
}
- closedest:
- NtClose(FileHandleDest);
- unmapsrcsec:
- NtUnmapViewOfSection( NtCurrentProcess(), SourceFileMap );
- closesrcsec:
- NtClose(SourceFileSection);
- closesrc:
- NtClose(FileHandleSource);
- done:
- return(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");
-
- /* 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);
- }
+ 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
+ else
{
- DPRINT("Using new cabinet\n");
+ DPRINT("Using new cabinet\n");
- if (HasCurrentCabinet)
+ if (HasCurrentCabinet)
{
- CabinetCleanup();
+ 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)
+ {
+ DPRINT1("Unable to find '%S' in cabinet '%S'\n", SourceFileName, CabinetGetCabinetName());
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ CabinetSetDestinationPath(DestinationPathName);
+ CabStatus = CabinetExtractFile(&Search);
+ if (CabStatus != CAB_STATUS_SUCCESS)
{
- DPRINT("Cannot extract file %S (%d)\n", SourceFileName, CabStatus);
- return STATUS_UNSUCCESSFUL;
+ DPRINT("Cannot extract file %S (%d)\n", SourceFileName, CabStatus);
+ return STATUS_UNSUCCESSFUL;
}
- return STATUS_SUCCESS;
+ 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;
-
- wcscpy(FullName, PathName);
- if (FileName != NULL)
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING Name;
+ WCHAR FullName[MAX_PATH];
+ HANDLE FileHandle;
+ NTSTATUS Status;
+
+ 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);
-
- 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))
+ RtlInitUnicodeString(&Name,
+ FullName);
+
+ 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))
{
- return(FALSE);
+ return FALSE;
}
- NtClose(FileHandle);
+ NtClose(FileHandle);
- return(TRUE);
+ return TRUE;
}
/* EOF */
#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 */
/* FUNCTIONS ****************************************************************/
-static BOOLEAN NTAPI
+static
+BOOLEAN
+NTAPI
FormatCallback(
IN CALLBACKCOMMAND Command,
IN ULONG Modifier,
return TRUE;
}
+
NTSTATUS
FormatPartition(
IN PUNICODE_STRING DriveRoot,
InsertTailList(&List->ListHead, &Item->ListEntry);
}
+
PFILE_SYSTEM_LIST
CreateFileSystemList(
IN SHORT Left,
return List;
}
+
VOID
DestroyFileSystemList(
IN PFILE_SYSTEM_LIST List)
RtlFreeHeap(ProcessHeap, 0, List);
}
+
VOID
DrawFileSystemList(
IN PFILE_SYSTEM_LIST List)
}
}
+
VOID
ScrollDownFileSystemList(
IN PFILE_SYSTEM_LIST List)
}
}
+
VOID
ScrollUpFileSystemList(
IN PFILE_SYSTEM_LIST List)
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(
VOID
-DestroyGenericList(PGENERIC_LIST List,
- BOOLEAN FreeUserData)
+DestroyGenericList(
+ PGENERIC_LIST List,
+ BOOLEAN FreeUserData)
{
PGENERIC_LIST_ENTRY ListEntry;
PLIST_ENTRY Entry;
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;
}
-static VOID
-DrawListFrame(PGENERIC_LIST GenericList)
+static
+VOID
+DrawListFrame(
+ PGENERIC_LIST GenericList)
{
COORD coPos;
DWORD Written;
}
-static VOID
-DrawListEntries(PGENERIC_LIST GenericList)
+static
+VOID
+DrawListEntries(
+ PGENERIC_LIST GenericList)
{
PGENERIC_LIST_ENTRY ListEntry;
PLIST_ENTRY Entry;
}
}
-static VOID
-DrawScrollBarGenericList(PGENERIC_LIST GenericList)
+
+static
+VOID
+DrawScrollBarGenericList(
+ PGENERIC_LIST GenericList)
{
COORD coPos;
DWORD Written;
}
}
+
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;
DrawScrollBarGenericList(List);
}
+
VOID
-ScrollPageDownGenericList (PGENERIC_LIST List)
+ScrollPageDownGenericList(
+ PGENERIC_LIST List)
{
SHORT i;
List->Redraw = TRUE;
}
+
VOID
-ScrollPageUpGenericList (PGENERIC_LIST List)
+ScrollPageUpGenericList(
+ PGENERIC_LIST List)
{
SHORT i;
List->Redraw = TRUE;
}
+
VOID
-ScrollDownGenericList (PGENERIC_LIST List)
+ScrollDownGenericList(
+ PGENERIC_LIST List)
{
PLIST_ENTRY Entry;
VOID
-ScrollToPositionGenericList (PGENERIC_LIST List, ULONG uIndex)
+ScrollToPositionGenericList(
+ PGENERIC_LIST List,
+ ULONG uIndex)
{
PLIST_ENTRY Entry;
ULONG uCount = 0;
VOID
-ScrollUpGenericList (PGENERIC_LIST List)
+ScrollUpGenericList(
+ PGENERIC_LIST List)
{
PLIST_ENTRY Entry;
VOID
-RedrawGenericList(PGENERIC_LIST List)
+RedrawGenericList(
+ PGENERIC_LIST List)
{
if (List->CurrentEntry == NULL)
return;
VOID
-SetCurrentListEntry(PGENERIC_LIST List, PGENERIC_LIST_ENTRY Entry)
+SetCurrentListEntry(
+ PGENERIC_LIST List,
+ PGENERIC_LIST_ENTRY Entry)
{
if (Entry->List != List)
return;
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;
PGENERIC_LIST_ENTRY
-GetNextListEntry(PGENERIC_LIST_ENTRY Entry)
+GetNextListEntry(
+ PGENERIC_LIST_ENTRY Entry)
{
PLIST_ENTRY Next = Entry->Entry.Flink;
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;
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;
}
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 */
#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);
#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;
-
- RtlInitUnicodeString(&FileNameU, FileName);
- Status = InfOpenFile(
- &hInf,
- &FileNameU,
- LANGIDFROMLCID(LocaleId),
- &ErrorLineUL);
- *ErrorLine = (UINT)ErrorLineUL;
- if (!NT_SUCCESS(Status))
- return INVALID_HANDLE_VALUE;
-
- return hInf;
+ 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;
+
+ 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;
-
- currentIndex ^= 2;
-
- if (Key) *Key = NULL;
- if (Data) *Data = NULL;
-
- if (SetupGetFieldCount(Context) != 1)
- return FALSE;
-
- 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;
+ static PWCHAR pLastCallData[4] = { NULL, NULL, NULL, NULL };
+ static DWORD currentIndex = 0;
+ DWORD dwSize, i;
+ BOOL ret;
+
+ currentIndex ^= 2;
+
+ if (Key)
+ *Key = NULL;
+
+ if (Data)
+ *Data = NULL;
+
+ if (SetupGetFieldCount(Context) != 1)
+ return FALSE;
+
+ 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;
-
- *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;
-
- *Data = pLastCallsData[NextIndex];
- NextIndex = (NextIndex + 1) % (sizeof(pLastCallsData) / sizeof(pLastCallsData[0]));
- return TRUE;
+ static PWCHAR pLastCallsData[] = { NULL, NULL, NULL };
+ static DWORD NextIndex = 0;
+ DWORD dwSize;
+ BOOL ret;
+
+ *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;
+
+ *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;
-
- Status = InfOpenBufferedFile(
- &hInf,
- FileBuffer,
- FileSize,
- LANGIDFROMLCID(LocaleId),
- &ErrorLineUL);
- *ErrorLine = (UINT)ErrorLineUL;
- if (!NT_SUCCESS(Status))
- return INVALID_HANDLE_VALUE;
-
- return hInf;
+ 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;
+
+ return hInf;
#else
- return INVALID_HANDLE_VALUE;
+ return INVALID_HANDLE_VALUE;
#endif /* !__REACTOS__ */
}
* 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 */
/* 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);
+ 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)
+ 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");
+ RtlFreeHeap(ProcessHeap, 0, Section);
+ return NULL;
}
- /* Copy section name */
- for (i = 0; i < NameLength; i++)
+ /* Copy section name */
+ for (i = 0; i < NameLength; i++)
{
- Section->Name[i] = (WCHAR)Name[i];
+ Section->Name[i] = (WCHAR)Name[i];
}
- Section->Name[NameLength] = 0;
+ Section->Name[NameLength] = 0;
- /* Append section */
- if (Cache->FirstSection == NULL)
+ /* Append section */
+ if (Cache->FirstSection == NULL)
{
- Cache->FirstSection = Section;
- Cache->LastSection = Section;
+ Cache->FirstSection = Section;
+ Cache->LastSection = Section;
}
- else
+ else
{
- Cache->LastSection->Next = Section;
- Section->Prev = Cache->LastSection;
- Cache->LastSection = Section;
+ Cache->LastSection->Next = Section;
+ Section->Prev = Cache->LastSection;
+ Cache->LastSection = Section;
}
- return(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;
+ *NamePtr = NULL;
+ *NameSize = 0;
- /* skip whitespace */
- while (*Ptr != 0 && isspace(*Ptr))
+ /* skip whitespace */
+ while (*Ptr != 0 && isspace(*Ptr))
{
- Ptr++;
+ Ptr++;
}
- *NamePtr = Ptr;
+ *NamePtr = Ptr;
- while (*Ptr != 0 && *Ptr != ']')
+ while (*Ptr != 0 && *Ptr != ']')
{
- Size++;
- Ptr++;
+ Size++;
+ Ptr++;
}
+ Ptr++;
- Ptr++;
-
- while (*Ptr != 0 && *Ptr != L'\n')
+ while (*Ptr != 0 && *Ptr != L'\n')
{
- Ptr++;
+ Ptr++;
}
- Ptr++;
+ Ptr++;
- *NameSize = Size;
+ *NameSize = Size;
- strncpy(Name, *NamePtr, Size);
- Name[Size] = 0;
+ strncpy(Name, *NamePtr, Size);
+ Name[Size] = 0;
- DPRINT("SectionName: '%s'\n", Name);
+ DPRINT("SectionName: '%s'\n", Name);
- return(Ptr);
+ return Ptr;
}
-static PCHAR
-IniCacheGetKeyName(PCHAR Ptr,
- PCHAR *NamePtr,
- PULONG NameSize)
+static
+PCHAR
+IniCacheGetKeyName(
+ PCHAR Ptr,
+ PCHAR *NamePtr,
+ PULONG NameSize)
{
- ULONG Size = 0;
+ 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);
+ 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)
+static
+PCHAR
+IniCacheGetKeyValue(
+ PCHAR Ptr,
+ PCHAR *DataPtr,
+ PULONG DataSize,
+ BOOLEAN String)
{
- ULONG Size = 0;
+ ULONG Size = 0;
- *DataPtr = NULL;
- *DataSize = 0;
+ *DataPtr = NULL;
+ *DataSize = 0;
- /* Skip whitespace */
- while (*Ptr != 0 && isspace(*Ptr))
+ /* Skip whitespace */
+ while (*Ptr != 0 && isspace(*Ptr))
{
- Ptr++;
+ Ptr++;
}
- /* Check and skip '=' */
- if (*Ptr != '=')
+ /* Check and skip '=' */
+ if (*Ptr != '=')
{
- return(NULL);
+ return NULL;
}
- Ptr++;
+ Ptr++;
- /* Skip whitespace */
- while (*Ptr != 0 && isspace(*Ptr))
+ /* Skip whitespace */
+ while (*Ptr != 0 && isspace(*Ptr))
{
- Ptr++;
+ Ptr++;
}
- if (*Ptr == '"' && String)
+ if (*Ptr == '"' && String)
{
- Ptr++;
+ Ptr++;
+
+ /* Get data */
+ *DataPtr = Ptr;
+ while (*Ptr != '"')
+ {
+ Ptr++;
+ Size++;
+ }
+ Ptr++;
- /* Get data */
- *DataPtr = Ptr;
- while (*Ptr != '"')
- {
- Ptr++;
- Size++;
- }
- Ptr++;
- while (*Ptr && *Ptr != '\r' && *Ptr != '\n')
- {
- Ptr++;
- }
+ while (*Ptr && *Ptr != '\r' && *Ptr != '\n')
+ {
+ Ptr++;
+ }
}
- else
+ else
{
- /* Get data */
- *DataPtr = Ptr;
- while (*Ptr != 0 && *Ptr != '\r' && *Ptr != ';')
- {
- Ptr++;
- Size++;
- }
+ /* Get data */
+ *DataPtr = Ptr;
+ while (*Ptr != 0 && *Ptr != '\r' && *Ptr != ';')
+ {
+ Ptr++;
+ Size++;
+ }
}
- /* Skip to next line */
- if (*Ptr == '\r')
- Ptr++;
- if (*Ptr == '\n')
- Ptr++;
+ /* Skip to next line */
+ if (*Ptr == '\r')
+ Ptr++;
+ if (*Ptr == '\n')
+ Ptr++;
- *DataSize = Size;
+ *DataSize = Size;
- return(Ptr);
+ 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;
-
- PINICACHESECTION Section;
- PINICACHEKEY Key;
-
- PCHAR SectionName;
- ULONG SectionNameSize;
-
- PCHAR KeyName;
- ULONG KeyNameSize;
-
- PCHAR KeyValue;
- ULONG KeyValueSize;
-
- *Cache = 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))
- {
- DPRINT("NtOpenFile() failed (Status %lx)\n", Status);
- return(Status);
- }
-
- DPRINT("NtOpenFile() successful\n");
-
- /* 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);
- }
+ 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;
+
+ PCHAR SectionName;
+ ULONG SectionNameSize;
+
+ PCHAR KeyName;
+ ULONG KeyNameSize;
- FileLength = FileInfo.EndOfFile.u.LowPart;
+ PCHAR KeyValue;
+ ULONG KeyValueSize;
- DPRINT("File size: %lu\n", FileLength);
+ *Cache = NULL;
- /* Allocate file buffer */
- FileBuffer = (CHAR*) RtlAllocateHeap(ProcessHeap,
- 0,
- FileLength + 1);
- if (FileBuffer == 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))
{
- 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);
-
- /* Append string terminator */
- FileBuffer[FileLength] = 0;
-
- NtClose(FileHandle);
-
- if (!NT_SUCCESS(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)
- {
- DPRINT("RtlAllocateHeap() failed\n");
- return(STATUS_INSUFFICIENT_RESOURCES);
- }
-
- /* Initialize inicache header */
- RtlZeroMemory(*Cache,
- sizeof(INICACHE));
-
- /* Parse ini file */
- Section = NULL;
- Ptr = FileBuffer;
- while (Ptr != NULL && *Ptr != 0)
- {
- Ptr = IniCacheSkipWhitespace(Ptr);
- if (Ptr == NULL)
- continue;
-
- if (*Ptr == '[')
- {
- Section = NULL;
- Ptr++;
-
- Ptr = IniCacheGetSectionName(Ptr,
- &SectionName,
- &SectionNameSize);
-
- 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;
- }
-
- Ptr = IniCacheGetKeyName(Ptr,
- &KeyName,
- &KeyNameSize);
-
- Ptr = IniCacheGetKeyValue(Ptr,
- &KeyValue,
- &KeyValueSize,
- String);
-
- DPRINT1("'%.*s' = '%.*s'\n", KeyNameSize, KeyName, KeyValueSize, KeyValue);
-
- Key = IniCacheAddKey(Section,
- KeyName,
- KeyNameSize,
- KeyValue,
- KeyValueSize);
- if (Key == NULL)
- {
- DPRINT("IniCacheAddKey() failed\n");
- }
- }
- }
-
- /* Free file buffer */
- RtlFreeHeap(ProcessHeap,
- 0,
- FileBuffer);
-
- return(Status);
+ DPRINT("NtOpenFile() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ DPRINT("NtOpenFile() successful\n");
+
+ /* 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;
+ }
+
+ FileLength = FileInfo.EndOfFile.u.LowPart;
+
+ DPRINT("File size: %lu\n", FileLength);
+
+ /* Allocate file buffer */
+ FileBuffer = (CHAR*)RtlAllocateHeap(ProcessHeap,
+ 0,
+ FileLength + 1);
+ if (FileBuffer == NULL)
+ {
+ 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);
+
+ /* Append string terminator */
+ FileBuffer[FileLength] = 0;
+
+ NtClose(FileHandle);
+
+ if (!NT_SUCCESS(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)
+ {
+ DPRINT("RtlAllocateHeap() failed\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Initialize inicache header */
+ RtlZeroMemory(*Cache, sizeof(INICACHE));
+
+ /* Parse ini file */
+ Section = NULL;
+ Ptr = FileBuffer;
+ while (Ptr != NULL && *Ptr != 0)
+ {
+ Ptr = IniCacheSkipWhitespace(Ptr);
+ if (Ptr == NULL)
+ continue;
+
+ if (*Ptr == '[')
+ {
+ Section = NULL;
+ Ptr++;
+
+ Ptr = IniCacheGetSectionName(Ptr,
+ &SectionName,
+ &SectionNameSize);
+
+ 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;
+ }
+
+ Ptr = IniCacheGetKeyName(Ptr,
+ &KeyName,
+ &KeyNameSize);
+
+ Ptr = IniCacheGetKeyValue(Ptr,
+ &KeyValue,
+ &KeyValueSize,
+ String);
+
+ DPRINT1("'%.*s' = '%.*s'\n", KeyNameSize, KeyName, KeyValueSize, KeyValue);
+
+ Key = IniCacheAddKey(Section,
+ KeyName,
+ KeyNameSize,
+ KeyValue,
+ KeyValueSize);
+ if (Key == NULL)
+ {
+ DPRINT("IniCacheAddKey() failed\n");
+ }
+ }
+ }
+
+ /* Free file buffer */
+ RtlFreeHeap(ProcessHeap, 0, FileBuffer);
+
+ 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);
+ 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)
+ 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");
+ RtlFreeHeap(ProcessHeap, 0, Key);
+ return NULL;
}
- /* Copy value name */
- wcscpy(Key->Name, Name);
+ /* Copy value name */
+ wcscpy(Key->Name, Name);
- /* Allocate data buffer */
- Key->Data = (WCHAR*) RtlAllocateHeap(ProcessHeap,
- 0,
- (wcslen(Data) + 1) * sizeof(WCHAR));
- if (Key->Data == NULL)
+ /* Allocate data buffer */
+ Key->Data = (WCHAR*)RtlAllocateHeap(ProcessHeap,
+ 0,
+ (wcslen(Data) + 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 */
- wcscpy(Key->Data, Data);
+ /* Copy value data */
+ wcscpy(Key->Data, Data);
- /* Insert key into section */
- if (Section->FirstKey == NULL)
+ /* Insert key into section */
+ if (Section->FirstKey == NULL)
{
- Section->FirstKey = Key;
- Section->LastKey = Key;
+ Section->FirstKey = Key;
+ Section->LastKey = Key;
}
- else if ((InsertationType == INSERT_FIRST) ||
- ((InsertationType == INSERT_BEFORE) && ((AnchorKey == NULL) || (AnchorKey == Section->FirstKey))))
+ 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;
+ /* 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))
+ 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;
+ /* 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))))
+ else if ((InsertationType == INSERT_LAST) ||
+ ((InsertationType == INSERT_AFTER) && ((AnchorKey == NULL) || (AnchorKey == Section->LastKey))))
{
- Section->LastKey->Next = Key;
- Key->Prev = Section->LastKey;
- Section->LastKey = Key;
+ Section->LastKey->Next = Key;
+ Key->Prev = Section->LastKey;
+ Section->LastKey = Key;
}
- else if ((InsertationType == INSERT_AFTER) && (AnchorKey != NULL))
+ 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;
+ /* Insert after the anchor key */
+ Key->Next = AnchorKey->Next;
+ Key->Prev = AnchorKey;
+ AnchorKey->Next->Prev = Key;
+ AnchorKey->Next = Key;
}
- return(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;
-
- OBJECT_ATTRIBUTES ObjectAttributes;
- IO_STATUS_BLOCK IoStatusBlock;
- LARGE_INTEGER Offset;
- HANDLE FileHandle;
-
-
- /* Calculate required buffer size */
- BufferSize = 0;
- Section = Cache->FirstSection;
- while (Section != NULL)
- {
- 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;
- }
-
- Section = Section->Next;
- if (Section != NULL)
- BufferSize += 2; /* extra "\r\n" at end of each section */
- }
- BufferSize++; /* Null-terminator */
-
- DPRINT("BufferSize: %lu\n", BufferSize);
-
- /* 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;
- }
- }
-
- /* 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))
+ 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;
+
+
+ /* Calculate required buffer size */
+ BufferSize = 0;
+ Section = Cache->FirstSection;
+ while (Section != NULL)
+ {
+ 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;
+ }
+
+ Section = Section->Next;
+ if (Section != NULL)
+ BufferSize += 2; /* extra "\r\n" at end of each section */
+ }
+ BufferSize++; /* Null-terminator */
+
+ DPRINT("BufferSize: %lu\n", BufferSize);
+
+ /* 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;
+ }
+ }
+
+ /* 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);
+ 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)
+ 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");
+ RtlFreeHeap(ProcessHeap, 0, Section);
+ return NULL;
}
- /* Copy section name */
- wcscpy(Section->Name, Name);
+ /* Copy section name */
+ wcscpy(Section->Name, Name);
- /* Append section */
- if (Cache->FirstSection == NULL)
+ /* Append section */
+ if (Cache->FirstSection == NULL)
{
- Cache->FirstSection = Section;
- Cache->LastSection = Section;
+ Cache->FirstSection = Section;
+ Cache->LastSection = Section;
}
- else
+ else
{
- Cache->LastSection->Next = Section;
- Section->Prev = Cache->LastSection;
- Cache->LastSection = Section;
+ Cache->LastSection->Next = Section;
+ Section->Prev = Cache->LastSection;
+ Cache->LastSection = Section;
}
- return(Section);
+ return Section;
}
/* EOF */
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 */
return 0;
}
+
BOOLEAN
-IsLanguageAvailable(PWCHAR LanguageId)
+IsLanguageAvailable(
+ PWCHAR LanguageId)
{
ULONG lngIndex = 0;
static
const MUI_ENTRY *
-FindMUIEntriesOfPage(IN ULONG PageNumber)
+FindMUIEntriesOfPage(
+ IN ULONG PageNumber)
{
ULONG muiIndex = 0;
ULONG lngIndex;
return NULL;
}
+
static
const MUI_ERROR *
FindMUIErrorEntries(VOID)
return LanguageList[lngIndex].MuiErrors;
}
+
static
const MUI_STRING *
FindMUIStringEntries(VOID)
return LanguageList[lngIndex].MuiStrings;
}
+
LPCWSTR
MUIDefaultKeyboardLayout(VOID)
{
return LanguageList[lngIndex].MuiLayouts[0].LayoutID;
}
+
PWCHAR
MUIGetGeoID(VOID)
{
return LanguageList[lngIndex].GeoID;
}
+
const MUI_LAYOUTS *
MUIGetLayoutsList(VOID)
{
return LanguageList[lngIndex].MuiLayouts;
}
+
VOID
-MUIClearPage(IN ULONG page)
+MUIClearPage(
+ IN ULONG page)
{
const MUI_ENTRY * entry;
int index;
while (entry[index].Buffer != NULL);
}
+
VOID
-MUIDisplayPage(IN ULONG page)
+MUIDisplayPage(
+ IN ULONG page)
{
const MUI_ENTRY * entry;
int index;
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;
WaitEvent);
}
+
LPSTR
-MUIGetString(ULONG Number)
+MUIGetString(
+ ULONG Number)
{
ULONG i;
const MUI_STRING * entry;
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 "<nostring>";
}
-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;
return TRUE;
}
+
BOOLEAN
-AddKbLayoutsToRegistry(IN const MUI_LAYOUTS * MuiLayouts)
+AddKbLayoutsToRegistry(
+ IN const MUI_LAYOUTS *MuiLayouts)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName;
return TRUE;
}
+
BOOLEAN
AddKeyboardLayouts(VOID)
{
ULONG lngIndex = 0;
+
do
{
if (_wcsicmp(LanguageList[lngIndex].LanguageID , SelectedLanguageId) == 0)
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;
return TRUE;
}
-static BOOLEAN
-AddFontsSettingsToRegistry(IN const MUI_SUBFONT * MuiSubFonts)
+
+static
+BOOLEAN
+AddFontsSettingsToRegistry(
+ IN const MUI_SUBFONT * MuiSubFonts)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName;
return TRUE;
}
+
BOOLEAN
AddCodePage(VOID)
{
return FALSE;
}
+
VOID
SetConsoleCodePage(VOID)
{
} 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);
MUIGetLayoutsList(VOID);
BOOLEAN
-AddKbLayoutsToRegistry(IN const MUI_LAYOUTS * MuiLayouts);
+AddKbLayoutsToRegistry(
+ IN const MUI_LAYOUTS *MuiLayouts);
BOOLEAN
AddCodePage(VOID);
SetConsoleCodePage(VOID);
LPSTR
-MUIGetString(ULONG Number);
+MUIGetString(
+ ULONG Number);
#define STRING_PLEASEWAIT 1
#define STRING_INSTALLCREATEPARTITION 2
{
/* 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}
};
/* FUNCTIONS ****************************************************************/
-static VOID
-DrawBorder(PPROGRESSBAR Bar)
+static
+VOID
+DrawBorder(
+ PPROGRESSBAR Bar)
{
- 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 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 left and right edge */
- for (i = Bar->Top + 2; i < Bar->Bottom; 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 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 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->Right;
- 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);
}
- /* 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 right corner */
- coPos.X = Bar->Right;
- coPos.Y = Bar->Bottom;
- FillConsoleOutputCharacterA(StdOutput,
- 0xD9, // '+',
- 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 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;
-
- /* 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 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++)
+ 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 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 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->Right;
- 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);
}
- /* 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 right corner */
- coPos.X = Bar->Right;
- coPos.Y = Bar->Bottom;
- FillConsoleOutputCharacterA(StdOutput,
- 0xBC, // '+',
- 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 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;
-
- /* 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);
-
- /* Draw the progress bar border */
- DrawBorder(Bar);
-
- /* 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++)
+ CHAR TextBuffer[8];
+ COORD coPos;
+ DWORD Written;
+ PROGRESSBAR BarBorder = *Bar;
+
+ /* 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);
+
+ /* Draw the progress bar border */
+ DrawBorder(Bar);
+
+ /* Write Text Associated with Bar */
+ CONSOLE_SetTextXY(Bar->TextTop, Bar->TextRight, Bar->Text);
+
+ /* 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);
+ RtlFreeHeap(ProcessHeap, 0, Bar);
}
+
VOID
-ProgressSetStepCount(PPROGRESSBAR Bar,
- ULONG StepCount)
+ProgressSetStepCount(
+ PPROGRESSBAR Bar,
+ ULONG StepCount)
{
- Bar->CurrentStep = 0;
- Bar->StepCount = StepCount;
+ Bar->CurrentStep = 0;
+ Bar->StepCount = StepCount;
- DrawProgressBar(Bar);
+ DrawProgressBar(Bar);
}
VOID
-ProgressNextStep(PPROGRESSBAR Bar)
+ProgressNextStep(
+ PPROGRESSBAR Bar)
{
- ProgressSetStep(Bar, Bar->CurrentStep + 1);
+ ProgressSetStep(Bar, Bar->CurrentStep + 1);
}
VOID
-ProgressSetStep (PPROGRESSBAR Bar,
- ULONG Step)
+ProgressSetStep(
+ PPROGRESSBAR Bar,
+ ULONG Step)
{
- CHAR TextBuffer[8];
- COORD coPos;
- DWORD Written;
- ULONG NewPercent;
- ULONG NewPos;
+ CHAR TextBuffer[8];
+ COORD coPos;
+ DWORD Written;
+ ULONG NewPercent;
+ ULONG NewPos;
- if (Step > Bar->StepCount)
- return;
+ if (Step > Bar->StepCount)
+ return;
- Bar->CurrentStep = Step;
+ Bar->CurrentStep = Step;
- /* Calculate new percentage */
- NewPercent = (ULONG)(((100.0 * (float)Bar->CurrentStep) / (float)Bar->StepCount) + 0.5);
+ /* Calculate new percentage */
+ NewPercent = (ULONG)(((100.0 * (float)Bar->CurrentStep) / (float)Bar->StepCount) + 0.5);
- /* Redraw precentage if changed */
- if (Bar->Percent != NewPercent)
+ /* 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;
-
- 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 (coPos.X <= Bar->Right - 1)
- {
- FillConsoleOutputCharacterA(StdOutput,
- ' ',
- Bar->Right - coPos.X,
- coPos,
- &Written);
- }
- }
+ 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;
+
+ 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);
+ }
+ }
}
}
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 */
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 <poppack.h>
/* 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;
}
* 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];
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;
-
- /* 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)
+ WCHAR FileNameBuffer[MAX_PATH];
+ HINF hInf;
+ UINT ErrorLine;
+
+ /* 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)
{
- 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))
+ 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;
+ DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
+ return FALSE;
}
- return TRUE;
+ return TRUE;
}
+
BOOLEAN
-SetMountedDeviceValue(CHAR Letter, ULONG Signature, LARGE_INTEGER StartingOffset)
+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;
+ 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);
+ 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))
+ 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,
- 0,
- NULL,
- REG_OPTION_NON_VOLATILE,
- NULL);
+ Status = NtCreateKey(&KeyHandle,
+ KEY_ALL_ACCESS,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ NULL);
}
- if (!NT_SUCCESS(Status))
+ if (!NT_SUCCESS(Status))
{
- DPRINT1("NtCreateKey() failed (Status %lx)\n", Status);
- return FALSE;
+ 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))
+ 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;
+ DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
+ return FALSE;
}
- return TRUE;
+ 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");
#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 */
#define NDEBUG
#include <debug.h>
+/* 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;
-
- 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;
- }
+ 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;
+ }
pDeviceInformation = RtlAllocateHeap(RtlGetProcessHeap(), 0, DeviceInfoLength);
if (!pDeviceInformation)
}
-static BOOLEAN
-GetComputerIdentifier(PWSTR Identifier,
- ULONG IdentifierLength)
+static
+BOOLEAN
+GetComputerIdentifier(
+ PWSTR Identifier,
+ ULONG IdentifierLength)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName;
}
/* 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);
PGENERIC_LIST
-CreateComputerTypeList(HINF InfFile)
+CreateComputerTypeList(
+ HINF InfFile)
{
CHAR Buffer[128];
PGENERIC_LIST List;
}
-static BOOLEAN
-GetDisplayIdentifier(PWSTR Identifier,
+static
+BOOLEAN
+GetDisplayIdentifier(
+ PWSTR Identifier,
ULONG IdentifierLength)
{
OBJECT_ATTRIBUTES ObjectAttributes;
PGENERIC_LIST
-CreateDisplayDriverList(HINF InfFile)
+CreateDisplayDriverList(
+ HINF InfFile)
{
CHAR Buffer[128];
PGENERIC_LIST List;
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];
BOOLEAN
-ProcessDisplayRegistry(HINF InfFile, PGENERIC_LIST List)
+ProcessDisplayRegistry(
+ HINF InfFile,
+ PGENERIC_LIST List)
{
PGENERIC_LIST_ENTRY Entry;
INFCONTEXT Context;
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);
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);
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);
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);
BOOLEAN
-ProcessLocaleRegistry(PGENERIC_LIST List)
+ProcessLocaleRegistry(
+ PGENERIC_LIST List)
{
PGENERIC_LIST_ENTRY Entry;
PWCHAR LanguageId;
Status = NtOpenKey(&KeyHandle,
KEY_SET_VALUE,
&ObjectAttributes);
-
if (!NT_SUCCESS(Status))
{
DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
PGENERIC_LIST
-CreateKeyboardDriverList(HINF InfFile)
+CreateKeyboardDriverList(
+ HINF InfFile)
{
CHAR Buffer[128];
PGENERIC_LIST List;
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! */
return List;
}
-ULONG DefaultLanguageIndex = 0;
ULONG
GetDefaultLanguageIndex(VOID)
return DefaultLanguageIndex;
}
+
PGENERIC_LIST
-CreateLanguageList(HINF InfFile, WCHAR * DefaultLanguage)
+CreateLanguageList(
+ HINF InfFile,
+ WCHAR *DefaultLanguage)
{
CHAR Buffer[128];
PGENERIC_LIST List;
return List;
}
+
PGENERIC_LIST
-CreateKeyboardLayoutList(HINF InfFile, WCHAR * DefaultKBLayout)
+CreateKeyboardLayoutList(
+ HINF InfFile,
+ WCHAR *DefaultKBLayout)
{
CHAR Buffer[128];
PGENERIC_LIST List;
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! */
return List;
}
+
BOOLEAN
-ProcessKeyboardLayoutRegistry(PGENERIC_LIST List)
+ProcessKeyboardLayoutRegistry(
+ PGENERIC_LIST List)
{
PGENERIC_LIST_ENTRY Entry;
PWCHAR LayoutId;
#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;
WCHAR szKeyName[] = L"\\Registry\\User\\.DEFAULT\\Control Panel\\International\\Geo";
WCHAR szValueName[] = L"Nation";
NTSTATUS Status;
+
RtlInitUnicodeString(&KeyName,
szKeyName);
InitializeObjectAttributes(&ObjectAttributes,
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;
#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 */
#define _PAGE_NUMBER_DEFINED
typedef enum _PAGE_NUMBER
{
- START_PAGE,
- LANGUAGE_PAGE,
- INTRO_PAGE,
- LICENSE_PAGE,
- INSTALL_INTRO_PAGE,
-
-// SCSI_CONTROLLER_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_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,
-
- REPAIR_INTRO_PAGE,
-
- SUCCESS_PAGE,
- QUIT_PAGE,
- FLUSH_PAGE,
- REBOOT_PAGE, /* virtual page */
+ START_PAGE,
+ LANGUAGE_PAGE,
+ INTRO_PAGE,
+ LICENSE_PAGE,
+ INSTALL_INTRO_PAGE,
+
+// SCSI_CONTROLLER_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_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,
+
+ REPAIR_INTRO_PAGE,
+
+ SUCCESS_PAGE,
+ QUIT_PAGE,
+ FLUSH_PAGE,
+ REBOOT_PAGE, /* virtual page */
} PAGE_NUMBER, *PPAGE_NUMBER;
#endif
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
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
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
#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
/* 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
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"
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"
/* 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."
#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
#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
}
/* 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);
}
/* 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);
if (dwWritten != dwRead || CheckCtrlBreak(BREAK_INPUT))
{
ConOutResPuts(STRING_COPY_ERROR3);
- cmd_free (buffer);
+ VirtualFree (buffer, 0, MEM_RELEASE);
CloseHandle (hFileDest);
CloseHandle (hFileSrc);
nErrorLevel = 1;
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
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
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
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
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
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
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
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
BEGIN
MENUITEM "&Spustit...", ID_EXECUTE
MENUITEM SEPARATOR
- MENUITEM "&Ukonèit", ID_FILE_EXIT
+ MENUITEM "&Ukončit", ID_FILE_EXIT
END
- POPUP "&Zobrazení"
+ POPUP "&Zobrazení"
BEGIN
- MENUITEM "Panel &nástrojù", ID_VIEW_TOOL_BAR
+ MENUITEM "Panel &nástrojů", ID_VIEW_TOOL_BAR
MENUITEM "Panel &extra", ID_VIEW_EXTRA_BAR
- MENUITEM "L&i\9ata diskù", ID_VIEW_DRIVE_BAR
- MENUITEM "&Boèní 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 "&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
+ 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 "&Nástroje"
+ POPUP "&Nástroje"
BEGIN
- MENUITEM "&Mo\9enosti", ID_TOOLS_OPTIONS
+ MENUITEM "&Možnosti", ID_TOOLS_OPTIONS
END
- POPUP "Ná&povìda"
+ POPUP "Ná&pověda"
BEGIN
- 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
+ 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
BEGIN
POPUP ""
BEGIN
- MENUITEM "&Nastavení", ID_DESKTOPBAR_SETTINGS
- MENUITEM "&Správce úloh", ID_TASKMGR
+ MENUITEM "&Nastavení", ID_DESKTOPBAR_SETTINGS
+ MENUITEM "&Správce úloh", ID_TASKMGR
MENUITEM SEPARATOR
- MENUITEM "&O Prùzkumníku", ID_ABOUT_EXPLORER
+ MENUITEM "&O Průzkumníku", ID_ABOUT_EXPLORER
END
END
BEGIN
POPUP ""
BEGIN
- MENUITEM "&Otevøít ovládání hlasitosti", ID_TRAY_VOLUME
+ MENUITEM "&Otevřít ovládání hlasitosti", ID_TRAY_VOLUME
MENUITEM "&Upravit vlastnosti zvuku", ID_VOLUME_PROPERTIES
END
END
BEGIN
POPUP ""
BEGIN
- 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 "&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 Prùzkumníku", ID_ABOUT_EXPLORER
+ MENUITEM "&O Průzkumníku", ID_ABOUT_EXPLORER
END
END
BEGIN
MENUITEM "&Spustit...", ID_EXECUTE
MENUITEM SEPARATOR
- MENUITEM "&Ukonèit", ID_FILE_EXIT
+ MENUITEM "&Ukončit", ID_FILE_EXIT
END
- POPUP "&Zobrazení"
+ POPUP "&Zobrazení"
BEGIN
- MENUITEM "Panel &nástrojù", ID_VIEW_TOOL_BAR
- MENUITEM "&Boèní 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 "&Nástroje"
+ POPUP "&Nástroje"
BEGIN
- MENUITEM "&Nastavení", ID_TOOLS_OPTIONS
+ MENUITEM "&Nastavení", ID_TOOLS_OPTIONS
END
- POPUP "Ná&povìda"
+ POPUP "Ná&pověda"
BEGIN
- 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
+ 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
FONT 8, "MS Shell Dlg"
BEGIN
CONTROL "", 101, "Static", SS_SIMPLE | SS_NOPREFIX, 3, 6, 162, 10
- CONTROL "&Pøíkaz:", -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á&povìda", 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 nabídce 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
CAPTION "Vlastnosti plochy"
FONT 8, "MS Shell Dlg"
BEGIN
- LTEXT "Prosím zvolte si zpùsob zarovnání 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
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 "&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
+ 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 nabídky Start"
+CAPTION "Vlastnosti nabídky Start"
FONT 8, "MS Shell Dlg"
BEGIN
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 upozoròování"
+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 "&Název 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 "&skrýt", 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í zmìna:", 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
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 módu"
+CAPTION "Volba MDI / SDI módu"
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
- 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
+ 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 "&Otevírat slo\9eky v novém oknì", IDC_SEPARATE_SUBFOLDERS, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 90, 135, 10
- LTEXT "Toto nastavení bude pou\9eito jako výchozí pro v\9aechna okna Prùzkumníka.", 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 Prùzkumníku"
+CAPTION "O ReactOS Průzkumníku"
FONT 8, "MS Shell Dlg"
BEGIN
- LTEXT "ReactOS Prùzkumník", 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
STRINGTABLE
BEGIN
- IDS_TITLE "ReactOS Prùzkumník"
+ IDS_TITLE "ReactOS Průzkumník"
IDS_START "Start"
- IDS_LOGOFF "Odhlásit se..."
+ IDS_LOGOFF "Odhlásit se..."
IDS_SHUTDOWN "Vypnout..."
IDS_RESTART "Restartovat..."
IDS_LAUNCH "Spustit..."
- IDS_START_HELP "Nápovìda"
+ IDS_START_HELP "Nápověda"
IDS_SEARCH_FILES "Hledat"
IDS_DOCUMENTS "Dokumenty"
- IDS_FAVORITES "Oblíbené"
+ IDS_FAVORITES "Oblíbené"
IDS_PROGRAMS "Programy"
- IDS_SETTINGS "Nastavení"
+ IDS_SETTINGS "Nastavení"
IDS_EXPLORE "Prozkoumat"
- IDS_EMPTY "(Prázdné)"
- IDS_RECENT "Nedávné dokumenty"
- IDS_ADMIN "Systémové nástroje"
+ IDS_EMPTY "(Prázdné)"
+ IDS_RECENT "Nedávné dokumenty"
+ IDS_ADMIN "Systémové nástroje"
END
STRINGTABLE
BEGIN
- IDS_STARTMENU "Nabídka Start"
- IDS_MINIMIZE_ALL "minimalizovat v\9aechna okna"
+ IDS_STARTMENU "Nabídka Start"
+ IDS_MINIMIZE_ALL "minimalizovat všechna okna"
IDS_DESKTOP_NUM "Plocha %d"
IDS_VOLUME "Hlasitost"
- IDS_ITEMS_CUR "souèasné polo\9eky"
- 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 "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"
+ 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í\9d"
- IDS_CONNECTIONS "Sí\9dové spojení"
+ IDS_NETWORK "Síť"
+ IDS_CONNECTIONS "Síťové spojení"
IDS_DRIVES "Disky"
- IDS_SEARCH_COMPUTER "Hledat poèítaè"
- IDS_SETTINGS_MENU "Nastavení"
- IDS_CONTROL_PANEL "Ovládací panel"
- IDS_PRINTERS "Tiskárny"
- IDS_BROWSE "Prohlí\9eet 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 "V\9aichni u\9eivatelé\\"
+ IDS_ALL_USERS "Všichni uživatelé\\"
IDS_SEARCH "Hledat"
- IDS_ABOUT_EXPLORER "&O Prùzkumníku"
- IDS_LAUNCH_MANY_PROGRAMS "Bylo vybráno více programù.\nPøejete si je spustit v\9aechny?"
- 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 "Název"
+ IDS_TASKBAR "Panel úloh"
+ IDS_NAMECOLUMN "Název"
IDS_PATHCOLUMN "Cesta"
IDS_MENUCOLUMN "Menu path"
END
/* 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
#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
/* UTF-8 */
#pragma code_page(65001)
+#ifdef LANGUAGE_CS_CZ
+ #include "explorer-cz.rc"
+#endif
#ifdef LANGUAGE_HE_IL
#include "explorer-he.rc"
#endif
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
#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
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
#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
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
#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
#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
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
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
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
#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
# - 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
#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
/* 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
IDD_PROPPAGEKEYBOARD DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT
STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
-CAPTION "Klávesnice"
+CAPTION "Klávesnice"
FONT 8, "MS Shell Dlg", 0, 0, 0x0
BEGIN
- GROUPBOX "Jedním prstem", -1, PROPSHEETPADDING(1), LABELLINE(1), PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(6) + PROPSHEETPADDING(1)
- LTEXT "Tuto funkci pou\9eijte, pokud chcete pou\9eívat Shift, Ctrl nebo Alt stisknutím pouze jedné klávesy 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 "Pou\9eí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\9eijte funkci Filtrování kláves, pokud chcete, aby ReactOS ignoroval náhodná nebo opakovaná stisknutí kláves.",
+ 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 "Pou\9eí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\9eijte 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.",
+ 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 "Pou\9eí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,
+ 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
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 "Pou\9eijte funkci Zobrazení zvuku, pokud chcete aby ReactOS vizuálnì upozoròoval na ka\9edý zvuk vydaný systémem.",
+ 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 "&Pou\9eívat 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 "Pou\9eijte Zobrazení zvuku, aby programy zobrazovaly textový popis zároveò 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 "Pou\9eívat 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 mo\9enost pokud chcete, aby Reactos pou\9eíval barvy a písma urèené 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 "&Pou\9eí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
+ 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)
IDD_PROPPAGEMOUSE DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT
STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
-CAPTION "My\9a"
+CAPTION "Myš"
FONT 8, "MS Shell Dlg", 0, 0, 0x0
BEGIN
- GROUPBOX "Funkce My\9a klávesnicí", -1, PROPSHEETPADDING(1), LABELLINE(1), PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(6) + PROPSHEETPADDING(1)
- LTEXT "Vyberte tuto mo\9enost, pokud chcete ovládat my\9a pomocí \9aipek na numerické klávesnici.",
+ 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 "Pou\9eít funkci &My\9a 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
+ 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 usnadnìní po neèinnosti del\9aí ne\9e:",
+ 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 "Upozornìní", -1, PROPSHEETPADDING(1), LABELLINE(7) - 2, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(5)
- AUTOCHECKBOX "Pøi zapnutí funkce zobrazit upozornìní.", 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 usnadnìní 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 Vám umo\9ení alternativní pøístup k funkcím my\9ai a klávesnice.",
+ 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 "Pou\9eí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\9enosti správy", -1, PROPSHEETPADDING(1), LABELLINE(19) - 4, PROPSHEETWIDTH - PROPSHEETPADDING(2), LABELLINE(5)
- AUTOCHECKBOX "Pou\9eít &nastavení pøi pøihlá\9aení.", 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&u\9eít nastavení jako výchozí pro nové u\9eivatele.", 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
STRINGTABLE
BEGIN
- IDS_CPLSYSTEMNAME "Mo\9enosti usnadnìní"
- IDS_CPLSYSTEMDESCRIPTION "Upraví mo\9enosti usnadnìní pro tento poèítaè."
+ 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"
#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
/* 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
/* 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 "Prùvodce pøidáním hardwaru"
+CAPTION "Průvodce přidáním hardwaru"
FONT 8, "MS Shell Dlg"
BEGIN
- LTEXT "Vítejte v Prùvodci pøidáním hardwaru", IDC_FINISHTITLE, 114, 8, 203, 24
- LTEXT "Tento prùvodce vám pomù\9ee:", -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\9ait problémy, které mù\9eete s va\9aím hardwarem mít.", -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 pøibaleno instalaèní CD, doporuèuje se ukonèit tohoto prùvodce klepnutím na tlaèítko Storno a pou\9eít k instalaci hardwaru toto CD.", 503, 150, 106, 155, 50
- LTEXT "Pokraèujte klepnutím na tlaèítko Dal\9aí.", -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 "Prùvodce pøidáním hardwaru"
+CAPTION "Průvodce přidáním hardwaru"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "", IDC_STATUSTEXT, 21, 8, 275, 32
IDD_ISCONNECTEDPAGE DIALOG 0, 0, 317, 143
STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-CAPTION "Prùvodce pøidáním hardwaru"
+CAPTION "Průvodce přidáním hardwaru"
FONT 8, "MS Shell Dlg"
BEGIN
- LTEXT "Byl ji\9e tento hardware pøipojen k tomuto poèítaèi?", -1, 20, 11, 275, 8
- AUTORADIOBUTTON "&Ano, ji\9e byl pøipojen", IDC_CONNECTED, 29, 23, 266, 8, WS_GROUP
- AUTORADIOBUTTON "&Ne, je\9atì nebyl pøidán", 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 "Prùvodce pøidáním hardwaru"
+CAPTION "Průvodce přidáním hardwaru"
FONT 8, "MS Shell Dlg"
BEGIN
- LTEXT "Vyberte nainstalované zaøízení ze seznamu ní\9ee, poté lze klepnutím na tlaèítko Dal\9aí zkontrolovat jeho vlastnosti nebo zjistit øe\9aení mo\9ený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
+ 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 "Prùvodce pøidáním hardwaru"
+CAPTION "Průvodce přidáním hardwaru"
FONT 8, "MS Shell Dlg"
BEGIN
- LTEXT "Prùvodce mù\9ee vyhledat dal\9aí hardware a automaticky ho nainstalovat, nebo jej mù\9eete 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
+ 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 "Prùvodce pøidáním 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 "Prùvodce pøidáním hardwaru"
+CAPTION "Průvodce přidáním hardwaru"
FONT 8, "MS Shell Dlg"
BEGIN
- LTEXT "Pokud nevidíte vámi hledaný typ hardwaru, klepnìte na Zobrazit v\9aechna zaøízení.", IDC_STATUSTEXT, 21, 9, 275, 18
- LTEXT "Bì\9ené 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 "Prùvodce pøidáním hardwaru"
+CAPTION "Průvodce přidáním hardwaru"
FONT 8, "MS Shell Dlg"
BEGIN
- LTEXT "Vyhledávání hardwaru mù\9ee trvat nìkolik 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
IDD_FINISHPAGE DIALOG 0, 0, 317, 186
STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-CAPTION "Prùvodce pøidáním hardwaru"
+CAPTION "Průvodce přidáním hardwaru"
FONT 8, "MS Shell Dlg"
BEGIN
- 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ì\9anì dokonèen.", -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 "Klepnutím na Dokonèit uzavøete prùvodce.", -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 "Prùvodce pøidáním hardwaru"
+CAPTION "Průvodce přidáním hardwaru"
FONT 8, "MS Shell Dlg"
BEGIN
- LTEXT "Dokonèení Prùvodce pøidáním hardwaru", IDC_FINISHTITLE, 114, 8, 203, 24
- LTEXT "Prùvodce na\9ael 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
+ 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 "Prùvodce pøidáním hardwaru"
+CAPTION "Průvodce přidáním hardwaru"
FONT 8, "MS Shell Dlg"
BEGIN
- 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
+ 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 "Klepnutím na Dokonèit lze zaèít øe\9ait mo\9ené problémy.", -1, 114, 136, 193, 16
- LTEXT "Klepnutím na Storno ukonèíte prùvodce.", 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 "Prùvodce pøidáním hardwaru"
+CAPTION "Průvodce přidáním hardwaru"
FONT 8, "MS Shell Dlg"
BEGIN
- 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\9ainì 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
+ 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 "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\9atì nebyl nainstalován."
- IDS_ISCONNECTED "Je hardware pøipojen?"
- IDS_PROBELISTTITLE "Následující hardware ji\9e je nainstalován na tomto poèítaèi"
- IDS_ADDNEWDEVICE "Pøidat nové hardwarové zaøízení"
- IDS_SELECTWAYTITLE "Prùvodce vám mù\9ee pomoci nainstalovat jiný hardware"
- IDS_HDTYPESTITLE "Ze seznamu ní\9ee zvolte typ instalovaného 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
#include <reactos/manifest_dll.rc>
+#ifdef LANGUAGE_CS_CZ
+ #include "lang/cs-CZ.rc"
+#endif
#ifdef LANGUAGE_DE_DE
#include "lang/de-DE.rc"
#endif
--- /dev/null
+/* 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
#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
/* 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
/* 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
IDD_PROPPAGEMAIN DIALOGEX 0, 0, 252, 205
STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUPWINDOW | WS_CAPTION
EXSTYLE WS_EX_CONTEXTHELP
-CAPTION "Herní ovladaèe"
+CAPTION "Herní ovladače"
FONT 8, "MS Shell Dlg"
BEGIN
ICON IDI_CPLSYSTEM, -1, 7, 7, 20, 20
- 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
+ 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 "&Pøidat...", 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 "&Roz\9aíøené...", IDC_ADVANCED_BUTTON, 111, 157, 65, 14
- PUSHBUTTON "Ø&e\9aení problémù...", 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 "Pøidat 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 ní\9ee, poté kliknìte na tlaèítko OK. Pokud se vá\9a 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
+ 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 pedály", 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
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 "Zvlá\9atní 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á øídící páka 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/Pedály", 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 "&Tlaèítka", -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&rného úhlu", IDC_INC_POINT_CHECKBOX, 7, 123, 115, 10
- LTEXT "Název herního &ovladaèe:", -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
IDD_ADVANCED DIALOGEX 0, 0, 220, 86
STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUPWINDOW | WS_CAPTION
EXSTYLE WS_EX_CONTEXTHELP
-CAPTION "Roz\9aíøené 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 zaøízení, které chcete pou\9eívat se star\9aími programy.", -1, 7, 7, 208, 10
- LTEXT "&Preferované zaøízení:", -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í ovladaèe"
- IDS_CPLSYSTEMDESCRIPTION "Pøidat, odebrat a konfigurovat herní ovladaèe jako napøíklad 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
/* 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
BEGIN
ICON IDI_CPLICON, IDI_CPLICON, 8, 5, 32, 32
LTEXT "", IDC_DEVICE_NAME, 40, 10, 194, 36
- GROUPBOX "Hlasitost zaøízení", -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 "Nízká", -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 "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
+ 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í ní\9ee lze pou\9eít ke zmìnìní hlasitosti jednotlivých reproduktorù a dal\9aí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
+ 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
CAPTION "Zvuky"
FONT 8, "MS Shell Dlg"
BEGIN
- 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\9eit jiné, upravené.", -1, 8, 7, 230, 40
- LTEXT "Zvukové s&chéma:", -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 "&Ulo\9eit 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 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\9eit jako nové zvukové schéma.", -1, 8, 90, 230, 40
- LTEXT "&Události 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 "&Procházet...", 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
CAPTION "Zvuk"
FONT 8, "MS Shell Dlg"
BEGIN
- GROUPBOX "Pøehrávání 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 "&Výchozí zaøízení:", -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 "&Upøesnit...", IDC_ADV2_BTN, 160, 47, 70, 15
- GROUPBOX "Záznam 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í zaøízení:", -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&pøesnit...", IDC_ADV1_BTN, 160, 115, 70, 15
- GROUPBOX "Pøehrávání 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 "Výcho&zí zaøízení:", -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 "Pou\9eíva&t jen výchozí zaøízení", 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
CAPTION "Hlas"
FONT 8, "MS Shell Dlg"
BEGIN
- LTEXT "Tato nastavení ovlivòují hlasitost a roz\9aíø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
+ 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 "&Výchozí zaøízení:", -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 "&Upøesnit...", IDC_ADV4_BTN, 160, 77, 70, 15
- GROUPBOX "Záznam 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í zaøízení:", -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&pøesnit...", 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
IDD_SAVE_SCHEME_AS DIALOG 9, 23, 225, 54
STYLE DS_SHELLFONT | DS_MODALFRAME | DS_CONTEXTHELP | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION
-CAPTION "Ulo\9eit schéma jako"
+CAPTION "Uložit schéma jako"
FONT 8, "MS Shell Dlg"
BEGIN
- LTEXT "&Ulo\9eit toto zvukové schéma 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
FONT 8, "MS Shell Dlg"
BEGIN
ICON 4379, -1, 7, 8, 20, 20
- LTEXT "Zvolte rozmístìní reproduktorù, které nejvíce odpovídá souèasnému.", -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 "&Rozmístìní 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 "Výkon"
+CAPTION "Výkon"
FONT 8, "MS Shell Dlg"
BEGIN
- LTEXT "Tato nastavení ovlivòují, jak systém ReactOS pøehrává zvuk. Mohou pomoci pøi øe\9aení problémù se zvukem.", 8492, 34, 7, 218, 23
- GROUPBOX "Pøehrávání 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 pøevodu vzorkování:", 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 výchozí", 5400, 7, 191, 110, 14
- LTEXT "\8eádná", 8497, 128, 56, 21, 10
- LTEXT "Plná", 8498, 214, 56, 21, 9
- LTEXT "Dobrá", 8499, 128, 123, 21, 10
- LTEXT "Nejlep\9aí", 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
+ 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 "Výkon"
+CAPTION "Výkon"
FONT 8, "MS Shell Dlg"
BEGIN
- LTEXT "Tato nastavení ovlivòují, jak systém ReactOS zaznamenává zvuk. Mohou pomoci pøi øe\9aení problémù se zvukem.", 8492, 34, 7, 217, 20
- GROUPBOX "Záznam 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 pøevodu vzorkování:", 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 výchozí", 5400, 9, 158, 110, 14
- LTEXT "\8eádná", 8497, 125, 46, 24, 10
- LTEXT "Plná", 8498, 217, 46, 19, 9
- LTEXT "Dobrá", 8499, 125, 103, 24, 10
- LTEXT "Nejlep\9aí", 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
+ 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 poèítaè nemù\9ee pøehrávat zvuk, proto\9ee slu\9eba zvuku systému ReactOS není spu\9atìna.", 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 "Poznámky", 10246, 58, 87, 150, 11
- LTEXT "1. Pro spu\9atìní této slu\9eby je tøeba být správcem poèítaèe. Pokud nejste pøihlá\9aeni jako správce, bude vy\9eádáno jméno a heslo správce.", 10247, 60, 100, 150, 40
- LTEXT "2. Po spu\9atìní ReactOS zvuku bude tøeba restartovat poèítaè.", 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 "Vícekanálový zvuk"
+CAPTION "Vícekanálový zvuk"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "Tady bude popis.", 9506, 8, 4, 212, 24
- LTEXT "Nízká", 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 "Nízká", 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 "Nízká", 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 "Nízká", 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 "Nízká", 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 "Nízká", 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 "Nízká", 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 "Nízká", 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 v\9aemi posuvníky najednou", 9504, 5, 185, 216, 9
- PUSHBUTTON "&Obnovit výchozí", 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 "Slu\9eba zvuku systému ReactOS je nyní spu\9atìna. Zvuk nicménì nemusí fungovat správnì, dokud nebude systém ReactOS restartován. Pokud chcete restartovat nyní, nejdøíve ulo\9ete svou práci a ukonèete v\9aechny spu\9atì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
+ 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á zaøízení"
- IDS_CPLDESCRIPTION "Upraví zvukové schéma Va\9aeho poèítaèe, nebo nastaví reproduktory a nahrávací zaøízení."
- 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 "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\9ae"
- 5832 "Varování pøi nízkém 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 "Vyvolání pøíkazu z nabídky"
- 5835 "Vyvolání nabídky"
+ 5834 "Vyvolání příkazu z nabídky"
+ 5835 "Vyvolání nabídky"
5836 "Minimalizace"
- 5837 "Oznámení o nové po\9atì"
- 5838 "Zahájení navigace"
- 5839 "Spu\9atì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\9atìní systému ReactOS"
- 5851 "Otevøení nabídky Start"
- 5852 "Odhlá\9aení od systému ReactOS"
- 5853 "Pøihlá\9aení k systému 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
#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
/* 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
IDD_PROPPAGEPOWERSHEMES DIALOGEX 0, 0, 252, 237
STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
-CAPTION "Schémata napájení"
+CAPTION "Schémata napájení"
FONT 8, "MS Shell Dlg"
BEGIN
ICON IDI_ACDC, IDI_ACDC, 7, 7, 28, 22
- LTEXT "Vyberte napájecí schéma, které se nejvíce hodí pro tento poèítaè. V\9aechny zmìny nastavení se ulo\9eí do vybraného schématu.", -1, 37, 6, 209, 36
- GROUPBOX "&Schéma napájení", -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 "&Ulo\9eit 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 "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
+ 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ý &re\9eim:", 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 "&Re\9eim spánku:", 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 "Varování"
+CAPTION "Varování"
FONT 8, "MS Shell Dlg"
BEGIN
- 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\9e úroveò nabití dosáhne:", IDC_ALARM1, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 15, 17, 190, 15
- LTEXT "neznámá", 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 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
+ 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 "Neznámá", IDC_ALARMAKTION1, 154, 83, 84, 10
+ LTEXT "Neznámá", IDC_ALARMAKTION1, 154, 83, 84, 10
LTEXT "Spustit program:", -1, 95, 95, 55, 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\9e ú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 "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 &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
+ 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 "Neznámá", IDC_ALARMAKTION2, 154, 198, 84, 10
+ LTEXT "Neznámá", IDC_ALARMAKTION2, 154, 198, 84, 10
LTEXT "Spustit program:", -1, 95, 211, 50, 10
- LTEXT "Neznámý", 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 "Upøesnit"
+CAPTION "Upřesnit"
FONT 8, "MS Shell Dlg"
BEGIN
ICON IDI_ACDC, IDI_ACDC, 7, 7, 20, 20
- LTEXT "Vyberte, které nastavení sní\9eené spotøeby chcete pou\9eít.", -1, 37, 6, 207, 20
- GROUPBOX "Mo\9enosti", -1, 6, 30, 240, 65
- CONTROL "V\9edy 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\9eimu", IDC_PASSWORDLOGON, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 17, 60, 220, 10
- CONTROL "&Sní\9eit 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
+ 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 "Pøi stisknutí tlaèítka &napájení:", 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 "Pøi stisknutí tlaèítka re\9eimu &spánku:", 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 "Re\9eim spánku"
+CAPTION "Režim spánku"
FONT 8, "MS Shell Dlg"
BEGIN
ICON IDI_HIBERNATE, IDI_HIBERNATE, 7, 7, 20, 20
- LTEXT "Pokud Vá\9a poèítaè pøejde do re\9eimu spánku, ulo\9eí obsah své pamìti na pevný disk a vypne se. Po opìtovném spu\9atìní se vrátí do pùvodního stavu.", -1, 37, 6, 210, 35
- GROUPBOX "Re\9eim spánku", -1, 6, 41, 240, 32
- CONTROL "Zapnout funkci re\9eim &spánku", IDC_HIBERNATEFILE, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 17, 55, 210, 10
- GROUPBOX "Místo na disku potøebné pro re\9eim 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\9eim spánku musíte uvolnit místo 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 "Mo\9enosti napájení"
- IDS_CPLDESCRIPTION_1 "Nastaví mo\9enosti napájení a \9aetøení energií pro tento poèítaè."
+ 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 schéma napájení %1"
- IDS_CONFIG2 "Pokroèilá 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 "Nedìlat nic"
- IDS_PowerActionNone1 "\8eádná akce"
- IDS_PowerActionUnknown "Neznámý"
- IDS_PowerActionSleep "Úsporný re\9eim"
- IDS_PowerActionHibernate "Re\9eim spánku"
+ 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 napájení"
- IDS_PowerActionWarmEject "Zeptat se na po\9eadovanou 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_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 pøejete smazat toto schéma napájení?"
- IDS_DEL_SCHEME_TITLE "Smazat schéma"
+ IDS_DEL_SCHEME "Opravdu si přejete smazat toto schéma napájení?"
+ IDS_DEL_SCHEME_TITLE "Smazat schéma"
END
#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
/* 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
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
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
IDD_TIMEZONEPAGE DIALOGEX 0, 0, 252, 146
STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION
-CAPTION "Èasové pásmo"
+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 "Provádìt zmìnu na letní èas a zpìt 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 èasovým 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 mù\9ee probìhnout pouze v pøípadì, \9ee je poèítaè pøipojen k síti 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 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ì\9anì synchronizován z %s %s v %s"
- IDS_INETTIMENEXTSYNC "Dal\9aí 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"
+ 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
#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
/* 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
--- /dev/null
+/* 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
/* 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
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]);
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]);
${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)
/* 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;
@ 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)
@ 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
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 */
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)
newSelection = TREEVIEW_GetNextListItem(infoPtr, prevItem);
break;
+ case VK_RETURN:
+ TREEVIEW_SendSimpleNotify(infoPtr, NM_RETURN);
+ break;
+
case VK_HOME:
newSelection = infoPtr->root->firstChild;
break;
icp=HeapAlloc(GetProcessHeap(), 0, sizeof(*icp));
if (icp==NULL) {
+ closesocket(sid);
SetLastError(IP_NO_RESOURCES);
return INVALID_HANDLE_VALUE;
}
}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 {
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;
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));
/* 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,
lpCommandLine,
lpCurrentDirectory,
&VdmAnsiEnv,
- &CsrMsg,
+ &CsrMsg[1],
&VdmTask,
dwCreationFlags,
&StartupInfo,
lpCommandLine,
lpCurrentDirectory,
&VdmAnsiEnv,
- &CsrMsg,
+ &CsrMsg[1],
&VdmTask,
dwCreationFlags,
&StartupInfo,
&VdmWaitObject,
VdmTask,
VdmBinaryType);
+
+ if (!Result)
{
/* Bail out on failure */
DPRINT1("Failed to update VDM with wait object\n");
}
/* 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),
}
/* 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;
}
{
ULARGE_INTEGER TickCount;
+#ifdef _WIN64
+ TickCount.QuadPart = *((volatile ULONG64*)&SharedUserData->TickCount);
+#else
while (TRUE)
{
TickCount.HighPart = (ULONG)SharedUserData->TickCount.High1Time;
YieldProcessor();
}
+#endif
return (ULONG)((UInt32x32To64(TickCount.LowPart,
SharedUserData->TickCountMultiplier) >> 24) +
return 0;
}
-BOOL
+NTSTATUS
WINAPI
BaseCheckVDM(IN ULONG BinaryType,
IN PCWCH ApplicationName,
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
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)
/* Return it to the caller */
*WaitHandle = UpdateVdmEntry->WaitObjectForParent;
}
-#endif
+
/* We made it */
return TRUE;
}
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,
/* Get the exit code from the reply */
*ExitCode = GetVdmExitCode->ExitCode;
-#endif
return TRUE;
}
if (!lpEnvironment)
{
/* Nope, create one */
- Status = RtlCreateEnvironment(TRUE, (PWCHAR*)&Environment);
+ Status = RtlCreateEnvironment(TRUE, &Environment);
if (!NT_SUCCESS(Status)) goto Quickie;
}
else
p = NewEnvironment;
/* FIXME: Code here */
+ DPRINT1("BaseCreateVDMEnvironment is half-plemented!\n");
/* Terminate it */
*p++ = UNICODE_NULL;
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
}
/*
- * @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);
+ }
+}
/*
- * @unimplemented
+ * @implemented
*/
-DWORD
+BOOL
WINAPI
-GetNextVDMCommand (
- DWORD Unknown0
- )
+GetNextVDMCommand(PVDM_COMMAND_INFO CommandData)
{
- STUB;
- return 0;
+ 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
-GetVDMCurrentDirectories (
- DWORD Unknown0,
- DWORD Unknown1
- )
+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;
+ }
+
+ /* 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;
}
/*
- * @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;
}
/*
/*
* @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);
}
#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
OUT LPDWORD ExitCode
);
-BOOL
+NTSTATUS
WINAPI
BaseCheckVDM(
IN ULONG BinaryType,
#include <win/basemsg.h>
#include <win/console.h>
#include <win/conmsg.h>
+#include <win/vdm.h>
/* DDK Driver Headers */
#include <mountmgr.h>
* Samuel Serapión
*/
-/* synched with wine 1.1.26 */
+/* Partly synched with Wine 1.7.17 */
#include <k32.h>
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 */
-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
.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
# @ 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
@ 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
{
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;
/* 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 -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 <epm_c.h>
+ 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)
{
{
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)
{
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;
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
+ }
+ }
+
++#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_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;
--}
--
static RPC_STATUS rpcrt4_conn_create_pipe(RpcConnection *Connection, LPCSTR pname)
{
RpcConnection_np *npc = (RpcConnection_np *) Connection;
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;
}
/* 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;
}
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 */
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;
- 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);
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;
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;
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;
}
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;
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;
}
}
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);
(*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) {
(*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) {
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
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
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,
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,
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;
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 ((p = strrchrW( targetname, '\\' ))) filename = p + 1;
- else filename = targetname;
+ if (context_info->has_extracted)
+ return FILEOP_ABORT;
- 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;
}
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();
*/
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;
@ stub pSetupHandleFailedVerification
@ stub pSetupInfCacheBuild
@ stub pSetupInfIsFromOemLocation
-@ stub pSetupInstallCatalog
+@ stdcall pSetupInstallCatalog(wstr wstr ptr)
@ stub pSetupInstallStopEx
@ stdcall pSetupIsGuidNull(ptr)
@ stub pSetupIsLocalSystem
#include <regstr.h>
#include <sddl.h>
#include <setupapi.h>
+#include <softpub.h>
+#include <mscat.h>
#include <shlobj.h>
#include <wine/unicode.h>
#define NTOS_MODE_USER
}
/* 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);
/* 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
*/
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"
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))
{
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))
{
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 */
/* 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
*/
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
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.
* \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
* \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.
*/
while (Index < 4);
/* Enable the debugger */
- KdDebuggerNotPresent = FALSE;
+ KD_DEBUGGER_NOT_PRESENT = FALSE;
SharedUserData->KdDebuggerEnabled |= 0x00000002;
/* Return the received packet leader */
NTSTATUS
NTAPI
-BatteryIoctl(IN ULONG IoControlCode,
+BatteryIoctl(IN ULONG IoControlCode,
IN PDEVICE_OBJECT DeviceObject,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
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");
}
if (CompBattDebug & 8) DbgPrint("BatteryIoctl: couldn't create Irp\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
}
-
+
/* Return status */
return Status;
}
PFILE_OBJECT LocalFileObject;
HANDLE DeviceHandle;
PAGED_CODE();
-
+
/* Open a file object handle to the device */
InitializeObjectAttributes(&ObjectAttributes, DeviceName, 0, NULL, NULL);
Status = ZwCreateFile(&DeviceHandle,
/* Reference the file object */
Status = ObReferenceObjectByHandle(DeviceHandle,
0,
- IoFileObjectType,
+ *IoFileObjectType,
KernelMode,
(PVOID)&LocalFileObject,
NULL);
*FileObject = LocalFileObject;
*DeviceObject = IoGetRelatedDeviceObject(LocalFileObject);
}
-
+
/* Close the handle */
ZwClose(DeviceHandle);
}
-
+
/* Return status */
return Status;
}
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++)
PTEB Teb;
PPEB Peb;
PWSTR String;
- ULONG ReturnLength;
+ SIZE_T ReturnLength;
NTSTATUS Status;
/* Query some generic values */
/* 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)
{
}
/* 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;
if (Status)
{
/* store bytes returned */
- *BytesReturned = IoStatusBlock.Information;
+ *BytesReturned = (ULONG)IoStatusBlock.Information;
/* return status */
return IoStatusBlock.Status;
}
Status = IoStatusBlock.Status;
}
- *BytesReturned = IoStatusBlock.Information;
+ *BytesReturned = (ULONG)IoStatusBlock.Information;
return Status;
}
return;
}
- /* FIXME
- * delete object / device header
+ /* FIXME
+ * delete object / device header
* remove dead pin / filter instance
*/
UNIMPLEMENTED
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);
/* 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;
PKSPROPERTY_ITEM PropertyItem, CurrentPropertyItem;
NTSTATUS Status;
- // max properties
+ // max properties
PropertyCount = PropertySetA->PropertiesCount + PropertySetB->PropertiesCount;
// allocate items
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)
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,
KSEVENT Event;
PKSEVENT_ITEM EventItem, FoundEventItem;
PKSEVENTDATA EventData;
- PKSEVENT_SET FoundEventSet;
+ const KSEVENT_SET *FoundEventSet;
PKSEVENT_ENTRY EventEntry;
ULONG Index, SubIndex, Size;
PVOID Object;
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))
{
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))
{
/* invalid type requested */
return STATUS_INVALID_PARAMETER;
}
- }
+ }
/* calculate request size */
/*
@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);
}
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,
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))
/*
@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);
}
/*
@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);
}
OUT PVOID * Result)
{
PIO_STACK_LOCATION IoStack;
- ULONG ObjectLength, ParametersLength;
+ SIZE_T ObjectLength, ParametersLength;
PVOID Buffer;
/* get current irp stack */
/* store result */
*Result = Buffer;
- *Size = ParametersLength;
+ *Size = (ULONG)ParametersLength;
return STATUS_SUCCESS;
}
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 */
{
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))
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,
return STATUS_NOT_IMPLEMENTED;
}
-static KSDISPATCH_TABLE PinDispatchTable =
+static KSDISPATCH_TABLE PinDispatchTable =
{
IKsPin_DispatchDeviceIoControl,
KsDispatchInvalidDeviceRequest,
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,
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))
/*
@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);
}
IN LPWSTR ReferenceString)
{
LPWSTR DeviceName;
- ULONG Length;
+ SIZE_T Length;
PLIST_ENTRY Entry;
PBUS_DEVICE_ENTRY DeviceEntry = NULL; /* GCC warning */
BOOLEAN ItemExists = FALSE;
IN OUT PWCHAR *String)
{
LPWSTR Name;
- ULONG Length;
+ SIZE_T Length;
PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)Context;
/* sanity checks */
PIRP Irp,
PBUS_DEVICE_ENTRY DeviceEntry)
{
- ULONG Length;
+ SIZE_T Length;
LPWSTR Buffer;
PIO_STACK_LOCATION IoStack;
PBUS_DEVICE_ENTRY DeviceEntry;
PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension;
LPWSTR Name;
- ULONG Length;
+ SIZE_T Length;
/* get current irp stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp);
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;
PDEV_EXTENSION DeviceExtension;
PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension;
PIO_STACK_LOCATION IoStack;
- ULONG Length;
+ SIZE_T Length;
NTSTATUS Status;
LPWSTR Buffer;
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;
/* 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);
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
*/
0,
NULL,
MAXIMUM_ALLOWED,
- IoFileObjectType,
+ *IoFileObjectType,
Irp->RequestorMode,
&UserHandle);
if (NT_SUCCESS(Status))
Status = ObReferenceObjectByHandle( (PVOID)EventSelectInfo->
EventObject,
EVENT_ALL_ACCESS,
- ExEventObjectType,
+ *ExEventObjectType,
UserMode,
(PVOID *)&FCB->EventSelect,
NULL );
Status = ObReferenceObjectByHandle(EnumReq->Event,
EVENT_ALL_ACCESS,
- ExEventObjectType,
+ *ExEventObjectType,
UserMode,
(PVOID *)&UserEvent,
NULL);
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 */
case TDI_CONNECT:
DequeuedIrp = TCPRemoveIRP(TranContext->Handle.ConnectionContext, Irp);
break;
-
+
case TDI_DISCONNECT:
Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
Status = ObReferenceObjectByHandle(
Parameters->AddressHandle,
0,
- IoFileObjectType,
+ *IoFileObjectType,
KernelMode,
(PVOID*)&FileObject,
NULL);
Status = STATUS_INVALID_PARAMETER;
goto done;
}
-
+
Status = DispPrepareIrpForCancel
(TranContext->Handle.ConnectionContext,
Irp,
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;
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);
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 |
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)
{
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;
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);
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);
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);
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);
}
/* 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);
}
/* failed to register device interface
- * create a symbolic link instead
+ * create a symbolic link instead
*/
DeviceExtension->DeviceInterfaceSupport = FALSE;
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);
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))
{
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))
{
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);
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;
}
/* 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");
}
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))
{
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)
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 <asm.inc>
+
+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 */
--- /dev/null
+/*
+ * 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 */
#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
_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
((PSECURITY_SUBJECT_CONTEXT) SubjectContext)->PrimaryToken )
extern NTKERNELAPI PSE_EXPORTS SeExports;
+
/******************************************************************************
* Process Manager Functions *
******************************************************************************/
(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 )) \
)
#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) \
(((PSECTION_OBJECT_POINTERS)(FO)->SectionObjectPointer)->SharedCacheMap != NULL) \
)
-extern ULONG CcFastMdlReadWait;
+extern NTKERNELAPI ULONG CcFastMdlReadWait;
#if (NTDDI_VERSION >= NTDDI_WIN2K)
#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)
--- /dev/null
+/*
+ * 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 <nt_vdd.h>
+#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 */
#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_)
#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)
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
extern NTSYSAPI CCHAR KeNumberProcessors;
#else
extern PCCHAR KeNumberProcessors;
+__CREATE_NTOS_DATA_IMPORT_ALIAS(KeNumberProcessors)
#endif
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;
/******************************************************************************
/* 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)
} 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;
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
/******************************************************************************
#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();
#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)
_In_ ULONG dwFlags,
_In_ const GUID *ExtensionGuid,
_In_ ULONG SectionType,
- _In_ PUNICODE_STRING SectionName,
+ _In_ const UNICODE_STRING *SectionName,
_Inout_ PVOID ReturnedData
);
#endif // NTOS_MODE_USER
+NTSYSAPI
+NTSTATUS
+NTAPI
+RtlFindActivationContextSectionGuid(
+ ULONG flags,
+ const GUID *extguid,
+ ULONG section_kind,
+ const GUID *guid,
+ void *ptr
+);
+
#ifdef __cplusplus
}
#endif
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
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);
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);
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,
DECLARE_INTERFACE_(IKsControl,IUnknown)
{
- STDMETHOD_(NTSTATUS, QueryInterface)( THIS_
+ STDMETHOD_(NTSTATUS, QueryInterface)( THIS_
REFIID InterfaceId,
PVOID* Interface)PURE;
--- /dev/null
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * fast486.h
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *
+ * 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 */
#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)))
/* 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) \
: \
: "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) \
: \
: "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 */
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;
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ * 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 */
#endif /* HAVE_PWRITE */
#endif /* __REACTOS__ */
-#ifdef WIN32
+#ifdef _WIN32
#ifndef HAVE_SIGSETJMP
# include <setjmp.h>
typedef jmp_buf sigjmp_buf;
#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
(((PSECTION_OBJECT_POINTERS)(FO)->SectionObjectPointer)->SharedCacheMap != NULL) \
)
-extern ULONG CcFastMdlReadWait;
+extern NTKERNELAPI ULONG CcFastMdlReadWait;
#if (NTDDI_VERSION >= NTDDI_WIN2K)
/* 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)
(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 )) \
)
#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) \
#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
#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();
_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
#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)
extern NTSYSAPI CCHAR KeNumberProcessors;
#else
extern PCCHAR KeNumberProcessors;
+__CREATE_NTOS_DATA_IMPORT_ALIAS(KeNumberProcessors)
#endif
$endif (_WDMDDK_)
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_)
#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)
} 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;
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_)
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
((PSECURITY_SUBJECT_CONTEXT) SubjectContext)->PrimaryToken )
extern NTKERNELAPI PSE_EXPORTS SeExports;
+
$endif (_NTIFS_)
#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_)
#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)
#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)
--- /dev/null
+
+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})
--- /dev/null
+ 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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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.
+
+ <signature of Ty Coon>, 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.
--- /dev/null
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * common.c
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *
+ * 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 <windef.h>
+
+// #define NDEBUG
+#include <debug.h>
+
+#include <fast486.h>
+#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 */
--- /dev/null
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * common.h
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *
+ * 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 */
--- /dev/null
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * common.inl
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *
+ * 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 */
--- /dev/null
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * extraops.c
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *
+ * 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 <windef.h>
+
+// #define NDEBUG
+#include <debug.h>
+
+#include <fast486.h>
+#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;
+ }
+}
+
--- /dev/null
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * extraops.h
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *
+ * 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 */
+
--- /dev/null
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * fast486.c
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *
+ * 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 <windef.h>
+
+// #define NDEBUG
+#include <debug.h>
+
+#include <fast486.h>
+#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 */
--- /dev/null
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * fpu.c
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *
+ * 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 <windef.h>
+
+// #define NDEBUG
+#include <debug.h>
+
+#include <fast486.h>
+#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 */
--- /dev/null
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * fpu.h
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *
+ * 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 */
--- /dev/null
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * opcodes.c
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *
+ * 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 <windef.h>
+
+// #define NDEBUG
+#include <debug.h>
+
+#include <fast486.h>
+#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;
+}
--- /dev/null
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * opcodes.h
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *
+ * 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_
--- /dev/null
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * opgroups.c
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *
+ * 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 <windef.h>
+
+// #define NDEBUG
+#include <debug.h>
+
+#include <fast486.h>
+#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 */
--- /dev/null
+/*
+ * Fast486 386/486 CPU Emulation Library
+ * opgroups.h
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *
+ * 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 */
+
* Samuel Serapión
*/
-/* Based on Wine 1.1.26 */
+/* Based on Wine 1.7.17 */
#include <rtl.h>
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'
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:
+
+ <section header>
+ <index[]>
+ <data[]> --- <original name>
+ <redirect data>
+ <versioned name>
+ <module name>
+
+ 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:
+
+ <section header>
+ <index[]>
+ <data[]> --- <dll name>
+ <data>
+
+ This section doesn't seem to carry any payload data except dll names.
+
+ - typelib section format:
+
+ <section header>
+ <module names[]>
+ <index[]>
+ <data[]> --- <data>
+ <helpstring>
+
+ 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:
+
+ <section header>
+ <module names[]>
+ <index[]>
+ <data[]> --- <data> --- <data>
+ <progid> <clrdata>
+ <name>
+ <version>
+ <progid>
+
+ 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:
+
+ <section header>
+ <index[]>
+ <data[]> --- <data>
+ <name>
+
+ 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:
+
+ <section header>
+ <index[]>
+ <data[]> --- <data>
+ <name>
+ <version>
+
+ 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:
+
+ <section header>
+ <guids[]>
+ <index[]>
+ <data[]> --- <progid>
+ <data>
+
+ 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;
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;
};
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;
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
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};
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];
{
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);
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;
{
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);
}
}
- 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);
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;
{
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
{
}
}
- 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;
{
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);
}
}
- if (error || end) return end;
+ if (error) return FALSE;
+
+ acl->actctx->sections |= TLIBREDIRECT_SECTION;
+
+ if (end) return TRUE;
+
return parse_expect_end_elem(xmlbuf, typelibW, asmv1W);
}
-static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
+static inline int aligned_string_len(int len)
{
- xmlstr_t elem, content;
- BOOL end = FALSE, ret = TRUE;
- struct entity* entity;
- UNICODE_STRING elemU;
+ return (len + 3) & ~3;
+}
- if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
- return FALSE;
+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 (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
- if (end) return FALSE;
+ if (!ret) ret = buff;
+ return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
+}
- if (!parse_text_content(xmlbuf, &content)) return FALSE;
+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->u.class.name = xmlstrdupW(&content))) return FALSE;
+ if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
+ return FALSE;
- while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
+ entity->u.class.versioned = TRUE;
+ while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
{
- if (xmlstr_cmp_end(&elem, windowClassW))
+ 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);
+ attr_valueU = xmlstr2unicode(&attr_value);
+ DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
+ }
+ }
+
+ if (error || end) return end;
+
+ 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))
{
ret = parse_end_element(xmlbuf);
break;
}
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;
{
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, proxyStubClsid32W))
+ {
+ if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ else if (xmlstr_cmp(&attr_name, tlbidW))
{
- if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE;
+ if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
}
else
{
}
}
- 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;
{
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);
}
}
- 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);
}
!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;
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);
}
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;
}
if (error || !dll->name) return FALSE;
+
+ acl->actctx->sections |= DLLREDIRECT_SECTION;
+
if (end) return TRUE;
while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
}
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
{
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);
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;
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;
(!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 <assembly>\n", &elemU);
{
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;
}
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)
+{
+ 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;
+
+ /* 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];
+
+ /* 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++)
+ {
+ struct assembly *assembly = &actctx->assemblies[i];
+ for (j = 0; j < assembly->num_dlls; j++)
+ {
+ struct dll_redirect *dll = &assembly->dlls[j];
+ 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++;
+ }
+ }
+
+ *section = header;
+
+ return STATUS_SUCCESS;
+}
+
+static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
+{
+ 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 = v1;
- data->ulLength = 20; /* FIXME */
- data->lpSectionGlobalData = NULL; /* FIXME */
- data->ulSectionGlobalDataLength = 0; /* FIXME */
- data->lpSectionBase = v2;
- data->ulSectionTotalLength = 0; /* FIXME */
+ 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 >= offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
- data->ulAssemblyRosterIndex = i + 1;
+
+ if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
+ data->ulAssemblyRosterIndex = index->rosterindex;
return STATUS_SUCCESS;
}
-static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *section_name,
- PACTCTX_SECTION_KEYED_DATA data)
+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, snlen = section_name->Length / sizeof(WCHAR);
+ 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];
- if (!strncmpiW(section_name->Buffer, dll->name, snlen) && !dll->name[snlen])
- return fill_keyed_data(data, dll, assembly, i);
+ 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++;
+ }
+ }
}
}
- return STATUS_SXS_KEY_NOT_FOUND;
-}
-static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *section_name,
- PACTCTX_SECTION_KEYED_DATA data)
-{
- unsigned int i, j, k, snlen = section_name->Length / sizeof(WCHAR);
+ 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++)
{
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_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
- const UNICODE_STRING *section_name,
- DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
+static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
+ PACTCTX_SECTION_KEYED_DATA data)
{
- NTSTATUS status;
+ struct string_index *iter, *index = NULL;
+ struct wndclass_redirect_data *class;
+ ULONG hash;
+ int i;
- switch (section_kind)
+ if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
+
+ if (!actctx->wndclass_section)
{
- case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
- status = find_dll_redirection(actctx, section_name, data);
- break;
- 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:
- 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:
- DPRINT1("Unknown section_kind %x\n", section_kind);
- return STATUS_SXS_SECTION_NOT_FOUND;
+ 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);
}
- if (status != STATUS_SUCCESS) return status;
+ hash = 0;
+ RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
+ iter = get_wndclass_first_index(actctx);
- if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
+ for (i = 0; i < actctx->wndclass_section->count; i++)
{
- actctx_addref(actctx);
- data->hActCtx = actctx;
+ 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 find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
- const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
+static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
{
- NTSTATUS status;
+ 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;
- switch (section_kind)
+ /* 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,
+ const UNICODE_STRING *section_name,
+ DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
+{
+ NTSTATUS status;
+
+ switch (section_kind)
+ {
+ case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
+ status = find_dll_redirection(actctx, section_name, data);
+ break;
+ case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
+ status = find_window_class(actctx, section_name, data);
+ break;
+ case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
+ status = find_progid_redirection(actctx, section_name, data);
+ break;
+ case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
+ DPRINT1("Unsupported yet section_kind %x\n", section_kind);
+ return STATUS_SXS_SECTION_NOT_FOUND;
+ default:
+ DPRINT1("Unknown section_kind %x\n", section_kind);
+ return STATUS_SXS_SECTION_NOT_FOUND;
+ }
+
+ if (status != STATUS_SUCCESS) return status;
+
+ if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
+ {
+ actctx_addref(actctx);
+ data->hActCtx = actctx;
+ }
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
+ const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
+{
+ NTSTATUS status;
+
+ 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;
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)))
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;
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 *****************************************************************/
#define RtlpAllocateStringMemory RtlpAllocateMemory
#define RtlpFreeStringMemory RtlpFreeMemory
+ULONG
+NTAPI
+RtlGetTickCount(VOID);
+#define NtGetTickCount RtlGetTickCount
+
BOOLEAN
NTAPI
RtlpSetInDbgPrint(
; 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
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
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;
int *__p__fmode(void);
int *__p___mb_cur_max(void);
+extern int _commode;
+
+#ifndef _IOCOMMIT
+#define _IOCOMMIT 0x4000
+#endif
+
#ifdef feof
#undef feof
#endif
/* 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;
/* 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;
}
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)
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;
}
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++;
}
}
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)
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);
{
int plus = strchrW(mode, '+') != NULL;
+ TRACE("%s\n", debugstr_w(mode));
+
+ while(*mode == ' ') mode++;
+
switch(*mode++)
{
case 'R': case 'r':
*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':
*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;
}
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();
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;
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;
+}
+
/*********************************************************************
- * _sopen_s (MSVCRT.@)
+ * _wsopen_s (MSVCRT.@)
*/
-int CDECL _sopen_s( int *fd, const char *path, int oflags, int shflags, int pmode )
+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;
- SECURITY_ATTRIBUTES sa;
- TRACE("fd*: %p file: (%s) oflags: 0x%04x shflags: 0x%04x pmode: 0x%04x\n",
- fd, path, oflags, shflags, pmode);
+ 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;
- }
+ if (!MSVCRT_CHECK_PMT( fd != NULL )) return EINVAL;
*fd = -1;
wxflag = split_oflags(oflags);
sa.nLength = sizeof( SECURITY_ATTRIBUTES );
sa.lpSecurityDescriptor = NULL;
- sa.bInheritHandle = (oflags & _O_NOINHERIT) ? FALSE : TRUE;
+ sa.bInheritHandle = !(oflags & _O_NOINHERIT);
- hand = CreateFileA(path, access, sharing, &sa, creation, attrib, 0);
+ 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());
+ 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;
}
/*********************************************************************
- * _sopen (MSVCRT.@)
+ * _wsopen (MSVCRT.@)
*/
-int CDECL _sopen( const char *path, int oflags, int shflags, ... )
+int CDECL _wsopen( const wchar_t *path, int oflags, int shflags, ... )
{
int pmode;
int fd;
else
pmode = 0;
- _sopen_s(&fd, path, oflags, shflags, pmode);
+ _wsopen_s(&fd, path, oflags, shflags, pmode);
return fd;
}
/*********************************************************************
- * _wsopen_s (MSVCRT.@)
+ * _sopen_s (MSVCRT.@)
*/
-int CDECL _wsopen_s( int *fd, const wchar_t* path, int oflags, int shflags, int pmode )
+int CDECL _sopen_s( int *fd, const char *path, int oflags, int shflags, int pmode )
{
DWORD access = 0, creation = 0, attrib;
- SECURITY_ATTRIBUTES sa;
DWORD sharing;
int wxflag;
HANDLE hand;
+ SECURITY_ATTRIBUTES sa;
- TRACE("fd*: %p :file (%s) oflags: 0x%04x shflags: 0x%04x pmode: 0x%04x\n",
- fd, debugstr_w(path), oflags, shflags, pmode);
+ TRACE("fd*: %p file: (%s) oflags: 0x%04x shflags: 0x%04x pmode: 0x%04x\n",
+ fd, path, oflags, shflags, pmode);
if (!fd)
{
- MSVCRT_INVALID_PMT("null out fd pointer");
- *_errno() = EINVAL;
+ MSVCRT_INVALID_PMT("null out fd pointer", EINVAL);
return EINVAL;
}
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = (oflags & _O_NOINHERIT) ? FALSE : TRUE;
- hand = CreateFileW(path, access, sharing, &sa, creation, attrib, 0);
-
+ hand = CreateFileA(path, access, sharing, &sa, creation, attrib, 0);
if (hand == INVALID_HANDLE_VALUE) {
- WARN(":failed-last error (%d)\n",GetLastError());
+ WARN(":failed-last error (%d)\n", GetLastError());
_dosmaperr(GetLastError());
return *_errno();
}
}
/*********************************************************************
- * _wsopen (MSVCRT.@)
+ * _sopen (MSVCRT.@)
*/
-int CDECL _wsopen( const wchar_t *path, int oflags, int shflags, ... )
+int CDECL _sopen( const char *path, int oflags, int shflags, ... )
{
int pmode;
int fd;
else
pmode = 0;
- _wsopen_s(&fd, path, oflags, shflags, pmode);
+ _sopen_s(&fd, path, oflags, shflags, pmode);
return fd;
}
*/
int CDECL _open_osfhandle(intptr_t handle, int oflags)
{
+ DWORD flags;
int fd;
/* _O_RDONLY (0) always matches, so set the read flag
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;
}
*/
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;
+
}
/*********************************************************************
*/
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 (((info->exflag&EF_UTF8) || (info->exflag&EF_UTF16)) && count&1)
+ {
+ *_errno() = EINVAL;
+ return -1;
+ }
- if (!(get_ioinfo(fd)->wxflag & WX_TEXT))
+ /* 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;
+ 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;
- 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 <count; i++)
- {
- if (s[i]== '\n')
- {
- nr_lf++;
- /*if ((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;
+ else
+ {
+ unsigned int i, j, nr_lf, size;
+ char *p = NULL;
+ const char *q;
+ const char *s = buf, *buf_start = 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 (!(info->exflag & (EF_UTF8|EF_UTF16)))
+ {
+ /* find number of \n */
+ for (nr_lf=0, i=0; i<count; i++)
+ if (s[i] == '\n')
+ nr_lf++;
+ if (nr_lf)
+ {
+ size = count+nr_lf;
+ if ((q = p = malloc(size)))
+ {
+ for (s = buf, i = 0, j = 0; i < count; i++)
+ {
+ if (s[i] == '\n')
+ p[j++] = '\r';
+ p[j++] = s[i];
+ }
+ }
+ else
+ {
+ FIXME("Malloc failed\n");
+ nr_lf = 0;
+ size = count;
+ q = buf;
+ }
+ }
+ else
+ {
+ size = count;
+ q = buf;
+ }
+ }
+ else if (info->exflag & EF_UTF16)
+ {
+ for (nr_lf=0, i=0; i<count; i+=2)
+ if (s[i]=='\n' && s[i+1]==0)
+ nr_lf += 2;
+ if (nr_lf)
+ {
+ size = count+nr_lf;
+ if ((q = p = malloc(size)))
+ {
+ for (s=buf, i=0, j=0; i<count; i++)
+ {
+ if (s[i]=='\n' && s[i+1]==0)
+ {
+ p[j++] = '\r';
+ p[j++] = 0;
+ }
+ p[j++] = s[i++];
+ p[j++] = s[i];
+ }
+ }
+ else
+ {
+ FIXME("Malloc failed\n");
+ nr_lf = 0;
+ size = count;
+ q = buf;
+ }
+ }
+ else
+ {
+ size = count;
+ q = buf;
+ }
+ }
+ else
+ {
+ DWORD conv_len;
+
+ for(nr_lf=0, i=0; i<count; i+=2)
+ if (s[i]=='\n' && s[i+1]==0)
+ nr_lf++;
+
+ conv_len = WideCharToMultiByte(CP_UTF8, 0, (WCHAR*)buf, count/2, NULL, 0, NULL, NULL);
+ if(!conv_len) {
+ _dosmaperr(GetLastError());
+ free(p);
+ return -1;
+ }
+
+ size = conv_len+nr_lf;
+ if((p = malloc(count+nr_lf*2+size)))
+ {
+ for (s=buf, i=0, j=0; i<count; i++)
+ {
+ if (s[i]=='\n' && s[i+1]==0)
+ {
+ p[j++] = '\r';
+ p[j++] = 0;
+ }
+ p[j++] = s[i++];
+ p[j++] = s[i];
+ }
+ q = p+count+nr_lf*2;
+ WideCharToMultiByte(CP_UTF8, 0, (WCHAR*)p, count/2+nr_lf,
+ p+count+nr_lf*2, conv_len+nr_lf, NULL, NULL);
+ }
+ else
+ {
+ FIXME("Malloc failed\n");
+ nr_lf = 0;
+ size = count;
+ q = buf;
+ }
+ }
+
+ if (!WriteFile(hand, q, size, &num_written, NULL))
+ num_written = -1;
+ if(p)
+ free(p);
+ if (num_written != size)
+ {
+ TRACE("WriteFile (fd %d, hand %p) failed-last error (%d), num_written %d\n",
+ fd, hand, GetLastError(), num_written);
+ *_errno() = ENOSPC;
+ return s - buf_start;
+ }
+ return count;
+ }
+
+ return -1;
}
/*********************************************************************
*/
int CDECL feof(FILE* file)
{
- int ret;
-
- _lock_file(file);
- ret = file->_flag & _IOEOF;
- _unlock_file(file);
-
- return ret;
+ return file->_flag & _IOEOF;
}
/*********************************************************************
*/
int CDECL ferror(FILE* file)
{
- int ret;
-
- _lock_file(file);
- ret = file->_flag & _IOERR;
- _unlock_file(file);
-
- return ret;
+ return file->_flag & _IOERR;
}
/*********************************************************************
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);
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)
- {
+
+ 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;
+ }
+
+ if(_write(file->_file, ptr, wrcnt) <= 0) {
file->_flag |= _IOERR;
- pwritten=0;
+ break;
}
- written += pwritten;
+ written += wrcnt;
+ wrcnt = 0;
+ } else {
+ if(_flsbuf(*(const char*)ptr, file) == EOF)
+ break;
+ written++;
+ wrcnt--;
+ ptr = (const char*)ptr + 1;
}
}
*/
__int64 CDECL _ftelli64(FILE* file)
{
- /* TODO: just call fgetpos and return lower half of result */
- int off=0;
__int64 pos;
_lock_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<file->_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<file->_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<file->_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<file->_ptr; p++)
+ if(*p == '\n')
+ pos++;
}
}
}
_unlock_file(file);
- return off + pos;
+ return pos;
}
/*********************************************************************
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;
}
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;
}
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
{
/* 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;
}
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;
}
static _invalid_parameter_handler invalid_parameter_handler = NULL;
-/*
- * @implemented
+/*********************************************************************
+ * _errno (MSVCRT.@)
*/
-unsigned long* CDECL __doserrno(void)
+int CDECL *_errno(void)
{
- return &(msvcrt_get_thread_data()->thread_doserrno);
+ return &(msvcrt_get_thread_data()->thread_errno);
}
-/*
- * @implemented
+/*********************************************************************
+ * __doserrno (MSVCRT.@)
*/
-int CDECL *_errno(void)
+unsigned long* CDECL __doserrno(void)
{
- return &(msvcrt_get_thread_data()->thread_errno);
+ return &(msvcrt_get_thread_data()->thread_doserrno);
}
-/*
- * @implemented
+/*********************************************************************
+ * _get_errno (MSVCRT.@)
*/
-errno_t CDECL _get_doserrno(unsigned long *pValue)
+errno_t CDECL _get_errno(int *pValue)
{
if (!pValue)
return EINVAL;
- *pValue = *__doserrno();
+ *pValue = *_errno();
return 0;
}
-/*
- * @implemented
+/*********************************************************************
+ * _get_doserrno (MSVCRT.@)
*/
-errno_t CDECL _set_doserrno(unsigned long error)
+errno_t CDECL _get_doserrno(unsigned long *pValue)
{
- *__doserrno() = error;
+ if (!pValue)
+ return EINVAL;
+
+ *pValue = *__doserrno();
return 0;
}
-/*
- * @implemented
+/*********************************************************************
+ * _set_errno (MSVCRT.@)
*/
-errno_t CDECL _get_errno(int *pValue)
+errno_t CDECL _set_errno(int value)
{
- if (!pValue)
- return EINVAL;
-
- *pValue = *_errno();
+ *_errno() = value;
return 0;
}
-/*
- * @implemented
+/*********************************************************************
+ * _set_doserrno (MSVCRT.@)
*/
-int CDECL _set_errno(int error)
+errno_t CDECL _set_doserrno(unsigned long value)
{
- *_errno() = error;
+ *__doserrno() = value;
return 0;
}
}
/******************************************************************************
-* _seterrormode (MSVCRT.@)
-*/
+ * _seterrormode (MSVCRT.@)
+ */
void CDECL _seterrormode(int mode)
{
SetErrorMode( 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
invalid_parameter_handler = handler;
return old;
}
-/* EOF */
{
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);
#include <precomp.h>
#include <tchar.h>
+#include <mbctype.h>
#if IS_SECAPI
#define _FAILURE -1
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;
/* 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';
}
*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;
}
}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;
}
*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;
}
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;
}
} 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;
}
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;
}
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)
}
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;
}
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;
}
__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;
}
__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;
}
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;
}
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
/* GLOBALS *******************************************************************/
-POBJECT_TYPE _ExEventObjectType = NULL;
+POBJECT_TYPE ExEventObjectType = NULL;
GENERIC_MAPPING ExpEventMapping =
{
/* GLOBALS ******************************************************************/
-POBJECT_TYPE _ExSemaphoreObjectType;
+POBJECT_TYPE ExSemaphoreObjectType;
GENERIC_MAPPING ExSemaphoreMapping =
{
}
/* Acquire spinlock for ExpNonPagedLookasideListHead */
- OldIrql = KfAcquireSpinLock(&ExpNonPagedLookasideListLock);
+ KeAcquireSpinLock(&ExpNonPagedLookasideListLock, &OldIrql);
/* Copy info from non-paged lookaside lists */
ExpCopyLookasideInformation(&Info,
TRUE);
/* Release spinlock for ExpNonPagedLookasideListHead */
- KfReleaseSpinLock(&ExpNonPagedLookasideListLock, OldIrql);
+ KeReleaseSpinLock(&ExpNonPagedLookasideListLock, OldIrql);
if (Remaining == 0)
{
}
/* Acquire spinlock for ExpPagedLookasideListHead */
- OldIrql = KfAcquireSpinLock(&ExpPagedLookasideListLock);
+ KeAcquireSpinLock(&ExpPagedLookasideListLock, &OldIrql);
/* Copy info from paged lookaside lists */
ExpCopyLookasideInformation(&Info,
TRUE);
/* Release spinlock for ExpPagedLookasideListHead */
- KfReleaseSpinLock(&ExpPagedLookasideListLock, OldIrql);
+ KeReleaseSpinLock(&ExpPagedLookasideListLock, OldIrql);
Leave:
ULONG FsRtlPagingIoResourceSelector;
NTSTATUS NTAPI INIT_FUNCTION FsRtlInitializeWorkerThread(VOID);
-static UCHAR LegalAnsiCharacterArray[] =
+static const UCHAR LegalAnsiCharacterArray[] =
{
0, /* CTRL+@, 0x00 */
0, /* CTRL+A, 0x01 */
FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL /* 0x7f */
};
-PUCHAR FsRtlLegalAnsiCharacterArray = LegalAnsiCharacterArray;
+const UCHAR * const FsRtlLegalAnsiCharacterArray = LegalAnsiCharacterArray;
/* PRIVATE FUNCTIONS *********************************************************/
{
/// FIXME
__debugbreak();
- return (PointerPte->u.Long & 0xFFFFFC01 != 0);
+ return ((PointerPte->u.Long & 0xFFFFFC01) != 0);
}
VOID
// Global data inside the File System Runtime Library
//
extern PERESOURCE FsRtlPagingIoResources;
-extern PUCHAR _FsRtlLegalAnsiCharacterArray;
extern PAGED_LOOKASIDE_LIST FsRtlFileLockLookasideList;
#include <cportlib/cportlib.h>
-#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;
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;
//
// 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 */
/* We are disabled now */
KdDebuggerEnabled = FALSE;
-#undef KdDebuggerEnabled
SharedUserData->KdDebuggerEnabled = FALSE;
-#define KdDebuggerEnabled _KdDebuggerEnabled
}
}
//
BOOLEAN KdBreakAfterSymbolLoad;
BOOLEAN KdPitchDebugger;
-BOOLEAN _KdDebuggerNotPresent;
-BOOLEAN _KdDebuggerEnabled;
+BOOLEAN KdDebuggerNotPresent;
+BOOLEAN KdDebuggerEnabled;
BOOLEAN KdAutoEnableOnEvent;
BOOLEAN KdBlockEnable;
BOOLEAN KdIgnoreUmExceptions;
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)
/* 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 */
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);
@ 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)
@ 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()
@ 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)
@ 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)
@ 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)
@ 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
@ 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)
@ 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)
@ 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)
{
KIRQL OldIrql;
- OldIrql = KfAcquireSpinLock(&PspQuotaLock);
+ KeAcquireSpinLock(&PspQuotaLock, &OldIrql);
InsertTailList(&PspQuotaBlockList, &QuotaBlock->QuotaList);
- KfReleaseSpinLock(&PspQuotaLock, OldIrql);
+ KeReleaseSpinLock(&PspQuotaLock, OldIrql);
}
VOID
if (QuotaBlock != &PspDefaultQuotaBlock &&
InterlockedDecrementUL(&QuotaBlock->ReferenceCount) == 0)
{
- OldIrql = KfAcquireSpinLock(&PspQuotaLock);
+ KeAcquireSpinLock(&PspQuotaLock, &OldIrql);
RemoveEntryList(&QuotaBlock->QuotaList);
- KfReleaseSpinLock(&PspQuotaLock, OldIrql);
+ KeReleaseSpinLock(&PspQuotaLock, OldIrql);
ExFreePool(QuotaBlock);
}
}
-if(ARCH STREQUAL "i386")
- add_subdirectory(ntvdm)
-endif()
+add_subdirectory(ntvdm)
add_subdirectory(win)
add_subdirectory(win32)
-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)
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* 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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* 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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ * 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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ * 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 */
--- /dev/null
+/*
+ * COPYRIGHT: GPL - See COPYING in the top level directory
+ * PROJECT: ReactOS Virtual DOS Machine
+ * FILE: bop.c
+ * PURPOSE: BIOS Operation Handlers
+ * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ * 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 */
--- /dev/null
+/*
+ * COPYRIGHT: GPL - See COPYING in the top level directory
+ * PROJECT: ReactOS Virtual DOS Machine
+ * FILE: bop.h
+ * PURPOSE: BIOS Operation Handlers
+ * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ * 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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+#include "callback.h"
+
+#include "bop.h"
+#include <isvbop.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
+
+
+#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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ * 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 */
--- /dev/null
+/*
+ * COPYRIGHT: GPL - See COPYING in the top level directory
+ * PROJECT: ReactOS Virtual DOS Machine
+ * FILE: clock.c
+ * PURPOSE: Clock for VDM
+ * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ * 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;
+}
--- /dev/null
+/*
+ * COPYRIGHT: GPL - See COPYING in the top level directory
+ * PROJECT: ReactOS Virtual DOS Machine
+ * FILE: clock.h
+ * PURPOSE: Clock for VDM
+ * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+#ifndef _CLOCK_H_
+#define _CLOCK_H_
+
+/* FUNCTIONS ******************************************************************/
+
+VOID ClockUpdate(VOID);
+BOOLEAN ClockInitialize(VOID);
+
+#endif // _CLOCK_H_
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ * 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 <ndk/obtypes.h>
+
+/* 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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ * 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 */
--- /dev/null
+/*
+ * COPYRIGHT: GPL - See COPYING in the top level directory
+ * PROJECT: ReactOS Virtual DOS Machine
+ * FILE: dos.c
+ * PURPOSE: VDM DOS Kernel
+ * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* 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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* 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 */
--- /dev/null
+/*
+ * COPYRIGHT: GPL - See COPYING in the top level directory
+ * PROJECT: ReactOS Virtual DOS Machine
+ * FILE: dos.h
+ * PURPOSE: VDM DOS Kernel
+ * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* 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);
+}
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* 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 <isvbop.h>
+
+/* 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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#ifndef _EMULATOR_H_
+#define _EMULATOR_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+#include <fast486.h>
+
+/* 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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* 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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* 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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* 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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#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 */
--- /dev/null
+/*
+ * 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 <ndk/iofuncs.h>
+#include <ndk/obfuncs.h>
+#include <ndk/rtlfuncs.h>
+
+/* DDK Driver Headers */
+#include <ntddbeep.h>
+
+/* 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ * 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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ * 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 */
--- /dev/null
+/*
+ * COPYRIGHT: GPL - See COPYING in the top level directory
+ * PROJECT: ReactOS Virtual DOS Machine
+ * FILE: vga.c
+ * PURPOSE: VGA hardware emulation
+ * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* 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 <ntddvdeo.h>
+
+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 */
--- /dev/null
+/*
+ * COPYRIGHT: GPL - See COPYING in the top level directory
+ * PROJECT: ReactOS Virtual DOS Machine
+ * FILE: vga.h
+ * PURPOSE: VGA hardware emulation
+ * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ * 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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ * 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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ * 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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ * 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 */
+++ /dev/null
-LANGUAGE LANG_BULGARIAN, SUBLANG_DEFAULT
-
-STRINGTABLE
-BEGIN
- STRING_WelcomeMsg "Поддръжка на РеактОС за привидна ДОС машина.\n"
- STRING_PromptMsg "Напишете r<cr> за пускане, s<cr> за спиране или q<cr> за изход."
-END
-/* 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<cr> pro spuštìní, s<cr> pro vypnutí nebo q<cr> 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
-/*
- * 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<cr> zum Starten, s<cr> zum Herunterfahren oder q<cr> 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
STRINGTABLE
BEGIN
- STRING_WelcomeMsg "ReactOS Virtual DOS Machine support.\n"
- STRING_PromptMsg "Type r<cr> to run, s<cr> to shutdown or q<cr> 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
-/* 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<cr> para correr, s<cr> para desactivar or q<cr> 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
STRINGTABLE
BEGIN
- STRING_WelcomeMsg "Aide de la Machine DOS Virtuel de ReactOS.\n"
- STRING_PromptMsg "Taper r<cr> pour démarrer, s<cr> pour éteindre ou q<cr> 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
+++ /dev/null
-/* 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<cr>, leállításhoz a s<cr> vagy kilépéshez a q<cr> gombot."
-END
+++ /dev/null
-LANGUAGE LANG_INDONESIAN, SUBLANG_DEFAULT
-
-STRINGTABLE
-BEGIN
- STRING_WelcomeMsg "Dukungan ReactOS Virtual DOS Machine.\n"
- STRING_PromptMsg "Ketik r<cr> untuk menjalankan, s<cr> untuk mematikan atau q<cr> untuk keluar sekarang."
-END
-/*
-* 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<invio> per avviare, s<invio> per arrestare o q<invio> 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
+++ /dev/null
-LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
-
-STRINGTABLE
-BEGIN
- STRING_WelcomeMsg "ReactOS Virtual DOS Machine support.\n"
- STRING_PromptMsg "起動するには r<cr> を、シャットダウンするには s<cr> を、今すぐ終了させるには q<cr> を入力してください。"
-END
+++ /dev/null
-LANGUAGE LANG_NORWEGIAN, SUBLANG_NEUTRAL
-
-STRINGTABLE
-BEGIN
- STRING_WelcomeMsg "ReactOS Vituell DOS Maskin støtte.\n"
- STRING_PromptMsg "Skriv r<cr> for å kjøre, s<cr> å avslutte eller q<cr> for å slutte nå."
-END
-/*
- * 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<cr> aby uruchomić, s<cr> aby wyłączyć lub q<cr>, 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
+++ /dev/null
-LANGUAGE LANG_PORTUGUESE, SUBLANG_NEUTRAL
-
-STRINGTABLE
-BEGIN
- STRING_WelcomeMsg "ReactOS subsistema para suporte DOS de 16 bits.\n"
- STRING_PromptMsg "Digite r<cr> para executar, s<cr> para desligar ou q<cr> para sair."
-END
+++ /dev/null
-/*
- * 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<cr> pentru a executa, s<cr> pentru a închide sau q<cr> pentru a ieși imediat."
-END
+++ /dev/null
-LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
-
-STRINGTABLE
-BEGIN
- STRING_WelcomeMsg "Виртуальная машина поддержки DOS для ReactOS.\n"
- STRING_PromptMsg "Введите r<cr> для запуска, s<cr> для выключения или q<cr> выхода."
-END
+++ /dev/null
-/* 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<cr> pre spustenie, s<cr> pre vypnutie alebo q<cr> pre okamžité skonèenie."
-END
+++ /dev/null
-LANGUAGE LANG_THAI, SUBLANG_DEFAULT
-
-STRINGTABLE
-BEGIN
- STRING_WelcomeMsg "รองรับการทำงานระบบดอสเสมือนของ ReactOS\n"
- STRING_PromptMsg "แบบ r<cr> เพื่อทำงาน, s<cr> เพื่อปิดระบบหรือ q<cr> เพื่อออกทันที"
-END
+++ /dev/null
-/*
- * 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<cr> для запуску, s<cr> для закриття або q<cr>, щоб вийти зараз."
-END
+++ /dev/null
-LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
-
-STRINGTABLE
-BEGIN
- STRING_WelcomeMsg "ReactOS 虚拟 DOS 机支持。\n"
- STRING_PromptMsg "输入 r<cr> 以便运行,s<cr> 以便关闭或者 q<cr> 以便立即退出。"
-END
+++ /dev/null
-LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL
-
-STRINGTABLE
-BEGIN
- STRING_WelcomeMsg "ReactOS 虛擬 DOS 機支援。\n"
- STRING_PromptMsg "鍵入 r<cr> 以便運行, s<cr> 以便關閉或者 q<cr> 以便立即退出。"
-END
/*
- * 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 <theflash AT sdf DOT lonestar DOT org>
*/
-/* INCLUDES *****************************************************************/
+/* INCLUDES *******************************************************************/
-#include <stdarg.h>
-#define WIN32_NO_STATUS
-#include <windef.h>
-#include <winbase.h>
-#include <wincon.h>
-#include <winuser.h>
-#include <stdio.h>
+#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 <debug.h>
+/* VARIABLES ******************************************************************/
+
+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;
+
+#ifndef STANDALONE
+ULONG SessionId = 0;
+#endif
-/* GLOBALS ******************************************************************/
+HANDLE VdmTaskEvent = NULL;
+/*
+ * Those menu helpers were taken from the GUI frontend in winsrv.dll
+ */
+typedef struct _VDM_MENUITEM
+{
+ UINT uID;
+ const struct _VDM_MENUITEM *SubMenu;
+ WORD wCmdID;
+} VDM_MENUITEM, *PVDM_MENUITEM;
-/* FUNCTIONS *****************************************************************/
+static const VDM_MENUITEM VdmMenuItems[] =
+{
+ { IDS_VDM_QUIT, NULL, ID_VDM_QUIT },
-void PrintString(char* fmt,...)
+ { 0, NULL, 0 } /* End of list */
+};
+
+static const VDM_MENUITEM VdmMainMenuItems[] =
{
- char buffer[512];
- va_list ap;
+ { -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 */
- va_start(ap, fmt);
- vsprintf(buffer, fmt, ap);
- va_end(ap);
+ { 0, NULL, 0 } /* End of list */
+};
- OutputDebugStringA(buffer);
+static VOID
+AppendMenuItems(HMENU hMenu,
+ const VDM_MENUITEM *Items)
+{
+ UINT i = 0;
+ WCHAR szMenuString[255];
+ HMENU hSubMenu;
+
+ 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);
+
+ if (!AppendMenuW(hMenu,
+ MF_STRING | MF_POPUP,
+ (UINT_PTR)hSubMenu,
+ szMenuString))
+ {
+ DestroyMenu(hSubMenu);
+ }
+ }
+ }
+ else
+ {
+ AppendMenuW(hMenu,
+ MF_STRING,
+ Items[i].wCmdID,
+ szMenuString);
+ }
+ }
+ }
+ else
+ {
+ AppendMenuW(hMenu,
+ MF_SEPARATOR,
+ 0,
+ NULL);
+ }
+ i++;
+ } while (!(Items[i].uID == 0 && Items[i].SubMenu == NULL && Items[i].wCmdID == 0));
}
-/*
-GetVersion
-GetVolumeInformationW
-GetWindowsDirectoryA
-GlobalMemoryStatus
-HeapAlloc
-HeapCreate
-HeapDestroy
-HeapFree
-HeapReAlloc
-
-GetNextVDMCommand
-ExitVDM
-RegisterConsoleVDM
-SetVDMCurrentDirectories
-VDMConsoleOperation
-WriteConsoleInputVDMW
-
-NtSetLdtEntries
-NtTerminateProcess
-
-NtMapViewOfSection
-NtUnmapViewOfSection
-
-NtVdmControl
- */
-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)
+static VOID
+CreateVdmMenu(HANDLE ConOutHandle)
{
- BOOL Result;
- STARTUPINFOA StartupInfo;
-
- 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;
+ hConsoleMenu = ConsoleMenuControl(ConOutHandle,
+ ID_SHOWHIDE_MOUSE,
+ ID_VDM_QUIT);
+ if (hConsoleMenu == NULL) return;
+
+ VdmMenuPos = GetMenuItemCount(hConsoleMenu);
+ AppendMenuItems(hConsoleMenu, VdmMainMenuItems);
+ DrawMenuBar(GetConsoleWindow());
}
-BOOL
-ShutdownVDM(PVDM_CONTROL_BLOCK vdm)
+static VOID
+DestroyVdmMenu(VOID)
{
- BOOL result = TRUE;
+ 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));
- return result;
+ DrawMenuBar(GetConsoleWindow());
}
-BOOL ReadConfigForVDM(PVDM_CONTROL_BLOCK vdm)
+static VOID ShowHideMousePointer(HANDLE ConOutHandle, BOOLEAN ShowPtr)
{
- BOOL result = TRUE;
- DWORD dwError;
- HANDLE hFile;
-
- 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);
+ 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;
+ }
- 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?
+ break;
}
- if (dwError == ERROR_ALREADY_EXISTS) {
- // read the line entries and cache in some struct...
+ default:
+ {
+ /* Stop the VDM if the user logs out or closes the console */
+ EmulatorTerminate();
}
- CloseHandle(hFile);
}
+ return TRUE;
+}
- return result;
+static VOID
+ConsoleInitUI(VOID)
+{
+ CreateVdmMenu(ConsoleOutput);
}
-BOOL
-LoadConfigDriversForVDM(PVDM_CONFIG vdmConfig)
+static VOID
+ConsoleCleanupUI(VOID)
{
- BOOL result = TRUE;
+ /* Display again properly the mouse pointer */
+ if (ShowPointer) ShowHideMousePointer(ConsoleOutput, ShowPointer);
- return result;
+ DestroyVdmMenu();
}
-BOOL
-SetConfigOptionsForVDM(PVDM_AUTOEXEC vdmAutoexec)
+static BOOL
+ConsoleAttach(VOID)
{
- BOOL result = TRUE;
+ /* 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;
+ }
+
+ /* Initialize the UI */
+ ConsoleInitUI();
- return result;
+ return TRUE;
}
-BOOL
-CreateVDM(PVDM_CONTROL_BLOCK vdm)
+static VOID
+ConsoleDetach(VOID)
{
-// 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;
- }
+ /* Restore the original input and output console modes */
+ SetConsoleMode(ConsoleOutput, OrgConsoleOutputMode);
+ SetConsoleMode(ConsoleInput , OrgConsoleInputMode );
- }
+ /* Cleanup the UI */
+ ConsoleCleanupUI();
+}
- GetSystemInfo(&inf);
- vdm->hHeap = HeapCreate(0, inf.dwAllocationGranularity, 0);
- if (vdm->hHeap == NULL) {
- DPRINT("VDM: failed to create heap.\n");
+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;
}
-#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;
+ /* 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;
}
- return TRUE;
+
+ /* Effectively attach to the console */
+ return ConsoleAttach();
}
-BOOL
-DestroyVDM(PVDM_CONTROL_BLOCK vdm)
+static VOID
+ConsoleCleanup(VOID)
{
- BOOL result = TRUE;
+ /* Detach from the console */
+ ConsoleDetach();
+
+ /* Close the console handles */
+ if (ConsoleOutput != INVALID_HANDLE_VALUE) CloseHandle(ConsoleOutput);
+ if (ConsoleInput != INVALID_HANDLE_VALUE) CloseHandle(ConsoleInput);
+}
- 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;
+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;
}
- vdm->ImageMem = NULL;
}
- if (vdm->hHeap != NULL) {
- if (!HeapDestroy(vdm->hHeap)) {
- DPRINT("VDM: failed to destroy heap %x.\n", vdm->hHeap);
- result = FALSE;
+
+ 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;
}
- vdm->hHeap = NULL;
+
+ First = FALSE;
}
- return result;
+ while (AcceptCommands);
+
+ return 0;
}
+#endif
-int WINAPI
-WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
+INT
+wmain(INT argc, WCHAR *argv[])
{
- VDM_CONTROL_BLOCK VdmCB;
+#ifdef STANDALONE
+
DWORD Result;
- ULONG i;
- BOOL vdmStarted = FALSE;
+ CHAR ApplicationName[MAX_PATH];
+ CHAR CommandLine[DOS_CMDLINE_LENGTH];
- WCHAR WelcomeMsg[RC_STRING_MAX_SIZE];
- WCHAR PromptMsg[RC_STRING_MAX_SIZE];
- CHAR InputBuffer[255];
+ if (argc >= 2)
+ {
+ WideCharToMultiByte(CP_ACP, 0, argv[1], -1, ApplicationName, sizeof(ApplicationName), NULL, NULL);
- LoadStringW( GetModuleHandle(NULL), STRING_WelcomeMsg, WelcomeMsg,sizeof(WelcomeMsg) / sizeof(WelcomeMsg[0]));
- LoadStringW( GetModuleHandle(NULL), STRING_PromptMsg, PromptMsg ,sizeof(PromptMsg) / sizeof(PromptMsg[0]));
+ 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 <executable> [<parameters>]\n");
+ return 0;
+ }
- AllocConsole();
- SetConsoleTitleW(L"ntvdm");
+#else
- WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE),
- WelcomeMsg, lstrlenW(WelcomeMsg), // wcslen(WelcomeMsg),
- &Result, NULL);
+ INT i;
+ WCHAR *endptr;
- if (!CreateVDM(&VdmCB)) {
- DPRINT("VDM: failed to create VDM.\n");
- //SetLastError();
- return 2;
+ /* 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;
+ }
}
- ReadConfigForVDM(&VdmCB);
+#endif
+
+ DPRINT1("\n\n\nNTVDM - Starting...\n\n\n");
+
+ /* Create the task event */
+ VdmTaskEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ ASSERT(VdmTaskEvent != NULL);
- if (!LoadConfigDriversForVDM(&(VdmCB.vdmConfig))) {
- DPRINT("VDM: failed to load configuration drivers.\n");
- //SetLastError();
- return 2;
+ /* Initialize the console */
+ if (!ConsoleInit())
+ {
+ wprintf(L"FATAL: A problem occurred when trying to initialize the console\n");
+ goto Cleanup;
}
- if (!SetConfigOptionsForVDM(&(VdmCB.vdmAutoexec))) {
- DPRINT("VDM: failed to set configuration options.\n");
- //SetLastError();
- return 3;
+
+ /* Initialize the emulator */
+ if (!EmulatorInitialize(ConsoleInput, ConsoleOutput))
+ {
+ wprintf(L"FATAL: Failed to initialize the emulator\n");
+ goto Cleanup;
}
- 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");
- }
- } 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 {
- DPRINT("VDM: not started.\n");
- }
- }
- if (InputBuffer[0] == 'q' || InputBuffer[0] == 'Q') {
- break;
- }
+ /* Initialize the system BIOS */
+ if (!BiosInitialize(NULL))
+ {
+ wprintf(L"FATAL: Failed to initialize the VDM BIOS.\n");
+ goto Cleanup;
}
- if (!ShutdownVDM(&VdmCB)) {
- DPRINT("VDM: failed to cleanly shutdown VDM.\n");
- //SetLastError();
- return 5;
+ /* Initialize the VDM DOS kernel */
+ if (!DosInitialize(NULL))
+ {
+ wprintf(L"FATAL: Failed to initialize the VDM DOS kernel.\n");
+ goto Cleanup;
}
- if (!DestroyVDM(&VdmCB)) {
- DPRINT("VDM: failed to cleanly destroy VDM.\n");
- //SetLastError();
- return 6;
+#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;
}
- ExitProcess(0);
+ /* 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 */
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#ifndef _NTVDM_H_
+#define _NTVDM_H_
+
+/* INCLUDES *******************************************************************/
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <conio.h>
+#include <wchar.h>
+
+#define WIN32_NO_STATUS
+#include <windef.h>
+#include <winbase.h>
+#include <wingdi.h>
+#include <wincon.h>
+#include <winnls.h>
+#include <winreg.h>
+#include <winuser.h>
+#include <subsys/win/vdm.h>
+
+#include <vddsvc.h>
+
+DWORD WINAPI SetLastConsoleEventActive(VOID);
+
+#include <debug.h>
+
+/*
+ * Activate this line if you want to run NTVDM in standalone mode with:
+ * ntvdm.exe <program>
+ */
+// #define STANDALONE
+
+/* FUNCTIONS ******************************************************************/
+
+#ifndef STANDALONE
+extern ULONG SessionId;
+#endif
+
+extern HANDLE VdmTaskEvent;
+
+VOID DisplayMessage(LPCWSTR Format, ...);
+
+#endif // _NTVDM_H_
+
+/* EOF */
#include <windef.h>
+#include <winuser.h>
+// #include <commctrl.h>
#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 <reactos/version.rc>
+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
--- /dev/null
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 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()
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
#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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 <isvbop.h>
+
+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 */
--- /dev/null
+/*
+ * 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 */
#include <ndk/psfuncs.h>
#include <ndk/exfuncs.h>
#include <ndk/umfuncs.h>
+#include <ndk/cmfuncs.h>
/* PSEH for SEH Support */
#include <pseh/pseh2.h>
/* INCLUDES *******************************************************************/
#include "basesrv.h"
+#include "vdm.h"
#include <winreg.h>
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 */
#endif
LoadedServerDll->SizeOfProcessData = 0;
LoadedServerDll->ConnectCallback = NULL;
- LoadedServerDll->DisconnectCallback = NULL;
+ LoadedServerDll->DisconnectCallback = BaseSrvDisconnect;
LoadedServerDll->ShutdownProcessCallback = NULL;
BaseSrvDllInstance = LoadedServerDll->ServerHandle;
/* Initialize DOS devices management */
BaseInitDefineDosDevice();
+ /* Initialize VDM support */
+ BaseInitializeVDM();
+
/* All done */
return STATUS_SUCCESS;
}
/* INCLUDES *******************************************************************/
#include "basesrv.h"
+#include "vdm.h"
#define NDEBUG
#include <debug.h>
/* 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;
* FILE: subsystems/win/basesrv/vdm.c
* PURPOSE: Virtual DOS Machines (VDM) Support
* PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ * Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*/
/* INCLUDES *******************************************************************/
#include "basesrv.h"
+#include "vdm.h"
#define NDEBUG
#include <debug.h>
+/* 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)
--- /dev/null
+/*
+ * 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 <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#ifndef __VDM_H__
+#define __VDM_H__
+
+#include <win/vdm.h>
+
+/* 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__
}
/* 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;
}
*/
#include "videoprt.h"
+#include <stdio.h>
#define NDEBUG
#include <debug.h>
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;
/* Create a handle, and have Ob fill out the pKEvent field */
Status = ObReferenceObjectByHandle(EngEvent,
EVENT_ALL_ACCESS,
- ExEventObjectType,
+ *ExEventObjectType,
UserMode,
&EngEvent->pKEvent,
NULL);
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;
INT cyBmp; /* Height " */
//// ReactOS
UNICODE_STRING lpstr;
- struct tagITEM *Next;
} ITEM, *PITEM;
typedef struct tagMENULIST
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;
/* 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)
{
/* 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)
{
goto error;
}
Status = ObReferenceObjectByHandle(ptiCurrent->hEventQueueClient, 0,
- ExEventObjectType, KernelMode,
+ *ExEventObjectType, KernelMode,
(PVOID*)&ptiCurrent->pEventQueueServer, NULL);
if (!NT_SUCCESS(Status))
{
/* 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. */
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) &= ~MF_GRAYED; \
+ } /* Separate the two for test_menu_resource_layout.*/ \
+ if((change) & MF_DISABLED) { \
+ (state) |= MF_DISABLED; \
} else { \
- (state) &= ~MFS_DISABLED; \
+ (state) &= ~MF_DISABLED; \
} \
if((change) & MFS_CHECKED) { \
(state) |= MFS_CHECKED; \
} \
}
-#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);
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)
{
return Menu;
}
-BOOL FASTCALL
-IntFreeMenuItem(PMENU Menu, PITEM MenuItem, BOOL bRecurse)
+PMENU FASTCALL VerifyMenu(PMENU pMenu)
{
- FreeMenuText(Menu,MenuItem);
- if(bRecurse && MenuItem->spSubMenu)
- {
- IntDestroyMenuObject(MenuItem->spSubMenu, bRecurse, TRUE);
- }
-
- /* Free memory */
- DesktopHeapFree(Menu->head.rpdesk, MenuItem);
-
- return TRUE;
-}
+ HMENU hMenu;
+ PITEM pItem;
+ UINT i;
+ if (!pMenu) return NULL;
-BOOL FASTCALL
-IntRemoveMenuItem(PMENU Menu, UINT uPosition, UINT uFlags, BOOL bRecurse)
-{
- PITEM PrevMenuItem, MenuItem = NULL;
- if(IntGetMenuItemByFlag(Menu, uPosition, uFlags, &Menu, &MenuItem, &PrevMenuItem) > -1)
+ ERR("VerifyMenu 1!\n");
+ _SEH2_TRY
{
- 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
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;
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;
* 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)
{
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)
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)
{
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;
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;
}
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;
{
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)
{
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)
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))
{
FreeMenuText(MenuObject,MenuItem);
RtlInitUnicodeString(&MenuItem->lpstr, NULL);
+ MenuItem->Xlpstr = NULL;
}
if(lpmii->fType & MFT_BITMAP)
{
{ /* 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)
{
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);
}
}
else
{ // If submenu just dereference it.
- if (MenuItem->spSubMenu) UserDereferenceObject(MenuItem->spSubMenu);
+ if (MenuItem->spSubMenu) IntReleaseMenuObject(MenuItem->spSubMenu);
MenuItem->spSubMenu = NULL;
}
}
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;
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)
{
}
-/**********************************************************************
- * 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)
{
}
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)
{
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 */
{
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)
- {
- if(MenuItem->fState & MFS_DEFAULT)
- {
-
- if(!(gmdiFlags & GMDI_USEDISABLED) && (MenuItem->fState & MFS_DISABLED))
- break;
+ /* empty menu */
+ if (!MenuItem) return -1;
- 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)--;
+ while ( !( MenuItem->fState & MFS_DEFAULT ) )
+ {
+ i++; MenuItem++;
+ if (i >= MenuObject->cItems ) return -1;
+ }
- if(sres > (UINT)-1)
- res = sres;
- }
+ /* default: don't return disabled items */
+ if ( (!(GMDI_USEDISABLED & gmdiFlags)) && (MenuItem->fState & MFS_DISABLED )) return -1;
- break;
- }
+ /* 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;
- MenuItem = MenuItem->Next;
- x++;
+ /* when item not found in submenu, return the popup item */
}
-
- return res;
+ return ( fByPos ) ? i : MenuItem->wID;
}
VOID FASTCALL
{
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);
}
PMENU Menu,
UINT uItem,
BOOL fByPosition,
- LPCMENUITEMINFOW UnsafeItemInfo)
+ LPCMENUITEMINFOW UnsafeItemInfo,
+ PUNICODE_STRING lpstr)
{
NTSTATUS Status;
ROSMENUITEMINFO ItemInfo;
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) */
return FALSE;
}
ItemInfo.hbmpItem = (HBITMAP)0;
- return IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo);
+ return IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo, lpstr);
}
SetLastNtError(Status);
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;
UINT Item,
BOOL ByPosition,
PROSMENUITEMINFO UnsafeItemInfo,
- BOOL SetOrGet)
+ BOOL SetOrGet,
+ PUNICODE_STRING lpstr)
{
PITEM MenuItem;
ROSMENUITEMINFO ItemInfo;
if (SetOrGet)
{
- Ret = IntSetMenuItemInfo(Menu, MenuItem, &ItemInfo, NULL);
+ Ret = IntSetMenuItemInfo(Menu, MenuItem, &ItemInfo, lpstr);
}
else
{
{
LONG XMove, YMove;
PITEM MenuItem;
- //int p = 0;
if (!pWnd)
{
return FALSE;
}
- //if(Menu->Process != PsGetCurrentProcess())
if (Menu->head.rpdesk != pti->rpdesk)
{
EngSetLastError(ERROR_ACCESS_DENIED);
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;
//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
{
PMENU Menu, SubMenu;
PITEM MenuItem;
+ UINT i;
DECLARE_RETURN(UINT);
TRACE("Enter NtUserGetMenuIndex\n");
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:
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;
{
break;
}
- mi = mi->Next;
}
RETURN( (mi ? i : NO_SELECTED_ITEM));
RETURN(FALSE);
}
- lstrCaption.Buffer = NULL;
+ RtlInitUnicodeString(&lstrCaption, 0);
/* Check if we got a Caption */
if (lpszCaption && lpszCaption->Buffer)
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_);
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);
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 );
{
RETURN(FALSE);
}
-
+
ptiSendTo = IntSendTo(Window, Win32Thread, Msg);
if (Msg & 0x80000000 &&
((ClientInfo->CI_flags & CI_CURTHPRHOOK) ? 1 : 0),
(LPARAM)&CWP,
Hook->Proc,
- Hook->ihmod,
+ Hook->ihmod,
Hook->offPfn,
Hook->Ansi,
&Hook->ModuleName);
((ClientInfo->CI_flags & CI_CURTHPRHOOK) ? 1 : 0),
(LPARAM)&CWPR,
Hook->Proc,
- Hook->ihmod,
+ Hook->ihmod,
Hook->offPfn,
Hook->Ansi,
&Hook->ModuleName);
Status = ObReferenceObjectByHandle(hProcess,
PROCESS_QUERY_INFORMATION,
- PsProcessType,
+ *PsProcessType,
UserMode,
(PVOID*)&Process,
NULL);
break;
case THREADSTATE_INSENDMESSAGE:
{
- PUSER_SENT_MESSAGE Message =
+ PUSER_SENT_MESSAGE Message =
((PTHREADINFO)PsGetCurrentThreadWin32Thread())->pusmCurrent;
ERR("THREADSTATE_INSENDMESSAGE\n");
if (Message->QS_Flags & QS_SMRESULT) ret |= ISMEX_REPLIED;
}
- break;
+ break;
}
case THREADSTATE_GETMESSAGETIME:
ret = ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->timeLast;
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)
Status = ObReferenceObjectByHandle(hProcess,
PROCESS_QUERY_INFORMATION,
- PsProcessType,
+ *PsProcessType,
ExGetPreviousMode(),
(PVOID*)&Process,
NULL);
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);
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);
}
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);
}
#pragma once
-PMENU FASTCALL UserGetMenuObject(HMENU hMenu);
+FORCEINLINE PMENU UserGetMenuObject(HMENU hMenu)
+{
+ return ValidateHandle(hMenu, TYPE_MENU);
+}
#define ASSERT_REFS_CO(_obj_) \
{ \
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);
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;
RECTL valid_rects[2];
PROSRGNDATA VisRgn;
HRGN VisBefore = NULL;
+ HRGN VisBeforeJustClient = NULL;
HRGN VisAfter = NULL;
HRGN DirtyRgn = NULL;
HRGN ExposedRgn = NULL;
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);
+ }
+ }
}
}
((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
* 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. */
*/
int WINAPI TranslateAcceleratorA(HWND hWnd, HACCEL hAccTable, LPMSG lpMsg)
{
- MSG mCopy = *lpMsg;
- CHAR cChar;
- WCHAR wChar;
- NTSTATUS Status;
-
- if(!U32IsValidAccelMessage(lpMsg->message)) return 0;
-
- Status = RtlMultiByteToUnicodeN(&wChar, sizeof(wChar), NULL, &cChar, sizeof(cChar));
- if(!NT_SUCCESS(Status))
- {
- SetLastError(RtlNtStatusToDosError(Status));
- return 0;
- }
-
- return TranslateAcceleratorW(hWnd, hAccTable, &mCopy);
+ switch (lpMsg->message)
+ {
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ return TranslateAcceleratorW( hWnd, hAccTable, lpMsg );
+
+ 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 );
+ }
+
+ default:
+ return 0;
+ }
}
/* EOF */
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)))
{
}
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);
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
case WM_CHILDACTIVATE:
case WM_SYSCOMMAND:
case WM_SHOWWINDOW:
-#ifndef __REACTOS__
case WM_SETVISIBLE:
-#endif
case WM_SIZE:
case WM_NEXTMENU:
case WM_SYSCHAR:
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;
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);
*/
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;
}
/***********************************************************************
{
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)
{
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)
- {
- if (Item->fState & MFS_DEFAULT)
- {
- if (!(gmdiFlags & GMDI_USEDISABLED) &&
- (Item->fState & MFS_DISABLED) )
- break;
+ /* empty menu */
+ if (!Item) return -1;
- res = fByPos ? x : Item->wID;
+ while ( !( Item->fState & MFS_DEFAULT ) )
+ {
+ i++; Item++;
+ if (i >= Menu->cItems ) return -1;
+ }
- if ((*gismc < MAX_GOINTOSUBMENU) &&
- (gmdiFlags & GMDI_GOINTOPOPUPS) &&
- Item->spSubMenu)
- {
- if (DesktopPtrToUser(Item->spSubMenu) == Menu)
- break;
+ /* default: don't return disabled items */
+ if ( (!(GMDI_USEDISABLED & gmdiFlags)) && (Item->fState & MFS_DISABLED )) return -1;
- (*gismc)++;
- sres = IntGetMenuDefaultItem( DesktopPtrToUser(Item->spSubMenu), fByPos, gmdiFlags, gismc);
- (*gismc)--;
+ /* 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;
- if(sres > (UINT)-1)
- res = sres;
- }
- break;
- }
- Item = Item->Next ? DesktopPtrToUser(Item->Next) : NULL;
- x++;
+ /* when item not found in submenu, return the popup item */
}
- return res;
+ return ( fByPos ) ? i : Item->wID;
}
static BOOL GetMenuItemInfo_common ( HMENU hmenu,
if (!pItem)
{
SetLastError( ERROR_MENU_ITEM_NOT_FOUND);
- //SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
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;
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;
{
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;
}
}
}
-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
*
* 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;
}
* 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 */
- }
- if (i == 0)
- {
- MenuCleanupAllRosMenuItemInfo(MenuItems);
- return NO_SELECTED_ITEM;
- }
+ for(i = menu->iItem; i != 0 &&
+ !(pItem[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK));
+ --i); /* empty */
- for (--i; 0 != i; --i)
- if (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK))
- break;
+ if(i == 0)
+ return NO_SELECTED_ITEM;
+
+ for(--i; i != 0; --i) {
+ if (pItem[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK))
+ break;
+ }
- MenuCleanupAllRosMenuItemInfo(MenuItems);
TRACE("ret %d.\n", i );
return i;
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;
* 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 );
+
+ 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 |= MenuInfo->fFlags & MNF_POPUP ? MF_POPUP : 0;
- Flags |= MenuInfo->fFlags & MNF_SYSDESKMN ? MF_SYSMENU : 0;
+ 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);
}
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;
DeleteDC(hdcMem);
}
-
/***********************************************************************
* MenuDrawMenuItem
*
PWCHAR Text;
BOOL flat_menu = FALSE;
int bkgnd;
- PWND Wnd = ValidateHwnd(hWnd);
+ PWND Wnd = ValidateHwndNoErr(hWnd);
if (!Wnd)
return;
SetBkColor( hdc, GetSysColor( bkgnd ) );
}
+ TRACE("rect=%s\n", wine_dbgstr_rect( &lpitem->Rect));
rect = lpitem->Rect;
MENU_AdjustMenuItemRect(MenuInfo, &rect);
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;
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;
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
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);
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 */
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;
}
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;
}
-
- 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);
+ 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);
+
return TRUE;
}
PWND pWnd;
PPOPUPMENU pPopupMenu;
- pWnd = ValidateHwnd(Wnd);
+ pWnd = ValidateHwndNoErr(Wnd);
if (pWnd)
{
if (!pWnd->fnid)
}
break;
+#ifdef __REACTOS__
+ case WM_NCDESTROY:
+ NtUserSetWindowFNID(Wnd, FNID_DESTROY);
+ break;
+#endif
+
case WM_SHOWWINDOW:
if (0 != wParam)
{
return res;
}
-
/**********************************************************************
* MENUEX_ParseResource
*
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.@)
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
*
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;
/* 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 );
*/
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();
}
/***********************************************************************
{
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);
+ ////
}
}
}
* 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;
*
*/
static INT FASTCALL
-MenuButtonUp(MTRACKER *Mt, HMENU PtMenu, UINT Flags)
+MENU_ButtonUp(MTRACKER *Mt, HMENU PtMenu, UINT Flags)
{
INT Id;
ROSMENUINFO MenuInfo;
* 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;
}
/***********************************************************************
*
* 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))
+ if ((!menu) || (menu->iItem == NO_SELECTED_ITEM)) return 0;
+
+ //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))
{
- MenuCleanupRosMenuItemInfo(&ItemInfo);
- return ItemInfo.hSubMenu;
+ PMENU pSubMenu = DesktopPtrToUser(item->spSubMenu);
+ return UserHMGetHandle(pSubMenu);
}
-
- MenuCleanupRosMenuItemInfo(&ItemInfo);
- return NULL;
+ return 0;
}
/***********************************************************************
while (MenuTmp != Mt->CurrentMenu)
{
MenuPrev = MenuTmp;
- MenuTmp = MenuGetSubPopup(MenuPrev);
+ MenuTmp = MENU_GetSubPopup(MenuPrev);
}
if (MenuGetRosMenuInfo(&MenuInfo, MenuPrev))
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))
{
while (MenuTmp != Mt->CurrentMenu)
{
MenuPrev = MenuTmp;
- MenuTmp = MenuGetSubPopup(MenuPrev);
+ MenuTmp = MENU_GetSubPopup(MenuPrev);
}
if (! MenuGetRosMenuInfo(&PrevMenuInfo, MenuPrev))
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))
MSG msg;
ROSMENUINFO MenuInfo;
ROSMENUITEMINFO ItemInfo;
+ PMENU menu;
BOOL fRemove;
INT executedMenuId = -1;
MTRACKER mt;
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;
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;
}
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;
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;
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 */
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;
/* 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 */
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;
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;
/* 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);
}
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,
* 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))
CHILDID_SELF, 0);
return TRUE;
}
+
/***********************************************************************
* MenuExitTracking
*/
}
}
-
/***********************************************************************
* MenuTrackKbdMenuBar
*
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;
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);
/**********************************************************************
* 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;
+
+ 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) : "-" );
- if (!IsMenu(Menu))
+ /* 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 (!(wFlags & TPM_NONOTIFY))
+ SendMessageW(hWnd, WM_INITMENUPOPUP, (WPARAM) hMenu, 0);
- /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
- if (!(Flags & TPM_NONOTIFY))
- SendMessageW(Wnd, WM_INITMENUPOPUP, (WPARAM) Menu, 0);
+ 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 (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 (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;
}
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));
- }
- else
- {
- mii->fType |= MFT_SEPARATOR;
- if (!(Flags & (MF_GRAYED|MF_DISABLED)))
- Flags |= MF_GRAYED|MF_DISABLED;
- }
- }
-
- 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);
+ 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;
+ }
+ if( flags & MF_OWNERDRAW){
+ pmii->fMask |= MIIM_DATA;
+ pmii->dwItemData = (ULONG_PTR) str;
+ }
+ 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;
}
/**********************************************************************
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 *****************************************************************/
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;
}
/*
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;
}
/*
return NtUserCheckMenuItem(hmenu, uIDCheckItem, uCheck);
}
-
/*
* @implemented
*/
/* 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,
return UlongToHandle(Wnd->IDMenu);
}
-
/*
* @implemented
*/
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;
}
/*
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);
}
/*
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.
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);
}
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;
return 0;
}
lstrcpynW( lpString, text, nMaxCount );
- ERR("returning %S\n", lpString);
+ TRACE("W returning %S\n", lpString);
return strlenW(lpString);
}
UINT_PTR uIDNewItem,
LPCSTR lpNewItem)
{
- MENUITEMINFOA mii;
- memset( &mii, 0, sizeof(mii) );
- mii.cbSize = sizeof(MENUITEMINFOA);
- mii.fMask = MIIM_FTYPE;
-
- MenuSetItemData((LPMENUITEMINFOW) &mii,
- uFlags,
- uIDNewItem,
- (LPCWSTR) lpNewItem,
- FALSE);
-
- return InsertMenuItemA(hMenu, uPosition, (BOOL)((MF_BYPOSITION & uFlags) > 0), &mii);
+ 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("Handle bitmaps\n");
+ }
+ res = NtUserThunkedMenuItemInfo(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), TRUE, &mii, &UnicodeString);
+ if ( UnicodeString.Buffer ) RtlFreeUnicodeString ( &UnicodeString );
+ return res;
}
/*
}
else
{
- UnicodeString.Buffer = NULL;
+ TRACE("Handle bitmaps\n");
}
res = NtUserThunkedMenuItemInfo(hMenu, uItem, fByPosition, TRUE, &mii, &UnicodeString);
if ( UnicodeString.Buffer ) RtlFreeUnicodeString ( &UnicodeString );
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);
+
+ MENU_mnu2mnuii( uFlags, uIDNewItem, lpNewItem, &mii, TRUE);
- return InsertMenuItemW(hMenu, uPosition, (BOOL)((MF_BYPOSITION & uFlags) > 0), &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);
+ }
+ res = NtUserThunkedMenuItemInfo(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), TRUE, &mii, &MenuText);
+ return res;
}
/*
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;
-
- MenuSetItemData((LPMENUITEMINFOW) &mii,
- uFlags,
- uIDNewItem,
- (LPCWSTR) lpNewItem,
- FALSE);
-
- //if (mii.hSubMenu && (uFlags & MF_POPUP) && (mii.hSubMenu != (HMENU)uIDNewItem))
- // NtUserDestroyMenu( mii.hSubMenu ); /* ModifyMenu() spec */
-
- return SetMenuItemInfoA( hMnu,
- uPosition,
- (BOOL)(MF_BYPOSITION & uFlags),
- &mii);
+ 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("Handle bitmaps\n");
+ }
+ res = NtUserThunkedMenuItemInfo(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), FALSE, &mii, &UnicodeString);
+ if ( UnicodeString.Buffer ) RtlFreeUnicodeString ( &UnicodeString );
+ return res;
}
/*
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;
-
- /* Init new data for this menu item */
- MenuSetItemData( &mii,
- uFlags,
- uIDNewItem,
- lpNewItem,
- TRUE);
-
- //if (mii.hSubMenu && (uFlags & MF_POPUP) && (mii.hSubMenu != (HMENU)uIDNewItem))
- // NtUserDestroyMenu( mii.hSubMenu ); /* ModifyMenu() spec */
-
- return SetMenuItemInfoW( hMnu,
- uPosition,
- (BOOL)(MF_BYPOSITION & uFlags),
- &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);
+ }
+ else
+ {
+ TRACE("Handle bitmaps\n");
+ }
+ res = NtUserThunkedMenuItemInfo(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), FALSE, &mii, &MenuText);
+ return res;
}
/*
NULL); // LPTPMPARAMS is null
}
-
-
/*
* @unimplemented
*/
return FALSE;
}
return NtUserMessageCall(hWnd, Msg, wParam, lParam, Result, FNID_MENU, TRUE);
-
}
/*
// SVC_(<NAME>, <ARG_COUNT>)
//
-// 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)
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)
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)
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)
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)