diff --git a/base/applications/calc/lang/sk-SK.rc b/base/applications/calc/lang/sk-SK.rc index 2bf46e61535..41f9ca78fe2 100644 --- a/base/applications/calc/lang/sk-SK.rc +++ b/base/applications/calc/lang/sk-SK.rc @@ -1,6 +1,6 @@ /* TRANSLATOR : Mrio Kamr /Mario Kacmar/ aka Kario (kario@szm.sk) * DATE OF TR.: 30-01-2008 - * LAST CHANGE: 31-05-2010 + * LAST CHANGE: 17-09-2010 * --------------------------------------- * TODO: * pridanie naviganch znaiek "&" ? @@ -545,9 +545,9 @@ END STRINGTABLE DISCARDABLE BEGIN IDS_ENERGY_15_C_CALORIES "15 C calories" - IDS_ENERGY_BTUS "British Thermal Units" + IDS_ENERGY_BTUS "Britsk termlne jednotky" IDS_ENERGY_ERGS "Ergs" - IDS_ENERGY_EVS "Electron-Volts" + IDS_ENERGY_EVS "Elektron-Volty" IDS_ENERGY_FOOT_POUNDS "Foot-Pounds" IDS_ENERGY_IT_CALORIES "International Table calories" IDS_ENERGY_IT_KILOCALORIES "International Table kilocalories" @@ -593,7 +593,7 @@ BEGIN IDS_LENGTH_MILLIMETERS "Milimetre" IDS_LENGTH_NAUTICAL_MILES "Nmorn mle" IDS_LENGTH_NIEU "Nieu" - IDS_LENGTH_PARSECS "Parsecy" + IDS_LENGTH_PARSECS "Parseky" IDS_LENGTH_PICAS "Picas" IDS_LENGTH_RI_JAPAN "Ri (Japonsko)" IDS_LENGTH_RI_KOREA "Ri (Krea)" @@ -626,10 +626,10 @@ STRINGTABLE DISCARDABLE BEGIN IDS_PRESSURE_ATMOSPHERES "Atmosfry" IDS_PRESSURE_BARS "Bary" - IDS_PRESSURE_HECTOPASCALS "Hektopascals" - IDS_PRESSURE_KILOPASCALS "Kilopascals" - IDS_PRESSURE_MM_OF_MERCURY "Millimeters of mercury" - IDS_PRESSURE_PASCALS "Pascals" + IDS_PRESSURE_HECTOPASCALS "Hektopascaly" + IDS_PRESSURE_KILOPASCALS "Kilopascaly" + IDS_PRESSURE_MM_OF_MERCURY "Milimetre ortuti" + IDS_PRESSURE_PASCALS "Pascaly" IDS_PRESSURE_PSI "Libry na tvorcov palec" END diff --git a/base/applications/network/ipconfig/ipconfig.c b/base/applications/network/ipconfig/ipconfig.c index 3d9de7d8e19..26576144190 100644 --- a/base/applications/network/ipconfig/ipconfig.c +++ b/base/applications/network/ipconfig/ipconfig.c @@ -25,6 +25,17 @@ HINSTANCE hInstance; HANDLE ProcessHeap; +int LoadStringAndOem(HINSTANCE hInst, + UINT uID, + LPTSTR szNode, + int Siz +) +{ + TCHAR szTmp[25]; + int res = LoadString(hInst, uID, szTmp, sizeof(szTmp)); + CharToOem(szTmp, szNode); + return(res); +} LPTSTR GetNodeTypeName(UINT NodeType) { @@ -33,27 +44,27 @@ LPTSTR GetNodeTypeName(UINT NodeType) switch (NodeType) { case 1: - if (!LoadString(hInstance, IDS_BCAST, szNode, sizeof(szNode))) + if (!LoadStringAndOem(hInstance, IDS_BCAST, szNode, sizeof(szNode))) return NULL; break; case 2: - if (!LoadString(hInstance, IDS_P2P, szNode, sizeof(szNode))) + if (!LoadStringAndOem(hInstance, IDS_P2P, szNode, sizeof(szNode))) return NULL; break; case 4: - if (!LoadString(hInstance, IDS_MIXED, szNode, sizeof(szNode))) + if (!LoadStringAndOem(hInstance, IDS_MIXED, szNode, sizeof(szNode))) return NULL; break; case 8: - if (!LoadString(hInstance, IDS_HYBRID, szNode, sizeof(szNode))) + if (!LoadStringAndOem(hInstance, IDS_HYBRID, szNode, sizeof(szNode))) return NULL; break; default : - if (!LoadString(hInstance, IDS_UNKNOWN, szNode, sizeof(szNode))) + if (!LoadStringAndOem(hInstance, IDS_UNKNOWN, szNode, sizeof(szNode))) return NULL; break; } @@ -69,42 +80,42 @@ LPTSTR GetInterfaceTypeName(UINT InterfaceType) switch (InterfaceType) { case MIB_IF_TYPE_OTHER: - if (!LoadString(hInstance, IDS_OTHER, szIntType, sizeof(szIntType))) + if (!LoadStringAndOem(hInstance, IDS_OTHER, szIntType, sizeof(szIntType))) return NULL; break; case MIB_IF_TYPE_ETHERNET: - if (!LoadString(hInstance, IDS_ETH, szIntType, sizeof(szIntType))) + if (!LoadStringAndOem(hInstance, IDS_ETH, szIntType, sizeof(szIntType))) return NULL; break; case MIB_IF_TYPE_TOKENRING: - if (!LoadString(hInstance, IDS_TOKEN, szIntType, sizeof(szIntType))) + if (!LoadStringAndOem(hInstance, IDS_TOKEN, szIntType, sizeof(szIntType))) return NULL; break; case MIB_IF_TYPE_FDDI: - if (!LoadString(hInstance, IDS_FDDI, szIntType, sizeof(szIntType))) + if (!LoadStringAndOem(hInstance, IDS_FDDI, szIntType, sizeof(szIntType))) return NULL; break; case MIB_IF_TYPE_PPP: - if (!LoadString(hInstance, IDS_PPP, szIntType, sizeof(szIntType))) + if (!LoadStringAndOem(hInstance, IDS_PPP, szIntType, sizeof(szIntType))) return NULL; break; case MIB_IF_TYPE_LOOPBACK: - if (!LoadString(hInstance, IDS_LOOP, szIntType, sizeof(szIntType))) + if (!LoadStringAndOem(hInstance, IDS_LOOP, szIntType, sizeof(szIntType))) return NULL; break; case MIB_IF_TYPE_SLIP: - if (!LoadString(hInstance, IDS_SLIP, szIntType, sizeof(szIntType))) + if (!LoadStringAndOem(hInstance, IDS_SLIP, szIntType, sizeof(szIntType))) return NULL; break; default: - if (!LoadString(hInstance, IDS_UNKNOWN, szIntType, sizeof(szIntType))) + if (!LoadStringAndOem(hInstance, IDS_UNKNOWN, szIntType, sizeof(szIntType))) return NULL; break; } @@ -153,6 +164,7 @@ LPTSTR GetConnectionType(LPTSTR lpClass) { HKEY hKey = NULL; LPTSTR ConType = NULL; + LPTSTR ConTypeTmp = NULL; TCHAR Path[256]; LPTSTR PrePath = _T("SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\"); LPTSTR PostPath = _T("\\Connection"); @@ -180,24 +192,34 @@ LPTSTR GetConnectionType(LPTSTR lpClass) NULL, &dwDataSize) == ERROR_SUCCESS) { + ConTypeTmp = (LPTSTR)HeapAlloc(ProcessHeap, + 0, + dwDataSize); + ConType = (LPTSTR)HeapAlloc(ProcessHeap, 0, dwDataSize); - if (ConType) + if (ConType && ConTypeTmp) { if(RegQueryValueEx(hKey, _T("Name"), NULL, &dwType, - (PBYTE)ConType, + (PBYTE)ConTypeTmp, &dwDataSize) != ERROR_SUCCESS) { HeapFree(ProcessHeap, 0, ConType); + HeapFree(ProcessHeap, + 0, + ConTypeTmp); + ConType = NULL; } + + if (ConType) CharToOem(ConTypeTmp, ConType); } } } @@ -674,7 +696,7 @@ VOID Usage(VOID) if (lpUsage == NULL) return; - if (LoadString(hInstance, + if (LoadStringAndOem(hInstance, IDS_USAGE, lpUsage, Size)) diff --git a/base/applications/network/tracert/tracert.c b/base/applications/network/tracert/tracert.c index 4ec2508fa64..e3c1048f7be 100644 --- a/base/applications/network/tracert/tracert.c +++ b/base/applications/network/tracert/tracert.c @@ -422,7 +422,7 @@ AllocateBuffers(PAPPINFO pInfo) pInfo->RecvPacket = (PIPv4_HEADER)HeapAlloc(GetProcessHeap(), 0, - sizeof(IPv4_HEADER) + PACKET_SIZE); + MAX_PING_PACKET_SIZE); if (!pInfo->RecvPacket) { HeapFree(GetProcessHeap(), diff --git a/base/applications/rapps/CMakeLists.txt b/base/applications/rapps/CMakeLists.txt index 0b87bcf7bea..2efcded110d 100644 --- a/base/applications/rapps/CMakeLists.txt +++ b/base/applications/rapps/CMakeLists.txt @@ -1,3 +1,6 @@ + +set_unicode() + list(APPEND SOURCE aboutdlg.c available.c @@ -61,4 +64,4 @@ ENDMACRO (MACRO_ADD_MESSAGE_HEADERS) MACRO_ADD_MESSAGE_HEADERS(rappsmsg.mc) -add_cab_target(rapps 1) \ No newline at end of file +add_cab_target(rapps 1) diff --git a/base/applications/rapps/rapps/7zip.txt b/base/applications/rapps/rapps/7zip.txt index 93cdb8ad47e..fb070f717d4 100644 --- a/base/applications/rapps/rapps/7zip.txt +++ b/base/applications/rapps/rapps/7zip.txt @@ -17,5 +17,8 @@ Description = Tool zum Erstellen und Öffnen von 7zip, zip, tar, rar und andrern [Section.040a] Description = Utilidad para crear y abrir 7zip, zip, tar, rar y otros archivos comprimidos. +[Section.0415] +Description = Narzędzie do tworzenia i otwierania plików typu 7zip, zip, tar, i innych plików archiwizacyjnych. + [Section.0422] Description = Утиліта для створення та відкриття 7zip, zip, tar, rar та інших архівних файлів. diff --git a/base/applications/rapps/rapps/abyss.txt b/base/applications/rapps/rapps/abyss.txt index 49d505cf414..8959327b617 100644 --- a/base/applications/rapps/rapps/abyss.txt +++ b/base/applications/rapps/rapps/abyss.txt @@ -14,5 +14,10 @@ CDPath = none [Section.0407] Description = Abyss Web Server ermöglicht es Webseiten auf Ihrem Computer zu hosten. Er unterstützt sichere SSL/TLS Verbindungen (HTTPS) sowie eine Vielfalt an Web Technologien. Er kann ebenfalls PHP, Perl, Python, ASP, ASP.NET, und Ruby on Rails Web Anwendungen ausführen, welche von Datenbanken, wie MySQL, SQLite, MS SQL Server, MS Access, oder Oracle unterstützt werden können. +[Section.0415] +Description = Abyss Web Server pozwala Ci na stworzenie serwera WWW na własnym komputerze. Ten program obsługuje zabezpieczone połączenia typu SSL/TLS (HTTPS) i wiele technologii Sieci. +Może także uruchamiać zaawansowane aplikacje internetowe takie jak PHP, Perl, Python, ASP, ASP.NET, i Ruby on Rails. +Mogą one zostać oparte o MySQL, SQLite, MS SQL Server, MS Access, lub Oracle. + [Section.0422] Description = Abyss Web Server дозволить вам утримувати веб-сайти на вашому комп'ютері. Від підтримує безпечні SSL/TLS з'єднання (HTTPS) та великий ряд веб-технологій. Він також запускає PHP, Perl, Python, ASP, ASP.NET, та Ruby on Rails веб-додатки, які можуть підтримуватись такими базами даних, як MySQL, SQLite, MS SQL Server, MS Access, чи Oracle. diff --git a/base/applications/rapps/rapps/comctl32ocx.txt b/base/applications/rapps/rapps/comctl32ocx.txt index a678a338180..392e8faf26c 100644 --- a/base/applications/rapps/rapps/comctl32ocx.txt +++ b/base/applications/rapps/rapps/comctl32ocx.txt @@ -21,7 +21,7 @@ Description = X es necesario para varias aplicaciones. [Section.0415] Licence = Nieznana -Description = X jest używana przez część aplikacji. +Description = Microsoft Visual Basic 6.0 Common Controls jest używany przez część aplikacji. [Section.0422] Licence = Невідома diff --git a/base/applications/rapps/rapps/dosblaster.txt b/base/applications/rapps/rapps/dosblaster.txt index 3974dda66aa..a499b7a956c 100644 --- a/base/applications/rapps/rapps/dosblaster.txt +++ b/base/applications/rapps/rapps/dosblaster.txt @@ -17,5 +17,8 @@ Description = DosBlaster ist eine Shell Extension, die es ermöglicht jede DOS A [Section.040a] Description = DosBlaster en una extensión Shell que permite abrir cualquier ejecutable DOS en DOSBox desde el botón derecho del ratón. Esta versión contiene DOSBox 0.70, pero puede ser actualizado facilmente instalando una nueva versión de DOSBox en la carpeta de DosBlaster. +[Section.0415] +Description = DosBlaster to rozszerzenie powłoki, które umożliwia otwarcie każdego DOS-owego pliku wykonywalnego w DOSBox za pomocą prawego klawisza myszki. Ta wersja zawiera DosBox 0.70, ale można go łatwo zaktualizować, instalując nowszą wersje DOSBox do folderów DosBlaster. + [Section.0422] Description = DosBlaster це розширення оболонки, яке дозволяє запустити будь-який виконавчий файл DOS в DOSBox через правий клік. Ця версія містить DOSBox 0.70, але може бути оновлена встановленням новішої версії DOSBox в теки DosBlaster. diff --git a/base/applications/rapps/rapps/fap.txt b/base/applications/rapps/rapps/fap.txt index 6bbac0edc57..56a42cb23f8 100644 --- a/base/applications/rapps/rapps/fap.txt +++ b/base/applications/rapps/rapps/fap.txt @@ -14,5 +14,8 @@ CDPath = none [Section.0407] Description = Kleiner und einfacher Mediaplayer. +[Section.0415] +Description = Prosty i lekki odtwarzacz audio. + [Section.0422] Description = Простий та маленький програвач аудіо файлів. diff --git a/base/applications/rapps/rapps/firefox36.txt b/base/applications/rapps/rapps/firefox36.txt index 92b7a75b809..31b72a5514f 100644 --- a/base/applications/rapps/rapps/firefox36.txt +++ b/base/applications/rapps/rapps/firefox36.txt @@ -2,47 +2,47 @@ [Section] Name = Mozilla Firefox 3.6 -Version = 3.6.11 +Version = 3.6.12 Licence = MPL/GPL/LGPL Description = The most popular and one of the best free Web Browsers out there. Size = 8.1M Category = 5 URLSite = http://www.mozilla.com/en-US/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.11/win32/en-US/Firefox%20Setup%203.6.11.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.12/win32/en-US/Firefox%20Setup%203.6.12.exe CDPath = none [Section.0407] Description = Der populärste und einer der besten freien Webbrowser. Size = 8.0M URLSite = http://www.mozilla-europe.org/de/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.11/win32/de/Firefox%20Setup%203.6.11.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.12/win32/de/Firefox%20Setup%203.6.12.exe [Section.040a] Description = El más popular y uno de los mejores navegadores web gratuitos que hay. Size = 8.0M URLSite = http://www.mozilla-europe.org/es/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.11/win32/es-ES/Firefox%20Setup%203.6.11.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.12/win32/es-ES/Firefox%20Setup%203.6.12.exe [Section.0414] Description = Mest populære og best også gratis nettleserene der ute. Size = 8.0M URLSite = http://www.mozilla-europe.org/no/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.11/win32/nb-NO/Firefox%20Setup%203.6.11.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.12/win32/nb-NO/Firefox%20Setup%203.6.12.exe [Section.0415] Description = Najpopularniejsza i jedna z najlepszych darmowych przeglądarek internetowych. Size = 8.8M URLSite = http://www.mozilla-europe.org/pl/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.11/win32/pl/Firefox%20Setup%203.6.11.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.12/win32/pl/Firefox%20Setup%203.6.12.exe [Section.0419] Description = Один из самых популярных и лучших бесплатных браузеров. Size = 8.4M URLSite = http://www.mozilla-europe.org/ru/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.11/win32/ru/Firefox%20Setup%203.6.11.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.12/win32/ru/Firefox%20Setup%203.6.12.exe [Section.0422] Description = Найпопулярніший та один з кращих безплатних веб-браузерів. Size = 8.4M URLSite = http://www.mozilla-europe.org/uk/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.11/win32/uk/Firefox%20Setup%203.6.11.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.12/win32/uk/Firefox%20Setup%203.6.12.exe diff --git a/base/applications/rapps/rapps/go-oo.txt b/base/applications/rapps/rapps/go-oo.txt index e32599ed605..39dbe608ad5 100644 --- a/base/applications/rapps/rapps/go-oo.txt +++ b/base/applications/rapps/rapps/go-oo.txt @@ -18,7 +18,7 @@ Description = Open Source Office Suite, basierend auf Open Office, aber viel bes Description = La suite de ofimática de código abierto. [Section.0415] -Description = Otwarty pakiet biurowy. +Description = Otwarty pakiet biurowy, bazujący na Open Office, ale znacznie lepszy. [Section.0422] Description = Відкритий офісний пакет. diff --git a/base/applications/rapps/rapps/kdewin.txt b/base/applications/rapps/rapps/kdewin.txt index f0bd4ecd08c..4c47525940a 100644 --- a/base/applications/rapps/rapps/kdewin.txt +++ b/base/applications/rapps/rapps/kdewin.txt @@ -14,5 +14,8 @@ CDPath = none [Section.0407] Description = KDE für Windows. +[Section.0415] +Description = KDE dla Windows. + [Section.0422] Description = KDE для Windows. diff --git a/base/applications/rapps/rapps/mirandaim.txt b/base/applications/rapps/rapps/mirandaim.txt index 8cc6b8ee29e..00737374627 100644 --- a/base/applications/rapps/rapps/mirandaim.txt +++ b/base/applications/rapps/rapps/mirandaim.txt @@ -2,13 +2,13 @@ [Section] Name = Miranda IM -Version = 0.9.8 +Version = 0.9.10 Licence = GPL Description = Open source multiprotocol instant messaging application - May not work completely. Size = 3.0MB Category = 5 URLSite = http://www.miranda-im.org/ -URLDownload = http://miranda.googlecode.com/files/miranda-im-v0.9.8-unicode.exe +URLDownload = http://miranda.googlecode.com/files/miranda-im-v0.9.10-unicode.exe CDPath = none [Section.0407] diff --git a/base/applications/rapps/rapps/mirc.txt b/base/applications/rapps/rapps/mirc.txt index 83a74f3b307..1f7220a9947 100644 --- a/base/applications/rapps/rapps/mirc.txt +++ b/base/applications/rapps/rapps/mirc.txt @@ -2,13 +2,13 @@ [Section] Name = mIRC -Version = 7.14 +Version = 7.15 Licence = Shareware Description = The most popular client for the Internet Relay Chat (IRC). Size = 2.0M Category = 5 URLSite = http://www.mirc.com/ -URLDownload = http://download.mirc.com/mirc714.exe +URLDownload = http://download.mirc.com/mirc715.exe CDPath = none [Section.0407] diff --git a/base/applications/rapps/rapps/mono2.txt b/base/applications/rapps/rapps/mono2.txt index 6de2539031c..c766941d5f9 100644 --- a/base/applications/rapps/rapps/mono2.txt +++ b/base/applications/rapps/rapps/mono2.txt @@ -2,14 +2,17 @@ [Section] Name = Mono .net Development Framework -Version = 2.6.7 +Version = 2.8 Licence = Unknown Description = Open Source .net Framework. -Size = 72MB +Size = 78MB Category = 14 URLSite = http://www.mono-project.com/Main_Page -URLDownload = http://ftp.novell.com/pub/mono/archive/2.6.7/windows-installer/2/mono-2.6.7-gtksharp-2.12.10-win32-2.exe +URLDownload = http://ftp.novell.com/pub/mono/archive/2.8/windows-installer/9/mono-2.8-gtksharp-2.12.10-win32-9.exe CDPath = none +[Section.0415] +Description = Pakiet Mono .net Framework dla Programistów. + [Section.0422] Description = Відкритий .net Фреймворк. diff --git a/base/applications/rapps/rapps/mpc.txt b/base/applications/rapps/rapps/mpc.txt index cf59628dcc3..d89fb38bb6a 100644 --- a/base/applications/rapps/rapps/mpc.txt +++ b/base/applications/rapps/rapps/mpc.txt @@ -20,5 +20,8 @@ Description = Reproductor multimedia. [Section.0419] Description = Мультимедийный проигрыватель. +[Section.0415] +Description = Odtwarzacz multimediów. + [Section.0422] Description = Мультимедійний програвач. diff --git a/base/applications/rapps/rapps/net11.txt b/base/applications/rapps/rapps/net11.txt index f6d4ca63f27..15966d9b229 100644 --- a/base/applications/rapps/rapps/net11.txt +++ b/base/applications/rapps/rapps/net11.txt @@ -10,3 +10,6 @@ Category = 14 URLSite = http://www.microsoft.com/downloads/details.aspx?FamilyId=262D25E3-F589-4842-8157-034D1E7CF3A3 URLDownload = http://download.microsoft.com/download/a/a/c/aac39226-8825-44ce-90e3-bf8203e74006/dotnetfx.exe CDPath = none + +[Section.0415] +Description = Microsoft .NET Framework Wersja 1.1 - Pakiet Dystrybucyjny. diff --git a/base/applications/rapps/rapps/net20.txt b/base/applications/rapps/rapps/net20.txt index cb83683985c..a29ed102861 100644 --- a/base/applications/rapps/rapps/net20.txt +++ b/base/applications/rapps/rapps/net20.txt @@ -10,3 +10,6 @@ Category = 14 URLSite = http://www.microsoft.com/downloads/details.aspx?FamilyID=0856eacb-4362-4b0d-8edd-aab15c5e04f5 URLDownload = http://download.microsoft.com/download/5/6/7/567758a3-759e-473e-bf8f-52154438565a/dotnetfx.exe CDPath = none + +[Section.0415] +Description = Microsoft .NET Framework Wersja 2.0 - Pakiet Dystrybucyjny. diff --git a/base/applications/rapps/rapps/net20sp2.txt b/base/applications/rapps/rapps/net20sp2.txt index 65c98858d43..1901bfe937e 100644 --- a/base/applications/rapps/rapps/net20sp2.txt +++ b/base/applications/rapps/rapps/net20sp2.txt @@ -10,3 +10,6 @@ Category = 14 URLSite = http://www.microsoft.com/downloads/details.aspx?familyid=5B2C0358-915B-4EB5-9B1D-10E506DA9D0F URLDownload = http://download.microsoft.com/download/c/6/e/c6e88215-0178-4c6c-b5f3-158ff77b1f38/NetFx20SP2_x86.exe CDPath = none + +[Section.0415] +Description = Microsoft .NET Framework Wersja 2.0 Service Pack 2. \ No newline at end of file diff --git a/base/applications/rapps/rapps/python.txt b/base/applications/rapps/rapps/python.txt index 4664d47b104..4c77199eb62 100644 --- a/base/applications/rapps/rapps/python.txt +++ b/base/applications/rapps/rapps/python.txt @@ -14,5 +14,9 @@ CDPath = none [Section.0407] Description = Eine sehr mächtige, dynamische Programmiersprache. + +[Section.0415] +Description = Potęży i dynamiczny język programowania. + [Section.0422] Description = Дуже потужна динамічна мова програмування. diff --git a/base/applications/rapps/rapps/remood.txt b/base/applications/rapps/rapps/remood.txt index 7ee5f97ee55..dd58417f4fa 100644 --- a/base/applications/rapps/rapps/remood.txt +++ b/base/applications/rapps/rapps/remood.txt @@ -14,5 +14,8 @@ CDPath = none [Section.0407] Description = ReMooD ist ein Port des Doom Legacy Sources. Es versucht das klassische Legacy Erfahrung zusammen mit neuen Features und mehr Stabilitt zu bieten. Untersttzt werden Windows 98/98SE/ME/NT/2000/XP/2003/ Vista/2008/7/XP 64-bit/2003 64-bit/Vista 64-bit/2008 64-bit/7 64-bit; ReactOS 0.3.x und hher; und Linux (x86 und x86_64). +[Section.0415] +Description = rdowy port Doom. Jego celem jest zapewnienie rozrywki znanej z klasycznej wersji z nowymi funkcjami, i lepsz stabilnoci. Obsuguje Windows 98/98SE/ME/NT/2000/XP/2003/ Vista/2008/7/XP 64-bit/2003 64-bit/Vista 64-bit/2008 64-bit/7 64-bit; ReactOS 0.3.x i wysze; i Linux (x86 i x86_64). + [Section.0422] Description = ReMooD э Портом вихідних кодів Doom Legacy. Його метою є додати нові можливості та стабільність до досвіду класичного Legacy. Він підтримує Windows 98/98SE/ME/NT/2000/XP/2003/ Vista/2008/7/XP 64-bit/2003 64-bit/Vista 64-bit/2008 64-bit/7 64-bit; ReactOS 0.3.x та новіші; а також Linux (x86 та x86_64). diff --git a/base/applications/rapps/rapps/scite.txt b/base/applications/rapps/rapps/scite.txt index 6fe68efa4d6..bdb56884200 100644 --- a/base/applications/rapps/rapps/scite.txt +++ b/base/applications/rapps/rapps/scite.txt @@ -2,13 +2,13 @@ [Section] Name = SciTE -Version = 2.21 +Version = 2.22 Licence = Freeware Description = SciTE is a SCIntilla based Text Editor. Originally built to demonstrate Scintilla, it has grown to be a generally useful editor with facilities for building and running programs. Size = 0.6M Category = 7 URLSite = http://www.scintilla.org/ -URLDownload = http://kent.dl.sourceforge.net/project/scintilla/SciTE/2.21/Sc221.exe +URLDownload = http://kent.dl.sourceforge.net/project/scintilla/SciTE/2.22/Sc222.exe CDPath = none [Section.0407] @@ -17,5 +17,8 @@ Description = SciTE ist ein SCIntilla basierter Text Editor. Ursprünglich wurde [Section.040a] Description = Editor de texto basado en SCIntilla. Originalmente creado para demostrar Scintilla, a crecido para ser un gran editor con capacidad para crear y ejecutar programas. +[Section.0415] +Description = SciTE to edytor tekstu bazowany na SCIntilla. Oryginalnie stworzony aby pokazać Scintille, stał sie ogólnie przydatnym edytorem z infrastrukturą potrzebną do tworzenia i uruchamiania programów. + [Section.0422] Description = Текстовий редактор на основі SCIntilla. Був зібраний як презентація Scintilla, але виріс до редактора загального користування з засобами збирання та запуску програм. diff --git a/base/applications/rapps/rapps/seamonkey.txt b/base/applications/rapps/rapps/seamonkey.txt index 4544d24d0ac..ae5b9134110 100644 --- a/base/applications/rapps/rapps/seamonkey.txt +++ b/base/applications/rapps/rapps/seamonkey.txt @@ -2,31 +2,31 @@ [Section] Name = Mozilla SeaMonkey -Version = 2.0.9 +Version = 2.0.10 Licence = MPL/GPL/LGPL Description = Mozilla Suite is alive. This is the one and only Browser, Mail, Chat, and Composer bundle you will ever need. Size = 10.1MB Category = 5 URLSite = http://www.seamonkey-project.org/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.9/win32/en-US/SeaMonkey%20Setup%202.0.9.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.10/win32/en-US/SeaMonkey%20Setup%202.0.10.exe CDPath = none [Section.0407] Description = Mozilla Suite lebt. Dies ist das einzige Browser-, Mail-, Chat- and Composerwerkzeug-Bundle welches Sie benötigen. Size = 10.0MB -URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.9/win32/de/SeaMonkey%20Setup%202.0.9.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.10/win32/de/SeaMonkey%20Setup%202.0.10.exe [Section.040a] Description = La suite de Mozilla está viva. Es el primero y único navegador web, gestor de correo, lector de noticias, Chat y editor HTML que necesitarás. Size = 10.0MB -URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.9/win32/es-ES/SeaMonkey%20Setup%202.0.9.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.10/win32/es-ES/SeaMonkey%20Setup%202.0.10.exe [Section.0415] Description = Pakiet Mozilla żyje. W zestawie: przeglądarka, klient poczty, IRC oraz Edytor HTML - wszystko, czego potrzebujesz. Size = 10.8MB -URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.9/win32/pl/SeaMonkey%20Setup%202.0.9.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.10/win32/pl/SeaMonkey%20Setup%202.0.10.exe [Section.0419] Description = Продолжение Mozilla Suite. Включает браузер, почтовый клиент, IRC-клиент и HTML-редактор. Size = 10.4MB -URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.9/win32/ru/SeaMonkey%20Setup%202.0.9.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.10/win32/ru/SeaMonkey%20Setup%202.0.10.exe diff --git a/base/applications/rapps/rapps/steam.txt b/base/applications/rapps/rapps/steam.txt index 3caccc4e584..9d4a0af1012 100644 --- a/base/applications/rapps/rapps/steam.txt +++ b/base/applications/rapps/rapps/steam.txt @@ -14,5 +14,8 @@ CDPath = none [Section.0407] Description = Die STEAM Spieleplattform, die von viele Spielen verwendet wird. +[Section.0415] +Description = STEAM - platforma, którą używa obecnie wiele gier. + [Section.0422] Description = Ігрова платформа, що використовується багатьма іграми. diff --git a/base/applications/rapps/rapps/superfinder.txt b/base/applications/rapps/rapps/superfinder.txt index 02b55605cc3..9098b11e8db 100644 --- a/base/applications/rapps/rapps/superfinder.txt +++ b/base/applications/rapps/rapps/superfinder.txt @@ -13,3 +13,6 @@ CDPath = none [Section.0407] Description = Eine schnelle und effektive Suchanwendung. + +[Section.0415] +Description = Szybka i bogata w opcje aplikacja szukająca. diff --git a/base/applications/rapps/rapps/tahoma.txt b/base/applications/rapps/rapps/tahoma.txt index b5c87a0d3fe..c5e57fdf4b4 100644 --- a/base/applications/rapps/rapps/tahoma.txt +++ b/base/applications/rapps/rapps/tahoma.txt @@ -15,6 +15,9 @@ CDPath = none Licence = Unbekannt Description = Tahoma Font pack, der von einigen Anwendungen benötigt wird (Steam). +[Section.0415] +Description = Pakiet Czcionki Tahoma wymagany przez niektóre programy (np. Steam). + [Section.0422] Licence = Невідома Description = Пакет шрифтів Tahoma, що необхідні деяким програмам (Steam). diff --git a/base/applications/rapps/rapps/thunderbird.txt b/base/applications/rapps/rapps/thunderbird.txt index 0d3fa6e3d3d..2e120b09a7c 100644 --- a/base/applications/rapps/rapps/thunderbird.txt +++ b/base/applications/rapps/rapps/thunderbird.txt @@ -2,41 +2,41 @@ [Section] Name = Mozilla Thunderbird -Version = 3.1.5 +Version = 3.1.6 Licence = MPL/GPL/LGPL Description = The most popular and one of the best free Mail Clients out there. Size = 9.0M Category = 5 URLSite = http://www.mozilla-europe.org/en/products/thunderbird/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.5/win32/en-US/Thunderbird%20Setup%203.1.5.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.6/win32/en-US/Thunderbird%20Setup%203.1.6.exe CDPath = none [Section.0407] Description = Der populärste und einer der besten freien Mail-Clients. Size = 8.8M URLSite = http://www.mozilla-europe.org/de/products/thunderbird/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.5/win32/de/Thunderbird%20Setup%203.1.5.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.6/win32/de/Thunderbird%20Setup%203.1.6.exe [Section.040a] Description = El más popular y uno de los mejores clientes mail que hay. Size = 8.8M URLSite = http://www.mozilla-europe.org/es/products/thunderbird/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.5/win32/es-ES/Thunderbird%20Setup%203.1.5.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.6/win32/es-ES/Thunderbird%20Setup%203.1.6.exe [Section.0415] Description = Najpopularniejszy i jeden z najlepszych darmowych klientów poczty. Size = 9.7M URLSite = http://www.mozilla-europe.org/pl/products/thunderbird/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.5/win32/pl/Thunderbird%20Setup%203.1.5.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.6/win32/pl/Thunderbird%20Setup%203.1.6.exe [Section.0419] Description = Один из самых популярных и лучших бесплатных почтовых клиентов. Size = 9.2M URLSite = http://www.mozilla-europe.org/ru/products/thunderbird/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.5/win32/ru/Thunderbird%20Setup%203.1.5.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.6/win32/ru/Thunderbird%20Setup%203.1.6.exe [Section.0422] Description = Найпопулярніший та один з кращих поштових клієнтів. Size = 9.2M URLSite = http://www.mozillamessaging.com/uk/thunderbird/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.5/win32/uk/Thunderbird%20Setup%203.1.5.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.6/win32/uk/Thunderbird%20Setup%203.1.6.exe diff --git a/base/applications/rapps/rapps/ultravnc.txt b/base/applications/rapps/rapps/ultravnc.txt index f00b1434902..89ab6740655 100644 --- a/base/applications/rapps/rapps/ultravnc.txt +++ b/base/applications/rapps/rapps/ultravnc.txt @@ -2,17 +2,20 @@ [Section] Name = UltraVNC -Version = 1.0.8.2 +Version = 1.0.9.1 Licence = GPL Description = Open-source VNC client/server. -Size = 1.9MB +Size = 2.0MB Category = 5 URLSite = http://www.uvnc.com/ -URLDownload = http://support1.uvnc.com/download/1082/UltraVNC_1.0.8.2_Setup.exe +URLDownload = http://support1.uvnc.com/download/109/UltraVNC_1.0.9.1_Setup.exe CDPath = none [Section.040a] Description = Cliente/Servidor VNC de código abierto. +[Section.0415] +Description = Otwarty klient/serwer VNC. + [Section.0422] Description = Відкритий VNC клієнт/сервер. diff --git a/base/applications/rapps/rapps/utorrent.txt b/base/applications/rapps/rapps/utorrent.txt index cb05f9bd3e0..86fa5ae6884 100644 --- a/base/applications/rapps/rapps/utorrent.txt +++ b/base/applications/rapps/rapps/utorrent.txt @@ -2,13 +2,13 @@ [Section] Name = µTorrent -Version = 2.0.4 +Version = 2.2 Licence = Freeware for non-commercial uses Description = Small and fast BitTorrent Client. -Size = 320K +Size = 385K Category = 5 URLSite = http://www.utorrent.com/ -URLDownload = http://download.utorrent.com/2.0.4/utorrent.exe +URLDownload = http://download.utorrent.com/2.2/utorrent.exe CDPath = none diff --git a/base/applications/rapps/rapps/vlc.txt b/base/applications/rapps/rapps/vlc.txt index 8a362fa2428..76c8c74fe8b 100644 --- a/base/applications/rapps/rapps/vlc.txt +++ b/base/applications/rapps/rapps/vlc.txt @@ -2,13 +2,13 @@ [Section] Name = VLC media player -Version = 1.1.4 +Version = 1.1.5 Licence = GPL Description = A media player. -Size = 18.7MB +Size = 19.1MB Category = 1 URLSite = http://www.videolan.org/vlc/ -URLDownload = http://ignum.dl.sourceforge.net/project/vlc/1.1.4/win32/vlc-1.1.4-win32.exe +URLDownload = http://ignum.dl.sourceforge.net/project/vlc/1.1.5/win32/vlc-1.1.5-win32.exe CDPath = none [Section.0407] @@ -20,5 +20,8 @@ Description = Reproductor multimedia. [Section.0419] Description = Мультимедийный проигрыватель. +[Section.0415] +Description = Odtwarzacz multimediów. + [Section.0422] Description = Мультимедійний програвач. diff --git a/base/applications/regedit/CMakeLists.txt b/base/applications/regedit/CMakeLists.txt index a79251c2d70..40adac9b9ea 100644 --- a/base/applications/regedit/CMakeLists.txt +++ b/base/applications/regedit/CMakeLists.txt @@ -8,6 +8,7 @@ list(APPEND SOURCE about.c childwnd.c edit.c + error.c find.c framewnd.c hexedit.c @@ -31,4 +32,4 @@ add_importlibs(regedit user32 gdi32 advapi32 ole32 shell32 comctl32 comdlg32 shl #add_subdirectory(clb) -add_cab_target(regedit 4) \ No newline at end of file +add_cab_target(regedit 4) diff --git a/base/applications/regedit/childwnd.c b/base/applications/regedit/childwnd.c index 6675e21d4ec..56ab005334e 100644 --- a/base/applications/regedit/childwnd.c +++ b/base/applications/regedit/childwnd.c @@ -67,19 +67,21 @@ static void draw_splitbar(HWND hWnd, int x) static void ResizeWnd(ChildWnd* pChildWnd, int cx, int cy) { - HDWP hdwp = BeginDeferWindowPos(2); - RECT rt, rs; - + HDWP hdwp = BeginDeferWindowPos(3); + RECT rt, rs, rb; + const int tHeight = 18; SetRect(&rt, 0, 0, cx, cy); cy = 0; if (hStatusBar != NULL) { GetWindowRect(hStatusBar, &rs); - cy = rs.bottom - rs.top + 8; + cy = rs.bottom - rs.top; } + GetWindowRect(pChildWnd->hAddressBtnWnd, &rb); cx = pChildWnd->nSplitPos + SPLIT_WIDTH/2; - DeferWindowPos(hdwp, pChildWnd->hAddressBarWnd, 0, rt.left, rt.top, rt.right-rt.left, 23, SWP_NOZORDER|SWP_NOACTIVATE); - DeferWindowPos(hdwp, pChildWnd->hTreeWnd, 0, rt.left, rt.top + 25, pChildWnd->nSplitPos-SPLIT_WIDTH/2-rt.left, rt.bottom-rt.top-cy, SWP_NOZORDER|SWP_NOACTIVATE); - DeferWindowPos(hdwp, pChildWnd->hListWnd, 0, rt.left+cx , rt.top + 25, rt.right-cx, rt.bottom-rt.top-cy, SWP_NOZORDER|SWP_NOACTIVATE); + DeferWindowPos(hdwp, pChildWnd->hAddressBarWnd, 0, rt.left, rt.top, rt.right-rt.left - tHeight-2, tHeight, SWP_NOZORDER|SWP_NOACTIVATE); + DeferWindowPos(hdwp, pChildWnd->hAddressBtnWnd, 0, rt.right - tHeight, rt.top, tHeight, tHeight, SWP_NOZORDER|SWP_NOACTIVATE); + DeferWindowPos(hdwp, pChildWnd->hTreeWnd, 0, rt.left, rt.top + tHeight+2, pChildWnd->nSplitPos-SPLIT_WIDTH/2-rt.left, rt.bottom-rt.top-cy, SWP_NOZORDER|SWP_NOACTIVATE); + DeferWindowPos(hdwp, pChildWnd->hListWnd, 0, rt.left+cx, rt.top + tHeight+2, rt.right-cx, rt.bottom-rt.top-cy, SWP_NOZORDER|SWP_NOACTIVATE); EndDeferWindowPos(hdwp); } @@ -259,7 +261,7 @@ static void SuggestKeys(HKEY hRootKey, LPCTSTR pszKeyPath, LPTSTR pszSuggestions /* Check CLSID key */ if (RegOpenKey(hRootKey, pszKeyPath, &hSubKey) == ERROR_SUCCESS) { - if (QueryStringValue(hSubKey, TEXT("CLSID"), NULL, szBuffer, + if (QueryStringValue(hSubKey, TEXT("CLSID"), NULL, szBuffer, COUNT_OF(szBuffer)) == ERROR_SUCCESS) { lstrcpyn(pszSuggestions, TEXT("HKCR\\CLSID\\"), (int) iSuggestionsLength); @@ -324,29 +326,35 @@ LRESULT CALLBACK ChildWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPa /* load "My Computer" string */ LoadString(hInst, IDS_MY_COMPUTER, buffer, sizeof(buffer)/sizeof(TCHAR)); - g_pChildWnd = pChildWnd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ChildWnd)); + g_pChildWnd = pChildWnd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ChildWnd)); if (!pChildWnd) return 0; _tcsncpy(pChildWnd->szPath, buffer, MAX_PATH); pChildWnd->nSplitPos = 250; pChildWnd->hWnd = hWnd; - pChildWnd->hAddressBarWnd = CreateWindowEx(WS_EX_CLIENTEDGE, _T("Edit"), NULL, WS_CHILD | WS_VISIBLE | WS_CHILDWINDOW | WS_TABSTOP, + pChildWnd->hAddressBarWnd = CreateWindowEx(WS_EX_CLIENTEDGE, _T("Edit"), NULL, WS_CHILD | WS_VISIBLE | WS_CHILDWINDOW | WS_TABSTOP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hWnd, (HMENU)0, hInst, 0); + pChildWnd->hAddressBtnWnd = CreateWindowEx(WS_EX_CLIENTEDGE, _T("Button"), _T("»"), WS_CHILD | WS_VISIBLE | WS_CHILDWINDOW | WS_TABSTOP | BS_DEFPUSHBUTTON, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + hWnd, (HMENU)0, hInst, 0); pChildWnd->hTreeWnd = CreateTreeView(hWnd, pChildWnd->szPath, (HMENU) TREE_WINDOW); pChildWnd->hListWnd = CreateListView(hWnd, (HMENU) LIST_WINDOW/*, pChildWnd->szPath*/); SetFocus(pChildWnd->hTreeWnd); - /* set the address bar font */ - if (pChildWnd->hAddressBarWnd) + /* set the address bar and button font */ + if ((pChildWnd->hAddressBarWnd) && (pChildWnd->hAddressBtnWnd)) { hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); SendMessage(pChildWnd->hAddressBarWnd, WM_SETFONT, (WPARAM)hFont, 0); + SendMessage(pChildWnd->hAddressBtnWnd, + WM_SETFONT, + (WPARAM)hFont, + 0); } - /* Subclass the AddressBar */ oldproc = (WNDPROC)(LONG_PTR)GetWindowLongPtr(pChildWnd->hAddressBarWnd, GWL_WNDPROC); SetWindowLongPtr(pChildWnd->hAddressBarWnd, GWL_USERDATA, (DWORD_PTR)oldproc); @@ -354,7 +362,10 @@ LRESULT CALLBACK ChildWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPa break; } case WM_COMMAND: - if (!_CmdWndProc(hWnd, message, wParam, lParam)) { + if(HIWORD(wParam) == BN_CLICKED){ + PostMessage(pChildWnd->hAddressBarWnd, WM_KEYUP, VK_RETURN, 0); + } + else if (!_CmdWndProc(hWnd, message, wParam, lParam)) { goto def; } break; @@ -477,10 +488,28 @@ LRESULT CALLBACK ChildWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPa rootName = get_root_key_name(hRootKey); fullPath = HeapAlloc(GetProcessHeap(), 0, (_tcslen(rootName) + 1 + _tcslen(keyPath) + 1) * sizeof(TCHAR)); if (fullPath) { - _stprintf(fullPath, _T("%s\\%s"), rootName, keyPath); + /* set (correct) the address bar text */ + if(keyPath[0] != '\0') + _stprintf(fullPath, _T("%s\\%s"), rootName, keyPath); + else + fullPath = _tcscpy(fullPath, rootName); SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)fullPath); SendMessage(pChildWnd->hAddressBarWnd, WM_SETTEXT, 0, (LPARAM)fullPath); - HeapFree(GetProcessHeap(), 0, fullPath); + HeapFree(GetProcessHeap(), 0, fullPath); + /* disable hive manipulation items temporarily (enable only if necessary) */ + EnableMenuItem(GetSubMenu(hMenuFrame,0), ID_REGISTRY_LOADHIVE, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(GetSubMenu(hMenuFrame,0), ID_REGISTRY_UNLOADHIVE, MF_BYCOMMAND | MF_GRAYED); + /* compare the strings to see if we should enable/disable the "Load Hive" menus accordingly */ + if (!(_tcsicmp(rootName, TEXT("HKEY_LOCAL_MACHINE")) && + _tcsicmp(rootName, TEXT("HKEY_USERS")))) + { + // enable the unload menu item if at the root + // otherwise enable the load menu item if there is no slash in keyPath (ie. immediate child selected) + if(keyPath[0] == '\0') + EnableMenuItem(GetSubMenu(hMenuFrame,0), ID_REGISTRY_LOADHIVE, MF_BYCOMMAND | MF_ENABLED); + else if(!_tcschr(keyPath, _T('\\'))) + EnableMenuItem(GetSubMenu(hMenuFrame,0), ID_REGISTRY_UNLOADHIVE, MF_BYCOMMAND | MF_ENABLED); + } { HKEY hKey; diff --git a/base/applications/regedit/edit.c b/base/applications/regedit/edit.c index 9812b9bf625..85a5bd853e8 100644 --- a/base/applications/regedit/edit.c +++ b/base/applications/regedit/edit.c @@ -59,19 +59,10 @@ void error(HWND hwnd, INT resId, ...) static void error_code_messagebox(HWND hwnd, DWORD error_code) { - LPTSTR lpMsgBuf; - DWORD status; TCHAR title[256]; - static const TCHAR fallback[] = TEXT("Error displaying error message.\n"); if (!LoadString(hInst, IDS_ERROR, title, COUNT_OF(title))) lstrcpy(title, TEXT("Error")); - status = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, error_code, 0, (LPTSTR)&lpMsgBuf, 0, NULL); - if (!status) - lpMsgBuf = (LPTSTR)fallback; - MessageBox(hwnd, lpMsgBuf, title, MB_OK | MB_ICONERROR); - if (lpMsgBuf != fallback) - LocalFree(lpMsgBuf); + ErrorMessageBox(hwnd, title, error_code); } void warning(HWND hwnd, INT resId, ...) diff --git a/base/applications/regedit/error.c b/base/applications/regedit/error.c new file mode 100644 index 00000000000..aaadf1af600 --- /dev/null +++ b/base/applications/regedit/error.c @@ -0,0 +1,14 @@ +#include +void ErrorMessageBox(HWND hWnd, LPCTSTR title, DWORD code) +{ + LPTSTR lpMsgBuf; + DWORD status; + static const TCHAR fallback[] = TEXT("Error displaying error message.\n"); + status = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, code, 0, (LPTSTR)&lpMsgBuf, 0, NULL); + if (!status) + lpMsgBuf = (LPTSTR)fallback; + MessageBox(hWnd, lpMsgBuf, title, MB_OK | MB_ICONERROR); + if (lpMsgBuf != fallback) + LocalFree(lpMsgBuf); +} diff --git a/base/applications/regedit/framewnd.c b/base/applications/regedit/framewnd.c index 4e465e6bb30..aa3a649f5da 100644 --- a/base/applications/regedit/framewnd.c +++ b/base/applications/regedit/framewnd.c @@ -282,6 +282,105 @@ static BOOL InitOpenFileName(HWND hWnd, OPENFILENAME* pofn) return TRUE; } +static INT_PTR CALLBACK LoadHive_KeyNameInHookProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static LPTSTR sKey = NULL; + static INT sLength = 0; + switch(uMsg) + { + case WM_INITDIALOG: + sKey = (LPTSTR)lParam; + sLength = 128; /* FIXME: Ugly hack! */ + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDOK: + if(GetDlgItemText(hWndDlg, IDC_EDIT_KEY, sKey, sLength)) + return EndDialog(hWndDlg, -1); + else + return EndDialog(hWndDlg, 0); + case IDCANCEL: + return EndDialog(hWndDlg, 0); + } + break; + } + return FALSE; +} + +static BOOL LoadHive(HWND hWnd) +{ + OPENFILENAME ofn; + TCHAR Caption[128]; + LPCTSTR pszKeyPath; + TCHAR xPath[128]; + HKEY hRootKey; + TCHAR Filter[1024]; + FILTERPAIR filter; + /* get the item key to load the hive in */ + pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey); + /* initialize the "open file" dialog */ + InitOpenFileName(hWnd, &ofn); + /* build the "All Files" filter up */ + filter.DisplayID = IDS_FLT_ALLFILES; + filter.FilterID = IDS_FLT_ALLFILES_FLT; + BuildFilterStrings(Filter, &filter, sizeof(filter)); + ofn.lpstrFilter = Filter; + /* load and set the caption and flags for dialog */ + LoadString(hInst, IDS_LOAD_HIVE, Caption, COUNT_OF(Caption)); + ofn.lpstrTitle = Caption; + ofn.Flags |= OFN_ENABLESIZING; + /* ofn.lCustData = ;*/ + /* now load the hive */ + if (GetOpenFileName(&ofn)) + { + if(DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_LOADHIVE), hWnd, &LoadHive_KeyNameInHookProc, (LPARAM)xPath)) + { + LONG regLoadResult = RegLoadKey(hRootKey, xPath, ofn.lpstrFile); + if(regLoadResult == ERROR_SUCCESS) + { + /* refresh tree and list views */ + RefreshTreeView(g_pChildWnd->hTreeWnd); + pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey); + RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath); + } + else + { + ErrorMessageBox(hWnd, Caption, regLoadResult); + return FALSE; + } + } + } else { + CheckCommDlgError(hWnd); + } + return TRUE; +} + +static BOOL UnloadHive(HWND hWnd) +{ + TCHAR Caption[128]; + LPCTSTR pszKeyPath; + HKEY hRootKey; + /* get the item key to unload */ + pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey); + /* load and set the caption and flags for dialog */ + LoadString(hInst, IDS_UNLOAD_HIVE, Caption, COUNT_OF(Caption)); + /* now unload the hive */ + LONG regUnloadResult = RegUnLoadKey(hRootKey, pszKeyPath); + if(regUnloadResult == ERROR_SUCCESS) + { + /* refresh tree and list views */ + RefreshTreeView(g_pChildWnd->hTreeWnd); + pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey); + RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath); + } + else + { + ErrorMessageBox(hWnd, Caption, regUnloadResult); + return FALSE; + } + return TRUE; +} + static BOOL ImportRegistryFile(HWND hWnd) { OPENFILENAME ofn; @@ -316,7 +415,6 @@ static BOOL ImportRegistryFile(HWND hWnd) return TRUE; } - static UINT_PTR CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) { HWND hwndExportAll; @@ -397,7 +495,7 @@ BOOL ExportRegistryFile(HWND hWnd) if (GetSaveFileName(&ofn)) { BOOL result; DWORD format; - + if (ofn.nFilterIndex == 1) format = REG_FORMAT_5; else @@ -758,6 +856,12 @@ static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) UNREFERENCED_PARAMETER(message); switch (LOWORD(wParam)) { + case ID_REGISTRY_LOADHIVE: + LoadHive(hWnd); + return TRUE; + case ID_REGISTRY_UNLOADHIVE: + UnloadHive(hWnd); + return TRUE; case ID_REGISTRY_IMPORTREGISTRYFILE: ImportRegistryFile(hWnd); return TRUE; diff --git a/base/applications/regedit/lang/bg-BG.rc b/base/applications/regedit/lang/bg-BG.rc index 7ecabedf807..da8521bc924 100644 --- a/base/applications/regedit/lang/bg-BG.rc +++ b/base/applications/regedit/lang/bg-BG.rc @@ -177,6 +177,16 @@ END /* * Dialog */ +IDD_LOADHIVE DIALOGEX DISCARDABLE 0, 0, 193, 34 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Hive" +FONT 8, "Ms Shell Dlg" +{ + LTEXT "&Key:", IDC_STATIC, 4, 4, 15, 8, SS_LEFT + EDITTEXT IDC_EDIT_KEY, 23, 2, 167, 13 + DEFPUSHBUTTON "OK", IDOK, 140, 17, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 89, 17, 50, 14 +} IDD_EDIT_STRING DIALOGEX 32, 24, 252, 84 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_NOIDLEMSG | DS_CONTEXTHELP | @@ -276,6 +286,10 @@ BEGIN ID_REGISTRY_IMPORTREGISTRYFILE " " ID_REGISTRY_EXPORTREGISTRYFILE " " + ID_REGISTRY_LOADHIVE + "Loads a hive file into the registry" + ID_REGISTRY_UNLOADHIVE + "Unloads a hive from the registry" ID_REGISTRY_CONNECTNETWORKREGISTRY " " ID_REGISTRY_DISCONNECTNETWORKREGISTRY @@ -332,6 +346,8 @@ BEGIN IDS_MY_COMPUTER " " IDS_IMPORT_REG_FILE " " IDS_EXPORT_REG_FILE " " + IDS_LOAD_HIVE "Load Hive" + IDS_UNLOAD_HIVE "Unload Hive" IDS_INVALID_DWORD "( )" END diff --git a/base/applications/regedit/lang/cs-CZ.rc b/base/applications/regedit/lang/cs-CZ.rc index c1d12dbfa95..9226c8eb36a 100644 --- a/base/applications/regedit/lang/cs-CZ.rc +++ b/base/applications/regedit/lang/cs-CZ.rc @@ -175,6 +175,16 @@ END /* * Dialog */ +IDD_LOADHIVE DIALOGEX DISCARDABLE 0, 0, 193, 34 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Hive" +FONT 8, "Ms Shell Dlg" +{ + LTEXT "&Key:", IDC_STATIC, 4, 4, 15, 8, SS_LEFT + EDITTEXT IDC_EDIT_KEY, 23, 2, 167, 13 + DEFPUSHBUTTON "OK", IDOK, 140, 17, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 89, 17, 50, 14 +} IDD_EDIT_STRING DIALOGEX 32, 24, 252, 84 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_NOIDLEMSG | DS_CONTEXTHELP | @@ -274,6 +284,10 @@ BEGIN ID_REGISTRY_IMPORTREGISTRYFILE "Importuje textov soubor do registru" ID_REGISTRY_EXPORTREGISTRYFILE "Exportuje vechny sti registru do textovho souboru" + ID_REGISTRY_LOADHIVE + "Loads a hive file into the registry" + ID_REGISTRY_UNLOADHIVE + "Unloads a hive from the registry" ID_REGISTRY_CONNECTNETWORKREGISTRY "Pipoj se ke vzdlenmu registru jinho potae" ID_REGISTRY_DISCONNECTNETWORKREGISTRY @@ -330,6 +344,8 @@ BEGIN IDS_MY_COMPUTER "Tento pota" IDS_IMPORT_REG_FILE "Importovat soubor registru" IDS_EXPORT_REG_FILE "Exportovat do souboru registru" + IDS_LOAD_HIVE "Load Hive" + IDS_UNLOAD_HIVE "Unload Hive" IDS_INVALID_DWORD "(Neplatn hodnota DWORD)" END diff --git a/base/applications/regedit/lang/de-DE.rc b/base/applications/regedit/lang/de-DE.rc index 4cf8657a80f..8d6f251f962 100644 --- a/base/applications/regedit/lang/de-DE.rc +++ b/base/applications/regedit/lang/de-DE.rc @@ -177,6 +177,16 @@ END /* * Dialog */ +IDD_LOADHIVE DIALOGEX DISCARDABLE 0, 0, 193, 34 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Hive" +FONT 8, "Ms Shell Dlg" +{ + LTEXT "&Key:", IDC_STATIC, 4, 4, 15, 8, SS_LEFT + EDITTEXT IDC_EDIT_KEY, 23, 2, 167, 13 + DEFPUSHBUTTON "OK", IDOK, 140, 17, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 89, 17, 50, 14 +} IDD_EDIT_STRING DIALOGEX 32, 24, 252, 84 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_NOIDLEMSG | DS_CONTEXTHELP | @@ -276,6 +286,10 @@ BEGIN ID_REGISTRY_IMPORTREGISTRYFILE "Importiert eine Textddatei in die Registry" ID_REGISTRY_EXPORTREGISTRYFILE "Exportiert Teile oder die ganze Registry in eine Textdatei" + ID_REGISTRY_LOADHIVE + "Loads a hive file into the registry" + ID_REGISTRY_UNLOADHIVE + "Unloads a hive from the registry" ID_REGISTRY_CONNECTNETWORKREGISTRY "Verbindet zu einer Registry eines Fremdcomputers" ID_REGISTRY_DISCONNECTNETWORKREGISTRY @@ -332,6 +346,8 @@ BEGIN IDS_MY_COMPUTER "Arbeitsplatz" IDS_IMPORT_REG_FILE "Registry importieren" IDS_EXPORT_REG_FILE "Registry exportieren" + IDS_LOAD_HIVE "Load Hive" + IDS_UNLOAD_HIVE "Unload Hive" IDS_INVALID_DWORD "(ungltiger DWORD-Wert)" END diff --git a/base/applications/regedit/lang/el-GR.rc b/base/applications/regedit/lang/el-GR.rc index 281ed2d299e..44ca2d9f33c 100644 --- a/base/applications/regedit/lang/el-GR.rc +++ b/base/applications/regedit/lang/el-GR.rc @@ -177,6 +177,16 @@ END /* * Dialog */ +IDD_LOADHIVE DIALOGEX DISCARDABLE 0, 0, 193, 34 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Hive" +FONT 8, "Ms Shell Dlg" +{ + LTEXT "&Key:", IDC_STATIC, 4, 4, 15, 8, SS_LEFT + EDITTEXT IDC_EDIT_KEY, 23, 2, 167, 13 + DEFPUSHBUTTON "OK", IDOK, 140, 17, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 89, 17, 50, 14 +} IDD_EDIT_STRING DIALOGEX 32, 24, 252, 84 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_NOIDLEMSG | DS_CONTEXTHELP | @@ -276,6 +286,10 @@ BEGIN ID_REGISTRY_IMPORTREGISTRYFILE " registry" ID_REGISTRY_EXPORTREGISTRYFILE " registry " + ID_REGISTRY_LOADHIVE + "Loads a hive file into the registry" + ID_REGISTRY_UNLOADHIVE + "Unloads a hive from the registry" ID_REGISTRY_CONNECTNETWORKREGISTRY " registry " ID_REGISTRY_DISCONNECTNETWORKREGISTRY @@ -332,6 +346,8 @@ BEGIN IDS_MY_COMPUTER " " IDS_IMPORT_REG_FILE " Registry" IDS_EXPORT_REG_FILE " Registry" + IDS_LOAD_HIVE "Load Hive" + IDS_UNLOAD_HIVE "Unload Hive" IDS_INVALID_DWORD "( DWORD )" END diff --git a/base/applications/regedit/lang/en-US.rc b/base/applications/regedit/lang/en-US.rc index e5a94cba8e7..fb81f164e87 100644 --- a/base/applications/regedit/lang/en-US.rc +++ b/base/applications/regedit/lang/en-US.rc @@ -274,6 +274,10 @@ BEGIN ID_REGISTRY_IMPORTREGISTRYFILE "Imports a text file into the registry" ID_REGISTRY_EXPORTREGISTRYFILE "Exports all or part of the registry to a text file" + ID_REGISTRY_LOADHIVE + "Loads a hive file into the registry" + ID_REGISTRY_UNLOADHIVE + "Unloads a hive from the registry" ID_REGISTRY_CONNECTNETWORKREGISTRY "Connects to a remote computer's registry" ID_REGISTRY_DISCONNECTNETWORKREGISTRY @@ -330,6 +334,8 @@ BEGIN IDS_MY_COMPUTER "My Computer" IDS_IMPORT_REG_FILE "Import Registry File" IDS_EXPORT_REG_FILE "Export Registry File" + IDS_LOAD_HIVE "Load Hive" + IDS_UNLOAD_HIVE "Unload Hive" IDS_INVALID_DWORD "(invalid DWORD value)" END @@ -392,6 +398,20 @@ BEGIN EDITTEXT IDC_EXPORT_BRANCH_TEXT,30,34,335,12 END +// +// Dialog resources +// +IDD_LOADHIVE DIALOGEX DISCARDABLE 0, 0, 193, 34 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Hive" +FONT 8, "Ms Shell Dlg" +{ + LTEXT "&Key:", IDC_STATIC, 4, 4, 15, 8, SS_LEFT + EDITTEXT IDC_EDIT_KEY, 23, 2, 167, 13 + DEFPUSHBUTTON "OK", IDOK, 140, 17, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 89, 17, 50, 14 +} + IDD_ADDFAVORITES DIALOGEX DISCARDABLE 0, 0, 186, 46 STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Add to Favorites" diff --git a/base/applications/regedit/lang/es-ES.rc b/base/applications/regedit/lang/es-ES.rc index b128846bca1..0e1dc4c5d86 100644 --- a/base/applications/regedit/lang/es-ES.rc +++ b/base/applications/regedit/lang/es-ES.rc @@ -180,6 +180,16 @@ END /* * Dialog */ +IDD_LOADHIVE DIALOGEX DISCARDABLE 0, 0, 193, 34 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Hive" +FONT 8, "Ms Shell Dlg" +{ + LTEXT "&Key:", IDC_STATIC, 4, 4, 15, 8, SS_LEFT + EDITTEXT IDC_EDIT_KEY, 23, 2, 167, 13 + DEFPUSHBUTTON "OK", IDOK, 140, 17, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 89, 17, 50, 14 +} IDD_EDIT_STRING DIALOGEX 32, 24, 252, 84 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_NOIDLEMSG | DS_CONTEXTHELP | @@ -279,6 +289,10 @@ BEGIN ID_REGISTRY_IMPORTREGISTRYFILE "Importa un archivo de texto al registro" ID_REGISTRY_EXPORTREGISTRYFILE "Exporta todo o parte del registro a un archivo de texto" + ID_REGISTRY_LOADHIVE + "Loads a hive file into the registry" + ID_REGISTRY_UNLOADHIVE + "Unloads a hive from the registry" ID_REGISTRY_CONNECTNETWORKREGISTRY "Se conecta al registro de un ordenador remoto" ID_REGISTRY_DISCONNECTNETWORKREGISTRY @@ -335,6 +349,8 @@ BEGIN IDS_MY_COMPUTER "Mi PC" IDS_IMPORT_REG_FILE "Importa Fichero de Registro" IDS_EXPORT_REG_FILE "Exporta Fichero de Registro" + IDS_LOAD_HIVE "Load Hive" + IDS_UNLOAD_HIVE "Unload Hive" IDS_INVALID_DWORD "(valor DWORD invalido)" END diff --git a/base/applications/regedit/lang/fr-FR.rc b/base/applications/regedit/lang/fr-FR.rc index c5042da4c9a..56e31bcd755 100644 --- a/base/applications/regedit/lang/fr-FR.rc +++ b/base/applications/regedit/lang/fr-FR.rc @@ -180,6 +180,16 @@ END /* * Dialog */ +IDD_LOADHIVE DIALOGEX DISCARDABLE 0, 0, 193, 34 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Hive" +FONT 8, "Ms Shell Dlg" +{ + LTEXT "&Key:", IDC_STATIC, 4, 4, 15, 8, SS_LEFT + EDITTEXT IDC_EDIT_KEY, 23, 2, 167, 13 + DEFPUSHBUTTON "OK", IDOK, 140, 17, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 89, 17, 50, 14 +} IDD_EDIT_STRING DIALOGEX 32, 24, 252, 84 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_NOIDLEMSG | DS_CONTEXTHELP | @@ -279,6 +289,10 @@ BEGIN ID_REGISTRY_IMPORTREGISTRYFILE "Importe un fichier texte dans les registres" ID_REGISTRY_EXPORTREGISTRYFILE "Exporte tout ou une partie des registres dans un fichier texte" + ID_REGISTRY_LOADHIVE + "Loads a hive file into the registry" + ID_REGISTRY_UNLOADHIVE + "Unloads a hive from the registry" ID_REGISTRY_CONNECTNETWORKREGISTRY "Connecte aux registres d'un ordinateur distant" ID_REGISTRY_DISCONNECTNETWORKREGISTRY @@ -335,6 +349,8 @@ BEGIN IDS_MY_COMPUTER "Mon ordinateur" IDS_IMPORT_REG_FILE "Importer un fichier registre" IDS_EXPORT_REG_FILE "Exporter un fichier registre" + IDS_LOAD_HIVE "Load Hive" + IDS_UNLOAD_HIVE "Unload Hive" IDS_INVALID_DWORD "(valeur mot double invalide)" END diff --git a/base/applications/regedit/lang/hu-HU.rc b/base/applications/regedit/lang/hu-HU.rc index 42faef3a4ea..7efa45d5221 100644 --- a/base/applications/regedit/lang/hu-HU.rc +++ b/base/applications/regedit/lang/hu-HU.rc @@ -178,6 +178,16 @@ END /* * Dialog */ +IDD_LOADHIVE DIALOGEX DISCARDABLE 0, 0, 193, 34 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Hive" +FONT 8, "Ms Shell Dlg" +{ + LTEXT "&Key:", IDC_STATIC, 4, 4, 15, 8, SS_LEFT + EDITTEXT IDC_EDIT_KEY, 23, 2, 167, 13 + DEFPUSHBUTTON "OK", IDOK, 140, 17, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 89, 17, 50, 14 +} IDD_EDIT_STRING DIALOGEX 32, 24, 252, 84 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_NOIDLEMSG | DS_CONTEXTHELP | @@ -277,6 +287,10 @@ BEGIN ID_REGISTRY_IMPORTREGISTRYFILE "Imports a text file into the registry" ID_REGISTRY_EXPORTREGISTRYFILE "Exports all or part of the registry to a text file" + ID_REGISTRY_LOADHIVE + "Loads a hive file into the registry" + ID_REGISTRY_UNLOADHIVE + "Unloads a hive from the registry" ID_REGISTRY_CONNECTNETWORKREGISTRY "Connects to a remote computer's registry" ID_REGISTRY_DISCONNECTNETWORKREGISTRY @@ -333,6 +347,8 @@ BEGIN IDS_MY_COMPUTER "My Computer" IDS_IMPORT_REG_FILE "Import Registry File" IDS_EXPORT_REG_FILE "Export Registry File" + IDS_LOAD_HIVE "Load Hive" + IDS_UNLOAD_HIVE "Unload Hive" IDS_INVALID_DWORD "(invalid DWORD value)" END diff --git a/base/applications/regedit/lang/id-ID.rc b/base/applications/regedit/lang/id-ID.rc index 059abec9576..4d8571470fe 100644 --- a/base/applications/regedit/lang/id-ID.rc +++ b/base/applications/regedit/lang/id-ID.rc @@ -177,6 +177,16 @@ END /* * Dialog */ +IDD_LOADHIVE DIALOGEX DISCARDABLE 0, 0, 193, 34 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Hive" +FONT 8, "Ms Shell Dlg" +{ + LTEXT "&Key:", IDC_STATIC, 4, 4, 15, 8, SS_LEFT + EDITTEXT IDC_EDIT_KEY, 23, 2, 167, 13 + DEFPUSHBUTTON "OK", IDOK, 140, 17, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 89, 17, 50, 14 +} IDD_EDIT_STRING DIALOGEX 32, 24, 252, 84 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_NOIDLEMSG | DS_CONTEXTHELP | @@ -276,6 +286,10 @@ BEGIN ID_REGISTRY_IMPORTREGISTRYFILE "Mengimpor file teks ke dalam registri" ID_REGISTRY_EXPORTREGISTRYFILE "Mengekspor semua atau sebagian registri le file teks" + ID_REGISTRY_LOADHIVE + "Loads a hive file into the registry" + ID_REGISTRY_UNLOADHIVE + "Unloads a hive from the registry" ID_REGISTRY_CONNECTNETWORKREGISTRY "Menyambung ke registri komputer remote" ID_REGISTRY_DISCONNECTNETWORKREGISTRY @@ -332,6 +346,8 @@ BEGIN IDS_MY_COMPUTER "My Computer" IDS_IMPORT_REG_FILE "Impor File Registri" IDS_EXPORT_REG_FILE "Ekspor File Registri" + IDS_LOAD_HIVE "Load Hive" + IDS_UNLOAD_HIVE "Unload Hive" IDS_INVALID_DWORD "(nilai DWORD tidak benar)" END diff --git a/base/applications/regedit/lang/it-IT.rc b/base/applications/regedit/lang/it-IT.rc index 53c68565cb2..8f81f05ea36 100644 --- a/base/applications/regedit/lang/it-IT.rc +++ b/base/applications/regedit/lang/it-IT.rc @@ -180,6 +180,16 @@ END /* * Dialog */ +IDD_LOADHIVE DIALOGEX DISCARDABLE 0, 0, 193, 34 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Hive" +FONT 8, "Ms Shell Dlg" +{ + LTEXT "&Key:", IDC_STATIC, 4, 4, 15, 8, SS_LEFT + EDITTEXT IDC_EDIT_KEY, 23, 2, 167, 13 + DEFPUSHBUTTON "OK", IDOK, 140, 17, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 89, 17, 50, 14 +} IDD_EDIT_STRING DIALOGEX 32, 24, 252, 84 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_NOIDLEMSG | DS_CONTEXTHELP | @@ -281,6 +291,10 @@ BEGIN ID_REGISTRY_IMPORTREGISTRYFILE "Importa un file di testo nel Registro" ID_REGISTRY_EXPORTREGISTRYFILE "Esporta tutto o parte del Registro in un file di testo" + ID_REGISTRY_LOADHIVE + "Loads a hive file into the registry" + ID_REGISTRY_UNLOADHIVE + "Unloads a hive from the registry" ID_REGISTRY_CONNECTNETWORKREGISTRY "Si connette al Registro di un computer remoto" ID_REGISTRY_DISCONNECTNETWORKREGISTRY @@ -337,6 +351,8 @@ BEGIN IDS_MY_COMPUTER "Il mio Computer" IDS_IMPORT_REG_FILE "Importa file di Registro" IDS_EXPORT_REG_FILE "Esporta file di Registro" + IDS_LOAD_HIVE "Load Hive" + IDS_UNLOAD_HIVE "Unload Hive" IDS_INVALID_DWORD "(valore DWORD non valido)" END diff --git a/base/applications/regedit/lang/ja-JP.rc b/base/applications/regedit/lang/ja-JP.rc index 8b1816bf03f..66a0967fb17 100644 --- a/base/applications/regedit/lang/ja-JP.rc +++ b/base/applications/regedit/lang/ja-JP.rc @@ -175,6 +175,16 @@ END /* * Dialog */ +IDD_LOADHIVE DIALOGEX DISCARDABLE 0, 0, 193, 34 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Hive" +FONT 8, "Ms Shell Dlg" +{ + LTEXT "&Key:", IDC_STATIC, 4, 4, 15, 8, SS_LEFT + EDITTEXT IDC_EDIT_KEY, 23, 2, 167, 13 + DEFPUSHBUTTON "OK", IDOK, 140, 17, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 89, 17, 50, 14 +} IDD_EDIT_STRING DIALOGEX 32, 24, 252, 84 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_NOIDLEMSG | DS_CONTEXTHELP | @@ -274,6 +284,10 @@ BEGIN ID_REGISTRY_IMPORTREGISTRYFILE "eLXg t@CWXgɃC|[g܂B" ID_REGISTRY_EXPORTREGISTRYFILE "WXg̈ꕔ܂͑ŜeLXg t@CɃGNX|[g܂B" + ID_REGISTRY_LOADHIVE + "Loads a hive file into the registry" + ID_REGISTRY_UNLOADHIVE + "Unloads a hive from the registry" ID_REGISTRY_CONNECTNETWORKREGISTRY "[g Rs[^̃WXgɐڑ܂B" ID_REGISTRY_DISCONNECTNETWORKREGISTRY @@ -330,6 +344,8 @@ BEGIN IDS_MY_COMPUTER "}C Rs[^" IDS_IMPORT_REG_FILE "WXg t@C̃C|[g" IDS_EXPORT_REG_FILE "WXg t@C̃GNX|[g" + IDS_LOAD_HIVE "Load Hive" + IDS_UNLOAD_HIVE "Unload Hive" IDS_INVALID_DWORD "( DWORD l)" END diff --git a/base/applications/regedit/lang/ko-KR.rc b/base/applications/regedit/lang/ko-KR.rc index 01777d0344b..b2057978fca 100644 --- a/base/applications/regedit/lang/ko-KR.rc +++ b/base/applications/regedit/lang/ko-KR.rc @@ -162,6 +162,16 @@ END /* * Dialog */ +IDD_LOADHIVE DIALOGEX DISCARDABLE 0, 0, 193, 34 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Hive" +FONT 8, "Ms Shell Dlg" +{ + LTEXT "&Key:", IDC_STATIC, 4, 4, 15, 8, SS_LEFT + EDITTEXT IDC_EDIT_KEY, 23, 2, 167, 13 + DEFPUSHBUTTON "OK", IDOK, 140, 17, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 89, 17, 50, 14 +} IDD_EDIT_STRING DIALOGEX 32, 24, 252, 84 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_NOIDLEMSG | DS_CONTEXTHELP | @@ -261,6 +271,10 @@ BEGIN ID_REGISTRY_IMPORTREGISTRYFILE "ؽƮ Ʈ ҷ ɴϴ" ID_REGISTRY_EXPORTREGISTRYFILE "ؽƮ Ϸ Ʈ ü Ϻθ ϴ" + ID_REGISTRY_LOADHIVE + "Loads a hive file into the registry" + ID_REGISTRY_UNLOADHIVE + "Unloads a hive from the registry" ID_REGISTRY_CONNECTNETWORKREGISTRY " ǻ Ʈ մϴ" ID_REGISTRY_DISCONNECTNETWORKREGISTRY @@ -317,6 +331,8 @@ BEGIN IDS_MY_COMPUTER " ǻ" IDS_IMPORT_REG_FILE "Ʈ ҷ" IDS_EXPORT_REG_FILE "Ʈ " + IDS_LOAD_HIVE "Load Hive" + IDS_UNLOAD_HIVE "Unload Hive" IDS_INVALID_DWORD "(߸ DWORD)" END diff --git a/base/applications/regedit/lang/nl-NL.rc b/base/applications/regedit/lang/nl-NL.rc index be86610e59c..2bc09796371 100644 --- a/base/applications/regedit/lang/nl-NL.rc +++ b/base/applications/regedit/lang/nl-NL.rc @@ -177,6 +177,16 @@ END /* * Dialog */ +IDD_LOADHIVE DIALOGEX DISCARDABLE 0, 0, 193, 34 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Hive" +FONT 8, "Ms Shell Dlg" +{ + LTEXT "&Key:", IDC_STATIC, 4, 4, 15, 8, SS_LEFT + EDITTEXT IDC_EDIT_KEY, 23, 2, 167, 13 + DEFPUSHBUTTON "OK", IDOK, 140, 17, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 89, 17, 50, 14 +} IDD_EDIT_STRING DIALOGEX 32, 24, 252, 84 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_NOIDLEMSG | DS_CONTEXTHELP | @@ -276,6 +286,10 @@ BEGIN ID_REGISTRY_IMPORTREGISTRYFILE "Een tekstbestand in het register importeren" ID_REGISTRY_EXPORTREGISTRYFILE "Het register of een gedeelte ervan naar een tekstbestand exporteren" + ID_REGISTRY_LOADHIVE + "Loads a hive file into the registry" + ID_REGISTRY_UNLOADHIVE + "Unloads a hive from the registry" ID_REGISTRY_CONNECTNETWORKREGISTRY "Een verbinding maken met het register van een externe computer" ID_REGISTRY_DISCONNECTNETWORKREGISTRY @@ -332,6 +346,8 @@ BEGIN IDS_MY_COMPUTER "My Computer" IDS_IMPORT_REG_FILE "Import Registry File" IDS_EXPORT_REG_FILE "Export Registry File" + IDS_LOAD_HIVE "Load Hive" + IDS_UNLOAD_HIVE "Unload Hive" IDS_INVALID_DWORD "(invalid DWORD value)" END diff --git a/base/applications/regedit/lang/no-NO.rc b/base/applications/regedit/lang/no-NO.rc index b052432f8ec..60d0d1af091 100644 --- a/base/applications/regedit/lang/no-NO.rc +++ b/base/applications/regedit/lang/no-NO.rc @@ -177,6 +177,16 @@ END /* * Dialog */ +IDD_LOADHIVE DIALOGEX DISCARDABLE 0, 0, 193, 34 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Hive" +FONT 8, "Ms Shell Dlg" +{ + LTEXT "&Key:", IDC_STATIC, 4, 4, 15, 8, SS_LEFT + EDITTEXT IDC_EDIT_KEY, 23, 2, 167, 13 + DEFPUSHBUTTON "OK", IDOK, 140, 17, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 89, 17, 50, 14 +} IDD_EDIT_STRING DIALOGEX 32, 24, 252, 84 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_NOIDLEMSG | DS_CONTEXTHELP | @@ -276,6 +286,10 @@ BEGIN ID_REGISTRY_IMPORTREGISTRYFILE "Importerer en tekstfil inn i Registret" ID_REGISTRY_EXPORTREGISTRYFILE "Eksporterer hele eller deler av Registret til en tekstfil" + ID_REGISTRY_LOADHIVE + "Loads a hive file into the registry" + ID_REGISTRY_UNLOADHIVE + "Unloads a hive from the registry" ID_REGISTRY_CONNECTNETWORKREGISTRY "Kobler til Registret p en annen datamaskin" ID_REGISTRY_DISCONNECTNETWORKREGISTRY @@ -332,6 +346,8 @@ BEGIN IDS_MY_COMPUTER "Min datamaskin" IDS_IMPORT_REG_FILE "Importer registerfil" IDS_EXPORT_REG_FILE "Eksporter registerfil" + IDS_LOAD_HIVE "Load Hive" + IDS_UNLOAD_HIVE "Unload Hive" IDS_INVALID_DWORD "(ugyldig DWORD-verdi)" END diff --git a/base/applications/regedit/lang/pl-PL.rc b/base/applications/regedit/lang/pl-PL.rc index 198125c772c..4f864f3df01 100644 --- a/base/applications/regedit/lang/pl-PL.rc +++ b/base/applications/regedit/lang/pl-PL.rc @@ -182,6 +182,16 @@ END /* * Dialog */ +IDD_LOADHIVE DIALOGEX DISCARDABLE 0, 0, 193, 34 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Hive" +FONT 8, "Ms Shell Dlg" +{ + LTEXT "&Key:", IDC_STATIC, 4, 4, 15, 8, SS_LEFT + EDITTEXT IDC_EDIT_KEY, 23, 2, 167, 13 + DEFPUSHBUTTON "OK", IDOK, 140, 17, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 89, 17, 50, 14 +} IDD_EDIT_STRING DIALOGEX 32, 24, 252, 84 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_NOIDLEMSG | DS_CONTEXTHELP | @@ -281,6 +291,10 @@ BEGIN ID_REGISTRY_IMPORTREGISTRYFILE "Importuje plik do rejestru" ID_REGISTRY_EXPORTREGISTRYFILE "Eksportuje cao lub cz rejestru do pliku" + ID_REGISTRY_LOADHIVE + "Loads a hive file into the registry" + ID_REGISTRY_UNLOADHIVE + "Unloads a hive from the registry" ID_REGISTRY_CONNECTNETWORKREGISTRY "Poczenie z rejestrem zdalnego komputera" ID_REGISTRY_DISCONNECTNETWORKREGISTRY @@ -337,6 +351,8 @@ BEGIN IDS_MY_COMPUTER "Mj komputer" IDS_IMPORT_REG_FILE "Importuj plik rejestru" IDS_EXPORT_REG_FILE "Eksportuj plik rejestru" + IDS_LOAD_HIVE "Load Hive" + IDS_UNLOAD_HIVE "Unload Hive" IDS_INVALID_DWORD "(niewaciwa warto DWORD)" END diff --git a/base/applications/regedit/lang/pt-BR.rc b/base/applications/regedit/lang/pt-BR.rc index 4cd21990e30..7abc3c211ba 100644 --- a/base/applications/regedit/lang/pt-BR.rc +++ b/base/applications/regedit/lang/pt-BR.rc @@ -178,6 +178,16 @@ END /* * Dialog */ +IDD_LOADHIVE DIALOGEX DISCARDABLE 0, 0, 193, 34 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Hive" +FONT 8, "Ms Shell Dlg" +{ + LTEXT "&Key:", IDC_STATIC, 4, 4, 15, 8, SS_LEFT + EDITTEXT IDC_EDIT_KEY, 23, 2, 167, 13 + DEFPUSHBUTTON "OK", IDOK, 140, 17, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 89, 17, 50, 14 +} IDD_EDIT_STRING DIALOGEX 32, 24, 252, 84 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_NOIDLEMSG | DS_CONTEXTHELP | @@ -277,6 +287,10 @@ BEGIN ID_REGISTRY_IMPORTREGISTRYFILE "Importa um arquivo de texto para o registro" ID_REGISTRY_EXPORTREGISTRYFILE "Exporta todo ou parte do Registro para um arquivo texto" + ID_REGISTRY_LOADHIVE + "Loads a hive file into the registry" + ID_REGISTRY_UNLOADHIVE + "Unloads a hive from the registry" ID_REGISTRY_CONNECTNETWORKREGISTRY "Conecta-se ao Registro de um computador remoto" ID_REGISTRY_DISCONNECTNETWORKREGISTRY @@ -333,6 +347,8 @@ BEGIN IDS_MY_COMPUTER "Meu computador" IDS_IMPORT_REG_FILE "Importar arquivo do Registro" IDS_EXPORT_REG_FILE "Exportar arquivo do Registro" + IDS_LOAD_HIVE "Load Hive" + IDS_UNLOAD_HIVE "Unload Hive" IDS_INVALID_DWORD "(valor DWORD invlido)" END diff --git a/base/applications/regedit/lang/pt-PT.rc b/base/applications/regedit/lang/pt-PT.rc index 15fee2f3166..52b15fd526c 100644 --- a/base/applications/regedit/lang/pt-PT.rc +++ b/base/applications/regedit/lang/pt-PT.rc @@ -277,6 +277,10 @@ BEGIN ID_REGISTRY_IMPORTREGISTRYFILE "Importa um arquivo texto para o registro." ID_REGISTRY_EXPORTREGISTRYFILE "Exporta todo ou parte do registro para um arquivo texto." + ID_REGISTRY_LOADHIVE + "Loads a hive file into the registry" + ID_REGISTRY_UNLOADHIVE + "Unloads a hive from the registry" ID_REGISTRY_CONNECTNETWORKREGISTRY "Conecta a um registro em um computador remoto." ID_REGISTRY_DISCONNECTNETWORKREGISTRY @@ -333,6 +337,8 @@ BEGIN IDS_MY_COMPUTER "My Computer" IDS_IMPORT_REG_FILE "Import Registry File" IDS_EXPORT_REG_FILE "Export Registry File" + IDS_LOAD_HIVE "Load Hive" + IDS_UNLOAD_HIVE "Unload Hive" IDS_INVALID_DWORD "(invalid DWORD value)" END @@ -384,6 +390,16 @@ END /* * Dialog */ +IDD_LOADHIVE DIALOGEX DISCARDABLE 0, 0, 193, 34 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Hive" +FONT 8, "Ms Shell Dlg" +{ + LTEXT "&Key:", IDC_STATIC, 4, 4, 15, 8, SS_LEFT + EDITTEXT IDC_EDIT_KEY, 23, 2, 167, 13 + DEFPUSHBUTTON "OK", IDOK, 140, 17, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 89, 17, 50, 14 +} IDD_EXPORTRANGE DIALOGEX DISCARDABLE 50, 50, 370, 50 STYLE DS_SHELLFONT | DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | diff --git a/base/applications/regedit/lang/ru-RU.rc b/base/applications/regedit/lang/ru-RU.rc index 62892800f15..f8e74660ab9 100644 --- a/base/applications/regedit/lang/ru-RU.rc +++ b/base/applications/regedit/lang/ru-RU.rc @@ -177,6 +177,16 @@ END /* * Dialog */ +IDD_LOADHIVE DIALOGEX DISCARDABLE 0, 0, 193, 34 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Hive" +FONT 8, "Ms Shell Dlg" +{ + LTEXT "&Key:", IDC_STATIC, 4, 4, 15, 8, SS_LEFT + EDITTEXT IDC_EDIT_KEY, 23, 2, 167, 13 + DEFPUSHBUTTON "OK", IDOK, 140, 17, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 89, 17, 50, 14 +} IDD_EDIT_STRING DIALOGEX 32, 24, 252, 84 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_NOIDLEMSG | DS_CONTEXTHELP | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU @@ -275,6 +285,8 @@ BEGIN ID_EDIT_NEW_DWORDVALUE " DWORD-" ID_REGISTRY_IMPORTREGISTRYFILE " " ID_REGISTRY_EXPORTREGISTRYFILE " " + ID_REGISTRY_LOADHIVE "Loads a hive file into the registry" + ID_REGISTRY_UNLOADHIVE "Unloads a hive from the registry" ID_REGISTRY_CONNECTNETWORKREGISTRY " " @@ -332,6 +344,8 @@ BEGIN IDS_MY_COMPUTER " " IDS_IMPORT_REG_FILE " " IDS_EXPORT_REG_FILE " " + IDS_LOAD_HIVE "Load Hive" + IDS_UNLOAD_HIVE "Unload Hive" IDS_INVALID_DWORD "( DWORD)" END diff --git a/base/applications/regedit/lang/sk-SK.rc b/base/applications/regedit/lang/sk-SK.rc index f5437e9cb65..b6cb4754993 100644 --- a/base/applications/regedit/lang/sk-SK.rc +++ b/base/applications/regedit/lang/sk-SK.rc @@ -162,6 +162,16 @@ END /* * Dialog */ +IDD_LOADHIVE DIALOGEX DISCARDABLE 0, 0, 193, 34 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Hive" +FONT 8, "Ms Shell Dlg" +{ + LTEXT "&Key:", IDC_STATIC, 4, 4, 15, 8, SS_LEFT + EDITTEXT IDC_EDIT_KEY, 23, 2, 167, 13 + DEFPUSHBUTTON "OK", IDOK, 140, 17, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 89, 17, 50, 14 +} IDD_EDIT_STRING DIALOGEX 32, 24, 252, 84 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_NOIDLEMSG | DS_CONTEXTHELP | @@ -261,6 +271,10 @@ BEGIN ID_REGISTRY_IMPORTREGISTRYFILE "Imports a text file into the registry" ID_REGISTRY_EXPORTREGISTRYFILE "Exports all or part of the registry to a text file" + ID_REGISTRY_LOADHIVE + "Loads a hive file into the registry" + ID_REGISTRY_UNLOADHIVE + "Unloads a hive from the registry" ID_REGISTRY_CONNECTNETWORKREGISTRY "Connects to a remote computer's registry" ID_REGISTRY_DISCONNECTNETWORKREGISTRY @@ -317,6 +331,8 @@ BEGIN IDS_MY_COMPUTER "Tento pota" IDS_IMPORT_REG_FILE "Import Registry File" IDS_EXPORT_REG_FILE "Export Registry File" + IDS_LOAD_HIVE "Load Hive" + IDS_UNLOAD_HIVE "Unload Hive" IDS_INVALID_DWORD "(neplatn DWORD hodnota)" END diff --git a/base/applications/regedit/lang/sl-SI.rc b/base/applications/regedit/lang/sl-SI.rc index d5c5804c881..0be7a429a8a 100644 --- a/base/applications/regedit/lang/sl-SI.rc +++ b/base/applications/regedit/lang/sl-SI.rc @@ -177,6 +177,16 @@ END /* * Dialog */ +IDD_LOADHIVE DIALOGEX DISCARDABLE 0, 0, 193, 34 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Hive" +FONT 8, "Ms Shell Dlg" +{ + LTEXT "&Key:", IDC_STATIC, 4, 4, 15, 8, SS_LEFT + EDITTEXT IDC_EDIT_KEY, 23, 2, 167, 13 + DEFPUSHBUTTON "OK", IDOK, 140, 17, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 89, 17, 50, 14 +} IDD_EDIT_STRING DIALOGEX 32, 24, 252, 84 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_NOIDLEMSG | DS_CONTEXTHELP | @@ -276,6 +286,10 @@ BEGIN ID_REGISTRY_IMPORTREGISTRYFILE "V register uvozi datoteko z besedilom" ID_REGISTRY_EXPORTREGISTRYFILE "Registrsko datoteko ali njen del izvozi v besedilno datoteko" + ID_REGISTRY_LOADHIVE + "Loads a hive file into the registry" + ID_REGISTRY_UNLOADHIVE + "Unloads a hive from the registry" ID_REGISTRY_CONNECTNETWORKREGISTRY "Vzpostavi povezavo z registrom oddaljenega raunalnika" ID_REGISTRY_DISCONNECTNETWORKREGISTRY @@ -332,6 +346,8 @@ BEGIN IDS_MY_COMPUTER "My Computer" IDS_IMPORT_REG_FILE "Import Registry File" IDS_EXPORT_REG_FILE "Export Registry File" + IDS_LOAD_HIVE "Load Hive" + IDS_UNLOAD_HIVE "Unload Hive" IDS_INVALID_DWORD "(invalid DWORD value)" END diff --git a/base/applications/regedit/lang/sv-SE.rc b/base/applications/regedit/lang/sv-SE.rc index ee1515dd08b..70832d3e573 100644 --- a/base/applications/regedit/lang/sv-SE.rc +++ b/base/applications/regedit/lang/sv-SE.rc @@ -175,6 +175,16 @@ END /* * Dialog */ +IDD_LOADHIVE DIALOGEX DISCARDABLE 0, 0, 193, 34 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Hive" +FONT 8, "Ms Shell Dlg" +{ + LTEXT "&Key:", IDC_STATIC, 4, 4, 15, 8, SS_LEFT + EDITTEXT IDC_EDIT_KEY, 23, 2, 167, 13 + DEFPUSHBUTTON "OK", IDOK, 140, 17, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 89, 17, 50, 14 +} IDD_EDIT_STRING DIALOGEX 32, 24, 252, 84 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_NOIDLEMSG | DS_CONTEXTHELP | @@ -274,6 +284,10 @@ BEGIN ID_REGISTRY_IMPORTREGISTRYFILE "Importerar en textfil till registret" ID_REGISTRY_EXPORTREGISTRYFILE "Exporterar hela eller en del av registret till en textfil" + ID_REGISTRY_LOADHIVE + "Loads a hive file into the registry" + ID_REGISTRY_UNLOADHIVE + "Unloads a hive from the registry" ID_REGISTRY_CONNECTNETWORKREGISTRY "Ansluter till en annan dators register" ID_REGISTRY_DISCONNECTNETWORKREGISTRY @@ -330,6 +344,8 @@ BEGIN IDS_MY_COMPUTER "Den hr datorn" IDS_IMPORT_REG_FILE "Importera registerfil" IDS_EXPORT_REG_FILE "Exportera registerfil" + IDS_LOAD_HIVE "Load Hive" + IDS_UNLOAD_HIVE "Unload Hive" IDS_INVALID_DWORD "(felaktigt DWORD-vrde)" END diff --git a/base/applications/regedit/lang/th-TH.rc b/base/applications/regedit/lang/th-TH.rc index c7bb7fde7d9..51aa5da0a8f 100644 --- a/base/applications/regedit/lang/th-TH.rc +++ b/base/applications/regedit/lang/th-TH.rc @@ -177,6 +177,16 @@ END /* * Dialog */ +IDD_LOADHIVE DIALOGEX DISCARDABLE 0, 0, 193, 34 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Hive" +FONT 8, "Ms Shell Dlg" +{ + LTEXT "&Key:", IDC_STATIC, 4, 4, 15, 8, SS_LEFT + EDITTEXT IDC_EDIT_KEY, 23, 2, 167, 13 + DEFPUSHBUTTON "OK", IDOK, 140, 17, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 89, 17, 50, 14 +} IDD_EDIT_STRING DIALOGEX 32, 24, 252, 84 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_NOIDLEMSG | DS_CONTEXTHELP | @@ -276,6 +286,10 @@ BEGIN ID_REGISTRY_IMPORTREGISTRYFILE "Imports a text file into the registry" ID_REGISTRY_EXPORTREGISTRYFILE "Exports all or part of the registry to a text file" + ID_REGISTRY_LOADHIVE + "Loads a hive file into the registry" + ID_REGISTRY_UNLOADHIVE + "Unloads a hive from the registry" ID_REGISTRY_CONNECTNETWORKREGISTRY "Connects to a remote computer's registry" ID_REGISTRY_DISCONNECTNETWORKREGISTRY @@ -332,6 +346,8 @@ BEGIN IDS_MY_COMPUTER "My Computer" IDS_IMPORT_REG_FILE "Import Registry File" IDS_EXPORT_REG_FILE "Export Registry File" + IDS_LOAD_HIVE "Load Hive" + IDS_UNLOAD_HIVE "Unload Hive" IDS_INVALID_DWORD "(invalid DWORD value)" END diff --git a/base/applications/regedit/lang/uk-UA.rc b/base/applications/regedit/lang/uk-UA.rc index 5fd1fa5ec45..6f98e38c0eb 100644 --- a/base/applications/regedit/lang/uk-UA.rc +++ b/base/applications/regedit/lang/uk-UA.rc @@ -178,6 +178,16 @@ END /* * Dialog */ +IDD_LOADHIVE DIALOGEX DISCARDABLE 0, 0, 193, 34 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Hive" +FONT 8, "Ms Shell Dlg" +{ + LTEXT "&Key:", IDC_STATIC, 4, 4, 15, 8, SS_LEFT + EDITTEXT IDC_EDIT_KEY, 23, 2, 167, 13 + DEFPUSHBUTTON "OK", IDOK, 140, 17, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 89, 17, 50, 14 +} IDD_EDIT_STRING DIALOGEX 32, 24, 252, 84 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_NOIDLEMSG | DS_CONTEXTHELP | @@ -277,6 +287,10 @@ BEGIN ID_REGISTRY_IMPORTREGISTRYFILE " " ID_REGISTRY_EXPORTREGISTRYFILE " " + ID_REGISTRY_LOADHIVE + "Loads a hive file into the registry" + ID_REGISTRY_UNLOADHIVE + "Unloads a hive from the registry" ID_REGISTRY_CONNECTNETWORKREGISTRY "ϳ '" ID_REGISTRY_DISCONNECTNETWORKREGISTRY @@ -333,6 +347,8 @@ BEGIN IDS_MY_COMPUTER "̳ '" IDS_IMPORT_REG_FILE " " IDS_EXPORT_REG_FILE " " + IDS_LOAD_HIVE "Load Hive" + IDS_UNLOAD_HIVE "Unload Hive" IDS_INVALID_DWORD "( DWORD)" END diff --git a/base/applications/regedit/lang/zh-CN.rc b/base/applications/regedit/lang/zh-CN.rc index 0d20667cdd3..8e098469ad3 100644 --- a/base/applications/regedit/lang/zh-CN.rc +++ b/base/applications/regedit/lang/zh-CN.rc @@ -177,6 +177,16 @@ END /* * Dialog */ +IDD_LOADHIVE DIALOGEX DISCARDABLE 0, 0, 193, 34 +STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Hive" +FONT 8, "Ms Shell Dlg" +{ + LTEXT "&Key:", IDC_STATIC, 4, 4, 15, 8, SS_LEFT + EDITTEXT IDC_EDIT_KEY, 23, 2, 167, 13 + DEFPUSHBUTTON "OK", IDOK, 140, 17, 50, 14 + PUSHBUTTON "Cancel", IDCANCEL, 89, 17, 50, 14 +} IDD_EDIT_STRING DIALOGEX 32, 24, 252, 84 STYLE DS_SHELLFONT | DS_MODALFRAME | DS_NOIDLEMSG | DS_CONTEXTHELP | @@ -276,6 +286,10 @@ BEGIN ID_REGISTRY_IMPORTREGISTRYFILE "ļ뵽עС" ID_REGISTRY_EXPORTREGISTRYFILE "עȫ򲿷ֵļС" + ID_REGISTRY_LOADHIVE + "Loads a hive file into the registry" + ID_REGISTRY_UNLOADHIVE + "Unloads a hive from the registry" ID_REGISTRY_CONNECTNETWORKREGISTRY "ӵԶ̼ע" ID_REGISTRY_DISCONNECTNETWORKREGISTRY @@ -332,6 +346,8 @@ BEGIN IDS_MY_COMPUTER "My Computer" IDS_IMPORT_REG_FILE "עļ" IDS_EXPORT_REG_FILE "עļ" + IDS_LOAD_HIVE "Load Hive" + IDS_UNLOAD_HIVE "Unload Hive" IDS_INVALID_DWORD "(ȷ DWORD ֵ)" END diff --git a/base/applications/regedit/listview.c b/base/applications/regedit/listview.c index d7eac5974d2..fcf9f52c8fe 100644 --- a/base/applications/regedit/listview.c +++ b/base/applications/regedit/listview.c @@ -556,18 +556,12 @@ BOOL RefreshListView(HWND hwndLV, HKEY hKey, LPCTSTR keyPath) /* } */ /* dwValSize = max_val_size; */ while (RegEnumValue(hNewKey, dwIndex, ValName, &dwValNameLen, NULL, &dwValType, ValBuf, &dwValSize) == ERROR_SUCCESS) { - /* Remove unwanted path from key name */ - TCHAR *pLastBl = _tcsrchr(ValName, TEXT('\\')); - if (pLastBl != NULL) - ++pLastBl; - else - pLastBl = ValName; /* Add a terminating 0 character. Usually this is only necessary for strings. */ ValBuf[dwValSize] = 0; #ifdef UNICODE ValBuf[dwValSize + 1] = 0; #endif - AddEntryToList(hwndLV, pLastBl, dwValType, ValBuf, dwValSize, -1, TRUE); + AddEntryToList(hwndLV, ValName, dwValType, ValBuf, dwValSize, -1, TRUE); dwValNameLen = max_val_name_len; dwValSize = max_val_size; dwValType = 0L; diff --git a/base/applications/regedit/main.h b/base/applications/regedit/main.h index 4b837d9f84c..c8220495852 100644 --- a/base/applications/regedit/main.h +++ b/base/applications/regedit/main.h @@ -58,6 +58,7 @@ typedef struct { HWND hTreeWnd; HWND hListWnd; HWND hAddressBarWnd; + HWND hAddressBtnWnd; int nFocusPanel; /* 0: left 1: right */ int nSplitPos; WINDOWPLACEMENT pos; @@ -88,6 +89,9 @@ extern void ShowAboutBox(HWND hWnd); /* childwnd.c */ extern LRESULT CALLBACK ChildWndProc(HWND, UINT, WPARAM, LPARAM); +/* error.c */ +extern void ErrorMessageBox(HWND hWnd, LPCTSTR title, DWORD code); + /* find.c */ extern void FindDialog(HWND hWnd); extern BOOL FindNext(HWND hWnd); diff --git a/base/applications/regedit/resource.h b/base/applications/regedit/resource.h index 2190e0e3ed6..771d743ab9f 100644 --- a/base/applications/regedit/resource.h +++ b/base/applications/regedit/resource.h @@ -137,9 +137,11 @@ #define IDS_ERR_RENVAL_CAPTION 32856 #define IDS_ERR_RENVAL_TOEMPTY 32857 #define IDS_BAD_KEY 32858 +#define IDS_LOAD_HIVE 32859 +#define IDS_UNLOAD_HIVE 32860 -#define ID_EDIT_NEW_MULTISTRINGVALUE 32860 -#define ID_EDIT_NEW_EXPANDABLESTRINGVALUE 32861 +#define ID_EDIT_NEW_MULTISTRINGVALUE 32861 +#define ID_EDIT_NEW_EXPANDABLESTRINGVALUE 32862 #define ID_SWITCH_PANELS 32871 #define ID_EDIT_PERMISSIONS 32872 @@ -199,6 +201,8 @@ #define IDC_EXPORT_BRANCH 2009 #define IDC_EXPORT_BRANCH_TEXT 2010 +#define IDD_LOADHIVE 2500 +#define IDC_EDIT_KEY 2501 #define IDC_FAVORITENAME 2011 #define IDC_FAVORITESLIST 2012 diff --git a/base/applications/regedit/treeview.c b/base/applications/regedit/treeview.c index cd592036907..5e0727fdc61 100644 --- a/base/applications/regedit/treeview.c +++ b/base/applications/regedit/treeview.c @@ -633,7 +633,7 @@ BOOL SelectNode(HWND hwndTV, LPCTSTR keyPath) TVITEM tvi; /* Total no-good hack */ - if (!_tcsncmp(keyPath, _T("My Computer\\"), 12)) + if (!_tcsnicmp(keyPath, _T("My Computer\\"), 12)) keyPath += 12; hRoot = TreeView_GetRoot(hwndTV); @@ -647,17 +647,17 @@ BOOL SelectNode(HWND hwndTV, LPCTSTR keyPath) /* Special case for root to expand root key abbreviations */ if (hItem == hRoot) { - if (!_tcscmp(szPathPart, TEXT("HKCR"))) + if (!_tcsicmp(szPathPart, TEXT("HKCR"))) _tcscpy(szPathPart, TEXT("HKEY_CLASSES_ROOT")); - else if (!_tcscmp(szPathPart, TEXT("HKCU"))) + else if (!_tcsicmp(szPathPart, TEXT("HKCU"))) _tcscpy(szPathPart, TEXT("HKEY_CURRENT_USER")); - else if (!_tcscmp(szPathPart, TEXT("HKLM"))) + else if (!_tcsicmp(szPathPart, TEXT("HKLM"))) _tcscpy(szPathPart, TEXT("HKEY_LOCAL_MACHINE")); - else if (!_tcscmp(szPathPart, TEXT("HKU"))) + else if (!_tcsicmp(szPathPart, TEXT("HKU"))) _tcscpy(szPathPart, TEXT("HKEY_USERS")); - else if (!_tcscmp(szPathPart, TEXT("HKCC"))) + else if (!_tcsicmp(szPathPart, TEXT("HKCC"))) _tcscpy(szPathPart, TEXT("HKEY_CURRENT_CONFIG")); - else if (!_tcscmp(szPathPart, TEXT("HKDD"))) + else if (!_tcsicmp(szPathPart, TEXT("HKDD"))) _tcscpy(szPathPart, TEXT("HKEY_DYN_DATA")); } @@ -672,7 +672,7 @@ BOOL SelectNode(HWND hwndTV, LPCTSTR keyPath) (void)TreeView_GetItem(hwndTV, &tvi); - if (!_tcscmp(szBuffer, szPathPart)) + if (!_tcsicmp(szBuffer, szPathPart)) break; } diff --git a/base/applications/taskmgr/lang/ru-RU.rc b/base/applications/taskmgr/lang/ru-RU.rc index b632ad53c6a..97d9215ac84 100644 --- a/base/applications/taskmgr/lang/ru-RU.rc +++ b/base/applications/taskmgr/lang/ru-RU.rc @@ -641,10 +641,10 @@ BEGIN IDS_MSG_UNABLEDEBUGPROCESS " " IDS_MSG_WARNINGDEBUG ": .\n , ?" IDS_MSG_TASKMGRWARNING " " - IDS_MSG_WARNINGTERMINATING ": \n .\n ?" + IDS_MSG_WARNINGTERMINATING ": \n .\n ?" IDS_MSG_UNABLETERMINATEPRO " " IDS_MSG_UNABLECHANGEPRIORITY " " - IDS_MSG_WARNINGCHANGEPRIORITY ": .\n , ?" + IDS_MSG_WARNINGCHANGEPRIORITY ": .\n , ?" IDS_MSG_TRAYICONCPUUSAGE " : %d%%" IDS_STATUS_MEMUSAGE " : %dK / %dK" IDS_STATUS_CPUUSAGE " : %3d%%" diff --git a/base/setup/usetup/lang/sk-SK.h b/base/setup/usetup/lang/sk-SK.h index 73117a45a46..6c35e8da169 100644 --- a/base/setup/usetup/lang/sk-SK.h +++ b/base/setup/usetup/lang/sk-SK.h @@ -1,7 +1,7 @@ /* TRANSLATOR: Mrio Kamr /Mario Kacmar/ aka Kario (kario@szm.sk) * DATE OF TR: 22-01-2008 * Encoding : Latin II (852) - * LastChange: 31-05-2010 + * LastChange: 05-09-2010 */ #pragma once @@ -993,13 +993,13 @@ static MUI_ENTRY skSKBootLoaderEntries[] = { 8, 12, - "Install bootloader on the harddisk (MBR and VBR).", + "Naintalova zavdza systmu na pevn disk (MBR a VBR).", TEXT_STYLE_NORMAL }, { 8, 13, - "Install bootloader on the harddisk (VBR only).", + "Naintalova zavdza systmu na pevn disk (iba VBR).", TEXT_STYLE_NORMAL }, { diff --git a/base/shell/cmd/lang/sk-SK.rc b/base/shell/cmd/lang/sk-SK.rc index f436e5c6990..cec75b04ef3 100644 --- a/base/shell/cmd/lang/sk-SK.rc +++ b/base/shell/cmd/lang/sk-SK.rc @@ -1,9 +1,9 @@ /* Slovak translation for CMD * TRANSLATOR: Mrio Kamr /Mario Kacmar/ aka Kario (kario@szm.sk) * DATE OF TR: 21-03-2009 - * LastChange: 21-06-2009 + * LastChange: 10-08-2010 * _________________________________________________________________ - * NOTE : this file is not really translated (only scrap yet) + * NOTE : this file is not fully translated */ LANGUAGE LANG_SLOVAK, SUBLANG_DEFAULT @@ -118,7 +118,7 @@ dec hex name dec hex name\n\ 6 6 Yellow 14 E Bright Yellow\n\ 7 7 White 15 F Bright White\n" -STRING_COPY_HELP1, "Overwrite %s (Yes/No/All)? " +STRING_COPY_HELP1, "Prepsa %s (Yes/No/All)? " STRING_COPY_HELP2, "Skopruje jeden alebo viac sborov na in umiestnenie.\n\n\ COPY [/V][/Y|/-Y][/A|/B] source [/A|/B]\n\ @@ -141,7 +141,7 @@ STRING_DATE_HELP2, "\nZadajte nov STRING_DATE_HELP3, "\nZadajte nov dtum (rrrr%cmm%cdd): " -STRING_DATE_HELP4, "Displays or sets the date.\n\n\ +STRING_DATE_HELP4, "Zobraz alebo nastav dtum.\n\n\ DATE [/T][date]\n\n\ /T display only\n\n\ Type DATE without parameters to display the current date setting and\n\ @@ -469,7 +469,7 @@ STRING_TITLE_HELP, "Sets the window title for the command prompt window.\n\n\ TITLE [string]\n\n\ string Specifies the title for the command prompt window.\n" -STRING_TIME_HELP1, "Displays or sets the system time.\n\n\ +STRING_TIME_HELP1, "Zobraz alebo nastav systmov as.\n\n\ TIME [/T][time]\n\n\ /T display only\n\n\ Type TIME with no parameters to display the current time setting and a prompt\n\ @@ -547,18 +547,18 @@ STRING_WINDOW_HELP1, "change console window aspect\n\n\ WINDOW [/POS[=]left,top,width,heigth]\n\ [MIN|MAX|RESTORE] ['title']\n\n\ /POS specify window placement and dimensions\n\ -MIN minimize the window\n\ -MAX maximize the window\n\ -RESTORE restore the window" +MIN minimalizova okno\n\ +MAX maximalizujte okno\n\ +RESTORE obnovi okno" STRING_WINDOW_HELP2, "change console window aspect\n\n\ ACTIVATE 'window' [/POS[=]left,top,width,heigth]\n\ [MIN|MAX|RESTORE] ['title']\n\n\ window tile of window on which perform actions\n\ /POS specify window placement and dimensions\n\ -MIN minimize the window\n\ -MAX maximize the window\n\ -RESTORE restore the window\n\ +MIN minimalizova okno\n\ +MAX maximalizujte okno\n\ +RESTORE obnovi okno\n\ title new title\n" @@ -576,7 +576,7 @@ CLS Vyma CMD Starts a new instance of the ReactOS command interpreter.\n\ COLOR Sets the default console foreground and background colors.\n\ COPY Skopruje jeden alebo viac sborov na in umiestnenie.\n\ -DATE Displays or sets the date.\n\ +DATE Zobraz alebo nastav dtum.\n\ DELETE Deletes one or more files.\n\ DIR Displays a list of files and subdirectories in a directory.\n\ ECHO Displays messages, or turns command echoing on or off.\n\ @@ -590,8 +590,8 @@ HELP Provides Help information for ReactOS commands.\n\ HISTORY List all commands which has been used\n\ IF Performs conditional processing in batch programs.\n\ LABEL Creates, changes, or deletes the volume label of a disk.\n\ -MD Creates a directory.\n\ -MKDIR Creates a directory.\n\ +MD Vytvor adresr.\n\ +MKDIR Vytvor adresr.\n\ MKLINK Creates a filesystem link object.\n\ MOVE Moves one or more files from one directory to another\n\ directory.\n\ @@ -603,8 +603,8 @@ PROMPT Changes the command prompt.\n\ PUSHD Saves the current directory then changes it.\n\ RD Removes a directory.\n\ REM Records comments (remarks) in batch files.\n\ -REN Renames a file or files.\n\ -RENAME Renames a file or files.\n\ +REN Premenuje sbor alebo sbory.\n\ +RENAME Premenuje sbor alebo sbory.\n\ REPLACE Replaces files.\n\ RMDIR Removes a directory.\n\ SCREEN Move cursor and optionally print text.\n\ @@ -612,7 +612,7 @@ SET Displays, sets, or removes ReactOS environment variables.\n\ SHIFT Shifts the position of replaceable parameters in batch files.\n" STRING_HELP2, "START Starts a separate window to run a specified program or command.\n\ Executes command.\n\ -TIME Displays or sets the system time.\n\ +TIME Zobraz alebo nastav systmov as.\n\ TIMER Allow the use of ten stopwatches.\n\ TITLE Sets the window title for a CMD.EXE session.\n\ TYPE Displays the contents of a text file.\n\ @@ -651,9 +651,9 @@ STRING_COPY_ERROR3, "Error writing destination!\n" STRING_COPY_ERROR4, "Chyba: Zatia neimplementovan!\n" //Not implemented yet STRING_DATE_ERROR, "Neplatn dtum." STRING_DEL_ERROR5, "The file %s will be deleted! " -STRING_DEL_ERROR6, "Are you sure (Y/N)?" +STRING_DEL_ERROR6, "Ste si ist (Y/N)?" STRING_DEL_ERROR7, "Deleting: %s\n" -STRING_ERROR_ERROR1, "Unknown error! Error code: 0x%lx\n" +STRING_ERROR_ERROR1, "Neznma chyba! Kd chyby: 0x%lx\n" STRING_ERROR_ERROR2, "Syntax error" STRING_FOR_ERROR1, "'in' missing in for statement." STRING_FOR_ERROR2, "no brackets found." @@ -675,47 +675,47 @@ STRING_TIME_ERROR1, "Neplatn STRING_TYPE_ERROR1, "Invalid option '/%s'\n" -STRING_WINDOW_ERROR1, "window not found" +STRING_WINDOW_ERROR1, "okno sa nenalo" STRING_ERROR_PARAMETERF_ERROR, "Parameter format not correct - %c\n" -STRING_ERROR_INVALID_SWITCH, "Invalid switch - /%c\n" +STRING_ERROR_INVALID_SWITCH, "Neplatn prepna - /%c\n" STRING_ERROR_TOO_MANY_PARAMETERS, "Prli vea parametrov - %s\n" -STRING_ERROR_PATH_NOT_FOUND, "Path not found\n" -STRING_ERROR_FILE_NOT_FOUND, "File not found\n" +STRING_ERROR_PATH_NOT_FOUND, "Cesta sa nenala\n" +STRING_ERROR_FILE_NOT_FOUND, "Sbor sa nenaiel\n" STRING_ERROR_REQ_PARAM_MISSING, "Required parameter missing\n" STRING_ERROR_INVALID_DRIVE, "Invalid drive specification\n" STRING_ERROR_INVALID_PARAM_FORMAT, "Invalid parameter format - %s\n" -STRING_ERROR_BADCOMMAND, "Bad command or filename - %s\n" +STRING_ERROR_BADCOMMAND, "Chybn prkaz alebo nzov sboru - %s\n" STRING_ERROR_OUT_OF_MEMORY, "Chyba (z) nedostatku pamte.\n" //Out of memory error. -STRING_ERROR_CANNOTPIPE, "Error! Cannot pipe! Cannot open temporary file!\n" +STRING_ERROR_CANNOTPIPE, "Chyba! Cannot pipe! Cannot open temporary file!\n" STRING_ERROR_D_PAUSEMSG, "Pokraujte stlaenm ubovonho klvesu ..." -STRING_ERROR_DRIVER_NOT_READY, "Drive not ready" +STRING_ERROR_DRIVER_NOT_READY, "Jednotka nie je pripraven" STRING_PATH_ERROR, "CMD: Not in environment '%s'\n" -STRING_REPLACE_ERROR1, "Invalid switch - %s\n" -STRING_REPLACE_ERROR2, "Path not found - %s\n" +STRING_REPLACE_ERROR1, "Neplatn prepna - %s\n" +STRING_REPLACE_ERROR2, "Cesta sa nenala - %s\n" STRING_REPLACE_ERROR3, "The filename, directory name, or volume label syntax is incorrect.\n" STRING_REPLACE_ERROR4, "Invalid parameter combination\n" -STRING_REPLACE_ERROR5, "Access denied - %s\n" -STRING_REPLACE_ERROR6, "No files found - %s\n" +STRING_REPLACE_ERROR5, "Prstup zamietnut - %s\n" +STRING_REPLACE_ERROR6, "iadne sbory sa nenali - %s\n" STRING_REPLACE_ERROR7, "Extended Error 32\n" STRING_REACTOS_VERSION, "Operan systm ReactOS [Verzia %s-%s]\n" -STRING_CMD_SHELLINFO, "\nReactOS Command Line Interpreter\nVerzia %s %s" +STRING_CMD_SHELLINFO, "\nInterprter prkazovho riadku systmu ReactOS\nVerzia %s %s" STRING_VERSION_RUNVER, " running on %s" STRING_COPY_FILE , " %d sbor(ov) skoprovan(ch)\n" STRING_DELETE_WIPE, "wiped" STRING_FOR_ERROR, "bad variable specification." -STRING_SCREEN_COL, "invalid value for col" -STRING_SCREEN_ROW, "invalid value for row" +STRING_SCREEN_COL, "neplatn hodnota pre stpec" +STRING_SCREEN_ROW, "neplatn hodnota pre riadok" STRING_TIMER_TIME "Timer %d is %s: " STRING_MKLINK_CREATED_SYMBOLIC, "Symbolic link created for %s <<===>> %s\n" STRING_MKLINK_CREATED_HARD, "Hard link created for %s <<===>> %s\n" STRING_MKLINK_CREATED_JUNCTION, "Junction created for %s <<===>> %s\n" STRING_MORE, "Viac? " //"More? " -STRING_CANCEL_BATCH_FILE, "\r\nCtrl-Break pressed. Cancel batch file? (Yes/No/All) " +STRING_CANCEL_BATCH_FILE, "\r\nStlaen Ctrl-Break. Cancel batch file? (Yes/No/All) " STRING_INVALID_OPERAND, "Invalid operand." STRING_EXPECTED_CLOSE_PAREN, "Oakvan ')'." diff --git a/base/system/format/format.c b/base/system/format/format.c index 4eae18bb614..8c356e63e5d 100755 --- a/base/system/format/format.c +++ b/base/system/format/format.c @@ -48,6 +48,19 @@ SIZEDEFINITION LegalSizes[] = { }; +int LoadStringAndOem(HINSTANCE hInst, + UINT uID, + LPTSTR szStr, + int Siz +) +{ + TCHAR szTmp[RC_STRING_MAX_SIZE]; + int res = LoadString(hInst, uID, szTmp, sizeof(szTmp)); + CharToOem(szTmp, szStr); + return(res); +} + + //---------------------------------------------------------------------- // // PrintWin32Error @@ -171,7 +184,7 @@ FormatExCallback ( case PROGRESS: percent = (PDWORD) Argument; - LoadString( GetModuleHandle(NULL), STRING_COMPLETE, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_COMPLETE, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); _tprintf(szMsg, *percent); break; @@ -184,7 +197,7 @@ FormatExCallback ( status = (PBOOLEAN) Argument; if( *status == FALSE ) { - LoadString( GetModuleHandle(NULL), STRING_FORMAT_FAIL, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_FORMAT_FAIL, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); _tprintf("%s", szMsg); Error = TRUE; } @@ -203,7 +216,7 @@ FormatExCallback ( case UNKNOWND: case STRUCTUREPROGRESS: case CLUSTERSIZETOOSMALL: - LoadString( GetModuleHandle(NULL), STRING_NO_SUPPORT, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_NO_SUPPORT, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); _tprintf("%s", szMsg); return FALSE; } @@ -261,7 +274,7 @@ static VOID Usage( LPTSTR ProgramName ) BYTE dummy; BOOLEAN lastestVersion; - LoadString( GetModuleHandle(NULL), STRING_HELP, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_HELP, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); if (!LoadFMIFSEntryPoints()) { _tprintf(szMsg, ProgramName, _T("")); @@ -319,7 +332,7 @@ _tmain(int argc, TCHAR *argv[]) // Get function pointers // if( !LoadFMIFSEntryPoints()) { - LoadString( GetModuleHandle(NULL), STRING_FMIFS_FAIL, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_FMIFS_FAIL, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); _tprintf("%s", szMsg); return -1; } @@ -329,7 +342,7 @@ _tmain(int argc, TCHAR *argv[]) // if( (badArg = ParseCommandLine( argc, argv ))) { - LoadString( GetModuleHandle(NULL), STRING_UNKNOW_ARG, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_UNKNOW_ARG, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); _tprintf(szMsg, argv[badArg] ); Usage(argv[0]); @@ -341,7 +354,7 @@ _tmain(int argc, TCHAR *argv[]) // if( !Drive ) { - LoadString( GetModuleHandle(NULL), STRING_DRIVE_PARM, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_DRIVE_PARM, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); _tprintf(szMsg); Usage( argv[0] ); return -1; @@ -359,7 +372,7 @@ _tmain(int argc, TCHAR *argv[]) driveType = GetDriveType( RootDirectory ); if( driveType == 0 ) { - LoadString( GetModuleHandle(NULL), STRING_ERROR_DRIVE_TYPE, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_ERROR_DRIVE_TYPE, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); PrintWin32Error( szMsg, GetLastError()); return -1; } @@ -371,7 +384,7 @@ _tmain(int argc, TCHAR *argv[]) } if( driveType != DRIVE_FIXED ) { - LoadString( GetModuleHandle(NULL), STRING_INSERT_DISK, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_INSERT_DISK, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); _tprintf(szMsg, RootDirectory[0] ); _fgetts( input, sizeof(input)/2, stdin ); @@ -386,7 +399,7 @@ _tmain(int argc, TCHAR *argv[]) &serialNumber, &maxComponent, &flags, fileSystem, sizeof(fileSystem)/2)) { - LoadString( GetModuleHandle(NULL), STRING_NO_VOLUME, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_NO_VOLUME, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); PrintWin32Error( szMsg, GetLastError()); return -1; } @@ -396,11 +409,11 @@ _tmain(int argc, TCHAR *argv[]) &totalNumberOfBytes, &totalNumberOfFreeBytes )) { - LoadString( GetModuleHandle(NULL), STRING_NO_VOLUME_SIZE, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_NO_VOLUME_SIZE, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); PrintWin32Error( szMsg, GetLastError()); return -1; } - LoadString( GetModuleHandle(NULL), STRING_FILESYSTEM, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_FILESYSTEM, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); _tprintf(szMsg, fileSystem ); // @@ -412,7 +425,7 @@ _tmain(int argc, TCHAR *argv[]) while(1 ) { - LoadString( GetModuleHandle(NULL), STRING_LABEL_NAME_EDIT, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_LABEL_NAME_EDIT, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); _tprintf(szMsg, RootDirectory[0] ); _fgetts( input, sizeof(input)/2, stdin ); input[ _tcslen( input ) - 1] = 0; @@ -421,15 +434,15 @@ _tmain(int argc, TCHAR *argv[]) break; } - LoadString( GetModuleHandle(NULL), STRING_ERROR_LABEL, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_ERROR_LABEL, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); _tprintf("%s", szMsg); } } - LoadString( GetModuleHandle(NULL), STRING_YN_FORMAT, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_YN_FORMAT, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); _tprintf(szMsg, RootDirectory[0] ); - LoadString( GetModuleHandle(NULL), STRING_YES_NO_FAQ, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_YES_NO_FAQ, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); while( 1 ) { _fgetts( input, sizeof(input)/2, stdin ); @@ -460,7 +473,7 @@ _tmain(int argc, TCHAR *argv[]) } } else { - LoadString( GetModuleHandle(NULL), STRING_FAST_FMT, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_FAST_FMT, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); if( totalNumberOfBytes.QuadPart > 1024*1024*10 ) { _tprintf(_T("%s %luM\n"),szMsg, (DWORD) (totalNumberOfBytes.QuadPart/(1024*1024))); @@ -470,7 +483,7 @@ _tmain(int argc, TCHAR *argv[]) _tprintf(_T("%s %.2fM\n"),szMsg, ((float)(LONGLONG)totalNumberOfBytes.QuadPart)/(float)(1024.0*1024.0)); } - LoadString( GetModuleHandle(NULL), STRING_CREATE_FSYS, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_CREATE_FSYS, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); _tprintf("%s", szMsg); } @@ -488,7 +501,7 @@ _tmain(int argc, TCHAR *argv[]) ClusterSize, FormatExCallback ); #endif if( Error ) return -1; - LoadString( GetModuleHandle(NULL), STRING_FMT_COMPLETE, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_FMT_COMPLETE, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); _tprintf("%s", szMsg); // @@ -503,7 +516,7 @@ _tmain(int argc, TCHAR *argv[]) if( !EnableVolumeCompression( RootDirectory, TRUE )) { #endif - LoadString( GetModuleHandle(NULL), STRING_VOL_COMPRESS, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_VOL_COMPRESS, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); _tprintf("%s", szMsg); } } @@ -520,7 +533,7 @@ _tmain(int argc, TCHAR *argv[]) input[ _tcslen(input)-1] = 0; if( !SetVolumeLabel( RootDirectory, input )) { - LoadString( GetModuleHandle(NULL), STRING_NO_LABEL, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_NO_LABEL, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); PrintWin32Error(szMsg, GetLastError()); return -1; } @@ -531,7 +544,7 @@ _tmain(int argc, TCHAR *argv[]) &serialNumber, &maxComponent, &flags, fileSystem, sizeof(fileSystem)/2)) { - LoadString( GetModuleHandle(NULL), STRING_NO_VOLUME, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_NO_VOLUME, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); PrintWin32Error( szMsg, GetLastError()); return -1; } @@ -544,12 +557,12 @@ _tmain(int argc, TCHAR *argv[]) &totalNumberOfBytes, &totalNumberOfFreeBytes )) { - LoadString( GetModuleHandle(NULL), STRING_NO_VOLUME_SIZE, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_NO_VOLUME_SIZE, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); PrintWin32Error(szMsg, GetLastError()); return -1; } - LoadString( GetModuleHandle(NULL), STRING_FREE_SPACE, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_FREE_SPACE, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); _tprintf(szMsg, totalNumberOfBytes.QuadPart, totalNumberOfFreeBytes.QuadPart ); // @@ -560,11 +573,11 @@ _tmain(int argc, TCHAR *argv[]) &serialNumber, &maxComponent, &flags, fileSystem, sizeof(fileSystem)/2)) { - LoadString( GetModuleHandle(NULL), STRING_NO_VOLUME, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_NO_VOLUME, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); PrintWin32Error( szMsg, GetLastError()); return -1; } - LoadString( GetModuleHandle(NULL), STRING_SERIAL_NUMBER, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadStringAndOem( GetModuleHandle(NULL), STRING_SERIAL_NUMBER, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); _tprintf(szMsg, (unsigned int)(serialNumber >> 16), (unsigned int)(serialNumber & 0xFFFF) ); diff --git a/base/system/format/lang/sk-SK.rc b/base/system/format/lang/sk-SK.rc index deaee258367..c40b08fc2b6 100644 --- a/base/system/format/lang/sk-SK.rc +++ b/base/system/format/lang/sk-SK.rc @@ -1,6 +1,6 @@ /* TRANSLATOR : Mrio Kamr /Mario Kacmar/ aka Kario (kario@szm.sk) * DATE OF TR.: 15-02-2008 - * LAST CHANGE: 08-08-2008 + * LAST CHANGE: 10-08-2010 */ #include "resource.h" @@ -14,14 +14,14 @@ STRING_HELP, "Pou -FS:systm sborov Uruje typ sborovho systmu (%s).\n\ -V:menovka Uruje menovku zvzku.\n\ -Q Vykonva rchle formtovanie.\n\ - -A:vekos Overrides the default allocation unit size. Default settings\n\ - are strongly recommended for general use\n\ - NTFS supports 512, 1024, 2048, 4096, 8192, 16K, 32K, 64K.\n\ - FAT supports 8192, 16K, 32K, 64K, 128K, 256K.\n\ - NTFS compression is not supported for allocation unit sizes\n\ - above 4096.\n\ - -C Files created on the new volume will be compressed by\n\ - default.\n\n" + -A:vekos Prepe predvolen vekos alokanej jednotky. Pre veobecn\n\ + pouitie s drazne odporan predvolen nastavenia\n\ + NTFS podporuje 512, 1024, 2048, 4096, 8192, 16K, 32K, 64K.\n\ + FAT podporuje 8192, 16K, 32K, 64K, 128K, 256K.\n\ + NTFS kompresia nie je podporovan pre vekosti alokanej\n\ + jednotky nad 4096.\n\ + -C Sbory vytvoren na novom zvzku bud automaticky\n\ + komprimovan.\n\n" STRING_COMPLETE "Dokonen na %lu percent.\r" @@ -29,19 +29,19 @@ STRING_FORMAT_FAIL "FormatEx nebol schopn STRING_NO_SUPPORT "Opercia nie je podporovan" -STRING_FMIFS_FAIL "Could not located FMIFS entry points.\n\n" +STRING_FMIFS_FAIL "Nepodarilo sa lokalizova vstupn body FMIFS.\n\n" STRING_UNKNOW_ARG "Neznmy argument: %s\n" STRING_DRIVE_PARM "Chba nevyhnutn parameter jednotky.\n\n" -STRING_ERROR_DRIVE_TYPE "Could not get drive type" +STRING_ERROR_DRIVE_TYPE "Nemono zska typ jednotky" STRING_INSERT_DISK "Vlote nov disketu do jednotky %C:\na potom stlate ENTER..." -STRING_NO_VOLUME "Could not query volume" +STRING_NO_VOLUME "Nemono dotazova zvzok" -STRING_NO_VOLUME_SIZE "Could not query volume size" +STRING_NO_VOLUME_SIZE "Nemono dotazova vekos zvzku" STRING_FILESYSTEM "Typ systmu sborov je %s.\n" @@ -49,8 +49,8 @@ STRING_LABEL_NAME_EDIT "Vlo STRING_ERROR_LABEL "Bola zadan nesprvna menovka zvzku pre tto jednotku.\n" -STRING_YN_FORMAT "\nWARNING, ALL DATA ON NON_REMOVABLE DISK\n\ -DRIVE %C: WILL BE LOST!\nProceed with Format (A/N)? " +STRING_YN_FORMAT "\nUPOZORNENIE: VETKY DAJE NA NIE_VYMENITENEJ DISKOVEJ\n\ +JEDNOTKE %C: BUD STRATEN!\nPokraova s formtovanm (A/N)? " STRING_YES_NO_FAQ "AN" diff --git a/boot/freeldr/freeldr/debug.c b/boot/freeldr/freeldr/debug.c index daabc6715f3..08f49bdf515 100644 --- a/boot/freeldr/freeldr/debug.c +++ b/boot/freeldr/freeldr/debug.c @@ -66,6 +66,19 @@ ULONG BaudRate = 115200; BOOLEAN DebugStartOfLine = TRUE; +// We need to emulate these, because the original ones don't work in freeldr +int __cdecl wctomb(char *mbchar, wchar_t wchar) +{ + *mbchar = wchar; + return 1; +} + +int __cdecl mbtowc (wchar_t *wchar, const char *mbchar, size_t count) +{ + *wchar = *mbchar; + return 1; +} + VOID DebugInit(VOID) { if (DebugPort & RS232) diff --git a/dll/directx/ksuser/ksuser.c b/dll/directx/ksuser/ksuser.c index 8f62abf950d..1b231674693 100644 --- a/dll/directx/ksuser/ksuser.c +++ b/dll/directx/ksuser/ksuser.c @@ -1,34 +1,19 @@ /* - * KSUSER.DLL - ReactOS - * - * Copyright 2008 Magnus Olsen and Dmitry Chapyshev - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Kernel Streaming + * FILE: dll/directx/ksuser/ksuser.c + * PURPOSE: KS USER functions + * PROGRAMMER: Magnus Olsen and Dmitry Chapyshev and Johannes Anderwald */ - #include "ksuser.h" #define NDEBUG #include -NTSTATUS NTAPI KsiCreateObjectType( HANDLE hHandle, PVOID guidstr, PVOID Buffer, ULONG BufferSize, ACCESS_MASK DesiredAccess, PHANDLE phHandle); - NTSTATUS NTAPI KsiCreateObjectType( HANDLE hHandle, - PVOID IID, + LPWSTR ObjectType, PVOID Buffer, ULONG BufferSize, ACCESS_MASK DesiredAccess, @@ -42,31 +27,56 @@ KsiCreateObjectType( HANDLE hHandle, OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; - Length = wcslen(IID); + /* get length of object type */ + Length = wcslen(ObjectType); - TotalSize = (Length * sizeof(WCHAR)) + BufferSize + 4 * sizeof(WCHAR); + /* get length for request */ + TotalSize = (Length * sizeof(WCHAR)) + BufferSize; + /* append space for '\\'*/ + TotalSize += sizeof(WCHAR); + + /* allocate buffer */ pStr = HeapAlloc(GetProcessHeap(), 0, TotalSize); if (!pStr) - return STATUS_INSUFFICIENT_RESOURCES; - pStr[0] = L'\\'; - wcscpy(&pStr[1], (LPWSTR)IID); - pStr[Length+1] = L'\\'; - memcpy(&pStr[Length+2], Buffer, BufferSize); - pStr[Length+3+(BufferSize/sizeof(WCHAR))] = L'\0'; + { + /* out of memory */ + return ERROR_NOT_ENOUGH_MEMORY; + } - RtlInitUnicodeString(&ObjectName, pStr); + /* copy object type */ + wcscpy(pStr, ObjectType); + + /* append slash */ + pStr[Length] = L'\\'; + + /* append parameters */ + memcpy(&pStr[Length+1], Buffer, BufferSize); + + /* initialize object name */ + ObjectName.Buffer = pStr; ObjectName.Length = ObjectName.MaximumLength = TotalSize; + /* initialize object attributes */ InitializeObjectAttributes(&ObjectAttributes, &ObjectName, OBJ_CASE_INSENSITIVE, hHandle, NULL); + /* create the object */ Status = NtCreateFile(phHandle, DesiredAccess, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, 1, 0, NULL, 0); + + /* free buffer */ HeapFree(GetProcessHeap(), 0, pStr); + + /* check for success */ if (!NT_SUCCESS(Status)) { + /* failed zero handle */ *phHandle = INVALID_HANDLE_VALUE; + + /* convert error code */ Status = RtlNtStatusToDosError(Status); } + + /* done */ return Status; } diff --git a/dll/ntdll/ldr/utils.c b/dll/ntdll/ldr/utils.c index 30373f35848..1cfb8c85505 100644 --- a/dll/ntdll/ldr/utils.c +++ b/dll/ntdll/ldr/utils.c @@ -256,7 +256,7 @@ LdrpQueryAppPaths(IN PCWSTR ImageName) /* Copy it to the heap allocd memory */ Path = RtlAllocateHeap(RtlGetProcessHeap(), 0, - wcslen(SearchPathBuffer) * sizeof(WCHAR)); + (wcslen(SearchPathBuffer) + 1) * sizeof(WCHAR)); if (!Path) { diff --git a/dll/win32/advapi32/sec/lsa.c b/dll/win32/advapi32/sec/lsa.c index 604dcb26b98..246fbc5ae29 100644 --- a/dll/win32/advapi32/sec/lsa.c +++ b/dll/win32/advapi32/sec/lsa.c @@ -143,18 +143,37 @@ LsaDelete(IN LSA_HANDLE ObjectHandle) /* - * @unimplemented + * @implemented */ NTSTATUS WINAPI -LsaAddAccountRights( - LSA_HANDLE PolicyHandle, - PSID AccountSid, - PLSA_UNICODE_STRING UserRights, - ULONG CountOfRights) +LsaAddAccountRights(IN LSA_HANDLE PolicyHandle, + IN PSID AccountSid, + IN PLSA_UNICODE_STRING UserRights, + IN ULONG CountOfRights) { - FIXME("(%p,%p,%p,0x%08x) stub\n", PolicyHandle, AccountSid, UserRights, CountOfRights); - return STATUS_OBJECT_NAME_NOT_FOUND; + LSAPR_USER_RIGHT_SET UserRightSet; + NTSTATUS Status; + + TRACE("(%p,%p,%p,0x%08x) stub\n", PolicyHandle, AccountSid, UserRights, CountOfRights); + + UserRightSet.Entries = CountOfRights; + UserRightSet.UserRights = (PRPC_UNICODE_STRING)UserRights; + + RpcTryExcept + { + Status = LsarAddAccountRights((LSAPR_HANDLE)PolicyHandle, + (PRPC_SID)AccountSid, + &UserRightSet); + + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + Status = I_RpcMapWin32Status(RpcExceptionCode()); + } + RpcEndExcept; + + return Status; } @@ -265,6 +284,7 @@ LsaCreateTrustedDomainEx( return STATUS_SUCCESS; } + /* * @implemented */ @@ -291,16 +311,16 @@ LsaDeleteTrustedDomain(IN LSA_HANDLE PolicyHandle, return Status; } + /* * @implemented */ NTSTATUS WINAPI -LsaEnumerateAccountRights( - LSA_HANDLE PolicyHandle, - PSID AccountSid, - PLSA_UNICODE_STRING *UserRights, - PULONG CountOfRights) +LsaEnumerateAccountRights(IN LSA_HANDLE PolicyHandle, + IN PSID AccountSid, + OUT PLSA_UNICODE_STRING *UserRights, + OUT PULONG CountOfRights) { LSAPR_USER_RIGHT_SET UserRightsSet; NTSTATUS Status; @@ -333,6 +353,7 @@ LsaEnumerateAccountRights( return Status; } + /* * @unimplemented */ @@ -385,17 +406,19 @@ LsaEnumerateTrustedDomainsEx( return STATUS_SUCCESS; } + /* * @implemented */ NTSTATUS WINAPI -LsaFreeMemory(PVOID Buffer) +LsaFreeMemory(IN PVOID Buffer) { TRACE("(%p)\n", Buffer); return RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); } + /* * @implemented */ @@ -446,6 +469,7 @@ LsaLookupNames(IN LSA_HANDLE PolicyHandle, return Status; } + /* * @unimplemented */ @@ -470,8 +494,9 @@ LsaLookupNames2( return STATUS_NONE_MAPPED; } + /* - * @unmplemented + * @implemented */ NTSTATUS WINAPI @@ -504,6 +529,7 @@ LsaLookupPrivilegeName(IN LSA_HANDLE PolicyHandle, return Status; } + /* * @implemented */ @@ -535,6 +561,7 @@ LsaLookupPrivilegeValue(IN LSA_HANDLE PolicyHandle, return Status; } + /* * @implemented */ @@ -591,6 +618,7 @@ LsaLookupSids(IN LSA_HANDLE PolicyHandle, return Status; } + /****************************************************************************** * LsaNtStatusToWinError * @@ -599,7 +627,8 @@ LsaLookupSids(IN LSA_HANDLE PolicyHandle, * * @implemented */ -ULONG WINAPI +ULONG +WINAPI LsaNtStatusToWinError(IN NTSTATUS Status) { TRACE("(%lx)\n", Status); @@ -747,6 +776,7 @@ LsaQueryForestTrustInformation( return STATUS_NOT_IMPLEMENTED; } + /* * @implemented */ @@ -782,20 +812,6 @@ LsaQueryInformationPolicy(IN LSA_HANDLE PolicyHandle, return Status; } -/* - * @unimplemented - */ -NTSTATUS -WINAPI -LsaQueryTrustedDomainInfoByName( - LSA_HANDLE PolicyHandle, - PLSA_UNICODE_STRING TrustedDomainName, - TRUSTED_INFORMATION_CLASS InformationClass, - PVOID *Buffer) -{ - FIXME("(%p,%p,%d,%p) stub\n", PolicyHandle, TrustedDomainName, InformationClass, Buffer); - return STATUS_OBJECT_NAME_NOT_FOUND; -} /* * @unimplemented @@ -812,22 +828,78 @@ LsaQueryTrustedDomainInfo( return STATUS_OBJECT_NAME_NOT_FOUND; } + /* - * @unimplemented + * @implemented */ NTSTATUS WINAPI -LsaRemoveAccountRights( - LSA_HANDLE PolicyHandle, - PSID AccountSid, - BOOLEAN AllRights, - PLSA_UNICODE_STRING UserRights, - ULONG CountOfRights) +LsaQueryTrustedDomainInfoByName(IN LSA_HANDLE PolicyHandle, + IN PLSA_UNICODE_STRING TrustedDomainName, + IN TRUSTED_INFORMATION_CLASS InformationClass, + OUT PVOID *Buffer) { - FIXME("(%p,%p,%d,%p,0x%08x) stub\n", PolicyHandle, AccountSid, AllRights, UserRights, CountOfRights); + NTSTATUS Status; + + TRACE("(%p,%p,%d,%p)\n", PolicyHandle, TrustedDomainName, InformationClass, Buffer); + + if (InformationClass == TrustedDomainAuthInformationInternal || + InformationClass == TrustedDomainFullInformationInternal) + return STATUS_INVALID_INFO_CLASS; + + RpcTryExcept + { + Status = LsarQueryTrustedDomainInfoByName((LSAPR_HANDLE)PolicyHandle, + (PRPC_UNICODE_STRING)TrustedDomainName, + InformationClass, + (unsigned long *)Buffer); // Shuld be: (PLSAPR_POLICY_INFORMATION *)Buffer + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + Status = I_RpcMapWin32Status(RpcExceptionCode()); + } + RpcEndExcept; + + return Status; +} + + +/* + * @implemented + */ +NTSTATUS +WINAPI +LsaRemoveAccountRights(IN LSA_HANDLE PolicyHandle, + IN PSID AccountSid, + IN BOOLEAN AllRights, + IN PLSA_UNICODE_STRING UserRights, + IN ULONG CountOfRights) +{ + LSAPR_USER_RIGHT_SET UserRightSet; + NTSTATUS Status; + + TRACE("(%p,%p,%d,%p,0x%08x) stub\n", PolicyHandle, AccountSid, AllRights, UserRights, CountOfRights); + + UserRightSet.Entries = CountOfRights; + UserRightSet.UserRights = (PRPC_UNICODE_STRING)UserRights; + + RpcTryExcept + { + Status = LsarRemoveAccountRights((LSAPR_HANDLE)PolicyHandle, + (PRPC_SID)AccountSid, + AllRights, + &UserRightSet); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + Status = I_RpcMapWin32Status(RpcExceptionCode()); + } + RpcEndExcept; + return STATUS_SUCCESS; } + /* * @unimplemented */ diff --git a/dll/win32/kernel32/except/except.c b/dll/win32/kernel32/except/except.c index d46a51c4ed3..d57bd7a2e14 100644 --- a/dll/win32/kernel32/except/except.c +++ b/dll/win32/kernel32/except/except.c @@ -413,7 +413,7 @@ RaiseException(IN DWORD dwExceptionCode, } } - if (dwExceptionCode == 0xeedface) + if (dwExceptionCode == 0xeedface || dwExceptionCode == 0xeedfade) { DPRINT1("Delphi Exception at address: %p\n", ExceptionRecord.ExceptionInformation[0]); DPRINT1("Exception-Object: %p\n", ExceptionRecord.ExceptionInformation[1]); diff --git a/dll/win32/netcfgx/tcpipconf_notify.c b/dll/win32/netcfgx/tcpipconf_notify.c index 14b9a4ab2f4..5238d60c72e 100644 --- a/dll/win32/netcfgx/tcpipconf_notify.c +++ b/dll/win32/netcfgx/tcpipconf_notify.c @@ -2860,7 +2860,7 @@ Initialize(TcpipConfNotifyImpl * This) } pCurSettings->AutoconfigActive = pPerInfo->AutoconfigActive; } - CoTaskMemFree(pInfo); + CoTaskMemFree(pPerInfo); } } diff --git a/dll/win32/setupapi/cfgmgr.c b/dll/win32/setupapi/cfgmgr.c index ccff5e652cd..e995e8fbf3e 100644 --- a/dll/win32/setupapi/cfgmgr.c +++ b/dll/win32/setupapi/cfgmgr.c @@ -1987,10 +1987,47 @@ CONFIGRET WINAPI CM_Get_Device_ID_List_ExW( PCWSTR pszFilter, PWCHAR Buffer, ULONG BufferLen, ULONG ulFlags, HMACHINE hMachine) { - FIXME("%p %p %ld %ld %lx\n", + RPC_BINDING_HANDLE BindingHandle = NULL; + CONFIGRET ret; + + TRACE("%p %p %ld %ld %lx\n", pszFilter, Buffer, BufferLen, ulFlags, hMachine); - memset(Buffer,0,2); - return CR_SUCCESS; + + if (Buffer == NULL || BufferLen == 0) + return CR_INVALID_POINTER; + + if (ulFlags & ~CM_GETIDLIST_FILTER_BITS) + return CR_INVALID_FLAG; + + if (hMachine != NULL) + { + BindingHandle = ((PMACHINE_INFO)hMachine)->BindingHandle; + if (BindingHandle == NULL) + return CR_FAILURE; + } + else + { + if (!PnpGetLocalHandles(&BindingHandle, NULL)) + return CR_FAILURE; + } + + *Buffer = 0; + + RpcTryExcept + { + ret = PNP_GetDeviceList(BindingHandle, + pszFilter, + Buffer, + &BufferLen, + ulFlags); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + ret = RpcStatusToCmStatus(RpcExceptionCode()); + } + RpcEndExcept; + + return ret; } diff --git a/dll/win32/shell32/drive.c b/dll/win32/shell32/drive.c index 2e8cce57f75..8f70e74cc7f 100644 --- a/dll/win32/shell32/drive.c +++ b/dll/win32/shell32/drive.c @@ -395,7 +395,6 @@ InitializeGeneralDriveDialog(HWND hwndDlg, WCHAR * szDrive) { WCHAR szResult[128]; LONGLONG Result; -#ifdef IOCTL_DISK_GET_LENGTH_INFO_IMPLEMENTED HANDLE hVolume; DWORD BytesReturned = 0; @@ -404,16 +403,13 @@ InitializeGeneralDriveDialog(HWND hwndDlg, WCHAR * szDrive) if (hVolume != INVALID_HANDLE_VALUE) { ret = DeviceIoControl(hVolume, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, (LPVOID)&TotalNumberOfBytes, sizeof(ULARGE_INTEGER), &BytesReturned, NULL); - if (ret && StrFormatByteSizeW(LengthInformation.Length.QuadPart, szResult, sizeof(szResult) / sizeof(WCHAR))) + if (ret && StrFormatByteSizeW(TotalNumberOfBytes.QuadPart, szResult, sizeof(szResult) / sizeof(WCHAR))) SendDlgItemMessageW(hwndDlg, 14007, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szResult); CloseHandle(hVolume); } - TRACE("szResult %s hVOlume %p ret %d LengthInformation %ul Bytesreturned %d\n", debugstr_w(szResult), hVolume, ret, LengthInformation.Length.QuadPart, BytesReturned); -#else - if (ret && StrFormatByteSizeW(TotalNumberOfBytes.QuadPart, szResult, sizeof(szResult) / sizeof(WCHAR))) - SendDlgItemMessageW(hwndDlg, 14007, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szResult); -#endif + + TRACE("szResult %s hVOlume %p ret %d LengthInformation %ul Bytesreturned %d\n", debugstr_w(szResult), hVolume, ret, TotalNumberOfBytes.QuadPart, BytesReturned); if (StrFormatByteSizeW(TotalNumberOfBytes.QuadPart - FreeBytesAvailable.QuadPart, szResult, sizeof(szResult) / sizeof(WCHAR))) SendDlgItemMessageW(hwndDlg, 14003, WM_SETTEXT, (WPARAM)NULL, (LPARAM)szResult); diff --git a/dll/win32/shlwapi/CMakeLists.txt b/dll/win32/shlwapi/CMakeLists.txt index 0d8fe4c01cb..ffdbe034676 100644 --- a/dll/win32/shlwapi/CMakeLists.txt +++ b/dll/win32/shlwapi/CMakeLists.txt @@ -46,6 +46,7 @@ add_importlibs(shlwapi version shell32 kernel32 + msvcrt ntdll) diff --git a/dll/win32/user32/windows/hook.c b/dll/win32/user32/windows/hook.c index b848225741b..7df8e25ba81 100644 --- a/dll/win32/user32/windows/hook.c +++ b/dll/win32/user32/windows/hook.c @@ -154,49 +154,18 @@ CallMsgFilterA( LPMSG lpMsg, int nCode) { - BOOL ret = FALSE; - - if (nCode != HCBT_CREATEWND) ret = NtUserCallMsgFilter((LPMSG) lpMsg, nCode); - else + MSG Msg; + if (NtCurrentTeb()->Win32ThreadInfo && IsThreadHooked(GetWin32ClientInfo())) + { + if ( lpMsg->message & ~WM_MAXIMUM ) { - UNICODE_STRING usBuffer; - CBT_CREATEWNDA *cbtcwA = (CBT_CREATEWNDA *)lpMsg->lParam; - CBT_CREATEWNDW cbtcwW; - CREATESTRUCTW csW; - MSG Msg; - - Msg.hwnd = lpMsg->hwnd; - Msg.message = lpMsg->message; - Msg.time = lpMsg->time; - Msg.pt = lpMsg->pt; - Msg.wParam = lpMsg->wParam; - - cbtcwW.lpcs = &csW; - cbtcwW.hwndInsertAfter = cbtcwA->hwndInsertAfter; - csW = *(CREATESTRUCTW *)cbtcwA->lpcs; - - if (HIWORD(cbtcwA->lpcs->lpszName)) - { - RtlCreateUnicodeStringFromAsciiz(&usBuffer,cbtcwA->lpcs->lpszName); - csW.lpszName = usBuffer.Buffer; - } - if (HIWORD(cbtcwA->lpcs->lpszClass)) - { - RtlCreateUnicodeStringFromAsciiz(&usBuffer,cbtcwA->lpcs->lpszClass); - csW.lpszClass = usBuffer.Buffer; - } - Msg.lParam =(LPARAM) &cbtcwW; - - ret = NtUserCallMsgFilter((LPMSG)&Msg, nCode); - - lpMsg->time = Msg.time; - lpMsg->pt = Msg.pt; - - cbtcwA->hwndInsertAfter = cbtcwW.hwndInsertAfter; - if (HIWORD(csW.lpszName)) HeapFree( GetProcessHeap(), 0, (LPWSTR)csW.lpszName ); - if (HIWORD(csW.lpszClass)) HeapFree( GetProcessHeap(), 0, (LPWSTR)csW.lpszClass ); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; } - return ret; + RtlCopyMemory(&Msg, lpMsg, sizeof(MSG)); + return NtUserCallMsgFilter( &Msg, nCode); + } + return FALSE; } @@ -209,7 +178,18 @@ CallMsgFilterW( LPMSG lpMsg, int nCode) { - return NtUserCallMsgFilter((LPMSG) lpMsg, nCode); + MSG Msg; + if (NtCurrentTeb()->Win32ThreadInfo && IsThreadHooked(GetWin32ClientInfo())) + { + if ( lpMsg->message & ~WM_MAXIMUM ) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + RtlCopyMemory(&Msg, lpMsg, sizeof(MSG)); + return NtUserCallMsgFilter( &Msg, nCode); + } + return FALSE; } @@ -454,7 +434,7 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra = NULL; KBDLLHOOKSTRUCT KeyboardLlData, *pKeyboardLlData; MSLLHOOKSTRUCT MouseLlData, *pMouseLlData; - MSG Msg, *pMsg; + MSG *pcMsg, *pMsg; PMOUSEHOOKSTRUCT pMHook; CWPSTRUCT CWP, *pCWP; CWPRETSTRUCT CWPR, *pCWPR; @@ -471,18 +451,18 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) { case WH_CBT: { + //ERR("WH_CBT: Code %d\n", Common->Code); switch(Common->Code) { case HCBT_CREATEWND: CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS) ((PCHAR) Common + Common->lParam); - Csw = CbtCreatewndExtra->Cs; - Csw.lpszName = CbtCreatewndExtra->Cs.lpszName; - Csw.lpszClass = CbtCreatewndExtra->Cs.lpszClass; - wParam = Common->wParam; + RtlCopyMemory(&Csw, &CbtCreatewndExtra->Cs, sizeof(CREATESTRUCTW)); CbtCreatewndw.lpcs = &Csw; CbtCreatewndw.hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter; + wParam = Common->wParam; lParam = (LPARAM) &CbtCreatewndw; + //ERR("HCBT_CREATEWND: hWnd 0x%x Name 0x%x Class 0x%x\n", Common->wParam, Csw.lpszName, Csw.lpszClass); break; case HCBT_CLICKSKIPPED: pMHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam); @@ -524,7 +504,7 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) } else { - ERR("Common = 0x%x, Proc = 0x%x\n",Common,Common->Proc); + ERR("Null Proc! Common = 0x%x, Proc = 0x%x\n",Common,Common->Proc); } switch(Common->Code) { @@ -539,12 +519,13 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) break; } case WH_KEYBOARD_LL: - ERR("WH_KEYBOARD_LL: Code %d, wParam %d\n",Common->Code,Common->wParam); + //ERR("WH_KEYBOARD_LL: Code %d, wParam %d\n",Common->Code,Common->wParam); pKeyboardLlData = (PKBDLLHOOKSTRUCT)((PCHAR) Common + Common->lParam); RtlCopyMemory(&KeyboardLlData, pKeyboardLlData, sizeof(KBDLLHOOKSTRUCT)); Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &KeyboardLlData); break; case WH_MOUSE_LL: + //ERR("WH_MOUSE_LL: Code %d, wParam %d\n",Common->Code,Common->wParam); pMouseLlData = (PMSLLHOOKSTRUCT)((PCHAR) Common + Common->lParam); RtlCopyMemory(&MouseLlData, pMouseLlData, sizeof(MSLLHOOKSTRUCT)); Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &MouseLlData); @@ -562,7 +543,7 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) _SEH2_END; break; case WH_CALLWNDPROC: - ERR("WH_CALLWNDPROC: Code %d, wParam %d\n",Common->Code,Common->wParam); +// ERR("WH_CALLWNDPROC: Code %d, wParam %d\n",Common->Code,Common->wParam); pCWP = (PCWPSTRUCT)((PCHAR) Common + Common->lParam); RtlCopyMemory(&CWP, pCWP, sizeof(CWPSTRUCT)); Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &CWP); @@ -573,14 +554,15 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &CWPR); break; case WH_MSGFILTER: /* All SEH support */ - ERR("WH_MSGFILTER: Code %d, wParam %d\n",Common->Code,Common->wParam); case WH_SYSMSGFILTER: case WH_GETMESSAGE: pMsg = (PMSG)((PCHAR) Common + Common->lParam); - RtlCopyMemory(&Msg, pMsg, sizeof(MSG)); + pcMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MSG)); + RtlCopyMemory(pcMsg, pMsg, sizeof(MSG)); +// ERR("pMsg %d pcMsg %d\n",pMsg->message, pcMsg->message); _SEH2_TRY { - Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &Msg); + Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) pcMsg); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -588,11 +570,14 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) } _SEH2_END; if (!Hit && Common->HookId == WH_GETMESSAGE) - RtlCopyMemory(pMsg, &Msg, sizeof(MSG)); + RtlCopyMemory(pMsg, pcMsg, sizeof(MSG)); + HeapFree( GetProcessHeap(), 0, pcMsg ); break; - case WH_FOREGROUNDIDLE: /* <-- SEH support */ case WH_KEYBOARD: case WH_SHELL: + Result = Common->Proc(Common->Code, Common->wParam, Common->lParam); + break; + case WH_FOREGROUNDIDLE: /* <-- SEH support */ _SEH2_TRY { Result = Common->Proc(Common->Code, Common->wParam, Common->lParam); diff --git a/dll/win32/wdmaud.drv/legacy.c b/dll/win32/wdmaud.drv/legacy.c index cce93e8994a..88df5b2c080 100644 --- a/dll/win32/wdmaud.drv/legacy.c +++ b/dll/win32/wdmaud.drv/legacy.c @@ -171,7 +171,7 @@ WdmAudGetCapabilitiesByLegacy( { case MIXER_DEVICE_TYPE: { - LPMIXERCAPS MixerCaps = (LPMIXERCAPS) Capabilities; + LPMIXERCAPSW MixerCaps = (LPMIXERCAPSW) Capabilities; DeviceInfo.u.MixCaps.szPname[MAXPNAMELEN-1] = L'\0'; CopyWideString(MixerCaps->szPname, DeviceInfo.u.MixCaps.szPname); @@ -185,13 +185,13 @@ WdmAudGetCapabilitiesByLegacy( } case WAVE_OUT_DEVICE_TYPE : { - LPWAVEOUTCAPS WaveOutCaps = (LPWAVEOUTCAPS) Capabilities; + LPWAVEOUTCAPSW WaveOutCaps = (LPWAVEOUTCAPSW) Capabilities; DeviceInfo.u.WaveOutCaps.szPname[MAXPNAMELEN-1] = L'\0'; WaveOutCaps->wMid = DeviceInfo.u.WaveOutCaps.wMid; WaveOutCaps->wPid = DeviceInfo.u.WaveOutCaps.wPid; - WaveOutCaps->vDriverVersion = 0x0001; + WaveOutCaps->vDriverVersion = DeviceInfo.u.WaveOutCaps.vDriverVersion; CopyWideString(WaveOutCaps->szPname, DeviceInfo.u.WaveOutCaps.szPname); WaveOutCaps->dwFormats = DeviceInfo.u.WaveOutCaps.dwFormats; @@ -208,7 +208,7 @@ WdmAudGetCapabilitiesByLegacy( WaveInCaps->wMid = DeviceInfo.u.WaveInCaps.wMid; WaveInCaps->wPid = DeviceInfo.u.WaveInCaps.wPid; - WaveInCaps->vDriverVersion = 0x0001; + WaveInCaps->vDriverVersion = DeviceInfo.u.WaveInCaps.vDriverVersion; CopyWideString(WaveInCaps->szPname, DeviceInfo.u.WaveInCaps.szPname); WaveInCaps->dwFormats = DeviceInfo.u.WaveInCaps.dwFormats; @@ -216,6 +216,34 @@ WdmAudGetCapabilitiesByLegacy( WaveInCaps->wReserved1 = 0; break; } + case MIDI_IN_DEVICE_TYPE : + { + LPMIDIINCAPSW MidiInCaps = (LPMIDIINCAPSW)Capabilities; + + DeviceInfo.u.MidiInCaps.szPname[MAXPNAMELEN-1] = L'\0'; + + MidiInCaps->vDriverVersion = DeviceInfo.u.MidiInCaps.vDriverVersion; + MidiInCaps->wMid = DeviceInfo.u.MidiInCaps.wMid; + MidiInCaps->wPid = DeviceInfo.u.MidiInCaps.wPid; + MidiInCaps->dwSupport = DeviceInfo.u.MidiInCaps.dwSupport; + + CopyWideString(MidiInCaps->szPname, DeviceInfo.u.MidiInCaps.szPname); + break; + } + case MIDI_OUT_DEVICE_TYPE : + { + LPMIDIOUTCAPSW MidiOutCaps = (LPMIDIOUTCAPSW)Capabilities; + + DeviceInfo.u.MidiOutCaps.szPname[MAXPNAMELEN-1] = L'\0'; + + MidiOutCaps->vDriverVersion = DeviceInfo.u.MidiOutCaps.vDriverVersion; + MidiOutCaps->wMid = DeviceInfo.u.MidiOutCaps.wMid; + MidiOutCaps->wPid = DeviceInfo.u.MidiOutCaps.wPid; + MidiOutCaps->dwSupport = DeviceInfo.u.MidiOutCaps.dwSupport; + + CopyWideString(MidiOutCaps->szPname, DeviceInfo.u.MidiOutCaps.szPname); + break; + } } return MMSYSERR_NOERROR; diff --git a/dll/win32/wdmaud.drv/mmixer.c b/dll/win32/wdmaud.drv/mmixer.c index c47b651ecbd..a3a021ce29d 100644 --- a/dll/win32/wdmaud.drv/mmixer.c +++ b/dll/win32/wdmaud.drv/mmixer.c @@ -655,17 +655,46 @@ WdmAudSetWaveStateByMMixer( IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, IN BOOL bStart) { - if (bStart) + MMDEVICE_TYPE DeviceType; + PSOUND_DEVICE SoundDevice; + MMRESULT Result; + + Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); + SND_ASSERT( Result == MMSYSERR_NOERROR ); + + + Result = GetSoundDeviceType(SoundDevice, &DeviceType); + SND_ASSERT( Result == MMSYSERR_NOERROR ); + + if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE) { - MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE); - MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE); - MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_RUN); + if (bStart) + { + MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE); + MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE); + MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_RUN); + } + else + { + MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE); + MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE); + MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_STOP); + } } - else + else if (DeviceType == MIDI_IN_DEVICE_TYPE || DeviceType == MIDI_OUT_DEVICE_TYPE) { - MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE); - MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE); - MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_STOP); + if (bStart) + { + MMixerSetMidiStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE); + MMixerSetMidiStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE); + MMixerSetMidiStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_RUN); + } + else + { + MMixerSetMidiStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE); + MMixerSetMidiStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE); + MMixerSetMidiStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_STOP); + } } return MMSYSERR_NOERROR; diff --git a/dll/win32/wdmaud.drv/wdmaud.c b/dll/win32/wdmaud.drv/wdmaud.c index 67523ebe4bb..6255deef5d9 100644 --- a/dll/win32/wdmaud.drv/wdmaud.c +++ b/dll/win32/wdmaud.drv/wdmaud.c @@ -90,6 +90,12 @@ PopulateWdmDeviceList( FuncTable.CommitWaveBuffer = WriteFileEx_Remixer; #endif } + else if (DeviceType == MIDI_IN_DEVICE_TYPE || DeviceType == MIDI_OUT_DEVICE_TYPE) + { + FuncTable.SetWaveFormat = FUNC_NAME(WdmAudSetMixerDeviceFormat); + FuncTable.SetState = FUNC_NAME(WdmAudSetWaveState); + FuncTable.GetPos = FUNC_NAME(WdmAudGetWavePosition); + } SetSoundDeviceFunctionTable(SoundDevice, &FuncTable); } diff --git a/drivers/ksfilter/ks/irp.c b/drivers/ksfilter/ks/irp.c index 32ba84d9fd1..fb36d6df78a 100644 --- a/drivers/ksfilter/ks/irp.c +++ b/drivers/ksfilter/ks/irp.c @@ -661,6 +661,11 @@ KsProbeStreamIrp( if (Irp->RequestorMode == KernelMode || Irp->AssociatedIrp.SystemBuffer) { + if (Irp->RequestorMode == KernelMode) + { + /* no need to allocate stream header */ + Irp->AssociatedIrp.SystemBuffer = Irp->UserBuffer; + } AllocMdl: /* check if alloc mdl flag is passed */ if (!(ProbeFlags & KSPROBE_ALLOCATEMDL)) @@ -724,7 +729,16 @@ ProbeMdl: Mdl = Irp->MdlAddress; /* determine operation */ - Operation = (ProbeFlags & KSPROBE_STREAMWRITE) ? IoWriteAccess : IoReadAccess; + if (!(ProbeFlags & KSPROBE_STREAMWRITE) || (ProbeFlags & KSPROBE_MODIFY)) + { + /* operation is read / modify stream, need write access */ + Operation = IoWriteAccess; + } + else + { + /* operation is write to device, so we need read access */ + Operation = IoReadAccess; + } do { @@ -859,7 +873,8 @@ ProbeMdl: if (StreamHeader->FrameExtent) { /* allocate an mdl */ - Mdl = IoAllocateMdl(StreamHeader->Data, StreamHeader->FrameExtent, Irp->MdlAddress != NULL, TRUE, Irp); + ASSERT(Irp->MdlAddress == NULL); + Mdl = IoAllocateMdl(StreamHeader->Data, StreamHeader->FrameExtent, FALSE, TRUE, Irp); if (!Mdl) { /* not enough memory */ @@ -880,18 +895,14 @@ ProbeMdl: /* now probe the allocated mdl's */ if (!NT_SUCCESS(Status)) - { + { DPRINT("Status %x\n", Status); return Status; - } + } else goto ProbeMdl; } -#if 0 - // HACK for MS PORTCLS - HeaderSize = Length; -#endif /* probe user mode buffers */ if (Length && ( (!HeaderSize) || (Length % HeaderSize == 0) || ((ProbeFlags & KSPROBE_ALLOWFORMATCHANGE) && (Length == sizeof(KSSTREAM_HEADER))) ) ) { @@ -904,6 +915,9 @@ ProbeMdl: return STATUS_INSUFFICIENT_RESOURCES; } + /* mark irp as buffered so that changes the stream headers are propagated back */ + Irp->Flags = IRP_DEALLOCATE_BUFFER | IRP_BUFFERED_IO; + _SEH2_TRY { if (ProbeFlags & KSPROBE_STREAMWRITE) @@ -917,6 +931,9 @@ ProbeMdl: { /* stream reads means writing */ ProbeForWrite(Irp->UserBuffer, Length, sizeof(UCHAR)); + + /* set input operation flags */ + Irp->Flags |= IRP_INPUT_OPERATION; } /* copy stream buffer */ @@ -1360,7 +1377,7 @@ KsRemoveIrpFromCancelableQueue( PLIST_ENTRY CurEntry; KIRQL OldIrql; - //DPRINT("KsRemoveIrpFromCancelableQueue ListHead %p SpinLock %p ListLocation %x RemovalOperation %x\n", QueueHead, SpinLock, ListLocation, RemovalOperation); + DPRINT("KsRemoveIrpFromCancelableQueue ListHead %p SpinLock %p ListLocation %x RemovalOperation %x\n", QueueHead, SpinLock, ListLocation, RemovalOperation); /* check parameters */ if (!QueueHead || !SpinLock) @@ -1619,19 +1636,32 @@ KsAddIrpToCancelableQueue( PIO_STACK_LOCATION IoStack; KIRQL OldLevel; - DPRINT("KsAddIrpToCancelableQueue QueueHead %p SpinLock %p Irp %p ListLocation %x DriverCancel %p\n", QueueHead, SpinLock, Irp, ListLocation, DriverCancel); /* check for required parameters */ if (!QueueHead || !SpinLock || !Irp) return; + /* get current irp stack */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + DPRINT("KsAddIrpToCancelableQueue QueueHead %p SpinLock %p Irp %p ListLocation %x DriverCancel %p\n", QueueHead, SpinLock, Irp, ListLocation, DriverCancel); + + // HACK for ms portcls + if (IoStack->MajorFunction == IRP_MJ_CREATE) + { + // complete the request + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return; + } + + if (!DriverCancel) { /* default to KsCancelRoutine */ DriverCancel = KsCancelRoutine; } - /* get current irp stack */ - IoStack = IoGetCurrentIrpStackLocation(Irp); /* acquire spinlock */ KeAcquireSpinLock(SpinLock, &OldLevel); @@ -1720,22 +1750,24 @@ FindMatchingCreateItem( PLIST_ENTRY Entry; PCREATE_ITEM_ENTRY CreateItemEntry; UNICODE_STRING RefString; + LPWSTR pStr; + /* get terminator */ + pStr = wcschr(Buffer, L'\\'); -#ifndef MS_KSUSER - /* remove '\' slash */ - Buffer++; - BufferSize -= sizeof(WCHAR); -#endif + /* sanity check */ + ASSERT(pStr != NULL); - if (!wcschr(Buffer, L'\\')) + if (pStr == Buffer) { - RtlInitUnicodeString(&RefString, Buffer); + // skip slash + RtlInitUnicodeString(&RefString, ++pStr); } else { + // request is for pin / node / allocator RefString.Buffer = Buffer; - RefString.Length = RefString.MaximumLength = ((ULONG_PTR)wcschr(Buffer, L'\\') - (ULONG_PTR)Buffer); + RefString.Length = BufferSize = RefString.MaximumLength = ((ULONG_PTR)pStr - (ULONG_PTR)Buffer); } /* point to first entry */ @@ -1963,12 +1995,6 @@ KsSetMajorFunctionHandler( IN ULONG MajorFunction) { DPRINT("KsSetMajorFunctionHandler Function %x\n", MajorFunction); -#if 1 - // HACK - // for MS PORTCLS - // - DriverObject->MajorFunction[IRP_MJ_CREATE] = KspCreate; -#endif switch ( MajorFunction ) { @@ -2006,7 +2032,7 @@ KsDispatchIrp( PKSIDEVICE_HEADER DeviceHeader; PDEVICE_EXTENSION DeviceExtension; - //DPRINT("KsDispatchIrp DeviceObject %p Irp %p\n", DeviceObject, Irp); + DPRINT("KsDispatchIrp DeviceObject %p Irp %p\n", DeviceObject, Irp); /* get device extension */ DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; diff --git a/drivers/ksfilter/ks/misc.c b/drivers/ksfilter/ks/misc.c index d6b1e26078a..057103d3414 100644 --- a/drivers/ksfilter/ks/misc.c +++ b/drivers/ksfilter/ks/misc.c @@ -95,7 +95,7 @@ KspCopyCreateRequest( IoStack = IoGetCurrentIrpStackLocation(Irp); /* get object class length */ - ObjectLength = (wcslen(ObjectClass) + 2) * sizeof(WCHAR); + ObjectLength = (wcslen(ObjectClass) + 1) * sizeof(WCHAR); /* check for minium length requirement */ if (ObjectLength + *Size > IoStack->FileObject->FileName.MaximumLength) diff --git a/drivers/ksfilter/ks/topology.c b/drivers/ksfilter/ks/topology.c index 321f0ba59ed..49ae6599a7a 100644 --- a/drivers/ksfilter/ks/topology.c +++ b/drivers/ksfilter/ks/topology.c @@ -27,7 +27,7 @@ KspCreateObjectType( /* calculate request length */ Name.Length = 0; - Name.MaximumLength = wcslen(ObjectType) * sizeof(WCHAR) + CreateParametersSize + 2 * sizeof(WCHAR); + Name.MaximumLength = wcslen(ObjectType) * sizeof(WCHAR) + CreateParametersSize + 1 * sizeof(WCHAR); Name.MaximumLength += sizeof(WCHAR); /* acquire request buffer */ Name.Buffer = AllocateItem(NonPagedPool, Name.MaximumLength); @@ -38,11 +38,10 @@ KspCreateObjectType( return STATUS_INSUFFICIENT_RESOURCES; } - /* build a request which looks like \{ObjectClass}\CreateParameters + /* build a request which looks like {ObjectClass}\CreateParameters * For pins the parent is the reference string used in registration * For clocks it is full path for pin\{ClockGuid}\ClockCreateParams */ - RtlAppendUnicodeToString(&Name, L"\\"); RtlAppendUnicodeToString(&Name, ObjectType); RtlAppendUnicodeToString(&Name, L"\\"); /* append create parameters */ diff --git a/drivers/storage/class/disk/disk.c b/drivers/storage/class/disk/disk.c index a7085c43631..5d62cfac63a 100644 --- a/drivers/storage/class/disk/disk.c +++ b/drivers/storage/class/disk/disk.c @@ -2808,6 +2808,53 @@ Return Value: // Fall through and let the class driver process the request. // + case IOCTL_DISK_GET_LENGTH_INFO: + + // + // Validate buffer length. + // + + if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < + sizeof(GET_LENGTH_INFORMATION)) { + status = STATUS_BUFFER_TOO_SMALL; + + } else { + + PGET_LENGTH_INFORMATION lengthInformation = Irp->AssociatedIrp.SystemBuffer; + + // + // Update the geometry in case it has changed. + // + + status = UpdateRemovableGeometry (DeviceObject, Irp); + + if (!NT_SUCCESS(status)) { + + // + // Note the drive is not ready. + // + + diskData->DriveNotReady = TRUE; + break; + } + + // + // Note the drive is now ready. + // + + diskData->DriveNotReady = FALSE; + + // + // Output data, and return + // + + lengthInformation->Length.QuadPart = deviceExtension->PartitionLength.QuadPart; + status = STATUS_SUCCESS; + Irp->IoStatus.Information = sizeof(GET_LENGTH_INFORMATION); + } + + break; + default: // diff --git a/drivers/wdm/audio/backpln/portcls/guids.cpp b/drivers/wdm/audio/backpln/portcls/guids.cpp index 34fed4811fb..f311bcc9431 100644 --- a/drivers/wdm/audio/backpln/portcls/guids.cpp +++ b/drivers/wdm/audio/backpln/portcls/guids.cpp @@ -35,7 +35,6 @@ const GUID CLSID_MiniportDriverUart = {0xb4c90ae1L, 0x5791, 0x11d0, {0x86, 0xf9, const GUID CLSID_MiniportDriverFmSynth = {0xb4c90ae0L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}}; const GUID CLSID_MiniportDriverFmSynthWithVol = {0xe5a3c139L, 0xf0f2, 0x11d1, {0x81, 0xaf, 0x00, 0x60, 0x08, 0x33, 0x16, 0xc1}}; - const GUID IID_IPort = {0xb4c90a25L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}}; const GUID IID_IDrmPort = {0x286D3DF8L, 0xCA22, 0x4E2E, {0xB9, 0xBC, 0x20, 0xB4, 0xF0, 0xE2, 0x01, 0xCE}}; const GUID IID_IDrmPort2 = {0x1ACCE59CL, 0x7311, 0x4B6B, {0x9F, 0xBA, 0xCC, 0x3B, 0xA5, 0x9A, 0xCD, 0xCE}}; @@ -46,6 +45,7 @@ const GUID IID_IPortMidi = {0xb4c90a40L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0 const GUID IID_IPortDMus = {0xc096df9cL, 0xfb09, 0x11d1, {0x81, 0xb0, 0x00, 0x60, 0x08, 0x33, 0x16, 0xc1}}; const GUID IID_IAdapterPowerManagement = {0x793417D0L, 0x35FE, 0x11D1, {0xAD, 0x08, 0x00, 0xA0, 0xC9, 0x0A, 0xB1, 0xB0}}; +const GUID IID_IMiniport = {0xb4c90a24, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}}; const GUID IID_IMiniportWaveCyclic = {0xb4c90a27L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}}; const GUID IID_IPortWaveCyclic = {0xb4c90a26L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}}; const GUID IID_IResourceList = {0x22C6AC60L, 0x851B, 0x11D0, {0x9A, 0x7F, 0x00, 0xAA, 0x00, 0x38, 0xAC, 0xFE}}; @@ -59,6 +59,7 @@ const GUID IID_IServiceSink = {0x22C6AC64L, 0x851B, 0x11D0, {0x9A, 0x7F, 0x00, 0 const GUID IID_IPortClsVersion = {0x7D89A7BBL, 0x869B, 0x4567, {0x8D, 0xBE, 0x1E, 0x16, 0x8C, 0xC8, 0x53, 0xDE}}; const GUID IID_IUnknown = {0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x46}}; const GUID IID_IPortEvents = {0xA80F29C4L, 0x5498, 0x11D2, {0x95, 0xD9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}}; +const GUID IID_IMusicTechnology = {0x80396C3C, 0xCBCB, 0x409B, {0x9F, 0x65, 0x4F, 0x1E, 0x74, 0x67, 0xCD, 0xAF}}; const GUID KSNAME_PIN = {0x146F1A80, 0x4791, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; const GUID IID_IDrmAudioStream = {0x1915c967, 0x3299, 0x48cb, {0xa3, 0xe4, 0x69, 0xfd, 0x1d, 0x1b, 0x30, 0x6e}}; @@ -69,8 +70,14 @@ const GUID KS_CATEGORY_AUDIO = {0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00 const GUID KS_CATEGORY_RENDER = {0x65E8773E, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; const GUID KS_CATEGORY_CAPTURE = {0x65E8773D, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; const GUID KS_CATEGORY_TOPOLOGY = {0xDDA54A40, 0x1E4C, 0x11D1, {0xA0, 0x50, 0x40, 0x57, 0x05, 0xC1, 0x00, 0x00}}; +const GUID KSCATEGORY_AUDIO = {0x6994AD04L, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; +const GUID KSNODETYPE_SYNTHESIZER = {0xDFF220F3, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; +const GUID KSAUDFNAME_DMUSIC_MPU_IN = {0xB2EC0A7D, 0xBAC9, 0x11d2, {0xB7, 0xA8, 0x00, 0x60, 0x08, 0x33, 0x16, 0xC1}}; +const GUID KSAUDFNAME_MIDI = {0x185FEDF8L, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}}; +const GUID KSAUDFNAME_DMUSIC_MPU_OUT = {0xA4DF0EB5, 0xBAC9, 0x11d2, {0xB7, 0xA8, 0x00, 0x60, 0x08, 0x33, 0x16, 0xC1}}; + const GUID KSDATAFORMAT_TYPE_AUDIO = {0x73647561L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; const GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}}; @@ -80,13 +87,16 @@ const GUID KSPROPSETID_Pin = {0x8C134960L, 0x51AD, 0x11CF, { const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; const GUID KSPROPTYPESETID_General = {0x97E99BA0L, 0xBDEA, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; const GUID KSPROPSETID_DrmAudioStream = {0x2f2c8ddd, 0x4198, 0x4fac, {0xba, 0x29, 0x61, 0xbb, 0x05, 0xb7, 0xde, 0x06}}; +const GUID KSPROPSETID_Synth = {0xfedfae25L, 0xe46e, 0x11d1, {0xaa, 0xce, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12}}; +const GUID KSPROPSETID_Audio = {0x45FFAAA0L, 0x6E1B, 0x11D0, {0xBC, 0xF2, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}; const GUID KSEVENTSETID_LoopedStreaming = {0x4682B940L, 0xC6EF, 0x11D0, {0x96, 0xD8, 0x00, 0xAA, 0x00, 0x51, 0xE5, 0x1D}}; const GUID KSEVENTSETID_Connection = {0x7f4bcbe0L, 0x9ea5, 0x11cf, {0xa5, 0xd6, 0x28, 0xdb, 0x04, 0xc1, 0x00, 0x00}}; const GUID IID_IAllocatorMXF = {0xa5f0d62cL, 0xb30f, 0x11d2, {0xb7, 0xa3, 0x00, 0x60, 0x08, 0x33, 0x16, 0xc1}}; +const GUID IID_IMXF = {0xc096df9e, 0xfb09, 0x11d1, {0x81, 0xb0, 0x00, 0x60, 0x08, 0x33, 0x16, 0xc1}}; +const GUID KSMUSIC_TECHNOLOGY_PORT = {0x86C92E60, 0x62E8, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; -const GUID KSPROPSETID_Audio = {0x45FFAAA0L, 0x6E1B, 0x11D0, {0xBC, 0xF2, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}; /// /// undocumented guids diff --git a/drivers/wdm/audio/backpln/portcls/interfaces.hpp b/drivers/wdm/audio/backpln/portcls/interfaces.hpp index 248bcbe9012..9163a6a78d6 100644 --- a/drivers/wdm/audio/backpln/portcls/interfaces.hpp +++ b/drivers/wdm/audio/backpln/portcls/interfaces.hpp @@ -319,9 +319,11 @@ DECLARE_INTERFACE_(IIrpQueue, IUnknown) DEFINE_ABSTRACT_UNKNOWN() STDMETHOD_(NTSTATUS, Init)(THIS_ - IN KSPIN_CONNECT *ConnectDetails, + IN PKSPIN_CONNECT ConnectDetails, + IN PKSPIN_DESCRIPTOR Descriptor, IN ULONG FrameSize, - IN ULONG Alignment) PURE; + IN ULONG Alignment, + IN ULONG TagSupportEnabled) PURE; STDMETHOD_(NTSTATUS, AddMapping)(THIS_ IN PIRP Irp, @@ -360,9 +362,11 @@ DECLARE_INTERFACE_(IIrpQueue, IUnknown) #define IMP_IIrpQueue \ STDMETHODIMP_(NTSTATUS) Init(THIS_ \ - IN KSPIN_CONNECT *ConnectDetails, \ + IN PKSPIN_CONNECT ConnectDetails, \ + IN PKSPIN_DESCRIPTOR Descriptor, \ IN ULONG FrameSize, \ - IN ULONG Alignment); \ + IN ULONG Alignment, \ + IN ULONG TagSupportEnabled); \ \ STDMETHODIMP_(NTSTATUS) AddMapping(THIS_ \ IN PIRP Irp, \ diff --git a/drivers/wdm/audio/backpln/portcls/interrupt.cpp b/drivers/wdm/audio/backpln/portcls/interrupt.cpp index af4b0c18cdf..30d78568550 100644 --- a/drivers/wdm/audio/backpln/portcls/interrupt.cpp +++ b/drivers/wdm/audio/backpln/portcls/interrupt.cpp @@ -232,21 +232,21 @@ CInterruptSync::Connect() if (IsListEmpty(&m_ServiceRoutines)) return STATUS_UNSUCCESSFUL; - DPRINT("Vector %u Level %u Flags %x Affinity %x\n", Descriptor->u.Interrupt.Vector, Descriptor->u.Interrupt.Level, Descriptor->Flags, Descriptor->u.Interrupt.Affinity); + DPRINT1("Vector %u Level %u Flags %x Affinity %x\n", Descriptor->u.Interrupt.Vector, Descriptor->u.Interrupt.Level, Descriptor->Flags, Descriptor->u.Interrupt.Affinity); Status = IoConnectInterrupt(&m_Interrupt, IInterruptServiceRoutine, (PVOID)this, - &m_Lock, + NULL, //&m_Lock, Descriptor->u.Interrupt.Vector, (KIRQL)Descriptor->u.Interrupt.Level, (KIRQL)Descriptor->u.Interrupt.Level, (KINTERRUPT_MODE)(Descriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED), - (Descriptor->Flags != CM_RESOURCE_INTERRUPT_LATCHED), + (Descriptor->ShareDisposition != CmResourceShareDeviceExclusive), Descriptor->u.Interrupt.Affinity, FALSE); - DPRINT("CInterruptSync::Connect result %x\n", Status); + DPRINT1("CInterruptSync::Connect result %x\n", Status); return Status; } diff --git a/drivers/wdm/audio/backpln/portcls/irpstream.cpp b/drivers/wdm/audio/backpln/portcls/irpstream.cpp index a19a6da6e5c..2c6b88ccf28 100644 --- a/drivers/wdm/audio/backpln/portcls/irpstream.cpp +++ b/drivers/wdm/audio/backpln/portcls/irpstream.cpp @@ -35,31 +35,40 @@ public: virtual ~CIrpQueue(){} protected: - volatile ULONG m_CurrentOffset; - LONG m_NumMappings; - ULONG m_NumDataAvailable; + PKSPIN_CONNECT m_ConnectDetails; + PKSPIN_DESCRIPTOR m_Descriptor; + KSPIN_LOCK m_IrpListLock; LIST_ENTRY m_IrpList; LIST_ENTRY m_FreeIrpList; - PIRP m_Irp; ULONG m_OutOfMapping; ULONG m_MaxFrameSize; ULONG m_Alignment; + ULONG m_TagSupportEnabled; + ULONG m_NumDataAvailable; + volatile ULONG m_CurrentOffset; + + PIRP m_Irp; + LONG m_Ref; }; -#define OFFSET_HEADERINDEX (0) -#define OFFSET_STREAMHEADER (2) -#define OFFSET_HEADERCOUNT (3) +typedef struct +{ + ULONG StreamHeaderCount; + ULONG StreamHeaderIndex; + ULONG TotalStreamData; + PKSSTREAM_HEADER CurStreamHeader; + PVOID * Data; + PVOID * Tags; +}KSSTREAM_DATA, *PKSSTREAM_DATA; -#define STREAMHEADER_INDEX(Irp) (PtrToUlong(Irp->Tail.Overlay.DriverContext[OFFSET_HEADERINDEX])) -#define STREAMHEADER_COUNT(Irp) (PtrToUlong(Irp->Tail.Overlay.DriverContext[OFFSET_HEADERCOUNT])) -#define STREAMHEADER_CURRENT(Irp) (Irp->Tail.Overlay.DriverContext[OFFSET_STREAMHEADER]) +#define STREAM_DATA_OFFSET (0) NTSTATUS @@ -81,13 +90,17 @@ CIrpQueue::QueryInterface( NTSTATUS NTAPI CIrpQueue::Init( - IN KSPIN_CONNECT *ConnectDetails, + IN PKSPIN_CONNECT ConnectDetails, + IN PKSPIN_DESCRIPTOR Descriptor, IN ULONG FrameSize, - IN ULONG Alignment) + IN ULONG Alignment, + IN ULONG TagSupportEnabled) { m_ConnectDetails = ConnectDetails; + m_Descriptor = Descriptor; m_MaxFrameSize = FrameSize; m_Alignment = Alignment; + m_TagSupportEnabled = TagSupportEnabled; InitializeListHead(&m_IrpList); InitializeListHead(&m_FreeIrpList); @@ -103,110 +116,158 @@ CIrpQueue::AddMapping( OUT PULONG Data) { PKSSTREAM_HEADER Header; - NTSTATUS Status = STATUS_SUCCESS; + NTSTATUS Status = STATUS_UNSUCCESSFUL; PIO_STACK_LOCATION IoStack; - ULONG NumHeaders, NumData, Index; + ULONG Index, Length; PMDL Mdl; + PKSSTREAM_DATA StreamData; PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); + // allocate stream data + StreamData = (PKSSTREAM_DATA)AllocateItem(NonPagedPool, sizeof(KSSTREAM_DATA), TAG_PORTCLASS); + if (!StreamData) + { + // not enough memory + return STATUS_INSUFFICIENT_RESOURCES; + } + // get current irp stack location IoStack = IoGetCurrentIrpStackLocation(Irp); - if (!Irp->MdlAddress) + // lets probe the irp + if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM) { - // ioctl from KsStudio - // Wdmaud already probes buffers, therefore no need to probe it again - // probe the stream irp - if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM) - Status = KsProbeStreamIrp(Irp, KSSTREAM_WRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, 0); - else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM) - Status = KsProbeStreamIrp(Irp, KSSTREAM_READ | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, 0); - else - PC_ASSERT(0); + // probe IOCTL_KS_WRITE_STREAM + Status = KsProbeStreamIrp(Irp, KSSTREAM_WRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, 0); + } + else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM) + { + // probe IOCTL_KS_READ_STREAM + Status = KsProbeStreamIrp(Irp, KSSTREAM_READ | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, 0); + } - // check for success - if (!NT_SUCCESS(Status)) - { - DPRINT("KsProbeStreamIrp failed with %x\n", Status); - return Status; - } + // check for success + if (!NT_SUCCESS(Status)) + { + // irp probing failed + FreeItem(StreamData, TAG_PORTCLASS); + return Status; } // get first stream header + Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer; - if (Irp->RequestorMode == UserMode) - Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer; - else - Header = (PKSSTREAM_HEADER)Irp->UserBuffer; + // store header + StreamData->CurStreamHeader = Header; // sanity check PC_ASSERT(Header); - // calculate num headers - NumHeaders = IoStack->Parameters.DeviceIoControl.OutputBufferLength / Header->Size; + // first calculate the numbers of stream headers + Length = IoStack->Parameters.DeviceIoControl.OutputBufferLength; - // assume headers of same length - PC_ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength % Header->Size == 0); - - - // get first audio buffer - Mdl = Irp->MdlAddress; - // sanity check - PC_ASSERT(Mdl); - - // store the current stream header - Irp->Tail.Overlay.DriverContext[OFFSET_STREAMHEADER] = (PVOID)Header; - // store header count - Irp->Tail.Overlay.DriverContext[OFFSET_HEADERCOUNT] = UlongToPtr(NumHeaders); - - // store current header index - Irp->Tail.Overlay.DriverContext[OFFSET_HEADERINDEX] = UlongToPtr(0); - - NumData = 0; - // prepare all headers - for(Index = 0; Index < NumHeaders; Index++) + do { - // sanity checks - PC_ASSERT(Header); - PC_ASSERT(Mdl); + /* subtract size */ + Length -= Header->Size; - if (Irp->RequestorMode == UserMode) + /* increment header count */ + StreamData->StreamHeaderCount++; + + if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_IN) { - Header->Data = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority); + // irp sink + StreamData->TotalStreamData += Header->DataUsed; + } + else + { + // irp source + StreamData->TotalStreamData += Header->FrameExtent; } - if (!Header->Data) - { - // insufficient resources - ExFreePool(Irp->AssociatedIrp.SystemBuffer); - Irp->AssociatedIrp.SystemBuffer = NULL; - // complete and forget request - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - Irp->IoStatus.Information = 0; + /* move to next header */ + Header = (PKSSTREAM_HEADER)((ULONG_PTR)Header + Header->Size); - IoCompleteRequest(Irp, IO_NO_INCREMENT); + }while(Length); + + // sanity check + ASSERT(StreamData->StreamHeaderCount); + + // allocate array for storing the pointers of the data */ + StreamData->Data = (PVOID*)AllocateItem(NonPagedPool, sizeof(PVOID) * StreamData->StreamHeaderCount, TAG_PORTCLASS); + if (!StreamData->Data) + { + // out of memory + FreeItem(StreamData, TAG_PORTCLASS); + + // done + return STATUS_INSUFFICIENT_RESOURCES; + } + + if (m_TagSupportEnabled) + { + // allocate array for storing the pointers of the data */ + StreamData->Tags = (PVOID*)AllocateItem(NonPagedPool, sizeof(PVOID) * StreamData->StreamHeaderCount, TAG_PORTCLASS); + if (!StreamData->Data) + { + // out of memory + FreeItem(StreamData->Data, TAG_PORTCLASS); + FreeItem(StreamData, TAG_PORTCLASS); + + // done + return STATUS_INSUFFICIENT_RESOURCES; + } + } + + + // now get a system address for the user buffers + Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer; + Mdl = Irp->MdlAddress; + + for(Index = 0; Index < StreamData->StreamHeaderCount; Index++) + { + /* get system address */ + StreamData->Data[Index] = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority); + + /* check for success */ + if (!StreamData->Data[Index]) + { + // out of resources + FreeItem(StreamData->Data, TAG_PORTCLASS); + + if (m_TagSupportEnabled) + { + // free tag array + FreeItem(StreamData->Tags, TAG_PORTCLASS); + } + + FreeItem(StreamData, TAG_PORTCLASS); + // done return STATUS_INSUFFICIENT_RESOURCES; } - // increment num mappings - InterlockedIncrement(&m_NumMappings); + if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_IN) + { + // increment available data + InterlockedExchangeAdd((PLONG)&m_NumDataAvailable, Header->DataUsed); + } + else if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_OUT) + { + // increment available data + InterlockedExchangeAdd((PLONG)&m_NumDataAvailable, Header->FrameExtent); + } - // increment available data - InterlockedExchangeAdd((PLONG)&m_NumDataAvailable, - (max(Header->DataUsed, Header->FrameExtent))); - - NumData += max(Header->DataUsed, Header->FrameExtent); - - // move to next header - Header = (PKSSTREAM_HEADER)((ULONG_PTR)Header + Header->Size); - - // move to next mdl + // move to next header / mdl Mdl = Mdl->Next; + Header = (PKSSTREAM_HEADER)((ULONG_PTR)Header + Header->Size); + } - DPRINT("StreamHeaders %u NumData %u FrameSize %u NumDataAvailable %u\n", NumHeaders, NumData, m_MaxFrameSize, m_NumDataAvailable); - *Data = NumData; + // store stream data + Irp->Tail.Overlay.DriverContext[STREAM_DATA_OFFSET] = (PVOID)StreamData; + + *Data = StreamData->TotalStreamData; // mark irp as pending IoMarkIrpPending(Irp); @@ -218,7 +279,7 @@ CIrpQueue::AddMapping( m_OutOfMapping = FALSE; // done - return Status; + return STATUS_SUCCESS; } NTSTATUS @@ -229,8 +290,7 @@ CIrpQueue::GetMapping( { PIRP Irp; ULONG Offset; - //PIO_STACK_LOCATION IoStack; - PKSSTREAM_HEADER StreamHeader; + PKSSTREAM_DATA StreamData; // check if there is an irp in the partially processed if (m_Irp) @@ -247,6 +307,7 @@ CIrpQueue::GetMapping( m_Irp->IoStatus.Status = STATUS_CANCELLED; IoCompleteRequest(m_Irp, IO_NO_INCREMENT); m_Irp = Irp = NULL; + m_CurrentOffset = 0; } } else @@ -259,26 +320,32 @@ CIrpQueue::GetMapping( if (!Irp) { // no irp buffer available - DPRINT("NoIrp\n"); return STATUS_UNSUCCESSFUL; } - // get stream header - StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2]; + // get stream data + StreamData = (PKSSTREAM_DATA)Irp->Tail.Overlay.DriverContext[STREAM_DATA_OFFSET]; // sanity check - PC_ASSERT(StreamHeader); + PC_ASSERT(StreamData); - // store buffersize - if (StreamHeader->DataUsed) - *BufferSize = StreamHeader->DataUsed - Offset; + // get buffer size + if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_IN) + { + // sink pin + *BufferSize = StreamData->CurStreamHeader->DataUsed - Offset; + } else - *BufferSize = StreamHeader->FrameExtent - Offset; + { + // source pin + *BufferSize = StreamData->CurStreamHeader->FrameExtent - Offset; + } + // sanity check PC_ASSERT(*BufferSize); // store buffer - *Buffer = &((PUCHAR)StreamHeader->Data)[Offset]; + *Buffer = &((PUCHAR)StreamData->Data[StreamData->StreamHeaderIndex])[Offset]; // unset flag that no irps are available m_OutOfMapping = FALSE; @@ -291,107 +358,119 @@ NTAPI CIrpQueue::UpdateMapping( IN ULONG BytesWritten) { - PKSSTREAM_HEADER StreamHeader; - ULONG Size, NumData, Index; - - if (!m_Irp) - { - // silence buffer was used - return; - } - - // get stream header - StreamHeader = (PKSSTREAM_HEADER)STREAMHEADER_CURRENT(m_Irp); + PKSSTREAM_DATA StreamData; + ULONG Size; + PIO_STACK_LOCATION IoStack; // sanity check - // ASSERT(StreamHeader); + ASSERT(m_Irp); + + // get stream data + StreamData = (PKSSTREAM_DATA)m_Irp->Tail.Overlay.DriverContext[STREAM_DATA_OFFSET]; + + // sanity check + ASSERT(StreamData); // add to current offset InterlockedExchangeAdd((volatile PLONG)&m_CurrentOffset, (LONG)BytesWritten); + if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_OUT) + { + // store written bytes (source pin) + StreamData->CurStreamHeader->DataUsed += BytesWritten; + } + // decrement available data counter m_NumDataAvailable -= BytesWritten; - if (StreamHeader->DataUsed) - Size = StreamHeader->DataUsed; + // get audio buffer size + if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_OUT) + Size = StreamData->CurStreamHeader->FrameExtent; else - Size = StreamHeader->FrameExtent; + Size = StreamData->CurStreamHeader->DataUsed; + // sanity check PC_ASSERT(Size); if (m_CurrentOffset >= Size) { - if (STREAMHEADER_INDEX(m_Irp) + 1 < STREAMHEADER_COUNT(m_Irp)) + // sanity check + PC_ASSERT(Size == m_CurrentOffset); + + if (StreamData->StreamHeaderIndex + 1 < StreamData->StreamHeaderCount) { - // the irp has at least one more stream header - m_Irp->Tail.Overlay.DriverContext[OFFSET_HEADERINDEX] = UlongToPtr(STREAMHEADER_INDEX(m_Irp) + 1); + // move to next stream header + StreamData->CurStreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamData->CurStreamHeader + StreamData->CurStreamHeader->Size); - // get next stream header - StreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamHeader + StreamHeader->Size); + // increment stream header index + StreamData->StreamHeaderIndex++; - // store next stream header - STREAMHEADER_CURRENT(m_Irp) = (PVOID)StreamHeader; - - // reset current offset + // reset offset m_CurrentOffset = 0; // done return; } - // irp has been processed completly - - NumData = 0; - if (m_Irp->RequestorMode == KernelMode) - StreamHeader = (PKSSTREAM_HEADER)m_Irp->UserBuffer; - else - StreamHeader = (PKSSTREAM_HEADER)m_Irp->AssociatedIrp.SystemBuffer; - - // loop all stream headers - for(Index = 0; Index < STREAMHEADER_COUNT(m_Irp); Index++) - { - PC_ASSERT(StreamHeader); - - // add size of buffer - // depends on if the buffer is input / output - if (StreamHeader->DataUsed) - Size = StreamHeader->DataUsed; - else - Size = StreamHeader->FrameExtent; - - // increment size - NumData += Size; - - // get next stream header - StreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamHeader + StreamHeader->Size); - } - + // + // all stream buffers have been played + // check if this is a looped buffer + // if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING) { // looped streaming repeat the buffers untill // the caller decides to stop the streams // reset stream header index - m_Irp->Tail.Overlay.DriverContext[OFFSET_HEADERINDEX] = UlongToPtr(0); + StreamData->StreamHeaderIndex = 0; + + // reset stream header + StreamData->CurStreamHeader = (PKSSTREAM_HEADER)m_Irp->AssociatedIrp.SystemBuffer; + + // increment available data + InterlockedExchangeAdd((PLONG)&m_NumDataAvailable, StreamData->TotalStreamData); + // re-insert irp KsAddIrpToCancelableQueue(&m_IrpList, &m_IrpListLock, m_Irp, KsListEntryTail, NULL); + // clear current irp m_Irp = NULL; + // reset offset m_CurrentOffset = 0; - // increment available data - InterlockedExchangeAdd((PLONG)&m_NumDataAvailable, NumData); + // done return; } + // free stream data array + FreeItem(StreamData->Data, TAG_PORTCLASS); + + if (m_TagSupportEnabled) + { + // free tag array + FreeItem(StreamData->Tags, TAG_PORTCLASS); + } + + // free stream data + FreeItem(StreamData, TAG_PORTCLASS); + + // get io stack + IoStack = IoGetCurrentIrpStackLocation(m_Irp); + + // store operation status m_Irp->IoStatus.Status = STATUS_SUCCESS; - m_Irp->IoStatus.Information = NumData; + + // store operation length + m_Irp->IoStatus.Information = IoStack->Parameters.DeviceIoControl.OutputBufferLength; // complete the request IoCompleteRequest(m_Irp, IO_SOUND_INCREMENT); + // remove irp as it is complete m_Irp = NULL; + + // reset offset m_CurrentOffset = 0; } } @@ -408,6 +487,8 @@ BOOL NTAPI CIrpQueue::CancelBuffers() { + //TODO: own cancel routine + // is there an active irp if (m_Irp) { @@ -419,8 +500,7 @@ CIrpQueue::CancelBuffers() // cancel all irps KsCancelIo(&m_IrpList, &m_IrpListLock); - // reset number of mappings - m_NumMappings = 0; + // reset number of data available m_NumDataAvailable = 0; @@ -437,44 +517,83 @@ CIrpQueue::GetMappingWithTag( OUT PULONG ByteCount, OUT PULONG Flags) { - PKSSTREAM_HEADER StreamHeader; - PIRP Irp; + PKSSTREAM_DATA StreamData; - *Flags = 0; + /* sanity checks */ PC_ASSERT(Tag != NULL); + PC_ASSERT(PhysicalAddress); + PC_ASSERT(VirtualAddress); + PC_ASSERT(ByteCount); + PC_ASSERT(Flags); - // get an irp from the queue - Irp = KsRemoveIrpFromCancelableQueue(&m_IrpList, &m_IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem); + if (!m_Irp) + { + // get an irp from the queue + m_Irp = KsRemoveIrpFromCancelableQueue(&m_IrpList, &m_IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem); + } // check if there is an irp - if (!Irp) + if (!m_Irp) { // no irp available m_OutOfMapping = TRUE; return STATUS_NOT_FOUND; } - //FIXME support more than one stream header - PC_ASSERT(STREAMHEADER_COUNT(Irp) == 1); + // get stream data + StreamData = (PKSSTREAM_DATA)m_Irp->Tail.Overlay.DriverContext[STREAM_DATA_OFFSET]; - // HACK get stream header - StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2]; + // sanity check + PC_ASSERT(StreamData->StreamHeaderIndex < StreamData->StreamHeaderCount); - // store mapping in the free list - ExInterlockedInsertTailList(&m_FreeIrpList, &Irp->Tail.Overlay.ListEntry, &m_IrpListLock); - - // return mapping - *PhysicalAddress = MmGetPhysicalAddress(StreamHeader->Data); - *VirtualAddress = StreamHeader->Data; - *ByteCount = StreamHeader->DataUsed; - - // decrement mapping count - InterlockedDecrement(&m_NumMappings); - // decrement num data available - m_NumDataAvailable -= StreamHeader->DataUsed; + // setup mapping + *PhysicalAddress = MmGetPhysicalAddress(StreamData->Data[StreamData->StreamHeaderIndex]); + *VirtualAddress = StreamData->Data[StreamData->StreamHeaderIndex]; // store tag in irp - Irp->Tail.Overlay.DriverContext[3] = Tag; + StreamData->Tags[StreamData->StreamHeaderIndex] = Tag; + + // mapping size + if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_IN) + { + // sink pin + *ByteCount = StreamData->CurStreamHeader->DataUsed; + + // decrement num data available + m_NumDataAvailable -= StreamData->CurStreamHeader->DataUsed; + } + else + { + // source pin + *ByteCount = StreamData->CurStreamHeader->FrameExtent; + + // decrement num data available + m_NumDataAvailable -= StreamData->CurStreamHeader->FrameExtent; + } + + if (StreamData->StreamHeaderIndex + 1 == StreamData->StreamHeaderCount) + { + // last mapping + *Flags = 1; + + // insert mapping into free list + ExInterlockedInsertTailList(&m_FreeIrpList, &m_Irp->Tail.Overlay.ListEntry, &m_IrpListLock); + + // clear irp + m_Irp = NULL; + + } + else + { + // one more mapping in the irp + *Flags = 0; + + // increment header index + StreamData->StreamHeaderIndex++; + + // move to next header + StreamData->CurStreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamData->CurStreamHeader + StreamData->CurStreamHeader->Size); + } // done return STATUS_SUCCESS; @@ -487,34 +606,123 @@ CIrpQueue::ReleaseMappingWithTag( { PIRP Irp; PLIST_ENTRY CurEntry; - PKSSTREAM_HEADER StreamHeader; + PKSSTREAM_DATA StreamData; + PIO_STACK_LOCATION IoStack; + ULONG Index; - DPRINT("CIrpQueue::ReleaseMappingWithTag Tag %p\n", Tag); + // first check if there is an active irp + if (m_Irp) + { + // now check if there are already used mappings + StreamData = (PKSSTREAM_DATA)m_Irp->Tail.Overlay.DriverContext[STREAM_DATA_OFFSET]; + + if (StreamData->StreamHeaderIndex) + { + // check if the released mapping is one current processed irps + for(Index = 0; Index < StreamData->StreamHeaderIndex; Index++) + { + // check if it is the same tag + if (StreamData->Tags[Index] == Tag) + { + // mark mapping as released + StreamData->Tags[Index] = NULL; + + // done + return STATUS_SUCCESS; + } + + } + } + } // remove irp from used list CurEntry = ExInterlockedRemoveHeadList(&m_FreeIrpList, &m_IrpListLock); + // sanity check PC_ASSERT(CurEntry); // get irp from list entry Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry); - // HACK get stream header - StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2]; + // get stream data + StreamData = (PKSSTREAM_DATA)Irp->Tail.Overlay.DriverContext[STREAM_DATA_OFFSET]; - // driver must release items in the same order - PC_ASSERT(Irp->Tail.Overlay.DriverContext[3] == Tag); + // sanity check + PC_ASSERT(StreamData->StreamHeaderIndex + 1 == StreamData->StreamHeaderCount); - // irp has been processed completly - Irp->IoStatus.Status = STATUS_SUCCESS; + // check if the released mapping is one of these + for(Index = 0; Index < StreamData->StreamHeaderCount; Index++) + { + if (StreamData->Tags[Index] == Tag) + { + // mark mapping as released + StreamData->Tags[Index] = NULL; - // frame extend contains the original request size, DataUsed contains the real buffer size - // is different when kmixer performs channel conversion, upsampling etc - - Irp->IoStatus.Information = StreamHeader->FrameExtent; + // done + break; + } + else + { + // + // we assume that mappings are released in the same order as they have been acquired + // therefore if the current mapping is not the searched one, it must have been already + // released + // + PC_ASSERT(StreamData->Tags[Index] == NULL); + } + } - // complete the request - IoCompleteRequest(Irp, IO_SOUND_INCREMENT); + // check if this is the last one released mapping + if (Index + 1 == StreamData->StreamHeaderCount) + { + // last mapping released + // now check if this is a looped buffer + if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING) + { + // looped buffers are not completed when they have been played + // they are completed when the stream is set to stop + + // reset stream header index + StreamData->StreamHeaderIndex = 0; + + // reset stream header + StreamData->CurStreamHeader = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer; + + // increment available data + InterlockedExchangeAdd((PLONG)&m_NumDataAvailable, StreamData->TotalStreamData); + + // re-insert irp + KsAddIrpToCancelableQueue(&m_IrpList, &m_IrpListLock, Irp, KsListEntryTail, NULL); + + // done + return STATUS_SUCCESS; + } + + // + // time to complete non looped buffer + // + + // free stream data array + FreeItem(StreamData->Data, TAG_PORTCLASS); + + // free stream tags array + FreeItem(StreamData->Tags, TAG_PORTCLASS); + + // free stream data + FreeItem(StreamData, TAG_PORTCLASS); + + // get io stack + IoStack = IoGetCurrentIrpStackLocation(Irp); + + // store operation status + Irp->IoStatus.Status = STATUS_SUCCESS; + + // store operation length + Irp->IoStatus.Information = IoStack->Parameters.DeviceIoControl.OutputBufferLength; + + // complete the request + IoCompleteRequest(Irp, IO_SOUND_INCREMENT); + } return STATUS_SUCCESS; } @@ -542,38 +750,18 @@ CIrpQueue::GetAcquiredTagRange( { KIRQL OldLevel; BOOLEAN Ret = FALSE; - PIRP Irp; - PLIST_ENTRY CurEntry; + //PIRP Irp; + //PLIST_ENTRY CurEntry; + //PKSSTREAM_DATA StreamData; + // lock list KeAcquireSpinLock(&m_IrpListLock, &OldLevel); - if (!IsListEmpty(&m_FreeIrpList)) - { - // get first entry - CurEntry = RemoveHeadList(&m_FreeIrpList); - // get irp from list entry - Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry); + // initialize to zero + *FirstTag = NULL; + *LastTag = NULL; - // get tag of first acquired buffer - *FirstTag = Irp->Tail.Overlay.DriverContext[3]; - - // put back irp - InsertHeadList(&m_FreeIrpList, &Irp->Tail.Overlay.ListEntry); - - // get last entry - CurEntry = RemoveTailList(&m_FreeIrpList); - // get irp from list entry - Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry); - - // get tag of first acquired buffer - *LastTag = Irp->Tail.Overlay.DriverContext[3]; - - // put back irp - InsertTailList(&m_FreeIrpList, &Irp->Tail.Overlay.ListEntry); - - // indicate success - Ret = TRUE; - } + UNIMPLEMENTED; // release lock KeReleaseSpinLock(&m_IrpListLock, OldLevel); diff --git a/drivers/wdm/audio/backpln/portcls/miniport_dmus.cpp b/drivers/wdm/audio/backpln/portcls/miniport_dmus.cpp index 65d32ed5a33..7d40c68b37d 100644 --- a/drivers/wdm/audio/backpln/portcls/miniport_dmus.cpp +++ b/drivers/wdm/audio/backpln/portcls/miniport_dmus.cpp @@ -1,15 +1,102 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Kernel Streaming - * FILE: drivers/wdm/audio/backpln/portcls/miniport_dmus.cpp - * PURPOSE: DirectMusic miniport - * PROGRAMMER: Johannes Anderwald +/***************************************************************************** + * miniport_dmus.cpp - UART miniport implementation + ***************************************************************************** + * Copyright (c) 1997-2000 Microsoft Corporation. All Rights Reserved. + * + * Feb 98 MartinP -- based on UART, began deltas for DirectMusic. + * */ + #include "private.hpp" -class CMiniportDMus : public IMiniportDMus +// + for absolute / - for relative + +#define kOneMillisec (10 * 1000) + +// +// MPU401 ports +// +#define MPU401_REG_STATUS 0x01 // Status register +#define MPU401_DRR 0x40 // Output ready (for command or data) + // if this bit is set, the output FIFO is FULL +#define MPU401_DSR 0x80 // Input ready (for data) + // if this bit is set, the input FIFO is empty + +#define MPU401_REG_DATA 0x00 // Data in +#define MPU401_REG_COMMAND 0x01 // Commands +#define MPU401_CMD_RESET 0xFF // Reset command +#define MPU401_CMD_UART 0x3F // Switch to UART mod + + +/***************************************************************************** + * Prototypes + */ + +NTSTATUS NTAPI InitMPU(IN PINTERRUPTSYNC InterruptSync,IN PVOID DynamicContext); +NTSTATUS ResetHardware(PUCHAR portBase); +NTSTATUS ValidatePropertyRequest(IN PPCPROPERTY_REQUEST pRequest, IN ULONG ulValueSize, IN BOOLEAN fValueRequired); +NTSTATUS NTAPI PropertyHandler_Synth(IN PPCPROPERTY_REQUEST PropertyRequest); +NTSTATUS NTAPI DMusMPUInterruptServiceRoutine(PINTERRUPTSYNC InterruptSync,PVOID DynamicContext); +VOID NTAPI DMusUARTTimerDPC(PKDPC Dpc,PVOID DeferredContext,PVOID SystemArgument1,PVOID SystemArgument2); +NTSTATUS NTAPI SynchronizedDMusMPUWrite(PINTERRUPTSYNC InterruptSync,PVOID syncWriteContext); +/***************************************************************************** + * Constants + */ + +const BOOLEAN COMMAND = TRUE; +const BOOLEAN DATA = FALSE; +const ULONG kMPUInputBufferSize = 128; + + +/***************************************************************************** + * Classes + */ + +/***************************************************************************** + * CMiniportDMusUART + ***************************************************************************** + * MPU-401 miniport. This object is associated with the device and is + * created when the device is started. The class inherits IMiniportDMus + * so it can expose this interface and CUnknown so it automatically gets + * reference counting and aggregation support. + */ +class CMiniportDMusUART +: public IMiniportDMus, + public IMusicTechnology, + public IPowerNotify { +private: + LONG m_Ref; // Reference count + KSSTATE m_KSStateInput; // Miniport state (RUN/PAUSE/ACQUIRE/STOP) + PPORTDMUS m_pPort; // Callback interface. + PUCHAR m_pPortBase; // Base port address. + PINTERRUPTSYNC m_pInterruptSync; // Interrupt synchronization object. + PSERVICEGROUP m_pServiceGroup; // Service group for capture. + PMASTERCLOCK m_MasterClock; // for input data + REFERENCE_TIME m_InputTimeStamp; // capture data timestamp + USHORT m_NumRenderStreams; // Num active render streams. + USHORT m_NumCaptureStreams; // Num active capture streams. + ULONG m_MPUInputBufferHead; // Index of the newest byte in the FIFO. + ULONG m_MPUInputBufferTail; // Index of the oldest empty space in the FIFO. + GUID m_MusicFormatTechnology; + POWER_STATE m_PowerState; // Saved power state (D0 = full power, D3 = off) + BOOLEAN m_fMPUInitialized; // Is the MPU HW initialized. + BOOLEAN m_UseIRQ; // FALSE if no IRQ is used for MIDI. + UCHAR m_MPUInputBuffer[kMPUInputBufferSize]; // Internal SW FIFO. + + /************************************************************************* + * CMiniportDMusUART methods + * + * These are private member functions used internally by the object. + * See MINIPORT.CPP for specific descriptions. + */ + NTSTATUS ProcessResources + ( + IN PRESOURCELIST ResourceList + ); + NTSTATUS InitializeHardware(PINTERRUPTSYNC interruptSync,PUCHAR portBase); + public: STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); @@ -29,107 +116,2578 @@ public: } return m_Ref; } - IMP_IMiniportDMus; - CMiniportDMus(IUnknown *OuterUnknown){} - virtual ~CMiniportDMus(){} -protected: - LONG m_Ref; + CMiniportDMusUART(IUnknown * Unknown){} + ~CMiniportDMusUART(); + /************************************************************************* + * IMiniport methods + */ + STDMETHODIMP_(NTSTATUS) + GetDescription + ( OUT PPCFILTER_DESCRIPTOR * OutFilterDescriptor + ); + STDMETHODIMP_(NTSTATUS) + DataRangeIntersection + ( IN ULONG PinId + , IN PKSDATARANGE DataRange + , IN PKSDATARANGE MatchingDataRange + , IN ULONG OutputBufferLength + , OUT PVOID ResultantFormat + , OUT PULONG ResultantFormatLength + ) + { + return STATUS_NOT_IMPLEMENTED; + } + + /************************************************************************* + * IMiniportDMus methods + */ + STDMETHODIMP_(NTSTATUS) Init + ( + IN PUNKNOWN UnknownAdapter, + IN PRESOURCELIST ResourceList, + IN PPORTDMUS Port, + OUT PSERVICEGROUP * ServiceGroup + ); + STDMETHODIMP_(NTSTATUS) NewStream + ( + OUT PMXF * Stream, + IN PUNKNOWN OuterUnknown OPTIONAL, + IN POOL_TYPE PoolType, + IN ULONG PinID, + IN DMUS_STREAM_TYPE StreamType, + IN PKSDATAFORMAT DataFormat, + OUT PSERVICEGROUP * ServiceGroup, + IN PAllocatorMXF AllocatorMXF, + IN PMASTERCLOCK MasterClock, + OUT PULONGLONG SchedulePreFetch + ); + STDMETHODIMP_(void) Service + ( void + ); + + /************************************************************************* + * IMusicTechnology methods + */ + IMP_IMusicTechnology; + + /************************************************************************* + * IPowerNotify methods + */ + IMP_IPowerNotify; + + /************************************************************************* + * Friends + */ + friend class CMiniportDMusUARTStream; + friend NTSTATUS + DMusMPUInterruptServiceRoutine(PINTERRUPTSYNC InterruptSync,PVOID DynamicContext); + friend NTSTATUS + SynchronizedDMusMPUWrite(PINTERRUPTSYNC InterruptSync,PVOID syncWriteContext); + friend VOID NTAPI + DMusUARTTimerDPC(PKDPC Dpc,PVOID DeferredContext,PVOID SystemArgument1,PVOID SystemArgument2); + friend NTSTATUS NTAPI PropertyHandler_Synth(IN PPCPROPERTY_REQUEST PropertyRequest); + friend STDMETHODIMP_(NTSTATUS) SnapTimeStamp(PINTERRUPTSYNC InterruptSync,PVOID pStream); }; -// IUnknown methods - -NTSTATUS -NTAPI -CMiniportDMus::QueryInterface( - IN REFIID refiid, - OUT PVOID* Output) +/***************************************************************************** + * CMiniportDMusUARTStream + ***************************************************************************** + * MPU-401 miniport stream. This object is associated with the pin and is + * created when the pin is instantiated. It inherits IMXF + * so it can expose this interface and CUnknown so it automatically gets + * reference counting and aggregation support. + */ +class CMiniportDMusUARTStream : public IMXF { - if (IsEqualGUIDAligned(refiid, IID_IMiniportDMus)) +private: + LONG m_Ref; // Reference Count + CMiniportDMusUART * m_pMiniport; // Parent. + REFERENCE_TIME m_SnapshotTimeStamp; // Current snapshot of miniport's input timestamp. + PUCHAR m_pPortBase; // Base port address. + BOOLEAN m_fCapture; // Whether this is capture. + long m_NumFailedMPUTries; // Deadman timeout for MPU hardware. + PAllocatorMXF m_AllocatorMXF; // source/sink for DMus structs + PMXF m_sinkMXF; // sink for DMus capture + PDMUS_KERNEL_EVENT m_DMKEvtQueue; // queue of waiting events + ULONG m_NumberOfRetries; // Number of consecutive times the h/w was busy/full + ULONG m_DMKEvtOffset; // offset into the event + KDPC m_Dpc; // DPC for timer + KTIMER m_TimerEvent; // timer + BOOL m_TimerQueued; // whether a timer has been set + KSPIN_LOCK m_DpcSpinLock; // protects the ConsumeEvents DPC + + STDMETHODIMP_(NTSTATUS) SourceEvtsToPort(); + STDMETHODIMP_(NTSTATUS) ConsumeEvents(); + STDMETHODIMP_(NTSTATUS) PutMessageLocked(PDMUS_KERNEL_EVENT pDMKEvt); + +public: + STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); + + STDMETHODIMP_(ULONG) AddRef() { - *Output = PVOID(PUNKNOWN(this)); - PUNKNOWN(*Output)->AddRef(); - return STATUS_SUCCESS; + InterlockedIncrement(&m_Ref); + return m_Ref; } - return STATUS_UNSUCCESSFUL; + STDMETHODIMP_(ULONG) Release() + { + InterlockedDecrement(&m_Ref); + + if (!m_Ref) + { + delete this; + return 0; + } + return m_Ref; + } + + ~CMiniportDMusUARTStream(); + + STDMETHODIMP_(NTSTATUS) Init + ( + IN CMiniportDMusUART * pMiniport, + IN PUCHAR pPortBase, + IN BOOLEAN fCapture, + IN PAllocatorMXF allocatorMXF, + IN PMASTERCLOCK masterClock + ); + + NTSTATUS HandlePortParams + ( + IN PPCPROPERTY_REQUEST Request + ); + + /************************************************************************* + * IMiniportStreamDMusUART methods + */ + IMP_IMXF; + + STDMETHODIMP_(NTSTATUS) Write + ( + IN PVOID BufferAddress, + IN ULONG BytesToWrite, + OUT PULONG BytesWritten + ); + + friend VOID NTAPI + DMusUARTTimerDPC + ( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2 + ); + friend NTSTATUS PropertyHandler_Synth(IN PPCPROPERTY_REQUEST); + friend STDMETHODIMP_(NTSTATUS) SnapTimeStamp(PINTERRUPTSYNC InterruptSync,PVOID pStream); +}; + + + +#define STR_MODULENAME "DMusUART:Miniport: " + +#ifdef _MSC_VER +#pragma code_seg("PAGE") +#endif + +#define UartFifoOkForWrite(status) ((status & MPU401_DRR) == 0) +#define UartFifoOkForRead(status) ((status & MPU401_DSR) == 0) + +typedef struct +{ + CMiniportDMusUART *Miniport; + PUCHAR PortBase; + PVOID BufferAddress; + ULONG Length; + PULONG BytesRead; +} +SYNCWRITECONTEXT, *PSYNCWRITECONTEXT; + +/***************************************************************************** + * PinDataRangesStreamLegacy + * PinDataRangesStreamDMusic + ***************************************************************************** + * Structures indicating range of valid format values for live pins. + */ +static +KSDATARANGE_MUSIC PinDataRangesStreamLegacy = +{ + { + { + sizeof(KSDATARANGE_MUSIC), + 0, + 0, + 0, + {STATICGUIDOF(KSDATAFORMAT_TYPE_MUSIC)}, + {STATICGUIDOF(KSDATAFORMAT_SUBTYPE_MIDI)}, + {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)} + } + }, + {STATICGUIDOF(KSMUSIC_TECHNOLOGY_PORT)}, + 0, + 0, + 0xFFFF +}; +static +KSDATARANGE_MUSIC PinDataRangesStreamDMusic = +{ + { + { + sizeof(KSDATARANGE_MUSIC), + 0, + 0, + 0, + {STATICGUIDOF(KSDATAFORMAT_TYPE_MUSIC)}, + {STATICGUIDOF(KSDATAFORMAT_SUBTYPE_DIRECTMUSIC)}, + {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)} + } + }, + {STATICGUIDOF(KSMUSIC_TECHNOLOGY_PORT)}, + 0, + 0, + 0xFFFF +}; + +/***************************************************************************** + * PinDataRangePointersStreamLegacy + * PinDataRangePointersStreamDMusic + * PinDataRangePointersStreamCombined + ***************************************************************************** + * List of pointers to structures indicating range of valid format values + * for live pins. + */ +static +PKSDATARANGE PinDataRangePointersStreamLegacy[] = +{ + PKSDATARANGE(&PinDataRangesStreamLegacy) +}; +static +PKSDATARANGE PinDataRangePointersStreamDMusic[] = +{ + PKSDATARANGE(&PinDataRangesStreamDMusic) +}; +static +PKSDATARANGE PinDataRangePointersStreamCombined[] = +{ + PKSDATARANGE(&PinDataRangesStreamLegacy) + ,PKSDATARANGE(&PinDataRangesStreamDMusic) +}; + +/***************************************************************************** + * PinDataRangesBridge + ***************************************************************************** + * Structures indicating range of valid format values for bridge pins. + */ +static +KSDATARANGE PinDataRangesBridge[] = +{ + { + { + sizeof(KSDATARANGE), + 0, + 0, + 0, + {STATICGUIDOF(KSDATAFORMAT_TYPE_MUSIC)}, + {STATICGUIDOF(KSDATAFORMAT_SUBTYPE_MIDI_BUS)}, + {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)} + } + } +}; + +/***************************************************************************** + * PinDataRangePointersBridge + ***************************************************************************** + * List of pointers to structures indicating range of valid format values + * for bridge pins. + */ +static +PKSDATARANGE PinDataRangePointersBridge[] = +{ + &PinDataRangesBridge[0] +}; + +/***************************************************************************** + * SynthProperties + ***************************************************************************** + * List of properties in the Synth set. + */ +static +PCPROPERTY_ITEM +SynthProperties[] = +{ + // Global: S/Get synthesizer caps + { + &KSPROPSETID_Synth, + KSPROPERTY_SYNTH_CAPS, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_Synth + }, + // Global: S/Get port parameters + { + &KSPROPSETID_Synth, + KSPROPERTY_SYNTH_PORTPARAMETERS, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_Synth + }, + // Per stream: S/Get channel groups + { + &KSPROPSETID_Synth, + KSPROPERTY_SYNTH_CHANNELGROUPS, + KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_Synth + }, + // Per stream: Get current latency time + { + &KSPROPSETID_Synth, + KSPROPERTY_SYNTH_LATENCYCLOCK, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_Synth + } +}; +DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSynth, SynthProperties); +DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSynth2, SynthProperties); + +#define kMaxNumCaptureStreams 1 +#define kMaxNumLegacyRenderStreams 1 +#define kMaxNumDMusicRenderStreams 1 + +/***************************************************************************** + * MiniportPins + ***************************************************************************** + * List of pins. + */ +static +PCPIN_DESCRIPTOR MiniportPins[] = +{ + { + kMaxNumLegacyRenderStreams,kMaxNumLegacyRenderStreams,0, // InstanceCount + NULL, // AutomationTable + { // KsPinDescriptor + 0, // InterfacesCount + NULL, // Interfaces + 0, // MediumsCount + NULL, // Mediums + SIZEOF_ARRAY(PinDataRangePointersStreamLegacy), // DataRangesCount + PinDataRangePointersStreamLegacy, // DataRanges + KSPIN_DATAFLOW_IN, // DataFlow + KSPIN_COMMUNICATION_SINK, // Communication + (GUID *) &KSCATEGORY_AUDIO, // Category + &KSAUDFNAME_MIDI, // Name + {0} // Reserved + } + }, + { + kMaxNumDMusicRenderStreams,kMaxNumDMusicRenderStreams,0, // InstanceCount + NULL, // AutomationTable + { // KsPinDescriptor + 0, // InterfacesCount + NULL, // Interfaces + 0, // MediumsCount + NULL, // Mediums + SIZEOF_ARRAY(PinDataRangePointersStreamDMusic), // DataRangesCount + PinDataRangePointersStreamDMusic, // DataRanges + KSPIN_DATAFLOW_IN, // DataFlow + KSPIN_COMMUNICATION_SINK, // Communication + (GUID *) &KSCATEGORY_AUDIO, // Category + &KSAUDFNAME_DMUSIC_MPU_OUT, // Name + {0} // Reserved + } + }, + { + 0,0,0, // InstanceCount + NULL, // AutomationTable + { // KsPinDescriptor + 0, // InterfacesCount + NULL, // Interfaces + 0, // MediumsCount + NULL, // Mediums + SIZEOF_ARRAY(PinDataRangePointersBridge), // DataRangesCount + PinDataRangePointersBridge, // DataRanges + KSPIN_DATAFLOW_OUT, // DataFlow + KSPIN_COMMUNICATION_NONE, // Communication + (GUID *) &KSCATEGORY_AUDIO, // Category + NULL, // Name + {0} // Reserved + } + }, + { + 0,0,0, // InstanceCount + NULL, // AutomationTable + { // KsPinDescriptor + 0, // InterfacesCount + NULL, // Interfaces + 0, // MediumsCount + NULL, // Mediums + SIZEOF_ARRAY(PinDataRangePointersBridge), // DataRangesCount + PinDataRangePointersBridge, // DataRanges + KSPIN_DATAFLOW_IN, // DataFlow + KSPIN_COMMUNICATION_NONE, // Communication + (GUID *) &KSCATEGORY_AUDIO, // Category + NULL, // Name + {0} // Reserved + } + }, + { + kMaxNumCaptureStreams,kMaxNumCaptureStreams,0, // InstanceCount + NULL, // AutomationTable + { // KsPinDescriptor + 0, // InterfacesCount + NULL, // Interfaces + 0, // MediumsCount + NULL, // Mediums + SIZEOF_ARRAY(PinDataRangePointersStreamCombined), // DataRangesCount + PinDataRangePointersStreamCombined, // DataRanges + KSPIN_DATAFLOW_OUT, // DataFlow + KSPIN_COMMUNICATION_SINK, // Communication + (GUID *) &KSCATEGORY_AUDIO, // Category + &KSAUDFNAME_DMUSIC_MPU_IN, // Name + {0} // Reserved + } + } +}; + +/***************************************************************************** + * MiniportNodes + ***************************************************************************** + * List of nodes. + */ +#define CONST_PCNODE_DESCRIPTOR(n) { 0, NULL, &n, NULL } +#define CONST_PCNODE_DESCRIPTOR_AUTO(n,a) { 0, &a, &n, NULL } +static +PCNODE_DESCRIPTOR MiniportNodes[] = +{ + CONST_PCNODE_DESCRIPTOR_AUTO(KSNODETYPE_SYNTHESIZER, AutomationSynth) + , CONST_PCNODE_DESCRIPTOR_AUTO(KSNODETYPE_SYNTHESIZER, AutomationSynth2) +}; + +/***************************************************************************** + * MiniportConnections + ***************************************************************************** + * List of connections. + */ +enum { + eSynthNode = 0 + , eInputNode +}; + +enum { + eFilterInputPinLeg = 0, + eFilterInputPinDM, + eBridgeOutputPin, + eBridgeInputPin, + eFilterOutputPin +}; + +static +PCCONNECTION_DESCRIPTOR MiniportConnections[] = +{ // From To + // Node pin Node pin + { PCFILTER_NODE, eFilterInputPinLeg, PCFILTER_NODE, eBridgeOutputPin } // Legacy Stream in to synth. + , { PCFILTER_NODE, eFilterInputPinDM, eSynthNode, KSNODEPIN_STANDARD_IN } // DM Stream in to synth. + , { eSynthNode, KSNODEPIN_STANDARD_OUT, PCFILTER_NODE, eBridgeOutputPin } // Synth to bridge out. + , { PCFILTER_NODE, eBridgeInputPin, eInputNode, KSNODEPIN_STANDARD_IN } // Bridge in to input. + , { eInputNode, KSNODEPIN_STANDARD_OUT, PCFILTER_NODE, eFilterOutputPin } // Input to DM/Legacy Stream out. +}; + +/***************************************************************************** + * MiniportCategories + ***************************************************************************** + * List of categories. + */ +static +GUID MiniportCategories[] = +{ + {STATICGUIDOF(KSCATEGORY_AUDIO)}, + {STATICGUIDOF(KSCATEGORY_RENDER)}, + {STATICGUIDOF(KSCATEGORY_CAPTURE)} +}; + +/***************************************************************************** + * MiniportFilterDescriptor + ***************************************************************************** + * Complete miniport filter description. + */ +static +PCFILTER_DESCRIPTOR MiniportFilterDescriptor = +{ + 0, // Version + NULL, // AutomationTable + sizeof(PCPIN_DESCRIPTOR), // PinSize + SIZEOF_ARRAY(MiniportPins), // PinCount + MiniportPins, // Pins + sizeof(PCNODE_DESCRIPTOR), // NodeSize + SIZEOF_ARRAY(MiniportNodes), // NodeCount + MiniportNodes, // Nodes + SIZEOF_ARRAY(MiniportConnections), // ConnectionCount + MiniportConnections, // Connections + SIZEOF_ARRAY(MiniportCategories), // CategoryCount + MiniportCategories // Categories +}; + +#ifdef _MSC_VER +#pragma code_seg("PAGE") +#endif + +BOOLEAN TryMPU(IN PUCHAR PortBase); +NTSTATUS WriteMPU(IN PUCHAR PortBase,IN BOOLEAN IsCommand,IN UCHAR Value); + +#ifdef _MSC_VER +#pragma code_seg("PAGE") +#endif + +// make sure we're in UART mode +NTSTATUS ResetHardware(PUCHAR portBase) +{ + PAGED_CODE(); + + return WriteMPU(portBase,COMMAND,MPU401_CMD_UART); } -// IMiniport methods +#ifdef _MSC_VER +#pragma code_seg("PAGE") +#endif +// +// We initialize the UART with interrupts suppressed so we don't +// try to service the chip prematurely. +// +NTSTATUS CMiniportDMusUART::InitializeHardware(PINTERRUPTSYNC interruptSync,PUCHAR portBase) +{ + PAGED_CODE(); + + NTSTATUS ntStatus; + if (m_UseIRQ) + { + ntStatus = interruptSync->CallSynchronizedRoutine(InitMPU,PVOID(portBase)); + } + else + { + ntStatus = InitMPU(NULL,PVOID(portBase)); + } + + if (NT_SUCCESS(ntStatus)) + { + // + // Start the UART (this should trigger an interrupt). + // + ntStatus = ResetHardware(portBase); + } + else + { + DPRINT("*** InitMPU returned with ntStatus 0x%08x ***", ntStatus); + } + + m_fMPUInitialized = NT_SUCCESS(ntStatus); + + return ntStatus; +} + +#ifdef _MSC_VER +#pragma code_seg() +#endif + +/***************************************************************************** + * InitMPU() + ***************************************************************************** + * Synchronized routine to initialize the MPU401. + */ NTSTATUS -NTAPI -CMiniportDMus::DataRangeIntersection( - IN ULONG PinId, - IN PKSDATARANGE DataRange, - IN PKSDATARANGE MatchingDataRange, - IN ULONG OutputBufferLength, - OUT PVOID ResultantFormat OPTIONAL, - OUT PULONG ResultantFormatLength) +InitMPU +( + IN PINTERRUPTSYNC InterruptSync, + IN PVOID DynamicContext +) { - return STATUS_UNSUCCESSFUL; + DPRINT("InitMPU"); + if (!DynamicContext) + { + return STATUS_INVALID_PARAMETER_2; + } + + PUCHAR portBase = PUCHAR(DynamicContext); + UCHAR status; + ULONGLONG startTime; + BOOLEAN success; + NTSTATUS ntStatus = STATUS_SUCCESS; + + // + // Reset the card (puts it into "smart mode") + // + ntStatus = WriteMPU(portBase,COMMAND,MPU401_CMD_RESET); + + // wait for the acknowledgement + // NOTE: When the Ack arrives, it will trigger an interrupt. + // Normally the DPC routine would read in the ack byte and we + // would never see it, however since we have the hardware locked (HwEnter), + // we can read the port before the DPC can and thus we receive the Ack. + startTime = PcGetTimeInterval(0); + success = FALSE; + while(PcGetTimeInterval(startTime) < GTI_MILLISECONDS(50)) + { + status = READ_PORT_UCHAR(portBase + MPU401_REG_STATUS); + + if (UartFifoOkForRead(status)) // Is data waiting? + { + READ_PORT_UCHAR(portBase + MPU401_REG_DATA); // yep.. read ACK + success = TRUE; // don't need to do more + break; + } + KeStallExecutionProcessor(25); // microseconds + } +#if (DBG) + if (!success) + { + DPRINT("First attempt to reset the MPU didn't get ACKed.\n"); + } +#endif // (DBG) + + // NOTE: We cannot check the ACK byte because if the card was already in + // UART mode it will not send an ACK but it will reset. + + // reset the card again + (void) WriteMPU(portBase,COMMAND,MPU401_CMD_RESET); + + // wait for ack (again) + startTime = PcGetTimeInterval(0); // This might take a while + BYTE dataByte = 0; + success = FALSE; + while (PcGetTimeInterval(startTime) < GTI_MILLISECONDS(50)) + { + status = READ_PORT_UCHAR(portBase + MPU401_REG_STATUS); + if (UartFifoOkForRead(status)) // Is data waiting? + { + dataByte = READ_PORT_UCHAR(portBase + MPU401_REG_DATA); // yep.. read ACK + success = TRUE; // don't need to do more + break; + } + KeStallExecutionProcessor(25); + } + + if ((0xFE != dataByte) || !success) // Did we succeed? If no second ACK, something is hosed + { + DPRINT("Second attempt to reset the MPU didn't get ACKed.\n"); + DPRINT("Init Reset failure error. Ack = %X", ULONG(dataByte)); + + ntStatus = STATUS_IO_DEVICE_ERROR; + } + + return ntStatus; } +#ifdef _MSC_VER +#pragma code_seg() +#endif + +/***************************************************************************** + * CMiniportDMusUARTStream::Write() + ***************************************************************************** + * Writes outgoing MIDI data. + */ +STDMETHODIMP_(NTSTATUS) +CMiniportDMusUARTStream:: +Write +( + IN PVOID BufferAddress, + IN ULONG Length, + OUT PULONG BytesWritten +) +{ + DPRINT("Write\n"); + ASSERT(BytesWritten); + if (!BufferAddress) + { + Length = 0; + } + + NTSTATUS ntStatus = STATUS_SUCCESS; + + if (!m_fCapture) + { + PUCHAR pMidiData; + ULONG count; + + count = 0; + pMidiData = PUCHAR(BufferAddress); + + if (Length) + { + SYNCWRITECONTEXT context; + context.Miniport = (m_pMiniport); + context.PortBase = m_pPortBase; + context.BufferAddress = pMidiData; + context.Length = Length; + context.BytesRead = &count; + + if (m_pMiniport->m_UseIRQ) + { + ntStatus = m_pMiniport->m_pInterruptSync-> + CallSynchronizedRoutine(SynchronizedDMusMPUWrite,PVOID(&context)); + } + else // !m_UseIRQ + { + ntStatus = SynchronizedDMusMPUWrite(NULL,PVOID(&context)); + } // !m_UseIRQ + + if (count == 0) + { + m_NumFailedMPUTries++; + if (m_NumFailedMPUTries >= 100) + { + ntStatus = STATUS_IO_DEVICE_ERROR; + m_NumFailedMPUTries = 0; + } + } + else + { + m_NumFailedMPUTries = 0; + } + } // if we have data at all + *BytesWritten = count; + } + else // called write on the read stream + { + ntStatus = STATUS_INVALID_DEVICE_REQUEST; + } + return ntStatus; +} + +#ifdef _MSC_VER +#pragma code_seg() +#endif + +/***************************************************************************** + * SynchronizedDMusMPUWrite() + ***************************************************************************** + * Writes outgoing MIDI data. + */ NTSTATUS -NTAPI -CMiniportDMus::GetDescription( - OUT PPCFILTER_DESCRIPTOR *Description) +SynchronizedDMusMPUWrite +( + IN PINTERRUPTSYNC InterruptSync, + IN PVOID syncWriteContext +) { - return STATUS_UNSUCCESSFUL; + PSYNCWRITECONTEXT context; + context = (PSYNCWRITECONTEXT)syncWriteContext; + ASSERT(context->Miniport); + ASSERT(context->PortBase); + ASSERT(context->BufferAddress); + ASSERT(context->Length); + ASSERT(context->BytesRead); + + PUCHAR pChar = PUCHAR(context->BufferAddress); + NTSTATUS ntStatus,readStatus; + ntStatus = STATUS_SUCCESS; + // + // while we're not there yet, and + // while we don't have to wait on an aligned byte (including 0) + // (we never wait on a byte. Better to come back later) + readStatus = DMusMPUInterruptServiceRoutine(InterruptSync,PVOID(context->Miniport)); + while ( (*(context->BytesRead) < context->Length) + && ( TryMPU(context->PortBase) + || (*(context->BytesRead)%3) + ) ) + { + ntStatus = WriteMPU(context->PortBase,DATA,*pChar); + if (NT_SUCCESS(ntStatus)) + { + pChar++; + *(context->BytesRead) = *(context->BytesRead) + 1; +// readStatus = DMusMPUInterruptServiceRoutine(InterruptSync,PVOID(context->Miniport)); + } + else + { + DPRINT("SynchronizedDMusMPUWrite failed (0x%08x)",ntStatus); + break; + } + } + readStatus = DMusMPUInterruptServiceRoutine(InterruptSync,PVOID(context->Miniport)); + return ntStatus; } -HRESULT -NTAPI -CMiniportDMus::Init( - IN PUNKNOWN pUnknownAdapter, - IN PRESOURCELIST pResourceList, - IN PPORTDMUS pPort, - OUT PSERVICEGROUP *ppServiceGroup - ) +#define kMPUPollTimeout 2 + +#ifdef _MSC_VER +#pragma code_seg() +#endif + +/***************************************************************************** + * TryMPU() + ***************************************************************************** + * See if the MPU401 is free. + */ +BOOLEAN +TryMPU +( + IN PUCHAR PortBase +) { - return STATUS_UNSUCCESSFUL; + BOOLEAN success; + USHORT numPolls; + UCHAR status; + + DPRINT("TryMPU"); + numPolls = 0; + + while (numPolls < kMPUPollTimeout) + { + status = READ_PORT_UCHAR(PortBase + MPU401_REG_STATUS); + + if (UartFifoOkForWrite(status)) // Is this a good time to write data? + { + break; + } + numPolls++; + } + if (numPolls >= kMPUPollTimeout) + { + success = FALSE; + DPRINT("TryMPU failed"); + } + else + { + success = TRUE; + } + + return success; } -HRESULT -NTAPI -CMiniportDMus::NewStream( - OUT PMXF *ppMXF, - IN PUNKNOWN pOuterUnknown OPTIONAL, - IN POOL_TYPE PoolType, - IN ULONG uPinId, - IN DMUS_STREAM_TYPE StreamType, - IN PKSDATAFORMAT pDataFormat, - OUT PSERVICEGROUP *ppServiceGroup, - IN PAllocatorMXF pAllocatorMXF, - IN PMASTERCLOCK pMasterClock, - OUT PULONGLONG puuSchedulePreFetch - ) +#ifdef _MSC_VER +#pragma code_seg() +#endif + +/***************************************************************************** + * WriteMPU() + ***************************************************************************** + * Write a byte out to the MPU401. + */ +NTSTATUS +WriteMPU +( + IN PUCHAR PortBase, + IN BOOLEAN IsCommand, + IN UCHAR Value +) { - return STATUS_UNSUCCESSFUL; + DPRINT("WriteMPU"); + NTSTATUS ntStatus = STATUS_IO_DEVICE_ERROR; + + if (!PortBase) + { + DPRINT("O: PortBase is zero\n"); + return ntStatus; + } + PUCHAR deviceAddr = PortBase + MPU401_REG_DATA; + + if (IsCommand) + { + deviceAddr = PortBase + MPU401_REG_COMMAND; + } + + ULONGLONG startTime = PcGetTimeInterval(0); + + while (PcGetTimeInterval(startTime) < GTI_MILLISECONDS(50)) + { + UCHAR status + = READ_PORT_UCHAR(PortBase + MPU401_REG_STATUS); + + if (UartFifoOkForWrite(status)) // Is this a good time to write data? + { // yep (Jon comment) + WRITE_PORT_UCHAR(deviceAddr,Value); + DPRINT("WriteMPU emitted 0x%02x",Value); + ntStatus = STATUS_SUCCESS; + break; + } + } + return ntStatus; } -VOID -NTAPI -CMiniportDMus::Service() -{ +#ifdef _MSC_VER +#pragma code_seg() +#endif +/***************************************************************************** + * SnapTimeStamp() + ***************************************************************************** + * + * At synchronized execution to ISR, copy miniport's volatile m_InputTimeStamp + * to stream's m_SnapshotTimeStamp and zero m_InputTimeStamp. + * + */ +STDMETHODIMP_(NTSTATUS) +SnapTimeStamp(PINTERRUPTSYNC InterruptSync,PVOID pStream) +{ + CMiniportDMusUARTStream *pMPStream = (CMiniportDMusUARTStream *)pStream; + + // cache the timestamp + pMPStream->m_SnapshotTimeStamp = pMPStream->m_pMiniport->m_InputTimeStamp; + + // if the window is closed, zero the timestamp + if (pMPStream->m_pMiniport->m_MPUInputBufferHead == + pMPStream->m_pMiniport->m_MPUInputBufferTail) + { + pMPStream->m_pMiniport->m_InputTimeStamp = 0; + } + + return STATUS_SUCCESS; } +/***************************************************************************** + * CMiniportDMusUARTStream::SourceEvtsToPort() + ***************************************************************************** + * + * Reads incoming MIDI data, feeds into DMus events. + * No need to touch the hardware, just read from our SW FIFO. + * + */ +STDMETHODIMP_(NTSTATUS) +CMiniportDMusUARTStream::SourceEvtsToPort() +{ + NTSTATUS ntStatus; + + ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); + DPRINT("SourceEvtsToPort"); + + if (m_fCapture) + { + ntStatus = STATUS_SUCCESS; + if (m_pMiniport->m_MPUInputBufferHead != m_pMiniport->m_MPUInputBufferTail) + { + PDMUS_KERNEL_EVENT aDMKEvt,eventTail,eventHead = NULL; + + while (m_pMiniport->m_MPUInputBufferHead != m_pMiniport->m_MPUInputBufferTail) + { + (void) m_AllocatorMXF->GetMessage(&aDMKEvt); + if (!aDMKEvt) + { + DPRINT("SourceEvtsToPort can't allocate DMKEvt"); + return STATUS_INSUFFICIENT_RESOURCES; + } + + // put this event at the end of the list + if (!eventHead) + { + eventHead = aDMKEvt; + } + else + { + eventTail = eventHead; + while (eventTail->pNextEvt) + { + eventTail = eventTail->pNextEvt; + } + eventTail->pNextEvt = aDMKEvt; + } + // read all the bytes out of the buffer, into event(s) + for (aDMKEvt->cbEvent = 0; aDMKEvt->cbEvent < sizeof(PBYTE); aDMKEvt->cbEvent++) + { + if (m_pMiniport->m_MPUInputBufferHead == m_pMiniport->m_MPUInputBufferTail) + { +// _DbgPrintF(DEBUGLVL_TERSE, ("SourceEvtsToPort m_MPUInputBufferHead met m_MPUInputBufferTail, overrun")); + break; + } + aDMKEvt->uData.abData[aDMKEvt->cbEvent] = m_pMiniport->m_MPUInputBuffer[m_pMiniport->m_MPUInputBufferHead]; + m_pMiniport->m_MPUInputBufferHead++; + if (m_pMiniport->m_MPUInputBufferHead >= kMPUInputBufferSize) + { + m_pMiniport->m_MPUInputBufferHead = 0; + } + } + } + + if (m_pMiniport->m_UseIRQ) + { + ntStatus = m_pMiniport->m_pInterruptSync->CallSynchronizedRoutine(SnapTimeStamp,PVOID(this)); + } + else // !m_UseIRQ + { + ntStatus = SnapTimeStamp(NULL,PVOID(this)); + } // !m_UseIRQ + aDMKEvt = eventHead; + while (aDMKEvt) + { + aDMKEvt->ullPresTime100ns = m_SnapshotTimeStamp; + aDMKEvt->usChannelGroup = 1; + aDMKEvt->usFlags = DMUS_KEF_EVENT_INCOMPLETE; + aDMKEvt = aDMKEvt->pNextEvt; + } + (void)m_sinkMXF->PutMessage(eventHead); + } + } + else // render stream + { + DPRINT("SourceEvtsToPort called on render stream"); + ntStatus = STATUS_INVALID_DEVICE_REQUEST; + } + return ntStatus; +} + +#ifdef _MSC_VER +#pragma code_seg() +#endif + +/***************************************************************************** + * DMusMPUInterruptServiceRoutine() + ***************************************************************************** + * ISR. + */ +NTSTATUS +DMusMPUInterruptServiceRoutine +( + IN PINTERRUPTSYNC InterruptSync, + IN PVOID DynamicContext +) +{ + DPRINT("DMusMPUInterruptServiceRoutine"); + ULONGLONG startTime; + + ASSERT(DynamicContext); + + NTSTATUS ntStatus; + BOOL newBytesAvailable; + CMiniportDMusUART *that; + NTSTATUS clockStatus; + + that = (CMiniportDMusUART *) DynamicContext; + newBytesAvailable = FALSE; + ntStatus = STATUS_UNSUCCESSFUL; + + UCHAR portStatus = 0xff; + + // + // Read the MPU status byte. + // + if (that->m_pPortBase) + { + portStatus = + READ_PORT_UCHAR(that->m_pPortBase + MPU401_REG_STATUS); + + // + // If there is outstanding work to do and there is a port-driver for + // the MPU miniport... + // + if (UartFifoOkForRead(portStatus) && that->m_pPort) + { + startTime = PcGetTimeInterval(0); + while ( (PcGetTimeInterval(startTime) < GTI_MILLISECONDS(50)) + && (UartFifoOkForRead(portStatus)) ) + { + UCHAR uDest = READ_PORT_UCHAR(that->m_pPortBase + MPU401_REG_DATA); + if ( (that->m_KSStateInput == KSSTATE_RUN) + && (that->m_NumCaptureStreams) + ) + { + ULONG buffHead = that->m_MPUInputBufferHead; + if ( (that->m_MPUInputBufferTail + 1 == buffHead) + || (that->m_MPUInputBufferTail + 1 - kMPUInputBufferSize == buffHead)) + { + DPRINT("*****MPU Input Buffer Overflow*****"); + } + else + { + if (!that->m_InputTimeStamp) + { + clockStatus = that->m_MasterClock->GetTime(&that->m_InputTimeStamp); + if (STATUS_SUCCESS != clockStatus) + { + DPRINT("GetTime failed for clock 0x%08x",that->m_MasterClock); + } + } + newBytesAvailable = TRUE; + // ...place the data in our FIFO... + that->m_MPUInputBuffer[that->m_MPUInputBufferTail] = uDest; + ASSERT(that->m_MPUInputBufferTail < kMPUInputBufferSize); + + that->m_MPUInputBufferTail++; + if (that->m_MPUInputBufferTail >= kMPUInputBufferSize) + { + that->m_MPUInputBufferTail = 0; + } + } + } + // + // Look for more MIDI data. + // + portStatus = + READ_PORT_UCHAR(that->m_pPortBase + MPU401_REG_STATUS); + } // either there's no data or we ran too long + if (newBytesAvailable) + { + // + // ...notify the MPU port driver that we have bytes. + // + that->m_pPort->Notify(that->m_pServiceGroup); + } + ntStatus = STATUS_SUCCESS; + } + } + + return ntStatus; +} + +/***************************************************************************** + * CMiniportDMusUART::GetDescription() + ***************************************************************************** + * Gets the topology. + */ +STDMETHODIMP_(NTSTATUS) +CMiniportDMusUART:: +GetDescription +( + OUT PPCFILTER_DESCRIPTOR * OutFilterDescriptor +) +{ + PAGED_CODE(); + + ASSERT(OutFilterDescriptor); + + DPRINT("GetDescription"); + + *OutFilterDescriptor = &MiniportFilterDescriptor; + + return STATUS_SUCCESS; +} + +#ifdef _MSC_VER +#pragma code_seg("PAGE") +#endif + NTSTATUS NewMiniportDMusUART( OUT PMINIPORT* OutMiniport, IN REFCLSID ClassId) { - CMiniportDMus * This; + CMiniportDMusUART * This; + NTSTATUS Status; - This = new(NonPagedPool, TAG_PORTCLASS)CMiniportDMus(NULL); + This= new(NonPagedPool, TAG_PORTCLASS) CMiniportDMusUART(NULL); if (!This) return STATUS_INSUFFICIENT_RESOURCES; - *OutMiniport = (PMINIPORT)This; - This->AddRef(); + Status = This->QueryInterface(IID_IMiniport, (PVOID*)OutMiniport); + + if (!NT_SUCCESS(Status)) + { + delete This; + } + + DPRINT("NewMiniportDMusUART %p Status %x\n", *OutMiniport, Status); + return Status; +} + + +#ifdef _MSC_VER +#pragma code_seg("PAGE") +#endif + +/***************************************************************************** + * CMiniportDMusUART::ProcessResources() + ***************************************************************************** + * Processes the resource list, setting up helper objects accordingly. + */ +NTSTATUS +CMiniportDMusUART:: +ProcessResources +( + IN PRESOURCELIST ResourceList +) +{ + PAGED_CODE(); + + DPRINT("ProcessResources"); + + ASSERT(ResourceList); + if (!ResourceList) + { + return STATUS_DEVICE_CONFIGURATION_ERROR; + } + // + // Get counts for the types of resources. + // + ULONG countIO = ResourceList->NumberOfPorts(); + ULONG countIRQ = ResourceList->NumberOfInterrupts(); + ULONG countDMA = ResourceList->NumberOfDmas(); + ULONG lengthIO = ResourceList->FindTranslatedPort(0)->u.Port.Length; + +#ifdef DBG + DPRINT("Starting MPU401 Port 0x%lx", ResourceList->FindTranslatedPort(0)->u.Port.Start.LowPart); +#endif + + NTSTATUS ntStatus = STATUS_SUCCESS; + + // + // Make sure we have the expected number of resources. + // + if ( (countIO != 1) + || (countIRQ > 1) + || (countDMA != 0) + || (lengthIO == 0) + ) + { + DPRINT("Unknown ResourceList configuraton"); + ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR; + } + + if (NT_SUCCESS(ntStatus)) + { + // + // Get the port address. + // + m_pPortBase = + PUCHAR(ResourceList->FindTranslatedPort(0)->u.Port.Start.QuadPart); + + ntStatus = InitializeHardware(m_pInterruptSync,m_pPortBase); + } + + return ntStatus; +} + +#ifdef _MSC_VER +#pragma code_seg("PAGE") +#endif +/***************************************************************************** + * CMiniportDMusUART::NonDelegatingQueryInterface() + ***************************************************************************** + * Obtains an interface. This function works just like a COM QueryInterface + * call and is used if the object is not being aggregated. + */ +STDMETHODIMP_(NTSTATUS) +CMiniportDMusUART::QueryInterface +( + REFIID Interface, + PVOID * Object +) +{ + PAGED_CODE(); + + DPRINT("Miniport::NonDelegatingQueryInterface"); + ASSERT(Object); + + if (IsEqualGUIDAligned(Interface,IID_IUnknown)) + { + *Object = PVOID(PUNKNOWN(PMINIPORTDMUS(this))); + } + else + if (IsEqualGUIDAligned(Interface,IID_IMiniport)) + { + *Object = PVOID(PMINIPORT(this)); + } + else + if (IsEqualGUIDAligned(Interface,IID_IMiniportDMus)) + { + *Object = PVOID(PMINIPORTDMUS(this)); + } + else + if (IsEqualGUIDAligned(Interface,IID_IMusicTechnology)) + { + *Object = PVOID(PMUSICTECHNOLOGY(this)); + } + else + if (IsEqualGUIDAligned(Interface,IID_IPowerNotify)) + { + *Object = PVOID(PPOWERNOTIFY(this)); + } + else + { + *Object = NULL; + } + + if (*Object) + { + // + // We reference the interface for the caller. + // + PUNKNOWN(*Object)->AddRef(); + return STATUS_SUCCESS; + } + + return STATUS_INVALID_PARAMETER; +} + +#ifdef _MSC_VER +#pragma code_seg("PAGE") +#endif +/***************************************************************************** + * CMiniportDMusUART::~CMiniportDMusUART() + ***************************************************************************** + * Destructor. + */ +CMiniportDMusUART::~CMiniportDMusUART(void) +{ + PAGED_CODE(); + + DPRINT("~CMiniportDMusUART"); + + ASSERT(0 == m_NumCaptureStreams); + ASSERT(0 == m_NumRenderStreams); + + // reset the HW so we don't get anymore interrupts + if (m_UseIRQ && m_pInterruptSync) + { + (void) m_pInterruptSync->CallSynchronizedRoutine((PINTERRUPTSYNCROUTINE)InitMPU,PVOID(m_pPortBase)); + } + else + { + (void) InitMPU(NULL,PVOID(m_pPortBase)); + } + + if (m_pInterruptSync) + { + m_pInterruptSync->Release(); + m_pInterruptSync = NULL; + } + if (m_pServiceGroup) + { + m_pServiceGroup->Release(); + m_pServiceGroup = NULL; + } + if (m_pPort) + { + m_pPort->Release(); + m_pPort = NULL; + } +} + +#ifdef _MSC_VER +#pragma code_seg("PAGE") +#endif +/***************************************************************************** + * CMiniportDMusUART::Init() + ***************************************************************************** + * Initializes a the miniport. + */ +STDMETHODIMP_(NTSTATUS) +CMiniportDMusUART:: +Init +( + IN PUNKNOWN UnknownInterruptSync OPTIONAL, + IN PRESOURCELIST ResourceList, + IN PPORTDMUS Port_, + OUT PSERVICEGROUP * ServiceGroup +) +{ + PAGED_CODE(); + + ASSERT(ResourceList); + if (!ResourceList) + { + return STATUS_DEVICE_CONFIGURATION_ERROR; + } + + ASSERT(Port_); + ASSERT(ServiceGroup); + + DPRINT("Init"); + + *ServiceGroup = NULL; + m_pPortBase = 0; + m_fMPUInitialized = FALSE; + + // This will remain unspecified if the miniport does not get any power + // messages. + // + m_PowerState.DeviceState = PowerDeviceUnspecified; + + // + // AddRef() is required because we are keeping this pointer. + // + m_pPort = Port_; + m_pPort->AddRef(); + + // Set dataformat. + // + if (IsEqualGUIDAligned(m_MusicFormatTechnology, GUID_NULL)) + { + RtlCopyMemory( &m_MusicFormatTechnology, + &KSMUSIC_TECHNOLOGY_PORT, + sizeof(GUID)); + } + RtlCopyMemory( &PinDataRangesStreamLegacy.Technology, + &m_MusicFormatTechnology, + sizeof(GUID)); + RtlCopyMemory( &PinDataRangesStreamDMusic.Technology, + &m_MusicFormatTechnology, + sizeof(GUID)); + + for (ULONG bufferCount = 0;bufferCount < kMPUInputBufferSize;bufferCount++) + { + m_MPUInputBuffer[bufferCount] = 0; + } + m_MPUInputBufferHead = 0; + m_MPUInputBufferTail = 0; + m_InputTimeStamp = 0; + m_KSStateInput = KSSTATE_STOP; + + NTSTATUS ntStatus = STATUS_SUCCESS; + + m_NumRenderStreams = 0; + m_NumCaptureStreams = 0; + + m_UseIRQ = TRUE; + if (ResourceList->NumberOfInterrupts() == 0) + { + m_UseIRQ = FALSE; + } + + ntStatus = PcNewServiceGroup(&m_pServiceGroup,NULL); + if (NT_SUCCESS(ntStatus) && !m_pServiceGroup) // keep any error + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + + if (NT_SUCCESS(ntStatus)) + { + *ServiceGroup = m_pServiceGroup; + m_pServiceGroup->AddRef(); + + // + // Register the service group with the port early so the port is + // prepared to handle interrupts. + // + m_pPort->RegisterServiceGroup(m_pServiceGroup); + } + + if (NT_SUCCESS(ntStatus) && m_UseIRQ) + { + // + // Due to a bug in the InterruptSync design, we shouldn't share + // the interrupt sync object. Whoever goes away first + // will disconnect it, and the other points off into nowhere. + // + // Instead we generate our own interrupt sync object. + // + UnknownInterruptSync = NULL; + + if (UnknownInterruptSync) + { + ntStatus = + UnknownInterruptSync->QueryInterface + ( + IID_IInterruptSync, + (PVOID *) &m_pInterruptSync + ); + + if (!m_pInterruptSync && NT_SUCCESS(ntStatus)) // keep any error + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + if (NT_SUCCESS(ntStatus)) + { // run this ISR first + ntStatus = m_pInterruptSync-> + RegisterServiceRoutine(DMusMPUInterruptServiceRoutine,PVOID(this),TRUE); + } + + } + else + { // create our own interruptsync mechanism. + ntStatus = + PcNewInterruptSync + ( + &m_pInterruptSync, + NULL, + ResourceList, + 0, // Resource Index + InterruptSyncModeNormal // Run ISRs once until we get SUCCESS + ); + + if (!m_pInterruptSync && NT_SUCCESS(ntStatus)) // keep any error + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + + if (NT_SUCCESS(ntStatus)) + { + ntStatus = m_pInterruptSync->RegisterServiceRoutine( + DMusMPUInterruptServiceRoutine, + PVOID(this), + TRUE); // run this ISR first + } + if (NT_SUCCESS(ntStatus)) + { + ntStatus = m_pInterruptSync->Connect(); + } + } + } + + if (NT_SUCCESS(ntStatus)) + { + ntStatus = ProcessResources(ResourceList); + } + + if (!NT_SUCCESS(ntStatus)) + { + // + // clean up our mess + // + + // clean up the interrupt sync + if( m_pInterruptSync ) + { + m_pInterruptSync->Release(); + m_pInterruptSync = NULL; + } + + // clean up the service group + if( m_pServiceGroup ) + { + m_pServiceGroup->Release(); + m_pServiceGroup = NULL; + } + + // clean up the out param service group. + if (*ServiceGroup) + { + (*ServiceGroup)->Release(); + (*ServiceGroup) = NULL; + } + + // release the port + m_pPort->Release(); + m_pPort = NULL; + } + + return ntStatus; +} + +#ifdef _MSC_VER +#pragma code_seg("PAGE") +#endif +/***************************************************************************** + * CMiniportDMusUART::NewStream() + ***************************************************************************** + * Gets the topology. + */ +STDMETHODIMP_(NTSTATUS) +CMiniportDMusUART:: +NewStream +( + OUT PMXF * MXF, + IN PUNKNOWN OuterUnknown OPTIONAL, + IN POOL_TYPE PoolType, + IN ULONG PinID, + IN DMUS_STREAM_TYPE StreamType, + IN PKSDATAFORMAT DataFormat, + OUT PSERVICEGROUP * ServiceGroup, + IN PAllocatorMXF AllocatorMXF, + IN PMASTERCLOCK MasterClock, + OUT PULONGLONG SchedulePreFetch +) +{ + PAGED_CODE(); + + DPRINT("NewStream"); + NTSTATUS ntStatus = STATUS_SUCCESS; + + // In 100 ns, we want stuff as soon as it comes in + // + *SchedulePreFetch = 0; + + // if we don't have any streams already open, get the hardware ready. + if ((!m_NumCaptureStreams) && (!m_NumRenderStreams)) + { + ntStatus = ResetHardware(m_pPortBase); + if (!NT_SUCCESS(ntStatus)) + { + DPRINT("CMiniportDMusUART::NewStream ResetHardware failed"); + return ntStatus; + } + } + + if ( ((m_NumCaptureStreams < kMaxNumCaptureStreams) + && (StreamType == DMUS_STREAM_MIDI_CAPTURE)) + || ((m_NumRenderStreams < kMaxNumLegacyRenderStreams + kMaxNumDMusicRenderStreams) + && (StreamType == DMUS_STREAM_MIDI_RENDER)) + ) + { + CMiniportDMusUARTStream *pStream = + new(PoolType) CMiniportDMusUARTStream(); + + if (pStream) + { + pStream->AddRef(); + + ntStatus = + pStream->Init(this,m_pPortBase,(StreamType == DMUS_STREAM_MIDI_CAPTURE),AllocatorMXF,MasterClock); + + if (NT_SUCCESS(ntStatus)) + { + *MXF = PMXF(pStream); + (*MXF)->AddRef(); + + if (StreamType == DMUS_STREAM_MIDI_CAPTURE) + { + m_NumCaptureStreams++; + *ServiceGroup = m_pServiceGroup; + (*ServiceGroup)->AddRef(); + } + else + { + m_NumRenderStreams++; + *ServiceGroup = NULL; + } + } + + pStream->Release(); + } + else + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + } + else + { + ntStatus = STATUS_INVALID_DEVICE_REQUEST; + if (StreamType == DMUS_STREAM_MIDI_CAPTURE) + { + DPRINT("NewStream failed, too many capture streams"); + } + else if (StreamType == DMUS_STREAM_MIDI_RENDER) + { + DPRINT("NewStream failed, too many render streams"); + } + else + { + DPRINT("NewStream invalid stream type"); + } + } + + return ntStatus; +} + +#ifdef _MSC_VER +#pragma code_seg("PAGE") +#endif +/***************************************************************************** + * CMiniportDMusUART::SetTechnology() + ***************************************************************************** + * Sets pindatarange technology. + */ +STDMETHODIMP_(NTSTATUS) +CMiniportDMusUART:: +SetTechnology +( + IN const GUID * Technology +) +{ + PAGED_CODE(); + + NTSTATUS ntStatus = STATUS_UNSUCCESSFUL; + + // Fail if miniport has already been initialized. + // + if (NULL == m_pPort) + { + RtlCopyMemory(&m_MusicFormatTechnology, Technology, sizeof(GUID)); + ntStatus = STATUS_SUCCESS; + } + + return ntStatus; +} // SetTechnology + +/***************************************************************************** + * CMiniportDMusUART::PowerChangeNotify() + ***************************************************************************** + * Handle power state change for the miniport. + */ +#ifdef _MSC_VER +#pragma code_seg("PAGE") +#endif + +STDMETHODIMP_(void) +CMiniportDMusUART:: +PowerChangeNotify +( + IN POWER_STATE PowerState +) +{ + PAGED_CODE(); + + DPRINT("CMiniportDMusUART::PoweChangeNotify D%d", PowerState.DeviceState); + + switch (PowerState.DeviceState) + { + case PowerDeviceD0: + if (m_PowerState.DeviceState != PowerDeviceD0) + { + if (!NT_SUCCESS(InitializeHardware(m_pInterruptSync,m_pPortBase))) + { + DPRINT("InitializeHardware failed when resuming"); + } + } + break; + + case PowerDeviceD1: + case PowerDeviceD2: + case PowerDeviceD3: + default: + break; + } + m_PowerState.DeviceState = PowerState.DeviceState; +} // PowerChangeNotify + +#ifdef _MSC_VER +#pragma code_seg("PAGE") +#endif +/***************************************************************************** + * CMiniportDMusUARTStream::NonDelegatingQueryInterface() + ***************************************************************************** + * Obtains an interface. This function works just like a COM QueryInterface + * call and is used if the object is not being aggregated. + */ +STDMETHODIMP_(NTSTATUS) +CMiniportDMusUARTStream::QueryInterface +( + REFIID Interface, + PVOID * Object +) +{ + PAGED_CODE(); + + DPRINT("Stream::NonDelegatingQueryInterface"); + ASSERT(Object); + + if (IsEqualGUIDAligned(Interface,IID_IUnknown)) + { + *Object = PVOID(PUNKNOWN(this)); + } + else + if (IsEqualGUIDAligned(Interface,IID_IMXF)) + { + *Object = PVOID(PMXF(this)); + } + else + { + *Object = NULL; + } + + if (*Object) + { + // + // We reference the interface for the caller. + // + PUNKNOWN(*Object)->AddRef(); + return STATUS_SUCCESS; + } + + return STATUS_INVALID_PARAMETER; +} + +#ifdef _MSC_VER +#pragma code_seg("PAGE") +#endif +/***************************************************************************** + * CMiniportDMusUARTStream::~CMiniportDMusUARTStream() + ***************************************************************************** + * Destructs a stream. + */ +CMiniportDMusUARTStream::~CMiniportDMusUARTStream(void) +{ + PAGED_CODE(); + + DPRINT("~CMiniportDMusUARTStream"); + + KeCancelTimer(&m_TimerEvent); + + if (m_DMKEvtQueue) + { + if (m_AllocatorMXF) + { + m_AllocatorMXF->PutMessage(m_DMKEvtQueue); + } + else + { + DPRINT("~CMiniportDMusUARTStream, no allocator, can't flush DMKEvts"); + } + m_DMKEvtQueue = NULL; + } + if (m_AllocatorMXF) + { + m_AllocatorMXF->Release(); + m_AllocatorMXF = NULL; + } + + if (m_pMiniport) + { + if (m_fCapture) + { + m_pMiniport->m_NumCaptureStreams--; + } + else + { + m_pMiniport->m_NumRenderStreams--; + } + + m_pMiniport->Release(); + } +} + +#ifdef _MSC_VER +#pragma code_seg("PAGE") +#endif +/***************************************************************************** + * CMiniportDMusUARTStream::Init() + ***************************************************************************** + * Initializes a stream. + */ +STDMETHODIMP_(NTSTATUS) +CMiniportDMusUARTStream:: +Init +( + IN CMiniportDMusUART * pMiniport, + IN PUCHAR pPortBase, + IN BOOLEAN fCapture, + IN PAllocatorMXF allocatorMXF, + IN PMASTERCLOCK masterClock +) +{ + PAGED_CODE(); + + ASSERT(pMiniport); + ASSERT(pPortBase); + + DPRINT("Init"); + + m_NumFailedMPUTries = 0; + m_TimerQueued = FALSE; + KeInitializeSpinLock(&m_DpcSpinLock); + m_pMiniport = pMiniport; + m_pMiniport->AddRef(); + + pMiniport->m_MasterClock = masterClock; + + m_pPortBase = pPortBase; + m_fCapture = fCapture; + + m_SnapshotTimeStamp = 0; + m_DMKEvtQueue = NULL; + m_DMKEvtOffset = 0; + + m_NumberOfRetries = 0; + + if (allocatorMXF) + { + allocatorMXF->AddRef(); + m_AllocatorMXF = allocatorMXF; + m_sinkMXF = m_AllocatorMXF; + } + else + { + return STATUS_INVALID_PARAMETER; + } + + KeInitializeDpc + ( + &m_Dpc, + &::DMusUARTTimerDPC, + PVOID(this) + ); + KeInitializeTimer(&m_TimerEvent); return STATUS_SUCCESS; } +#ifdef _MSC_VER +#pragma code_seg("PAGE") +#endif +/***************************************************************************** + * CMiniportDMusUARTStream::SetState() + ***************************************************************************** + * Sets the state of the channel. + */ +STDMETHODIMP_(NTSTATUS) +CMiniportDMusUARTStream:: +SetState +( + IN KSSTATE NewState +) +{ + PAGED_CODE(); + + DPRINT("SetState %d",NewState); + + if (NewState == KSSTATE_RUN) + { + if (m_pMiniport->m_fMPUInitialized) + { + LARGE_INTEGER timeDue100ns; + timeDue100ns.QuadPart = 0; + KeSetTimer(&m_TimerEvent,timeDue100ns,&m_Dpc); + } + else + { + DPRINT("CMiniportDMusUARTStream::SetState KSSTATE_RUN failed due to uninitialized MPU"); + return STATUS_INVALID_DEVICE_STATE; + } + } + + if (m_fCapture) + { + m_pMiniport->m_KSStateInput = NewState; + if (NewState == KSSTATE_STOP) // STOPping + { + m_pMiniport->m_MPUInputBufferHead = 0; // Previously read bytes are discarded. + m_pMiniport->m_MPUInputBufferTail = 0; // The entire FIFO is available. + } + } + return STATUS_SUCCESS; +} + +#ifdef _MSC_VER +#pragma code_seg() +#endif + + +/***************************************************************************** + * CMiniportDMusUART::Service() + ***************************************************************************** + * DPC-mode service call from the port. + */ +STDMETHODIMP_(void) +CMiniportDMusUART:: +Service +( void +) +{ + DPRINT("Service"); + if (!m_NumCaptureStreams) + { + // we should never get here.... + // if we do, we must have read some trash, + // so just reset the input FIFO + m_MPUInputBufferTail = m_MPUInputBufferHead = 0; + } +} + +#ifdef _MSC_VER +#pragma code_seg("PAGE") +#endif + +/***************************************************************************** + * CMiniportDMusUARTStream::ConnectOutput() + ***************************************************************************** + * Writes outgoing MIDI data. + */ +NTSTATUS +CMiniportDMusUARTStream:: +ConnectOutput(PMXF sinkMXF) +{ + PAGED_CODE(); + + if (m_fCapture) + { + if ((sinkMXF) && (m_sinkMXF == m_AllocatorMXF)) + { + DPRINT("ConnectOutput"); + m_sinkMXF = sinkMXF; + return STATUS_SUCCESS; + } + else + { + DPRINT("ConnectOutput failed"); + } + } + else + { + DPRINT("ConnectOutput called on renderer; failed"); + } + return STATUS_UNSUCCESSFUL; +} + +#ifdef _MSC_VER +#pragma code_seg("PAGE") +#endif + +/***************************************************************************** + * CMiniportDMusUARTStream::DisconnectOutput() + ***************************************************************************** + * Writes outgoing MIDI data. + */ +NTSTATUS +CMiniportDMusUARTStream:: +DisconnectOutput(PMXF sinkMXF) +{ + PAGED_CODE(); + + if (m_fCapture) + { + if ((m_sinkMXF == sinkMXF) || (!sinkMXF)) + { + DPRINT("DisconnectOutput"); + m_sinkMXF = m_AllocatorMXF; + return STATUS_SUCCESS; + } + else + { + DPRINT("DisconnectOutput failed"); + } + } + else + { + DPRINT("DisconnectOutput called on renderer; failed"); + } + return STATUS_UNSUCCESSFUL; +} + +#ifdef _MSC_VER +#pragma code_seg() +#endif + + +/***************************************************************************** + * CMiniportDMusUARTStream::PutMessageLocked() + ***************************************************************************** + * Now that the spinlock is held, add this message to the queue. + * + * Writes an outgoing MIDI message. + * We don't sort a new message into the queue -- we append it. + * This is fine, since the sequencer feeds us sequenced data. + * Timestamps will ascend by design. + */ +NTSTATUS CMiniportDMusUARTStream::PutMessageLocked(PDMUS_KERNEL_EVENT pDMKEvt) +{ + NTSTATUS ntStatus = STATUS_SUCCESS; + PDMUS_KERNEL_EVENT aDMKEvt; + + ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); + + if (!m_fCapture) + { + DPRINT("PutMessage to render stream"); + if (pDMKEvt) + { + // m_DpcSpinLock already held + + if (m_DMKEvtQueue) + { + aDMKEvt = m_DMKEvtQueue; // put pDMKEvt in event queue + + while (aDMKEvt->pNextEvt) + { + aDMKEvt = aDMKEvt->pNextEvt; + } + aDMKEvt->pNextEvt = pDMKEvt; // here is end of queue + } + else // currently nothing in queue + { + m_DMKEvtQueue = pDMKEvt; + if (m_DMKEvtOffset) + { + DPRINT("PutMessage Nothing in the queue, but m_DMKEvtOffset == %d",m_DMKEvtOffset); + m_DMKEvtOffset = 0; + } + } + + // m_DpcSpinLock already held + } + if (!m_TimerQueued) + { + (void) ConsumeEvents(); + } + } + else // capture + { + DPRINT("PutMessage to capture stream"); + ASSERT(NULL == pDMKEvt); + + SourceEvtsToPort(); + } + return ntStatus; +} + +#ifdef _MSC_VER +#pragma code_seg() +#endif + +/***************************************************************************** + * CMiniportDMusUARTStream::PutMessage() + ***************************************************************************** + * Writes an outgoing MIDI message. + * We don't sort a new message into the queue -- we append it. + * This is fine, since the sequencer feeds us sequenced data. + * Timestamps will ascend by design. + */ +NTSTATUS CMiniportDMusUARTStream::PutMessage(PDMUS_KERNEL_EVENT pDMKEvt) +{ + NTSTATUS ntStatus = STATUS_SUCCESS; + PDMUS_KERNEL_EVENT aDMKEvt; + + ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); + + if (!m_fCapture) + { + DPRINT("PutMessage to render stream"); + if (pDMKEvt) + { + KeAcquireSpinLockAtDpcLevel(&m_DpcSpinLock); + + if (m_DMKEvtQueue) + { + aDMKEvt = m_DMKEvtQueue; // put pDMKEvt in event queue + + while (aDMKEvt->pNextEvt) + { + aDMKEvt = aDMKEvt->pNextEvt; + } + aDMKEvt->pNextEvt = pDMKEvt; // here is end of queue + } + else // currently nothing in queue + { + m_DMKEvtQueue = pDMKEvt; + if (m_DMKEvtOffset) + { + DPRINT("PutMessage Nothing in the queue, but m_DMKEvtOffset == %d", m_DMKEvtOffset); + m_DMKEvtOffset = 0; + } + } + + KeReleaseSpinLockFromDpcLevel(&m_DpcSpinLock); + } + if (!m_TimerQueued) + { + (void) ConsumeEvents(); + } + } + else // capture + { + DPRINT("PutMessage to capture stream"); + ASSERT(NULL == pDMKEvt); + + SourceEvtsToPort(); + } + return ntStatus; +} + +#ifdef _MSC_VER +#pragma code_seg() +#endif + +/***************************************************************************** + * CMiniportDMusUARTStream::ConsumeEvents() + ***************************************************************************** + * Attempts to empty the render message queue. + * Called either from DPC timer or upon IRP submittal. +// TODO: support packages right +// process the package (actually, should do this above. +// treat the package as a list fragment that shouldn't be sorted. +// better yet, go through each event in the package, and when +// an event is exhausted, delete it and decrement m_offset. + */ +NTSTATUS CMiniportDMusUARTStream::ConsumeEvents(void) +{ + PDMUS_KERNEL_EVENT aDMKEvt; + + NTSTATUS ntStatus = STATUS_SUCCESS; + ULONG bytesRemaining = 0,bytesWritten = 0; + LARGE_INTEGER aMillisecIn100ns; + + ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); + KeAcquireSpinLockAtDpcLevel(&m_DpcSpinLock); + + m_TimerQueued = FALSE; + while (m_DMKEvtQueue) // do we have anything to play at all? + { + aDMKEvt = m_DMKEvtQueue; // event we try to play + if (aDMKEvt->cbEvent) + { + bytesRemaining = aDMKEvt->cbEvent - m_DMKEvtOffset; // number of bytes left in this evt + + ASSERT(bytesRemaining > 0); + if (bytesRemaining <= 0) + { + bytesRemaining = aDMKEvt->cbEvent; + } + + if (aDMKEvt->cbEvent <= sizeof(PBYTE)) // short message + { + DPRINT("ConsumeEvents(%02x%02x%02x%02x)", aDMKEvt->uData.abData[0], aDMKEvt->uData.abData[1], aDMKEvt->uData.abData[2], aDMKEvt->uData.abData[3]); + ntStatus = Write(aDMKEvt->uData.abData + m_DMKEvtOffset,bytesRemaining,&bytesWritten); + } + else if (PACKAGE_EVT(aDMKEvt)) + { + ASSERT(m_DMKEvtOffset == 0); + m_DMKEvtOffset = 0; + DPRINT("ConsumeEvents(Package)"); + + ntStatus = PutMessageLocked(aDMKEvt->uData.pPackageEvt); // we already own the spinlock + + // null this because we are about to throw it in the allocator + aDMKEvt->uData.pPackageEvt = NULL; + aDMKEvt->cbEvent = 0; + bytesWritten = bytesRemaining; + } + else // SysEx message + { + DPRINT("ConsumeEvents(%02x%02x%02x%02x)", aDMKEvt->uData.pbData[0], aDMKEvt->uData.pbData[1], aDMKEvt->uData.pbData[2], aDMKEvt->uData.pbData[3]); + + ntStatus = Write(aDMKEvt->uData.pbData + m_DMKEvtOffset,bytesRemaining,&bytesWritten); + } + } // if (aDMKEvt->cbEvent) + if (STATUS_SUCCESS != ntStatus) + { + DPRINT("ConsumeEvents: Write returned 0x%08x", ntStatus); + bytesWritten = bytesRemaining; // just bail on this event and try next time + } + + ASSERT(bytesWritten <= bytesRemaining); + if (bytesWritten == bytesRemaining) + { + m_DMKEvtQueue = m_DMKEvtQueue->pNextEvt; + aDMKEvt->pNextEvt = NULL; + + m_AllocatorMXF->PutMessage(aDMKEvt); // throw back in free pool + m_DMKEvtOffset = 0; // start fresh on next evt + m_NumberOfRetries = 0; + } // but wait ... there's more! + else // our FIFO is full for now. + { + // update our offset by that amount we did write + m_DMKEvtOffset += bytesWritten; + ASSERT(m_DMKEvtOffset < aDMKEvt->cbEvent); + + DPRINT("ConsumeEvents tried %d, wrote %d, at offset %d", bytesRemaining,bytesWritten,m_DMKEvtOffset); + aMillisecIn100ns.QuadPart = -(kOneMillisec); // set timer, come back later + m_TimerQueued = TRUE; + m_NumberOfRetries++; + ntStatus = KeSetTimer( &m_TimerEvent, aMillisecIn100ns, &m_Dpc ); + break; + } // we didn't write it all + } // go back, Jack, do it again (while m_DMKEvtQueue) + KeReleaseSpinLockFromDpcLevel(&m_DpcSpinLock); + return ntStatus; +} + +#ifdef _MSC_VER +#pragma code_seg() +#endif + +/***************************************************************************** + * CMiniportDMusUARTStream::HandlePortParams() + ***************************************************************************** + * Writes an outgoing MIDI message. + */ +NTSTATUS +CMiniportDMusUARTStream:: +HandlePortParams +( + IN PPCPROPERTY_REQUEST pRequest +) +{ + PAGED_CODE(); + + NTSTATUS ntStatus; + + if (pRequest->Verb & KSPROPERTY_TYPE_SET) + { + return STATUS_INVALID_DEVICE_REQUEST; + } + + ntStatus = ValidatePropertyRequest(pRequest, sizeof(SYNTH_PORTPARAMS), TRUE); + if (NT_SUCCESS(ntStatus)) + { + RtlCopyMemory(pRequest->Value, pRequest->Instance, sizeof(SYNTH_PORTPARAMS)); + + PSYNTH_PORTPARAMS Params = (PSYNTH_PORTPARAMS)pRequest->Value; + + if (Params->ValidParams & ~SYNTH_PORTPARAMS_CHANNELGROUPS) + { + Params->ValidParams &= SYNTH_PORTPARAMS_CHANNELGROUPS; + } + + if (!(Params->ValidParams & SYNTH_PORTPARAMS_CHANNELGROUPS)) + { + Params->ChannelGroups = 1; + } + else if (Params->ChannelGroups != 1) + { + Params->ChannelGroups = 1; + } + + pRequest->ValueSize = sizeof(SYNTH_PORTPARAMS); + } + + return ntStatus; +} + +#ifdef _MSC_VER +#pragma code_seg() +#endif + +/***************************************************************************** + * DMusTimerDPC() + ***************************************************************************** + * The timer DPC callback. Thunks to a C++ member function. + * This is called by the OS in response to the DirectMusic pin + * wanting to wakeup later to process more DirectMusic stuff. + */ +VOID +NTAPI +DMusUARTTimerDPC +( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2 +) +{ + ASSERT(DeferredContext); + + CMiniportDMusUARTStream *aStream; + aStream = (CMiniportDMusUARTStream *) DeferredContext; + if (aStream) + { + DPRINT("DMusUARTTimerDPC"); + if (false == aStream->m_fCapture) + { + (void) aStream->ConsumeEvents(); + } + // ignores return value! + } +} + +/***************************************************************************** + * DirectMusic properties + ****************************************************************************/ + +#ifdef _MSC_VER +#pragma code_seg() +#endif + +/* + * Properties concerning synthesizer functions. + */ +const WCHAR wszDescOut[] = L"DMusic MPU-401 Out "; +const WCHAR wszDescIn[] = L"DMusic MPU-401 In "; + +NTSTATUS PropertyHandler_Synth +( + IN PPCPROPERTY_REQUEST pRequest +) +{ + NTSTATUS ntStatus; + + PAGED_CODE(); + + if (pRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) + { + ntStatus = ValidatePropertyRequest(pRequest, sizeof(ULONG), TRUE); + if (NT_SUCCESS(ntStatus)) + { + // if return buffer can hold a ULONG, return the access flags + PULONG AccessFlags = PULONG(pRequest->Value); + + *AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT; + switch (pRequest->PropertyItem->Id) + { + case KSPROPERTY_SYNTH_CAPS: + case KSPROPERTY_SYNTH_CHANNELGROUPS: + *AccessFlags |= KSPROPERTY_TYPE_GET; + } + switch (pRequest->PropertyItem->Id) + { + case KSPROPERTY_SYNTH_CHANNELGROUPS: + *AccessFlags |= KSPROPERTY_TYPE_SET; + } + ntStatus = STATUS_SUCCESS; + pRequest->ValueSize = sizeof(ULONG); + + switch (pRequest->PropertyItem->Id) + { + case KSPROPERTY_SYNTH_PORTPARAMETERS: + if (pRequest->MinorTarget) + { + *AccessFlags |= KSPROPERTY_TYPE_GET; + } + else + { + pRequest->ValueSize = 0; + ntStatus = STATUS_INVALID_DEVICE_REQUEST; + } + } + } + } + else + { + ntStatus = STATUS_SUCCESS; + switch(pRequest->PropertyItem->Id) + { + case KSPROPERTY_SYNTH_CAPS: + DPRINT("PropertyHandler_Synth:KSPROPERTY_SYNTH_CAPS"); + + if (pRequest->Verb & KSPROPERTY_TYPE_SET) + { + ntStatus = STATUS_INVALID_DEVICE_REQUEST; + } + + if (NT_SUCCESS(ntStatus)) + { + ntStatus = ValidatePropertyRequest(pRequest, sizeof(SYNTHCAPS), TRUE); + + if (NT_SUCCESS(ntStatus)) + { + SYNTHCAPS *caps = (SYNTHCAPS*)pRequest->Value; + int increment; + RtlZeroMemory(caps, sizeof(SYNTHCAPS)); + // XXX Different guids for different instances! + // + if (pRequest->Node == eSynthNode) + { + increment = sizeof(wszDescOut) - 2; + RtlCopyMemory( caps->Description,wszDescOut,increment); + caps->Guid = CLSID_MiniportDriverDMusUART; + } + else + { + increment = sizeof(wszDescIn) - 2; + RtlCopyMemory( caps->Description,wszDescIn,increment); + caps->Guid = CLSID_MiniportDriverDMusUARTCapture; + } + + caps->Flags = SYNTH_PC_EXTERNAL; + caps->MemorySize = 0; + caps->MaxChannelGroups = 1; + caps->MaxVoices = 0xFFFFFFFF; + caps->MaxAudioChannels = 0xFFFFFFFF; + + caps->EffectFlags = 0; + + CMiniportDMusUART *aMiniport; + ASSERT(pRequest->MajorTarget); + aMiniport = (CMiniportDMusUART *)(PMINIPORTDMUS)(pRequest->MajorTarget); + WCHAR wszDesc2[16]; + int cLen; + cLen = swprintf(wszDesc2,L"[%03x]\0",PtrToUlong(aMiniport->m_pPortBase)); + + cLen *= sizeof(WCHAR); + RtlCopyMemory((WCHAR *)((DWORD_PTR)(caps->Description) + increment), + wszDesc2, + cLen); + + + pRequest->ValueSize = sizeof(SYNTHCAPS); + } + } + + break; + + case KSPROPERTY_SYNTH_PORTPARAMETERS: + DPRINT("PropertyHandler_Synth:KSPROPERTY_SYNTH_PORTPARAMETERS"); + { + CMiniportDMusUARTStream *aStream; + + aStream = (CMiniportDMusUARTStream*)(pRequest->MinorTarget); + if (aStream) + { + ntStatus = aStream->HandlePortParams(pRequest); + } + else + { + ntStatus = STATUS_INVALID_DEVICE_REQUEST; + } + } + break; + + case KSPROPERTY_SYNTH_CHANNELGROUPS: + DPRINT("PropertyHandler_Synth:KSPROPERTY_SYNTH_CHANNELGROUPS"); + + ntStatus = ValidatePropertyRequest(pRequest, sizeof(ULONG), TRUE); + if (NT_SUCCESS(ntStatus)) + { + *(PULONG)(pRequest->Value) = 1; + pRequest->ValueSize = sizeof(ULONG); + } + break; + + case KSPROPERTY_SYNTH_LATENCYCLOCK: + DPRINT("PropertyHandler_Synth:KSPROPERTY_SYNTH_LATENCYCLOCK"); + + if(pRequest->Verb & KSPROPERTY_TYPE_SET) + { + ntStatus = STATUS_INVALID_DEVICE_REQUEST; + } + else + { + ntStatus = ValidatePropertyRequest(pRequest, sizeof(ULONGLONG), TRUE); + if(NT_SUCCESS(ntStatus)) + { + REFERENCE_TIME rtLatency; + CMiniportDMusUARTStream *aStream; + + aStream = (CMiniportDMusUARTStream*)(pRequest->MinorTarget); + if(aStream == NULL) + { + ntStatus = STATUS_INVALID_DEVICE_REQUEST; + } + else + { + aStream->m_pMiniport->m_MasterClock->GetTime(&rtLatency); + *((PULONGLONG)pRequest->Value) = rtLatency; + pRequest->ValueSize = sizeof(ULONGLONG); + } + } + } + break; + + default: + DPRINT("Unhandled property in PropertyHandler_Synth"); + break; + } + } + return ntStatus; +} + +/***************************************************************************** + * ValidatePropertyRequest() + ***************************************************************************** + * Validates pRequest. + * Checks if the ValueSize is valid + * Checks if the Value is valid + * + * This does not update pRequest->ValueSize if it returns NT_SUCCESS. + * Caller must set pRequest->ValueSize in case of NT_SUCCESS. + */ +NTSTATUS ValidatePropertyRequest +( + IN PPCPROPERTY_REQUEST pRequest, + IN ULONG ulValueSize, + IN BOOLEAN fValueRequired +) +{ + NTSTATUS ntStatus; + + if (pRequest->ValueSize >= ulValueSize) + { + if (fValueRequired && NULL == pRequest->Value) + { + ntStatus = STATUS_INVALID_PARAMETER; + } + else + { + ntStatus = STATUS_SUCCESS; + } + } + else if (0 == pRequest->ValueSize) + { + ntStatus = STATUS_BUFFER_OVERFLOW; + } + else + { + ntStatus = STATUS_BUFFER_TOO_SMALL; + } + + if (STATUS_BUFFER_OVERFLOW == ntStatus) + { + pRequest->ValueSize = ulValueSize; + } + else + { + pRequest->ValueSize = 0; + } + + return ntStatus; +} // ValidatePropertyRequest + +#ifdef _MSC_VER +#pragma code_seg() +#endif + diff --git a/drivers/wdm/audio/backpln/portcls/pin_dmus.cpp b/drivers/wdm/audio/backpln/portcls/pin_dmus.cpp index 5a616f302ec..848e4e98795 100644 --- a/drivers/wdm/audio/backpln/portcls/pin_dmus.cpp +++ b/drivers/wdm/audio/backpln/portcls/pin_dmus.cpp @@ -604,7 +604,7 @@ CPortPinDMus::Init( } } - Status = m_IrpQueue->Init(ConnectDetails, 0, 0); + Status = m_IrpQueue->Init(ConnectDetails, KsPinDescriptor, 0, 0, FALSE); if (!NT_SUCCESS(Status)) { DPRINT("IrpQueue_Init failed with %x\n", Status); diff --git a/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp b/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp index 226457c1059..7733606c6a5 100644 --- a/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp +++ b/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp @@ -699,15 +699,15 @@ CPortPinWaveCyclic::UpdateCommonBuffer( if (!NT_SUCCESS(Status)) { Gap = Position - m_CommonBufferOffset; - if (Gap > m_FrameSize) + if (Gap > BufferLength) { // insert silence samples - DPRINT1("Inserting Silence Buffer Offset %lu GapLength %lu\n", m_CommonBufferOffset, BufferLength); + DPRINT("Inserting Silence Buffer Offset %lu GapLength %lu\n", m_CommonBufferOffset, BufferLength); m_Stream->Silence((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, BufferLength); m_CommonBufferOffset += BufferLength; - break; } + break; } BytesToCopy = min(BufferLength, BufferSize); @@ -758,10 +758,10 @@ CPortPinWaveCyclic::UpdateCommonBufferOverlap( if (!NT_SUCCESS(Status)) { Gap = m_CommonBufferSize - m_CommonBufferOffset + Position; - if (Gap > m_FrameSize) + if (Gap > BufferLength) { // insert silence samples - DPRINT1("Overlap Inserting Silence Buffer Size %lu Offset %lu Gap %lu Position %lu\n", m_CommonBufferSize, m_CommonBufferOffset, Gap, Position); + DPRINT("Overlap Inserting Silence Buffer Size %lu Offset %lu Gap %lu Position %lu\n", m_CommonBufferSize, m_CommonBufferOffset, Gap, Position); m_Stream->Silence((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, BufferLength); m_CommonBufferOffset += BufferLength; @@ -771,7 +771,7 @@ CPortPinWaveCyclic::UpdateCommonBufferOverlap( BytesToCopy = min(BufferLength, BufferSize); - if (m_Capture) + if (m_Capture) { m_DmaChannel->CopyFrom(Buffer, (PUCHAR)m_CommonBuffer + m_CommonBufferOffset, @@ -1290,7 +1290,7 @@ CPortPinWaveCyclic::Init( PC_ASSERT(NT_SUCCESS(Status)); PC_ASSERT(m_FrameSize); - DPRINT1("Bits %u Samples %u Channels %u Tag %u FrameSize %u CommonBufferSize %lu\n", ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.wBitsPerSample, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.nSamplesPerSec, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.nChannels, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.wFormatTag, m_FrameSize, m_CommonBufferSize); + DPRINT1("Bits %u Samples %u Channels %u Tag %u FrameSize %u CommonBufferSize %lu, CommonBuffer %p\n", ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.wBitsPerSample, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.nSamplesPerSec, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.nChannels, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.wFormatTag, m_FrameSize, m_CommonBufferSize, m_DmaChannel->SystemAddress()); /* set up allocator framing */ @@ -1303,7 +1303,7 @@ CPortPinWaveCyclic::Init( m_Stream->Silence(m_CommonBuffer, m_CommonBufferSize); - Status = m_IrpQueue->Init(ConnectDetails, m_FrameSize, 0); + Status = m_IrpQueue->Init(ConnectDetails, KsPinDescriptor, m_FrameSize, 0, FALSE); if (!NT_SUCCESS(Status)) { m_IrpQueue->Release(); diff --git a/drivers/wdm/audio/backpln/portcls/pin_wavepci.cpp b/drivers/wdm/audio/backpln/portcls/pin_wavepci.cpp index 9a1cc75613b..021648a9dd1 100644 --- a/drivers/wdm/audio/backpln/portcls/pin_wavepci.cpp +++ b/drivers/wdm/audio/backpln/portcls/pin_wavepci.cpp @@ -919,7 +919,7 @@ CPortPinWavePci::Init( } // initialize irp queue - Status = m_IrpQueue->Init(ConnectDetails, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment); + Status = m_IrpQueue->Init(ConnectDetails, KsPinDescriptor, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment, TRUE); if (!NT_SUCCESS(Status)) { // this should never happen diff --git a/drivers/wdm/audio/backpln/portcls/pin_wavert.cpp b/drivers/wdm/audio/backpln/portcls/pin_wavert.cpp index fd6be3cc28f..f9a2644bb62 100644 --- a/drivers/wdm/audio/backpln/portcls/pin_wavert.cpp +++ b/drivers/wdm/audio/backpln/portcls/pin_wavert.cpp @@ -283,7 +283,7 @@ NTAPI CPortPinWaveRT::HandleKsStream( IN PIRP Irp) { - DPRINT("IPortPinWaveRT_HandleKsStream entered State %u Stream %p\n", m_State, m_Stream); + DPRINT("IPortPinWaveRT_HandleKsStream entered State %u Stream %p is UNIMPLEMENTED\n", m_State, m_Stream); return STATUS_PENDING; } @@ -587,7 +587,7 @@ CPortPinWaveRT::Init( goto cleanup; } - Status = m_IrpQueue->Init(ConnectDetails, 0, 0); + Status = m_IrpQueue->Init(ConnectDetails, KsPinDescriptor, 0, 0, FALSE); if (!NT_SUCCESS(Status)) { goto cleanup; @@ -624,7 +624,7 @@ CPortPinWaveRT::Init( // delay of 10 milisec m_Delay = Int32x32To64(10, -10000); - Status = m_Stream->AllocateAudioBuffer(16384 * 11, &m_Mdl, &m_CommonBufferSize, &m_CommonBufferOffset, &m_CacheType); + Status = m_Stream->AllocateAudioBuffer(16384 * 11, &m_Mdl, &m_CommonBufferSize, &m_CommonBufferOffset, &m_CacheType); if (!NT_SUCCESS(Status)) { DPRINT("AllocateAudioBuffer failed with %x\n", Status); diff --git a/drivers/wdm/audio/backpln/portcls/port_topology.cpp b/drivers/wdm/audio/backpln/portcls/port_topology.cpp index ab4322aa943..d1040aa9c60 100644 --- a/drivers/wdm/audio/backpln/portcls/port_topology.cpp +++ b/drivers/wdm/audio/backpln/portcls/port_topology.cpp @@ -251,7 +251,7 @@ CPortTopology::Init( // create the subdevice descriptor Status = PcCreateSubdeviceDescriptor(&m_SubDeviceDescriptor, 2, - InterfaceGuids, + InterfaceGuids, 0, NULL, 2, diff --git a/drivers/wdm/audio/backpln/portcls/port_wavecyclic.cpp b/drivers/wdm/audio/backpln/portcls/port_wavecyclic.cpp index 41879cd8950..3262b5f64b0 100644 --- a/drivers/wdm/audio/backpln/portcls/port_wavecyclic.cpp +++ b/drivers/wdm/audio/backpln/portcls/port_wavecyclic.cpp @@ -39,10 +39,8 @@ public: virtual ~CPortWaveCyclic(){} protected: - BOOL m_bInitialized; PDEVICE_OBJECT m_pDeviceObject; PMINIPORTWAVECYCLIC m_pMiniport; - PRESOURCELIST m_pResourceList; PPINCOUNT m_pPinCount; PPOWERNOTIFY m_pPowerNotify; PPCFILTER_DESCRIPTOR m_pDescriptor; @@ -202,12 +200,6 @@ CPortWaveCyclic::GetDeviceProperty( { PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); - if (!m_bInitialized) - { - DPRINT("IPortWaveCyclic_fnNewRegistryKey called w/o initiazed\n"); - return STATUS_UNSUCCESSFUL; - } - return IoGetDeviceProperty(m_pDeviceObject, DeviceRegistryProperty, BufferLength, PropertyBuffer, ReturnLength); } @@ -228,12 +220,6 @@ CPortWaveCyclic::Init( DPRINT("IPortWaveCyclic_Init entered %p\n", this); PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); - if (m_bInitialized) - { - DPRINT("IPortWaveCyclic_Init called again\n"); - return STATUS_SUCCESS; - } - Status = UnknownMiniport->QueryInterface(IID_IMiniportWaveCyclic, (PVOID*)&Miniport); if (!NT_SUCCESS(Status)) { @@ -244,22 +230,13 @@ CPortWaveCyclic::Init( // Initialize port object m_pMiniport = Miniport; m_pDeviceObject = DeviceObject; - m_bInitialized = TRUE; - m_pResourceList = ResourceList; - - - if (ResourceList) - { - // increment reference on resource list - ResourceList->AddRef(); - } + // initialize miniport Status = Miniport->Init(UnknownAdapter, ResourceList, this); if (!NT_SUCCESS(Status)) { DPRINT("IMiniportWaveCyclic_Init failed with %x\n", Status); Miniport->Release(); - m_bInitialized = FALSE; return Status; } @@ -270,7 +247,6 @@ CPortWaveCyclic::Init( { DPRINT("failed to get description\n"); Miniport->Release(); - m_bInitialized = FALSE; return Status; } @@ -294,7 +270,6 @@ CPortWaveCyclic::Init( { DPRINT("PcCreateSubdeviceDescriptor failed with %x\n", Status); Miniport->Release(); - m_bInitialized = FALSE; return Status; } @@ -335,11 +310,6 @@ CPortWaveCyclic::NewRegistryKey( { PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); - if (!m_bInitialized) - { - DPRINT("IPortWaveCyclic_fnNewRegistryKey called w/o initialized\n"); - return STATUS_UNSUCCESSFUL; - } return PcNewRegistryKey(OutRegistryKey, OuterUnknown, RegistryKeyType, DesiredAccess, m_pDeviceObject, (ISubdevice*)this, ObjectAttributes, CreateOptions, Disposition); } @@ -365,12 +335,6 @@ CPortWaveCyclic::NewMasterDmaChannel( PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); - if (!m_bInitialized) - { - DPRINT("IPortWaveCyclic_fnNewSlaveDmaChannel called w/o initialized\n"); - return STATUS_UNSUCCESSFUL; - } - Status = PcDmaMasterDescription(ResourceList, (Dma32BitAddresses | Dma64BitAddresses), Dma32BitAddresses, 0, Dma64BitAddresses, DmaWidth, DmaSpeed, MaximumLength, 0, &DeviceDescription); if (NT_SUCCESS(Status)) { @@ -397,12 +361,6 @@ CPortWaveCyclic::NewSlaveDmaChannel( PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); - if (!m_bInitialized) - { - DPRINT("IPortWaveCyclic_fnNewSlaveDmaChannel called w/o initialized\n"); - return STATUS_UNSUCCESSFUL; - } - // FIXME // Check for F-Type DMA Support // diff --git a/drivers/wdm/audio/backpln/portcls/port_wavepci.cpp b/drivers/wdm/audio/backpln/portcls/port_wavepci.cpp index ec451fe6067..64e90097389 100644 --- a/drivers/wdm/audio/backpln/portcls/port_wavepci.cpp +++ b/drivers/wdm/audio/backpln/portcls/port_wavepci.cpp @@ -43,8 +43,6 @@ protected: PMINIPORTWAVEPCI m_Miniport; PDEVICE_OBJECT m_pDeviceObject; - BOOL m_bInitialized; - PRESOURCELIST m_pResourceList; PSERVICEGROUP m_ServiceGroup; PPINCOUNT m_pPinCount; PPOWERNOTIFY m_pPowerNotify; @@ -233,12 +231,6 @@ CPortWavePci::Init( this, DeviceObject, Irp, UnknownMiniport, UnknownAdapter, ResourceList); PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); - if (m_bInitialized) - { - DPRINT("IPortWavePci_fnInit called again\n"); - return STATUS_SUCCESS; - } - Status = UnknownMiniport->QueryInterface(IID_IMiniportWavePci, (PVOID*)&Miniport); if (!NT_SUCCESS(Status)) { @@ -249,30 +241,20 @@ CPortWavePci::Init( // Initialize port object m_Miniport = Miniport; m_pDeviceObject = DeviceObject; - m_bInitialized = TRUE; - m_pResourceList = ResourceList; + InitializeListHead(&m_EventList); KeInitializeSpinLock(&m_EventListLock); // increment reference on miniport adapter Miniport->AddRef(); - - if (ResourceList) - { - // increment reference on resource list - ResourceList->AddRef(); - } - Status = Miniport->Init(UnknownAdapter, ResourceList, this, &ServiceGroup); if (!NT_SUCCESS(Status)) { DPRINT("IPortWavePci_fnInit failed with %x\n", Status); - m_bInitialized = FALSE; + // release reference on miniport adapter Miniport->Release(); - // increment reference on resource list - ResourceList->Release(); return Status; } @@ -282,7 +264,6 @@ CPortWavePci::Init( { DPRINT("failed to get description\n"); Miniport->Release(); - m_bInitialized = FALSE; return Status; } @@ -307,7 +288,6 @@ CPortWavePci::Init( { DPRINT("PcCreateSubdeviceDescriptor failed with %x\n", Status); Miniport->Release(); - m_bInitialized = FALSE; return Status; } @@ -361,12 +341,6 @@ CPortWavePci::NewRegistryKey( DPRINT("IPortWavePci_fnNewRegistryKey entered\n"); PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); - if (!m_bInitialized) - { - DPRINT("IPortWavePci_fnNewRegistryKey called w/o initiazed\n"); - return STATUS_UNSUCCESSFUL; - } - return PcNewRegistryKey(OutRegistryKey, OuterUnknown, RegistryKeyType, @@ -389,12 +363,6 @@ CPortWavePci::GetDeviceProperty( DPRINT("IPortWavePci_fnGetDeviceProperty entered\n"); PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); - if (!m_bInitialized) - { - DPRINT("IPortWavePci_fnNewRegistryKey called w/o initiazed\n"); - return STATUS_UNSUCCESSFUL; - } - return IoGetDeviceProperty(m_pDeviceObject, DeviceRegistryProperty, BufferLength, PropertyBuffer, ReturnLength); } @@ -434,8 +402,6 @@ NTAPI CPortWavePci::Notify( IN PSERVICEGROUP ServiceGroup) { - //IPortWavePciImpl * This = (IPortWavePciImpl*)iface; - //DPRINT("IPortWavePci_fnNotify entered %p, ServiceGroup %p\n", This, ServiceGroup); if (ServiceGroup) @@ -492,8 +458,6 @@ NTSTATUS NTAPI CPortWavePci::ReleaseChildren() { - //IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblSubDevice); - UNIMPLEMENTED return STATUS_UNSUCCESSFUL; } diff --git a/drivers/wdm/audio/backpln/portcls/private.hpp b/drivers/wdm/audio/backpln/portcls/private.hpp index e2e600bd75e..df0c9cf9e1e 100644 --- a/drivers/wdm/audio/backpln/portcls/private.hpp +++ b/drivers/wdm/audio/backpln/portcls/private.hpp @@ -22,6 +22,8 @@ #include "interfaces.hpp" #include #include +#include + //#include #define TAG_PORTCLASS 'SLCP' diff --git a/drivers/wdm/audio/legacy/wdmaud/control.c b/drivers/wdm/audio/legacy/wdmaud/control.c index 3af87b858c3..afc692c15ac 100644 --- a/drivers/wdm/audio/legacy/wdmaud/control.c +++ b/drivers/wdm/audio/legacy/wdmaud/control.c @@ -27,6 +27,12 @@ WdmAudControlOpen( return WdmAudControlOpenWave(DeviceObject, Irp, DeviceInfo, ClientInfo); } + if (DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE || DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE) + { + return WdmAudControlOpenMidi(DeviceObject, Irp, DeviceInfo, ClientInfo); + } + + return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO)); } @@ -55,6 +61,15 @@ WdmAudControlDeviceType( { Result = WdmAudGetWaveOutDeviceCount(); } + else if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE) + { + Result = WdmAudGetMidiInDeviceCount(); + } + else if (DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE) + { + Result = WdmAudGetMidiOutDeviceCount(); + } + /* store result count */ DeviceInfo->DeviceCount = Result; @@ -121,6 +136,10 @@ WdmAudCapabilities( { Status = WdmAudWaveCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension); } + else if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE || DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE) + { + Status = WdmAudMidiCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension); + } return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); } @@ -219,80 +238,38 @@ WdmAudGetDeviceInterface( /* get device interface string input length */ Size = DeviceInfo->u.Interface.DeviceInterfaceStringSize; - if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) + /* get mixer info */ + Status = WdmAudGetPnpNameByIndexAndType(DeviceInfo->DeviceIndex, DeviceInfo->DeviceType, &Device); + + /* check for success */ + if (!NT_SUCCESS(Status)) + { + /* invalid device id */ + return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); + } + + /* calculate length */ + Length = (wcslen(Device)+1) * sizeof(WCHAR); + + if (!Size) { - /* get wave info */ - Status = WdmAudGetPnpNameByIndexAndType(DeviceInfo->DeviceIndex, DeviceInfo->DeviceType, &Device); - - /* check for success */ - if (!NT_SUCCESS(Status)) - { - /* invalid device id */ - return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); - } - - /* calculate length */ - Length = (wcslen(Device)+1) * sizeof(WCHAR); - - if (!Size) - { - /* store device interface size */ - DeviceInfo->u.Interface.DeviceInterfaceStringSize = Length; - } - else if (Size < Length) - { - /* buffer too small */ - DeviceInfo->u.Interface.DeviceInterfaceStringSize = Length; - return SetIrpIoStatus(Irp, STATUS_BUFFER_OVERFLOW, sizeof(WDMAUD_DEVICE_INFO)); - } - else - { - //FIXME SEH - RtlMoveMemory(DeviceInfo->u.Interface.DeviceInterfaceString, Device, Length); - } - - FreeItem(Device); - return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); + /* store device interface size */ + DeviceInfo->u.Interface.DeviceInterfaceStringSize = Length; } - else if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE) + else if (Size < Length) { - if (DeviceInfo->DeviceIndex >= WdmAudGetMixerDeviceCount()) - { - /* invalid device id */ - return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, sizeof(WDMAUD_DEVICE_INFO)); - } - - Status = WdmAudGetMixerPnpNameByIndex(DeviceInfo->DeviceIndex, &Device); - /* check for success */ - if (!NT_SUCCESS(Status)) - { - /* invalid device id */ - return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); - } - - /* calculate length */ - Length = (wcslen(Device)+1) * sizeof(WCHAR); - - if (!Size) - { - /* store device interface size */ - DeviceInfo->u.Interface.DeviceInterfaceStringSize = Length; - } - else if (Size < Length) - { - /* buffer too small */ - DeviceInfo->u.Interface.DeviceInterfaceStringSize = Length; - return SetIrpIoStatus(Irp, STATUS_BUFFER_OVERFLOW, sizeof(WDMAUD_DEVICE_INFO)); - } - else - { - //FIXME SEH - RtlMoveMemory(DeviceInfo->u.Interface.DeviceInterfaceString, Device, Length); - } - return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); + /* buffer too small */ + DeviceInfo->u.Interface.DeviceInterfaceStringSize = Length; + return SetIrpIoStatus(Irp, STATUS_BUFFER_OVERFLOW, sizeof(WDMAUD_DEVICE_INFO)); + } + else + { + //FIXME SEH + RtlMoveMemory(DeviceInfo->u.Interface.DeviceInterfaceString, Device, Length); } - return SetIrpIoStatus(Irp, STATUS_INVALID_DEVICE_REQUEST, sizeof(WDMAUD_DEVICE_INFO)); + FreeItem(Device); + return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); } NTSTATUS @@ -407,6 +384,93 @@ WdmAudDeviceControl( return SetIrpIoStatus(Irp, STATUS_NOT_IMPLEMENTED, 0); } +NTSTATUS +NTAPI +IoCompletion ( + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Ctx) +{ + PKSSTREAM_HEADER Header; + ULONG Length = 0; + PMDL Mdl, NextMdl; + PWDMAUD_COMPLETION_CONTEXT Context = (PWDMAUD_COMPLETION_CONTEXT)Ctx; + + /* get stream header */ + Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer; + + /* sanity check */ + ASSERT(Header); + + /* iterate through all stream headers and collect size */ + do + { + if (Context->Function == IOCTL_KS_READ_STREAM) + { + /* length is stored in DataUsed */ + Length += Header->DataUsed; + } + else + { + /* length stored in frameextend */ + Length += Header->FrameExtent; + } + + /* subtract size */ + Context->Length -= Header->Size; + + /* move to next stream header */ + Header = (PKSSTREAM_HEADER)((ULONG_PTR)Header + Header->Size); + + }while(Context->Length); + + /* time to free all allocated mdls */ + Mdl = Irp->MdlAddress; + + while(Mdl) + { + /* get next mdl */ + NextMdl = Mdl->Next; + + /* unlock pages */ + MmUnlockPages(Mdl); + + /* grab next mdl */ + Mdl = NextMdl; + } + + /* clear mdl list */ + Irp->MdlAddress = NULL; + + /* check if mdl is locked */ + if (Context->Mdl->MdlFlags & MDL_PAGES_LOCKED) + { + /* unlock pages */ + MmUnlockPages(Context->Mdl); + } + + /* now free the mdl */ + IoFreeMdl(Context->Mdl); + + DPRINT("IoCompletion Irp %p IoStatus %lx Information %lx Length %lu\n", Irp, Irp->IoStatus.Status, Irp->IoStatus.Information, Length); + + if (Irp->IoStatus.Status == STATUS_SUCCESS) + { + /* store the length */ + Irp->IoStatus.Information = Length; + } + else + { + /* failed */ + Irp->IoStatus.Information = 0; + } + + /* free context */ + FreeItem(Context); + + return STATUS_SUCCESS; +} + NTSTATUS NTAPI @@ -421,6 +485,20 @@ WdmAudReadWrite( ULONG Length; PMDL Mdl; BOOLEAN Read = TRUE; + PWDMAUD_COMPLETION_CONTEXT Context; + + /* allocate completion context */ + Context = AllocateItem(NonPagedPool, sizeof(WDMAUD_COMPLETION_CONTEXT)); + + if (!Context) + { + /* not enough memory */ + Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + /* done */ + return STATUS_INSUFFICIENT_RESOURCES; + } /* get current irp stack location */ IoStack = IoGetCurrentIrpStackLocation(Irp); @@ -437,6 +515,11 @@ WdmAudReadWrite( /* store outputbuffer length */ IoStack->Parameters.DeviceIoControl.OutputBufferLength = Length; + /* setup context */ + Context->Length = Length; + Context->Function = (IoStack->MajorFunction == IRP_MJ_WRITE ? IOCTL_KS_WRITE_STREAM : IOCTL_KS_READ_STREAM); + Context->Mdl = Irp->MdlAddress; + /* store mdl address */ Mdl = Irp->MdlAddress; @@ -464,9 +547,6 @@ WdmAudReadWrite( return SetIrpIoStatus(Irp, Status, 0); } - /* now free the mdl */ - IoFreeMdl(Mdl); - /* get device info */ DeviceInfo = (PWDMAUD_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer; ASSERT(DeviceInfo); @@ -499,6 +579,9 @@ WdmAudReadWrite( IoStack->Parameters.Write.Length = Length; IoStack->MajorFunction = IRP_MJ_WRITE; + IoSetCompletionRoutine(Irp, IoCompletion, (PVOID)Context, TRUE, TRUE, TRUE); + + /* mark irp as pending */ // IoMarkIrpPending(Irp); /* call the driver */ diff --git a/drivers/wdm/audio/legacy/wdmaud/interface.h b/drivers/wdm/audio/legacy/wdmaud/interface.h index aa5e7b25f28..025bebba7db 100644 --- a/drivers/wdm/audio/legacy/wdmaud/interface.h +++ b/drivers/wdm/audio/legacy/wdmaud/interface.h @@ -42,6 +42,8 @@ typedef struct WAVEOUTCAPSW WaveOutCaps; AUXCAPSW AuxCaps; WAVEINCAPSW WaveInCaps; + MIDIINCAPSW MidiInCaps; + MIDIOUTCAPSW MidiOutCaps; ULONGLONG Position; struct { diff --git a/drivers/wdm/audio/legacy/wdmaud/mmixer.c b/drivers/wdm/audio/legacy/wdmaud/mmixer.c index 72e7776ce9d..fbc76389405 100644 --- a/drivers/wdm/audio/legacy/wdmaud/mmixer.c +++ b/drivers/wdm/audio/legacy/wdmaud/mmixer.c @@ -612,25 +612,44 @@ WdmAudGetWaveOutDeviceCount() return MMixerGetWaveOutCount(&MixerContext); } -NTSTATUS -WdmAudGetMixerPnpNameByIndex( - IN ULONG DeviceIndex, - OUT LPWSTR * Device) +ULONG +WdmAudGetMidiInDeviceCount() { - UNIMPLEMENTED - return STATUS_NOT_IMPLEMENTED; + return MMixerGetMidiInCount(&MixerContext); +} + +ULONG +WdmAudGetMidiOutDeviceCount() +{ + return MMixerGetWaveOutCount(&MixerContext); } NTSTATUS WdmAudGetPnpNameByIndexAndType( - IN ULONG DeviceIndex, - IN SOUND_DEVICE_TYPE DeviceType, + IN ULONG DeviceIndex, + IN SOUND_DEVICE_TYPE DeviceType, OUT LPWSTR *DevicePath) { - if (MMixerGetWaveDevicePath(&MixerContext, DeviceType == WAVE_IN_DEVICE_TYPE, DeviceIndex, DevicePath) == MM_STATUS_SUCCESS) - return STATUS_SUCCESS; - else - return STATUS_UNSUCCESSFUL; + if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE) + { + if (MMixerGetWaveDevicePath(&MixerContext, DeviceType == WAVE_IN_DEVICE_TYPE, DeviceIndex, DevicePath) == MM_STATUS_SUCCESS) + return STATUS_SUCCESS; + else + return STATUS_UNSUCCESSFUL; + } + else if (DeviceType == MIDI_IN_DEVICE_TYPE || DeviceType == MIDI_OUT_DEVICE_TYPE) + { + if (MMixerGetMidiDevicePath(&MixerContext, DeviceType == MIDI_IN_DEVICE_TYPE, DeviceIndex, DevicePath) == MM_STATUS_SUCCESS) + return STATUS_SUCCESS; + else + return STATUS_UNSUCCESSFUL; + } + else if (DeviceType == MIXER_DEVICE_TYPE) + { + UNIMPLEMENTED; + } + + return STATUS_UNSUCCESSFUL; } NTSTATUS @@ -640,7 +659,7 @@ WdmAudWaveCapabilities( IN PWDMAUD_CLIENT ClientInfo, IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) { - MIXER_STATUS Status; + MIXER_STATUS Status = MM_STATUS_UNSUCCESSFUL; if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) { @@ -652,10 +671,31 @@ WdmAudWaveCapabilities( /* get capabilities */ Status = MMixerWaveOutCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.WaveOutCaps); } + + if (Status == MM_STATUS_SUCCESS) + return STATUS_SUCCESS; else + return Status; +} + +NTSTATUS +WdmAudMidiCapabilities( + IN PDEVICE_OBJECT DeviceObject, + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN PWDMAUD_CLIENT ClientInfo, + IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) +{ + MIXER_STATUS Status = MM_STATUS_UNSUCCESSFUL; + + if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE) { - ASSERT(0); - return STATUS_UNSUCCESSFUL; + /* get capabilities */ + Status = MMixerMidiInCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.MidiInCaps); + } + else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) + { + /* get capabilities */ + Status = MMixerMidiOutCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.MidiOutCaps); } if (Status == MM_STATUS_SUCCESS) @@ -737,3 +777,26 @@ WdmAudControlOpenWave( else return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO)); } + +NTSTATUS +WdmAudControlOpenMidi( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN PWDMAUD_CLIENT ClientInfo) +{ + MIXER_STATUS Status; + PIN_CREATE_CONTEXT Context; + + Context.ClientInfo = ClientInfo; + Context.DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + Context.DeviceType = DeviceInfo->DeviceType; + + Status = MMixerOpenMidi(&MixerContext, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE, CreatePinCallback, &Context, &DeviceInfo->hDevice); + + if (Status == MM_STATUS_SUCCESS) + return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); + else + return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO)); +} + diff --git a/drivers/wdm/audio/legacy/wdmaud/wdmaud.h b/drivers/wdm/audio/legacy/wdmaud/wdmaud.h index dff0d8f75fb..002cf8d0d0a 100644 --- a/drivers/wdm/audio/legacy/wdmaud/wdmaud.h +++ b/drivers/wdm/audio/legacy/wdmaud/wdmaud.h @@ -16,6 +16,14 @@ #include "interface.h" +typedef struct +{ + PMDL Mdl; + ULONG Length; + ULONG Function; +}WDMAUD_COMPLETION_CONTEXT, *PWDMAUD_COMPLETION_CONTEXT; + + typedef struct { HANDLE Handle; @@ -130,6 +138,12 @@ WdmAudControlOpenWave( IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo); +NTSTATUS +WdmAudControlOpenMidi( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN PWDMAUD_CLIENT ClientInfo); ULONG GetNumOfMixerDevices( @@ -166,6 +180,13 @@ WdmAudWaveCapabilities( IN PWDMAUD_CLIENT ClientInfo, IN PWDMAUD_DEVICE_EXTENSION DeviceExtension); +NTSTATUS +WdmAudMidiCapabilities( + IN PDEVICE_OBJECT DeviceObject, + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN PWDMAUD_CLIENT ClientInfo, + IN PWDMAUD_DEVICE_EXTENSION DeviceExtension); + NTSTATUS NTAPI WdmAudFrameSize( @@ -267,10 +288,11 @@ WdmAudGetWaveInDeviceCount(); ULONG WdmAudGetWaveOutDeviceCount(); -NTSTATUS -WdmAudGetMixerPnpNameByIndex( - IN ULONG DeviceIndex, - OUT LPWSTR * Device); +ULONG +WdmAudGetMidiInDeviceCount(); + +ULONG +WdmAudGetMidiOutDeviceCount(); NTSTATUS WdmAudGetPnpNameByIndexAndType( diff --git a/drivers/wdm/audio/sysaudio/pin.c b/drivers/wdm/audio/sysaudio/pin.c index eb5ee6177e0..0a665bed4f8 100644 --- a/drivers/wdm/audio/sysaudio/pin.c +++ b/drivers/wdm/audio/sysaudio/pin.c @@ -398,7 +398,7 @@ GetConnectRequest( IoStack = IoGetCurrentIrpStackLocation(Irp); /* get object class length */ - ObjectLength = (wcslen(KSSTRING_Pin) + 2) * sizeof(WCHAR); + ObjectLength = (wcslen(KSSTRING_Pin) + 1) * sizeof(WCHAR); /* check for minium length requirement */ if (ObjectLength + sizeof(KSPIN_CONNECT) > IoStack->FileObject->FileName.MaximumLength) diff --git a/hal/halx86/generic/cmos.c b/hal/halx86/generic/cmos.c index 71c4e67c13c..6a3a9ec47a3 100644 --- a/hal/halx86/generic/cmos.c +++ b/hal/halx86/generic/cmos.c @@ -152,6 +152,7 @@ HalpSetCmosData(IN ULONG BusNumber, VOID NTAPI +INIT_FUNCTION HalpInitializeCmos(VOID) { /* Set default century offset byte */ diff --git a/hal/halx86/generic/dma.c b/hal/halx86/generic/dma.c index bdfae48bfc0..725e23f2690 100644 --- a/hal/halx86/generic/dma.c +++ b/hal/halx86/generic/dma.c @@ -126,6 +126,7 @@ static DMA_OPERATIONS HalpDmaOperations = { #ifndef _MINIHAL_ VOID +INIT_FUNCTION HalpInitDma(VOID) { /* diff --git a/hal/halx86/generic/halinit.c b/hal/halx86/generic/halinit.c index 9615891c045..f0011d71429 100644 --- a/hal/halx86/generic/halinit.c +++ b/hal/halx86/generic/halinit.c @@ -20,6 +20,7 @@ BOOLEAN HalpPciLockSettings; VOID NTAPI +INIT_FUNCTION HalpGetParameters(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { PCHAR CommandLine; @@ -45,6 +46,7 @@ HalpGetParameters(IN PLOADER_PARAMETER_BLOCK LoaderBlock) */ BOOLEAN NTAPI +INIT_FUNCTION HalInitSystem(IN ULONG BootPhase, IN PLOADER_PARAMETER_BLOCK LoaderBlock) { diff --git a/hal/halx86/generic/legacy/bus/libpcidata.a b/hal/halx86/generic/legacy/bus/libpcidata.a new file mode 100644 index 00000000000..a186d0fb299 Binary files /dev/null and b/hal/halx86/generic/legacy/bus/libpcidata.a differ diff --git a/hal/halx86/generic/legacy/bus/pcibus.c b/hal/halx86/generic/legacy/bus/pcibus.c index 8169fb19deb..ddb05cacf43 100644 --- a/hal/halx86/generic/legacy/bus/pcibus.c +++ b/hal/halx86/generic/legacy/bus/pcibus.c @@ -600,6 +600,7 @@ HalpGetISAFixedPCIIrq(IN PBUS_HANDLER BusHandler, NTSTATUS NTAPI +INIT_FUNCTION HalpSetupPciDeviceForDebugging(IN PVOID LoaderBlock, IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice) { @@ -609,6 +610,7 @@ HalpSetupPciDeviceForDebugging(IN PVOID LoaderBlock, NTSTATUS NTAPI +INIT_FUNCTION HalpReleasePciDeviceForDebugging(IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice) { DPRINT1("Unimplemented!\n"); @@ -617,6 +619,7 @@ HalpReleasePciDeviceForDebugging(IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice) VOID NTAPI +INIT_FUNCTION HalpRegisterPciDebuggingDeviceInfo(VOID) { BOOLEAN Found = FALSE; @@ -853,6 +856,7 @@ HaliPciInterfaceReadConfig(IN PBUS_HANDLER RootBusHandler, PPCI_REGISTRY_INFO_INTERNAL NTAPI +INIT_FUNCTION HalpQueryPciRegistryInfo(VOID) { #ifndef _MINIHAL_ @@ -1085,6 +1089,7 @@ HalpQueryPciRegistryInfo(VOID) VOID NTAPI +INIT_FUNCTION HalpInitializePciStubs(VOID) { PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo; diff --git a/hal/halx86/generic/legacy/bus/pcidata.c b/hal/halx86/generic/legacy/bus/pcidata.c index 83ccecef7d6..f7ca914752f 100644 --- a/hal/halx86/generic/legacy/bus/pcidata.c +++ b/hal/halx86/generic/legacy/bus/pcidata.c @@ -15,7 +15,7 @@ /* GLOBALS *******************************************************************/ #ifndef _MINIHAL_ -CHAR ClassTable[3922] = +INIT_FUNCTION CHAR ClassTable[3922] = { 0x43, 0x20, 0x30, 0x30, 0x20, 0x20, 0x55, 0x6E, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0D, 0x0A, 0x09, 0x30, 0x30, 0x20, 0x20, @@ -265,7 +265,7 @@ CHAR ClassTable[3922] = 0x72, 0x00, }; -CHAR VendorTable[642355] = +INIT_FUNCTION CHAR VendorTable[642355] = { 0x30, 0x30, 0x30, 0x30, 0x20, 0x20, 0x47, 0x61, 0x6D, 0x6D, 0x61, 0x67, 0x72, 0x61, 0x70, 0x68, 0x78, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x28, 0x6F, 0x72, 0x20, 0x6D, 0x69, 0x73, 0x73, diff --git a/hal/halx86/generic/legacy/bussupp.c b/hal/halx86/generic/legacy/bussupp.c index 078a05980a7..013b8564d79 100644 --- a/hal/halx86/generic/legacy/bussupp.c +++ b/hal/halx86/generic/legacy/bussupp.c @@ -65,6 +65,7 @@ HalpAllocateBusHandler(IN INTERFACE_TYPE InterfaceType, VOID NTAPI +INIT_FUNCTION HalpRegisterInternalBusHandlers(VOID) { PBUS_HANDLER Bus; @@ -139,6 +140,7 @@ HalpRegisterInternalBusHandlers(VOID) #ifndef _MINIHAL_ NTSTATUS NTAPI +INIT_FUNCTION HalpMarkChipsetDecode(BOOLEAN OverrideEnable) { NTSTATUS Status; @@ -186,6 +188,7 @@ HalpMarkChipsetDecode(BOOLEAN OverrideEnable) PBUS_HANDLER NTAPI +INIT_FUNCTION HalpAllocateAndInitPciBusHandler(IN ULONG PciType, IN ULONG BusNo, IN BOOLEAN TestAllocation) @@ -270,6 +273,7 @@ HalpAllocateAndInitPciBusHandler(IN ULONG PciType, BOOLEAN NTAPI +INIT_FUNCTION HalpIsValidPCIDevice(IN PBUS_HANDLER BusHandler, IN PCI_SLOT_NUMBER Slot) { @@ -331,6 +335,7 @@ static BOOLEAN WarningsGiven[5]; NTSTATUS NTAPI +INIT_FUNCTION HalpGetChipHacks(IN USHORT VendorId, IN USHORT DeviceId, IN UCHAR RevisionId, @@ -394,6 +399,7 @@ HalpGetChipHacks(IN USHORT VendorId, BOOLEAN NTAPI +INIT_FUNCTION HalpIsRecognizedCard(IN PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo, IN PPCI_COMMON_CONFIG PciData, IN ULONG Flags) @@ -474,6 +480,7 @@ HalpIsRecognizedCard(IN PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo, BOOLEAN NTAPI +INIT_FUNCTION HalpIsIdeDevice(IN PPCI_COMMON_CONFIG PciData) { /* Simple test first */ @@ -526,6 +533,7 @@ HalpIsIdeDevice(IN PPCI_COMMON_CONFIG PciData) BOOLEAN NTAPI +INIT_FUNCTION HalpIsBridgeDevice(IN PPCI_COMMON_CONFIG PciData) { /* Either this is a PCI-to-PCI Bridge, or a CardBUS Bridge */ @@ -539,6 +547,7 @@ HalpIsBridgeDevice(IN PPCI_COMMON_CONFIG PciData) BOOLEAN NTAPI +INIT_FUNCTION HalpGetPciBridgeConfig(IN ULONG PciType, IN PUCHAR BusCount) { @@ -591,6 +600,7 @@ HalpGetPciBridgeConfig(IN ULONG PciType, VOID NTAPI +INIT_FUNCTION HalpFixupPciSupportedRanges(IN ULONG BusCount) { ULONG i; @@ -653,6 +663,7 @@ HalpFixupPciSupportedRanges(IN ULONG BusCount) VOID NTAPI +INIT_FUNCTION ShowSize(ULONG x) { if (!x) return; @@ -678,6 +689,7 @@ ShowSize(ULONG x) VOID NTAPI +INIT_FUNCTION HalpDebugPciDumpBus(IN ULONG i, IN ULONG j, IN ULONG k, @@ -829,6 +841,7 @@ HalpDebugPciDumpBus(IN ULONG i, VOID NTAPI +INIT_FUNCTION HalpInitializePciBus(VOID) { #ifndef _MINIHAL_ @@ -1093,6 +1106,7 @@ HalpInitializePciBus(VOID) VOID NTAPI +INIT_FUNCTION HalpInitBusHandlers(VOID) { /* Register the HAL Bus Handler support */ @@ -1101,6 +1115,7 @@ HalpInitBusHandlers(VOID) VOID NTAPI +INIT_FUNCTION HalpRegisterKdSupportFunctions(VOID) { /* Register PCI Device Functions */ diff --git a/hal/halx86/generic/legacy/halpcat.c b/hal/halx86/generic/legacy/halpcat.c index 28913f9fc16..c403b6ffd19 100644 --- a/hal/halx86/generic/legacy/halpcat.c +++ b/hal/halx86/generic/legacy/halpcat.c @@ -23,6 +23,7 @@ PWCHAR HalName = L"PC Compatible Eisa/Isa HAL"; NTSTATUS NTAPI +INIT_FUNCTION HalpSetupAcpiPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { /* There is no ACPI on these HALs */ @@ -31,6 +32,7 @@ HalpSetupAcpiPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock) VOID NTAPI +INIT_FUNCTION HalpBuildAddressMap(VOID) { /* FIXME: Inherit ROM blocks from the registry */ @@ -42,6 +44,7 @@ HalpBuildAddressMap(VOID) BOOLEAN NTAPI +INIT_FUNCTION HalpGetDebugPortTable(VOID) { /* No ACPI */ @@ -50,6 +53,7 @@ HalpGetDebugPortTable(VOID) ULONG NTAPI +INIT_FUNCTION HalpIs16BitPortDecodeSupported(VOID) { /* Only EISA systems support this */ @@ -58,9 +62,11 @@ HalpIs16BitPortDecodeSupported(VOID) NTSTATUS NTAPI +INIT_FUNCTION HaliInitPnpDriver(VOID) { /* On PC-AT, this will interface with the PCI driver */ + //HalpDebugPciBus(); return STATUS_SUCCESS; } @@ -69,6 +75,7 @@ HaliInitPnpDriver(VOID) */ VOID NTAPI +INIT_FUNCTION HalReportResourceUsage(VOID) { INTERFACE_TYPE InterfaceType; diff --git a/hal/halx86/generic/memory.c b/hal/halx86/generic/memory.c index 74f20cbc6ed..979cacf4f0d 100644 --- a/hal/halx86/generic/memory.c +++ b/hal/halx86/generic/memory.c @@ -25,7 +25,6 @@ PVOID HalpHeapStart = MM_HAL_HEAP_START; /* PRIVATE FUNCTIONS *********************************************************/ - ULONG NTAPI HalpAllocPhysicalMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock, diff --git a/hal/halx86/generic/misc.c b/hal/halx86/generic/misc.c index 4b171a819a6..2ddd18599e1 100644 --- a/hal/halx86/generic/misc.c +++ b/hal/halx86/generic/misc.c @@ -24,6 +24,7 @@ CHAR HalpSerialNumber[31]; #ifndef _MINIHAL_ VOID NTAPI +INIT_FUNCTION HalpReportSerialNumber(VOID) { NTSTATUS Status; @@ -54,6 +55,7 @@ HalpReportSerialNumber(VOID) NTSTATUS NTAPI +INIT_FUNCTION HalpMarkAcpiHal(VOID) { NTSTATUS Status; diff --git a/hal/halx86/generic/timer.c b/hal/halx86/generic/timer.c index 2f78ac46cd8..89d66279574 100644 --- a/hal/halx86/generic/timer.c +++ b/hal/halx86/generic/timer.c @@ -44,6 +44,7 @@ LARGE_INTEGER HalpRolloverTable[15] = VOID NTAPI +INIT_FUNCTION HalpInitializeClock(VOID) { PKPRCB Prcb = KeGetCurrentPrcb(); diff --git a/hal/halx86/generic/usage.c b/hal/halx86/generic/usage.c index be6710d73fd..8339119c39a 100644 --- a/hal/halx86/generic/usage.c +++ b/hal/halx86/generic/usage.c @@ -63,6 +63,7 @@ ADDRESS_USAGE HalpDefaultIoSpace = #ifndef _MINIHAL_ VOID NTAPI +INIT_FUNCTION HalpGetResourceSortValue(IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor, OUT PULONG Scale, OUT PLARGE_INTEGER Value) @@ -102,6 +103,7 @@ HalpGetResourceSortValue(IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor, VOID NTAPI +INIT_FUNCTION HalpBuildPartialFromIdt(IN ULONG Entry, IN PCM_PARTIAL_RESOURCE_DESCRIPTOR RawDescriptor, IN PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedDescriptor) @@ -139,6 +141,7 @@ HalpBuildPartialFromIdt(IN ULONG Entry, VOID NTAPI +INIT_FUNCTION HalpBuildPartialFromAddress(IN INTERFACE_TYPE Interface, IN PADDRESS_USAGE CurrentAddress, IN ULONG Element, @@ -206,6 +209,7 @@ HalpBuildPartialFromAddress(IN INTERFACE_TYPE Interface, VOID NTAPI +INIT_FUNCTION HalpReportResourceUsage(IN PUNICODE_STRING HalName, IN INTERFACE_TYPE InterfaceType) { @@ -484,6 +488,7 @@ HalpReportResourceUsage(IN PUNICODE_STRING HalName, VOID NTAPI +INIT_FUNCTION HalpRegisterVector(IN UCHAR Flags, IN ULONG BusVector, IN ULONG SystemVector, @@ -500,6 +505,7 @@ HalpRegisterVector(IN UCHAR Flags, #ifndef _MINIHAL_ VOID NTAPI +INIT_FUNCTION HalpEnableInterruptHandler(IN UCHAR Flags, IN ULONG BusVector, IN ULONG SystemVector, @@ -522,6 +528,7 @@ HalpEnableInterruptHandler(IN UCHAR Flags, VOID NTAPI +INIT_FUNCTION HalpGetNMICrashFlag(VOID) { UNICODE_STRING ValueName; diff --git a/hal/halx86/include/halp.h b/hal/halx86/include/halp.h index 3ab0f7b253c..cbb372a1e47 100644 --- a/hal/halx86/include/halp.h +++ b/hal/halx86/include/halp.h @@ -4,6 +4,16 @@ #pragma once +#define PLACE_IN_SECTION(s) __attribute__((section (s))) +#ifdef __GNUC__ +#define INIT_FUNCTION PLACE_IN_SECTION("init") +#define PAGE_LOCKED_FUNCTION PLACE_IN_SECTION("pagelk") +#define PAGE_UNLOCKED_FUNCTION PLACE_IN_SECTION("pagepo") +#else +#define INIT_FUNCTION +#define PAGE_LOCKED_FUNCTION +#define PAGE_UNLOCKED_FUNCTION +#endif #ifdef _MSC_VER #define REGISTERCALL FASTCALL diff --git a/include/ddk/dmusicks.h b/include/ddk/dmusicks.h index 27cd6ac06d9..c5586e44019 100644 --- a/include/ddk/dmusicks.h +++ b/include/ddk/dmusicks.h @@ -1,6 +1,8 @@ #ifndef _DMUSICKS_ #define _DMUSICKS_ +#include + #define DONT_HOLD_FOR_SEQUENCING 0x8000000000000000 #ifndef REFERENCE_TIME @@ -230,4 +232,35 @@ typedef IMiniportDMus *PMINIPORTDMUS; IN PMASTERCLOCK MasterClock, \ OUT PULONGLONG SchedulePreFetch) + +#define STATIC_KSAUDFNAME_DMUSIC_MPU_OUT\ + 0xA4DF0EB5, 0xBAC9, 0x11d2, {0xB7, 0xA8, 0x00, 0x60, 0x08, 0x33, 0x16, 0xC1} +DEFINE_GUIDSTRUCT("A4DF0EB5-BAC9-11d2-B7A8-0060083316C1", KSAUDFNAME_DMUSIC_MPU_OUT); +#define KSAUDFNAME_DMUSIC_MPU_OUT DEFINE_GUIDNAMED(KSAUDFNAME_DMUSIC_MPU_OUT) + +#define STATIC_KSAUDFNAME_DMUSIC_MPU_IN\ + 0xB2EC0A7D, 0xBAC9, 0x11d2, {0xB7, 0xA8, 0x00, 0x60, 0x08, 0x33, 0x16, 0xC1} +DEFINE_GUIDSTRUCT("B2EC0A7D-BAC9-11d2-B7A8-0060083316C1", KSAUDFNAME_DMUSIC_MPU_IN); +#define KSAUDFNAME_DMUSIC_MPU_IN DEFINE_GUIDNAMED(KSAUDFNAME_DMUSIC_MPU_IN) + +#define STATIC_IID_IMXF\ + 0xc096df9e, 0xfb09, 0x11d1, {0x81, 0xb0, 0x00, 0x60, 0x08, 0x33, 0x16, 0xc1} +DEFINE_GUIDSTRUCT("c096df9e-fb09-11d1-81b0-0060083316c1", IID_IMXF); +#define IID_IMXF DEFINE_GUIDNAMED(IID_IMXF) + +#define DMUS_KEF_EVENT_COMPLETE 0x0000 +#define DMUS_KEF_EVENT_INCOMPLETE 0x0001 +#define DMUS_KEF_PACKAGE_EVENT 0x0002 +#define kBytePositionNone (~(ULONGLONG)0) + +#define SHORT_EVT(evt) ((evt)->cbEvent <= sizeof(PBYTE)) +#define PACKAGE_EVT(evt) ((evt)->usFlags & DMUS_KEF_PACKAGE_EVENT) +#define INCOMPLETE_EVT(evt) ((evt)->usFlags & DMUS_KEF_EVENT_INCOMPLETE) +#define COMPLETE_EVT(evt) (((evt)->usFlags & DMUS_KEF_EVENT_INCOMPLETE) == 0) + +#define SET_INCOMPLETE_EVT(evt) ((evt)->usFlags |= DMUS_KEF_EVENT_INCOMPLETE) +#define SET_COMPLETE_EVT(evt) ((evt)->usFlags &= (~DMUS_KEF_EVENT_INCOMPLETE)) +#define SET_PACKAGE_EVT(evt) ((evt)->usFlags |= DMUS_KEF_PACKAGE_EVENT) +#define CLEAR_PACKAGE_EVT(evt) ((evt)->usFlags &= (~DMUS_KEF_PACKAGE_EVENT)) + #endif /* _DMUSICKS_ */ diff --git a/include/ddk/dmusprop.h b/include/ddk/dmusprop.h new file mode 100644 index 00000000000..55877e57e7b --- /dev/null +++ b/include/ddk/dmusprop.h @@ -0,0 +1,203 @@ +#ifndef _DMusProp_ +#define _DMusProp_ + +//#include "dmusbuff.h" + +#define STATIC_KSDATAFORMAT_SUBTYPE_DIRECTMUSIC\ + 0x1a82f8bc, 0x3f8b, 0x11d2, {0xb7, 0x74, 0x00, 0x60, 0x08, 0x33, 0x16, 0xc1} +DEFINE_GUIDSTRUCT("1a82f8bc-3f8b-11d2-b774-0060083316c1", KSDATAFORMAT_SUBTYPE_DIRECTMUSIC); +#define KSDATAFORMAT_SUBTYPE_DIRECTMUSIC DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_DIRECTMUSIC) + +#define STATIC_KSNODETYPE_DMSYNTH\ + 0x94824f88, 0x6183, 0x11d2, {0x8f, 0x7a, 0x0, 0xc0, 0x4f, 0xbf, 0x8f, 0xef} +DEFINE_GUIDSTRUCT("94824F88-6183-11d2-8F7A-00C04FBF8FEF", KSNODETYPE_DMSYNTH); +#define KSNODETYPE_DMSYNTH DEFINE_GUIDNAMED(KSNODETYPE_DMSYNTH) + +#define STATIC_KSNODETYPE_DMSYNTH_CAPS\ + 0xbca2a2f1, 0x93c6, 0x11d2, {0xba, 0x1d, 0x0, 0x0, 0xf8, 0x75, 0xac, 0x12} +DEFINE_GUIDSTRUCT("bca2a2f1-93c6-11d2-ba1d-0000f875ac12", KSNODETYPE_DMSYNTH_CAPS); +#define KSNODETYPE_DMSYNTH_CAPS DEFINE_GUIDNAMED(KSNODETYPE_DMSYNTH_CAPS) + +#define STATIC_KSPROPSETID_Synth_Dls\ + 0xd523fa2c, 0xdee3, 0x11d1, {0xa7, 0x89, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12} +DEFINE_GUIDSTRUCT("d523fa2c-dee3-11d1-a789-0000f875ac12", KSPROPSETID_Synth_Dls); +#define KSPROPSETID_Synth_Dls DEFINE_GUIDNAMED(KSPROPSETID_Synth_Dls) + +typedef enum +{ + KSPROPERTY_SYNTH_DLS_DOWNLOAD = 0, + KSPROPERTY_SYNTH_DLS_UNLOAD, + KSPROPERTY_SYNTH_DLS_COMPACT, + KSPROPERTY_SYNTH_DLS_APPEND, + KSPROPERTY_SYNTH_DLS_WAVEFORMAT +} KSPROPERTY_SYNTH_DLS; + +typedef struct _SYNTH_BUFFER +{ + ULONG BufferSize; + PVOID BufferAddress; +} SYNTH_BUFFER, *PSYNTH_BUFFER; + +typedef struct _SYNTHDOWNLOAD +{ + HANDLE DownloadHandle; + BOOL Free; +} SYNTHDOWNLOAD, *PSYNTHDOWNLOAD; + +#define STATIC_KSPROPSETID_Synth\ + 0xfedfae25L, 0xe46e, 0x11d1, {0xaa, 0xce, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12} +DEFINE_GUIDSTRUCT("fedfae25-e46e-11d1-aace-0000f875ac12", KSPROPSETID_Synth); +#define KSPROPSETID_Synth DEFINE_GUIDNAMED(KSPROPSETID_Synth) + +typedef enum +{ + KSPROPERTY_SYNTH_VOLUME = 0, + KSPROPERTY_SYNTH_VOLUMEBOOST, + KSPROPERTY_SYNTH_CAPS, + KSPROPERTY_SYNTH_PORTPARAMETERS, + KSPROPERTY_SYNTH_CHANNELGROUPS, + KSPROPERTY_SYNTH_VOICEPRIORITY, + KSPROPERTY_SYNTH_LATENCYCLOCK, + KSPROPERTY_SYNTH_RUNNINGSTATS +} KSPROPERTY_SYNTH; + +#define SYNTH_PC_DLS (0x00000001) +#define SYNTH_PC_EXTERNAL (0x00000002) +#define SYNTH_PC_SOFTWARESYNTH (0x00000004) +#define SYNTH_PC_MEMORYSIZEFIXED (0x00000008) +#define SYNTH_PC_GMINHARDWARE (0x00000010) +#define SYNTH_PC_GSINHARDWARE (0x00000020) +#define SYNTH_PC_SYSTEMMEMORY (0x7fffffff) + +#if (NTDDI_VERSION < NTDDI_WINXP) +#define SYNTH_PC_REVERB (0x00000040) +#elif (NTDDI_VERSION >= NTDDI_WINXP) +#define SYNTH_PC_XGINHARDWARE (0x00000040) +#define SYNTH_PC_DLS2 (0x00000200) +#define SYNTH_PC_REVERB (0x40000000) +#endif + +typedef struct _SYNTHCAPS +{ + GUID Guid; + DWORD Flags; + DWORD MemorySize; + DWORD MaxChannelGroups; + DWORD MaxVoices; + DWORD MaxAudioChannels; + DWORD EffectFlags; + WCHAR Description[128]; +} SYNTHCAPS, *PSYNTHCAPS; + + +typedef struct _SYNTH_PORTPARAMS +{ + DWORD ValidParams; + DWORD Voices; + DWORD ChannelGroups; + DWORD AudioChannels; + DWORD SampleRate; + DWORD EffectsFlags; + DWORD Share; +} SYNTH_PORTPARAMS, *PSYNTH_PORTPARAMS; + +#define SYNTH_PORTPARAMS_VOICES 0x00000001 +#define SYNTH_PORTPARAMS_CHANNELGROUPS 0x00000002 +#define SYNTH_PORTPARAMS_AUDIOCHANNELS 0x00000004 +#define SYNTH_PORTPARAMS_SAMPLERATE 0x00000008 +#define SYNTH_PORTPARAMS_EFFECTS 0x00000020 +#define SYNTH_PORTPARAMS_SHARE 0x00000040 + +#define SYNTH_EFFECT_NONE 0x00000000 +#define SYNTH_EFFECT_REVERB 0x00000001 +#define SYNTH_EFFECT_CHORUS 0x00000002 +#define SYNTH_EFFECT_DELAY 0x00000004 + +typedef struct _SYNTHVOICEPRIORITY_INSTANCE +{ + DWORD ChannelGroup; + DWORD Channel; +} SYNTHVOICEPRIORITY_INSTANCE, *PSYNTHVOICEPRIORITY_INSTANCE; + +typedef struct _SYNTH_STATS +{ + DWORD ValidStats; + DWORD Voices; + DWORD TotalCPU; + DWORD CPUPerVoice; + DWORD LostNotes; + DWORD FreeMemory; + LONG PeakVolume; +} SYNTH_STATS, *PSYNTH_STATS; + + +#define SYNTH_STATS_VOICES (1 << 0) +#define SYNTH_STATS_TOTAL_CPU (1 << 1) +#define SYNTH_STATS_CPU_PER_VOICE (1 << 2) +#define SYNTH_STATS_LOST_NOTES (1 << 3) +#define SYNTH_STATS_PEAK_VOLUME (1 << 4) +#define SYNTH_STATS_FREE_MEMORY (1 << 5) + +#ifndef _DIRECTAUDIO_PRIORITIES_DEFINED_ +#define _DIRECTAUDIO_PRIORITIES_DEFINED_ + +#define DAUD_CRITICAL_VOICE_PRIORITY (0xF0000000) +#define DAUD_HIGH_VOICE_PRIORITY (0xC0000000) +#define DAUD_STANDARD_VOICE_PRIORITY (0x80000000) +#define DAUD_LOW_VOICE_PRIORITY (0x40000000) +#define DAUD_PERSIST_VOICE_PRIORITY (0x10000000) + +#define DAUD_CHAN1_VOICE_PRIORITY_OFFSET (0x0000000E) +#define DAUD_CHAN2_VOICE_PRIORITY_OFFSET (0x0000000D) +#define DAUD_CHAN3_VOICE_PRIORITY_OFFSET (0x0000000C) +#define DAUD_CHAN4_VOICE_PRIORITY_OFFSET (0x0000000B) +#define DAUD_CHAN5_VOICE_PRIORITY_OFFSET (0x0000000A) +#define DAUD_CHAN6_VOICE_PRIORITY_OFFSET (0x00000009) +#define DAUD_CHAN7_VOICE_PRIORITY_OFFSET (0x00000008) +#define DAUD_CHAN8_VOICE_PRIORITY_OFFSET (0x00000007) +#define DAUD_CHAN9_VOICE_PRIORITY_OFFSET (0x00000006) +#define DAUD_CHAN10_VOICE_PRIORITY_OFFSET (0x0000000F) +#define DAUD_CHAN11_VOICE_PRIORITY_OFFSET (0x00000005) +#define DAUD_CHAN12_VOICE_PRIORITY_OFFSET (0x00000004) +#define DAUD_CHAN13_VOICE_PRIORITY_OFFSET (0x00000003) +#define DAUD_CHAN14_VOICE_PRIORITY_OFFSET (0x00000002) +#define DAUD_CHAN15_VOICE_PRIORITY_OFFSET (0x00000001) +#define DAUD_CHAN16_VOICE_PRIORITY_OFFSET (0x00000000) + +#define DAUD_CHAN1_DEF_VOICE_PRIORITY (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN1_VOICE_PRIORITY_OFFSET) +#define DAUD_CHAN2_DEF_VOICE_PRIORITY (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN2_VOICE_PRIORITY_OFFSET) +#define DAUD_CHAN3_DEF_VOICE_PRIORITY (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN3_VOICE_PRIORITY_OFFSET) +#define DAUD_CHAN4_DEF_VOICE_PRIORITY (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN4_VOICE_PRIORITY_OFFSET) +#define DAUD_CHAN5_DEF_VOICE_PRIORITY (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN5_VOICE_PRIORITY_OFFSET) +#define DAUD_CHAN6_DEF_VOICE_PRIORITY (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN6_VOICE_PRIORITY_OFFSET) +#define DAUD_CHAN7_DEF_VOICE_PRIORITY (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN7_VOICE_PRIORITY_OFFSET) +#define DAUD_CHAN8_DEF_VOICE_PRIORITY (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN8_VOICE_PRIORITY_OFFSET) +#define DAUD_CHAN9_DEF_VOICE_PRIORITY (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN9_VOICE_PRIORITY_OFFSET) +#define DAUD_CHAN10_DEF_VOICE_PRIORITY (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN10_VOICE_PRIORITY_OFFSET) +#define DAUD_CHAN11_DEF_VOICE_PRIORITY (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN11_VOICE_PRIORITY_OFFSET) +#define DAUD_CHAN12_DEF_VOICE_PRIORITY (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN12_VOICE_PRIORITY_OFFSET) +#define DAUD_CHAN13_DEF_VOICE_PRIORITY (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN13_VOICE_PRIORITY_OFFSET) +#define DAUD_CHAN14_DEF_VOICE_PRIORITY (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN14_VOICE_PRIORITY_OFFSET) +#define DAUD_CHAN15_DEF_VOICE_PRIORITY (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN15_VOICE_PRIORITY_OFFSET) +#define DAUD_CHAN16_DEF_VOICE_PRIORITY (DAUD_STANDARD_VOICE_PRIORITY | DAUD_CHAN16_VOICE_PRIORITY_OFFSET) +#endif + +typedef struct _SYNTH_REVERB_PARAMS +{ + float fInGain; + float fReverbMix; + float fReverbTime; + float fHighFreqRTRatio; +} SYNTH_REVERB_PARAMS, *PSYNTH_REVERB_PARAMS; + + +#define STATIC_KSPROPSETID_SynthClock \ + 0xfedfae26L, 0xe46e, 0x11d1, 0xaa, 0xce, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12 +DEFINE_GUIDSTRUCT("fedfae26-e46e-11d1-aace-0000f875ac12", KSPROPSETID_SynthClock); +#define KSPROPSETID_SynthClock DEFINE_GUIDNAMED(KSPROPSETID_SynthClock) + +typedef enum +{ + KSPROPERTY_SYNTH_MASTERCLOCK +} KSPROPERTY_SYNTHCLOCK; +#endif diff --git a/include/ddk/portcls.h b/include/ddk/portcls.h index 0a6573293c6..226073aca5b 100644 --- a/include/ddk/portcls.h +++ b/include/ddk/portcls.h @@ -1958,6 +1958,12 @@ DECLARE_INTERFACE_(IPowerNotify, IUnknown) typedef IPowerNotify *PPOWERNOTIFY; +#define IMP_IPowerNotify\ + STDMETHODIMP_(void) PowerChangeNotify\ + ( IN POWER_STATE PowerState\ + ) + + #undef INTERFACE /* =============================================================== @@ -2158,6 +2164,11 @@ typedef IPortClsVersion *PPORTCLSVERSION; #undef INTERFACE +#if (NTDDI_VERSION >= NTDDI_WINXP) +DEFINE_GUID(IID_IMusicTechnology, +0x80396C3CL, 0xCBCB, 0x409B, 0x9F, 0x65, 0x4F, 0x1E, 0x74, 0x67, 0xCD, 0xAF); +#endif + /* =============================================================== IDmaOperations Interface */ @@ -2364,6 +2375,10 @@ PORTCLASSAPI ULONGLONG NTAPI PcGetTimeInterval( IN ULONGLONG Since); +#define GTI_SECONDS(t) (ULONGLONG(t)*10000000) +#define GTI_MILLISECONDS(t) (ULONGLONG(t)*10000) +#define GTI_MICROSECONDS(t) (ULONGLONG(t)*10) + PORTCLASSAPI NTSTATUS NTAPI PcRegisterSubdevice( IN PDEVICE_OBJECT DeviceObject, diff --git a/include/ndk/inline_ntcurrentteb.h b/include/ndk/inline_ntcurrentteb.h new file mode 100644 index 00000000000..ffda4d96924 --- /dev/null +++ b/include/ndk/inline_ntcurrentteb.h @@ -0,0 +1,86 @@ +#ifndef _INLINE_NT_CURRENTTEB_H_ +#define _INLINE_NT_CURRENTTEB_H_ + +#ifdef __GNUC__ + +#if defined(_M_IX86) +FORCEINLINE struct _TEB * NtCurrentTeb(void) +{ + struct _TEB *ret; + + __asm__ __volatile__ ( + "movl %%fs:0x18, %0\n" + : "=r" (ret) + : /* no inputs */ + ); + + return ret; +} +#elif defined(_M_ARM) + +// +// NT-ARM is not documented +// +#include + +#elif defined(_M_AMD64) +FORCEINLINE struct _TEB * NtCurrentTeb(VOID) +{ + return (struct _TEB *)__readgsqword(FIELD_OFFSET(NT_TIB, Self)); +} +#elif defined(_M_PPC) +extern __inline__ struct _TEB * NtCurrentTeb(void) +{ + return __readfsdword_winnt(0x18); +} +#else +extern __inline__ struct _TEB * NtCurrentTeb(void) +{ + return __readfsdword_winnt(0x18); +} +#endif + +#elif defined(__WATCOMC__) + +extern PVOID GetCurrentFiber(void); +#pragma aux GetCurrentFiber = \ + "mov eax, dword ptr fs:0x10" \ + value [eax] \ + modify [eax]; + +extern struct _TEB * NtCurrentTeb(void); +#pragma aux NtCurrentTeb = \ + "mov eax, dword ptr fs:0x18" \ + value [eax] \ + modify [eax]; + +#elif defined(_MSC_VER) + +#if (_MSC_FULL_VER >= 13012035) + +__inline PVOID GetCurrentFiber(void) { return (PVOID)(ULONG_PTR)__readfsdword(0x10); } +__inline struct _TEB * NtCurrentTeb(void) { return (struct _TEB *)(ULONG_PTR)__readfsdword(0x18); } + +#else + +static __inline PVOID GetCurrentFiber(void) +{ + PVOID p; + __asm mov eax, fs:[10h] + __asm mov [p], eax + return p; +} + +static __inline struct _TEB * NtCurrentTeb(void) +{ + struct _TEB *p; + __asm mov eax, fs:[18h] + __asm mov [p], eax + return p; +} + +#endif /* _MSC_FULL_VER */ + +#endif /* __GNUC__/__WATCOMC__/_MSC_VER */ + +#endif//_INLINE_NT_CURRENTTEB_H_ diff --git a/include/ndk/psfuncs.h b/include/ndk/psfuncs.h index 327af5a99b6..4b0a96f52af 100644 --- a/include/ndk/psfuncs.h +++ b/include/ndk/psfuncs.h @@ -329,35 +329,7 @@ NtCreateThread( IN BOOLEAN CreateSuspended ); -#ifndef NTOS_MODE_USER -#if defined(_M_IX86) -FORCEINLINE -PTEB -NtCurrentTeb(VOID) -{ -#ifndef __GNUC__ - return (PTEB)(ULONG_PTR)__readfsdword(0x18); -#else - struct _TEB *ret; - - __asm__ __volatile__ ( - "movl %%fs:0x18, %0\n" - : "=r" (ret) - : /* no inputs */ - ); - - return ret; -#endif -} -#elif defined (_M_AMD64) -FORCEINLINE struct _TEB * NtCurrentTeb(VOID) -{ - return (struct _TEB *)__readgsqword(FIELD_OFFSET(NT_TIB, Self)); -} -#endif -#else -struct _TEB * NtCurrentTeb(void); -#endif +#include "inline_ntcurrentteb.h" NTSYSCALLAPI NTSTATUS diff --git a/include/psdk/ks.h b/include/psdk/ks.h index 7f99f136077..8cd467a2f02 100644 --- a/include/psdk/ks.h +++ b/include/psdk/ks.h @@ -1017,28 +1017,6 @@ DEFINE_GUIDSTRUCT("97E99BA0-BDEA-11CF-A5D6-28DB04C10000", KSPROPTYPESETID_Genera KSPROPERTY_ITD3D_PARAMS */ -#define KSPROPSETID_Synth -/* - KSPROPERTY_SYNTH_CAPS - KSPROPERTY_SYNTH_CHANNELGROUPS - KSPROPERTY_SYNTH_LATENCYCLOCK - KSPROPERTY_SYNTH_MASTERCLOCK - KSPROPERTY_SYNTH_PORTPARAMETERS - KSPROPERTY_SYNTH_RUNNINGSTATS - KSPROPERTY_SYNTH_VOICEPRIORITY - KSPROPERTY_SYNTH_VOLUME - KSPROPERTY_SYNTH_VOLUMEBOOST -*/ - -#define KSPROPSETID_Synth_Dls -/* - KSPROPERTY_SYNTH_DLS_APPEND - KSPROPERTY_SYNTH_DLS_COMPACT - KSPROPERTY_SYNTH_DLS_DOWNLOAD - KSPROPERTY_SYNTH_DLS_UNLOAD - KSPROPERTY_SYNTH_DLS_WAVEFORMAT -*/ - #define KSPROPSETID_TopologyNode /* KSPROPERTY_TOPOLOGYNODE_ENABLE diff --git a/include/psdk/ksmedia.h b/include/psdk/ksmedia.h index 5a34bba37e6..4873e1dbe64 100644 --- a/include/psdk/ksmedia.h +++ b/include/psdk/ksmedia.h @@ -686,4 +686,52 @@ typedef struct { ULONG Accuracy; } KSRTAUDIO_HWREGISTER, *PKSRTAUDIO_HWREGISTER; +#define KSNODEPIN_STANDARD_IN 1 +#define KSNODEPIN_STANDARD_OUT 0 + +#define KSNODEPIN_SUM_MUX_IN 1 +#define KSNODEPIN_SUM_MUX_OUT 0 + +#define KSNODEPIN_DEMUX_IN 0 +#define KSNODEPIN_DEMUX_OUT 1 + +#if (NTDDI_VERSION < NTDDI_VISTA) + +#define KSNODEPIN_AEC_RENDER_IN 1 +#define KSNODEPIN_AEC_RENDER_OUT 0 +#define KSNODEPIN_AEC_CAPTURE_IN 2 +#define KSNODEPIN_AEC_CAPTURE_OUT 3 + +#endif + + +#define STATIC_KSMUSIC_TECHNOLOGY_PORT\ + 0x86C92E60L, 0x62E8, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00} +DEFINE_GUIDSTRUCT("86C92E60-62E8-11CF-A5D6-28DB04C10000", KSMUSIC_TECHNOLOGY_PORT); +#define KSMUSIC_TECHNOLOGY_PORT DEFINE_GUIDNAMED(KSMUSIC_TECHNOLOGY_PORT) + +#define STATIC_KSDATAFORMAT_SUBTYPE_MIDI_BUS\ + 0x2CA15FA0L, 0x6CFE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00} +DEFINE_GUIDSTRUCT("2CA15FA0-6CFE-11CF-A5D6-28DB04C10000", KSDATAFORMAT_SUBTYPE_MIDI_BUS); +#define KSDATAFORMAT_SUBTYPE_MIDI_BUS DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MIDI_BUS) + +#define STATIC_KSAUDFNAME_MIDI\ + 0x185FEDF8L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 +DEFINE_GUIDSTRUCT("185FEDF8-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_MIDI); +#define KSAUDFNAME_MIDI DEFINE_GUIDNAMED(KSAUDFNAME_MIDI) + +#define STATIC_KSNODETYPE_SYNTHESIZER\ + DEFINE_USB_TERMINAL_GUID(0x0713) +DEFINE_GUIDSTRUCT("DFF220F3-F70F-11D0-B917-00A0C9223196", KSNODETYPE_SYNTHESIZER); +#define KSNODETYPE_SYNTHESIZER DEFINE_GUIDNAMED(KSNODETYPE_SYNTHESIZER) + +typedef struct +{ + KSDATARANGE DataRange; + GUID Technology; + ULONG Channels; + ULONG Notes; + ULONG ChannelMask; +} KSDATARANGE_MUSIC, *PKSDATARANGE_MUSIC; + #endif diff --git a/include/psdk/ntsecapi.h b/include/psdk/ntsecapi.h index 7aaf903ec56..27127a29106 100644 --- a/include/psdk/ntsecapi.h +++ b/include/psdk/ntsecapi.h @@ -318,7 +318,9 @@ typedef enum _TRUSTED_INFORMATION_CLASS { TrustedDomainInformationBasic, TrustedDomainInformationEx, TrustedDomainAuthInformation, - TrustedDomainFullInformation + TrustedDomainFullInformation, + TrustedDomainAuthInformationInternal, + TrustedDomainFullInformationInternal } TRUSTED_INFORMATION_CLASS, *PTRUSTED_INFORMATION_CLASS; typedef enum _LSA_FOREST_TRUST_RECORD_TYPE { ForestTrustTopLevelName, diff --git a/include/psdk/winnt.h b/include/psdk/winnt.h index 1606cd0caf5..50dbd6b09ca 100644 --- a/include/psdk/winnt.h +++ b/include/psdk/winnt.h @@ -5086,43 +5086,6 @@ static __inline__ PVOID GetCurrentFiber(void) } #endif -#if defined(_M_IX86) -extern __inline__ struct _TEB * NtCurrentTeb(void) -{ - struct _TEB *ret; - - __asm__ __volatile__ ( - "movl %%fs:0x18, %0\n" - : "=r" (ret) - : /* no inputs */ - ); - - return ret; -} -#elif defined(_M_ARM) - -// -// NT-ARM is not documented -// -#include - -#elif defined(_M_AMD64) -FORCEINLINE struct _TEB * NtCurrentTeb(VOID) -{ - return (struct _TEB *)__readgsqword(FIELD_OFFSET(NT_TIB, Self)); -} -#elif defined(_M_PPC) -extern __inline__ struct _TEB * NtCurrentTeb(void) -{ - return __readfsdword_winnt(0x18); -} -#else -extern __inline__ struct _TEB * NtCurrentTeb(void) -{ - return __readfsdword_winnt(0x18); -} -#endif - #elif defined(__WATCOMC__) extern PVOID GetCurrentFiber(void); @@ -5131,18 +5094,11 @@ extern PVOID GetCurrentFiber(void); value [eax] \ modify [eax]; -extern struct _TEB * NtCurrentTeb(void); -#pragma aux NtCurrentTeb = \ - "mov eax, dword ptr fs:0x18" \ - value [eax] \ - modify [eax]; - #elif defined(_MSC_VER) #if (_MSC_FULL_VER >= 13012035) __inline PVOID GetCurrentFiber(void) { return (PVOID)(ULONG_PTR)__readfsdword(0x10); } -__inline struct _TEB * NtCurrentTeb(void) { return (struct _TEB *)(ULONG_PTR)__readfsdword(0x18); } #else @@ -5154,18 +5110,12 @@ static __inline PVOID GetCurrentFiber(void) return p; } -static __inline struct _TEB * NtCurrentTeb(void) -{ - struct _TEB *p; - __asm mov eax, fs:[18h] - __asm mov [p], eax - return p; -} - #endif /* _MSC_FULL_VER */ #endif /* __GNUC__/__WATCOMC__/_MSC_VER */ +#include "inline_ntcurrentteb.h" + static __inline PVOID GetFiberData(void) { return *((PVOID *)GetCurrentFiber()); diff --git a/include/reactos/libs/sound/mmebuddy.h b/include/reactos/libs/sound/mmebuddy.h index cae6f3f1489..1a2a5431242 100644 --- a/include/reactos/libs/sound/mmebuddy.h +++ b/include/reactos/libs/sound/mmebuddy.h @@ -68,7 +68,7 @@ SND_TRACE(L"-- Current wave header list --\n"); \ while ( CurrDumpHdr ) \ { \ - SND_TRACE(L"%x | %d bytes | flags: %x\n", CurrDumpHdr->lpData, \ + SND_TRACE(L"%x | %d bytes | flags: %x\n", CurrDumpHdr, \ CurrDumpHdr->dwBufferLength, \ CurrDumpHdr->dwFlags); \ CurrDumpHdr = CurrDumpHdr->lpNext; \ @@ -364,6 +364,8 @@ typedef struct _SOUND_DEVICE_INSTANCE WAVEFORMATEX WaveFormatEx; HANDLE hNotifyEvent; HANDLE hStopEvent; + HANDLE hResetEvent; + BOOL ResetInProgress; } SOUND_DEVICE_INSTANCE, *PSOUND_DEVICE_INSTANCE; /* This lives in WAVEHDR.reserved */ @@ -411,7 +413,7 @@ MmeGetSoundDeviceCapabilities( IN DWORD CapabilitiesSize); MMRESULT -MmeOpenWaveDevice( +MmeOpenDevice( IN MMDEVICE_TYPE DeviceType, IN UINT DeviceId, IN LPWAVEOPENDESC OpenParameters, diff --git a/include/reactos/win32k/callback.h b/include/reactos/win32k/callback.h index fc7c0bb95e2..76792380bd2 100644 --- a/include/reactos/win32k/callback.h +++ b/include/reactos/win32k/callback.h @@ -48,8 +48,6 @@ typedef struct _HOOKPROC_CALLBACK_ARGUMENTS LPARAM lParam; HOOKPROC Proc; BOOLEAN Ansi; - UINT ModuleNameLength; - WCHAR ModuleName[1]; } HOOKPROC_CALLBACK_ARGUMENTS, *PHOOKPROC_CALLBACK_ARGUMENTS; typedef struct _HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS diff --git a/lib/drivers/sound/mmebuddy/capabilities.c b/lib/drivers/sound/mmebuddy/capabilities.c index c8ff6586a74..edf75990783 100644 --- a/lib/drivers/sound/mmebuddy/capabilities.c +++ b/lib/drivers/sound/mmebuddy/capabilities.c @@ -62,32 +62,32 @@ GetSoundDeviceCapabilities( { case WAVE_OUT_DEVICE_TYPE : { - GoodSize = CapabilitiesSize >= sizeof(WAVEOUTCAPS); + GoodSize = CapabilitiesSize >= sizeof(WAVEOUTCAPSW); break; } case WAVE_IN_DEVICE_TYPE : { - GoodSize = CapabilitiesSize >= sizeof(WAVEINCAPS); + GoodSize = CapabilitiesSize >= sizeof(WAVEINCAPSW); break; } case MIDI_OUT_DEVICE_TYPE : { - GoodSize = CapabilitiesSize >= sizeof(MIDIOUTCAPS); + GoodSize = CapabilitiesSize >= sizeof(MIDIOUTCAPSW); break; } case MIDI_IN_DEVICE_TYPE : { - GoodSize = CapabilitiesSize >= sizeof(MIDIINCAPS); + GoodSize = CapabilitiesSize >= sizeof(MIDIINCAPSW); break; } case AUX_DEVICE_TYPE : { - GoodSize = CapabilitiesSize >= sizeof(AUXCAPS); + GoodSize = CapabilitiesSize >= sizeof(AUXCAPSW); break; } case MIXER_DEVICE_TYPE : { - GoodSize = CapabilitiesSize >= sizeof(MIXERCAPS); + GoodSize = CapabilitiesSize >= sizeof(MIXERCAPSW); break; } }; diff --git a/lib/drivers/sound/mmebuddy/midi/midMessage.c b/lib/drivers/sound/mmebuddy/midi/midMessage.c index 9e1a0ec24f6..95738d78d89 100644 --- a/lib/drivers/sound/mmebuddy/midi/midMessage.c +++ b/lib/drivers/sound/mmebuddy/midi/midMessage.c @@ -65,6 +65,33 @@ midMessage( break; } + case MIDM_OPEN : + { + Result = MmeOpenDevice(MIDI_IN_DEVICE_TYPE, + DeviceId, + (LPWAVEOPENDESC) Parameter1, + Parameter2, + (DWORD_PTR*) PrivateHandle); + break; + } + + case MIDM_CLOSE : + { + Result = MmeCloseDevice(PrivateHandle); + break; + } + + case MIDM_START : + { + Result = MmeSetState(PrivateHandle, TRUE); + break; + } + + case MIDM_STOP : + { + Result = MmeSetState(PrivateHandle, FALSE); + break; + } } SND_TRACE(L"midMessage returning MMRESULT %d\n", Result); diff --git a/lib/drivers/sound/mmebuddy/midi/modMessage.c b/lib/drivers/sound/mmebuddy/midi/modMessage.c index febfca516b5..d189b03fd1b 100644 --- a/lib/drivers/sound/mmebuddy/midi/modMessage.c +++ b/lib/drivers/sound/mmebuddy/midi/modMessage.c @@ -64,6 +64,24 @@ modMessage( Result = MmeGetDeviceInterfaceString(MIDI_OUT_DEVICE_TYPE, DeviceId, (LPWSTR)Parameter1, Parameter2, NULL); //FIXME DWORD_PTR break; } + + case MODM_OPEN : + { + Result = MmeOpenDevice(MIDI_OUT_DEVICE_TYPE, + DeviceId, + (LPWAVEOPENDESC) Parameter1, /* unused */ + Parameter2, + (DWORD_PTR*)PrivateHandle); + break; + } + + case MODM_CLOSE : + { + Result = MmeCloseDevice(PrivateHandle); + + break; + } + } SND_TRACE(L"modMessage returning MMRESULT %d\n", Result); diff --git a/lib/drivers/sound/mmebuddy/mixer/mxdMessage.c b/lib/drivers/sound/mmebuddy/mixer/mxdMessage.c index cf870540ba1..08815ba8eee 100644 --- a/lib/drivers/sound/mmebuddy/mixer/mxdMessage.c +++ b/lib/drivers/sound/mmebuddy/mixer/mxdMessage.c @@ -52,99 +52,6 @@ MmeGetLineInfo( } -MMRESULT -MmeCloseMixerDevice( - IN DWORD_PTR PrivateHandle) -{ - MMRESULT Result; - PSOUND_DEVICE_INSTANCE SoundDeviceInstance; - PSOUND_DEVICE SoundDevice; - - SND_TRACE(L"Closing mixer device \n"); - - VALIDATE_MMSYS_PARAMETER( PrivateHandle ); - SoundDeviceInstance = (PSOUND_DEVICE_INSTANCE) PrivateHandle; - - if ( ! IsValidSoundDeviceInstance(SoundDeviceInstance) ) - return MMSYSERR_INVALHANDLE; - - Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); - if ( ! MMSUCCESS(Result) ) - return TranslateInternalMmResult(Result); - - - Result = DestroySoundDeviceInstance(SoundDeviceInstance); - - return Result; -} - -MMRESULT -MmeOpenMixerDevice( - IN MMDEVICE_TYPE DeviceType, - IN DWORD DeviceId, - IN LPMIXEROPENDESC OpenParameters, - IN DWORD Flags, - OUT DWORD* PrivateHandle) -{ - MMRESULT Result; - PMMFUNCTION_TABLE FunctionTable; - PSOUND_DEVICE SoundDevice; - PSOUND_DEVICE_INSTANCE SoundDeviceInstance; - - SND_TRACE(L"Opening mixer device"); - - VALIDATE_MMSYS_PARAMETER( OpenParameters ); - - Result = GetSoundDevice(DeviceType, DeviceId, &SoundDevice); - if ( ! MMSUCCESS(Result) ) - return TranslateInternalMmResult(Result); - - /* Check that winmm gave us a private handle to fill */ - VALIDATE_MMSYS_PARAMETER( PrivateHandle ); - - /* Create a sound device instance and open the sound device */ - Result = CreateSoundDeviceInstance(SoundDevice, &SoundDeviceInstance); - if ( ! MMSUCCESS(Result) ) - return TranslateInternalMmResult(Result); - - Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable); - if ( ! MMSUCCESS(Result) ) - return TranslateInternalMmResult(Result); - - if ( ! FunctionTable->SetWaveFormat ) - return MMSYSERR_NOTSUPPORTED; - - Result = FunctionTable->SetWaveFormat(SoundDeviceInstance, DeviceId, NULL, 0); - if ( ! MMSUCCESS(Result) ) - { - /* TODO: Destroy sound instance */ - return TranslateInternalMmResult(Result); - } - - /* Store the device instance pointer in the private handle - is DWORD safe here? */ - *PrivateHandle = (DWORD_PTR) SoundDeviceInstance; - - /* Store the additional information we were given - FIXME: Need flags! */ - SetSoundDeviceInstanceMmeData(SoundDeviceInstance, - (HDRVR)OpenParameters->hmx, - OpenParameters->dwCallback, - OpenParameters->dwInstance, - Flags); - - /* Let the application know the device is open */ - ReleaseEntrypointMutex(DeviceType); -#if 0 - NotifyMmeClient(SoundDeviceInstance, - DeviceType == WAVE_OUT_DEVICE_TYPE ? WOM_OPEN : WIM_OPEN, - 0); -#endif - AcquireEntrypointMutex(DeviceType); - - SND_TRACE(L"Mixer device now open\n"); - - return MMSYSERR_NOERROR; -} - /* Standard MME driver entry-point for messages relating to mixers. */ @@ -188,18 +95,18 @@ mxdMessage( case MXDM_OPEN : { - Result = MmeOpenMixerDevice(MIXER_DEVICE_TYPE, - DeviceId, - (LPMIXEROPENDESC) Parameter1, - Parameter2, - (DWORD*) PrivateHandle); + Result = MmeOpenDevice(MIXER_DEVICE_TYPE, + DeviceId, + (LPWAVEOPENDESC) Parameter1, /* unused */ + Parameter2, + (DWORD*) PrivateHandle); break; } case MXDM_CLOSE : { - Result = MmeCloseMixerDevice(PrivateHandle); + Result = MmeCloseDevice(PrivateHandle); break; } diff --git a/lib/drivers/sound/mmebuddy/mmewrap.c b/lib/drivers/sound/mmebuddy/mmewrap.c index 960c4839a50..583d198ca87 100644 --- a/lib/drivers/sound/mmebuddy/mmewrap.c +++ b/lib/drivers/sound/mmebuddy/mmewrap.c @@ -119,7 +119,7 @@ MmeGetSoundDeviceCapabilities( } MMRESULT -MmeOpenWaveDevice( +MmeOpenDevice( IN MMDEVICE_TYPE DeviceType, IN UINT DeviceId, IN LPWAVEOPENDESC OpenParameters, @@ -127,33 +127,36 @@ MmeOpenWaveDevice( OUT DWORD_PTR* PrivateHandle) { MMRESULT Result; - + UINT Message; PSOUND_DEVICE SoundDevice; PSOUND_DEVICE_INSTANCE SoundDeviceInstance; LPWAVEFORMATEX Format; - SND_TRACE(L"Opening wave device (WIDM_OPEN / WODM_OPEN)"); + SND_TRACE(L"Opening device"); VALIDATE_MMSYS_PARAMETER( IS_WAVE_DEVICE_TYPE(DeviceType) ); /* FIXME? wave in too? */ VALIDATE_MMSYS_PARAMETER( OpenParameters ); - Format = OpenParameters->lpFormat; - Result = GetSoundDevice(DeviceType, DeviceId, &SoundDevice); if ( ! MMSUCCESS(Result) ) return TranslateInternalMmResult(Result); - /* Does this device support the format? */ - Result = QueryWaveDeviceFormatSupport(SoundDevice, Format, sizeof(WAVEFORMATEX)); - if ( ! MMSUCCESS(Result) ) + if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE) { - SND_ERR(L"Format not supported\n"); - return TranslateInternalMmResult(Result); - } + Format = OpenParameters->lpFormat; - /* If the caller just wanted to know if a format is supported, end here */ - if ( Flags & WAVE_FORMAT_QUERY ) - return MMSYSERR_NOERROR; + /* Does this device support the format? */ + Result = QueryWaveDeviceFormatSupport(SoundDevice, Format, sizeof(WAVEFORMATEX)); + if ( ! MMSUCCESS(Result) ) + { + SND_ERR(L"Format not supported\n"); + return TranslateInternalMmResult(Result); + } + + /* If the caller just wanted to know if a format is supported, end here */ + if ( Flags & WAVE_FORMAT_QUERY ) + return MMSYSERR_NOERROR; + } /* Check that winmm gave us a private handle to fill */ VALIDATE_MMSYS_PARAMETER( PrivateHandle ); @@ -175,20 +178,35 @@ MmeOpenWaveDevice( /* Store the additional information we were given - FIXME: Need flags! */ SetSoundDeviceInstanceMmeData(SoundDeviceInstance, - (HDRVR)OpenParameters->hWave, + (HDRVR)OpenParameters->hWave, /* works because LPMIXEROPENDESC/etc has also the handle as first member */ OpenParameters->dwCallback, OpenParameters->dwInstance, Flags); - /* Let the application know the device is open */ - ReleaseEntrypointMutex(DeviceType); - NotifyMmeClient(SoundDeviceInstance, - DeviceType == WAVE_OUT_DEVICE_TYPE ? WOM_OPEN : WIM_OPEN, - 0); + if (DeviceType == WAVE_OUT_DEVICE_TYPE || DeviceType == WAVE_IN_DEVICE_TYPE || + DeviceType == MIDI_OUT_DEVICE_TYPE || DeviceType == MIDI_IN_DEVICE_TYPE) + { + /* Let the application know the device is open */ - AcquireEntrypointMutex(DeviceType); + if (DeviceType == WAVE_OUT_DEVICE_TYPE) + Message = WOM_OPEN; + else if (DeviceType == WAVE_IN_DEVICE_TYPE) + Message = WIM_OPEN; + else if (DeviceType == MIDI_IN_DEVICE_TYPE) + Message = MIM_OPEN; + else + Message = MOM_OPEN; - SND_TRACE(L"Wave device now open\n"); + ReleaseEntrypointMutex(DeviceType); + + NotifyMmeClient(SoundDeviceInstance, + Message, + 0); + + AcquireEntrypointMutex(DeviceType); + } + + SND_TRACE(L"device now open\n"); return MMSYSERR_NOERROR; } @@ -201,6 +219,7 @@ MmeCloseDevice( PSOUND_DEVICE_INSTANCE SoundDeviceInstance; PSOUND_DEVICE SoundDevice; MMDEVICE_TYPE DeviceType; + UINT Message = 0; SND_TRACE(L"Closing wave device (WIDM_CLOSE / WODM_CLOSE)\n"); @@ -221,12 +240,26 @@ MmeCloseDevice( /* TODO: Check device is stopped! */ - ReleaseEntrypointMutex(DeviceType); - /* TODO: Work with MIDI devices too */ - NotifyMmeClient(SoundDeviceInstance, - DeviceType == WAVE_OUT_DEVICE_TYPE ? WOM_CLOSE : WIM_CLOSE, - 0); - AcquireEntrypointMutex(DeviceType); + + if (DeviceType != MIXER_DEVICE_TYPE) + { + ReleaseEntrypointMutex(DeviceType); + + if (DeviceType == WAVE_OUT_DEVICE_TYPE) + Message = WOM_CLOSE; + else if (DeviceType == WAVE_IN_DEVICE_TYPE) + Message = WIM_CLOSE; + else if (DeviceType == MIDI_IN_DEVICE_TYPE) + Message = MIM_CLOSE; + else if (DeviceType == MIDI_OUT_DEVICE_TYPE) + Message = MOM_CLOSE; + + /* TODO: Work with MIDI devices too */ + NotifyMmeClient(SoundDeviceInstance, + Message, + 0); + AcquireEntrypointMutex(DeviceType); + } Result = DestroySoundDeviceInstance(SoundDeviceInstance); diff --git a/lib/drivers/sound/mmebuddy/wave/widMessage.c b/lib/drivers/sound/mmebuddy/wave/widMessage.c index 47825aeccd9..6584d3d7bac 100644 --- a/lib/drivers/sound/mmebuddy/wave/widMessage.c +++ b/lib/drivers/sound/mmebuddy/wave/widMessage.c @@ -68,7 +68,7 @@ widMessage( } case WIDM_OPEN : { - Result = MmeOpenWaveDevice(WAVE_IN_DEVICE_TYPE, + Result = MmeOpenDevice(WAVE_IN_DEVICE_TYPE, DeviceId, (LPWAVEOPENDESC) Parameter1, Parameter2, diff --git a/lib/drivers/sound/mmebuddy/wave/wodMessage.c b/lib/drivers/sound/mmebuddy/wave/wodMessage.c index 70bd6b70d05..330c5f2aab6 100644 --- a/lib/drivers/sound/mmebuddy/wave/wodMessage.c +++ b/lib/drivers/sound/mmebuddy/wave/wodMessage.c @@ -65,11 +65,11 @@ wodMessage( case WODM_OPEN : { - Result = MmeOpenWaveDevice(WAVE_OUT_DEVICE_TYPE, - DeviceId, - (LPWAVEOPENDESC) Parameter1, - Parameter2, - (DWORD_PTR*)PrivateHandle); + Result = MmeOpenDevice(WAVE_OUT_DEVICE_TYPE, + DeviceId, + (LPWAVEOPENDESC) Parameter1, + Parameter2, + (DWORD_PTR*)PrivateHandle); break; } diff --git a/lib/drivers/sound/mmixer/CMakeLists.txt b/lib/drivers/sound/mmixer/CMakeLists.txt index 3d24393b896..4edfc124e47 100644 --- a/lib/drivers/sound/mmixer/CMakeLists.txt +++ b/lib/drivers/sound/mmixer/CMakeLists.txt @@ -8,6 +8,7 @@ include_directories(${REACTOS_SOURCE_DIR}/include/reactos/libs/sound) list(APPEND SOURCE controls.c filter.c + midi.c mixer.c sup.c wave.c diff --git a/lib/drivers/sound/mmixer/controls.c b/lib/drivers/sound/mmixer/controls.c index 6963f49e467..5b5dd1831ae 100644 --- a/lib/drivers/sound/mmixer/controls.c +++ b/lib/drivers/sound/mmixer/controls.c @@ -955,7 +955,7 @@ MMixerInitializeFilter( MixerInfo->hMixer = MixerData->hDevice; /* get mixer name */ - MMixerGetDeviceName(MixerContext, MixerInfo, MixerData->hDeviceInterfaceKey); + MMixerGetDeviceName(MixerContext, MixerInfo->MixCaps.szPname, MixerData->hDeviceInterfaceKey); /* initialize line list */ InitializeListHead(&MixerInfo->LineList); @@ -1128,6 +1128,9 @@ MMixerSetupFilter( } + /* activate midi devices */ + MMixerInitializeMidiForFilter(MixerContext, MixerList, MixerData, Topology); + /* done */ return Status; } diff --git a/lib/drivers/sound/mmixer/midi.c b/lib/drivers/sound/mmixer/midi.c new file mode 100644 index 00000000000..e60d14999c2 --- /dev/null +++ b/lib/drivers/sound/mmixer/midi.c @@ -0,0 +1,541 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Kernel Streaming + * FILE: lib/drivers/sound/mmixer/midi.c + * PURPOSE: Midi Support Functions + * PROGRAMMER: Johannes Anderwald + */ + +#include "priv.h" + +MIXER_STATUS +MMixerGetPinDataFlowAndCommunication( + IN PMIXER_CONTEXT MixerContext, + IN LPMIXER_DATA MixerData, + IN ULONG PinId, + OUT PKSPIN_DATAFLOW DataFlow, + OUT PKSPIN_COMMUNICATION Communication) +{ + KSP_PIN Pin; + ULONG BytesReturned; + MIXER_STATUS Status; + + /* setup request */ + Pin.PinId = PinId; + Pin.Reserved = 0; + Pin.Property.Flags = KSPROPERTY_TYPE_GET; + Pin.Property.Id = KSPROPERTY_PIN_DATAFLOW; + Pin.Property.Set = KSPROPSETID_Pin; + + /* get pin dataflow */ + Status = MixerContext->Control(MixerData->hDevice, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned); + if (Status != MM_STATUS_SUCCESS) + { + /* failed to retrieve dataflow */ + return Status; + } + + /* setup communication request */ + Pin.Property.Id = KSPROPERTY_PIN_COMMUNICATION; + + /* get pin communication */ + Status = MixerContext->Control(MixerData->hDevice, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned); + + return Status; +} + +MIXER_STATUS +MMixerAddMidiPin( + IN PMIXER_CONTEXT MixerContext, + IN PMIXER_LIST MixerList, + IN ULONG DeviceId, + IN ULONG PinId, + IN ULONG bInput, + IN LPWSTR DeviceName) +{ + LPMIDI_INFO MidiInfo; + + /* allocate midi info */ + MidiInfo = MixerContext->Alloc(sizeof(MIDI_INFO)); + + if (!MidiInfo) + { + /* no memory */ + return MM_STATUS_NO_MEMORY; + } + + /* initialize midi info */ + MidiInfo->DeviceId = DeviceId; + MidiInfo->PinId = PinId; + + /* sanity check */ + ASSERT(wcslen(DeviceName) + 1 < MAXPNAMELEN); + + /* copy device name */ + if (bInput && DeviceName) + { + wcscpy(MidiInfo->u.InCaps.szPname, DeviceName); + } + else if (!bInput && DeviceName) + { + wcscpy(MidiInfo->u.OutCaps.szPname, DeviceName); + } + + /* FIXME determine manufacturer / product id */ + if (bInput) + { + MidiInfo->u.InCaps.dwSupport = 0; + MidiInfo->u.InCaps.wMid = MM_MICROSOFT; + MidiInfo->u.InCaps.wPid = MM_PID_UNMAPPED; + MidiInfo->u.InCaps.vDriverVersion = 1; + } + else + { + MidiInfo->u.OutCaps.dwSupport = 0; + MidiInfo->u.OutCaps.wMid = MM_MICROSOFT; + MidiInfo->u.OutCaps.wPid = MM_PID_UNMAPPED; + MidiInfo->u.OutCaps.vDriverVersion = 1; + } + + if (bInput) + { + /* insert into list */ + InsertTailList(&MixerList->MidiInList, &MidiInfo->Entry); + MixerList->MidiInListCount++; + } + else + { + /* insert into list */ + InsertTailList(&MixerList->MidiOutList, &MidiInfo->Entry); + MixerList->MidiOutListCount++; + } + + return MM_STATUS_SUCCESS; +} + +VOID +MMixerCheckFilterPinMidiSupport( + IN PMIXER_CONTEXT MixerContext, + IN PMIXER_LIST MixerList, + IN LPMIXER_DATA MixerData, + IN ULONG PinId, + IN PKSMULTIPLE_ITEM MultipleItem, + IN LPWSTR szPname) +{ + ULONG Index; + PKSDATARANGE DataRange; + KSPIN_COMMUNICATION Communication; + KSPIN_DATAFLOW DataFlow; + MIXER_STATUS Status; + + /* get first datarange */ + DataRange = (PKSDATARANGE)(MultipleItem + 1); + + /* alignment assert */ + ASSERT(((ULONG_PTR)DataRange & 0x7) == 0); + + /* iterate through all data ranges */ + for(Index = 0; Index < MultipleItem->Count; Index++) + { + if (IsEqualGUIDAligned(&DataRange->MajorFormat, &KSDATAFORMAT_TYPE_MUSIC) && + IsEqualGUIDAligned(&DataRange->SubFormat, &KSDATAFORMAT_SUBTYPE_MIDI) && + IsEqualGUIDAligned(&DataRange->Specifier, &KSDATAFORMAT_SPECIFIER_NONE)) + { + /* pin supports midi datarange */ + if (MMixerGetPinDataFlowAndCommunication(MixerContext, MixerData, PinId, &DataFlow, &Communication) == MM_STATUS_SUCCESS) + { + if (DataFlow == KSPIN_DATAFLOW_IN && Communication == KSPIN_COMMUNICATION_SINK) + { + Status = MMixerAddMidiPin(MixerContext, MixerList, MixerData->DeviceId, PinId, FALSE, szPname); + } + else if (DataFlow == KSPIN_DATAFLOW_OUT && Communication == KSPIN_COMMUNICATION_SOURCE) + { + Status = MMixerAddMidiPin(MixerContext, MixerList, MixerData->DeviceId, PinId, TRUE, szPname); + } + } + } + + /* move to next datarange */ + DataRange = (PKSDATARANGE)((ULONG_PTR)DataRange + DataRange->FormatSize); + + /* alignment assert */ + ASSERT(((ULONG_PTR)DataRange & 0x7) == 0); + + /* data ranges are 64-bit aligned */ + DataRange = (PVOID)(((ULONG_PTR)DataRange + 0x7) & ~0x7); + } +} + +VOID +MMixerInitializeMidiForFilter( + IN PMIXER_CONTEXT MixerContext, + IN PMIXER_LIST MixerList, + IN LPMIXER_DATA MixerData, + IN PTOPOLOGY Topology) +{ + ULONG PinCount, Index; + MIXER_STATUS Status; + PKSMULTIPLE_ITEM MultipleItem; + WCHAR szPname[MAXPNAMELEN]; + + /* get filter pin count */ + MMixerGetTopologyPinCount(Topology, &PinCount); + + /* get mixer name */ + if (MMixerGetDeviceName(MixerContext, szPname, MixerData->hDeviceInterfaceKey) != MM_STATUS_SUCCESS) + { + /* clear name */ + szPname[0] = 0; + } + + /* iterate all pins and check for KSDATARANGE_MUSIC support */ + for(Index = 0; Index < PinCount; Index++) + { + /* get audio pin data ranges */ + Status = MMixerGetAudioPinDataRanges(MixerContext, MixerData->hDevice, Index, &MultipleItem); + + /* check for success */ + if (Status == MM_STATUS_SUCCESS) + { + /* check if there is support KSDATARANGE_MUSIC */ + MMixerCheckFilterPinMidiSupport(MixerContext, MixerList, MixerData, Index, MultipleItem, szPname); + } + } +} + +MIXER_STATUS +MMixerOpenMidiPin( + IN PMIXER_CONTEXT MixerContext, + IN PMIXER_LIST MixerList, + IN ULONG DeviceId, + IN ULONG PinId, + IN ACCESS_MASK DesiredAccess, + IN PIN_CREATE_CALLBACK CreateCallback, + IN PVOID Context, + OUT PHANDLE PinHandle) +{ + PKSPIN_CONNECT PinConnect; + PKSDATAFORMAT DataFormat; + LPMIXER_DATA MixerData; + NTSTATUS Status; + MIXER_STATUS MixerStatus; + + MixerData = MMixerGetDataByDeviceId(MixerList, DeviceId); + if (!MixerData) + return MM_STATUS_INVALID_PARAMETER; + + /* allocate pin connect */ + PinConnect = MMixerAllocatePinConnect(MixerContext, sizeof(KSDATAFORMAT)); + if (!PinConnect) + { + /* no memory */ + return MM_STATUS_NO_MEMORY; + } + + /* initialize pin connect struct */ + MMixerInitializePinConnect(PinConnect, PinId); + + /* get offset to dataformat */ + DataFormat = (PKSDATAFORMAT) (PinConnect + 1); + + /* initialize data format */ + RtlMoveMemory(&DataFormat->MajorFormat, &KSDATAFORMAT_TYPE_MUSIC, sizeof(GUID)); + RtlMoveMemory(&DataFormat->SubFormat, &KSDATAFORMAT_SUBTYPE_MIDI, sizeof(GUID)); + RtlMoveMemory(&DataFormat->Specifier, &KSDATAFORMAT_SPECIFIER_NONE, sizeof(GUID)); + + if (CreateCallback) + { + /* let the callback handle the creation */ + MixerStatus = CreateCallback(Context, DeviceId, PinId, MixerData->hDevice, PinConnect, DesiredAccess, PinHandle); + } + else + { + /* now create the pin */ + Status = KsCreatePin(MixerData->hDevice, PinConnect, DesiredAccess, PinHandle); + + /* normalize status */ + if (Status == STATUS_SUCCESS) + MixerStatus = MM_STATUS_SUCCESS; + else + MixerStatus = MM_STATUS_UNSUCCESSFUL; + } + + /* free create info */ + MixerContext->Free(PinConnect); + + /* done */ + return MixerStatus; +} + +MIXER_STATUS +MMixerGetMidiInfoByIndexAndType( + IN PMIXER_LIST MixerList, + IN ULONG DeviceIndex, + IN ULONG bMidiInputType, + OUT LPMIDI_INFO *OutMidiInfo) +{ + ULONG Index = 0; + PLIST_ENTRY Entry, ListHead; + LPMIDI_INFO MidiInfo; + + if (bMidiInputType) + ListHead = &MixerList->MidiInList; + else + ListHead = &MixerList->MidiOutList; + + /* get first entry */ + Entry = ListHead->Flink; + + while(Entry != ListHead) + { + MidiInfo = (LPMIDI_INFO)CONTAINING_RECORD(Entry, MIDI_INFO, Entry); + + if (Index == DeviceIndex) + { + *OutMidiInfo = MidiInfo; + return MM_STATUS_SUCCESS; + } + Index++; + Entry = Entry->Flink; + } + + return MM_STATUS_INVALID_PARAMETER; +} + +MIXER_STATUS +MMixerMidiOutCapabilities( + IN PMIXER_CONTEXT MixerContext, + IN ULONG DeviceIndex, + OUT LPMIDIOUTCAPSW Caps) +{ + PMIXER_LIST MixerList; + MIXER_STATUS Status; + LPMIDI_INFO MidiInfo; + + /* verify mixer context */ + Status = MMixerVerifyContext(MixerContext); + + if (Status != MM_STATUS_SUCCESS) + { + /* invalid context passed */ + return Status; + } + + /* grab mixer list */ + MixerList = (PMIXER_LIST)MixerContext->MixerContext; + + /* find destination midi */ + Status = MMixerGetMidiInfoByIndexAndType(MixerList, DeviceIndex, FALSE, &MidiInfo); + if (Status != MM_STATUS_SUCCESS) + { + /* failed to find midi info */ + return MM_STATUS_UNSUCCESSFUL; + } + + /* copy capabilities */ + MixerContext->Copy(Caps, &MidiInfo->u.OutCaps, sizeof(MIDIOUTCAPSW)); + + return MM_STATUS_SUCCESS; +} + +MIXER_STATUS +MMixerMidiInCapabilities( + IN PMIXER_CONTEXT MixerContext, + IN ULONG DeviceIndex, + OUT LPMIDIINCAPSW Caps) +{ + PMIXER_LIST MixerList; + MIXER_STATUS Status; + LPMIDI_INFO MidiInfo; + + /* verify mixer context */ + Status = MMixerVerifyContext(MixerContext); + + if (Status != MM_STATUS_SUCCESS) + { + /* invalid context passed */ + return Status; + } + + /* grab mixer list */ + MixerList = (PMIXER_LIST)MixerContext->MixerContext; + + /* find destination midi */ + Status = MMixerGetMidiInfoByIndexAndType(MixerList, DeviceIndex, TRUE, &MidiInfo); + if (Status != MM_STATUS_SUCCESS) + { + /* failed to find midi info */ + return MM_STATUS_UNSUCCESSFUL; + } + + /* copy capabilities */ + MixerContext->Copy(Caps, &MidiInfo->u.InCaps, sizeof(MIDIINCAPSW)); + + return MM_STATUS_SUCCESS; +} + +MIXER_STATUS +MMixerGetMidiDevicePath( + IN PMIXER_CONTEXT MixerContext, + IN ULONG bMidiIn, + IN ULONG DeviceId, + OUT LPWSTR * DevicePath) +{ + PMIXER_LIST MixerList; + LPMIXER_DATA MixerData; + LPMIDI_INFO MidiInfo; + ULONG Length; + MIXER_STATUS Status; + + /* verify mixer context */ + Status = MMixerVerifyContext(MixerContext); + + if (Status != MM_STATUS_SUCCESS) + { + /* invalid context passed */ + return Status; + } + + /* grab mixer list */ + MixerList = (PMIXER_LIST)MixerContext->MixerContext; + + /* find destination midi */ + Status = MMixerGetMidiInfoByIndexAndType(MixerList, DeviceId, bMidiIn, &MidiInfo); + if (Status != MM_STATUS_SUCCESS) + { + /* failed to find midi info */ + return MM_STATUS_INVALID_PARAMETER; + } + + /* get associated device id */ + MixerData = MMixerGetDataByDeviceId(MixerList, MidiInfo->DeviceId); + if (!MixerData) + return MM_STATUS_INVALID_PARAMETER; + + /* calculate length */ + Length = wcslen(MixerData->DeviceName)+1; + + /* allocate destination buffer */ + *DevicePath = MixerContext->Alloc(Length * sizeof(WCHAR)); + + if (!*DevicePath) + { + /* no memory */ + return MM_STATUS_NO_MEMORY; + } + + /* copy device path */ + MixerContext->Copy(*DevicePath, MixerData->DeviceName, Length * sizeof(WCHAR)); + + /* done */ + return MM_STATUS_SUCCESS; +} + +MIXER_STATUS +MMixerSetMidiStatus( + IN PMIXER_CONTEXT MixerContext, + IN HANDLE PinHandle, + IN KSSTATE State) +{ + KSPROPERTY Property; + ULONG Length; + + /* setup property request */ + Property.Set = KSPROPSETID_Connection; + Property.Id = KSPROPERTY_CONNECTION_STATE; + Property.Flags = KSPROPERTY_TYPE_SET; + + return MixerContext->Control(PinHandle, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), &State, sizeof(KSSTATE), &Length); +} + +MIXER_STATUS +MMixerOpenMidi( + IN PMIXER_CONTEXT MixerContext, + IN ULONG DeviceIndex, + IN ULONG bMidiIn, + IN PIN_CREATE_CALLBACK CreateCallback, + IN PVOID Context, + OUT PHANDLE PinHandle) +{ + PMIXER_LIST MixerList; + MIXER_STATUS Status; + LPMIDI_INFO MidiInfo; + ACCESS_MASK DesiredAccess = 0; + + /* verify mixer context */ + Status = MMixerVerifyContext(MixerContext); + + if (Status != MM_STATUS_SUCCESS) + { + /* invalid context passed */ + return Status; + } + + /* grab mixer list */ + MixerList = (PMIXER_LIST)MixerContext->MixerContext; + + /* find destination midi */ + Status = MMixerGetMidiInfoByIndexAndType(MixerList, DeviceIndex, bMidiIn, &MidiInfo); + if (Status != MM_STATUS_SUCCESS) + { + /* failed to find midi info */ + return MM_STATUS_INVALID_PARAMETER; + } + + /* get desired access */ + if (bMidiIn) + { + DesiredAccess |= GENERIC_READ; + } + else + { + DesiredAccess |= GENERIC_WRITE; + } + + /* now try open the pin */ + return MMixerOpenMidiPin(MixerContext, MixerList, MidiInfo->DeviceId, MidiInfo->PinId, DesiredAccess, CreateCallback, Context, PinHandle); +} + +ULONG +MMixerGetMidiInCount( + IN PMIXER_CONTEXT MixerContext) +{ + PMIXER_LIST MixerList; + MIXER_STATUS Status; + + /* verify mixer context */ + Status = MMixerVerifyContext(MixerContext); + + if (Status != MM_STATUS_SUCCESS) + { + /* invalid context passed */ + return Status; + } + + /* grab mixer list */ + MixerList = (PMIXER_LIST)MixerContext->MixerContext; + + return MixerList->MidiInListCount; +} + +ULONG +MMixerGetMidiOutCount( + IN PMIXER_CONTEXT MixerContext) +{ + PMIXER_LIST MixerList; + MIXER_STATUS Status; + + /* verify mixer context */ + Status = MMixerVerifyContext(MixerContext); + + if (Status != MM_STATUS_SUCCESS) + { + /* invalid context passed */ + return Status; + } + + /* grab mixer list */ + MixerList = (PMIXER_LIST)MixerContext->MixerContext; + + return MixerList->MidiOutListCount; +} diff --git a/lib/drivers/sound/mmixer/mixer.c b/lib/drivers/sound/mmixer/mixer.c index cd6b0a08a7d..b04b50c702f 100644 --- a/lib/drivers/sound/mmixer/mixer.c +++ b/lib/drivers/sound/mmixer/mixer.c @@ -447,11 +447,14 @@ MMixerInitialize( MixerList->MixerDataCount = 0; MixerList->WaveInListCount = 0; MixerList->WaveOutListCount = 0; + MixerList->MidiInListCount = 0; + MixerList->MidiOutListCount = 0; InitializeListHead(&MixerList->MixerList); InitializeListHead(&MixerList->MixerData); InitializeListHead(&MixerList->WaveInList); InitializeListHead(&MixerList->WaveOutList); - + InitializeListHead(&MixerList->MidiInList); + InitializeListHead(&MixerList->MidiOutList); /* store mixer list */ MixerContext->MixerContext = (PVOID)MixerList; diff --git a/lib/drivers/sound/mmixer/mmixer.h b/lib/drivers/sound/mmixer/mmixer.h index c7abbb69a52..846d4e9d83b 100644 --- a/lib/drivers/sound/mmixer/mmixer.h +++ b/lib/drivers/sound/mmixer/mmixer.h @@ -122,6 +122,15 @@ ULONG MMixerGetWaveOutCount( IN PMIXER_CONTEXT MixerContext); +ULONG +MMixerGetMidiInCount( + IN PMIXER_CONTEXT MixerContext); + +ULONG +MMixerGetMidiOutCount( + IN PMIXER_CONTEXT MixerContext); + + MIXER_STATUS MMixerGetCapabilities( @@ -199,3 +208,37 @@ MMixerGetWaveDevicePath( IN ULONG bWaveIn, IN ULONG DeviceId, OUT LPWSTR * DevicePath); + +MIXER_STATUS +MMixerMidiOutCapabilities( + IN PMIXER_CONTEXT MixerContext, + IN ULONG DeviceIndex, + OUT LPMIDIOUTCAPSW Caps); + +MIXER_STATUS +MMixerMidiInCapabilities( + IN PMIXER_CONTEXT MixerContext, + IN ULONG DeviceIndex, + OUT LPMIDIINCAPSW Caps); + +MIXER_STATUS +MMixerGetMidiDevicePath( + IN PMIXER_CONTEXT MixerContext, + IN ULONG bMidiIn, + IN ULONG DeviceId, + OUT LPWSTR * DevicePath); + +MIXER_STATUS +MMixerSetMidiStatus( + IN PMIXER_CONTEXT MixerContext, + IN HANDLE PinHandle, + IN KSSTATE State); + +MIXER_STATUS +MMixerOpenMidi( + IN PMIXER_CONTEXT MixerContext, + IN ULONG DeviceIndex, + IN ULONG bMidiIn, + IN PIN_CREATE_CALLBACK CreateCallback, + IN PVOID Context, + OUT PHANDLE PinHandle); diff --git a/lib/drivers/sound/mmixer/priv.h b/lib/drivers/sound/mmixer/priv.h index b854c2e70c2..8a4855f8ca8 100644 --- a/lib/drivers/sound/mmixer/priv.h +++ b/lib/drivers/sound/mmixer/priv.h @@ -128,16 +128,38 @@ typedef struct }u; }WAVE_INFO, *LPWAVE_INFO; +typedef struct +{ + LIST_ENTRY Entry; + ULONG DeviceId; + ULONG PinId; + union + { + MIDIOUTCAPSW OutCaps; + MIDIINCAPSW InCaps; + }u; + +}MIDI_INFO, *LPMIDI_INFO; + typedef struct { ULONG MixerListCount; LIST_ENTRY MixerList; + ULONG MixerDataCount; LIST_ENTRY MixerData; + ULONG WaveInListCount; LIST_ENTRY WaveInList; + ULONG WaveOutListCount; LIST_ENTRY WaveOutList; + + ULONG MidiInListCount; + LIST_ENTRY MidiInList; + + ULONG MidiOutListCount; + LIST_ENTRY MidiOutList; }MIXER_LIST, *PMIXER_LIST; typedef struct @@ -196,16 +218,6 @@ MMixerFreeMixerInfo( IN PMIXER_CONTEXT MixerContext, IN LPMIXER_INFO MixerInfo); -MIXER_STATUS -MMixerGetTargetPins( - IN PMIXER_CONTEXT MixerContext, - IN PKSMULTIPLE_ITEM NodeTypes, - IN PKSMULTIPLE_ITEM NodeConnections, - IN ULONG NodeIndex, - IN ULONG bUpDirection, - OUT PULONG Pins, - IN ULONG PinCount); - MIXER_STATUS MMixerGetPhysicalConnection( IN PMIXER_CONTEXT MixerContext, @@ -213,11 +225,6 @@ MMixerGetPhysicalConnection( IN ULONG PinId, OUT PKSPIN_PHYSICALCONNECTION *OutConnection); -ULONG -MMixerGetIndexOfGuid( - PKSMULTIPLE_ITEM MultipleItem, - LPCGUID NodeType); - MIXER_STATUS MMixerSetupFilter( IN PMIXER_CONTEXT MixerContext, @@ -225,24 +232,24 @@ MMixerSetupFilter( IN LPMIXER_DATA MixerData, IN PULONG DeviceCount); -MIXER_STATUS -MMixerGetTargetPinsByNodeConnectionIndex( +PKSPIN_CONNECT +MMixerAllocatePinConnect( IN PMIXER_CONTEXT MixerContext, - IN PKSMULTIPLE_ITEM NodeConnections, - IN PKSMULTIPLE_ITEM NodeTypes, - IN ULONG bUpDirection, - IN ULONG NodeConnectionIndex, - IN ULONG PinCount, - OUT PULONG Pins); + ULONG DataFormatSize); MIXER_STATUS -MMixerGetControlsFromPin( +MMixerGetAudioPinDataRanges( IN PMIXER_CONTEXT MixerContext, - IN PKSMULTIPLE_ITEM NodeConnections, - IN PKSMULTIPLE_ITEM NodeTypes, + IN HANDLE hDevice, IN ULONG PinId, - IN ULONG bUpDirection, - OUT PULONG Nodes); + IN OUT PKSMULTIPLE_ITEM * OutMultipleItem); + +VOID +MMixerInitializeMidiForFilter( + IN PMIXER_CONTEXT MixerContext, + IN PMIXER_LIST MixerList, + IN LPMIXER_DATA MixerData, + IN PTOPOLOGY Topology); MIXER_STATUS MMixerVerifyContext( @@ -314,12 +321,6 @@ MMixerCreateMixerData( IN HANDLE hDevice, IN HANDLE hKey); -MIXER_STATUS -MMixerGetDeviceName( - IN PMIXER_CONTEXT MixerContext, - IN LPMIXER_INFO MixerInfo, - IN HANDLE hKey); - MIXER_STATUS MMixerInitializeWaveInfo( IN PMIXER_CONTEXT MixerContext, @@ -337,6 +338,18 @@ MMixerAddEvent( IN PVOID MixerEvent, IN PMIXER_EVENT MixerEventRoutine); +MIXER_STATUS +MMixerGetDeviceName( + IN PMIXER_CONTEXT MixerContext, + OUT LPWSTR DeviceName, + IN HANDLE hKey); + +VOID +MMixerInitializePinConnect( + IN OUT PKSPIN_CONNECT PinConnect, + IN ULONG PinId); + + /* topology.c */ MIXER_STATUS @@ -448,3 +461,9 @@ MMixerIsTopologyNodeReserved( IN PTOPOLOGY Topology, IN ULONG NodeIndex, OUT PULONG bReserved); + +VOID +MMixerGetTopologyPinCount( + IN PTOPOLOGY Topology, + OUT PULONG PinCount); + diff --git a/lib/drivers/sound/mmixer/sup.c b/lib/drivers/sound/mmixer/sup.c index 572afbee24e..126bcb53662 100644 --- a/lib/drivers/sound/mmixer/sup.c +++ b/lib/drivers/sound/mmixer/sup.c @@ -31,6 +31,11 @@ const GUID KSPROPSETID_General = {0x1464EDA5L, 0x6A8F, 0x11D1, const GUID KSPROPSETID_Topology = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; const GUID KSEVENTSETID_AudioControlChange = {0xE85E9698L, 0xFA2F, 0x11D1, {0x95, 0xBD, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}}; +const GUID KSDATAFORMAT_TYPE_MUSIC = {0xE725D360L, 0x62CC, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; +const GUID KSDATAFORMAT_SUBTYPE_MIDI = {0x1D262760L, 0xE957, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; +const GUID KSDATAFORMAT_SPECIFIER_NONE = {0x0F6417D6L, 0xC318, 0x11D0, {0xA4, 0x3F, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; + + MIXER_STATUS MMixerVerifyContext( IN PMIXER_CONTEXT MixerContext) @@ -444,7 +449,7 @@ MMixerCreateMixerData( MIXER_STATUS MMixerGetDeviceName( IN PMIXER_CONTEXT MixerContext, - IN LPMIXER_INFO MixerInfo, + OUT LPWSTR DeviceName, IN HANDLE hKey) { LPWSTR Name; @@ -457,10 +462,10 @@ MMixerGetDeviceName( if (Status == MM_STATUS_SUCCESS) { /* copy device name */ - MixerContext->Copy(MixerInfo->MixCaps.szPname, Name, min(wcslen(Name), MAXPNAMELEN-1) * sizeof(WCHAR)); + MixerContext->Copy(DeviceName, Name, min(wcslen(Name), MAXPNAMELEN-1) * sizeof(WCHAR)); /* make sure its null terminated */ - MixerInfo->MixCaps.szPname[MAXPNAMELEN-1] = L'\0'; + DeviceName[MAXPNAMELEN-1] = L'\0'; /* free device name */ MixerContext->Free(Name); @@ -473,14 +478,14 @@ MMixerGetDeviceName( if (Status != MM_STATUS_SUCCESS) return Status; - Status = MixerContext->QueryKeyValue(hKey, L"FriendlyName", (PVOID*)&Name, &Length, &Type); + Status = MixerContext->QueryKeyValue(hTemp, L"FriendlyName", (PVOID*)&Name, &Length, &Type); if (Status == MM_STATUS_SUCCESS) { /* copy device name */ - MixerContext->Copy(MixerInfo->MixCaps.szPname, Name, min(wcslen(Name), MAXPNAMELEN-1) * sizeof(WCHAR)); + MixerContext->Copy(DeviceName, Name, min(wcslen(Name), MAXPNAMELEN-1) * sizeof(WCHAR)); /* make sure its null terminated */ - MixerInfo->MixCaps.szPname[MAXPNAMELEN-1] = L'\0'; + DeviceName[MAXPNAMELEN-1] = L'\0'; /* free device name */ MixerContext->Free(Name); @@ -489,3 +494,21 @@ MMixerGetDeviceName( MixerContext->CloseKey(hTemp); return Status; } + +VOID +MMixerInitializePinConnect( + IN OUT PKSPIN_CONNECT PinConnect, + IN ULONG PinId) +{ + PinConnect->Interface.Set = KSINTERFACESETID_Standard; + PinConnect->Interface.Id = KSINTERFACE_STANDARD_STREAMING; + PinConnect->Interface.Flags = 0; + PinConnect->Medium.Set = KSMEDIUMSETID_Standard; + PinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE; + PinConnect->Medium.Flags = 0; + PinConnect->PinToHandle = NULL; + PinConnect->PinId = PinId; + PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL; + PinConnect->Priority.PrioritySubClass = 1; +} + diff --git a/lib/drivers/sound/mmixer/topology.c b/lib/drivers/sound/mmixer/topology.c index 06f569a68d0..44e85da9c22 100644 --- a/lib/drivers/sound/mmixer/topology.c +++ b/lib/drivers/sound/mmixer/topology.c @@ -983,6 +983,15 @@ MMixerGetNextNodesFromNodeIndex( *OutNodesCount = TopologyNodesCount; } +VOID +MMixerGetTopologyPinCount( + IN PTOPOLOGY Topology, + OUT PULONG PinCount) +{ + /* store pin count */ + *PinCount = Topology->TopologyPinsCount; +} + MIXER_STATUS MMixerAllocateTopologyPinArray( IN PMIXER_CONTEXT MixerContext, diff --git a/lib/drivers/sound/mmixer/wave.c b/lib/drivers/sound/mmixer/wave.c index c0d832af880..c48f03bba58 100644 --- a/lib/drivers/sound/mmixer/wave.c +++ b/lib/drivers/sound/mmixer/wave.c @@ -109,22 +109,7 @@ MMixerGetWaveInfoByIndexAndType( } -VOID -MMixerInitializePinConnect( - IN OUT PKSPIN_CONNECT PinConnect, - IN ULONG PinId) -{ - PinConnect->Interface.Set = KSINTERFACESETID_Standard; - PinConnect->Interface.Id = KSINTERFACE_STANDARD_STREAMING; - PinConnect->Interface.Flags = 0; - PinConnect->Medium.Set = KSMEDIUMSETID_Standard; - PinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE; - PinConnect->Medium.Flags = 0; - PinConnect->PinToHandle = NULL; - PinConnect->PinId = PinId; - PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL; - PinConnect->Priority.PrioritySubClass = 1; -} + VOID MMixerInitializeDataFormat( @@ -369,7 +354,7 @@ MMixerInitializeWaveInfo( WaveInfo->PinId = Pins[0]; /* sanity check */ - ASSERT(wcslen(DeviceName) < MAXPNAMELEN); + ASSERT(wcslen(DeviceName) + 1 < MAXPNAMELEN); /* copy device name */ if (bWaveIn) diff --git a/lib/rtl/sprintf.c b/lib/rtl/sprintf.c index 52f46f8a3d3..51461147d0a 100644 --- a/lib/rtl/sprintf.c +++ b/lib/rtl/sprintf.c @@ -1,3 +1,5 @@ + +#ifndef USE_NEW_SPRINTF /* * PROGRAMMERS: David Welch * Eric Kohl @@ -741,3 +743,5 @@ int __cdecl vsprintf(char *buf, const char *fmt, va_list args) } /* EOF */ +#endif + diff --git a/lib/rtl/swprintf.c b/lib/rtl/swprintf.c index 64d7d65397a..20d975ff757 100644 --- a/lib/rtl/swprintf.c +++ b/lib/rtl/swprintf.c @@ -1,3 +1,4 @@ +#ifndef USE_NEW_SPRINTF /* * PROGRAMMERS: David Welch * Eric Kohl @@ -740,3 +741,4 @@ int __cdecl vswprintf(wchar_t *buf, const wchar_t *fmt, va_list args) } /* EOF */ +#endif diff --git a/lib/sdk/crt/CMakeLists.txt b/lib/sdk/crt/CMakeLists.txt index 9b6c5d9d6c4..80331f40618 100644 --- a/lib/sdk/crt/CMakeLists.txt +++ b/lib/sdk/crt/CMakeLists.txt @@ -122,7 +122,6 @@ list(APPEND CRT_SOURCE mem/memicmp.c misc/amsg.c misc/assert.c - misc/crtmain.c misc/environ.c misc/getargs.c misc/initterm.c @@ -567,4 +566,4 @@ endif(ARCH MATCHES i386) add_library(libcntpr ${LIBCNTPR_SOURCE}) set_property(TARGET libcntpr PROPERTY COMPILE_DEFINITIONS NO_RTL_INLINES _NTSYSTEM_ _NTDLLBUILD_ _LIBCNT_ __CRT__NO_INLINE) -add_dependencies(libcntpr psdk buildno_header) +add_dependencies(libcntpr psdk buildno_header ks386) diff --git a/lib/sdk/crt/conio/cprintf.c b/lib/sdk/crt/conio/cprintf.c index 5c6295c15a1..100e6ae63cf 100644 --- a/lib/sdk/crt/conio/cprintf.c +++ b/lib/sdk/crt/conio/cprintf.c @@ -5,6 +5,7 @@ * PURPOSE: C Runtime * PROGRAMMER: Magnus Olsen (Imported from wine cvs 2006-05-23) */ +#ifndef USE_NEW_SPRINTF #include @@ -38,3 +39,5 @@ _cprintf(const char *fmt, ...) free (mem); return retval; } + +#endif diff --git a/lib/sdk/crt/mbstring/mbstrlen.c b/lib/sdk/crt/mbstring/mbstrlen.c index c600bd1029b..9b324668458 100644 --- a/lib/sdk/crt/mbstring/mbstrlen.c +++ b/lib/sdk/crt/mbstring/mbstrlen.c @@ -12,7 +12,12 @@ #include #include +#ifdef _LIBCNT_ +unsigned short *NlsLeadByteInfo; +#define isleadbyte(c) NlsLeadByteInfo[c] +#else int isleadbyte(int byte); +#endif /* * @implemented diff --git a/lib/sdk/crt/misc/crtmain.c b/lib/sdk/crt/misc/crtmain.c deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/lib/sdk/crt/printf/_cprintf.c b/lib/sdk/crt/printf/_cprintf.c new file mode 100644 index 00000000000..4ce0494bbd6 --- /dev/null +++ b/lib/sdk/crt/printf/_cprintf.c @@ -0,0 +1,25 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/_vcprintf.c + * PURPOSE: Implementation of _vcprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include + +int _vcprintf(const char* format, va_list argptr); + +int +_cdecl +_cprintf(const char * format, ...) +{ + va_list argptr; + int result; + + va_start(argptr, format); + result = _vcprintf(format, argptr); + va_end(argptr); + return result; +} + diff --git a/lib/sdk/crt/printf/_snprintf.c b/lib/sdk/crt/printf/_snprintf.c new file mode 100644 index 00000000000..b8bd5370c56 --- /dev/null +++ b/lib/sdk/crt/printf/_snprintf.c @@ -0,0 +1,39 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/_snprintf.c + * PURPOSE: Implementation of _snprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include +#include + +int _cdecl streamout(FILE *stream, const char *format, va_list argptr); + +int +_cdecl +_snprintf(char *buffer, size_t count, const char *format, ...) +{ + va_list argptr; + int result; + FILE stream; + + stream._base = buffer; + stream._ptr = stream._base; + stream._charbuf = 0; + stream._bufsiz = (unsigned long)-1; + stream._cnt = stream._bufsiz; + stream._flag = 0; + stream._tmpfname = 0; + + va_start(argptr, format); + result = streamout(&stream, format, argptr); + va_end(argptr); + + *stream._ptr = '\0'; + return result; +} + + diff --git a/lib/sdk/crt/printf/_snwprintf.c b/lib/sdk/crt/printf/_snwprintf.c new file mode 100644 index 00000000000..5a4a951d2eb --- /dev/null +++ b/lib/sdk/crt/printf/_snwprintf.c @@ -0,0 +1,42 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/_snwprintf.c + * PURPOSE: Implementation of _snwprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include + +int _cdecl wstreamout(FILE *stream, const wchar_t *format, va_list argptr); + +int +__cdecl +_snwprintf( + wchar_t *buffer, + size_t count, + const wchar_t *format, + ...) +{ + va_list argptr; + int result; + FILE stream; + + stream._base = (char*)buffer; + stream._ptr = stream._base; + stream._bufsiz = count * sizeof(wchar_t); + stream._cnt = stream._bufsiz; + stream._flag = _IOSTRG | _IOWRT; + stream._tmpfname = 0; + stream._charbuf = 0; + + va_start(argptr, format); + result = wstreamout(&stream, format, argptr); + va_end(argptr); + + /* Only zero terminate if there is enough space left */ + if (stream._cnt >= sizeof(wchar_t)) *(wchar_t*)stream._ptr = L'\0'; + + return result; +} diff --git a/lib/sdk/crt/printf/_vcprintf.c b/lib/sdk/crt/printf/_vcprintf.c new file mode 100644 index 00000000000..345a4421e91 --- /dev/null +++ b/lib/sdk/crt/printf/_vcprintf.c @@ -0,0 +1,18 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/_vcprintf.c + * PURPOSE: Implementation of _vcprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include + +int +_cdecl +_vcprintf(const char* format, va_list va) +{ + return 0; +} + + diff --git a/lib/sdk/crt/printf/_vsnprintf.c b/lib/sdk/crt/printf/_vsnprintf.c new file mode 100644 index 00000000000..c94ffc60a8b --- /dev/null +++ b/lib/sdk/crt/printf/_vsnprintf.c @@ -0,0 +1,37 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/_vsnprintf.c + * PURPOSE: Implementation of _vsnprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include + +int _cdecl streamout(FILE *stream, const char *format, va_list argptr); + +int +__cdecl +_vsnprintf( + char *buffer, + size_t count, + const char *format, + va_list argptr) +{ + int result; + FILE stream; + + stream._base = buffer; + stream._ptr = stream._base; + stream._bufsiz = count; + stream._cnt = stream._bufsiz; + stream._flag = _IOSTRG | _IOWRT; + stream._tmpfname = 0; + stream._charbuf = 0; + + result = streamout(&stream, format, argptr); + *stream._ptr = '\0'; + + return result; +} diff --git a/lib/sdk/crt/printf/_vsnwprintf.c b/lib/sdk/crt/printf/_vsnwprintf.c new file mode 100644 index 00000000000..77e12303136 --- /dev/null +++ b/lib/sdk/crt/printf/_vsnwprintf.c @@ -0,0 +1,37 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/_vsnwprintf.c + * PURPOSE: Implementation of _vsnwprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include + +int _cdecl wstreamout(FILE *stream, const wchar_t *format, va_list argptr); + +int +__cdecl +_vsnwprintf( + wchar_t *buffer, + size_t count, + const wchar_t *format, + va_list argptr) +{ + int result; + FILE stream; + + stream._base = (char*)buffer; + stream._ptr = stream._base; + stream._bufsiz = count * sizeof(wchar_t); + stream._cnt = stream._bufsiz; + stream._flag = _IOSTRG | _IOWRT; + stream._tmpfname = 0; + stream._charbuf = 0; + + result = wstreamout(&stream, format, argptr); + *(wchar_t*)stream._ptr = L'\0'; + + return result; +} diff --git a/lib/sdk/crt/printf/fprintf.c b/lib/sdk/crt/printf/fprintf.c new file mode 100644 index 00000000000..9d0b9540995 --- /dev/null +++ b/lib/sdk/crt/printf/fprintf.c @@ -0,0 +1,24 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/fprintf.c + * PURPOSE: Implementation of fprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include + +int +_cdecl +fprintf(FILE *stream, const char *format, ...) +{ + va_list argptr; + int result; + + va_start(argptr, format); + result = vfprintf(stream, format, argptr); + va_end(argptr); + return result; +} + diff --git a/lib/sdk/crt/printf/fwprintf.c b/lib/sdk/crt/printf/fwprintf.c new file mode 100644 index 00000000000..f4b32b13488 --- /dev/null +++ b/lib/sdk/crt/printf/fwprintf.c @@ -0,0 +1,23 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/fwprintf.c + * PURPOSE: Implementation of fwprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include + +int +__cdecl +fwprintf(FILE* file, const wchar_t *format, ...) +{ + va_list argptr; + int result; + + va_start(argptr, format); + result = vfwprintf(file, format, argptr); + va_end(argptr); + return result; +} diff --git a/lib/sdk/crt/printf/printf.c b/lib/sdk/crt/printf/printf.c new file mode 100644 index 00000000000..a9f83f1046c --- /dev/null +++ b/lib/sdk/crt/printf/printf.c @@ -0,0 +1,27 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/printf.c + * PURPOSE: Implementation of printf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include +#include + +int _cdecl streamout(FILE *stream, const char *format, va_list argptr); + +int +_cdecl +printf(const char *format, ...) +{ + va_list argptr; + int result; + + va_start(argptr, format); + result = streamout(stdout, format, argptr); + va_end(argptr); + return result; +} + diff --git a/lib/sdk/crt/printf/sprintf.c b/lib/sdk/crt/printf/sprintf.c new file mode 100644 index 00000000000..33c60926c72 --- /dev/null +++ b/lib/sdk/crt/printf/sprintf.c @@ -0,0 +1,38 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/sprintf.c + * PURPOSE: Implementation of sprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include +#include + +int _cdecl streamout(FILE *stream, const char *format, va_list argptr); + +int +_cdecl +sprintf(char *buffer, const char *format, ...) +{ + va_list argptr; + int result; + FILE stream; + + stream._base = buffer; + stream._ptr = stream._base; + stream._charbuf = 0; + stream._bufsiz = INT_MAX; + stream._cnt = stream._bufsiz; + stream._flag = 0; + stream._tmpfname = 0; + + va_start(argptr, format); + result = streamout(&stream, format, argptr); + va_end(argptr); + + *stream._ptr = '\0'; + return result; +} + diff --git a/lib/sdk/crt/printf/streamout.c b/lib/sdk/crt/printf/streamout.c new file mode 100644 index 00000000000..53bfebafc42 --- /dev/null +++ b/lib/sdk/crt/printf/streamout.c @@ -0,0 +1,636 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/streamout.c + * PURPOSE: Implementation of streamout + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include +#include +#include +#include +#include + +#ifdef _UNICODE +#define streamout wstreamout +#define format_float format_floatw +#endif + +#define MB_CUR_MAX 10 +#define BUFFER_SIZE (32 + 17) + +int mbtowc(wchar_t *wchar, const char *mbchar, size_t count); +int wctomb(char *mbchar, wchar_t wchar); + +typedef struct _STRING +{ + unsigned short Length; + unsigned short MaximumLength; + void *Buffer; +} STRING; + +enum +{ + /* Formatting flags */ + FLAG_ALIGN_LEFT = 0x01, + FLAG_FORCE_SIGN = 0x02, + FLAG_FORCE_SIGNSP = 0x04, + FLAG_PAD_ZERO = 0x08, + FLAG_SPECIAL = 0x10, + + /* Data format flags */ + FLAG_SHORT = 0x100, + FLAG_LONG = 0x200, + FLAG_WIDECHAR = FLAG_LONG, + FLAG_INT64 = 0x400, +#ifdef _WIN64 + FLAG_INTPTR = FLAG_INT64, +#else + FLAG_INTPTR = 0, +#endif + FLAG_LONGDOUBLE = 0x800, +}; + +#define va_arg_f(argptr, flags) \ + (flags & FLAG_INT64) ? va_arg(argptr, __int64) : \ + (flags & FLAG_SHORT) ? (short)va_arg(argptr, int) : \ + va_arg(argptr, int) + +#define va_arg_fu(argptr, flags) \ + (flags & FLAG_INT64) ? va_arg(argptr, unsigned __int64) : \ + (flags & FLAG_SHORT) ? (unsigned short)va_arg(argptr, int) : \ + va_arg(argptr, unsigned int) + +#define va_arg_ffp(argptr, flags) \ + (flags & FLAG_LONGDOUBLE) ? va_arg(argptr, long double) : \ + va_arg(argptr, double) + +#ifdef _LIBCNT_ +# define _flsbuf(chr, stream) 0 +#endif + +#define get_exp(f) floor(f > 0 ? log10(f) : log10(-f)) + +void +#ifdef _LIBCNT +/* Due to restrictions in kernel mode regarding the use of floating point, + we prevent it from being inlined */ +__declspec(noinline) +#endif +format_float( + TCHAR chr, + unsigned int flags, + int precision, + TCHAR **string, + const TCHAR **prefix, + va_list *argptr) +{ + static const TCHAR digits_l[] = _T("0123456789abcdef0x"); + static const TCHAR digits_u[] = _T("0123456789ABCDEF0X"); + static const TCHAR _nan[] = _T("#QNAN"); + static const TCHAR _infinity[] = _T("#INF"); + const TCHAR *digits = digits_l; + int exponent = 0; + long double fpval; + int num_digits, val32, base = 10; + __int64 val64; + + if (precision < 0) precision = 6; + else if (precision > 512) precision = 512; + + fpval = va_arg_ffp(*argptr, flags); + exponent = get_exp(fpval); + + switch (chr) + { + case _T('G'): + digits = digits_u; + case _T('g'): + if (exponent < -4 || exponent >= precision) goto case_e; + break; + + case _T('E'): + digits = digits_u; + case _T('e'): + case_e: + fpval /= pow(10., exponent); + val32 = exponent >= 0 ? exponent : -exponent; + + // FIXME: handle length of exponent field: + // http://msdn.microsoft.com/de-de/library/0fatw238%28VS.80%29.aspx + num_digits = 3; + while (num_digits--) + { + *--(*string) = digits[val32 % 10]; + val32 /= 10; + } + + /* Sign for the exponent */ + *--(*string) = exponent > 0 ? _T('+') : _T('-'); + + /* Add 'e' or 'E' separator */ + *--(*string) = digits[0xe]; + break; + + case _T('A'): + digits = digits_u; + case _T('a'): +// base = 16; + // FIXME: TODO + + case _T('f'): + break; + } + + /* CHECKME: Windows seems to handle a max of 17 digits(?) */ + num_digits = precision <= 17 ? precision: 17; + + /* Handle sign */ + if (fpval < 0) + { + fpval = -fpval; + *prefix = _T("-"); + } + else if (flags & FLAG_FORCE_SIGN) + *prefix = _T("+"); + else if (flags & FLAG_FORCE_SIGNSP) + *prefix = _T(" "); + + /* Handle special cases first */ + if (_isnan(fpval)) + { + (*string) -= sizeof(_nan) / sizeof(TCHAR) - 1; + _tcscpy((*string), _nan); + val64 = 1; + } + else if (!_finite(fpval)) + { + (*string) -= sizeof(_infinity) / sizeof(TCHAR) - 1; + _tcscpy((*string), _infinity); + val64 = 1; + } + else + { + fpval *= pow(10., precision); + val64 = (__int64)(fpval + 0.5); + + while (num_digits-- > 0) + { + *--(*string) = digits[val64 % 10]; + val64 /= 10; + } + } + + *--(*string) = _T('.'); + + /* Digits before the decimal point */ + do + { + *--(*string) = digits[val64 % base]; + val64 /= base; + } + while (val64); + +} + +static +int +streamout_char(FILE *stream, int chr) +{ + /* Flush the buffer if neccessary */ + if (stream->_cnt < sizeof(TCHAR)) + { + return _flsbuf(chr, stream) != EOF; + } + + *(TCHAR*)stream->_ptr = chr; + stream->_ptr += sizeof(TCHAR); + stream->_cnt -= sizeof(TCHAR); + + return 1; +} + +static +int +streamout_astring(FILE *stream, const char *string, int count) +{ + TCHAR chr; + int written = 0; + + while (count--) + { +#ifdef _UNICODE + int len; + if ((len = mbtowc(&chr, string, MB_CUR_MAX)) < 1) break; + string += len; +#else + chr = *string++; +#endif + if (streamout_char(stream, chr) == 0) return -1; + written++; + } + + return written; +} + +static +int +streamout_wstring(FILE *stream, const wchar_t *string, int count) +{ + wchar_t chr; + int written = 0; + + while (count--) + { +#ifndef _UNICODE + char mbchar[MB_CUR_MAX], *ptr = mbchar; + int mblen; + + mblen = wctomb(mbchar, *string++); + if (mblen <= 0) return written; + + while (chr = *ptr++, mblen--) +#else + chr = *string++; +#endif + { + if (streamout_char(stream, chr) == 0) return -1; + written++; + } + } + + return written; +} + +#ifdef _UNICODE +#define streamout_string streamout_wstring +#else +#define streamout_string streamout_astring +#endif + + +int +_cdecl +streamout(FILE *stream, const TCHAR *format, va_list argptr) +{ + static const TCHAR digits_l[] = _T("0123456789abcdef0x"); + static const TCHAR digits_u[] = _T("0123456789ABCDEF0X"); + static const char *_nullstring = "(null)"; + TCHAR buffer[BUFFER_SIZE + 1]; + TCHAR chr, *string; + STRING *nt_string; + const TCHAR *digits, *prefix; + int base, len, prefixlen, fieldwidth, precision, padding; + int written = 1, written_all = 0; + unsigned int flags; + unsigned __int64 val64; + + buffer[BUFFER_SIZE] = '\0'; + + while (written >= 0) + { + chr = *format++; + + /* Check for end of format string */ + if (chr == _T('\0')) break; + + /* Check for 'normal' character or double % */ + if ((chr != _T('%')) || + (chr = *format++) == _T('%')) + { + /* Write the character to the stream */ + if ((written = streamout_char(stream, chr)) == -1) return -1; + written_all += written; + continue; + } + + /* Handle flags */ + flags = 0; + while (1) + { + if (chr == _T('-')) flags |= FLAG_ALIGN_LEFT; + else if (chr == _T('+')) flags |= FLAG_FORCE_SIGN; + else if (chr == _T(' ')) flags |= FLAG_FORCE_SIGNSP; + else if (chr == _T('0')) flags |= FLAG_PAD_ZERO; + else if (chr == _T('#')) flags |= FLAG_SPECIAL; + else break; + chr = *format++; + } + + /* Handle field width modifier */ + if (chr == _T('*')) + { + fieldwidth = va_arg(argptr, int); + if (fieldwidth < 0) + { + flags |= FLAG_ALIGN_LEFT; + fieldwidth = -fieldwidth; + } + chr = *format++; + } + else + { + fieldwidth = 0; + while (chr >= _T('0') && chr <= _T('9')) + { + fieldwidth = fieldwidth * 10 + (chr - _T('0')); + chr = *format++; + } + } + + /* Handle precision modifier */ + if (chr == '.') + { + chr = *format++; + + if (chr == _T('*')) + { + precision = va_arg(argptr, int); + chr = *format++; + } + else + { + precision = 0; + while (chr >= _T('0') && chr <= _T('9')) + { + precision = precision * 10 + (chr - _T('0')); + chr = *format++; + } + } + } + else precision = -1; + + /* Handle argument size prefix */ + while (1) + { + if (chr == _T('h')) flags |= FLAG_SHORT; + else if (chr == _T('w')) flags |= FLAG_WIDECHAR; + else if (chr == _T('L')) flags |= 0; // FIXME: long double + else if (chr == _T('l')) + { + flags |= FLAG_LONG; +#if SUPPORT_LL + if (format[0] == _T('l')) + { + format++; + flags |= FLAG_INT64; + } +#endif + } + else if (chr == _T('I')) + { + if (format[0] == _T('3') && format[1] == _T('2')) + { + format += 2; + } + else if (format[0] == _T('6') && format[1] == _T('4')) + { + format += 2; + flags |= FLAG_INT64; + } + else if (format[0] == _T('x') || format[0] == _T('X') || + format[0] == _T('d') || format[0] == _T('i') || + format[0] == _T('u') || format[0] == _T('o')) + { + flags |= FLAG_INTPTR; + } + else break; + } + else break; + chr = *format++; + } + + /* Handle the format specifier */ + digits = digits_l; + string = &buffer[BUFFER_SIZE]; + base = 10; + prefix = 0; + switch (chr) + { + case _T('n'): + if (flags & FLAG_INT64) + *va_arg(argptr, __int64*) = written_all; + else if (flags & FLAG_SHORT) + *va_arg(argptr, short*) = written_all; + else + *va_arg(argptr, int*) = written_all; + continue; + + case _T('C'): +#ifndef _UNICODE + if (!(flags & FLAG_SHORT)) flags |= FLAG_WIDECHAR; +#endif + goto case_char; + + case _T('c'): +#ifdef _UNICODE + if (!(flags & FLAG_SHORT)) flags |= FLAG_WIDECHAR; +#endif + case_char: + string = buffer; + len = 1; + if (flags & FLAG_WIDECHAR) + { + ((wchar_t*)string)[0] = va_arg(argptr, int); + ((wchar_t*)string)[1] = _T('\0'); + } + else + { + ((char*)string)[0] = va_arg(argptr, int); + ((char*)string)[1] = _T('\0'); + } + break; + + case _T('Z'): + nt_string = va_arg(argptr, void*); + if (nt_string && (string = nt_string->Buffer)) + { + len = nt_string->Length; + if (flags & FLAG_WIDECHAR) len /= sizeof(wchar_t); + break; + } + string = 0; + goto case_string; + + case _T('S'): + string = va_arg(argptr, void*); +#ifndef _UNICODE + if (!(flags & FLAG_SHORT)) flags |= FLAG_WIDECHAR; +#endif + goto case_string; + + case _T('s'): + string = va_arg(argptr, void*); +#ifdef _UNICODE + if (!(flags & FLAG_SHORT)) flags |= FLAG_WIDECHAR; +#endif + + case_string: + if (!string) + { + string = (TCHAR*)_nullstring; + flags &= ~FLAG_WIDECHAR; + } + + if (flags & FLAG_WIDECHAR) + len = wcslen((wchar_t*)string); + else + len = strlen((char*)string); + if (precision >= 0 && len > precision) len = precision; + break; + + case _T('G'): + case _T('E'): + case _T('A'): + case _T('g'): + case _T('e'): + case _T('a'): + case _T('f'): +#ifdef _UNICODE + flags |= FLAG_WIDECHAR; +#else + flags &= ~FLAG_WIDECHAR; +#endif + /* Use external function, one for kernel one for user mode */ + format_float(chr, flags, precision, &string, &prefix, &argptr); + len = _tcslen(string); + precision = 0; + break; + + case _T('d'): + case _T('i'): + val64 = (__int64)va_arg_f(argptr, flags); + + if ((__int64)val64 < 0) + { + val64 = -val64; + prefix = _T("-"); + } + else if (flags & FLAG_FORCE_SIGN) + prefix = _T("+"); + else if (flags & FLAG_FORCE_SIGNSP) + prefix = _T(" "); + + goto case_number; + + case _T('o'): + base = 8; + if (flags & FLAG_SPECIAL) prefix = _T("0"); + goto case_unsigned; + /* Fall through */ + + case _T('p'): + precision = 2 * sizeof(void*); + flags &= ~FLAG_PAD_ZERO; + flags |= FLAG_INTPTR; + /* Fall through */ + + case _T('X'): + digits = digits_u; + /* Fall through */ + + case _T('x'): + base = 16; + if (flags & FLAG_SPECIAL) + { + prefix = &digits[16]; + } + + case _T('u'): + case_unsigned: + val64 = va_arg_fu(argptr, flags); + + case_number: +#ifdef _UNICODE + flags |= FLAG_WIDECHAR; +#else + flags &= ~FLAG_WIDECHAR; +#endif + if (precision < 0) precision = 1; + + /* Gather digits in reverse order */ + while (val64) + { + *--string = digits[val64 % base]; + val64 /= base; + precision--; + } + + len = _tcslen(string); + break; + + default: + /* Treat anything else as a new character */ + format--; + continue; + } + + /* Calculate padding */ + prefixlen = prefix ? _tcslen(prefix) : 0; + if (precision < 0) precision = 0; + padding = fieldwidth - len - prefixlen - precision; + if (padding < 0) padding = 0; + + /* Optional left space padding */ + if ((flags & (FLAG_ALIGN_LEFT | FLAG_PAD_ZERO)) == 0) + { + for (; padding > 0; padding--) + { + if ((written = streamout_char(stream, _T(' '))) == -1) return -2; + written_all += written; + } + } + + /* Optional prefix */ + if (prefix) + { + written = streamout_string(stream, prefix, prefixlen); + if (written == -1) return -3; + written_all += written; + } + + /* Optional left '0' padding */ + if ((flags & FLAG_ALIGN_LEFT) == 0) precision += padding; + while (precision-- > 0) + { + if ((written = streamout_char(stream, _T('0'))) == -1) return -4; + written_all += written; + } + + /* Output the string */ + if (flags & FLAG_WIDECHAR) + written = streamout_wstring(stream, (wchar_t*)string, len); + else + written = streamout_astring(stream, (char*)string, len); + if (written == -1) return -5; + written_all += written; + +#if 0 && SUPPORT_FLOAT + /* Optional right '0' padding */ + while (precision-- > 0) + { + if ((written = streamout_char(stream, _T('0'))) == -1) return -6; + written_all += written; + len++; + } +#endif + + /* Optional right padding */ + if (flags & FLAG_ALIGN_LEFT) + { + while (padding-- > 0) + { + if ((written = streamout_char(stream, _T(' '))) == -1) return -7; + written_all += written; + } + } + + } + + if (written == -1) return -8; + + return written_all; +} + diff --git a/lib/sdk/crt/printf/swprintf.c b/lib/sdk/crt/printf/swprintf.c new file mode 100644 index 00000000000..115c1e6da56 --- /dev/null +++ b/lib/sdk/crt/printf/swprintf.c @@ -0,0 +1,39 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/swprintf.c + * PURPOSE: Implementation of swprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include +#include + +int _cdecl wstreamout(FILE *stream, const wchar_t *format, va_list argptr); + +int +_cdecl +swprintf(wchar_t *buffer, const wchar_t *format, ...) +{ + va_list argptr; + int result; + FILE stream; + + stream._base = (char*)buffer; + stream._ptr = stream._base; + stream._charbuf = 0; + stream._bufsiz = INT_MAX; + stream._cnt = stream._bufsiz; + stream._flag = 0; + stream._tmpfname = 0; + + va_start(argptr, format); + result = wstreamout(&stream, format, argptr); + va_end(argptr); + + *(wchar_t*)stream._ptr = '\0'; + return result; +} + + diff --git a/lib/sdk/crt/printf/vfprintf.c b/lib/sdk/crt/printf/vfprintf.c new file mode 100644 index 00000000000..5a28be59dac --- /dev/null +++ b/lib/sdk/crt/printf/vfprintf.c @@ -0,0 +1,29 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/vfprintf.c + * PURPOSE: Implementation of vfprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include + +void _cdecl _lock_file(FILE* file); +void _cdecl _unlock_file(FILE* file); +int _cdecl streamout(FILE *stream, const char *format, va_list argptr); + +int +_cdecl +vfprintf(FILE *stream, const char *format, va_list argptr) +{ + int result; + + _lock_file(stream); + + result = streamout(stream, format, argptr); + + _unlock_file(stream); + + return result; +} diff --git a/lib/sdk/crt/printf/vfwprintf.c b/lib/sdk/crt/printf/vfwprintf.c new file mode 100644 index 00000000000..fef618845c2 --- /dev/null +++ b/lib/sdk/crt/printf/vfwprintf.c @@ -0,0 +1,20 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/vfwprintf.c + * PURPOSE: Implementation of vfwprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include + +int _cdecl wstreamout(FILE *stream, const wchar_t *format, va_list argptr); + +int +__cdecl +vfwprintf(FILE* file, const wchar_t *format, va_list argptr) +{ + return wstreamout(file, format, argptr); +} + diff --git a/lib/sdk/crt/printf/vprintf.c b/lib/sdk/crt/printf/vprintf.c new file mode 100644 index 00000000000..e126c8ddf8f --- /dev/null +++ b/lib/sdk/crt/printf/vprintf.c @@ -0,0 +1,19 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/vprintf.c + * PURPOSE: Implementation of vprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include + +int _cdecl streamout(FILE *stream, const char *format, va_list argptr); + +int +__cdecl +vprintf(const char *format, va_list argptr) +{ + return streamout(stdout, format, argptr); +} diff --git a/lib/sdk/crt/printf/vsprintf.c b/lib/sdk/crt/printf/vsprintf.c new file mode 100644 index 00000000000..12a3d535835 --- /dev/null +++ b/lib/sdk/crt/printf/vsprintf.c @@ -0,0 +1,37 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/vsprintf.c + * PURPOSE: Implementation of vsprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include +#include + +int _cdecl streamout(FILE *stream, const char *format, va_list argptr); + +int +__cdecl +vsprintf( + char *buffer, + const char *format, + va_list argptr) +{ + int result; + FILE stream; + + stream._base = buffer; + stream._ptr = stream._base; + stream._charbuf = 0; + stream._bufsiz = INT_MAX; + stream._cnt = stream._bufsiz; + stream._flag = _IOSTRG|_IOWRT|_IOMYBUF; + stream._tmpfname = 0; + + result = streamout(&stream, format, argptr); + *stream._ptr = '\0'; + + return result; +} diff --git a/lib/sdk/crt/printf/vswprintf.c b/lib/sdk/crt/printf/vswprintf.c new file mode 100644 index 00000000000..4bba6ba3b2c --- /dev/null +++ b/lib/sdk/crt/printf/vswprintf.c @@ -0,0 +1,18 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/vswprintf.c + * PURPOSE: Implementation of vswprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include +#include + +int +__cdecl +vswprintf(wchar_t *buffer, const wchar_t *format, va_list argptr) +{ + return _vsnwprintf(buffer, INT_MAX, format, argptr); +} diff --git a/lib/sdk/crt/printf/vwprintf.c b/lib/sdk/crt/printf/vwprintf.c new file mode 100644 index 00000000000..b9ee541613d --- /dev/null +++ b/lib/sdk/crt/printf/vwprintf.c @@ -0,0 +1,19 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/vwprintf.c + * PURPOSE: Implementation of vwprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include + +int _cdecl wstreamout(FILE *stream, const wchar_t *format, va_list argptr); + +int +__cdecl +vwprintf(const wchar_t *format, va_list argptr) +{ + return wstreamout(stdout, format, argptr); +} diff --git a/lib/sdk/crt/printf/wprintf.c b/lib/sdk/crt/printf/wprintf.c new file mode 100644 index 00000000000..1c5e9011132 --- /dev/null +++ b/lib/sdk/crt/printf/wprintf.c @@ -0,0 +1,25 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/wprintf.c + * PURPOSE: Implementation of wprintf + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include + +int _cdecl wstreamout(FILE *stream, const wchar_t *format, va_list argptr); + +int +__cdecl +wprintf(const wchar_t *format, ...) +{ + va_list argptr; + int result; + + va_start(argptr, format); + result = wstreamout(stdout, format, argptr); + va_end(argptr); + return result; +} diff --git a/lib/sdk/crt/printf/wstreamout.c b/lib/sdk/crt/printf/wstreamout.c new file mode 100644 index 00000000000..bc078737db6 --- /dev/null +++ b/lib/sdk/crt/printf/wstreamout.c @@ -0,0 +1,12 @@ +/* + * COPYRIGHT: GNU GPL, see COPYING in the top level directory + * PROJECT: ReactOS crt library + * FILE: lib/sdk/crt/printf/wstreamout.c + * PURPOSE: Implementation of wstreamout + * PROGRAMMER: Timo Kreuzer + */ + +#define _UNICODE +#define UNICODE + +#include "streamout.c" diff --git a/lib/sdk/crt/stdio/file.c b/lib/sdk/crt/stdio/file.c index a3540ce28bd..eb20be7cf3f 100644 --- a/lib/sdk/crt/stdio/file.c +++ b/lib/sdk/crt/stdio/file.c @@ -2814,6 +2814,7 @@ FILE* CDECL tmpfile(void) return file; } +#ifndef USE_NEW_SPRINTF /********************************************************************* * vfprintf (MSVCRT.@) */ @@ -2947,6 +2948,7 @@ int CDECL printf(const char *format, ...) va_end(valist); return res; } +#endif /********************************************************************* * ungetc (MSVCRT.@) @@ -2984,6 +2986,7 @@ wint_t CDECL ungetwc(wint_t wc, FILE * file) return mwc; } +#ifndef USE_NEW_SPRINTF /********************************************************************* * wprintf (MSVCRT.@) */ @@ -2996,6 +2999,7 @@ int CDECL wprintf(const wchar_t *format, ...) va_end(valist); return res; } +#endif /********************************************************************* * _getmaxstdio (MSVCRT.@) diff --git a/lib/sdk/crt/stdio/lnx_sprintf.c b/lib/sdk/crt/stdio/lnx_sprintf.c index f42a4e37662..29d150d68e5 100644 --- a/lib/sdk/crt/stdio/lnx_sprintf.c +++ b/lib/sdk/crt/stdio/lnx_sprintf.c @@ -14,7 +14,7 @@ * Lars Wirzenius & Linus Torvalds * Wirzenius wrote this portably, Torvalds fucked it up :-) */ - +#ifndef USE_NEW_SPRINTF #include #include @@ -879,3 +879,4 @@ int __cdecl vsprintf(char *buf, const char *fmt, va_list args) } #endif /* EOF */ +#endif diff --git a/lib/sdk/crt/stdio/lock_file.c b/lib/sdk/crt/stdio/lock_file.c new file mode 100644 index 00000000000..28c0265c36e --- /dev/null +++ b/lib/sdk/crt/stdio/lock_file.c @@ -0,0 +1,15 @@ + +#include + +void +_cdecl +_lock_file(FILE* file) +{ +} + +void +_cdecl +_unlock_file(FILE* file) +{ +} + diff --git a/lib/sdk/crt/string/wcs.c b/lib/sdk/crt/string/wcs.c index aca8147fe76..e2f2a6af612 100644 --- a/lib/sdk/crt/string/wcs.c +++ b/lib/sdk/crt/string/wcs.c @@ -392,6 +392,7 @@ static inline int pf_output_format_A( pf_output *out, LPCSTR str, return r; } +#ifndef USE_NEW_SPRINTF static int pf_handle_string_format( pf_output *out, const void* str, int len, pf_flags *flags, BOOL capital_letter) { @@ -883,6 +884,7 @@ int CDECL vswprintf( wchar_t* str, const wchar_t* format, va_list args ) return _vsnwprintf( str, INT_MAX, format, args ); } #endif +#endif /********************************************************************* * wcscoll (MSVCRT.@) diff --git a/ntoskrnl/cache/cachesub.c b/ntoskrnl/cache/cachesub.c new file mode 100644 index 00000000000..fb9d9e31eb9 --- /dev/null +++ b/ntoskrnl/cache/cachesub.c @@ -0,0 +1,347 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Kernel + * FILE: ntoskrnl/cache/cachesup.c + * PURPOSE: Logging and configuration routines + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + * Art Yerkes + */ + +/* INCLUDES *******************************************************************/ + +#include +#include "newcc.h" +#include "section/newmm.h" +#define NDEBUG +#include + +/* STRUCTURES *****************************************************************/ + +typedef struct _WORK_QUEUE_WITH_READ_AHEAD +{ + WORK_QUEUE_ITEM WorkItem; + PFILE_OBJECT FileObject; + LARGE_INTEGER FileOffset; + ULONG Length; +} WORK_QUEUE_WITH_READ_AHEAD, *PWORK_QUEUE_WITH_READ_AHEAD; + +/* FUNCTIONS ******************************************************************/ + +PDEVICE_OBJECT +NTAPI +MmGetDeviceObjectForFile(IN PFILE_OBJECT FileObject); + +VOID +NTAPI +CcSetReadAheadGranularity(IN PFILE_OBJECT FileObject, + IN ULONG Granularity) +{ + PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)FileObject->SectionObjectPointer->SharedCacheMap; + if (Map) + { + Map->ReadAheadGranularity = Granularity; + } +} + +VOID +NTAPI +CcpReadAhead(PVOID Context) +{ + LARGE_INTEGER Offset; + PWORK_QUEUE_WITH_READ_AHEAD WorkItem = (PWORK_QUEUE_WITH_READ_AHEAD)Context; + PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)WorkItem->FileObject->SectionObjectPointer->SharedCacheMap; + DPRINT("Reading ahead %08x%08x:%x %wZ\n", + WorkItem->FileOffset.HighPart, + WorkItem->FileOffset.LowPart, + WorkItem->Length, + &WorkItem->FileObject->FileName); + Offset.HighPart = WorkItem->FileOffset.HighPart; + Offset.LowPart = PAGE_ROUND_DOWN(WorkItem->FileOffset.LowPart); + if (Map) + { + PLIST_ENTRY ListEntry; + volatile char *chptr; + PNOCC_BCB Bcb; + for (ListEntry = Map->AssociatedBcb.Flink; + ListEntry != &Map->AssociatedBcb; + ListEntry = ListEntry->Flink) + { + Bcb = CONTAINING_RECORD(ListEntry, NOCC_BCB, ThisFileList); + if ((Offset.QuadPart + WorkItem->Length < Bcb->FileOffset.QuadPart) || + (Bcb->FileOffset.QuadPart + Bcb->Length < Offset.QuadPart)) + continue; + for (chptr = Bcb->BaseAddress, Offset = Bcb->FileOffset; + chptr < ((PCHAR)Bcb->BaseAddress) + Bcb->Length && + Offset.QuadPart < + WorkItem->FileOffset.QuadPart + WorkItem->Length; + chptr += PAGE_SIZE, Offset.QuadPart += PAGE_SIZE) + { + *chptr ^= 0; + } + } + } + ObDereferenceObject(WorkItem->FileObject); + ExFreePool(WorkItem); + DPRINT("Done\n"); +} + +VOID +NTAPI +CcScheduleReadAhead(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length) +{ + PWORK_QUEUE_WITH_READ_AHEAD WorkItem; + DPRINT("Schedule read ahead %08x%08x:%x %wZ\n", + FileOffset->HighPart, + FileOffset->LowPart, + Length, + &FileObject->FileName); + WorkItem = ExAllocatePool(NonPagedPool, sizeof(*WorkItem)); + if (!WorkItem) KeBugCheck(0); + ObReferenceObject(FileObject); + WorkItem->FileObject = FileObject; + WorkItem->FileOffset = *FileOffset; + WorkItem->Length = Length; + ExInitializeWorkItem(((PWORK_QUEUE_ITEM)WorkItem), (PWORKER_THREAD_ROUTINE)CcpReadAhead, WorkItem); + ExQueueWorkItem((PWORK_QUEUE_ITEM)WorkItem, DelayedWorkQueue); + DPRINT("Done\n"); +} + +VOID +NTAPI +CcSetDirtyPinnedData(IN PVOID BcbVoid, + IN OPTIONAL PLARGE_INTEGER Lsn) +{ + PNOCC_BCB Bcb = (PNOCC_BCB)BcbVoid; + Bcb->Dirty = TRUE; +} + +LARGE_INTEGER +NTAPI +CcGetFlushedValidData(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, + IN BOOLEAN CcInternalCaller) +{ + LARGE_INTEGER Result = {{0}}; + UNIMPLEMENTED; + while (TRUE); + return Result; +} + + + +VOID +NTAPI +_CcpFlushCache(IN PNOCC_CACHE_MAP Map, + IN OPTIONAL PLARGE_INTEGER FileOffset, + IN ULONG Length, + OUT OPTIONAL PIO_STATUS_BLOCK IoStatus, + BOOLEAN Delete, + const char *File, + int Line) +{ + PNOCC_BCB Bcb = NULL; + LARGE_INTEGER LowerBound, UpperBound; + PLIST_ENTRY ListEntry; + IO_STATUS_BLOCK IOSB = { }; + + DPRINT1("CcFlushCache (while file) (%s:%d)\n", File, Line); + + if (FileOffset && Length) + { + LowerBound.QuadPart = FileOffset->QuadPart; + UpperBound.QuadPart = LowerBound.QuadPart + Length; + } + else + { + LowerBound.QuadPart = 0; + UpperBound.QuadPart = 0x7fffffffffffffffull; + } + + CcpLock(); + ListEntry = Map->AssociatedBcb.Flink; + + while (ListEntry != &Map->AssociatedBcb) + { + Bcb = CONTAINING_RECORD(ListEntry, NOCC_BCB, ThisFileList); + CcpReferenceCache(Bcb - CcCacheSections); + + if (Bcb->FileOffset.QuadPart + Bcb->Length >= LowerBound.QuadPart && + Bcb->FileOffset.QuadPart < UpperBound.QuadPart) + { + DPRINT + ("Bcb #%x (@%08x%08x)\n", + Bcb - CcCacheSections, + Bcb->FileOffset.u.HighPart, Bcb->FileOffset.u.LowPart); + + Bcb->RefCount++; + CcpUnlock(); + MiFlushMappedSection(Bcb->BaseAddress, &Bcb->FileOffset, &Map->FileSizes.FileSize, Bcb->Dirty); + CcpLock(); + Bcb->RefCount--; + + Bcb->Dirty = FALSE; + + ListEntry = ListEntry->Flink; + if (Delete && Bcb->RefCount < 2) + { + Bcb->RefCount = 1; + CcpDereferenceCache(Bcb - CcCacheSections, FALSE); + } + else + CcpUnpinData(Bcb); + } + else + { + ListEntry = ListEntry->Flink; + CcpUnpinData(Bcb); + } + + DPRINT("End loop\n"); + } + CcpUnlock(); + + if (IoStatus) *IoStatus = IOSB; +} + +VOID +NTAPI +CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, + IN OPTIONAL PLARGE_INTEGER FileOffset, + IN ULONG Length, + OUT OPTIONAL PIO_STATUS_BLOCK IoStatus) +{ + PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)SectionObjectPointer->SharedCacheMap; + + // Not cached + if (!Map) + { + if (IoStatus) + { + IoStatus->Status = STATUS_SUCCESS; + IoStatus->Information = 0; + } + return; + } + + CcpFlushCache(Map, FileOffset, Length, IoStatus, TRUE); +} + +BOOLEAN +NTAPI +CcFlushImageSection +(PSECTION_OBJECT_POINTERS SectionObjectPointer, + MMFLUSH_TYPE FlushType) +{ + PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)SectionObjectPointer->SharedCacheMap; + PNOCC_BCB Bcb; + PLIST_ENTRY Entry; + IO_STATUS_BLOCK IOSB; + BOOLEAN Result = TRUE; + + if (!Map) return TRUE; + + for (Entry = Map->AssociatedBcb.Flink; + Entry != &Map->AssociatedBcb; + Entry = Entry->Flink) + { + Bcb = CONTAINING_RECORD(Entry, NOCC_BCB, ThisFileList); + + if (!Bcb->Dirty) continue; + + switch (FlushType) + { + case MmFlushForDelete: + CcPurgeCacheSection + (SectionObjectPointer, + &Bcb->FileOffset, + Bcb->Length, + FALSE); + break; + case MmFlushForWrite: + CcFlushCache + (SectionObjectPointer, + &Bcb->FileOffset, + Bcb->Length, + &IOSB); + break; + } + } + + return Result; +} + +// Always succeeds for us +PVOID +NTAPI +CcRemapBcb(IN PVOID Bcb) +{ + CcpLock(); + ASSERT(RtlTestBit(CcCacheBitmap, ((PNOCC_BCB)Bcb) - CcCacheSections)); + CcpReferenceCache(((PNOCC_BCB)Bcb) - CcCacheSections); + CcpUnlock(); + return Bcb; +} + +VOID +NTAPI +CcShutdownSystem() +{ + ULONG i; + + DPRINT1("CC: Shutdown\n"); + + for (i = 0; i < CACHE_NUM_SECTIONS; i++) + { + PNOCC_BCB Bcb = &CcCacheSections[i]; + if (Bcb->SectionObject) + { + DPRINT1 + ("Evicting #%02x %08x%08x %wZ\n", + i, + Bcb->FileOffset.u.HighPart, Bcb->FileOffset.u.LowPart, + &MmGetFileObjectForSection + ((PROS_SECTION_OBJECT)Bcb->SectionObject)->FileName); + CcpFlushCache(Bcb->Map, NULL, 0, NULL, TRUE); + Bcb->Dirty = FALSE; + } + } + + DPRINT1("Done\n"); +} + + +VOID +NTAPI +CcRepinBcb(IN PVOID Bcb) +{ + CcpLock(); + ASSERT(RtlTestBit(CcCacheBitmap, ((PNOCC_BCB)Bcb) - CcCacheSections)); + DPRINT("CcRepinBcb(#%x)\n", ((PNOCC_BCB)Bcb) - CcCacheSections); + CcpReferenceCache(((PNOCC_BCB)Bcb) - CcCacheSections); + CcpUnlock(); +} + +VOID +NTAPI +CcUnpinRepinnedBcb(IN PVOID Bcb, + IN BOOLEAN WriteThrough, + OUT PIO_STATUS_BLOCK IoStatus) +{ + PNOCC_BCB RealBcb = (PNOCC_BCB)Bcb; + + if (WriteThrough) + { + DPRINT("BCB #%x\n", RealBcb - CcCacheSections); + + CcpFlushCache + (RealBcb->Map, + &RealBcb->FileOffset, + RealBcb->Length, + IoStatus, RealBcb->Dirty); + } + + CcUnpinData(Bcb); +} + +/* EOF */ diff --git a/ntoskrnl/cache/copysup.c b/ntoskrnl/cache/copysup.c new file mode 100644 index 00000000000..2f8a954e846 --- /dev/null +++ b/ntoskrnl/cache/copysup.c @@ -0,0 +1,214 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Kernel + * FILE: ntoskrnl/cache/copysup.c + * PURPOSE: Logging and configuration routines + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES *******************************************************************/ + +#include +#include "newcc.h" +#include "section/newmm.h" +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +ULONG CcFastMdlReadWait; +ULONG CcFastMdlReadNotPossible; +ULONG CcFastReadNotPossible; +ULONG CcFastReadWait; +ULONG CcFastReadNoWait; +ULONG CcFastReadResourceMiss; + +#define TAG_COPY_READ TAG('C', 'o', 'p', 'y') +#define TAG_COPY_WRITE TAG('R', 'i', 't', 'e') + +/* FUNCTIONS ******************************************************************/ + +BOOLEAN +NTAPI +CcCopyRead(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + OUT PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus) +{ + PCHAR ReadBuffer; + ULONG ReadLen; + PVOID Bcb; + PCHAR BufferTarget = (PCHAR)Buffer; + LARGE_INTEGER CacheOffset, EndOfExtent, NextOffset; + + DPRINT + ("CcCopyRead(%x,%x,%d,%d,%x)\n", + FileObject, + FileOffset->LowPart, + Length, + Wait, + Buffer); + + CacheOffset.QuadPart = FileOffset->QuadPart; + EndOfExtent.QuadPart = FileOffset->QuadPart + Length; + + while (CacheOffset.QuadPart < EndOfExtent.QuadPart) + { + NextOffset.QuadPart = CacheOffset.QuadPart; + NextOffset.LowPart = (NextOffset.LowPart + CACHE_STRIPE) & ~(CACHE_STRIPE-1); + ReadLen = EndOfExtent.QuadPart - CacheOffset.QuadPart; + if (CacheOffset.QuadPart + ReadLen > NextOffset.QuadPart) + { + ReadLen = NextOffset.QuadPart - CacheOffset.QuadPart; + } + + DPRINT("Reading %d bytes in this go (at %08x%08x)\n", ReadLen, CacheOffset.HighPart, CacheOffset.LowPart); + + if (!CcPinRead + (FileObject, + &CacheOffset, + ReadLen, + Wait ? PIN_WAIT : PIN_IF_BCB, + &Bcb, + (PVOID*)&ReadBuffer)) + { + IoStatus->Status = STATUS_UNSUCCESSFUL; + IoStatus->Information = 0; + DPRINT("Failed CcCopyRead\n"); + return FALSE; + } + + DPRINT1("Copying %d bytes at %08x%08x\n", ReadLen, CacheOffset.HighPart, CacheOffset.LowPart); + RtlCopyMemory + (BufferTarget, + ReadBuffer, + ReadLen); + + BufferTarget += ReadLen; + + CacheOffset = NextOffset; + CcUnpinData(Bcb); + } + + IoStatus->Status = STATUS_SUCCESS; + IoStatus->Information = Length; + + DPRINT("Done with CcCopyRead\n"); + + return TRUE; +} + +VOID +NTAPI +CcFastCopyRead(IN PFILE_OBJECT FileObject, + IN ULONG FileOffset, + IN ULONG Length, + IN ULONG PageCount, + OUT PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus) +{ + UNIMPLEMENTED; + while (TRUE); +} + +BOOLEAN +NTAPI +CcCopyWrite(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN PVOID Buffer) +{ + INT Count = 0; + BOOLEAN Result; + PNOCC_BCB Bcb; + PVOID WriteBuf; + ULONG WriteLen; + LARGE_INTEGER CurrentOffset = *FileOffset; + LARGE_INTEGER EndOffset; + LARGE_INTEGER NextOffset; + + EndOffset.QuadPart = CurrentOffset.QuadPart + Length; + + DPRINT + ("CcCopyWrite(%x,%x,%d,%d,%x)\n", + FileObject, + FileOffset->LowPart, + Length, + Wait, + Buffer); + + while (CurrentOffset.QuadPart < EndOffset.QuadPart) + { + NextOffset.HighPart = CurrentOffset.HighPart; + NextOffset.LowPart = (CurrentOffset.LowPart + CACHE_STRIPE) & ~(CACHE_STRIPE - 1); + DPRINT("NextOffset %08x%08x\n", NextOffset.u.HighPart, NextOffset.u.LowPart); + WriteLen = MIN(NextOffset.QuadPart - CurrentOffset.QuadPart, Length); + DPRINT("Copying %x bytes from %08x%08x\n", + WriteLen, + CurrentOffset.u.HighPart, CurrentOffset.u.LowPart); + DPRINT("CcPreparePinWrite\n"); + Result = CcPreparePinWrite + (FileObject, &CurrentOffset, WriteLen, FALSE, Wait ? PIN_WAIT : PIN_IF_BCB, + (PVOID *)&Bcb, &WriteBuf); + DPRINT("Result %s %x %x\n", Result ? "TRUE" : "FALSE", Bcb, WriteBuf); + if (!Result) + { + DPRINT1("CcPreparePinWrite Failed?\n"); + if (Wait) RtlRaiseStatus(STATUS_NOT_MAPPED_DATA); else return FALSE; + } + DPRINT1("Copying actual memory to BCB#%x (@%x) (from buffer at %x)\n", Bcb - CcCacheSections, WriteBuf, Bcb->BaseAddress); + + //MiZeroFillSection(WriteBuf, &CurrentOffset, WriteLen); + RtlCopyMemory(WriteBuf, ((PCHAR)Buffer) + Count, WriteLen); + Count += WriteLen; + Length -= WriteLen; + CurrentOffset = NextOffset; + Bcb->Dirty = TRUE; + CcUnpinData(Bcb); + } + + DPRINT("Done with CcCopyWrite\n"); + + return TRUE; +} + +VOID +NTAPI +CcFastCopyWrite(IN PFILE_OBJECT FileObject, + IN ULONG FileOffset, + IN ULONG Length, + IN PVOID Buffer) +{ + UNIMPLEMENTED; + while (TRUE); +} + +BOOLEAN +NTAPI +CcCanIWrite(IN PFILE_OBJECT FileObject, + IN ULONG BytesToWrite, + IN BOOLEAN Wait, + IN UCHAR Retrying) +{ + UNIMPLEMENTED; + while (TRUE); + return FALSE; +} + +VOID +NTAPI +CcDeferWrite(IN PFILE_OBJECT FileObject, + IN PCC_POST_DEFERRED_WRITE PostRoutine, + IN PVOID Context1, + IN PVOID Context2, + IN ULONG BytesToWrite, + IN BOOLEAN Retrying) +{ + UNIMPLEMENTED; + while (TRUE); +} + +/* EOF */ diff --git a/ntoskrnl/cache/fssup.c b/ntoskrnl/cache/fssup.c new file mode 100644 index 00000000000..8646513e3b0 --- /dev/null +++ b/ntoskrnl/cache/fssup.c @@ -0,0 +1,513 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Kernel + * FILE: ntoskrnl/cache/fssup.c + * PURPOSE: Logging and configuration routines + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + * Art Yerkes + */ + +/* INCLUDES *******************************************************************/ + +#include +#include "newcc.h" +#include "section/newmm.h" +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +PFSN_PREFETCHER_GLOBALS CcPfGlobals; +extern LONG CcOutstandingDeletes; +extern KEVENT CcpLazyWriteEvent; +extern KEVENT CcFinalizeEvent; +extern VOID NTAPI CcpUnmapThread(PVOID Unused); +extern VOID NTAPI CcpLazyWriteThread(PVOID Unused); +HANDLE CcUnmapThreadHandle, CcLazyWriteThreadHandle; +CLIENT_ID CcUnmapThreadId, CcLazyWriteThreadId; + +typedef struct _NOCC_PRIVATE_CACHE_MAP +{ + LIST_ENTRY ListEntry; + PFILE_OBJECT FileObject; + PNOCC_CACHE_MAP Map; +} NOCC_PRIVATE_CACHE_MAP, *PNOCC_PRIVATE_CACHE_MAP; + +LIST_ENTRY CcpAllSharedCacheMaps; + +/* FUNCTIONS ******************************************************************/ + +// Interact with legacy balance manager for now +// This can fall away when our section implementation supports +// demand paging properly +NTSTATUS +CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed) +{ + ULONG i, Freed, BcbHead; + + *NrFreed = 0; + + for (i = 0; i < CACHE_NUM_SECTIONS; i++) { + BcbHead = (i+CcCacheClockHand) % CACHE_NUM_SECTIONS; + + // Reference a cache stripe so it won't go away + CcpLock(); + if (CcCacheSections[BcbHead].BaseAddress) { + CcpReferenceCache(i); + CcpUnlock(); + } else { + CcpUnlock(); + continue; + } + + // Defer to MM to try recovering pages from it + Freed = MiCacheEvictPages + (CcCacheSections[BcbHead].BaseAddress, Target); + + Target -= Freed; + *NrFreed += Freed; + + CcpLock(); + CcpDereferenceCache(BcbHead, FALSE); + CcpUnlock(); + } + + return STATUS_SUCCESS; +} + +BOOLEAN +NTAPI +CcInitializeCacheManager(VOID) +{ + int i; + + DPRINT("Initialize\n"); + for (i = 0; i < CACHE_NUM_SECTIONS; i++) + { + KeInitializeEvent(&CcCacheSections[i].ExclusiveWait, SynchronizationEvent, FALSE); + InitializeListHead(&CcCacheSections[i].ThisFileList); + } + + InitializeListHead(&CcpAllSharedCacheMaps); + + KeInitializeEvent(&CcDeleteEvent, SynchronizationEvent, FALSE); + KeInitializeEvent(&CcFinalizeEvent, SynchronizationEvent, FALSE); + KeInitializeEvent(&CcpLazyWriteEvent, SynchronizationEvent, FALSE); + + CcCacheBitmap->Buffer = ((PULONG)&CcCacheBitmap[1]); + CcCacheBitmap->SizeOfBitMap = ROUND_UP(CACHE_NUM_SECTIONS, 32); + DPRINT("Cache has %d entries\n", CcCacheBitmap->SizeOfBitMap); + ExInitializeFastMutex(&CcMutex); + + // MM stub + KeInitializeEvent(&MmWaitPageEvent, SynchronizationEvent, FALSE); + + // Until we're fully demand paged, we can do things the old way through + // the balance manager + MmInitializeMemoryConsumer(MC_CACHE, CcRosTrimCache); + + return TRUE; +} + +VOID +NTAPI +CcPfInitializePrefetcher(VOID) +{ + /* Notify debugger */ + DbgPrintEx(DPFLTR_PREFETCHER_ID, + DPFLTR_TRACE_LEVEL, + "CCPF: InitializePrefetecher()\n"); + + /* Setup the Prefetcher Data */ + InitializeListHead(&CcPfGlobals.ActiveTraces); + InitializeListHead(&CcPfGlobals.CompletedTraces); + ExInitializeFastMutex(&CcPfGlobals.CompletedTracesLock); + + /* FIXME: Setup the rest of the prefetecher */ +} + +BOOLEAN +NTAPI +CcpAcquireFileLock(PNOCC_CACHE_MAP Map) +{ + DPRINT("Calling AcquireForLazyWrite: %x\n", Map->LazyContext); + return Map->Callbacks.AcquireForLazyWrite(Map->LazyContext, TRUE); +} + +VOID +NTAPI +CcpReleaseFileLock(PNOCC_CACHE_MAP Map) +{ + DPRINT("Releasing Lazy Write %x\n", Map->LazyContext); + Map->Callbacks.ReleaseFromLazyWrite(Map->LazyContext); +} + +// Must have CcpLock() +PFILE_OBJECT CcpFindOtherStreamFileObject(PFILE_OBJECT FileObject) +{ + PLIST_ENTRY Entry, Private; + for (Entry = CcpAllSharedCacheMaps.Flink; + Entry != &CcpAllSharedCacheMaps; + Entry = Entry->Flink) + { + // 'Identical' test for other stream file object + PNOCC_CACHE_MAP Map = CONTAINING_RECORD(Entry, NOCC_CACHE_MAP, Entry); + for (Private = Map->PrivateCacheMaps.Flink; + Private != &Map->PrivateCacheMaps; + Private = Private->Flink) + { + PNOCC_PRIVATE_CACHE_MAP PrivateMap = CONTAINING_RECORD(Private, NOCC_PRIVATE_CACHE_MAP, ListEntry); + if (PrivateMap->FileObject->Flags & FO_STREAM_FILE && + PrivateMap->FileObject->DeviceObject == FileObject->DeviceObject && + PrivateMap->FileObject->Vpb == FileObject->Vpb && + PrivateMap->FileObject->FsContext == FileObject->FsContext && + PrivateMap->FileObject->FsContext2 == FileObject->FsContext2 && + 1) + { + return PrivateMap->FileObject; + } + } + } + return 0; +} + +// Thanks: http://windowsitpro.com/Windows/Articles/ArticleID/3864/pg/2/2.html + +VOID +NTAPI +CcInitializeCacheMap(IN PFILE_OBJECT FileObject, + IN PCC_FILE_SIZES FileSizes, + IN BOOLEAN PinAccess, + IN PCACHE_MANAGER_CALLBACKS Callbacks, + IN PVOID LazyWriteContext) +{ + PNOCC_CACHE_MAP Map = FileObject->SectionObjectPointer->SharedCacheMap; + PNOCC_PRIVATE_CACHE_MAP PrivateCacheMap = FileObject->PrivateCacheMap; + + CcpLock(); + if (!Map && FileObject->Flags & FO_STREAM_FILE) + { + PFILE_OBJECT IdenticalStreamFileObject = + CcpFindOtherStreamFileObject(FileObject); + if (IdenticalStreamFileObject) + Map = IdenticalStreamFileObject->SectionObjectPointer->SharedCacheMap; + if (Map) + { + DPRINT1 + ("Linking SFO %x to previous SFO %x through cache map %x #\n", + FileObject, IdenticalStreamFileObject, Map); + } + } + if (!Map) + { + DPRINT("Initializing file object for (%p) %wZ\n", FileObject, &FileObject->FileName); + Map = ExAllocatePool(NonPagedPool, sizeof(NOCC_CACHE_MAP)); + FileObject->SectionObjectPointer->SharedCacheMap = Map; + Map->FileSizes = *FileSizes; + Map->LazyContext = LazyWriteContext; + Map->ReadAheadGranularity = PAGE_SIZE; + RtlCopyMemory(&Map->Callbacks, Callbacks, sizeof(*Callbacks)); + // For now ... + DPRINT("FileSizes->ValidDataLength %08x%08x\n", FileSizes->ValidDataLength.HighPart, FileSizes->ValidDataLength.LowPart); + InitializeListHead(&Map->AssociatedBcb); + InitializeListHead(&Map->PrivateCacheMaps); + InsertTailList(&CcpAllSharedCacheMaps, &Map->Entry); + DPRINT("New Map %x\n", Map); + } + if (!PrivateCacheMap) + { + PrivateCacheMap = ExAllocatePool(NonPagedPool, sizeof(*PrivateCacheMap)); + FileObject->PrivateCacheMap = PrivateCacheMap; + PrivateCacheMap->FileObject = FileObject; + ObReferenceObject(PrivateCacheMap->FileObject); + } + + PrivateCacheMap->Map = Map; + InsertTailList(&Map->PrivateCacheMaps, &PrivateCacheMap->ListEntry); + + CcpUnlock(); +} + +ULONG +NTAPI +CcpCountCacheSections(IN PNOCC_CACHE_MAP Map) +{ + PLIST_ENTRY Entry; + ULONG Count; + + for (Count = 0, Entry = Map->AssociatedBcb.Flink; Entry != &Map->AssociatedBcb; Entry = Entry->Flink, Count++); + + return Count; +} + +BOOLEAN +NTAPI +CcUninitializeCacheMap(IN PFILE_OBJECT FileObject, + IN OPTIONAL PLARGE_INTEGER TruncateSize, + IN OPTIONAL PCACHE_UNINITIALIZE_EVENT UninitializeEvent) +{ + BOOLEAN LastMap = FALSE; + PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)FileObject->SectionObjectPointer->SharedCacheMap; + PNOCC_PRIVATE_CACHE_MAP PrivateCacheMap = FileObject->PrivateCacheMap; + + DPRINT("Uninitializing file object for %wZ SectionObjectPointer %x\n", &FileObject->FileName, FileObject->SectionObjectPointer); + + ASSERT(UninitializeEvent == NULL); + + if (Map) + CcpFlushCache(Map, NULL, 0, NULL, FALSE); + + CcpLock(); + if (PrivateCacheMap) + { + ASSERT(!Map || Map == PrivateCacheMap->Map); + ASSERT(PrivateCacheMap->FileObject == FileObject); + + RemoveEntryList(&PrivateCacheMap->ListEntry); + if (IsListEmpty(&PrivateCacheMap->Map->PrivateCacheMaps)) + { + while (!IsListEmpty(&Map->AssociatedBcb)) + { + PNOCC_BCB Bcb = CONTAINING_RECORD(Map->AssociatedBcb.Flink, NOCC_BCB, ThisFileList); + DPRINT("Evicting cache stripe #%x\n", Bcb - CcCacheSections); + Bcb->RefCount = 1; + CcpDereferenceCache(Bcb - CcCacheSections, TRUE); + } + RemoveEntryList(&PrivateCacheMap->Map->Entry); + ExFreePool(PrivateCacheMap->Map); + FileObject->SectionObjectPointer->SharedCacheMap = NULL; + LastMap = TRUE; + } + ObDereferenceObject(PrivateCacheMap->FileObject); + FileObject->PrivateCacheMap = NULL; + ExFreePool(PrivateCacheMap); + } + CcpUnlock(); + + DPRINT("Uninit complete\n"); + + return LastMap; +} + +VOID +NTAPI +CcSetFileSizes(IN PFILE_OBJECT FileObject, + IN PCC_FILE_SIZES FileSizes) +{ + PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)FileObject->SectionObjectPointer->SharedCacheMap; + if (!Map) return; + Map->FileSizes = *FileSizes; + PNOCC_BCB Bcb = Map->AssociatedBcb.Flink == &Map->AssociatedBcb ? + NULL : CONTAINING_RECORD(Map->AssociatedBcb.Flink, NOCC_BCB, ThisFileList); + if (!Bcb) return; + MmExtendCacheSection(Bcb->SectionObject, &FileSizes->FileSize, FALSE); + DPRINT("FileSizes->FileSize %x\n", FileSizes->FileSize.LowPart); + DPRINT("FileSizes->AllocationSize %x\n", FileSizes->AllocationSize.LowPart); + DPRINT("FileSizes->ValidDataLength %x\n", FileSizes->ValidDataLength.LowPart); +} + +BOOLEAN +NTAPI +CcGetFileSizes +(IN PFILE_OBJECT FileObject, + IN PCC_FILE_SIZES FileSizes) +{ + PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)FileObject->SectionObjectPointer->SharedCacheMap; + if (!Map) return FALSE; + *FileSizes = Map->FileSizes; + return TRUE; +} + +BOOLEAN +NTAPI +CcPurgeCacheSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, + IN OPTIONAL PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN UninitializeCacheMaps) +{ + PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)SectionObjectPointer->SharedCacheMap; + if (!Map) return TRUE; + CcpFlushCache(Map, NULL, 0, NULL, TRUE); + return TRUE; +} + +VOID +NTAPI +CcSetDirtyPageThreshold(IN PFILE_OBJECT FileObject, + IN ULONG DirtyPageThreshold) +{ + UNIMPLEMENTED; + while (TRUE); +} + +BOOLEAN +NTAPI +CcZeroData(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER StartOffset, + IN PLARGE_INTEGER EndOffset, + IN BOOLEAN Wait) +{ + PNOCC_BCB Bcb = NULL; + PLIST_ENTRY ListEntry = NULL; + LARGE_INTEGER LowerBound = *StartOffset; + LARGE_INTEGER UpperBound = *EndOffset; + LARGE_INTEGER Target, End; + PVOID PinnedBcb, PinnedBuffer; + PNOCC_CACHE_MAP Map = FileObject->SectionObjectPointer->SharedCacheMap; + + DPRINT + ("S %08x%08x E %08x%08x\n", + StartOffset->u.HighPart, StartOffset->u.LowPart, + EndOffset->u.HighPart, EndOffset->u.LowPart); + + if (!Map) + { + NTSTATUS Status; + IO_STATUS_BLOCK IOSB; + PCHAR ZeroBuf = ExAllocatePool(PagedPool, PAGE_SIZE); + ULONG ToWrite; + + if (!ZeroBuf) RtlRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); + DPRINT1("RtlZeroMemory(%x,%x)\n", ZeroBuf, PAGE_SIZE); + RtlZeroMemory(ZeroBuf, PAGE_SIZE); + + Target.QuadPart = PAGE_ROUND_DOWN(LowerBound.QuadPart); + End.QuadPart = PAGE_ROUND_UP(UpperBound.QuadPart); + + // Handle leading page + if (LowerBound.QuadPart != Target.QuadPart) + { + ToWrite = MIN(UpperBound.QuadPart - LowerBound.QuadPart, (PAGE_SIZE - LowerBound.QuadPart) & (PAGE_SIZE - 1)); + DPRINT("Zero last half %08x%08x %x\n", Target.u.HighPart, Target.u.LowPart, ToWrite); + Status = MiSimpleRead(FileObject, &Target, ZeroBuf, PAGE_SIZE, &IOSB); + if (!NT_SUCCESS(Status)) + { + ExFreePool(ZeroBuf); + RtlRaiseStatus(Status); + } + DPRINT1("RtlZeroMemory(%x,%x)\n", ZeroBuf + LowerBound.QuadPart - Target.QuadPart, ToWrite); + RtlZeroMemory(ZeroBuf + LowerBound.QuadPart - Target.QuadPart, ToWrite); + Status = MiSimpleWrite(FileObject, &Target, ZeroBuf, MIN(PAGE_SIZE,UpperBound.QuadPart-Target.QuadPart), &IOSB); + if (!NT_SUCCESS(Status)) + { + ExFreePool(ZeroBuf); + RtlRaiseStatus(Status); + } + Target.QuadPart += PAGE_SIZE; + } + + DPRINT1("RtlZeroMemory(%x,%x)\n", ZeroBuf, PAGE_SIZE); + RtlZeroMemory(ZeroBuf, PAGE_SIZE); + + while (UpperBound.QuadPart - Target.QuadPart > PAGE_SIZE) + { + DPRINT("Zero full page %08x%08x\n", Target.u.HighPart, Target.u.LowPart); + Status = MiSimpleWrite(FileObject, &Target, ZeroBuf, PAGE_SIZE, &IOSB); + if (!NT_SUCCESS(Status)) + { + ExFreePool(ZeroBuf); + RtlRaiseStatus(Status); + } + Target.QuadPart += PAGE_SIZE; + } + + if (UpperBound.QuadPart > Target.QuadPart) + { + ToWrite = UpperBound.QuadPart - Target.QuadPart; + DPRINT("Zero first half %08x%08x %x\n", Target.u.HighPart, Target.u.LowPart, ToWrite); + Status = MiSimpleRead(FileObject, &Target, ZeroBuf, PAGE_SIZE, &IOSB); + if (!NT_SUCCESS(Status)) + { + ExFreePool(ZeroBuf); + RtlRaiseStatus(Status); + } + DPRINT1("RtlZeroMemory(%x,%x)\n", ZeroBuf, ToWrite); + RtlZeroMemory(ZeroBuf, ToWrite); + Status = MiSimpleWrite(FileObject, &Target, ZeroBuf, MIN(PAGE_SIZE, UpperBound.QuadPart-Target.QuadPart), &IOSB); + if (!NT_SUCCESS(Status)) + { + ExFreePool(ZeroBuf); + RtlRaiseStatus(Status); + } + Target.QuadPart += PAGE_SIZE; + } + + ExFreePool(ZeroBuf); + return TRUE; + } + + CcpLock(); + ListEntry = Map->AssociatedBcb.Flink; + + while (ListEntry != &Map->AssociatedBcb) + { + Bcb = CONTAINING_RECORD(ListEntry, NOCC_BCB, ThisFileList); + CcpReferenceCache(Bcb - CcCacheSections); + + if (Bcb->FileOffset.QuadPart + Bcb->Length >= LowerBound.QuadPart && + Bcb->FileOffset.QuadPart < UpperBound.QuadPart) + { + DPRINT + ("Bcb #%x (@%08x%08x)\n", + Bcb - CcCacheSections, + Bcb->FileOffset.u.HighPart, Bcb->FileOffset.u.LowPart); + + Target.QuadPart = MAX(Bcb->FileOffset.QuadPart, LowerBound.QuadPart); + End.QuadPart = MIN(Map->FileSizes.ValidDataLength.QuadPart, UpperBound.QuadPart); + End.QuadPart = MIN(End.QuadPart, Bcb->FileOffset.QuadPart + Bcb->Length); + CcpUnlock(); + + if (!CcPreparePinWrite + (FileObject, + &Target, + End.QuadPart - Target.QuadPart, + TRUE, + Wait, + &PinnedBcb, + &PinnedBuffer)) + { + return FALSE; + } + + ASSERT(PinnedBcb == Bcb); + + CcpLock(); + ListEntry = ListEntry->Flink; + // Return from pin state + CcpUnpinData(PinnedBcb); + } + + CcpUnpinData(Bcb); + } + + CcpUnlock(); + + return TRUE; +} + +PFILE_OBJECT +NTAPI +CcGetFileObjectFromSectionPtrs(IN PSECTION_OBJECT_POINTERS SectionObjectPointer) +{ + PFILE_OBJECT Result = NULL; + PNOCC_CACHE_MAP Map = SectionObjectPointer->SharedCacheMap; + CcpLock(); + if (!IsListEmpty(&Map->AssociatedBcb)) + { + PNOCC_BCB Bcb = CONTAINING_RECORD(Map->AssociatedBcb.Flink, NOCC_BCB, ThisFileList); + Result = MmGetFileObjectForSection((PROS_SECTION_OBJECT)Bcb->SectionObject); + } + CcpUnlock(); + return Result; +} + +PFILE_OBJECT +NTAPI +CcGetFileObjectFromBcb(PVOID Bcb) +{ + PNOCC_BCB RealBcb = (PNOCC_BCB)Bcb; + DPRINT("BCB #%x\n", RealBcb - CcCacheSections); + return MmGetFileObjectForSection((PROS_SECTION_OBJECT)RealBcb->SectionObject); +} + +/* EOF */ diff --git a/ntoskrnl/cache/lazyrite.c b/ntoskrnl/cache/lazyrite.c new file mode 100644 index 00000000000..4dcbb5d8a36 --- /dev/null +++ b/ntoskrnl/cache/lazyrite.c @@ -0,0 +1,36 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Kernel + * FILE: ntoskrnl/cache/lazyrite.c + * PURPOSE: Logging and configuration routines + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES *******************************************************************/ + +#include +#include "newcc.h" +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +KEVENT CcpLazyWriteEvent; + +/* FUNCTIONS ******************************************************************/ + +VOID NTAPI +CcpLazyWriteThread(PVOID Unused) +{ + /* Not implemented */ +} + +NTSTATUS +NTAPI +CcWaitForCurrentLazyWriterActivity(VOID) +{ + //KeWaitForSingleObject(&CcpLazyWriteEvent, Executive, KernelMode, FALSE, NULL); + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/ntoskrnl/cache/logsup.c b/ntoskrnl/cache/logsup.c new file mode 100644 index 00000000000..b06432fc394 --- /dev/null +++ b/ntoskrnl/cache/logsup.c @@ -0,0 +1,75 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Kernel + * FILE: ntoskrnl/cache/logsup.c + * PURPOSE: Logging and configuration routines + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES *******************************************************************/ + +#include +#include "newcc.h" +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +VOID +NTAPI +CcSetAdditionalCacheAttributes(IN PFILE_OBJECT FileObject, + IN BOOLEAN DisableReadAhead, + IN BOOLEAN DisableWriteBehind) +{ + UNIMPLEMENTED; + while (TRUE); +} + +VOID +NTAPI +CcSetLogHandleForFile(IN PFILE_OBJECT FileObject, + IN PVOID LogHandle, + IN PFLUSH_TO_LSN FlushToLsnRoutine) +{ + PNOCC_CACHE_MAP Map = FileObject->SectionObjectPointer->SharedCacheMap; + if (!Map) return; + Map->LogHandle = LogHandle; + Map->FlushToLsn = FlushToLsnRoutine; +} + +LARGE_INTEGER +NTAPI +CcGetDirtyPages(IN PVOID LogHandle, + IN PDIRTY_PAGE_ROUTINE DirtyPageRoutine, + IN PVOID Context1, + IN PVOID Context2) +{ + LARGE_INTEGER Result = {{0}}; + UNIMPLEMENTED; + while (TRUE); + return Result; +} + +BOOLEAN +NTAPI +CcIsThereDirtyData(IN PVPB Vpb) +{ + UNIMPLEMENTED; + while (TRUE); + return FALSE; +} + +LARGE_INTEGER +NTAPI +CcGetLsnForFileObject(IN PFILE_OBJECT FileObject, + OUT OPTIONAL PLARGE_INTEGER OldestLsn) +{ + LARGE_INTEGER Result = {{0}}; + UNIMPLEMENTED; + while (TRUE); + return Result; +} + +/* EOF */ diff --git a/ntoskrnl/cache/mdlsup.c b/ntoskrnl/cache/mdlsup.c new file mode 100644 index 00000000000..6e558d5aa4c --- /dev/null +++ b/ntoskrnl/cache/mdlsup.c @@ -0,0 +1,143 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Kernel + * FILE: ntoskrnl/cache/logsup.c + * PURPOSE: Logging and configuration routines + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES *******************************************************************/ + +#include +#include "newcc.h" +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + + +PMDL +NTAPI +CcpBuildCacheMdl +(PFILE_OBJECT FileObject, + PLARGE_INTEGER FileOffset, + ULONG Length, + PIO_STATUS_BLOCK IOSB) +{ + PMDL Mdl; + PVOID Bcb, Buffer; + + BOOLEAN Result = CcMapData + (FileObject, + FileOffset, + Length, + PIN_WAIT, + &Bcb, + &Buffer); + + if (!Result) + { + IOSB->Information = 0; + IOSB->Status = STATUS_UNSUCCESSFUL; + return NULL; + } + + IOSB->Information = Length; + IOSB->Status = STATUS_SUCCESS; + + Mdl = IoAllocateMdl + (Buffer, + Length, + FALSE, + FALSE, + NULL); + + if (!Mdl) + { + IOSB->Information = 0; + IOSB->Status = STATUS_NO_MEMORY; + return NULL; + } + + IOSB->Information = Length; + IOSB->Status = STATUS_SUCCESS; + + return Mdl; +} + +VOID +NTAPI +CcMdlRead(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + OUT PMDL *MdlChain, + OUT PIO_STATUS_BLOCK IoStatus) +{ + *MdlChain = CcpBuildCacheMdl + (FileObject, + FileOffset, + Length, + IoStatus); +} + +VOID +NTAPI +CcMdlReadComplete(IN PFILE_OBJECT FileObject, + IN PMDL MdlChain) +{ + IoFreeMdl(MdlChain); +} + +VOID +NTAPI +CcMdlReadComplete2(IN PMDL MdlChain, + IN PFILE_OBJECT FileObject) +{ + DPRINT("Not sure\n"); +} + +VOID +NTAPI +CcPrepareMdlWrite(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + OUT PMDL *MdlChain, + OUT PIO_STATUS_BLOCK IoStatus) +{ + *MdlChain = CcpBuildCacheMdl + (FileObject, + FileOffset, + Length, + IoStatus); +} + +VOID +NTAPI +CcMdlWriteComplete(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PMDL MdlChain) +{ + IoFreeMdl(MdlChain); +} + +VOID +NTAPI +CcMdlWriteComplete2(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PMDL MdlChain) +{ + DPRINT("Not sure\n"); +} + +VOID +NTAPI +CcMdlWriteAbort(IN PFILE_OBJECT FileObject, + IN PMDL MdlChain) +{ + ASSERT(FALSE); + IoFreeMdl(MdlChain); +} + +/* EOF */ diff --git a/ntoskrnl/cache/newcc.h b/ntoskrnl/cache/newcc.h new file mode 100644 index 00000000000..5e0bd2608eb --- /dev/null +++ b/ntoskrnl/cache/newcc.h @@ -0,0 +1,170 @@ +#pragma once + +struct _MM_CACHE_SECTION_SEGMENT; + +typedef struct _NOCC_BCB +{ + /* Public part */ + PUBLIC_BCB Bcb; + + struct _NOCC_CACHE_MAP *Map; + struct _MM_CACHE_SECTION_SEGMENT *SectionObject; + LARGE_INTEGER FileOffset; + ULONG Length; + PVOID BaseAddress; + BOOLEAN Dirty; + PVOID OwnerPointer; + + /* Reference counts */ + ULONG RefCount; + + LIST_ENTRY ThisFileList; + + KEVENT ExclusiveWait; + ULONG ExclusiveWaiter; + BOOLEAN Exclusive; +} NOCC_BCB, *PNOCC_BCB; + +typedef struct _NOCC_CACHE_MAP +{ + LIST_ENTRY Entry; + LIST_ENTRY AssociatedBcb; + LIST_ENTRY PrivateCacheMaps; + ULONG NumberOfMaps; + ULONG RefCount; + CC_FILE_SIZES FileSizes; + CACHE_MANAGER_CALLBACKS Callbacks; + PVOID LazyContext; + PVOID LogHandle; + PFLUSH_TO_LSN FlushToLsn; + ULONG ReadAheadGranularity; +} NOCC_CACHE_MAP, *PNOCC_CACHE_MAP; + +VOID +NTAPI +CcPfInitializePrefetcher( + VOID +); + +VOID +NTAPI +CcMdlReadComplete2( + IN PMDL MemoryDescriptorList, + IN PFILE_OBJECT FileObject +); + +VOID +NTAPI +CcMdlWriteComplete2( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PMDL MdlChain +); + +VOID +NTAPI +CcInitView(VOID); + +VOID +NTAPI +CcpUnpinData(PNOCC_BCB Bcb); + +BOOLEAN +NTAPI +CcInitializeCacheManager(VOID); + +VOID +NTAPI +CcShutdownSystem(); + +VOID +NTAPI +CcInitCacheZeroPage(VOID); + +/* Called by section.c */ +BOOLEAN +NTAPI +CcFlushImageSection(PSECTION_OBJECT_POINTERS SectionObjectPointer, MMFLUSH_TYPE FlushType); + +VOID +NTAPI +_CcpFlushCache +(IN PNOCC_CACHE_MAP Map, + IN OPTIONAL PLARGE_INTEGER FileOffset, + IN ULONG Length, + OUT OPTIONAL PIO_STATUS_BLOCK IoStatus, + BOOLEAN Delete, + const char *File, + int Line); + +#define CcpFlushCache(M,F,L,I,D) _CcpFlushCache(M,F,L,I,D,__FILE__,__LINE__) + +BOOLEAN +NTAPI +CcGetFileSizes(PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes); + +ULONG +NTAPI +CcpCountCacheSections(PNOCC_CACHE_MAP Map); + +BOOLEAN +NTAPI +CcpAcquireFileLock(PNOCC_CACHE_MAP Map); + +VOID +NTAPI +CcpReleaseFileLock(PNOCC_CACHE_MAP Map); + +/* + * Macro for generic cache manage bugchecking. Note that this macro assumes + * that the file name including extension is always longer than 4 characters. + */ +#define KEBUGCHECKCC \ + KEBUGCHECKEX(CACHE_MANAGER, \ + (*(ULONG*)(__FILE__ + sizeof(__FILE__) - 4) << 16) | \ + (__LINE__ & 0xFFFF), 0, 0, 0) + +/* Private data */ + +#define CACHE_SINGLE_FILE_MAX (16) +#define CACHE_OVERALL_SIZE (32 * 1024 * 1024) +#define CACHE_STRIPE VACB_MAPPING_GRANULARITY +#define CACHE_SHIFT 18 +#define CACHE_NUM_SECTIONS (CACHE_OVERALL_SIZE / CACHE_STRIPE) +#define CACHE_ROUND_UP(x) (((x) + (CACHE_STRIPE-1)) & ~(CACHE_STRIPE-1)) +#define CACHE_ROUND_DOWN(x) ((x) & ~(CACHE_STRIPE-1)) +#define INVALID_CACHE ((ULONG)~0) + +extern NOCC_BCB CcCacheSections[CACHE_NUM_SECTIONS]; +extern PRTL_BITMAP CcCacheBitmap; +extern FAST_MUTEX CcMutex; +extern KEVENT CcDeleteEvent; +extern ULONG CcCacheClockHand; +extern LIST_ENTRY CcPendingUnmap; +extern KEVENT CcpLazyWriteEvent; + +#define CcpLock() _CcpLock(__FILE__,__LINE__) +#define CcpUnlock() _CcpUnlock(__FILE__,__LINE__) + +extern VOID _CcpLock(const char *file, int line); +extern VOID _CcpUnlock(const char *file, int line); + +extern VOID CcpReferenceCache(ULONG Sector); +extern VOID CcpDereferenceCache(ULONG Sector, BOOLEAN Immediate); +BOOLEAN +NTAPI +CcpMapData +(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG Flags, + OUT PVOID *BcbResult, + OUT PVOID *Buffer); + +BOOLEAN +NTAPI +CcpPinMappedData(IN PNOCC_CACHE_MAP Map, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG Flags, + IN OUT PVOID *Bcb); diff --git a/ntoskrnl/cache/pinsup.c b/ntoskrnl/cache/pinsup.c new file mode 100644 index 00000000000..5531bbb9720 --- /dev/null +++ b/ntoskrnl/cache/pinsup.c @@ -0,0 +1,785 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Kernel + * FILE: ntoskrnl/cache/pinsup.c + * PURPOSE: Logging and configuration routines + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + * Art Yerkes + */ + +/* INCLUDES *******************************************************************/ + +#include +#include "newcc.h" +#include "section/newmm.h" +#define NDEBUG +#include + +/* The following is a test mode that only works with modified filesystems. + * it maps the cache sections read only until they're pinned writable, and then + * turns them readonly again when they're unpinned. + * This helped me determine that a certain bug was not a memory overwrite. */ +//#define PIN_WRITE_ONLY + +/* GLOBALS ********************************************************************/ + +#define TAG_MAP_SEC TAG('C', 'c', 'S', 'x') +#define TAG_MAP_READ TAG('M', 'c', 'p', 'y') +#define TAG_MAP_BCB TAG('B', 'c', 'b', ' ') + +NOCC_BCB CcCacheSections[CACHE_NUM_SECTIONS]; +CHAR CcpBitmapBuffer[sizeof(RTL_BITMAP) + ROUND_UP((CACHE_NUM_SECTIONS), 32) / 8]; +PRTL_BITMAP CcCacheBitmap = (PRTL_BITMAP)&CcpBitmapBuffer; +FAST_MUTEX CcMutex; +KEVENT CcDeleteEvent; +KEVENT CcFinalizeEvent; +ULONG CcCacheClockHand; +LONG CcOutstandingDeletes; + +/* FUNCTIONS ******************************************************************/ + +PETHREAD LastThread; +VOID _CcpLock(const char *file, int line) +{ + //DPRINT("<<<---<<< CC In Mutex(%s:%d %x)!\n", file, line, PsGetCurrentThread()); + ExAcquireFastMutex(&CcMutex); +} + +VOID _CcpUnlock(const char *file, int line) +{ + ExReleaseFastMutex(&CcMutex); + //DPRINT(">>>--->>> CC Exit Mutex!\n", file, line); +} + +PDEVICE_OBJECT +NTAPI +MmGetDeviceObjectForFile(IN PFILE_OBJECT FileObject); + +NTSTATUS CcpAllocateSection +(PFILE_OBJECT FileObject, + ULONG Length, + ULONG Protect, + PMM_CACHE_SECTION_SEGMENT *Result) +{ + NTSTATUS Status; + LARGE_INTEGER MaxSize; + + MaxSize.QuadPart = Length; + + DPRINT("Making Section for File %x\n", FileObject); + DPRINT("File name %wZ\n", &FileObject->FileName); + Status = MmCreateCacheSection + (Result, + STANDARD_RIGHTS_REQUIRED, + NULL, + &MaxSize, + Protect, + SEC_RESERVE | SEC_CACHE, + FileObject); + + return Status; +} + +typedef struct _WORK_QUEUE_WITH_CONTEXT +{ + WORK_QUEUE_ITEM WorkItem; + PVOID ToUnmap; + LARGE_INTEGER FileOffset; + LARGE_INTEGER MapSize; + PMM_CACHE_SECTION_SEGMENT ToDeref; + PACQUIRE_FOR_LAZY_WRITE AcquireForLazyWrite; + PRELEASE_FROM_LAZY_WRITE ReleaseFromLazyWrite; + PVOID LazyContext; + BOOLEAN Dirty; +} WORK_QUEUE_WITH_CONTEXT, *PWORK_QUEUE_WITH_CONTEXT; + +VOID +CcpUnmapCache(PVOID Context) +{ + PWORK_QUEUE_WITH_CONTEXT WorkItem = (PWORK_QUEUE_WITH_CONTEXT)Context; + DPRINT("Unmapping (finally) %x\n", WorkItem->ToUnmap); + WorkItem->AcquireForLazyWrite(WorkItem->LazyContext, TRUE); + MiFlushMappedSection(WorkItem->ToUnmap, &WorkItem->FileOffset, &WorkItem->MapSize, WorkItem->Dirty); + WorkItem->ReleaseFromLazyWrite(WorkItem->LazyContext); + MmUnmapCacheViewInSystemSpace(WorkItem->ToUnmap); + MmFinalizeSegment(WorkItem->ToDeref); + ExFreePool(WorkItem); + DPRINT("Done\n"); +} + +/* Must have acquired the mutex */ +VOID CcpDereferenceCache(ULONG Start, BOOLEAN Immediate) +{ + PVOID ToUnmap; + PNOCC_BCB Bcb; + BOOLEAN Dirty; + LARGE_INTEGER MappedSize; + LARGE_INTEGER BaseOffset; + PWORK_QUEUE_WITH_CONTEXT WorkItem; + + DPRINT("CcpDereferenceCache(#%x)\n", Start); + + Bcb = &CcCacheSections[Start]; + + Dirty = Bcb->Dirty; + ToUnmap = Bcb->BaseAddress; + BaseOffset = Bcb->FileOffset; + MappedSize = Bcb->Map->FileSizes.ValidDataLength; + + DPRINT("Dereference #%x (count %d)\n", Start, Bcb->RefCount); + ASSERT(Bcb->SectionObject); + ASSERT(Bcb->RefCount == 1); + + DPRINT("Firing work item for %x\n", Bcb->BaseAddress); + + if (Immediate) + { + PMM_CACHE_SECTION_SEGMENT ToDeref = Bcb->SectionObject; + BOOLEAN Dirty = Bcb->Dirty; + + Bcb->Map = NULL; + Bcb->SectionObject = NULL; + Bcb->BaseAddress = NULL; + Bcb->FileOffset.QuadPart = 0; + Bcb->Length = 0; + Bcb->RefCount = 0; + Bcb->Dirty = FALSE; + RemoveEntryList(&Bcb->ThisFileList); + + CcpUnlock(); + MiFlushMappedSection(ToUnmap, &BaseOffset, &MappedSize, Dirty); + MmUnmapCacheViewInSystemSpace(ToUnmap); + MmFinalizeSegment(ToDeref); + CcpLock(); + } + else + { + WorkItem = ExAllocatePool(NonPagedPool, sizeof(*WorkItem)); + if (!WorkItem) KeBugCheck(0); + WorkItem->ToUnmap = Bcb->BaseAddress; + WorkItem->FileOffset = Bcb->FileOffset; + WorkItem->Dirty = Bcb->Dirty; + WorkItem->MapSize = MappedSize; + WorkItem->ToDeref = Bcb->SectionObject; + WorkItem->AcquireForLazyWrite = Bcb->Map->Callbacks.AcquireForLazyWrite; + WorkItem->ReleaseFromLazyWrite = Bcb->Map->Callbacks.ReleaseFromLazyWrite; + WorkItem->LazyContext = Bcb->Map->LazyContext; + + ExInitializeWorkItem(((PWORK_QUEUE_ITEM)WorkItem), (PWORKER_THREAD_ROUTINE)CcpUnmapCache, WorkItem); + + Bcb->Map = NULL; + Bcb->SectionObject = NULL; + Bcb->BaseAddress = NULL; + Bcb->FileOffset.QuadPart = 0; + Bcb->Length = 0; + Bcb->RefCount = 0; + Bcb->Dirty = FALSE; + RemoveEntryList(&Bcb->ThisFileList); + + CcpUnlock(); + ExQueueWorkItem((PWORK_QUEUE_ITEM)WorkItem, DelayedWorkQueue); + CcpLock(); + } + DPRINT("Done\n"); +} + +/* Needs mutex */ +ULONG CcpAllocateCacheSections +(PFILE_OBJECT FileObject, + PMM_CACHE_SECTION_SEGMENT SectionObject) +{ + ULONG i = INVALID_CACHE; + PNOCC_CACHE_MAP Map; + PNOCC_BCB Bcb; + + DPRINT("AllocateCacheSections: FileObject %x\n", FileObject); + + if (!FileObject->SectionObjectPointer) + return INVALID_CACHE; + + Map = (PNOCC_CACHE_MAP)FileObject->SectionObjectPointer->SharedCacheMap; + + if (!Map) + return INVALID_CACHE; + + DPRINT("Allocating Cache Section\n"); + + i = RtlFindClearBitsAndSet(CcCacheBitmap, 1, CcCacheClockHand); + CcCacheClockHand = (i + 1) % CACHE_NUM_SECTIONS; + + if (i != INVALID_CACHE) + { + DPRINT("Setting up Bcb #%x\n", i); + + Bcb = &CcCacheSections[i]; + + ASSERT(Bcb->RefCount < 2); + + if (Bcb->RefCount > 0) + { + CcpDereferenceCache(i, FALSE); + } + + ASSERT(!Bcb->RefCount); + Bcb->RefCount = 1; + + DPRINT("Bcb #%x RefCount %d\n", Bcb - CcCacheSections, Bcb->RefCount); + + if (!RtlTestBit(CcCacheBitmap, i)) + { + DPRINT("Somebody stoeled BCB #%x\n", i); + } + ASSERT(RtlTestBit(CcCacheBitmap, i)); + + DPRINT("Allocated #%x\n", i); + ASSERT(CcCacheSections[i].RefCount); + } + else + { + DPRINT("Failed to allocate cache segment\n"); + } + return i; +} + +/* Must have acquired the mutex */ +VOID CcpReferenceCache(ULONG Start) +{ + PNOCC_BCB Bcb; + Bcb = &CcCacheSections[Start]; + ASSERT(Bcb->SectionObject); + Bcb->RefCount++; + RtlSetBit(CcCacheBitmap, Start); + +} + +VOID CcpMarkForExclusive(ULONG Start) +{ + PNOCC_BCB Bcb; + Bcb = &CcCacheSections[Start]; + Bcb->ExclusiveWaiter++; +} + +/* Must not have the mutex */ +VOID CcpReferenceCacheExclusive(ULONG Start) +{ + PNOCC_BCB Bcb = &CcCacheSections[Start]; + + KeWaitForSingleObject(&Bcb->ExclusiveWait, Executive, KernelMode, FALSE, NULL); + CcpLock(); + ASSERT(Bcb->ExclusiveWaiter); + ASSERT(Bcb->SectionObject); + Bcb->Exclusive = TRUE; + Bcb->ExclusiveWaiter--; + RtlSetBit(CcCacheBitmap, Start); + CcpUnlock(); +} + +/* Find a map that encompasses the target range */ +/* Must have the mutex */ +ULONG CcpFindMatchingMap(PLIST_ENTRY Head, PLARGE_INTEGER FileOffset, ULONG Length) +{ + PLIST_ENTRY Entry; + //DPRINT("Find Matching Map: (%x) %x:%x\n", FileOffset->LowPart, Length); + for (Entry = Head->Flink; Entry != Head; Entry = Entry->Flink) + { + //DPRINT("Link @%x\n", Entry); + PNOCC_BCB Bcb = CONTAINING_RECORD(Entry, NOCC_BCB, ThisFileList); + //DPRINT("Selected BCB %x #%x\n", Bcb, Bcb - CcCacheSections); + //DPRINT("This File: %x:%x\n", Bcb->FileOffset.LowPart, Bcb->Length); + if (FileOffset->QuadPart >= Bcb->FileOffset.QuadPart && + FileOffset->QuadPart < Bcb->FileOffset.QuadPart + CACHE_STRIPE) + { + //DPRINT("Found match at #%x\n", Bcb - CcCacheSections); + return Bcb - CcCacheSections; + } + } + + //DPRINT("This region isn't mapped\n"); + + return INVALID_CACHE; +} + +BOOLEAN +NTAPI +CcpMapData +(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG Flags, + OUT PVOID *BcbResult, + OUT PVOID *Buffer) +{ + BOOLEAN Success = FALSE, FaultIn = FALSE; + /* Note: windows 2000 drivers treat this as a bool */ + //BOOLEAN Wait = (Flags & MAP_WAIT) || (Flags == TRUE); + LARGE_INTEGER Target, EndInterval; + ULONG BcbHead; + PNOCC_BCB Bcb = NULL; + PMM_CACHE_SECTION_SEGMENT SectionObject = NULL; + NTSTATUS Status; + PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)FileObject->SectionObjectPointer->SharedCacheMap; + + if (!Map) + { + DPRINT1("File object was not mapped\n"); + return FALSE; + } + + DPRINT("CcMapData(F->%x,%08x%08x:%d)\n", FileObject, FileOffset->HighPart, FileOffset->LowPart, Length); + + ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); + + Target.HighPart = FileOffset->HighPart; + Target.LowPart = CACHE_ROUND_DOWN(FileOffset->LowPart); + + CcpLock(); + + /* Find out if any range is a superset of what we want */ + /* Find an accomodating section */ + BcbHead = CcpFindMatchingMap(&Map->AssociatedBcb, FileOffset, Length); + + if (BcbHead != INVALID_CACHE) + { + Bcb = &CcCacheSections[BcbHead]; + Success = TRUE; + *BcbResult = Bcb; + *Buffer = ((PCHAR)Bcb->BaseAddress) + (int)(FileOffset->QuadPart - Bcb->FileOffset.QuadPart); + DPRINT + ("Bcb #%x Buffer maps (%08x%08x) At %x Length %x (Getting %x:%x) %wZ\n", + Bcb - CcCacheSections, + Bcb->FileOffset.HighPart, + Bcb->FileOffset.LowPart, + Bcb->BaseAddress, + Bcb->Length, + *Buffer, + Length, + &FileObject->FileName); + DPRINT("w1n\n"); + goto cleanup; + } + + ULONG SectionSize; + + DPRINT("File size %08x%08x\n", Map->FileSizes.ValidDataLength.HighPart, Map->FileSizes.ValidDataLength.LowPart); + + if (Map->FileSizes.ValidDataLength.QuadPart) + { + SectionSize = min(CACHE_STRIPE, Map->FileSizes.ValidDataLength.QuadPart - Target.QuadPart); + } + else + { + SectionSize = CACHE_STRIPE; + } + + DPRINT("Allocating a cache stripe at %x:%d\n", + Target.LowPart, SectionSize); + //ASSERT(SectionSize <= CACHE_STRIPE); + + CcpUnlock(); + Status = CcpAllocateSection + (FileObject, + SectionSize, +#ifdef PIN_WRITE_ONLY + PAGE_READONLY, +#else + PAGE_READWRITE, +#endif + &SectionObject); + CcpLock(); + + if (!NT_SUCCESS(Status)) + { + *BcbResult = NULL; + *Buffer = NULL; + DPRINT1("End %08x\n", Status); + goto cleanup; + } + +retry: + /* Returns a reference */ + DPRINT("Allocating cache sections: %wZ\n", &FileObject->FileName); + BcbHead = CcpAllocateCacheSections(FileObject, SectionObject); + if (BcbHead == INVALID_CACHE) + { + ULONG i; + DbgPrint("Cache Map:"); + for (i = 0; i < CACHE_NUM_SECTIONS; i++) + { + if (!(i % 64)) DbgPrint("\n"); + DbgPrint("%c", CcCacheSections[i].RefCount + (RtlTestBit(CcCacheBitmap, i) ? '@' : '`')); + } + DbgPrint("\n"); + KeWaitForSingleObject(&CcDeleteEvent, Executive, KernelMode, FALSE, NULL); + goto retry; + } + + DPRINT("BcbHead #%x (final)\n", BcbHead); + + if (BcbHead == INVALID_CACHE) + { + *BcbResult = NULL; + *Buffer = NULL; + DPRINT1("End\n"); + goto cleanup; + } + + DPRINT("Selected BCB #%x\n", BcbHead); + ULONG ViewSize = CACHE_STRIPE; + + Bcb = &CcCacheSections[BcbHead]; + Status = MmMapCacheViewInSystemSpaceAtOffset + (SectionObject, + &Bcb->BaseAddress, + &Target, + &ViewSize); + + if (!NT_SUCCESS(Status)) + { + *BcbResult = NULL; + *Buffer = NULL; + MmFinalizeSegment(SectionObject); + RemoveEntryList(&Bcb->ThisFileList); + RtlZeroMemory(Bcb, sizeof(*Bcb)); + RtlClearBit(CcCacheBitmap, BcbHead); + DPRINT1("Failed to map\n"); + goto cleanup; + } + + Success = TRUE; + //DPRINT("w1n\n"); + + Bcb->Length = MIN(Map->FileSizes.ValidDataLength.QuadPart - Target.QuadPart, CACHE_STRIPE); + Bcb->SectionObject = SectionObject; + Bcb->Map = Map; + Bcb->FileOffset = Target; + InsertTailList(&Map->AssociatedBcb, &Bcb->ThisFileList); + + *BcbResult = &CcCacheSections[BcbHead]; + *Buffer = ((PCHAR)Bcb->BaseAddress) + (int)(FileOffset->QuadPart - Bcb->FileOffset.QuadPart); + FaultIn = TRUE; + + DPRINT + ("Bcb #%x Buffer maps (%08x%08x) At %x Length %x (Getting %x:%x) %wZ\n", + Bcb - CcCacheSections, + Bcb->FileOffset.HighPart, + Bcb->FileOffset.LowPart, + Bcb->BaseAddress, + Bcb->Length, + *Buffer, + Length, + &FileObject->FileName); + + EndInterval.QuadPart = Bcb->FileOffset.QuadPart + Bcb->Length - 1; + ASSERT((EndInterval.QuadPart & ~(CACHE_STRIPE - 1)) == (Bcb->FileOffset.QuadPart & ~(CACHE_STRIPE - 1))); + + //DPRINT("TERM!\n"); + +cleanup: + CcpUnlock(); + if (Success) + { + if (FaultIn) + { + // Fault in the pages. This forces reads to happen now. + ULONG i; + CHAR Dummy; + PCHAR FaultIn = Bcb->BaseAddress; + DPRINT1 + ("Faulting in pages at this point: file %wZ %08x%08x:%x\n", + &FileObject->FileName, + Bcb->FileOffset.HighPart, + Bcb->FileOffset.LowPart, + Bcb->Length); + for (i = 0; i < Bcb->Length; i++) + { + Dummy = FaultIn[i]; + } + } + ASSERT(Bcb >= CcCacheSections && Bcb < (CcCacheSections + CACHE_NUM_SECTIONS)); + } + else + { + ASSERT(FALSE); + } + + return Success; +} + +BOOLEAN +NTAPI +CcMapData +(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG Flags, + OUT PVOID *BcbResult, + OUT PVOID *Buffer) +{ + BOOLEAN Result; + + Result = CcpMapData + (FileObject, + FileOffset, + Length, + Flags, + BcbResult, + Buffer); + + if (Result) + { + PNOCC_BCB Bcb = (PNOCC_BCB)*BcbResult; + ASSERT(Bcb >= CcCacheSections && Bcb < CcCacheSections + CACHE_NUM_SECTIONS); + ASSERT(Bcb->BaseAddress); + CcpLock(); + CcpReferenceCache(Bcb - CcCacheSections); + CcpUnlock(); + } + + return Result; +} + +BOOLEAN +NTAPI +CcpPinMappedData(IN PNOCC_CACHE_MAP Map, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG Flags, + IN OUT PVOID *Bcb) +{ + BOOLEAN Exclusive = Flags & PIN_EXCLUSIVE; + ULONG BcbHead; + PNOCC_BCB TheBcb; + + CcpLock(); + + ASSERT(Map->AssociatedBcb.Flink == &Map->AssociatedBcb || (CONTAINING_RECORD(Map->AssociatedBcb.Flink, NOCC_BCB, ThisFileList) >= CcCacheSections && CONTAINING_RECORD(Map->AssociatedBcb.Flink, NOCC_BCB, ThisFileList) < CcCacheSections + CACHE_NUM_SECTIONS)); + BcbHead = CcpFindMatchingMap(&Map->AssociatedBcb, FileOffset, Length); + if (BcbHead == INVALID_CACHE) + { + CcpUnlock(); + return FALSE; + } + + TheBcb = &CcCacheSections[BcbHead]; + + if (Exclusive) + { + DPRINT("Requesting #%x Exclusive\n", BcbHead); + CcpMarkForExclusive(BcbHead); + } + else + { + DPRINT("Reference #%x\n", BcbHead); + CcpReferenceCache(BcbHead); + } + + if (Exclusive) + CcpReferenceCacheExclusive(BcbHead); + + CcpUnlock(); + + *Bcb = TheBcb; + return TRUE; +} + +BOOLEAN +NTAPI +CcPinMappedData(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG Flags, + IN OUT PVOID *Bcb) +{ + PVOID Buffer; + PNOCC_CACHE_MAP Map = (PNOCC_CACHE_MAP)FileObject->SectionObjectPointer->SharedCacheMap; + + if (!Map) + { + DPRINT1("Not cached\n"); + return FALSE; + } + + if (CcpMapData(FileObject, FileOffset, Length, Flags, Bcb, &Buffer)) + { + return CcpPinMappedData(Map, FileOffset, Length, Flags, Bcb); + } + else + { + DPRINT1("could not map\n"); + return FALSE; + } +} + +BOOLEAN +NTAPI +CcPinRead(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG Flags, + OUT PVOID *Bcb, + OUT PVOID *Buffer) +{ + PNOCC_BCB RealBcb; + BOOLEAN Result; + + Result = CcPinMappedData + (FileObject, + FileOffset, + Length, + Flags, + Bcb); + + if (Result) + { + CcpLock(); + RealBcb = *Bcb; + *Buffer = ((PCHAR)RealBcb->BaseAddress) + (int)(FileOffset->QuadPart - RealBcb->FileOffset.QuadPart); + CcpUnlock(); + } + + return Result; +} + +BOOLEAN +NTAPI +CcPreparePinWrite(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Zero, + IN ULONG Flags, + OUT PVOID *Bcb, + OUT PVOID *Buffer) +{ + BOOLEAN Result; + PNOCC_BCB RealBcb; +#ifdef PIN_WRITE_ONLY + PVOID BaseAddress; + SIZE_T NumberOfBytes; + ULONG OldProtect; +#endif + + DPRINT1("CcPreparePinWrite(%x:%x)\n", Buffer, Length); + + Result = CcPinRead + (FileObject, + FileOffset, + Length, + Flags, + Bcb, + Buffer); + + if (Result) + { + CcpLock(); + RealBcb = *Bcb; + +#ifdef PIN_WRITE_ONLY + BaseAddress = RealBcb->BaseAddress; + NumberOfBytes = RealBcb->Length; + + MiProtectVirtualMemory + (NULL, + &BaseAddress, + &NumberOfBytes, + PAGE_READWRITE, + &OldProtect); +#endif + + CcpUnlock(); + RealBcb->Dirty = TRUE; + + if (Zero) + { + DPRINT + ("Zero fill #%x %08x%08x:%x Buffer %x %wZ\n", + RealBcb - CcCacheSections, + FileOffset->u.HighPart, + FileOffset->u.LowPart, + Length, + *Buffer, + &FileObject->FileName); + + DPRINT1("RtlZeroMemory(%x,%x)\n", *Buffer, Length); + RtlZeroMemory(*Buffer, Length); + } + } + + return Result; +} + +VOID +NTAPI +CcpUnpinData(IN PNOCC_BCB RealBcb) +{ + if (RealBcb->RefCount <= 2) + { + RealBcb->Exclusive = FALSE; + if (RealBcb->ExclusiveWaiter) + { + DPRINT("Triggering exclusive waiter\n"); + KeSetEvent(&RealBcb->ExclusiveWait, IO_NO_INCREMENT, FALSE); + return; + } + } + if (RealBcb->RefCount > 1) + { + DPRINT("Removing one reference #%x\n", RealBcb - CcCacheSections); + RealBcb->RefCount--; + KeSetEvent(&CcDeleteEvent, IO_DISK_INCREMENT, FALSE); + } + if (RealBcb->RefCount == 1) + { + DPRINT("Clearing allocation bit #%x\n", RealBcb - CcCacheSections); + RtlClearBit(CcCacheBitmap, RealBcb - CcCacheSections); + +#ifdef PIN_WRITE_ONLY + PVOID BaseAddress = RealBcb->BaseAddress; + SIZE_T NumberOfBytes = RealBcb->Length; + ULONG OldProtect; + + MiProtectVirtualMemory + (NULL, + &BaseAddress, + &NumberOfBytes, + PAGE_READONLY, + &OldProtect); +#endif + } +} + +VOID +NTAPI +CcUnpinData(IN PVOID Bcb) +{ + PNOCC_BCB RealBcb = (PNOCC_BCB)Bcb; + ULONG Selected = RealBcb - CcCacheSections; + + ASSERT(RealBcb >= CcCacheSections && RealBcb - CcCacheSections < CACHE_NUM_SECTIONS); + DPRINT("CcUnpinData Bcb #%x (RefCount %d)\n", Selected, RealBcb->RefCount); + + CcpLock(); + CcpUnpinData(RealBcb); + CcpUnlock(); +} + +VOID +NTAPI +CcSetBcbOwnerPointer(IN PVOID Bcb, + IN PVOID OwnerPointer) +{ + PNOCC_BCB RealBcb = (PNOCC_BCB)Bcb; + CcpLock(); + CcpReferenceCache(RealBcb - CcCacheSections); + RealBcb->OwnerPointer = OwnerPointer; + CcpUnlock(); +} + +VOID +NTAPI +CcUnpinDataForThread(IN PVOID Bcb, + IN ERESOURCE_THREAD ResourceThreadId) +{ + CcUnpinData(Bcb); +} + +/* EOF */ diff --git a/ntoskrnl/cache/section/data.c b/ntoskrnl/cache/section/data.c new file mode 100644 index 00000000000..4e2d81bcc32 --- /dev/null +++ b/ntoskrnl/cache/section/data.c @@ -0,0 +1,713 @@ +/* + * Copyright (C) 1998-2005 ReactOS Team (and the authors from the programmers section) + * + * 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. + * + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/section.c + * PURPOSE: Implements section objects + * + * PROGRAMMERS: Rex Jolliff + * David Welch + * Eric Kohl + * Emanuele Aliberti + * Eugene Ingerman + * Casper Hornstrup + * KJK::Hyperion + * Guido de Jong + * Ge van Geldorp + * Royce Mitchell III + * Filip Navara + * Aleksey Bragin + * Jason Filby + * Thomas Weidenmueller + * Gunnar Andre' Dalsnes + * Mike Nordell + * Alex Ionescu + * Gregor Anich + * Steven Edwards + * Herve Poussineau + */ + +/* INCLUDES *****************************************************************/ + +#include +#include "newmm.h" +#include "../newcc.h" +#define NDEBUG +#include + +#define DPRINTC DPRINT + +extern KEVENT MpwThreadEvent; +extern KSPIN_LOCK MiSectionPageTableLock; + +/* GLOBALS *******************************************************************/ + +ULONG_PTR MmSubsectionBase; +BOOLEAN MmAllocationFragment; + +NTSTATUS +NTAPI +MiSimpleRead +(PFILE_OBJECT FileObject, + PLARGE_INTEGER FileOffset, + PVOID Buffer, + ULONG Length, + PIO_STATUS_BLOCK ReadStatus); + +static const INFORMATION_CLASS_INFO ExSectionInfoClass[] = +{ + ICI_SQ_SAME( sizeof(SECTION_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SectionBasicInformation */ + ICI_SQ_SAME( sizeof(SECTION_IMAGE_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SectionImageInformation */ +}; + +/* FUNCTIONS *****************************************************************/ + +/* Note: Mmsp prefix denotes "Memory Manager Section Private". */ + +VOID +NTAPI +_MmLockCacheSectionSegment(PMM_CACHE_SECTION_SEGMENT Segment, const char *file, int line) +{ + DPRINT("MmLockSectionSegment(%p,%s:%d)\n", Segment, file, line); + ExAcquireFastMutex(&Segment->Lock); +} + +VOID +NTAPI +_MmUnlockCacheSectionSegment(PMM_CACHE_SECTION_SEGMENT Segment, const char *file, int line) +{ + ExReleaseFastMutex(&Segment->Lock); + DPRINT("MmUnlockSectionSegment(%p,%s:%d)\n", Segment, file, line); +} + +NTSTATUS +NTAPI +MiZeroFillSection +(PVOID Address, + PLARGE_INTEGER FileOffsetPtr, + ULONG Length) +{ + PFN_NUMBER Page; + PMMSUPPORT AddressSpace; + PMEMORY_AREA MemoryArea; + PMM_CACHE_SECTION_SEGMENT Segment; + LARGE_INTEGER FileOffset = *FileOffsetPtr, End, FirstMapped; + DPRINT("MiZeroFillSection(Address %x,Offset %x,Length %x)\n", Address, FileOffset.LowPart, Length); + AddressSpace = MmGetKernelAddressSpace(); + MmLockAddressSpace(AddressSpace); + MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address); + MmUnlockAddressSpace(AddressSpace); + if (!MemoryArea || MemoryArea->Type != MEMORY_AREA_SECTION_VIEW) + { + return STATUS_NOT_MAPPED_DATA; + } + + Segment = MemoryArea->Data.CacheData.Segment; + End.QuadPart = FileOffset.QuadPart + Length; + End.LowPart = PAGE_ROUND_DOWN(End.LowPart); + FileOffset.LowPart = PAGE_ROUND_UP(FileOffset.LowPart); + FirstMapped.QuadPart = MemoryArea->Data.CacheData.ViewOffset.QuadPart; + DPRINT + ("Pulling zero pages for %08x%08x-%08x%08x\n", + FileOffset.u.HighPart, FileOffset.u.LowPart, + End.u.HighPart, End.u.LowPart); + while (FileOffset.QuadPart < End.QuadPart) + { + PVOID Address; + ULONG Entry; + + if (!NT_SUCCESS(MmRequestPageMemoryConsumer(MC_CACHE, TRUE, &Page))) + break; + + MmLockAddressSpace(AddressSpace); + MmLockCacheSectionSegment(Segment); + + Entry = MiGetPageEntryCacheSectionSegment(Segment, &FileOffset); + if (Entry == 0) + { + MiSetPageEntryCacheSectionSegment(Segment, &FileOffset, MAKE_PFN_SSE(Page)); + Address = ((PCHAR)MemoryArea->StartingAddress) + FileOffset.QuadPart - FirstMapped.QuadPart; + MmReferencePage(Page); + MmCreateVirtualMapping(NULL, Address, PAGE_READWRITE, &Page, 1); + MmInsertRmap(Page, NULL, Address); + } + else + MmReleasePageMemoryConsumer(MC_CACHE, Page); + + MmUnlockCacheSectionSegment(Segment); + MmUnlockAddressSpace(AddressSpace); + + FileOffset.QuadPart += PAGE_SIZE; + } + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +_MiFlushMappedSection +(PVOID BaseAddress, + PLARGE_INTEGER BaseOffset, + PLARGE_INTEGER FileSize, + BOOLEAN WriteData, + const char *File, + int Line) +{ + NTSTATUS Status = STATUS_SUCCESS; + ULONG_PTR PageAddress; + PMMSUPPORT AddressSpace = MmGetKernelAddressSpace(); + PMEMORY_AREA MemoryArea; + PMM_CACHE_SECTION_SEGMENT Segment; + ULONG_PTR BeginningAddress, EndingAddress; + LARGE_INTEGER ViewOffset; + LARGE_INTEGER FileOffset; + PFN_NUMBER Page; + PPFN_NUMBER Pages; + + DPRINT("MiFlushMappedSection(%x,%08x,%x,%d,%s:%d)\n", BaseAddress, BaseOffset->LowPart, FileSize, WriteData, File, Line); + + MmLockAddressSpace(AddressSpace); + MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress); + if (!MemoryArea || MemoryArea->Type != MEMORY_AREA_CACHE) + { + MmUnlockAddressSpace(AddressSpace); + DPRINT("STATUS_NOT_MAPPED_DATA\n"); + return STATUS_NOT_MAPPED_DATA; + } + BeginningAddress = PAGE_ROUND_DOWN((ULONG_PTR)MemoryArea->StartingAddress); + EndingAddress = PAGE_ROUND_UP((ULONG_PTR)MemoryArea->EndingAddress); + Segment = MemoryArea->Data.CacheData.Segment; + ViewOffset.QuadPart = MemoryArea->Data.CacheData.ViewOffset.QuadPart; + + ASSERT(ViewOffset.QuadPart == BaseOffset->QuadPart); + + MmLockCacheSectionSegment(Segment); + + Pages = ExAllocatePool + (NonPagedPool, + sizeof(PFN_NUMBER) * + ((EndingAddress - BeginningAddress) >> PAGE_SHIFT)); + + if (!Pages) + { + ASSERT(FALSE); + } + + DPRINT("Getting pages in range %08x-%08x\n", BeginningAddress, EndingAddress); + + for (PageAddress = BeginningAddress; + PageAddress < EndingAddress; + PageAddress += PAGE_SIZE) + { + ULONG Entry; + FileOffset.QuadPart = ViewOffset.QuadPart + PageAddress - BeginningAddress; + Entry = + MiGetPageEntryCacheSectionSegment + (MemoryArea->Data.CacheData.Segment, + &FileOffset); + Page = PFN_FROM_SSE(Entry); + if (Entry != 0 && !IS_SWAP_FROM_SSE(Entry) && + (MmIsDirtyPageRmap(Page) || IS_DIRTY_SSE(Entry)) && + FileOffset.QuadPart < FileSize->QuadPart) + { + Pages[(PageAddress - BeginningAddress) >> PAGE_SHIFT] = Page; + } + else + Pages[(PageAddress - BeginningAddress) >> PAGE_SHIFT] = 0; + } + + MmUnlockCacheSectionSegment(Segment); + MmUnlockAddressSpace(AddressSpace); + + for (PageAddress = BeginningAddress; + PageAddress < EndingAddress; + PageAddress += PAGE_SIZE) + { + FileOffset.QuadPart = ViewOffset.QuadPart + PageAddress - BeginningAddress; + Page = Pages[(PageAddress - BeginningAddress) >> PAGE_SHIFT]; + if (Page) + { + ULONG Entry; + if (WriteData) { + DPRINT("MiWriteBackPage(%wZ,addr %x,%08x%08x)\n", &Segment->FileObject->FileName, PageAddress, FileOffset.u.HighPart, FileOffset.u.LowPart); + Status = MiWriteBackPage(Segment->FileObject, &FileOffset, PAGE_SIZE, Page); + } else + Status = STATUS_SUCCESS; + + if (NT_SUCCESS(Status)) { + MmLockAddressSpace(AddressSpace); + MmSetCleanAllRmaps(Page); + MmLockCacheSectionSegment(Segment); + Entry = MiGetPageEntryCacheSectionSegment(Segment, &FileOffset); + if (Entry && !IS_SWAP_FROM_SSE(Entry) && PFN_FROM_SSE(Entry) == Page) + MiSetPageEntryCacheSectionSegment(Segment, &FileOffset, CLEAN_SSE(Entry)); + MmUnlockCacheSectionSegment(Segment); + MmUnlockAddressSpace(AddressSpace); + } else { + DPRINT + ("Writeback from section flush %08x%08x (%x) %x@%x (%08x%08x:%wZ) failed %x\n", + FileOffset.u.HighPart, FileOffset.u.LowPart, + (ULONG)(FileSize->QuadPart - FileOffset.QuadPart), + PageAddress, + Page, + FileSize->u.HighPart, + FileSize->u.LowPart, + &Segment->FileObject->FileName, + Status); + } + } + } + + ExFreePool(Pages); + + return Status; +} + +VOID +NTAPI +MmFinalizeSegment(PMM_CACHE_SECTION_SEGMENT Segment) +{ + KIRQL OldIrql = 0; + + MmLockCacheSectionSegment(Segment); + if (Segment->Flags & MM_DATAFILE_SEGMENT) { + KeAcquireSpinLock(&Segment->FileObject->IrpListLock, &OldIrql); + if (Segment->Flags & MM_SEGMENT_FINALIZE) { + KeReleaseSpinLock(&Segment->FileObject->IrpListLock, OldIrql); + MmUnlockCacheSectionSegment(Segment); + return; + } else { + Segment->Flags |= MM_SEGMENT_FINALIZE; + } + } + DPRINTC("Finalizing segment %x\n", Segment); + if (Segment->Flags & MM_DATAFILE_SEGMENT) + { + //Segment->FileObject->SectionObjectPointer->DataSectionObject = NULL; + KeReleaseSpinLock(&Segment->FileObject->IrpListLock, OldIrql); + MiFreePageTablesSectionSegment(Segment, MiFreeSegmentPage); + MmUnlockCacheSectionSegment(Segment); + ObDereferenceObject(Segment->FileObject); + } else { + MiFreePageTablesSectionSegment(Segment, MiFreeSegmentPage); + MmUnlockCacheSectionSegment(Segment); + } + DPRINTC("Segment %x destroy\n", Segment); + ExFreePool(Segment); +} + +NTSTATUS +NTAPI +MmCreateCacheSection +(PMM_CACHE_SECTION_SEGMENT *SegmentObject, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + PLARGE_INTEGER UMaximumSize, + ULONG SectionPageProtection, + ULONG AllocationAttributes, + PFILE_OBJECT FileObject) +/* + * Create a section backed by a data file + */ +{ + NTSTATUS Status; + ULARGE_INTEGER MaximumSize; + PMM_CACHE_SECTION_SEGMENT Segment; + ULONG FileAccess; + IO_STATUS_BLOCK Iosb; + CC_FILE_SIZES FileSizes; + FILE_STANDARD_INFORMATION FileInfo; + + /* + * Check file access required + */ + if (SectionPageProtection & PAGE_READWRITE || + SectionPageProtection & PAGE_EXECUTE_READWRITE) + { + FileAccess = FILE_READ_DATA | FILE_WRITE_DATA; + } + else + { + FileAccess = FILE_READ_DATA; + } + + /* + * Reference the file handle + */ + ObReferenceObject(FileObject); + + DPRINT("Getting original file size\n"); + /* A hack: If we're cached, we can overcome deadlocking with the upper + * layer filesystem call by retriving the object sizes from the cache + * which is made to keep track. If I had to guess, they were figuring + * out a similar problem. + */ + if (!CcGetFileSizes(FileObject, &FileSizes)) + { + /* + * FIXME: This is propably not entirely correct. We can't look into + * the standard FCB header because it might not be initialized yet + * (as in case of the EXT2FS driver by Manoj Paul Joseph where the + * standard file information is filled on first request). + */ + Status = IoQueryFileInformation + (FileObject, + FileStandardInformation, + sizeof(FILE_STANDARD_INFORMATION), + &FileInfo, + &Iosb.Information); + + if (!NT_SUCCESS(Status)) + { + return Status; + } + + ASSERT(Status != STATUS_PENDING); + + FileSizes.ValidDataLength = FileInfo.EndOfFile; + FileSizes.FileSize = FileInfo.EndOfFile; + } + DPRINT("Got %08x\n", FileSizes.ValidDataLength.u.LowPart); + + /* + * FIXME: Revise this once a locking order for file size changes is + * decided + */ + if (UMaximumSize != NULL) + { + MaximumSize.QuadPart = UMaximumSize->QuadPart; + } + else + { + DPRINT("Got file size %08x%08x\n", FileSizes.FileSize.u.HighPart, FileSizes.FileSize.u.LowPart); + MaximumSize.QuadPart = FileSizes.FileSize.QuadPart; + } + + Segment = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_CACHE_SECTION_SEGMENT), + TAG_MM_SECTION_SEGMENT); + if (Segment == NULL) + { + return(STATUS_NO_MEMORY); + } + + ExInitializeFastMutex(&Segment->Lock); + + Segment->ReferenceCount = 1; + + /* + * Set the lock before assigning the segment to the file object + */ + ExAcquireFastMutex(&Segment->Lock); + + DPRINT("Filling out Segment info (No previous data section)\n"); + ObReferenceObject(FileObject); + Segment->FileObject = FileObject; + Segment->Protection = SectionPageProtection; + Segment->Flags = MM_DATAFILE_SEGMENT; + memset(&Segment->Image, 0, sizeof(Segment->Image)); + Segment->WriteCopy = FALSE; + if (AllocationAttributes & SEC_RESERVE) + { + Segment->Length.QuadPart = Segment->RawLength.QuadPart = 0; + } + else + { + Segment->RawLength = MaximumSize; + Segment->Length.QuadPart = PAGE_ROUND_UP(Segment->RawLength.QuadPart); + } + + MiInitializeSectionPageTable(Segment); + MmUnlockCacheSectionSegment(Segment); + + /* Extend file if section is longer */ + DPRINT("MaximumSize %08x%08x ValidDataLength %08x%08x\n", + MaximumSize.u.HighPart, MaximumSize.u.LowPart, + FileSizes.ValidDataLength.u.HighPart, FileSizes.ValidDataLength.u.LowPart); + if (MaximumSize.QuadPart > FileSizes.ValidDataLength.QuadPart) + { + DPRINT("Changing file size to %08x%08x, segment %x\n", MaximumSize.u.HighPart, MaximumSize.u.LowPart, Segment); + Status = IoSetInformation(FileObject, FileEndOfFileInformation, sizeof(LARGE_INTEGER), &MaximumSize); + DPRINT("Change: Status %x\n", Status); + if (!NT_SUCCESS(Status)) + { + DPRINT("Could not expand section\n"); + return Status; + } + } + + DPRINTC("Segment %x created (%x)\n", Segment, Segment->Flags); + + *SegmentObject = Segment; + + return(STATUS_SUCCESS); +} + +NTSTATUS +NTAPI +_MiMapViewOfSegment +(PMMSUPPORT AddressSpace, + PMM_CACHE_SECTION_SEGMENT Segment, + PVOID* BaseAddress, + SIZE_T ViewSize, + ULONG Protect, + PLARGE_INTEGER ViewOffset, + ULONG AllocationType, + const char *file, + int line) +{ + PMEMORY_AREA MArea; + NTSTATUS Status; + PHYSICAL_ADDRESS BoundaryAddressMultiple; + + BoundaryAddressMultiple.QuadPart = 0; + + Status = MmCreateMemoryArea + (AddressSpace, + MEMORY_AREA_CACHE, + BaseAddress, + ViewSize, + Protect, + &MArea, + FALSE, + AllocationType, + BoundaryAddressMultiple); + + if (!NT_SUCCESS(Status)) + { + DPRINT("Mapping between 0x%.8X and 0x%.8X failed (%X).\n", + (*BaseAddress), (char*)(*BaseAddress) + ViewSize, Status); + return(Status); + } + + DPRINTC("MiMapViewOfSegment %x %x %x %x %x %wZ %s:%d\n", MmGetAddressSpaceOwner(AddressSpace), *BaseAddress, Segment, ViewOffset ? ViewOffset->LowPart : 0, ViewSize, Segment->FileObject ? &Segment->FileObject->FileName : NULL, file, line); + + MArea->Data.CacheData.Segment = Segment; + if (ViewOffset) + MArea->Data.CacheData.ViewOffset = *ViewOffset; + else + MArea->Data.CacheData.ViewOffset.QuadPart = 0; + +#if 0 + MArea->NotPresent = MmNotPresentFaultPageFile; + MArea->AccessFault = MiCowSectionPage; + MArea->PageOut = MmPageOutPageFileView; +#endif + + DPRINTC + ("MiMapViewOfSegment(P %x, A %x, T %x)\n", + MmGetAddressSpaceOwner(AddressSpace), *BaseAddress, MArea->Type); + + return(STATUS_SUCCESS); +} + +VOID +NTAPI +MiFreeSegmentPage +(PMM_CACHE_SECTION_SEGMENT Segment, + PLARGE_INTEGER FileOffset) +{ + ULONG Entry; + PFILE_OBJECT FileObject = Segment->FileObject; + + Entry = MiGetPageEntryCacheSectionSegment(Segment, FileOffset); + DPRINTC("MiFreeSegmentPage(%x:%08x%08x -> Entry %x\n", + Segment, FileOffset->HighPart, FileOffset->LowPart, Entry); + + if (Entry && !IS_SWAP_FROM_SSE(Entry)) + { + // The segment is carrying a dirty page. + PFN_NUMBER OldPage = PFN_FROM_SSE(Entry); + if (IS_DIRTY_SSE(Entry) && FileObject) + { + DPRINT("MiWriteBackPage(%x,%wZ,%08x%08x)\n", Segment, &FileObject->FileName, FileOffset->u.HighPart, FileOffset->u.LowPart); + MiWriteBackPage(FileObject, FileOffset, PAGE_SIZE, OldPage); + } + DPRINTC("Free page %x (off %x from %x) (ref ct %d, ent %x, dirty? %s)\n", OldPage, FileOffset->LowPart, Segment, MmGetReferenceCountPage(OldPage), Entry, IS_DIRTY_SSE(Entry) ? "true" : "false"); + + MiSetPageEntryCacheSectionSegment(Segment, FileOffset, 0); + MmReleasePageMemoryConsumer(MC_CACHE, OldPage); + } + else if (IS_SWAP_FROM_SSE(Entry)) + { + DPRINT("Free swap\n"); + MmFreeSwapPage(SWAPENTRY_FROM_SSE(Entry)); + } + + DPRINT("Done\n"); +} + +VOID +MmFreeCacheSectionPage +(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, + PFN_NUMBER Page, SWAPENTRY SwapEntry, BOOLEAN Dirty) +{ + ULONG Entry; + PVOID *ContextData = Context; + PMMSUPPORT AddressSpace; + PEPROCESS Process; + PMM_CACHE_SECTION_SEGMENT Segment; + LARGE_INTEGER Offset; + + DPRINT("MmFreeSectionPage(%x,%x,%x,%x,%d)\n", MmGetAddressSpaceOwner(ContextData[0]), Address, Page, SwapEntry, Dirty); + + AddressSpace = ContextData[0]; + Process = MmGetAddressSpaceOwner(AddressSpace); + Address = (PVOID)PAGE_ROUND_DOWN(Address); + Segment = ContextData[1]; + Offset.QuadPart = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress + + MemoryArea->Data.CacheData.ViewOffset.QuadPart; + + Entry = MiGetPageEntryCacheSectionSegment(Segment, &Offset); + + if (Page) + { + DPRINT("Removing page %x:%x -> %x\n", Segment, Offset.LowPart, Entry); + MmSetSavedSwapEntryPage(Page, 0); + MmDeleteRmap(Page, Process, Address); + MmDeleteVirtualMapping(Process, Address, FALSE, NULL, NULL); + MmReleasePageMemoryConsumer(MC_CACHE, Page); + } + if (Page != 0 && PFN_FROM_SSE(Entry) == Page && Dirty) + { + DPRINT("Freeing section page %x:%x -> %x\n", Segment, Offset.LowPart, Entry); + MiSetPageEntryCacheSectionSegment(Segment, &Offset, DIRTY_SSE(Entry)); + } + else if (SwapEntry != 0) + { + MmFreeSwapPage(SwapEntry); + } +} + +NTSTATUS +NTAPI +MmUnmapViewOfCacheSegment +(PMMSUPPORT AddressSpace, + PVOID BaseAddress) +{ + PVOID Context[2]; + PMEMORY_AREA MemoryArea; + PMM_CACHE_SECTION_SEGMENT Segment; + + MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress); + if (MemoryArea == NULL) + { + ASSERT(MemoryArea); + return(STATUS_UNSUCCESSFUL); + } + + MemoryArea->DeleteInProgress = TRUE; + Segment = MemoryArea->Data.CacheData.Segment; + MemoryArea->Data.CacheData.Segment = NULL; + + MmLockCacheSectionSegment(Segment); + + Context[0] = AddressSpace; + Context[1] = Segment; + DPRINT("MmFreeMemoryArea(%x,%x)\n", MmGetAddressSpaceOwner(AddressSpace), MemoryArea->StartingAddress); + MmFreeMemoryArea(AddressSpace, MemoryArea, MmFreeCacheSectionPage, Context); + + MmUnlockCacheSectionSegment(Segment); + + DPRINTC("MiUnmapViewOfSegment %x %x %x\n", MmGetAddressSpaceOwner(AddressSpace), BaseAddress, Segment); + + return(STATUS_SUCCESS); +} + +NTSTATUS +NTAPI +MmExtendCacheSection +(PMM_CACHE_SECTION_SEGMENT Segment, + PLARGE_INTEGER NewSize, + BOOLEAN ExtendFile) +{ + LARGE_INTEGER OldSize; + DPRINT("Extend Segment %x\n", Segment); + + MmLockCacheSectionSegment(Segment); + OldSize.QuadPart = Segment->RawLength.QuadPart; + MmUnlockCacheSectionSegment(Segment); + + DPRINT("OldSize %08x%08x NewSize %08x%08x\n", + OldSize.u.HighPart, OldSize.u.LowPart, + NewSize->u.HighPart, NewSize->u.LowPart); + + if (ExtendFile && OldSize.QuadPart < NewSize->QuadPart) + { + NTSTATUS Status; + Status = IoSetInformation(Segment->FileObject, FileEndOfFileInformation, sizeof(LARGE_INTEGER), NewSize); + if (!NT_SUCCESS(Status)) return Status; + } + + MmLockCacheSectionSegment(Segment); + Segment->RawLength.QuadPart = NewSize->QuadPart; + Segment->Length.QuadPart = MAX(Segment->Length.QuadPart, PAGE_ROUND_UP(Segment->RawLength.LowPart)); + MmUnlockCacheSectionSegment(Segment); + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +MmMapCacheViewInSystemSpaceAtOffset +(IN PMM_CACHE_SECTION_SEGMENT Segment, + OUT PVOID *MappedBase, + PLARGE_INTEGER FileOffset, + IN OUT PULONG ViewSize) +{ + PMMSUPPORT AddressSpace; + NTSTATUS Status; + + DPRINT("MmMapViewInSystemSpaceAtOffset() called offset %08x%08x\n", FileOffset->HighPart, FileOffset->LowPart); + + AddressSpace = MmGetKernelAddressSpace(); + + MmLockAddressSpace(AddressSpace); + MmLockCacheSectionSegment(Segment); + + Status = MiMapViewOfSegment + (AddressSpace, + Segment, + MappedBase, + *ViewSize, + PAGE_READWRITE, + FileOffset, + 0); + + MmUnlockCacheSectionSegment(Segment); + MmUnlockAddressSpace(AddressSpace); + + return Status; +} + +/* + * @implemented + */ +NTSTATUS NTAPI +MmUnmapCacheViewInSystemSpace (IN PVOID MappedBase) +{ + PMMSUPPORT AddressSpace; + NTSTATUS Status; + + DPRINT("MmUnmapViewInSystemSpace() called\n"); + + AddressSpace = MmGetKernelAddressSpace(); + + Status = MmUnmapViewOfCacheSegment(AddressSpace, MappedBase); + + return Status; +} + +/* EOF */ diff --git a/ntoskrnl/cache/section/fault.c b/ntoskrnl/cache/section/fault.c new file mode 100644 index 00000000000..204c264b579 --- /dev/null +++ b/ntoskrnl/cache/section/fault.c @@ -0,0 +1,766 @@ +/* + * Copyright (C) 1998-2005 ReactOS Team (and the authors from the programmers section) + * + * 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. + * + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/section/fault.c + * PURPOSE: Consolidate fault handlers for sections + * + * PROGRAMMERS: Arty + * Rex Jolliff + * David Welch + * Eric Kohl + * Emanuele Aliberti + * Eugene Ingerman + * Casper Hornstrup + * KJK::Hyperion + * Guido de Jong + * Ge van Geldorp + * Royce Mitchell III + * Filip Navara + * Aleksey Bragin + * Jason Filby + * Thomas Weidenmueller + * Gunnar Andre' Dalsnes + * Mike Nordell + * Alex Ionescu + * Gregor Anich + * Steven Edwards + * Herve Poussineau + */ + +/* INCLUDES *****************************************************************/ + +#include +#include "newmm.h" +#define NDEBUG +#include + +#define DPRINTC DPRINT + +extern KEVENT MmWaitPageEvent; + +NTSTATUS +NTAPI +MmNotPresentFaultCachePage +(PMMSUPPORT AddressSpace, + MEMORY_AREA* MemoryArea, + PVOID Address, + BOOLEAN Locked, + PMM_REQUIRED_RESOURCES Required) +{ + NTSTATUS Status; + PVOID PAddress; + ULONG Consumer; + PMM_CACHE_SECTION_SEGMENT Segment; + LARGE_INTEGER FileOffset, TotalOffset; + ULONG Entry; + ULONG Attributes; + PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace); + + DPRINT("Not Present: %p %p (%p-%p)\n", AddressSpace, Address, MemoryArea->StartingAddress, MemoryArea->EndingAddress); + + /* + * There is a window between taking the page fault and locking the + * address space when another thread could load the page so we check + * that. + */ + if (MmIsPagePresent(Process, Address)) + { + DPRINT("Done\n"); + return(STATUS_SUCCESS); + } + + PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE); + TotalOffset.QuadPart = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress; + + Segment = MemoryArea->Data.CacheData.Segment; + + TotalOffset.QuadPart += MemoryArea->Data.CacheData.ViewOffset.QuadPart; + FileOffset = TotalOffset; + + //Consumer = (Segment->Flags & MM_DATAFILE_SEGMENT) ? MC_CACHE : MC_USER; + Consumer = MC_CACHE; + + if (Segment->FileObject) + { + DPRINT("FileName %wZ\n", &Segment->FileObject->FileName); + } + + DPRINT("Total Offset %08x%08x\n", TotalOffset.HighPart, TotalOffset.LowPart); + + /* + * Lock the segment + */ + MmLockCacheSectionSegment(Segment); + + /* + * Get the entry corresponding to the offset within the section + */ + Entry = MiGetPageEntryCacheSectionSegment(Segment, &TotalOffset); + + Attributes = PAGE_READONLY; + + if (Required->State && Required->Page[0]) + { + DPRINT("Have file and page, set page %x in section @ %x #\n", Required->Page[0], TotalOffset.LowPart); + + if (Required->SwapEntry) + MmSetSavedSwapEntryPage(Required->Page[0], Required->SwapEntry); + + if (Required->State & 2) + { + DPRINT("Set in section @ %x\n", TotalOffset.LowPart); + Status = MiSetPageEntryCacheSectionSegment + (Segment, &TotalOffset, Entry = MAKE_PFN_SSE(Required->Page[0])); + if (!NT_SUCCESS(Status)) + { + MmReleasePageMemoryConsumer(MC_CACHE, Required->Page[0]); + } + MmUnlockCacheSectionSegment(Segment); + MiSetPageEvent(Process, Address); + DPRINT("Status %x\n", Status); + return STATUS_MM_RESTART_OPERATION; + } + else + { + DPRINT("Set %x in address space @ %x\n", Required->Page[0], Address); + Status = MmCreateVirtualMapping(Process, Address, Attributes, Required->Page, 1); + if (NT_SUCCESS(Status)) + { + MmInsertRmap(Required->Page[0], Process, Address); + } + else + { + // Drop the reference for our address space ... + MmReleasePageMemoryConsumer(MC_CACHE, Required->Page[0]); + } + MmUnlockCacheSectionSegment(Segment); + DPRINTC("XXX Set Event %x\n", Status); + MiSetPageEvent(Process, Address); + DPRINT("Status %x\n", Status); + return Status; + } + } + else if (Entry) + { + PFN_NUMBER Page = PFN_FROM_SSE(Entry); + DPRINT("Take reference to page %x #\n", Page); + + MmReferencePage(Page); + + Status = MmCreateVirtualMapping(Process, Address, Attributes, &Page, 1); + if (NT_SUCCESS(Status)) + { + MmInsertRmap(Page, Process, Address); + } + DPRINT("XXX Set Event %x\n", Status); + MiSetPageEvent(Process, Address); + MmUnlockCacheSectionSegment(Segment); + DPRINT("Status %x\n", Status); + return Status; + } + else + { + DPRINT("Get page into section\n"); + /* + * If the entry is zero (and it can't change because we have + * locked the segment) then we need to load the page. + */ + //DPRINT1("Read from file %08x %wZ\n", FileOffset.LowPart, &Section->FileObject->FileName); + Required->State = 2; + Required->Context = Segment->FileObject; + Required->Consumer = Consumer; + Required->FileOffset = FileOffset; + Required->Amount = PAGE_SIZE; + Required->DoAcquisition = MiReadFilePage; + MiSetPageEntryCacheSectionSegment(Segment, &TotalOffset, MAKE_SWAP_SSE(MM_WAIT_ENTRY)); + MmUnlockCacheSectionSegment(Segment); + return STATUS_MORE_PROCESSING_REQUIRED; + } + ASSERT(FALSE); + return STATUS_ACCESS_VIOLATION; +} + +NTSTATUS +NTAPI +MiCopyPageToPage(PFN_NUMBER DestPage, PFN_NUMBER SrcPage) +{ + PEPROCESS Process; + KIRQL Irql, Irql2; + PVOID TempAddress, TempSource; + + Process = PsGetCurrentProcess(); + TempAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql); + if (TempAddress == NULL) + { + return(STATUS_NO_MEMORY); + } + TempSource = MiMapPageInHyperSpace(Process, SrcPage, &Irql2); + if (!TempSource) { + MiUnmapPageInHyperSpace(Process, TempAddress, Irql); + return(STATUS_NO_MEMORY); + } + + memcpy(TempAddress, TempSource, PAGE_SIZE); + + MiUnmapPageInHyperSpace(Process, TempSource, Irql2); + MiUnmapPageInHyperSpace(Process, TempAddress, Irql); + return(STATUS_SUCCESS); +} + +NTSTATUS +NTAPI +MiCowCacheSectionPage +(PMMSUPPORT AddressSpace, + PMEMORY_AREA MemoryArea, + PVOID Address, + BOOLEAN Locked, + PMM_REQUIRED_RESOURCES Required) +{ + PMM_CACHE_SECTION_SEGMENT Segment; + PFN_NUMBER NewPage, OldPage; + NTSTATUS Status; + PVOID PAddress; + LARGE_INTEGER Offset; + PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace); + + DPRINT("MmAccessFaultSectionView(%x, %x, %x, %x)\n", AddressSpace, MemoryArea, Address, Locked); + + Segment = MemoryArea->Data.CacheData.Segment; + + /* + * Lock the segment + */ + MmLockCacheSectionSegment(Segment); + + /* + * Find the offset of the page + */ + PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE); + Offset.QuadPart = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress + + MemoryArea->Data.CacheData.ViewOffset.QuadPart; + +#if 0 // XXX Cache sections are not CoW. For now, treat all access violations this way. + if ((!Segment->WriteCopy && + !MemoryArea->Data.CacheData.WriteCopyView) || + Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED) +#endif + { +#if 0 // XXX Cache sections don't have regions at present, which streamlines things + if (Region->Protect == PAGE_READWRITE || + Region->Protect == PAGE_EXECUTE_READWRITE) +#endif + { + DPRINTC("setting non-cow page %x %x:%x offset %x (%x) to writable\n", Segment, Process, PAddress, Offset.u.LowPart, MmGetPfnForProcess(Process, Address)); + if (Segment->FileObject) + { + DPRINTC("file %wZ\n", &Segment->FileObject->FileName); + } + ULONG Entry = MiGetPageEntryCacheSectionSegment(Segment, &Offset); + DPRINT("Entry %x\n", Entry); + if (Entry && + !IS_SWAP_FROM_SSE(Entry) && + PFN_FROM_SSE(Entry) == MmGetPfnForProcess(Process, Address)) { + MiSetPageEntryCacheSectionSegment(Segment, &Offset, DIRTY_SSE(Entry)); + } + MmSetPageProtect(Process, PAddress, PAGE_READWRITE); + MmUnlockCacheSectionSegment(Segment); + DPRINT("Done\n"); + return STATUS_SUCCESS; + } +#if 0 + else + { + DPRINT("Not supposed to be writable\n"); + MmUnlockCacheSectionSegment(Segment); + return STATUS_ACCESS_VIOLATION; + } +#endif + } + + if (!Required->Page[0]) + { + SWAPENTRY SwapEntry; + if (MmIsPageSwapEntry(Process, Address)) + { + MmGetPageFileMapping(Process, Address, &SwapEntry); + MmUnlockCacheSectionSegment(Segment); + if (SwapEntry == MM_WAIT_ENTRY) + return STATUS_SUCCESS + 1; // Wait ... somebody else is getting it right now + else + return STATUS_SUCCESS; // Nonwait swap entry ... handle elsewhere + } + Required->Page[1] = MmGetPfnForProcess(Process, Address); + Required->Consumer = MC_CACHE; + Required->Amount = 1; + Required->File = __FILE__; + Required->Line = __LINE__; + Required->DoAcquisition = MiGetOnePage; + MmCreatePageFileMapping(Process, Address, MM_WAIT_ENTRY); + MmUnlockCacheSectionSegment(Segment); + return STATUS_MORE_PROCESSING_REQUIRED; + } + + NewPage = Required->Page[0]; + OldPage = Required->Page[1]; + + DPRINT("Allocated page %x\n", NewPage); + + /* + * Unshare the old page. + */ + MmDeleteRmap(OldPage, Process, PAddress); + + /* + * Copy the old page + */ + DPRINT("Copying\n"); + MiCopyPageToPage(NewPage, OldPage); + + /* + * Set the PTE to point to the new page + */ + Status = MmCreateVirtualMapping + (Process, Address, PAGE_READWRITE, &NewPage, 1); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("MmCreateVirtualMapping failed, not out of memory\n"); + ASSERT(FALSE); + MmUnlockCacheSectionSegment(Segment); + return(Status); + } + + MmInsertRmap(NewPage, Process, PAddress); + MmReleasePageMemoryConsumer(MC_CACHE, OldPage); + MmUnlockCacheSectionSegment(Segment); + + DPRINT("Address 0x%.8X\n", Address); + return(STATUS_SUCCESS); +} + +KEVENT MmWaitPageEvent; + +typedef struct _WORK_QUEUE_WITH_CONTEXT +{ + WORK_QUEUE_ITEM WorkItem; + PMMSUPPORT AddressSpace; + PMEMORY_AREA MemoryArea; + PMM_REQUIRED_RESOURCES Required; + NTSTATUS Status; + KEVENT Wait; + AcquireResource DoAcquisition; +} WORK_QUEUE_WITH_CONTEXT, *PWORK_QUEUE_WITH_CONTEXT; + +VOID +NTAPI +MmpFaultWorker +(PWORK_QUEUE_WITH_CONTEXT WorkItem) +{ + DPRINT("Calling work\n"); + WorkItem->Status = + WorkItem->Required->DoAcquisition + (WorkItem->AddressSpace, + WorkItem->MemoryArea, + WorkItem->Required); + DPRINT("Status %x\n", WorkItem->Status); + KeSetEvent(&WorkItem->Wait, IO_NO_INCREMENT, FALSE); +} + +NTSTATUS +NTAPI +MmpSectionAccessFaultInner +(KPROCESSOR_MODE Mode, + PMMSUPPORT AddressSpace, + ULONG_PTR Address, + BOOLEAN FromMdl, + PETHREAD Thread) +{ + MEMORY_AREA* MemoryArea; + NTSTATUS Status; + BOOLEAN Locked = FromMdl; + MM_REQUIRED_RESOURCES Resources = { 0 }; + + DPRINT("MmAccessFault(Mode %d, Address %x)\n", Mode, Address); + + if (KeGetCurrentIrql() >= DISPATCH_LEVEL) + { + DPRINT1("Page fault at high IRQL was %d\n", KeGetCurrentIrql()); + return(STATUS_UNSUCCESSFUL); + } + + /* + * Find the memory area for the faulting address + */ + if (Address >= (ULONG_PTR)MmSystemRangeStart) + { + /* + * Check permissions + */ + if (Mode != KernelMode) + { + DPRINT("MmAccessFault(Mode %d, Address %x)\n", Mode, Address); + return(STATUS_ACCESS_VIOLATION); + } + AddressSpace = MmGetKernelAddressSpace(); + } + else + { + AddressSpace = &PsGetCurrentProcess()->Vm; + } + + if (!FromMdl) + { + MmLockAddressSpace(AddressSpace); + } + + do + { + MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, (PVOID)Address); + if (MemoryArea == NULL || + MemoryArea->DeleteInProgress) + { + if (!FromMdl) + { + MmUnlockAddressSpace(AddressSpace); + } + DPRINT("Address: %x\n", Address); + return (STATUS_ACCESS_VIOLATION); + } + + DPRINT + ("Type %x (%x -> %x)\n", + MemoryArea->Type, + MemoryArea->StartingAddress, + MemoryArea->EndingAddress); + + Resources.DoAcquisition = NULL; + + // Note: fault handlers are called with address space locked + // We return STATUS_MORE_PROCESSING_REQUIRED if anything is needed + Status = MiCowCacheSectionPage + (AddressSpace, MemoryArea, (PVOID)Address, Locked, &Resources); + + if (!FromMdl) + { + MmUnlockAddressSpace(AddressSpace); + } + + if (Status == STATUS_SUCCESS + 1) + { + // Wait page ... + DPRINT("Waiting for %x\n", Address); + MiWaitForPageEvent(MmGetAddressSpaceOwner(AddressSpace), Address); + DPRINT("Restarting fault %x\n", Address); + Status = STATUS_MM_RESTART_OPERATION; + } + else if (Status == STATUS_MM_RESTART_OPERATION) + { + // Clean slate + RtlZeroMemory(&Resources, sizeof(Resources)); + } + else if (Status == STATUS_MORE_PROCESSING_REQUIRED) + { + if (Thread->ActiveFaultCount > 0) + { + WORK_QUEUE_WITH_CONTEXT Context = { }; + DPRINT("Already fault handling ... going to work item (%x)\n", Address); + Context.AddressSpace = AddressSpace; + Context.MemoryArea = MemoryArea; + Context.Required = &Resources; + KeInitializeEvent(&Context.Wait, NotificationEvent, FALSE); + ExInitializeWorkItem(&Context.WorkItem, (PWORKER_THREAD_ROUTINE)MmpFaultWorker, &Context); + DPRINT("Queue work item\n"); + ExQueueWorkItem(&Context.WorkItem, DelayedWorkQueue); + DPRINT("Wait\n"); + KeWaitForSingleObject(&Context.Wait, 0, KernelMode, FALSE, NULL); + Status = Context.Status; + DPRINT("Status %x\n", Status); + } + else + { + Status = Resources.DoAcquisition(AddressSpace, MemoryArea, &Resources); + } + + if (NT_SUCCESS(Status)) + { + Status = STATUS_MM_RESTART_OPERATION; + } + } + + if (!FromMdl) + { + MmLockAddressSpace(AddressSpace); + } + } + while (Status == STATUS_MM_RESTART_OPERATION); + + if (!NT_SUCCESS(Status) && MemoryArea->Type == 1) + { + DPRINT1("Completed page fault handling %x %x\n", Address, Status); + DPRINT1 + ("Type %x (%x -> %x)\n", + MemoryArea->Type, + MemoryArea->StartingAddress, + MemoryArea->EndingAddress); + } + + if (!FromMdl) + { + MmUnlockAddressSpace(AddressSpace); + } + + return(Status); +} + +NTSTATUS +NTAPI +MmAccessFaultCacheSection +(KPROCESSOR_MODE Mode, + ULONG_PTR Address, + BOOLEAN FromMdl) +{ + PETHREAD Thread; + PMMSUPPORT AddressSpace; + NTSTATUS Status; + + DPRINT("MmpAccessFault(Mode %d, Address %x)\n", Mode, Address); + + Thread = PsGetCurrentThread(); + + if (KeGetCurrentIrql() >= DISPATCH_LEVEL) + { + DPRINT1("Page fault at high IRQL %d, address %x\n", KeGetCurrentIrql(), Address); + return(STATUS_UNSUCCESSFUL); + } + + /* + * Find the memory area for the faulting address + */ + if (Address >= (ULONG_PTR)MmSystemRangeStart) + { + /* + * Check permissions + */ + if (Mode != KernelMode) + { + DPRINT1("Address: %x:%x\n", PsGetCurrentProcess(), Address); + return(STATUS_ACCESS_VIOLATION); + } + AddressSpace = MmGetKernelAddressSpace(); + } + else + { + AddressSpace = &PsGetCurrentProcess()->Vm; + } + + Thread->ActiveFaultCount++; + Status = MmpSectionAccessFaultInner(Mode, AddressSpace, Address, FromMdl, Thread); + Thread->ActiveFaultCount--; + + return(Status); +} + +NTSTATUS +NTAPI +MmNotPresentFaultCacheSectionInner +(KPROCESSOR_MODE Mode, + PMMSUPPORT AddressSpace, + ULONG_PTR Address, + BOOLEAN FromMdl, + PETHREAD Thread) +{ + BOOLEAN Locked = FromMdl; + PMEMORY_AREA MemoryArea; + MM_REQUIRED_RESOURCES Resources = { 0 }; + NTSTATUS Status = STATUS_SUCCESS; + + if (!FromMdl) + { + MmLockAddressSpace(AddressSpace); + } + + /* + * Call the memory area specific fault handler + */ + do + { + MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, (PVOID)Address); + if (MemoryArea == NULL || MemoryArea->DeleteInProgress) + { + Status = STATUS_ACCESS_VIOLATION; + if (MemoryArea) + { + DPRINT1("Type %x DIP %x\n", MemoryArea->Type, MemoryArea->DeleteInProgress); + } + else + { + DPRINT1("No memory area\n"); + } + DPRINT1("Process %x, Address %x\n", MmGetAddressSpaceOwner(AddressSpace), Address); + break; + } + + DPRINTC + ("Type %x (%x -> %x -> %x) in %x\n", + MemoryArea->Type, + MemoryArea->StartingAddress, + Address, + MemoryArea->EndingAddress, + PsGetCurrentThread()); + + Resources.DoAcquisition = NULL; + + // Note: fault handlers are called with address space locked + // We return STATUS_MORE_PROCESSING_REQUIRED if anything is needed + + Status = MmNotPresentFaultCachePage + (AddressSpace, MemoryArea, (PVOID)Address, Locked, &Resources); + + if (!FromMdl) + { + MmUnlockAddressSpace(AddressSpace); + } + + if (Status == STATUS_SUCCESS) + { + ; // Nothing + } + else if (Status == STATUS_SUCCESS + 1) + { + // Wait page ... + DPRINT("Waiting for %x\n", Address); + MiWaitForPageEvent(MmGetAddressSpaceOwner(AddressSpace), Address); + DPRINT("Done waiting for %x\n", Address); + Status = STATUS_MM_RESTART_OPERATION; + } + else if (Status == STATUS_MM_RESTART_OPERATION) + { + // Clean slate + DPRINT("Clear resource\n"); + RtlZeroMemory(&Resources, sizeof(Resources)); + } + else if (Status == STATUS_MORE_PROCESSING_REQUIRED) + { + if (Thread->ActiveFaultCount > 1) + { + WORK_QUEUE_WITH_CONTEXT Context = { }; + DPRINTC("Already fault handling ... going to work item (%x)\n", Address); + Context.AddressSpace = AddressSpace; + Context.MemoryArea = MemoryArea; + Context.Required = &Resources; + KeInitializeEvent(&Context.Wait, NotificationEvent, FALSE); + ExInitializeWorkItem(&Context.WorkItem, (PWORKER_THREAD_ROUTINE)MmpFaultWorker, &Context); + DPRINT("Queue work item\n"); + ExQueueWorkItem(&Context.WorkItem, DelayedWorkQueue); + DPRINT("Wait\n"); + KeWaitForSingleObject(&Context.Wait, 0, KernelMode, FALSE, NULL); + Status = Context.Status; + DPRINTC("Status %x\n", Status); + } + else + { + DPRINT("DoAcquisition %x\n", Resources.DoAcquisition); + Status = Resources.DoAcquisition + (AddressSpace, MemoryArea, &Resources); + DPRINT("DoAcquisition %x -> %x\n", Resources.DoAcquisition, Status); + } + + if (NT_SUCCESS(Status)) + { + Status = STATUS_MM_RESTART_OPERATION; + } + } + else if (NT_SUCCESS(Status)) + { + ASSERT(FALSE); + } + + if (!FromMdl) + { + MmLockAddressSpace(AddressSpace); + } + } + while (Status == STATUS_MM_RESTART_OPERATION); + + DPRINTC("Completed page fault handling: %x:%x %x\n", MmGetAddressSpaceOwner(AddressSpace), Address, Status); + if (!FromMdl) + { + MmUnlockAddressSpace(AddressSpace); + } + + MiSetPageEvent(MmGetAddressSpaceOwner(AddressSpace), Address); + DPRINT("Done %x\n", Status); + + return Status; +} + +NTSTATUS +NTAPI +MmNotPresentFaultCacheSection +(KPROCESSOR_MODE Mode, + ULONG_PTR Address, + BOOLEAN FromMdl) +{ + PETHREAD Thread; + PMMSUPPORT AddressSpace; + NTSTATUS Status; + + Address &= ~(PAGE_SIZE - 1); + DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode, Address); + + Thread = PsGetCurrentThread(); + + if (KeGetCurrentIrql() >= DISPATCH_LEVEL) + { + DPRINT1("Page fault at high IRQL %d, address %x\n", KeGetCurrentIrql(), Address); + ASSERT(FALSE); + return(STATUS_UNSUCCESSFUL); + } + + /* + * Find the memory area for the faulting address + */ + if (Address >= (ULONG_PTR)MmSystemRangeStart) + { + /* + * Check permissions + */ + if (Mode != KernelMode) + { + DPRINTC("Address: %x\n", Address); + return(STATUS_ACCESS_VIOLATION); + } + AddressSpace = MmGetKernelAddressSpace(); + } + else + { + AddressSpace = &PsGetCurrentProcess()->Vm; + } + + Thread->ActiveFaultCount++; + Status = MmNotPresentFaultCacheSectionInner + (Mode, AddressSpace, Address, FromMdl, Thread); + Thread->ActiveFaultCount--; + + ASSERT(Status != STATUS_UNSUCCESSFUL); + ASSERT(Status != STATUS_INVALID_PARAMETER); + DPRINT("MmAccessFault %x:%x -> %x\n", MmGetAddressSpaceOwner(AddressSpace), Address, Status); + + return(Status); +} diff --git a/ntoskrnl/cache/section/io.c b/ntoskrnl/cache/section/io.c new file mode 100644 index 00000000000..254c25c38a6 --- /dev/null +++ b/ntoskrnl/cache/section/io.c @@ -0,0 +1,309 @@ +/* + * Copyright (C) 1998-2005 ReactOS Team (and the authors from the programmers section) + * + * 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. + * + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/section.c + * PURPOSE: Implements section objects + * + * PROGRAMMERS: Rex Jolliff + * David Welch + * Eric Kohl + * Emanuele Aliberti + * Eugene Ingerman + * Casper Hornstrup + * KJK::Hyperion + * Guido de Jong + * Ge van Geldorp + * Royce Mitchell III + * Filip Navara + * Aleksey Bragin + * Jason Filby + * Thomas Weidenmueller + * Gunnar Andre' Dalsnes + * Mike Nordell + * Alex Ionescu + * Gregor Anich + * Steven Edwards + * Herve Poussineau + */ + +/* INCLUDES *****************************************************************/ + +#include +#include "newmm.h" +#define NDEBUG +#include +#include + +#if defined (ALLOC_PRAGMA) +#pragma alloc_text(INIT, MmCreatePhysicalMemorySection) +#pragma alloc_text(INIT, MmInitSectionImplementation) +#endif + +KEVENT CcpLazyWriteEvent; + +PDEVICE_OBJECT +NTAPI +MmGetDeviceObjectForFile(IN PFILE_OBJECT FileObject) +{ + return IoGetRelatedDeviceObject(FileObject); +} + +NTSTATUS +NTAPI +MiSimpleReadComplete +(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context) +{ + /* Unlock MDL Pages, page 167. */ + DPRINT("MiSimpleReadComplete %x\n", Irp); + PMDL Mdl = Irp->MdlAddress; + while (Mdl) + { + DPRINT("MDL Unlock %x\n", Mdl); + MmUnlockPages(Mdl); + Mdl = Mdl->Next; + } + + /* Check if there's an MDL */ + while ((Mdl = Irp->MdlAddress)) + { + /* Clear all of them */ + Irp->MdlAddress = Mdl->Next; + IoFreeMdl(Mdl); + } + + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +MiSimpleRead +(PFILE_OBJECT FileObject, + PLARGE_INTEGER FileOffset, + PVOID Buffer, + ULONG Length, + PIO_STATUS_BLOCK ReadStatus) +{ + NTSTATUS Status; + PIRP Irp = NULL; + KEVENT ReadWait; + PDEVICE_OBJECT DeviceObject; + PIO_STACK_LOCATION IrpSp; + + ASSERT(FileObject); + ASSERT(FileOffset); + ASSERT(Buffer); + ASSERT(ReadStatus); + + DeviceObject = MmGetDeviceObjectForFile(FileObject); + ReadStatus->Status = STATUS_INTERNAL_ERROR; + ReadStatus->Information = 0; + + ASSERT(DeviceObject); + + DPRINT + ("PAGING READ: FileObject %x <%wZ> Offset %08x%08x Length %d\n", + &FileObject, + &FileObject->FileName, + FileOffset->HighPart, + FileOffset->LowPart, + Length); + + KeInitializeEvent(&ReadWait, NotificationEvent, FALSE); + + Irp = IoBuildAsynchronousFsdRequest + (IRP_MJ_READ, + DeviceObject, + Buffer, + Length, + FileOffset, + ReadStatus); + + if (!Irp) + { + return STATUS_NO_MEMORY; + } + + Irp->Flags |= IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO | IRP_NOCACHE | IRP_SYNCHRONOUS_API; + + Irp->UserEvent = &ReadWait; + Irp->Tail.Overlay.OriginalFileObject = FileObject; + Irp->Tail.Overlay.Thread = PsGetCurrentThread(); + IrpSp = IoGetNextIrpStackLocation(Irp); + IrpSp->Control |= SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR; + IrpSp->FileObject = FileObject; + IrpSp->CompletionRoutine = MiSimpleReadComplete; + + Status = IoCallDriver(DeviceObject, Irp); + if (Status == STATUS_PENDING) + { + DPRINT1("KeWaitForSingleObject(&ReadWait)\n"); + if (!NT_SUCCESS + (KeWaitForSingleObject + (&ReadWait, + Suspended, + KernelMode, + FALSE, + NULL))) + { + DPRINT1("Warning: Failed to wait for synchronous IRP\n"); + ASSERT(FALSE); + return Status; + } + } + + DPRINT("Paging IO Done: %08x\n", ReadStatus->Status); + Status = + ReadStatus->Status == STATUS_END_OF_FILE ? + STATUS_SUCCESS : ReadStatus->Status; + return Status; +} + +NTSTATUS +NTAPI +_MiSimpleWrite +(PFILE_OBJECT FileObject, + PLARGE_INTEGER FileOffset, + PVOID Buffer, + ULONG Length, + PIO_STATUS_BLOCK ReadStatus, + const char *File, + int Line) +{ + NTSTATUS Status; + PIRP Irp = NULL; + KEVENT ReadWait; + PDEVICE_OBJECT DeviceObject; + PIO_STACK_LOCATION IrpSp; + + ASSERT(FileObject); + ASSERT(FileOffset); + ASSERT(Buffer); + ASSERT(ReadStatus); + + ObReferenceObject(FileObject); + DeviceObject = MmGetDeviceObjectForFile(FileObject); + ASSERT(DeviceObject); + + DPRINT + ("PAGING WRITE: FileObject %x Offset %x Length %d (%s:%d)\n", + &FileObject, + FileOffset->LowPart, + Length, + File, + Line); + + KeInitializeEvent(&ReadWait, NotificationEvent, FALSE); + + Irp = IoBuildAsynchronousFsdRequest + (IRP_MJ_WRITE, + DeviceObject, + Buffer, + Length, + FileOffset, + ReadStatus); + + if (!Irp) + { + ObDereferenceObject(FileObject); + return STATUS_NO_MEMORY; + } + + Irp->Flags = IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO | IRP_NOCACHE | IRP_SYNCHRONOUS_API; + + Irp->UserEvent = &ReadWait; + Irp->Tail.Overlay.OriginalFileObject = FileObject; + Irp->Tail.Overlay.Thread = PsGetCurrentThread(); + IrpSp = IoGetNextIrpStackLocation(Irp); + IrpSp->Control |= SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR; + IrpSp->FileObject = FileObject; + IrpSp->CompletionRoutine = MiSimpleReadComplete; + + DPRINT("Call Driver\n"); + Status = IoCallDriver(DeviceObject, Irp); + DPRINT("Status %x\n", Status); + + ObDereferenceObject(FileObject); + + if (Status == STATUS_PENDING) + { + DPRINT1("KeWaitForSingleObject(&ReadWait)\n"); + if (!NT_SUCCESS + (KeWaitForSingleObject + (&ReadWait, + Suspended, + KernelMode, + FALSE, + NULL))) + { + DPRINT1("Warning: Failed to wait for synchronous IRP\n"); + ASSERT(FALSE); + return Status; + } + } + + DPRINT("Paging IO Done: %08x\n", ReadStatus->Status); + return ReadStatus->Status; +} + +extern KEVENT MpwThreadEvent; +FAST_MUTEX MiWriteMutex; + +NTSTATUS +NTAPI +_MiWriteBackPage +(PFILE_OBJECT FileObject, + PLARGE_INTEGER FileOffset, + ULONG Length, + PFN_NUMBER Page, + const char *File, + int Line) +{ + NTSTATUS Status; + PVOID Hyperspace; + IO_STATUS_BLOCK Iosb; + KIRQL OldIrql; + PVOID PageBuffer = ExAllocatePool(NonPagedPool, PAGE_SIZE); + + if (!PageBuffer) return STATUS_NO_MEMORY; + + OldIrql = KfRaiseIrql(DISPATCH_LEVEL); + Hyperspace = MmCreateHyperspaceMapping(Page); + RtlCopyMemory(PageBuffer, Hyperspace, PAGE_SIZE); + MmDeleteHyperspaceMapping(Hyperspace); + KfLowerIrql(OldIrql); + + DPRINT1("MiWriteBackPage(%wZ,%08x%08x,%s:%d)\n", &FileObject->FileName, FileOffset->u.HighPart, FileOffset->u.LowPart, File, Line); + Status = MiSimpleWrite + (FileObject, + FileOffset, + PageBuffer, + Length, + &Iosb); + + ExFreePool(PageBuffer); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("MiSimpleWrite failed (%x)\n", Status); + } + + return Status; +} diff --git a/ntoskrnl/cache/section/newmm.h b/ntoskrnl/cache/section/newmm.h new file mode 100644 index 00000000000..43fd3fe7cef --- /dev/null +++ b/ntoskrnl/cache/section/newmm.h @@ -0,0 +1,454 @@ +#pragma once + +#include + +/* TYPES *********************************************************************/ + +#define MM_WAIT_ENTRY 0x7ffff800 +#define PFN_FROM_SSE(E) ((E) >> PAGE_SHIFT) +#define IS_SWAP_FROM_SSE(E) ((E) & 0x00000001) +#define MM_IS_WAIT_PTE(E) \ + (IS_SWAP_FROM_SSE(E) && SWAPENTRY_FROM_SSE(E) == MM_WAIT_ENTRY) +#define MAKE_PFN_SSE(P) ((P) << PAGE_SHIFT) +#define SWAPENTRY_FROM_SSE(E) ((E) >> 1) +#define MAKE_SWAP_SSE(S) (((S) << 1) | 0x1) +#define DIRTY_SSE(E) ((E) | 2) +#define CLEAN_SSE(E) ((E) & ~2) +#define IS_DIRTY_SSE(E) ((E) & 2) + +#define MEMORY_AREA_CACHE (2) +#define MM_SEGMENT_FINALIZE (0x40000000) + +#define RMAP_SEGMENT_MASK ~0xff +#define RMAP_IS_SEGMENT(x) (((ULONG_PTR)(x) & RMAP_SEGMENT_MASK) == RMAP_SEGMENT_MASK) + +#define MIN(x,y) (((x)<(y))?(x):(y)) +#define MAX(x,y) (((x)>(y))?(x):(y)) + +/* Determine what's needed to make paged pool fit in this category. + * it seems that something more is required to satisfy arm3. */ +#define BALANCER_CAN_EVICT(Consumer) \ + (((Consumer) == MC_USER) || \ + ((Consumer) == MC_CACHE)) + +#define SEC_CACHE (0x40000000) + +#define MiWaitForPageEvent(Process,Address) do { \ + DPRINT("MiWaitForPageEvent %x:%x #\n", Process, Address); \ + KeWaitForSingleObject(&MmWaitPageEvent, 0, KernelMode, FALSE, NULL); \ +} while(0) + +#define MiSetPageEvent(Process,Address) do { \ + DPRINT("MiSetPageEvent %x:%x #\n",Process, Address); \ + KeSetEvent(&MmWaitPageEvent, IO_NO_INCREMENT, FALSE); \ +} while(0) + +/* We store 8 bits of location with a page association */ +#define ENTRIES_PER_ELEMENT 256 + +extern KEVENT MmWaitPageEvent; + +typedef struct _MM_CACHE_SECTION_SEGMENT +{ + FAST_MUTEX Lock; /* lock which protects the page directory */ + PFILE_OBJECT FileObject; + ULARGE_INTEGER RawLength; /* length of the segment which is part of the mapped file */ + ULARGE_INTEGER Length; /* absolute length of the segment */ + ULONG ReferenceCount; + ULONG Protection; + ULONG Flags; + BOOLEAN WriteCopy; + + struct + { + LONG FileOffset; /* start offset into the file for image sections */ + ULONG_PTR VirtualAddress; /* dtart offset into the address range for image sections */ + ULONG Characteristics; + } Image; + + RTL_GENERIC_TABLE PageTable; +} MM_CACHE_SECTION_SEGMENT, *PMM_CACHE_SECTION_SEGMENT; + +typedef struct _CACHE_SECTION_PAGE_TABLE +{ + LARGE_INTEGER FileOffset; + PMM_CACHE_SECTION_SEGMENT Segment; + ULONG Refcount; + ULONG PageEntries[ENTRIES_PER_ELEMENT]; +} CACHE_SECTION_PAGE_TABLE, *PCACHE_SECTION_PAGE_TABLE; + +struct _MM_REQUIRED_RESOURCES; + +typedef NTSTATUS (NTAPI * AcquireResource) + (PMMSUPPORT AddressSpace, + struct _MEMORY_AREA *MemoryArea, + struct _MM_REQUIRED_RESOURCES *Required); +typedef NTSTATUS (NTAPI * NotPresentFaultHandler) + (PMMSUPPORT AddressSpace, + struct _MEMORY_AREA *MemoryArea, + PVOID Address, + BOOLEAN Locked, + struct _MM_REQUIRED_RESOURCES *Required); +typedef NTSTATUS (NTAPI * FaultHandler) + (PMMSUPPORT AddressSpace, + struct _MEMORY_AREA *MemoryArea, + PVOID Address, + struct _MM_REQUIRED_RESOURCES *Required); + +typedef struct _MM_REQUIRED_RESOURCES +{ + ULONG Consumer; + ULONG Amount; + ULONG Offset; + ULONG State; + PVOID Context; + LARGE_INTEGER FileOffset; + AcquireResource DoAcquisition; + PFN_NUMBER Page[2]; + PVOID Buffer[2]; + SWAPENTRY SwapEntry; + const char *File; + int Line; +} MM_REQUIRED_RESOURCES, *PMM_REQUIRED_RESOURCES; + +PFN_NUMBER +NTAPI +MmWithdrawSectionPage +(PMM_CACHE_SECTION_SEGMENT Segment, PLARGE_INTEGER FileOffset, BOOLEAN *Dirty); + +NTSTATUS +NTAPI +MmFinalizeSectionPageOut +(PMM_CACHE_SECTION_SEGMENT Segment, PLARGE_INTEGER FileOffset, PFN_NUMBER Page, + BOOLEAN Dirty); + +/* sptab.c *******************************************************************/ + +VOID +NTAPI +MiInitializeSectionPageTable(PMM_CACHE_SECTION_SEGMENT Segment); + +NTSTATUS +NTAPI +_MiSetPageEntryCacheSectionSegment +(PMM_CACHE_SECTION_SEGMENT Segment, + PLARGE_INTEGER Offset, + ULONG Entry, const char *file, int line); + +ULONG +NTAPI +_MiGetPageEntryCacheSectionSegment +(PMM_CACHE_SECTION_SEGMENT Segment, + PLARGE_INTEGER Offset, const char *file, int line); + +#define MiSetPageEntryCacheSectionSegment(S,O,E) _MiSetPageEntryCacheSectionSegment(S,O,E,__FILE__,__LINE__) +#define MiGetPageEntryCacheSectionSegment(S,O) _MiGetPageEntryCacheSectionSegment(S,O,__FILE__,__LINE__) + +typedef VOID (NTAPI *FREE_SECTION_PAGE_FUN) + (PMM_CACHE_SECTION_SEGMENT Segment, + PLARGE_INTEGER Offset); + +VOID +NTAPI +MiFreePageTablesSectionSegment(PMM_CACHE_SECTION_SEGMENT Segment, FREE_SECTION_PAGE_FUN FreePage); + +/* Yields a lock */ +PMM_CACHE_SECTION_SEGMENT +NTAPI +MmGetSectionAssociation(PFN_NUMBER Page, PLARGE_INTEGER Offset); + +NTSTATUS +NTAPI +MmSetSectionAssociation(PFN_NUMBER Page, PMM_CACHE_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset); + +VOID +NTAPI +MmDeleteSectionAssociation(PFN_NUMBER Page); + +NTSTATUS +NTAPI +MmpPageOutPhysicalAddress(PFN_NUMBER Page); + +/* io.c **********************************************************************/ + +NTSTATUS +MmspWaitForFileLock(PFILE_OBJECT File); + +NTSTATUS +NTAPI +MiSimpleRead +(PFILE_OBJECT FileObject, + PLARGE_INTEGER FileOffset, + PVOID Buffer, + ULONG Length, + PIO_STATUS_BLOCK ReadStatus); + +NTSTATUS +NTAPI +_MiSimpleWrite +(PFILE_OBJECT FileObject, + PLARGE_INTEGER FileOffset, + PVOID Buffer, + ULONG Length, + PIO_STATUS_BLOCK ReadStatus, + const char *file, + int line); + +#define MiSimpleWrite(F,O,B,L,R) _MiSimpleWrite(F,O,B,L,R,__FILE__,__LINE__) + +NTSTATUS +NTAPI +_MiWriteBackPage +(PFILE_OBJECT FileObject, + PLARGE_INTEGER Offset, + ULONG Length, + PFN_NUMBER Page, + const char *File, + int Line); + +#define MiWriteBackPage(F,O,L,P) _MiWriteBackPage(F,O,L,P,__FILE__,__LINE__) + +/* section.c *****************************************************************/ + +NTSTATUS +NTAPI +MmAccessFaultCacheSection +(KPROCESSOR_MODE Mode, + ULONG_PTR Address, + BOOLEAN FromMdl); + +NTSTATUS +NTAPI +MiReadFilePage +(PMMSUPPORT AddressSpace, + PMEMORY_AREA MemoryArea, + PMM_REQUIRED_RESOURCES RequiredResources); + +ULONG +NTAPI +MiChecksumPage(PFN_NUMBER Page, BOOLEAN Lock); + +NTSTATUS +NTAPI +MiGetOnePage +(PMMSUPPORT AddressSpace, + PMEMORY_AREA MemoryArea, + PMM_REQUIRED_RESOURCES RequiredResources); + +NTSTATUS +NTAPI +MiSwapInPage +(PMMSUPPORT AddressSpace, + PMEMORY_AREA MemoryArea, + PMM_REQUIRED_RESOURCES RequiredResources); + +NTSTATUS +NTAPI +MiWriteSwapPage +(PMMSUPPORT AddressSpace, + PMEMORY_AREA MemoryArea, + PMM_REQUIRED_RESOURCES Resources); + +NTSTATUS +NTAPI +MiWriteFilePage +(PMMSUPPORT AddressSpace, + PMEMORY_AREA MemoryArea, + PMM_REQUIRED_RESOURCES Resources); + +VOID +NTAPI +MiFreeSegmentPage +(PMM_CACHE_SECTION_SEGMENT Segment, + PLARGE_INTEGER FileOffset); + +NTSTATUS +NTAPI +MiCowCacheSectionPage +(PMMSUPPORT AddressSpace, + PMEMORY_AREA MemoryArea, + PVOID Address, + BOOLEAN Locked, + PMM_REQUIRED_RESOURCES Required); + +NTSTATUS +NTAPI +MiZeroFillSection(PVOID Address, PLARGE_INTEGER FileOffsetPtr, ULONG Length); + +VOID +MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address); + +VOID +NTAPI +_MmLockCacheSectionSegment(PMM_CACHE_SECTION_SEGMENT Segment, const char *file, int line); + +#define MmLockCacheSectionSegment(x) _MmLockCacheSectionSegment(x,__FILE__,__LINE__) + +VOID +NTAPI +_MmUnlockCacheSectionSegment(PMM_CACHE_SECTION_SEGMENT Segment, const char *file, int line); + +#define MmUnlockCacheSectionSegment(x) _MmUnlockCacheSectionSegment(x,__FILE__,__LINE__) + +VOID +MmFreeCacheSectionPage +(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, + PFN_NUMBER Page, SWAPENTRY SwapEntry, BOOLEAN Dirty); + +NTSTATUS +NTAPI +_MiFlushMappedSection(PVOID BaseAddress, PLARGE_INTEGER BaseOffset, PLARGE_INTEGER FileSize, BOOLEAN Dirty, const char *File, int Line); + +#define MiFlushMappedSection(A,O,S,D) _MiFlushMappedSection(A,O,S,D,__FILE__,__LINE__) + +VOID +NTAPI +MmFinalizeSegment(PMM_CACHE_SECTION_SEGMENT Segment); + +VOID +NTAPI +MmFreeSectionSegments(PFILE_OBJECT FileObject); + +NTSTATUS NTAPI +MmMapCacheViewInSystemSpaceAtOffset +(IN PMM_CACHE_SECTION_SEGMENT Segment, + OUT PVOID * MappedBase, + IN PLARGE_INTEGER ViewOffset, + IN OUT PULONG ViewSize); + +NTSTATUS +NTAPI +_MiMapViewOfSegment +(PMMSUPPORT AddressSpace, + PMM_CACHE_SECTION_SEGMENT Segment, + PVOID* BaseAddress, + SIZE_T ViewSize, + ULONG Protect, + PLARGE_INTEGER ViewOffset, + ULONG AllocationType, + const char *file, + int line); + +#define MiMapViewOfSegment(AddressSpace,Segment,BaseAddress,ViewSize,Protect,ViewOffset,AllocationType) _MiMapViewOfSegment(AddressSpace,Segment,BaseAddress,ViewSize,Protect,ViewOffset,AllocationType,__FILE__,__LINE__) + +NTSTATUS +NTAPI +MmUnmapViewOfCacheSegment +(PMMSUPPORT AddressSpace, + PVOID BaseAddress); + +NTSTATUS +NTAPI +MmUnmapCacheViewInSystemSpace(PVOID Address); + +NTSTATUS +NTAPI +MmNotPresentFaultCachePage +(PMMSUPPORT AddressSpace, + PMEMORY_AREA MemoryArea, + PVOID Address, + BOOLEAN Locked, + PMM_REQUIRED_RESOURCES Required); + +NTSTATUS +NTAPI +MmPageOutPageFileView +(PMMSUPPORT AddressSpace, + PMEMORY_AREA MemoryArea, + PVOID Address, + PMM_REQUIRED_RESOURCES Required); + +FORCEINLINE +BOOLEAN +_MmTryToLockAddressSpace(IN PMMSUPPORT AddressSpace, const char *file, int line) +{ + BOOLEAN Result = KeTryToAcquireGuardedMutex(&CONTAINING_RECORD(AddressSpace, EPROCESS, Vm)->AddressCreationLock); + //DbgPrint("(%s:%d) Try Lock Address Space %x -> %s\n", file, line, AddressSpace, Result ? "true" : "false"); + return Result; +} + +#define MmTryToLockAddressSpace(x) _MmTryToLockAddressSpace(x,__FILE__,__LINE__) + +NTSTATUS +NTAPI +MiWidenSegment +(PMMSUPPORT AddressSpace, + PMEMORY_AREA MemoryArea, + PMM_REQUIRED_RESOURCES RequiredResources); + +NTSTATUS +NTAPI +MiSwapInSectionPage +(PMMSUPPORT AddressSpace, + PMEMORY_AREA MemoryArea, + PMM_REQUIRED_RESOURCES RequiredResources); + +NTSTATUS +NTAPI +MmExtendCacheSection(PMM_CACHE_SECTION_SEGMENT Section, PLARGE_INTEGER NewSize, BOOLEAN ExtendFile); + +NTSTATUS +NTAPI +_MiFlushMappedSection(PVOID BaseAddress, PLARGE_INTEGER BaseOffset, PLARGE_INTEGER FileSize, BOOLEAN Dirty, const char *File, int Line); + +#define MiFlushMappedSection(A,O,S,D) _MiFlushMappedSection(A,O,S,D,__FILE__,__LINE__) + +NTSTATUS +NTAPI +MmCreateCacheSection +(PMM_CACHE_SECTION_SEGMENT *SegmentObject, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + PLARGE_INTEGER UMaximumSize, + ULONG SectionPageProtection, + ULONG AllocationAttributes, + PFILE_OBJECT FileObject); + +NTSTATUS +NTAPI +MiSimpleRead +(PFILE_OBJECT FileObject, + PLARGE_INTEGER FileOffset, + PVOID Buffer, + ULONG Length, + PIO_STATUS_BLOCK ReadStatus); + +NTSTATUS +NTAPI +_MiSimpleWrite +(PFILE_OBJECT FileObject, + PLARGE_INTEGER FileOffset, + PVOID Buffer, + ULONG Length, + PIO_STATUS_BLOCK ReadStatus, + const char *file, + int line); + +#define MiSimpleWrite(F,O,B,L,R) _MiSimpleWrite(F,O,B,L,R,__FILE__,__LINE__) + +NTSTATUS +NTAPI +_MiWriteBackPage +(PFILE_OBJECT FileObject, + PLARGE_INTEGER Offset, + ULONG Length, + PFN_NUMBER Page, + const char *File, + int Line); + +#define MiWriteBackPage(F,O,L,P) _MiWriteBackPage(F,O,L,P,__FILE__,__LINE__) + +PVOID +NTAPI +MmGetSegmentRmap(PFN_NUMBER Page, PULONG RawOffset); + +NTSTATUS +NTAPI +MmNotPresentFaultCacheSection +(KPROCESSOR_MODE Mode, + ULONG_PTR Address, + BOOLEAN FromMdl); + +ULONG +NTAPI +MiCacheEvictPages(PVOID BaseAddress, ULONG Target); diff --git a/ntoskrnl/cache/section/reqtools.c b/ntoskrnl/cache/section/reqtools.c new file mode 100644 index 00000000000..68056d49ec9 --- /dev/null +++ b/ntoskrnl/cache/section/reqtools.c @@ -0,0 +1,269 @@ +/* + * Copyright (C) 1998-2005 ReactOS Team (and the authors from the programmers section) + * + * 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. + * + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/section.c + * PURPOSE: Implements section objects + * + * PROGRAMMERS: Rex Jolliff + * David Welch + * Eric Kohl + * Emanuele Aliberti + * Eugene Ingerman + * Casper Hornstrup + * KJK::Hyperion + * Guido de Jong + * Ge van Geldorp + * Royce Mitchell III + * Filip Navara + * Aleksey Bragin + * Jason Filby + * Thomas Weidenmueller + * Gunnar Andre' Dalsnes + * Mike Nordell + * Alex Ionescu + * Gregor Anich + * Steven Edwards + * Herve Poussineau + */ + +/* INCLUDES *****************************************************************/ + +#include +#include "newmm.h" +#define NDEBUG +#include + +#define DPRINTC DPRINT + +NTSTATUS +NTAPI +MiGetOnePage +(PMMSUPPORT AddressSpace, + PMEMORY_AREA MemoryArea, + PMM_REQUIRED_RESOURCES Required) +{ + int i; + NTSTATUS Status = STATUS_SUCCESS; + + for (i = 0; i < Required->Amount; i++) + { + DPRINTC("MiGetOnePage(%s:%d)\n", Required->File, Required->Line); + Status = MmRequestPageMemoryConsumer(Required->Consumer, TRUE, &Required->Page[i]); + if (!NT_SUCCESS(Status)) + { + while (i > 0) + { + MmReleasePageMemoryConsumer(MC_CACHE, Required->Page[i-1]); + i--; + } + return Status; + } + } + + return Status; +} + +NTSTATUS +NTAPI +MiReadFilePage +(PMMSUPPORT AddressSpace, + PMEMORY_AREA MemoryArea, + PMM_REQUIRED_RESOURCES RequiredResources) +{ + PFILE_OBJECT FileObject = RequiredResources->Context; + PPFN_NUMBER Page = &RequiredResources->Page[RequiredResources->Offset]; + PLARGE_INTEGER FileOffset = &RequiredResources->FileOffset; + NTSTATUS Status; + PVOID PageBuf = NULL; + PMEMORY_AREA TmpArea; + IO_STATUS_BLOCK IOSB; + PHYSICAL_ADDRESS BoundaryAddressMultiple; + + BoundaryAddressMultiple.QuadPart = 0; + + DPRINTC + ("Pulling page %08x%08x from %wZ to %x\n", + FileOffset->u.HighPart, FileOffset->u.LowPart, + &FileObject->FileName, + Page); + + Status = MmRequestPageMemoryConsumer(RequiredResources->Consumer, TRUE, Page); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Status: %x\n", Status); + return Status; + } + + MmLockAddressSpace(MmGetKernelAddressSpace()); + Status = MmCreateMemoryArea + (MmGetKernelAddressSpace(), + MEMORY_AREA_VIRTUAL_MEMORY, + &PageBuf, + PAGE_SIZE, + PAGE_READWRITE, + &TmpArea, + FALSE, + MEM_TOP_DOWN, + BoundaryAddressMultiple); + + DPRINT("Status %x, PageBuf %x\n", Status, PageBuf); + if (!NT_SUCCESS(Status)) + { + DPRINT1("STATUS_NO_MEMORY: %x\n", Status); + MmUnlockAddressSpace(MmGetKernelAddressSpace()); + MmReleasePageMemoryConsumer(MC_CACHE, *Page); + return STATUS_NO_MEMORY; + } + + Status = MmCreateVirtualMapping(NULL, PageBuf, PAGE_READWRITE, Page, 1); + if (!NT_SUCCESS(Status)) + { + MmFreeMemoryArea(MmGetKernelAddressSpace(), TmpArea, NULL, NULL); + MmUnlockAddressSpace(MmGetKernelAddressSpace()); + MmReleasePageMemoryConsumer(MC_CACHE, *Page); + DPRINT1("Status: %x\n", Status); + return Status; + } + + MmUnlockAddressSpace(MmGetKernelAddressSpace()); + + Status = MiSimpleRead + (FileObject, + FileOffset, + PageBuf, + RequiredResources->Amount, + &IOSB); + RtlZeroMemory + ((PCHAR)PageBuf+RequiredResources->Amount, + PAGE_SIZE-RequiredResources->Amount); + + DPRINT("Read Status %x (Page %x)\n", Status, *Page); + + MmLockAddressSpace(MmGetKernelAddressSpace()); + MmFreeMemoryArea(MmGetKernelAddressSpace(), TmpArea, NULL, NULL); + MmUnlockAddressSpace(MmGetKernelAddressSpace()); + + if (!NT_SUCCESS(Status)) + { + MmReleasePageMemoryConsumer(MC_CACHE, *Page); + DPRINT("Status: %x\n", Status); + return Status; + } + + return STATUS_SUCCESS; +} + +ULONG +NTAPI +MiChecksumPage(PFN_NUMBER Page, BOOLEAN Lock) +{ + int i; + NTSTATUS Status; + ULONG Total = 0; + PULONG PageBuf = NULL; + PMEMORY_AREA TmpArea; + PHYSICAL_ADDRESS BoundaryAddressMultiple; + + BoundaryAddressMultiple.QuadPart = 0; + + if (Lock) MmLockAddressSpace(MmGetKernelAddressSpace()); + + Status = MmCreateMemoryArea + (MmGetKernelAddressSpace(), + MEMORY_AREA_VIRTUAL_MEMORY, + (PVOID*)&PageBuf, + PAGE_SIZE, + PAGE_READWRITE, + &TmpArea, + FALSE, + MEM_TOP_DOWN, + BoundaryAddressMultiple); + + DPRINT("Status %x, PageBuf %x\n", Status, PageBuf); + if (!NT_SUCCESS(Status)) + { + DPRINT1("STATUS_NO_MEMORY: %x\n", Status); + if (Lock) MmUnlockAddressSpace(MmGetKernelAddressSpace()); + return 0; + } + + Status = MmCreateVirtualMapping(NULL, PageBuf, PAGE_READWRITE, &Page, 1); + if (!NT_SUCCESS(Status)) + { + MmFreeMemoryArea(MmGetKernelAddressSpace(), TmpArea, NULL, NULL); + if (Lock) MmUnlockAddressSpace(MmGetKernelAddressSpace()); + DPRINT1("Status: %x\n", Status); + return Status; + } + + for (i = 0; i < 1024; i++) { + Total += PageBuf[i]; + } + + MmFreeMemoryArea(MmGetKernelAddressSpace(), TmpArea, NULL, NULL); + if (Lock) MmUnlockAddressSpace(MmGetKernelAddressSpace()); + + return Total; +} + +NTSTATUS +NTAPI +MiSwapInPage +(PMMSUPPORT AddressSpace, + PMEMORY_AREA MemoryArea, + PMM_REQUIRED_RESOURCES Resources) +{ + NTSTATUS Status; + + Status = MmRequestPageMemoryConsumer(Resources->Consumer, TRUE, &Resources->Page[Resources->Offset]); + if (!NT_SUCCESS(Status)) + { + DPRINT1("MmRequestPageMemoryConsumer failed, status = %x\n", Status); + return Status; + } + + Status = MmReadFromSwapPage(Resources->SwapEntry, Resources->Page[Resources->Offset]); + if (!NT_SUCCESS(Status)) + { + DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status); + return Status; + } + + MmSetSavedSwapEntryPage(Resources->Page[Resources->Offset], Resources->SwapEntry); + + DPRINT1("MiSwapInPage(%x,%x)\n", Resources->Page[Resources->Offset], Resources->SwapEntry); + + return Status; +} + +NTSTATUS +NTAPI +MiWriteFilePage +(PMMSUPPORT AddressSpace, + PMEMORY_AREA MemoryArea, + PMM_REQUIRED_RESOURCES Required) +{ + DPRINT1("MiWriteFilePage(%x,%x)\n", Required->Page[Required->Offset], Required->FileOffset.LowPart); + + return MiWriteBackPage + (Required->Context, + &Required->FileOffset, + PAGE_SIZE, + Required->Page[Required->Offset]); +} diff --git a/ntoskrnl/cache/section/sptab.c b/ntoskrnl/cache/section/sptab.c new file mode 100644 index 00000000000..0b71764b865 --- /dev/null +++ b/ntoskrnl/cache/section/sptab.c @@ -0,0 +1,266 @@ +/* + * Copyright (C) 1998-2005 ReactOS Team (and the authors from the programmers section) + * + * 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. + * + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/section.c + * PURPOSE: Section object page tables + * + * PROGRAMMERS: arty + */ + +/* INCLUDES *****************************************************************/ + +#include +#include "newmm.h" +#define NDEBUG +#include + +#define DPRINTC DPRINT + +/* TYPES *********************************************************************/ + +extern KSPIN_LOCK MiSectionPageTableLock; + +static +PVOID +NTAPI +MiSectionPageTableAllocate(PRTL_GENERIC_TABLE Table, CLONG Bytes) +{ + PVOID Result; + Result = ExAllocatePoolWithTag(NonPagedPool, Bytes, 'MmPt'); + DPRINT("MiSectionPageTableAllocate(%d) => %p\n", Bytes, Result); + return Result; +} + +static +VOID +NTAPI +MiSectionPageTableFree(PRTL_GENERIC_TABLE Table, PVOID Data) +{ + DPRINT("MiSectionPageTableFree(%p)\n", Data); + ExFreePoolWithTag(Data, 'MmPt'); +} + +static +RTL_GENERIC_COMPARE_RESULTS +NTAPI +MiSectionPageTableCompare(PRTL_GENERIC_TABLE Table, PVOID PtrA, PVOID PtrB) +{ + PLARGE_INTEGER A = PtrA, B = PtrB; + BOOLEAN Result = (A->QuadPart < B->QuadPart) ? GenericLessThan : + (A->QuadPart == B->QuadPart) ? GenericEqual : GenericGreaterThan; + + DPRINT + ("Compare: %08x%08x vs %08x%08x => %s\n", + A->u.HighPart, A->u.LowPart, + B->u.HighPart, B->u.LowPart, + Result == GenericLessThan ? "GenericLessThan" : + Result == GenericGreaterThan ? "GenericGreaterThan" : + "GenericEqual"); + + return Result; +} + +static +PCACHE_SECTION_PAGE_TABLE +NTAPI +MiSectionPageTableGet +(PRTL_GENERIC_TABLE Table, + PLARGE_INTEGER FileOffset) +{ + LARGE_INTEGER SearchFileOffset; + PCACHE_SECTION_PAGE_TABLE PageTable; + SearchFileOffset.QuadPart = ROUND_DOWN(FileOffset->QuadPart, ENTRIES_PER_ELEMENT * PAGE_SIZE); + PageTable = RtlLookupElementGenericTable(Table, &SearchFileOffset); + DPRINT + ("MiSectionPageTableGet(%08x,%08x%08x)\n", + Table, + FileOffset->HighPart, + FileOffset->LowPart); + return PageTable; +} + +static +PCACHE_SECTION_PAGE_TABLE +NTAPI +MiSectionPageTableGetOrAllocate +(PRTL_GENERIC_TABLE Table, + PLARGE_INTEGER FileOffset) +{ + LARGE_INTEGER SearchFileOffset; + PCACHE_SECTION_PAGE_TABLE PageTableSlice = + MiSectionPageTableGet(Table, FileOffset); + if (!PageTableSlice) + { + CACHE_SECTION_PAGE_TABLE SectionZeroPageTable = { }; + SearchFileOffset.QuadPart = ROUND_DOWN(FileOffset->QuadPart, ENTRIES_PER_ELEMENT * PAGE_SIZE); + SectionZeroPageTable.FileOffset = SearchFileOffset; + SectionZeroPageTable.Refcount = 1; + PageTableSlice = RtlInsertElementGenericTable + (Table, &SectionZeroPageTable, sizeof(SectionZeroPageTable), NULL); + DPRINT + ("Allocate page table %x (%08x%08x)\n", + PageTableSlice, + PageTableSlice->FileOffset.u.HighPart, + PageTableSlice->FileOffset.u.LowPart); + if (!PageTableSlice) return NULL; + } + return PageTableSlice; +} + +VOID +NTAPI +MiInitializeSectionPageTable(PMM_CACHE_SECTION_SEGMENT Segment) +{ + RtlInitializeGenericTable + (&Segment->PageTable, + MiSectionPageTableCompare, + MiSectionPageTableAllocate, + MiSectionPageTableFree, + NULL); + DPRINT("MiInitializeSectionPageTable(%p)\n", &Segment->PageTable); +} + +NTSTATUS +NTAPI +_MiSetPageEntryCacheSectionSegment +(PMM_CACHE_SECTION_SEGMENT Segment, + PLARGE_INTEGER Offset, + ULONG Entry, + const char *file, + int line) +{ + ULONG PageIndex, OldEntry; + PCACHE_SECTION_PAGE_TABLE PageTable; + PageTable = + MiSectionPageTableGetOrAllocate(&Segment->PageTable, Offset); + if (!PageTable) return STATUS_NO_MEMORY; + ASSERT(MiSectionPageTableGet(&Segment->PageTable, Offset)); + PageTable->Segment = Segment; + PageIndex = + (Offset->QuadPart - PageTable->FileOffset.QuadPart) / PAGE_SIZE; + OldEntry = PageTable->PageEntries[PageIndex]; + if (OldEntry && !IS_SWAP_FROM_SSE(OldEntry)) { + MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry)); + } + if (Entry && !IS_SWAP_FROM_SSE(Entry)) { + MmSetSectionAssociation(PFN_FROM_SSE(Entry), Segment, Offset); + } + PageTable->PageEntries[PageIndex] = Entry; + DPRINT + ("MiSetPageEntrySectionSegment(%p,%08x%08x,%x) %s:%d\n", + Segment, Offset->u.HighPart, Offset->u.LowPart, Entry, file, line); + return STATUS_SUCCESS; +} + +ULONG +NTAPI +_MiGetPageEntryCacheSectionSegment +(PMM_CACHE_SECTION_SEGMENT Segment, + PLARGE_INTEGER Offset, + const char *file, + int line) +{ + LARGE_INTEGER FileOffset; + ULONG PageIndex, Result; + PCACHE_SECTION_PAGE_TABLE PageTable; + + FileOffset.QuadPart = + ROUND_DOWN(Offset->QuadPart, ENTRIES_PER_ELEMENT * PAGE_SIZE); + PageTable = MiSectionPageTableGet(&Segment->PageTable, &FileOffset); + if (!PageTable) return 0; + PageIndex = + (Offset->QuadPart - PageTable->FileOffset.QuadPart) / PAGE_SIZE; + Result = PageTable->PageEntries[PageIndex]; +#if 0 + DPRINTC + ("MiGetPageEntrySectionSegment(%p,%08x%08x) => %x %s:%d\n", + Segment, + FileOffset.u.HighPart, + FileOffset.u.LowPart + PageIndex * PAGE_SIZE, + Result, + file, line); +#endif + return Result; +} + +VOID +NTAPI +MiFreePageTablesSectionSegment +(PMM_CACHE_SECTION_SEGMENT Segment, FREE_SECTION_PAGE_FUN FreePage) +{ + PCACHE_SECTION_PAGE_TABLE Element; + DPRINT("MiFreePageTablesSectionSegment(%p)\n", &Segment->PageTable); + while ((Element = RtlGetElementGenericTable(&Segment->PageTable, 0))) { + DPRINT + ("Delete table for %x -> %08x%08x\n", + Segment, + Element->FileOffset.u.HighPart, + Element->FileOffset.u.LowPart); + if (FreePage) + { + int i; + for (i = 0; i < ENTRIES_PER_ELEMENT; i++) + { + ULONG Entry; + LARGE_INTEGER Offset; + Offset.QuadPart = Element->FileOffset.QuadPart + i * PAGE_SIZE; + Entry = Element->PageEntries[i]; + if (Entry && !IS_SWAP_FROM_SSE(Entry)) + { + DPRINTC("Freeing page %x:%x @ %x\n", Segment, Entry, Offset.LowPart); + FreePage(Segment, &Offset); + } + } + } + DPRINT("Remove memory\n"); + RtlDeleteElementGenericTable(&Segment->PageTable, Element); + } + DPRINT("Done\n"); +} + +PMM_CACHE_SECTION_SEGMENT +NTAPI +MmGetSectionAssociation(PFN_NUMBER Page, PLARGE_INTEGER Offset) +{ + ULONG RawOffset; + PMM_CACHE_SECTION_SEGMENT Segment = NULL; + PCACHE_SECTION_PAGE_TABLE PageTable; + + PageTable = (PCACHE_SECTION_PAGE_TABLE)MmGetSegmentRmap(Page, &RawOffset); + if (PageTable) + { + Segment = PageTable->Segment; + Offset->QuadPart = PageTable->FileOffset.QuadPart + (RawOffset << PAGE_SHIFT); + } + + return(Segment); +} + +NTSTATUS +NTAPI +MmSetSectionAssociation(PFN_NUMBER Page, PMM_CACHE_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset) +{ + PCACHE_SECTION_PAGE_TABLE PageTable; + ULONG ActualOffset; + PageTable = MiSectionPageTableGet(&Segment->PageTable, Offset); + ASSERT(PageTable); + ActualOffset = (ULONG)(Offset->QuadPart - PageTable->FileOffset.QuadPart); + MmInsertRmap(Page, (PEPROCESS)PageTable, (PVOID)(RMAP_SEGMENT_MASK | (ActualOffset >> PAGE_SHIFT))); + return STATUS_SUCCESS; +} diff --git a/ntoskrnl/cache/section/swapout.c b/ntoskrnl/cache/section/swapout.c new file mode 100644 index 00000000000..685104e3d64 --- /dev/null +++ b/ntoskrnl/cache/section/swapout.c @@ -0,0 +1,508 @@ +/* + * Copyright (C) 1998-2005 ReactOS Team (and the authors from the programmers section) + * + * 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. + * + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/section/fault.c + * PURPOSE: Consolidate fault handlers for sections + * + * PROGRAMMERS: Arty + * Rex Jolliff + * David Welch + * Eric Kohl + * Emanuele Aliberti + * Eugene Ingerman + * Casper Hornstrup + * KJK::Hyperion + * Guido de Jong + * Ge van Geldorp + * Royce Mitchell III + * Filip Navara + * Aleksey Bragin + * Jason Filby + * Thomas Weidenmueller + * Gunnar Andre' Dalsnes + * Mike Nordell + * Alex Ionescu + * Gregor Anich + * Steven Edwards + * Herve Poussineau + */ + +/* INCLUDES *****************************************************************/ + +#include +#include "newmm.h" +#define NDEBUG +#include + +#define DPRINTC DPRINT + +extern KEVENT MmWaitPageEvent; +extern FAST_MUTEX RmapListLock; + +FAST_MUTEX GlobalPageOperation; + +PFN_NUMBER +NTAPI +MmWithdrawSectionPage +(PMM_CACHE_SECTION_SEGMENT Segment, PLARGE_INTEGER FileOffset, BOOLEAN *Dirty) +{ + ULONG Entry; + + DPRINT("MmWithdrawSectionPage(%x,%08x%08x,%x)\n", Segment, FileOffset->HighPart, FileOffset->LowPart, Dirty); + + MmLockCacheSectionSegment(Segment); + Entry = MiGetPageEntryCacheSectionSegment(Segment, FileOffset); + + *Dirty = !!IS_DIRTY_SSE(Entry); + + DPRINT("Withdraw %x (%x) of %wZ\n", FileOffset->LowPart, Entry, Segment->FileObject ? &Segment->FileObject->FileName : NULL); + + if (!Entry) + { + DPRINT("Stoeled!\n"); + MmUnlockCacheSectionSegment(Segment); + return 0; + } + else if (MM_IS_WAIT_PTE(Entry)) + { + DPRINT("WAIT\n"); + MmUnlockCacheSectionSegment(Segment); + return MM_WAIT_ENTRY; + } + else if (Entry && !IS_SWAP_FROM_SSE(Entry)) + { + DPRINT("Page %x\n", PFN_FROM_SSE(Entry)); + *Dirty |= (Entry & 2); + MiSetPageEntryCacheSectionSegment(Segment, FileOffset, MAKE_SWAP_SSE(MM_WAIT_ENTRY)); + MmUnlockCacheSectionSegment(Segment); + return PFN_FROM_SSE(Entry); + } + else + { + DPRINT1("SWAP ENTRY?! (%x:%08x%08x)\n", Segment, FileOffset->HighPart, FileOffset->LowPart); + ASSERT(FALSE); + MmUnlockCacheSectionSegment(Segment); + return 0; + } +} + +NTSTATUS +NTAPI +MmFinalizeSectionPageOut +(PMM_CACHE_SECTION_SEGMENT Segment, PLARGE_INTEGER FileOffset, PFN_NUMBER Page, + BOOLEAN Dirty) +{ + NTSTATUS Status = STATUS_SUCCESS; + BOOLEAN WriteZero = FALSE, WritePage = FALSE; + SWAPENTRY Swap = MmGetSavedSwapEntryPage(Page); + + MmLockCacheSectionSegment(Segment); + (void)InterlockedIncrementUL(&Segment->ReferenceCount); + + if (Dirty) + { + DPRINT("Finalize (dirty) Segment %x Page %x\n", Segment, Page); + DPRINT("Segment->FileObject %x\n", Segment->FileObject); + DPRINT("Segment->Flags %x\n", Segment->Flags); + + WriteZero = TRUE; + WritePage = TRUE; + } + else + { + WriteZero = TRUE; + } + + DPRINT("Status %x\n", Status); + + MmUnlockCacheSectionSegment(Segment); + + if (WritePage) + { + DPRINT("MiWriteBackPage(Segment %x FileObject %x Offset %x)\n", Segment, Segment->FileObject, FileOffset->LowPart); + Status = MiWriteBackPage(Segment->FileObject, FileOffset, PAGE_SIZE, Page); + } + + MmLockCacheSectionSegment(Segment); + + if (WriteZero && NT_SUCCESS(Status)) + { + DPRINT("Setting page entry in segment %x:%x to swap %x\n", Segment, FileOffset->LowPart, Swap); + MiSetPageEntryCacheSectionSegment(Segment, FileOffset, Swap ? MAKE_SWAP_SSE(Swap) : 0); + } + else + { + DPRINT("Setting page entry in segment %x:%x to page %x\n", Segment, FileOffset->LowPart, Page); + MiSetPageEntryCacheSectionSegment + (Segment, FileOffset, Page ? (Dirty ? DIRTY_SSE(MAKE_PFN_SSE(Page)) : MAKE_PFN_SSE(Page)) : 0); + } + + if (NT_SUCCESS(Status)) + { + DPRINT("Removing page %x for real\n", Page); + MmSetSavedSwapEntryPage(Page, 0); + // Note: the other one is held by MmTrimUserMemory + if (MmGetReferenceCountPage(Page) != 2) { + DPRINT1("ALERT: Page %x about to be evicted with ref count %d\n", Page, MmGetReferenceCountPage(Page)); + } + MmDereferencePage(Page); + } + + MmUnlockCacheSectionSegment(Segment); + + if (InterlockedDecrementUL(&Segment->ReferenceCount) == 0) + { + MmFinalizeSegment(Segment); + } + + /* Note: Writing may evict the segment... Nothing is guaranteed from here down */ + MiSetPageEvent(Segment, FileOffset->LowPart); + + DPRINT("Status %x\n", Status); + return Status; +} + +NTSTATUS +NTAPI +MmPageOutCacheSection +(PMMSUPPORT AddressSpace, + MEMORY_AREA* MemoryArea, + PVOID Address, + PMM_REQUIRED_RESOURCES Required) +{ + NTSTATUS Status = STATUS_SUCCESS; + ULONG Entry; + BOOLEAN Dirty = FALSE; + PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace); + LARGE_INTEGER TotalOffset; + PMM_CACHE_SECTION_SEGMENT Segment; + PVOID PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE); + + TotalOffset.QuadPart = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress + + MemoryArea->Data.CacheData.ViewOffset.QuadPart; + + Segment = MemoryArea->Data.CacheData.Segment; + + MmLockCacheSectionSegment(Segment); + ASSERT(KeGetCurrentIrql() <= APC_LEVEL); + + Dirty = MmIsDirtyPageRmap(Required->Page[0]); + Entry = MiGetPageEntryCacheSectionSegment(Segment, &TotalOffset); + + if (Dirty) + { + PFN_NUMBER OurPage; + MiSetPageEntryCacheSectionSegment(Segment, &TotalOffset, DIRTY_SSE(Entry)); + MmDeleteRmap(Required->Page[0], Process, Address); + MmDeleteVirtualMapping(Process, Address, FALSE, &Dirty, &OurPage); + ASSERT(OurPage == Required->Page[0]); + } else { + /* Just unmap if the page wasn't dirty */ + PFN_NUMBER OurPage; + MmDeleteRmap(Required->Page[0], Process, Address); + MmDeleteVirtualMapping(Process, Address, FALSE, &Dirty, &OurPage); + DPRINT("OurPage %x ThePage %x\n", OurPage, Required->Page[0]); + ASSERT(OurPage == Required->Page[0]); + } + + if (NT_SUCCESS(Status)) + { + MmDereferencePage(Required->Page[0]); + } + + MmUnlockCacheSectionSegment(Segment); + MiSetPageEvent(Process, Address); + return Status; +} + +NTSTATUS +NTAPI +MmpPageOutPhysicalAddress(PFN_NUMBER Page) +{ + BOOLEAN ProcRef = FALSE; + PFN_NUMBER SectionPage = 0; + PMM_RMAP_ENTRY entry; + PMM_CACHE_SECTION_SEGMENT Segment = NULL; + LARGE_INTEGER FileOffset; + PMEMORY_AREA MemoryArea; + PMMSUPPORT AddressSpace = MmGetKernelAddressSpace(); + BOOLEAN Dirty = FALSE; + PVOID Address = NULL; + PEPROCESS Process = NULL; + NTSTATUS Status = STATUS_SUCCESS; + MM_REQUIRED_RESOURCES Resources = { 0 }; + + DPRINTC("Page out %x (ref ct %x)\n", Page, MmGetReferenceCountPage(Page)); + + ExAcquireFastMutex(&GlobalPageOperation); + if ((Segment = MmGetSectionAssociation(Page, &FileOffset))) + { + DPRINT1("Withdrawing page (%x) %x:%x\n", Page, Segment, FileOffset.LowPart); + SectionPage = MmWithdrawSectionPage(Segment, &FileOffset, &Dirty); + DPRINTC("SectionPage %x\n", SectionPage); + + if (SectionPage == MM_WAIT_ENTRY || SectionPage == 0) + { + DPRINT1("In progress page out %x\n", SectionPage); + ExReleaseFastMutex(&GlobalPageOperation); + return STATUS_UNSUCCESSFUL; + } + else + { + ASSERT(SectionPage == Page); + } + Resources.State = Dirty ? 1 : 0; + } + else + { + DPRINT("No segment association for %x\n", Page); + } + + + Dirty = MmIsDirtyPageRmap(Page); + + DPRINTC("Trying to unmap all instances of %x\n", Page); + ExAcquireFastMutex(&RmapListLock); + entry = MmGetRmapListHeadPage(Page); + + // Entry and Segment might be null here in the case that the page + // is new and is in the process of being swapped in + if (!entry && !Segment) + { + Status = STATUS_UNSUCCESSFUL; + DPRINT1("Page %x is in transit\n", Page); + ExReleaseFastMutex(&RmapListLock); + goto bail; + } + + while (entry != NULL && NT_SUCCESS(Status)) + { + Process = entry->Process; + Address = entry->Address; + + DPRINTC("Process %x Address %x Page %x\n", Process, Address, Page); + + if (RMAP_IS_SEGMENT(Address)) { + entry = entry->Next; + continue; + } + + if (Process && Address < MmSystemRangeStart) + { + // Make sure we don't try to page out part of an exiting process + if (PspIsProcessExiting(Process)) + { + DPRINT("bail\n"); + ExReleaseFastMutex(&RmapListLock); + goto bail; + } + Status = ObReferenceObject(Process); + if (!NT_SUCCESS(Status)) + { + DPRINT("bail\n"); + ExReleaseFastMutex(&RmapListLock); + goto bail; + } + ProcRef = TRUE; + AddressSpace = &Process->Vm; + } + else + { + AddressSpace = MmGetKernelAddressSpace(); + } + ExReleaseFastMutex(&RmapListLock); + + RtlZeroMemory(&Resources, sizeof(Resources)); + + if ((((ULONG_PTR)Address) & 0xFFF) != 0) + { + KeBugCheck(MEMORY_MANAGEMENT); + } + + if (!MmTryToLockAddressSpace(AddressSpace)) + { + DPRINT1("Could not lock address space for process %x\n", MmGetAddressSpaceOwner(AddressSpace)); + Status = STATUS_UNSUCCESSFUL; + goto bail; + } + + do + { + MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address); + if (MemoryArea == NULL || + MemoryArea->DeleteInProgress) + { + Status = STATUS_UNSUCCESSFUL; + MmUnlockAddressSpace(AddressSpace); + DPRINTC("bail\n"); + goto bail; + } + + DPRINTC + ("Type %x (%x -> %x)\n", + MemoryArea->Type, + MemoryArea->StartingAddress, + MemoryArea->EndingAddress); + + Resources.DoAcquisition = NULL; + + Resources.Page[0] = Page; + + ASSERT(KeGetCurrentIrql() <= APC_LEVEL); + + DPRINT("%x:%x, page %x %x\n", Process, Address, Page, Resources.Page[0]); + Status = MmPageOutCacheSection + (AddressSpace, MemoryArea, Address, &Resources); + DPRINT("%x\n", Status); + + ASSERT(KeGetCurrentIrql() <= APC_LEVEL); + + MmUnlockAddressSpace(AddressSpace); + + if (Status == STATUS_SUCCESS + 1) + { + // Wait page ... the other guy has it, so we'll just fail for now + DPRINTC("Wait entry ... can't continue\n"); + Status = STATUS_UNSUCCESSFUL; + goto bail; + } + else if (Status == STATUS_MORE_PROCESSING_REQUIRED) + { + DPRINTC("DoAcquisition %x\n", Resources.DoAcquisition); + Status = Resources.DoAcquisition(AddressSpace, MemoryArea, &Resources); + DPRINTC("Status %x\n", Status); + if (!NT_SUCCESS(Status)) + { + DPRINT1("bail\n"); + goto bail; + } + else Status = STATUS_MM_RESTART_OPERATION; + } + + MmLockAddressSpace(AddressSpace); + } + while (Status == STATUS_MM_RESTART_OPERATION); + Dirty |= Resources.State & 1; // Accumulate dirty + + MmUnlockAddressSpace(AddressSpace); + + if (ProcRef) + { + ObDereferenceObject(Process); + ProcRef = FALSE; + } + + ExAcquireFastMutex(&RmapListLock); + ASSERT(!MM_IS_WAIT_PTE(MmGetPfnForProcess(Process, Address))); + entry = MmGetRmapListHeadPage(Page); + + DPRINTC("Entry %x\n", entry); + } + + ExReleaseFastMutex(&RmapListLock); + +bail: + DPRINTC("BAIL %x\n", Status); + + if (Segment) + { + DPRINTC("About to finalize section page %x (%x:%x) Status %x %s\n", Page, Segment, FileOffset.LowPart, Status, Dirty ? "dirty" : "clean"); + + if (!NT_SUCCESS(Status) || + !NT_SUCCESS + (Status = MmFinalizeSectionPageOut + (Segment, &FileOffset, Page, Dirty))) + { + DPRINTC + ("Failed to page out %x, replacing %x at %x in segment %x\n", + SectionPage, FileOffset.LowPart, Segment); + MmLockCacheSectionSegment(Segment); + MiSetPageEntryCacheSectionSegment(Segment, &FileOffset, Dirty ? MAKE_PFN_SSE(Page) : DIRTY_SSE(MAKE_PFN_SSE(Page))); + MmUnlockCacheSectionSegment(Segment); + } + + // Alas, we had the last reference + ULONG RefCount; + if ((RefCount = InterlockedDecrementUL(&Segment->ReferenceCount)) == 0) + MmFinalizeSegment(Segment); + } + + if (ProcRef) + { + DPRINTC("Dereferencing process...\n"); + ObDereferenceObject(Process); + } + + ExReleaseFastMutex(&GlobalPageOperation); + DPRINTC("%s %x %x\n", NT_SUCCESS(Status) ? "Evicted" : "Spared", Page, Status); + return NT_SUCCESS(Status) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; +} + +ULONG +NTAPI +MiCacheEvictPages(PVOID BaseAddress, ULONG Target) +{ + ULONG i, Entry, Result = 0; + NTSTATUS Status; + PFN_NUMBER Page; + PMEMORY_AREA MemoryArea; + LARGE_INTEGER Offset; + PMM_CACHE_SECTION_SEGMENT Segment; + + MmLockAddressSpace(MmGetKernelAddressSpace()); + MemoryArea = MmLocateMemoryAreaByAddress + (MmGetKernelAddressSpace(), + BaseAddress); + + ASSERT(MemoryArea); + ASSERT(MemoryArea->Type == MEMORY_AREA_CACHE); + + Segment = MemoryArea->Data.CacheData.Segment; + + ASSERT(Segment); + + MmLockCacheSectionSegment(Segment); + + for (i = 0; + i < Segment->Length.QuadPart - + MemoryArea->Data.CacheData.ViewOffset.QuadPart && + Result < Target; + i += PAGE_SIZE) { + Offset.QuadPart = MemoryArea->Data.CacheData.ViewOffset.QuadPart + i; + Entry = MiGetPageEntryCacheSectionSegment(Segment, &Offset); + if (Entry && !IS_SWAP_FROM_SSE(Entry)) { + Page = PFN_FROM_SSE(Entry); + MmReferencePage(Page); + MmUnlockCacheSectionSegment(Segment); + MmUnlockAddressSpace(MmGetKernelAddressSpace()); + Status = MmpPageOutPhysicalAddress(Page); + if (NT_SUCCESS(Status)) + Result++; + MmLockCacheSectionSegment(Segment); + MmLockAddressSpace(MmGetKernelAddressSpace()); + MmReleasePageMemoryConsumer(MC_CACHE, Page); + } + } + + MmUnlockCacheSectionSegment(Segment); + MmUnlockAddressSpace(MmGetKernelAddressSpace()); + + return Result; +} + diff --git a/ntoskrnl/cc/cacheman.c b/ntoskrnl/cc/cacheman.c index a9459d7988d..78d23e737cd 100644 --- a/ntoskrnl/cc/cacheman.c +++ b/ntoskrnl/cc/cacheman.c @@ -19,6 +19,7 @@ PFSN_PREFETCHER_GLOBALS CcPfGlobals; VOID NTAPI +INIT_FUNCTION CcPfInitializePrefetcher(VOID) { /* Notify debugger */ @@ -36,6 +37,7 @@ CcPfInitializePrefetcher(VOID) BOOLEAN NTAPI +INIT_FUNCTION CcInitializeCacheManager(VOID) { CcInitView(); diff --git a/ntoskrnl/cc/copy.c b/ntoskrnl/cc/copy.c index 8e19ba82d36..17702665945 100644 --- a/ntoskrnl/cc/copy.c +++ b/ntoskrnl/cc/copy.c @@ -41,6 +41,8 @@ CcInitCacheZeroPage(VOID) { NTSTATUS Status; + MI_SET_USAGE(MI_USAGE_CACHE); + //MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName); Status = MmRequestPageMemoryConsumer(MC_SYSTEM, TRUE, &CcZeroPage); if (!NT_SUCCESS(Status)) { diff --git a/ntoskrnl/cc/view.c b/ntoskrnl/cc/view.c index fcdefc4d032..a17e2c942fe 100644 --- a/ntoskrnl/cc/view.c +++ b/ntoskrnl/cc/view.c @@ -703,6 +703,18 @@ CcRosCreateCacheSegment(PBCB Bcb, #endif /* Create a virtual mapping for this memory area */ + MI_SET_USAGE(MI_USAGE_CACHE); +#if MI_TRACE_PFNS + PWCHAR pos = NULL; + ULONG len = 0; + if ((Bcb->FileObject) && (Bcb->FileObject->FileName.Buffer)) + { + pos = wcsrchr(Bcb->FileObject->FileName.Buffer, '\\'); + len = wcslen(pos) * sizeof(WCHAR); + if (pos) snprintf(MI_PFN_CURRENT_PROCESS_NAME, min(16, len), "%S", pos); + } +#endif + MmMapMemoryArea(current->BaseAddress, Bcb->CacheSegmentSize, MC_CACHE, PAGE_READWRITE); diff --git a/ntoskrnl/config/cmalloc.c b/ntoskrnl/config/cmalloc.c index 97dfc1a6e26..65028838e13 100644 --- a/ntoskrnl/config/cmalloc.c +++ b/ntoskrnl/config/cmalloc.c @@ -25,6 +25,7 @@ LIST_ENTRY CmpFreeDelayItemsListHead; VOID NTAPI +INIT_FUNCTION CmpInitCmPrivateAlloc(VOID) { /* Make sure we didn't already do this */ @@ -39,6 +40,7 @@ CmpInitCmPrivateAlloc(VOID) VOID NTAPI +INIT_FUNCTION CmpInitCmPrivateDelayAlloc(VOID) { /* Initialize the delay allocation list and lock */ diff --git a/ntoskrnl/config/cmboot.c b/ntoskrnl/config/cmboot.c index 50c6815866f..1416c4dfe01 100644 --- a/ntoskrnl/config/cmboot.c +++ b/ntoskrnl/config/cmboot.c @@ -17,6 +17,7 @@ HCELL_INDEX NTAPI +INIT_FUNCTION CmpFindControlSet(IN PHHIVE SystemHive, IN HCELL_INDEX RootCell, IN PUNICODE_STRING SelectKeyName, @@ -126,6 +127,7 @@ CmpFindControlSet(IN PHHIVE SystemHive, ULONG NTAPI +INIT_FUNCTION CmpFindTagIndex(IN PHHIVE Hive, IN HCELL_INDEX TagCell, IN HCELL_INDEX GroupOrderCell, @@ -175,6 +177,7 @@ CmpFindTagIndex(IN PHHIVE Hive, BOOLEAN NTAPI +INIT_FUNCTION CmpAddDriverToList(IN PHHIVE Hive, IN HCELL_INDEX DriverCell, IN HCELL_INDEX GroupOrderCell, @@ -341,6 +344,7 @@ CmpAddDriverToList(IN PHHIVE Hive, BOOLEAN NTAPI +INIT_FUNCTION CmpIsLoadType(IN PHHIVE Hive, IN HCELL_INDEX Cell, IN SERVICE_LOAD_TYPE LoadType) @@ -371,6 +375,7 @@ CmpIsLoadType(IN PHHIVE Hive, BOOLEAN NTAPI +INIT_FUNCTION CmpFindDrivers(IN PHHIVE Hive, IN HCELL_INDEX ControlSet, IN SERVICE_LOAD_TYPE LoadType, @@ -465,6 +470,7 @@ CmpFindDrivers(IN PHHIVE Hive, BOOLEAN NTAPI +INIT_FUNCTION CmpDoSort(IN PLIST_ENTRY DriverListHead, IN PUNICODE_STRING OrderList) { @@ -521,6 +527,7 @@ CmpDoSort(IN PLIST_ENTRY DriverListHead, BOOLEAN NTAPI +INIT_FUNCTION CmpSortDriverList(IN PHHIVE Hive, IN HCELL_INDEX ControlSet, IN PLIST_ENTRY DriverListHead) @@ -569,6 +576,7 @@ CmpSortDriverList(IN PHHIVE Hive, BOOLEAN NTAPI +INIT_FUNCTION CmpOrderGroup(IN PBOOT_DRIVER_NODE StartNode, IN PBOOT_DRIVER_NODE EndNode) { @@ -631,6 +639,7 @@ CmpOrderGroup(IN PBOOT_DRIVER_NODE StartNode, BOOLEAN NTAPI +INIT_FUNCTION CmpResolveDriverDependencies(IN PLIST_ENTRY DriverListHead) { PLIST_ENTRY NextEntry; diff --git a/ntoskrnl/config/cmconfig.c b/ntoskrnl/config/cmconfig.c index 7aae14da7a6..f483d700983 100644 --- a/ntoskrnl/config/cmconfig.c +++ b/ntoskrnl/config/cmconfig.c @@ -16,6 +16,7 @@ NTSTATUS NTAPI +INIT_FUNCTION CmpInitializeRegistryNode(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry, IN HANDLE NodeHandle, OUT PHANDLE NewHandle, @@ -195,6 +196,7 @@ CmpInitializeRegistryNode(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry, NTSTATUS NTAPI +INIT_FUNCTION CmpSetupConfigurationTree(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry, IN HANDLE ParentHandle, IN INTERFACE_TYPE InterfaceType, @@ -311,6 +313,7 @@ CmpSetupConfigurationTree(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry, NTSTATUS NTAPI +INIT_FUNCTION CmpInitializeHardwareConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { NTSTATUS Status; @@ -390,8 +393,3 @@ CmpInitializeHardwareConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock) NtClose(KeyHandle); return Status; } - - - - - diff --git a/ntoskrnl/config/cmcontrl.c b/ntoskrnl/config/cmcontrl.c index 8d3459ba72e..1e481e455c0 100644 --- a/ntoskrnl/config/cmcontrl.c +++ b/ntoskrnl/config/cmcontrl.c @@ -18,6 +18,7 @@ LANGID NTAPI +INIT_FUNCTION CmpConvertLangId(IN LPWSTR Name, IN ULONG NameLength) { @@ -68,6 +69,7 @@ CmpConvertLangId(IN LPWSTR Name, HCELL_INDEX NTAPI +INIT_FUNCTION CmpWalkPath(IN PHHIVE SystemHive, IN HCELL_INDEX ParentCell, IN LPWSTR Path) @@ -98,6 +100,7 @@ CmpWalkPath(IN PHHIVE SystemHive, VOID NTAPI +INIT_FUNCTION CmGetSystemControlValues(IN PVOID SystemHiveData, IN PCM_SYSTEM_CONTROL_VECTOR ControlVector) { diff --git a/ntoskrnl/config/cmdata.c b/ntoskrnl/config/cmdata.c index 6dbf2a0380d..a4e7acb6590 100644 --- a/ntoskrnl/config/cmdata.c +++ b/ntoskrnl/config/cmdata.c @@ -65,7 +65,7 @@ ULONG CmpTypeCount[MaximumType + 1]; HANDLE CmpRegistryRootHandle; -UNICODE_STRING CmClassName[MaximumClass + 1] = +INIT_FUNCTION UNICODE_STRING CmClassName[MaximumClass + 1] = { RTL_CONSTANT_STRING(L"System"), RTL_CONSTANT_STRING(L"Processor"), @@ -77,7 +77,7 @@ UNICODE_STRING CmClassName[MaximumClass + 1] = RTL_CONSTANT_STRING(L"Undefined") }; -UNICODE_STRING CmTypeName[MaximumType + 1] = +INIT_FUNCTION UNICODE_STRING CmTypeName[MaximumType + 1] = { RTL_CONSTANT_STRING(L"System"), RTL_CONSTANT_STRING(L"CentralProcessor"), @@ -123,7 +123,7 @@ UNICODE_STRING CmTypeName[MaximumType + 1] = RTL_CONSTANT_STRING(L"Undefined") }; -CMP_MF_TYPE CmpMultifunctionTypes[] = +INIT_FUNCTION CMP_MF_TYPE CmpMultifunctionTypes[] = { {"ISA", Isa, 0}, {"MCA", MicroChannel, 0}, @@ -136,7 +136,7 @@ CMP_MF_TYPE CmpMultifunctionTypes[] = {NULL, Internal, 0} }; -CM_SYSTEM_CONTROL_VECTOR CmControlVector[] = +INIT_FUNCTION CM_SYSTEM_CONTROL_VECTOR CmControlVector[] = { { L"Session Manager", diff --git a/ntoskrnl/config/cmdelay.c b/ntoskrnl/config/cmdelay.c index 015aa2f991f..58ac9a67ce8 100644 --- a/ntoskrnl/config/cmdelay.c +++ b/ntoskrnl/config/cmdelay.c @@ -185,6 +185,7 @@ CmpDelayCloseWorker(IN PVOID Context) VOID NTAPI +INIT_FUNCTION CmpInitializeDelayedCloseTable(VOID) { @@ -259,6 +260,7 @@ CmpDelayDerefKCBWorker(IN PVOID Context) VOID NTAPI +INIT_FUNCTION CmpInitDelayDerefKCBEngine(VOID) { /* Initialize lock and list */ diff --git a/ntoskrnl/config/cmhook.c b/ntoskrnl/config/cmhook.c index 6ccd751f3ed..cf12c26404a 100644 --- a/ntoskrnl/config/cmhook.c +++ b/ntoskrnl/config/cmhook.c @@ -34,6 +34,7 @@ typedef struct _REGISTRY_CALLBACK VOID NTAPI +INIT_FUNCTION CmpInitCallback(VOID) { ULONG i; diff --git a/ntoskrnl/config/cmkcbncb.c b/ntoskrnl/config/cmkcbncb.c index a123a3cee56..1c093403c48 100644 --- a/ntoskrnl/config/cmkcbncb.c +++ b/ntoskrnl/config/cmkcbncb.c @@ -22,6 +22,7 @@ PCM_NAME_HASH_TABLE_ENTRY CmpNameCacheTable; VOID NTAPI +INIT_FUNCTION CmpInitializeCache(VOID) { ULONG Length, i; diff --git a/ntoskrnl/config/cmse.c b/ntoskrnl/config/cmse.c index 4ee2335c064..019a14c8868 100644 --- a/ntoskrnl/config/cmse.c +++ b/ntoskrnl/config/cmse.c @@ -18,6 +18,7 @@ PSECURITY_DESCRIPTOR NTAPI +INIT_FUNCTION CmpHiveRootSecurityDescriptor(VOID) { NTSTATUS Status; diff --git a/ntoskrnl/config/cmsysini.c b/ntoskrnl/config/cmsysini.c index 779d902b650..f144e84a0fa 100644 --- a/ntoskrnl/config/cmsysini.c +++ b/ntoskrnl/config/cmsysini.c @@ -308,6 +308,7 @@ CmpInitHiveFromFile(IN PCUNICODE_STRING HiveName, NTSTATUS NTAPI +INIT_FUNCTION CmpSetSystemValues(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { OBJECT_ATTRIBUTES ObjectAttributes; @@ -361,6 +362,7 @@ Quickie: NTSTATUS NTAPI +INIT_FUNCTION CmpCreateControlSet(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { UNICODE_STRING ConfigName = RTL_CONSTANT_STRING(L"Control\\IDConfigDB"); @@ -689,6 +691,7 @@ CmpLinkHiveToMaster(IN PUNICODE_STRING LinkName, BOOLEAN NTAPI +INIT_FUNCTION CmpInitializeSystemHive(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { PVOID HiveBase; @@ -817,6 +820,7 @@ CmpInitializeSystemHive(IN PLOADER_PARAMETER_BLOCK LoaderBlock) NTSTATUS NTAPI +INIT_FUNCTION CmpCreateObjectTypes(VOID) { OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; @@ -849,6 +853,7 @@ CmpCreateObjectTypes(VOID) BOOLEAN NTAPI +INIT_FUNCTION CmpCreateRootNode(IN PHHIVE Hive, IN PCWSTR Name, OUT PHCELL_INDEX Index) @@ -909,6 +914,7 @@ CmpCreateRootNode(IN PHHIVE Hive, BOOLEAN NTAPI +INIT_FUNCTION CmpCreateRegistryRoot(VOID) { UNICODE_STRING KeyName; @@ -1366,6 +1372,7 @@ CmpInitializeHiveList(IN USHORT Flag) BOOLEAN NTAPI +INIT_FUNCTION CmInitSystem1(VOID) { OBJECT_ATTRIBUTES ObjectAttributes; @@ -1577,6 +1584,7 @@ CmInitSystem1(VOID) VOID NTAPI +INIT_FUNCTION CmpFreeDriverList(IN PHHIVE Hive, IN PLIST_ENTRY DriverList) { @@ -1625,6 +1633,7 @@ CmpFreeDriverList(IN PHHIVE Hive, PUNICODE_STRING* NTAPI +INIT_FUNCTION CmGetSystemDriverList(VOID) { LIST_ENTRY DriverList; diff --git a/ntoskrnl/ex/handle.c b/ntoskrnl/ex/handle.c index 548163d0099..17ae2814550 100644 --- a/ntoskrnl/ex/handle.c +++ b/ntoskrnl/ex/handle.c @@ -23,6 +23,7 @@ EX_PUSH_LOCK HandleTableListLock; VOID NTAPI +INIT_FUNCTION ExpInitializeHandleTables(VOID) { /* Initialize the list of handle tables and the lock */ diff --git a/ntoskrnl/ex/hdlsterm.c b/ntoskrnl/ex/hdlsterm.c index a47cd006152..ce34699fcb2 100644 --- a/ntoskrnl/ex/hdlsterm.c +++ b/ntoskrnl/ex/hdlsterm.c @@ -69,6 +69,7 @@ HdlspEnableTerminal( VOID NTAPI +INIT_FUNCTION HeadlessInit( IN PLOADER_PARAMETER_BLOCK LoaderBlock ) diff --git a/ntoskrnl/ex/init.c b/ntoskrnl/ex/init.c index 5b448efbbf1..ee7cc3c2f55 100644 --- a/ntoskrnl/ex/init.c +++ b/ntoskrnl/ex/init.c @@ -87,6 +87,7 @@ BOOLEAN ExpRealTimeIsUniversal; NTSTATUS NTAPI +INIT_FUNCTION ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { UNICODE_STRING LinkName; @@ -198,6 +199,7 @@ ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock) VOID NTAPI +INIT_FUNCTION ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { LARGE_INTEGER SectionSize; @@ -329,6 +331,7 @@ ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock) } /* Copy the codepage data in its new location. */ + ASSERT(SectionBase > MmSystemRangeStart); RtlCopyMemory(SectionBase, ExpNlsTableBase, ExpNlsTableSize); /* Free the previously allocated buffer and set the new location */ @@ -372,6 +375,7 @@ ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock) VOID NTAPI +INIT_FUNCTION ExpLoadInitialProcess(IN PINIT_BUFFER InitBuffer, OUT PRTL_USER_PROCESS_PARAMETERS *ProcessParameters, OUT PCHAR *ProcessEnvironment) @@ -592,6 +596,7 @@ ExpLoadInitialProcess(IN PINIT_BUFFER InitBuffer, ULONG NTAPI +INIT_FUNCTION ExComputeTickCountMultiplier(IN ULONG ClockIncrement) { ULONG MsRemainder = 0, MsIncrement; @@ -624,6 +629,7 @@ ExComputeTickCountMultiplier(IN ULONG ClockIncrement) BOOLEAN NTAPI +INIT_FUNCTION ExpInitSystemPhase0(VOID) { /* Initialize EXRESOURCE Support */ @@ -646,6 +652,7 @@ ExpInitSystemPhase0(VOID) BOOLEAN NTAPI +INIT_FUNCTION ExpInitSystemPhase1(VOID) { /* Initialize worker threads */ @@ -683,6 +690,7 @@ ExpInitSystemPhase1(VOID) BOOLEAN NTAPI +INIT_FUNCTION ExInitSystem(VOID) { /* Check the initialization phase */ @@ -708,6 +716,7 @@ ExInitSystem(VOID) BOOLEAN NTAPI +INIT_FUNCTION ExpIsLoaderValid(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { PLOADER_PARAMETER_EXTENSION Extension; @@ -733,6 +742,7 @@ ExpIsLoaderValid(IN PLOADER_PARAMETER_BLOCK LoaderBlock) VOID NTAPI +INIT_FUNCTION ExpLoadBootSymbols(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { ULONG i = 0; @@ -825,6 +835,7 @@ ExpLoadBootSymbols(IN PLOADER_PARAMETER_BLOCK LoaderBlock) VOID NTAPI +INIT_FUNCTION ExBurnMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN ULONG PagesToDestroy, IN TYPE_OF_MEMORY MemoryType) @@ -870,6 +881,7 @@ ExBurnMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock, VOID NTAPI +INIT_FUNCTION ExpInitializeExecutive(IN ULONG Cpu, IN PLOADER_PARAMETER_BLOCK LoaderBlock) { @@ -1280,6 +1292,7 @@ ExpInitializeExecutive(IN ULONG Cpu, VOID NTAPI +INIT_FUNCTION Phase1InitializationDiscard(IN PVOID Context) { PLOADER_PARAMETER_BLOCK LoaderBlock = Context; @@ -1898,6 +1911,7 @@ Phase1InitializationDiscard(IN PVOID Context) InbvUpdateProgressBar(90); /* Launch initial process */ + DPRINT1("Free non-cache pages: %lx\n", MmAvailablePages + MiMemoryConsumers[MC_CACHE].PagesUsed); ProcessInfo = &InitBuffer->ProcessInfo; ExpLoadInitialProcess(InitBuffer, &ProcessParameters, &Environment); @@ -1944,6 +1958,7 @@ Phase1InitializationDiscard(IN PVOID Context) /* Free the boot buffer */ ExFreePool(InitBuffer); + DPRINT1("Free non-cache pages: %lx\n", MmAvailablePages + MiMemoryConsumers[MC_CACHE].PagesUsed); } VOID diff --git a/ntoskrnl/ex/lookas.c b/ntoskrnl/ex/lookas.c index 7979e739e06..a82ececef68 100644 --- a/ntoskrnl/ex/lookas.c +++ b/ntoskrnl/ex/lookas.c @@ -31,6 +31,7 @@ GENERAL_LOOKASIDE ExpSmallPagedPoolLookasideLists[MAXIMUM_PROCESSORS]; VOID NTAPI +INIT_FUNCTION ExInitializeSystemLookasideList(IN PGENERAL_LOOKASIDE List, IN POOL_TYPE Type, IN ULONG Size, @@ -58,6 +59,7 @@ ExInitializeSystemLookasideList(IN PGENERAL_LOOKASIDE List, VOID NTAPI +INIT_FUNCTION ExInitPoolLookasidePointers(VOID) { ULONG i; @@ -87,6 +89,7 @@ ExInitPoolLookasidePointers(VOID) VOID NTAPI +INIT_FUNCTION ExpInitLookasideLists() { ULONG i; diff --git a/ntoskrnl/ex/pushlock.c b/ntoskrnl/ex/pushlock.c index f426d3d6c52..18ef8d66574 100644 --- a/ntoskrnl/ex/pushlock.c +++ b/ntoskrnl/ex/pushlock.c @@ -41,6 +41,7 @@ ULONG ExPushLockSpinCount = 0; *--*/ VOID NTAPI +INIT_FUNCTION ExpInitializePushLocks(VOID) { #ifdef CONFIG_SMP diff --git a/ntoskrnl/ex/xipdisp.c b/ntoskrnl/ex/xipdisp.c index aa739c2dfa8..c3249f43383 100644 --- a/ntoskrnl/ex/xipdisp.c +++ b/ntoskrnl/ex/xipdisp.c @@ -17,6 +17,7 @@ PMEMORY_ALLOCATION_DESCRIPTOR NTAPI +INIT_FUNCTION XIPpFindMemoryDescriptor(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { PLIST_ENTRY NextEntry; @@ -40,6 +41,7 @@ XIPpFindMemoryDescriptor(IN PLOADER_PARAMETER_BLOCK LoaderBlock) VOID NTAPI +INIT_FUNCTION XIPInit(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { PCHAR CommandLine, XipBoot, XipRom, XipMegs, XipVerbose, XipRam; diff --git a/ntoskrnl/fsrtl/faulttol.c b/ntoskrnl/fsrtl/faulttol.c index ca66fab20f4..ea868adbb3e 100644 --- a/ntoskrnl/fsrtl/faulttol.c +++ b/ntoskrnl/fsrtl/faulttol.c @@ -17,7 +17,7 @@ /*++ * @name FsRtlBalanceReads - * @implemented NT 4.0 + * @implemented NT 5.2 * * The FsRtlBalanceReads routine sends an IRP to an FTDISK Driver * requesting the driver to balance read requests across a mirror set. @@ -65,6 +65,8 @@ FsRtlBalanceReads(PDEVICE_OBJECT TargetDevice) KernelMode, FALSE, NULL); + ASSERT(Status == STATUS_SUCCESS); + /* Return Status */ Status = IoStatusBlock.Status; } @@ -75,7 +77,7 @@ FsRtlBalanceReads(PDEVICE_OBJECT TargetDevice) /*++ * @name FsRtlSyncVolumes - * @implemented NT 4.0 + * @implemented NT 5.2 * * The FsRtlSyncVolumes routine is deprecated. * diff --git a/ntoskrnl/fsrtl/fsrtlpc.c b/ntoskrnl/fsrtl/fsrtlpc.c index 9e018e44e20..6c59f4f691f 100644 --- a/ntoskrnl/fsrtl/fsrtlpc.c +++ b/ntoskrnl/fsrtl/fsrtlpc.c @@ -155,6 +155,7 @@ PUCHAR FsRtlLegalAnsiCharacterArray = LegalAnsiCharacterArray; BOOLEAN NTAPI +INIT_FUNCTION FsRtlInitSystem(VOID) { ULONG i; diff --git a/ntoskrnl/inbv/inbv.c b/ntoskrnl/inbv/inbv.c index 280e918bd83..98aff194e3f 100644 --- a/ntoskrnl/inbv/inbv.c +++ b/ntoskrnl/inbv/inbv.c @@ -28,6 +28,7 @@ BT_PROGRESS_INDICATOR InbvProgressIndicator = {0, 25, 0}; PVOID NTAPI +INIT_FUNCTION FindBitmapResource(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN ULONG ResourceId) { @@ -92,6 +93,7 @@ FindBitmapResource(IN PLOADER_PARAMETER_BLOCK LoaderBlock, BOOLEAN NTAPI +INIT_FUNCTION InbvDriverInitialize(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN ULONG Count) { @@ -174,6 +176,7 @@ InbvReleaseLock(VOID) VOID NTAPI +INIT_FUNCTION InbvEnableBootDriver(IN BOOLEAN Enable) { /* Check if we're installed */ @@ -408,6 +411,7 @@ InbvSolidColorFill(IN ULONG Left, VOID NTAPI +INIT_FUNCTION InbvUpdateProgressBar(IN ULONG Progress) { ULONG FillCount, BoundedProgress; @@ -523,6 +527,7 @@ InbvSetProgressBarSubset(IN ULONG Floor, VOID NTAPI +INIT_FUNCTION InbvIndicateProgress(VOID) { ULONG Percentage; @@ -570,6 +575,7 @@ NtDisplayString(IN PUNICODE_STRING DisplayString) VOID NTAPI +INIT_FUNCTION DisplayBootBitmap(IN BOOLEAN SosMode) { PVOID Header, Band, Text, Screen; @@ -705,6 +711,7 @@ DisplayBootBitmap(IN BOOLEAN SosMode) VOID NTAPI +INIT_FUNCTION FinalizeBootLogo(VOID) { /* Acquire lock and check the display state */ diff --git a/ntoskrnl/include/internal/i386/mm.h b/ntoskrnl/include/internal/i386/mm.h index 1014884b099..f02cc787a71 100644 --- a/ntoskrnl/include/internal/i386/mm.h +++ b/ntoskrnl/include/internal/i386/mm.h @@ -84,7 +84,11 @@ PULONG MmGetPageDirectory(VOID); #define MI_MAPPING_RANGE_START (ULONG)HYPER_SPACE #define MI_MAPPING_RANGE_END (MI_MAPPING_RANGE_START + \ MI_HYPERSPACE_PTES * PAGE_SIZE) -#define MI_ZERO_PTE (PMMPTE)(MI_MAPPING_RANGE_END + \ +#define MI_DUMMY_PTE (PMMPTE)(MI_MAPPING_RANGE_END + \ + PAGE_SIZE) +#define MI_VAD_BITMAP (PMMPTE)(MI_DUMMY_PTE + \ + PAGE_SIZE) +#define MI_WORKING_SET_LIST (PMMPTE)(MI_VAD_BITMAP + \ PAGE_SIZE) /* On x86, these two are the same */ diff --git a/ntoskrnl/include/internal/ke.h b/ntoskrnl/include/internal/ke.h index 45d47d1612a..56f3ee013c2 100644 --- a/ntoskrnl/include/internal/ke.h +++ b/ntoskrnl/include/internal/ke.h @@ -298,8 +298,8 @@ KeReadStateThread(IN PKTHREAD Thread); BOOLEAN FASTCALL KiSwapContext( - IN PKTHREAD CurrentThread, - IN PKTHREAD NewThread + IN KIRQL WaitIrql, + IN PKTHREAD CurrentThread ); VOID diff --git a/ntoskrnl/include/internal/mm.h b/ntoskrnl/include/internal/mm.h index 25360af7416..7499571f550 100644 --- a/ntoskrnl/include/internal/mm.h +++ b/ntoskrnl/include/internal/mm.h @@ -248,6 +248,8 @@ typedef struct _ROS_SECTION_OBJECT }; } ROS_SECTION_OBJECT, *PROS_SECTION_OBJECT; +struct _MM_CACHE_SECTION_SEGMENT; + typedef struct _MEMORY_AREA { PVOID StartingAddress; @@ -270,6 +272,11 @@ typedef struct _MEMORY_AREA PMM_SECTION_SEGMENT Segment; LIST_ENTRY RegionListHead; } SectionData; + struct + { + LARGE_INTEGER ViewOffset; + struct _MM_CACHE_SECTION_SEGMENT *Segment; + } CacheData; struct { LIST_ENTRY RegionListHead; @@ -288,6 +295,43 @@ typedef struct _MM_RMAP_ENTRY } MM_RMAP_ENTRY, *PMM_RMAP_ENTRY; +#if MI_TRACE_PFNS +extern ULONG MI_PFN_CURRENT_USAGE; +extern CHAR MI_PFN_CURRENT_PROCESS_NAME[16]; +#define MI_SET_USAGE(x) MI_PFN_CURRENT_USAGE = x +#define MI_SET_PROCESS2(x) memcpy(MI_PFN_CURRENT_PROCESS_NAME, x, 16) +#else +#define MI_SET_USAGE(x) +#define MI_SET_PROCESS2(x) +#endif + +typedef enum _MI_PFN_USAGES +{ + MI_USAGE_NOT_SET = 0, + MI_USAGE_PAGED_POOL, + MI_USAGE_NONPAGED_POOL, + MI_USAGE_NONPAGED_POOL_EXPANSION, + MI_USAGE_KERNEL_STACK, + MI_USAGE_KERNEL_STACK_EXPANSION, + MI_USAGE_SYSTEM_PTE, + MI_USAGE_VAD, + MI_USAGE_PEB_TEB, + MI_USAGE_SECTION, + MI_USAGE_PAGE_TABLE, + MI_USAGE_PAGE_DIRECTORY, + MI_USAGE_LEGACY_PAGE_DIRECTORY, + MI_USAGE_DRIVER_PAGE, + MI_USAGE_CONTINOUS_ALLOCATION, + MI_USAGE_MDL, + MI_USAGE_DEMAND_ZERO, + MI_USAGE_ZERO_LOOP, + MI_USAGE_CACHE, + MI_USAGE_PFN_DATABASE, + MI_USAGE_BOOT_DRIVER, + MI_USAGE_INIT_MEMORY, + MI_USAGE_FREE_PAGE +} MI_PFN_USAGES; + // // These two mappings are actually used by Windows itself, based on the ASSERTS // @@ -355,6 +399,10 @@ typedef struct _MMPFN ULONG_PTR MustBeCached:1; }; } u4; +#if MI_TRACE_PFNS + MI_PFN_USAGES PfnUsage; + CHAR ProcessName[16]; +#endif } MMPFN, *PMMPFN; extern PMMPFN MmPfnDatabase; @@ -1143,8 +1191,8 @@ MmInitializePageList( VOID NTAPI -MmDumpPfnDatabase( - VOID +MmDumpArmPfnDatabase( + IN BOOLEAN StatusOnly ); PFN_NUMBER @@ -1286,6 +1334,14 @@ VOID NTAPI MmRawDeleteVirtualMapping(PVOID Address); + +VOID +NTAPI +MmGetPageFileMapping( + struct _EPROCESS *Process, + PVOID Address, + SWAPENTRY* SwapEntry); + VOID NTAPI MmDeletePageFileMapping( diff --git a/ntoskrnl/include/internal/ps.h b/ntoskrnl/include/internal/ps.h index 1d55e3068ff..bf18cf818b3 100644 --- a/ntoskrnl/include/internal/ps.h +++ b/ntoskrnl/include/internal/ps.h @@ -399,6 +399,10 @@ PsChargeProcessPageFileQuota( IN SIZE_T Amount ); +BOOLEAN +NTAPI +PspIsProcessExiting(IN PEPROCESS Process); + // // Global data inside the Process Manager // diff --git a/ntoskrnl/io/iomgr/arcname.c b/ntoskrnl/io/iomgr/arcname.c index 17d242ef5c5..a49fdfc20ab 100644 --- a/ntoskrnl/io/iomgr/arcname.c +++ b/ntoskrnl/io/iomgr/arcname.c @@ -785,6 +785,7 @@ Cleanup: NTSTATUS NTAPI +INIT_FUNCTION IopReassignSystemRoot(IN PLOADER_PARAMETER_BLOCK LoaderBlock, OUT PANSI_STRING NtBootPath) { diff --git a/ntoskrnl/io/iomgr/driver.c b/ntoskrnl/io/iomgr/driver.c index 1f5832c65ce..b0d35fa8fdd 100644 --- a/ntoskrnl/io/iomgr/driver.c +++ b/ntoskrnl/io/iomgr/driver.c @@ -709,6 +709,7 @@ MiResolveImageReferences(IN PVOID ImageBase, // NTSTATUS NTAPI +INIT_FUNCTION LdrProcessDriverModule(PLDR_DATA_TABLE_ENTRY LdrEntry, PUNICODE_STRING FileName, PLDR_DATA_TABLE_ENTRY *ModuleObject) @@ -784,6 +785,7 @@ LdrProcessDriverModule(PLDR_DATA_TABLE_ENTRY LdrEntry, NTSTATUS NTAPI +INIT_FUNCTION IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry) { PDEVICE_NODE DeviceNode; @@ -870,6 +872,7 @@ IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry) */ VOID FASTCALL +INIT_FUNCTION IopInitializeBootDrivers(VOID) { PLIST_ENTRY ListHead, NextEntry, NextEntry2; @@ -1061,6 +1064,7 @@ IopInitializeBootDrivers(VOID) VOID FASTCALL +INIT_FUNCTION IopInitializeSystemDrivers(VOID) { PUNICODE_STRING *DriverList, *SavedList; diff --git a/ntoskrnl/io/iomgr/ramdisk.c b/ntoskrnl/io/iomgr/ramdisk.c index eec4f8d801a..3ca2d0351d8 100644 --- a/ntoskrnl/io/iomgr/ramdisk.c +++ b/ntoskrnl/io/iomgr/ramdisk.c @@ -24,6 +24,7 @@ NTSTATUS NTAPI +INIT_FUNCTION IopStartRamdisk(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor; diff --git a/ntoskrnl/io/iomgr/rawfs.c b/ntoskrnl/io/iomgr/rawfs.c index 32c396f712e..143f486977c 100755 --- a/ntoskrnl/io/iomgr/rawfs.c +++ b/ntoskrnl/io/iomgr/rawfs.c @@ -1076,6 +1076,7 @@ RawUnload(IN PDRIVER_OBJECT DriverObject) NTSTATUS NTAPI +INIT_FUNCTION RawFsDriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { diff --git a/ntoskrnl/io/pnpmgr/pnpinit.c b/ntoskrnl/io/pnpmgr/pnpinit.c index deced326832..7811632dd5c 100644 --- a/ntoskrnl/io/pnpmgr/pnpinit.c +++ b/ntoskrnl/io/pnpmgr/pnpinit.c @@ -44,6 +44,7 @@ IopInitializeArbiters(VOID) NTSTATUS NTAPI +INIT_FUNCTION PiInitCacheGroupInformation(VOID) { HANDLE KeyHandle; @@ -355,6 +356,7 @@ PipCallDriverAddDevice(IN PDEVICE_NODE DeviceNode, NTSTATUS NTAPI +INIT_FUNCTION IopInitializePlugPlayServices(VOID) { NTSTATUS Status; diff --git a/ntoskrnl/io/pnpmgr/pnpmgr.c b/ntoskrnl/io/pnpmgr/pnpmgr.c index 9b6dc29f94a..0d8a1995d82 100644 --- a/ntoskrnl/io/pnpmgr/pnpmgr.c +++ b/ntoskrnl/io/pnpmgr/pnpmgr.c @@ -2601,6 +2601,7 @@ cleanup: NTSTATUS NTAPI +INIT_FUNCTION IopUpdateRootKey(VOID) { UNICODE_STRING EnumU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum"); diff --git a/ntoskrnl/kd/kdinit.c b/ntoskrnl/kd/kdinit.c index 5fcc0ee8cd2..3e7b53e4057 100644 --- a/ntoskrnl/kd/kdinit.c +++ b/ntoskrnl/kd/kdinit.c @@ -44,6 +44,7 @@ PKDP_INIT_ROUTINE InitRoutines[KdMax] = {KdpScreenInit, PCHAR NTAPI +INIT_FUNCTION KdpGetDebugMode(PCHAR Currentp2) { PCHAR p2 = Currentp2; @@ -118,6 +119,7 @@ KdpGetDebugMode(PCHAR Currentp2) VOID NTAPI +INIT_FUNCTION KdpCallInitRoutine(ULONG BootPhase) { PLIST_ENTRY CurrentEntry; diff --git a/ntoskrnl/kd/kdio.c b/ntoskrnl/kd/kdio.c index db48c31e227..4c18d4c721d 100644 --- a/ntoskrnl/kd/kdio.c +++ b/ntoskrnl/kd/kdio.c @@ -134,6 +134,7 @@ KdpPrintToLogFile(PCH String, VOID NTAPI +INIT_FUNCTION KdpInitDebugLog(PKD_DISPATCH_TABLE DispatchTable, ULONG BootPhase) { diff --git a/ntoskrnl/kd/kdmain.c b/ntoskrnl/kd/kdmain.c index 0d649112016..6b16582735a 100644 --- a/ntoskrnl/kd/kdmain.c +++ b/ntoskrnl/kd/kdmain.c @@ -72,8 +72,8 @@ KdpServiceDispatcher(ULONG Service, DbgBreakPoint(); break; - case ThatsWhatSheSaid: - MmDumpPfnDatabase(); + case KdSpare3: + MmDumpArmPfnDatabase(FALSE); break; default: diff --git a/ntoskrnl/kd64/kdinit.c b/ntoskrnl/kd64/kdinit.c index 542b8ded5d8..9fb10a86878 100644 --- a/ntoskrnl/kd64/kdinit.c +++ b/ntoskrnl/kd64/kdinit.c @@ -70,6 +70,7 @@ KdRegisterDebuggerDataBlock(IN ULONG Tag, BOOLEAN NTAPI +INIT_FUNCTION KdInitSystem(IN ULONG BootPhase, IN PLOADER_PARAMETER_BLOCK LoaderBlock) { diff --git a/ntoskrnl/kdbg/kdb.c b/ntoskrnl/kdbg/kdb.c index bc7e01864b0..67037f6829d 100644 --- a/ntoskrnl/kdbg/kdb.c +++ b/ntoskrnl/kdbg/kdb.c @@ -1695,6 +1695,7 @@ continue_execution: VOID NTAPI +INIT_FUNCTION KdbpGetCommandLineSettings( PCHAR p1) { diff --git a/ntoskrnl/ke/config.c b/ntoskrnl/ke/config.c index 5f9a196d032..ae01ca87368 100644 --- a/ntoskrnl/ke/config.c +++ b/ntoskrnl/ke/config.c @@ -19,6 +19,7 @@ */ PCONFIGURATION_COMPONENT_DATA NTAPI +INIT_FUNCTION KeFindConfigurationEntry(IN PCONFIGURATION_COMPONENT_DATA Child, IN CONFIGURATION_CLASS Class, IN CONFIGURATION_TYPE Type, @@ -39,6 +40,7 @@ KeFindConfigurationEntry(IN PCONFIGURATION_COMPONENT_DATA Child, */ PCONFIGURATION_COMPONENT_DATA NTAPI +INIT_FUNCTION KeFindConfigurationNextEntry(IN PCONFIGURATION_COMPONENT_DATA Child, IN CONFIGURATION_CLASS Class, IN CONFIGURATION_TYPE Type, diff --git a/ntoskrnl/ke/dpc.c b/ntoskrnl/ke/dpc.c index 7b4446a543b..9895cae3f27 100644 --- a/ntoskrnl/ke/dpc.c +++ b/ntoskrnl/ke/dpc.c @@ -534,7 +534,7 @@ KiQuantumEnd(VOID) Thread->WaitIrql = APC_LEVEL; /* Swap threads */ - KiSwapContext(Thread, NextThread); + KiSwapContext(APC_LEVEL, Thread); /* Lower IRQL back to DISPATCH_LEVEL */ KeLowerIrql(DISPATCH_LEVEL); diff --git a/ntoskrnl/ke/freeldr.c b/ntoskrnl/ke/freeldr.c index 7e67916a7ff..866d0a7ca2b 100644 --- a/ntoskrnl/ke/freeldr.c +++ b/ntoskrnl/ke/freeldr.c @@ -8,6 +8,8 @@ /* INCLUDES *****************************************************************/ +#if !defined(_X86_) + #include #define NDEBUG #include @@ -1412,3 +1414,4 @@ KiRosPrepareForSystemStartup(IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock) /* Do general System Startup */ KiSystemStartup(NtLoaderBlock); } +#endif diff --git a/ntoskrnl/ke/i386/cpu.c b/ntoskrnl/ke/i386/cpu.c index 5e4f51dfd65..a8db4d5b5dd 100644 --- a/ntoskrnl/ke/i386/cpu.c +++ b/ntoskrnl/ke/i386/cpu.c @@ -120,6 +120,7 @@ RDMSR(IN ULONG Register) VOID NTAPI +INIT_FUNCTION KiSetProcessorType(VOID) { ULONG EFlags, NewEFlags; @@ -186,6 +187,7 @@ KiSetProcessorType(VOID) ULONG NTAPI +INIT_FUNCTION KiGetCpuVendor(VOID) { PKPRCB Prcb = KeGetCurrentPrcb(); @@ -247,6 +249,7 @@ KiGetCpuVendor(VOID) ULONG NTAPI +INIT_FUNCTION KiGetFeatureBits(VOID) { PKPRCB Prcb = KeGetCurrentPrcb(); @@ -472,6 +475,7 @@ KiGetFeatureBits(VOID) VOID NTAPI +INIT_FUNCTION KiGetCacheInformation(VOID) { PKIPCR Pcr = (PKIPCR)KeGetPcr(); @@ -774,6 +778,7 @@ KiGetCacheInformation(VOID) VOID NTAPI +INIT_FUNCTION KiSetCR0Bits(VOID) { ULONG Cr0; @@ -790,6 +795,7 @@ KiSetCR0Bits(VOID) VOID NTAPI +INIT_FUNCTION KiInitializeTSS2(IN PKTSS Tss, IN PKGDTENTRY TssEntry OPTIONAL) { @@ -843,6 +849,7 @@ KiInitializeTSS(IN PKTSS Tss) VOID FASTCALL +INIT_FUNCTION Ki386InitializeTss(IN PKTSS Tss, IN PKIDTENTRY Idt, IN PKGDTENTRY Gdt) @@ -1002,6 +1009,7 @@ KiSaveProcessorControlState(OUT PKPROCESSOR_STATE ProcessorState) VOID NTAPI +INIT_FUNCTION KiInitializeMachineType(VOID) { /* Set the Machine Type we got from NTLDR */ @@ -1010,6 +1018,7 @@ KiInitializeMachineType(VOID) ULONG_PTR NTAPI +INIT_FUNCTION KiLoadFastSyscallMachineSpecificRegisters(IN ULONG_PTR Context) { /* Set CS and ESP */ @@ -1023,6 +1032,7 @@ KiLoadFastSyscallMachineSpecificRegisters(IN ULONG_PTR Context) VOID NTAPI +INIT_FUNCTION KiRestoreFastSyscallReturnState(VOID) { /* Check if the CPU Supports fast system call */ @@ -1056,6 +1066,7 @@ KiRestoreFastSyscallReturnState(VOID) ULONG_PTR NTAPI +INIT_FUNCTION Ki386EnableDE(IN ULONG_PTR Context) { /* Enable DE */ @@ -1065,6 +1076,7 @@ Ki386EnableDE(IN ULONG_PTR Context) ULONG_PTR NTAPI +INIT_FUNCTION Ki386EnableFxsr(IN ULONG_PTR Context) { /* Enable FXSR */ @@ -1074,6 +1086,7 @@ Ki386EnableFxsr(IN ULONG_PTR Context) ULONG_PTR NTAPI +INIT_FUNCTION Ki386EnableXMMIExceptions(IN ULONG_PTR Context) { PKIDTENTRY IdtEntry; @@ -1096,6 +1109,7 @@ Ki386EnableXMMIExceptions(IN ULONG_PTR Context) VOID NTAPI +INIT_FUNCTION KiI386PentiumLockErrataFixup(VOID) { KDESCRIPTOR IdtDescriptor; @@ -1187,6 +1201,7 @@ KiSaveProcessorState(IN PKTRAP_FRAME TrapFrame, BOOLEAN NTAPI +INIT_FUNCTION KiIsNpxPresent(VOID) { ULONG Cr0; @@ -1227,6 +1242,7 @@ KiIsNpxPresent(VOID) BOOLEAN NTAPI +INIT_FUNCTION KiIsNpxErrataPresent(VOID) { BOOLEAN ErrataPresent; diff --git a/ntoskrnl/ke/i386/ctxswitch.S b/ntoskrnl/ke/i386/ctxswitch.S index 716db3b3b11..9a9c95f4db1 100644 --- a/ntoskrnl/ke/i386/ctxswitch.S +++ b/ntoskrnl/ke/i386/ctxswitch.S @@ -13,338 +13,20 @@ #include .intel_syntax noprefix -#define Ready 1 -#define Running 2 -#define WrDispatchInt 0x1F - /* FUNCTIONS ****************************************************************/ -/*++ - * KiSwapContextInternal - * - * The KiSwapContextInternal routine switches context to another thread. - * - * Params: - * ESI - Pointer to the KTHREAD to which the caller wishes to - * switch to. - * EDI - Pointer to the KTHREAD to which the caller wishes to - * switch from. - * - * Returns: - * None. - * - * Remarks: - * Absolutely all registers except ESP can be trampled here for maximum code flexibility. - * - *--*/ .globl @KiSwapContextInternal@0 .func @KiSwapContextInternal@0, @KiSwapContextInternal@0 @KiSwapContextInternal@0: - - /* Save the IRQL */ - push ecx - -#ifdef CONFIG_SMP -GetSwapLock: - /* Acquire the swap lock */ - cmp byte ptr [esi+KTHREAD_SWAP_BUSY], 0 - jz NotBusy - pause - jmp GetSwapLock -NotBusy: -#endif - /* Increase context switches (use ES for lazy load) */ - inc dword ptr es:[ebx+KPCR_CONTEXT_SWITCHES] - - /* Save the Exception list */ - push [ebx+KPCR_EXCEPTION_LIST] - - /* Check for WMI */ - cmp dword ptr [ebx+KPCR_PERF_GLOBAL_GROUP_MASK], 0 - jnz WmiTrace - -AfterTrace: -#ifdef CONFIG_SMP -#if DBG - /* Assert that we're on the right CPU */ - mov cl, [esi+KTHREAD_NEXT_PROCESSOR] - cmp cl, [ebx+KPCR_PROCESSOR_NUMBER] - jnz WrongCpu -#endif -#endif - - /* Get CR0 and save it */ - mov ebp, cr0 - mov edx, ebp - -#ifdef CONFIG_SMP - /* Check NPX State */ - cmp byte ptr [edi+KTHREAD_NPX_STATE], NPX_STATE_LOADED - jz NpxLoaded -SetStack: -#endif - - /* Set new stack */ - mov [edi+KTHREAD_KERNEL_STACK], esp - - /* Checking NPX, disable interrupts now */ - mov eax, [esi+KTHREAD_INITIAL_STACK] - cli - - /* Get the NPX State */ - movzx ecx, byte ptr [esi+KTHREAD_NPX_STATE] - - /* Clear the other bits, merge in CR0, merge in FPU CR0 bits and compare */ - and edx, ~(CR0_MP + CR0_EM + CR0_TS) - or ecx, edx - or ecx, [eax - (NPX_FRAME_LENGTH - FN_CR0_NPX_STATE)] - cmp ebp, ecx - jnz NewCr0 - -StackOk: - /* Enable interrupts and set the current stack */ - sti - mov esp, [esi+KTHREAD_KERNEL_STACK] - - /* Check if address space switch is needed */ - mov ebp, [esi+KTHREAD_APCSTATE_PROCESS] - mov eax, [edi+KTHREAD_APCSTATE_PROCESS] - cmp ebp, eax - jz SameProcess - -#ifdef CONFIG_SMP - /* Get the active processors and XOR with the process' */ - mov ecx, [ebx+KPCR_SET_MEMBER_COPY] - lock xor [ebp+KPROCESS_ACTIVE_PROCESSORS], ecx - lock xor [eax+KPROCESS_ACTIVE_PROCESSORS], ecx - - /* Assert change went ok */ -#if DBG - test [ebp+KPROCESS_ACTIVE_PROCESSORS], ecx - jz WrongActiveCpu - test [eax+KPROCESS_ACTIVE_PROCESSORS], ecx - jnz WrongActiveCpu -#endif -#endif - - /* Check if we need an LDT */ - mov ecx, [ebp+KPROCESS_LDT_DESCRIPTOR0] - or ecx, [eax+KPROCESS_LDT_DESCRIPTOR0] - jnz LdtReload - -UpdateCr3: - /* Switch address space */ - mov eax, [ebp+KPROCESS_DIRECTORY_TABLE_BASE] - mov cr3, eax - -SameProcess: - -#ifdef CONFIG_SMP - /* Release swap lock */ - and byte ptr [edi+KTHREAD_SWAP_BUSY], 0 -#endif - - /* Clear gs */ - xor eax, eax - mov gs, ax - - /* Set the TEB */ - mov eax, [esi+KTHREAD_TEB] - mov [ebx+KPCR_TEB], eax - mov ecx, [ebx+KPCR_GDT] - mov [ecx+0x3A], ax - shr eax, 16 - mov [ecx+0x3C], al - mov [ecx+0x3F], ah - - /* Get stack pointer */ - mov eax, [esi+KTHREAD_INITIAL_STACK] - - /* Make space for the NPX Frame */ - sub eax, NPX_FRAME_LENGTH - - /* Check if this isn't V86 Mode, so we can bias the Esp0 */ - test dword ptr [eax - KTRAP_FRAME_SIZE + KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK - jnz NoAdjust - - /* Bias esp */ - sub eax, KTRAP_FRAME_V86_GS - KTRAP_FRAME_SS - -NoAdjust: - - /* Set new ESP0 */ - mov ecx, [ebx+KPCR_TSS] - mov [ecx+KTSS_ESP0], eax - - /* Set current IOPM offset in the TSS */ - mov ax, [ebp+KPROCESS_IOPM_OFFSET] - mov [ecx+KTSS_IOMAPBASE], ax - - /* Increase context switches */ - inc dword ptr [esi+KTHREAD_CONTEXT_SWITCHES] - - /* Restore exception list */ - pop [ebx+KPCR_EXCEPTION_LIST] - - /* Restore IRQL */ - pop ecx - - /* DPC shouldn't be active */ - cmp byte ptr [ebx+KPCR_PRCB_DPC_ROUTINE_ACTIVE], 0 - jnz BugCheckDpc - - /* Check if kernel APCs are pending */ - cmp byte ptr [esi+KTHREAD_PENDING_KERNEL_APC], 0 - jnz CheckApc - - /* No APCs, return */ - xor eax, eax - ret - -CheckApc: - - /* Check if they're disabled */ - cmp word ptr [esi+KTHREAD_SPECIAL_APC_DISABLE], 0 - jnz ApcReturn - test cl, cl - jz ApcReturn - - /* Request APC Delivery */ - mov cl, APC_LEVEL - call @HalRequestSoftwareInterrupt@4 - or eax, esp - -ApcReturn: - - /* Return with APC pending */ - setz al - ret - -LdtReload: - /* Check if it's empty */ - mov eax, [ebp+KPROCESS_LDT_DESCRIPTOR0] - test eax, eax - jz LoadLdt - - /* Write the LDT Selector */ - mov ecx, [ebx+KPCR_GDT] - mov [ecx+KGDT_LDT], eax - mov eax, [ebp+KPROCESS_LDT_DESCRIPTOR1] - mov [ecx+KGDT_LDT+4], eax - - /* Write the INT21 handler */ - mov ecx, [ebx+KPCR_IDT] - mov eax, [ebp+KPROCESS_INT21_DESCRIPTOR0] - mov [ecx+0x108], eax - mov eax, [ebp+KPROCESS_INT21_DESCRIPTOR1] - mov [ecx+0x10C], eax - - /* Save LDT Selector */ - mov eax, KGDT_LDT - -LoadLdt: - lldt ax - jmp UpdateCr3 - -NewCr0: - -#if DBG - /* Assert NPX State */ - test byte ptr [esi+KTHREAD_NPX_STATE], ~(NPX_STATE_NOT_LOADED) - jnz InvalidNpx - test dword ptr [eax - (NPX_FRAME_LENGTH - FN_CR0_NPX_STATE)], ~(CR0_PE + CR0_MP + CR0_EM + CR0_TS) - jnz InvalidNpx -#endif - - /* Update CR0 */ - mov cr0, ecx - jmp StackOk - -#ifdef CONFIG_SMP -NpxLoaded: - - /* Mask out FPU flags */ - and edx, ~(CR0_MP + CR0_EM + CR0_TS) - - /* Get the NPX Frame */ - mov ecx, [edi+KTHREAD_INITIAL_STACK] - sub ecx, NPX_FRAME_LENGTH - - /* Check if we have a new CR0 */ - cmp ebp, edx - jz Cr0Equal - - /* We do, update it */ - mov cr0, edx - mov ebp, edx - -Cr0Equal: - - /* Save the NPX State */ - fxsave [ecx] - mov byte ptr [edi+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED - - /* Clear the NPX Thread */ - mov dword ptr [ebx+KPCR_NPX_THREAD], 0 - - /* Jump back */ - jmp SetStack -#endif - -WmiTrace: - - /* No WMI support yet */ - int 3 - - /* Jump back */ - jmp AfterTrace - -BugCheckDpc: - - /* Bugcheck the machine, printing out the threads being switched */ - mov eax, [edi+KTHREAD_INITIAL_STACK] - push 0 - push eax - push esi - push edi - push ATTEMPTED_SWITCH_FROM_DPC - call _KeBugCheckEx@20 - -#if DBG -InvalidNpx: - int 3 -WrongActiveCpu: - int 3 -WrongCpu: - int 3 -#endif + /* Build switch frame */ + sub esp, 2 * 4 + mov ecx, esp + jmp @KiSwapContextEntry@8 .endfunc -/*++ - * KiSwapContext - * - * The KiSwapContext routine switches context to another thread. - * - * Params: - * TargetThread - Pointer to the KTHREAD to which the caller wishes to - * switch to. - * - * Returns: - * The WaitStatus of the Target Thread. - * - * Remarks: - * This is a wrapper around KiSwapContextInternal which will save all the - * non-volatile registers so that the Internal function can use all of - * them. It will also save the old current thread and set the new one. - * - * The calling thread does not return after KiSwapContextInternal until - * another thread switches to IT. - * - *--*/ .globl @KiSwapContext@8 .func @KiSwapContext@8, @KiSwapContext@8 @KiSwapContext@8: - /* Save 4 registers */ sub esp, 4 * 4 @@ -354,17 +36,8 @@ WrongCpu: mov [esp+4], edi mov [esp+0], ebp - /* Get the current KPCR */ - mov ebx, fs:[KPCR_SELF] - - /* Get the Current Thread */ - mov edi, ecx - - /* Get the New Thread */ - mov esi, edx - /* Get the wait IRQL */ - movzx ecx, byte ptr [edi+KTHREAD_WAIT_IRQL] + or dl, cl /* Do the swap with the registers correctly setup */ call @KiSwapContextInternal@0 @@ -380,245 +53,30 @@ WrongCpu: ret .endfunc -/* DPC INTERRUPT HANDLER ******************************************************/ - -.globl _KiDispatchInterrupt@0 -.func KiDispatchInterrupt@0 -_KiDispatchInterrupt@0: - - /* Preserve EBX */ - push ebx - - /* Get the PCR and disable interrupts */ - mov ebx, PCR[KPCR_SELF] - cli - - /* Check if we have to deliver DPCs, timers, or deferred threads */ - mov eax, [ebx+KPCR_PRCB_DPC_QUEUE_DEPTH] - or eax, [ebx+KPCR_PRCB_TIMER_REQUEST] - or eax, [ebx+KPCR_PRCB_DEFERRED_READY_LIST_HEAD] - jz CheckQuantum - - /* Save stack pointer and exception list, then clear it */ - push ebp - push dword ptr [ebx+KPCR_EXCEPTION_LIST] - mov dword ptr [ebx+KPCR_EXCEPTION_LIST], -1 - - /* Save the stack and switch to the DPC Stack */ - mov edx, esp - mov esp, [ebx+KPCR_PRCB_DPC_STACK] - push edx - - /* Deliver DPCs */ - mov ecx, [ebx+KPCR_PRCB] - call @KiRetireDpcList@4 - - /* Restore stack and exception list */ - pop esp - pop dword ptr [ebx+KPCR_EXCEPTION_LIST] - pop ebp - -CheckQuantum: - - /* Re-enable interrupts */ - sti - - /* Check if we have quantum end */ - cmp byte ptr [ebx+KPCR_PRCB_QUANTUM_END], 0 - jnz QuantumEnd - - /* Check if we have a thread to swap to */ - cmp byte ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0 - je Return - - /* Make space on the stack to save registers */ - sub esp, 3 * 4 - mov [esp+8], esi - mov [esp+4], edi - mov [esp+0], ebp - - /* Get the current thread */ - mov edi, [ebx+KPCR_CURRENT_THREAD] - -#ifdef CONFIG_SMP - /* Raise to synch level */ - call _KeRaiseIrqlToSynchLevel@0 - - /* Set context swap busy */ - mov byte ptr [edi+KTHREAD_SWAP_BUSY], 1 - - /* Acquire the PRCB Lock */ - lock bts dword ptr [ebx+KPCR_PRCB_PRCB_LOCK], 0 - jnb GetNext - lea ecx, [ebx+KPCR_PRCB_PRCB_LOCK] - call @KefAcquireSpinLockAtDpcLevel@4 -#endif - -GetNext: - /* Get the next thread and clear it */ - mov esi, [ebx+KPCR_PRCB_NEXT_THREAD] - and dword ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0 - - /* Set us as the current running thread */ - mov [ebx+KPCR_CURRENT_THREAD], esi - mov byte ptr [esi+KTHREAD_STATE_], Running - mov byte ptr [edi+KTHREAD_WAIT_REASON], WrDispatchInt - - /* Put thread in ECX and get the PRCB in EDX */ - mov ecx, edi - lea edx, [ebx+KPCR_PRCB_DATA] - call @KiQueueReadyThread@8 - - /* Set APC_LEVEL and do the swap */ - mov cl, APC_LEVEL - call @KiSwapContextInternal@0 - -#ifdef CONFIG_SMP - /* Lower IRQL back to dispatch */ - mov cl, DISPATCH_LEVEL - call @KfLowerIrql@4 -#endif - - /* Restore registers */ - mov ebp, [esp+0] - mov edi, [esp+4] - mov esi, [esp+8] - add esp, 3*4 - -Return: - /* All done */ - pop ebx - ret - -QuantumEnd: - /* Disable quantum end and process it */ - mov byte ptr [ebx+KPCR_PRCB_QUANTUM_END], 0 - call _KiQuantumEnd@0 - pop ebx +.globl @KiSwitchThreads@8 +.func @KiSwitchThreads@8, @KiSwitchThreads@8 +@KiSwitchThreads@8: + /* Load the new kernel stack and switch OS to new thread */ + mov esp, edx + call @KiSwapContextExit@8 + + /* Now we're on the new thread. Return to the caller to restore registers */ + add esp, 2 * 4 ret .endfunc -.globl @KiIdleLoop@0 -.func @KiIdleLoop@0, @KiIdleLoop@0 -@KiIdleLoop@0: - - /* Set EBX */ - mov ebx, fs:[KPCR_SELF] - - /* Jump into mainline code */ - jmp MainLoop - -CpuIdle: - /* Call the CPU's idle function */ - lea ecx, [ebx+KPCR_PRCB_POWER_STATE_IDLE_FUNCTION] - call [ecx] - -MainLoop: - /* Cycle interrupts for 1 cycle */ - sti - nop - nop - cli - - /* Check if we have to deliver DPCs, timers, or deferred threads */ - mov eax, [ebx+KPCR_PRCB_DPC_QUEUE_DEPTH] - or eax, [ebx+KPCR_PRCB_TIMER_REQUEST] -#ifdef CONFIG_SMP - or eax, [ebx+KPCR_PRCB_DEFERRED_READY_LIST_HEAD] -#endif - jz CheckSchedule - - mov cl, DISPATCH_LEVEL - call @HalClearSoftwareInterrupt@4 - - /* Handle the above */ - lea ecx, [ebx+KPCR_PRCB_DATA] +.globl @KiRetireDpcListInDpcStack@8 +.func @KiRetireDpcListInDpcStack@8, @KiRetireDpcListInDpcStack@8 +@KiRetireDpcListInDpcStack@8: + /* Switch stacks and retire DPCs */ + mov eax, esp + mov esp, edx + push eax call @KiRetireDpcList@4 -CheckSchedule: - /* Check if a next thread is queued */ - cmp dword ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0 -#ifdef CONFIG_SMP - jz NoNextThread -#else - jz CpuIdle -#endif - -#ifdef CONFIG_SMP - /* There is, raise IRQL to synch level */ - call _KeRaiseIrqlToSynchLevel@0 -#endif - sti - - /* Set the current thread to ready */ - mov edi, [ebx+KPCR_CURRENT_THREAD] -#ifdef CONFIG_SMP - mov byte ptr [edi+KTHREAD_SWAP_BUSY], 1 - - /* Acquire the PRCB Lock */ - lock bts dword ptr [ebx+KPCR_PRCB_PRCB_LOCK], 0 - jnb CheckNext - lea ecx, [ebx+KPCR_PRCB_PRCB_LOCK] - call @KefAcquireSpinLockAtDpcLevel@4 -#endif - -CheckNext: - /* Check if the next thread is the current */ - mov esi, [ebx+KPCR_PRCB_NEXT_THREAD] -#ifdef CONFIG_SMP - cmp esi, edi - jz SameThread -#endif - - /* Clear the next thread and set this one instead */ - and dword ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0 - mov [ebx+KPCR_CURRENT_THREAD], esi - - /* Set the thread as running */ - mov byte ptr [esi+KTHREAD_STATE_], Running - -#ifdef CONFIG_SMP - /* Disable the idle scheduler and release the PRCB lock */ - and byte ptr [ebx+KPCR_PRCB_IDLE_SCHEDULE], 0 - and dword ptr [ebx+KPCR_PRCB_PRCB_LOCK], 0 -#endif - -SwapContext: - /* Swap context at APC_LEVEL */ - mov ecx, APC_LEVEL - call @KiSwapContextInternal@0 - -#ifdef CONFIG_SMP - /* Lower to DPC level */ - mov ecx, DISPATCH_LEVEL - call @KfLowerIrql@4 -#endif - jmp MainLoop - -#ifdef CONFIG_SMP -SameThread: - /* Clear the next thread, and put the thread as ready after lock release */ - and dword ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0 - and dword ptr [ebx+KPCR_PRCB_PRCB_LOCK], 0 - and byte ptr [edi+KTHREAD_STATE_], Ready - jmp MainLoop - -NoNextThread: - /* Check if the idle scheduler is enabled */ - cmp byte ptr [ebx+KPCR_PRCB_IDLE_SCHEDULE], 0 - jz CpuIdle - - /* It is, so call the scheduler */ - lea ecx, [ebx+KPCR_PRCB_DATA] - call @KiIdleSchedule@4 - test eax, eax - - /* Get new thread pointers and either swap or idle loop again */ - mov esi, eax - mov edi, [ebx+KPCR_PRCB_IDLE_THREAD] - jnz SwapContext - jmp MainLoop -#endif + /* Return on original stack */ + pop esp + ret .endfunc /* FIXFIX: Move to C code ****/ diff --git a/ntoskrnl/ke/i386/kiinit.c b/ntoskrnl/ke/i386/kiinit.c index b9ad8c65fea..535d6d27164 100644 --- a/ntoskrnl/ke/i386/kiinit.c +++ b/ntoskrnl/ke/i386/kiinit.c @@ -33,6 +33,7 @@ ULONGLONG BootCycles, BootCyclesEnd; VOID NTAPI +INIT_FUNCTION KiInitMachineDependent(VOID) { ULONG CpuCount; @@ -325,6 +326,7 @@ KiInitMachineDependent(VOID) VOID NTAPI +INIT_FUNCTION KiInitializePcr(IN ULONG ProcessorNumber, IN PKIPCR Pcr, IN PKIDTENTRY Idt, @@ -386,6 +388,7 @@ KiInitializePcr(IN ULONG ProcessorNumber, VOID NTAPI +INIT_FUNCTION KiInitializeKernel(IN PKPROCESS InitProcess, IN PKTHREAD InitThread, IN PVOID IdleStack, @@ -607,6 +610,7 @@ KiInitializeKernel(IN PKPROCESS InitProcess, VOID FASTCALL +INIT_FUNCTION KiGetMachineBootPointers(IN PKGDTENTRY *Gdt, IN PKIDTENTRY *Idt, IN PKIPCR *Pcr, @@ -647,6 +651,7 @@ KiGetMachineBootPointers(IN PKGDTENTRY *Gdt, VOID NTAPI +INIT_FUNCTION KiSystemStartupBootStack(VOID) { PKTHREAD Thread; @@ -676,6 +681,7 @@ KiSystemStartupBootStack(VOID) VOID NTAPI +INIT_FUNCTION KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { ULONG Cpu; @@ -689,10 +695,10 @@ KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock) /* Boot cycles timestamp */ BootCycles = __rdtsc(); - +#if !defined(_X86_) /* Check if we are being booted from FreeLDR */ if (!((ULONG_PTR)LoaderBlock & 0x80000000)) KiRosPrepareForSystemStartup((PROS_LOADER_PARAMETER_BLOCK)LoaderBlock); - +#endif /* Save the loader block and get the current CPU */ KeLoaderBlock = LoaderBlock; Cpu = KeNumberProcessors; diff --git a/ntoskrnl/ke/i386/mtrr.c b/ntoskrnl/ke/i386/mtrr.c index 72ceed70f31..d2f83038f66 100644 --- a/ntoskrnl/ke/i386/mtrr.c +++ b/ntoskrnl/ke/i386/mtrr.c @@ -18,6 +18,7 @@ VOID NTAPI +INIT_FUNCTION KiInitializeMTRR(IN BOOLEAN FinalCpu) { /* FIXME: Support this */ @@ -26,6 +27,7 @@ KiInitializeMTRR(IN BOOLEAN FinalCpu) VOID NTAPI +INIT_FUNCTION KiAmdK6InitializeMTRR(VOID) { /* FIXME: Support this */ diff --git a/ntoskrnl/ke/i386/patpge.c b/ntoskrnl/ke/i386/patpge.c index 9b6ef4b67c6..5e8e232727a 100644 --- a/ntoskrnl/ke/i386/patpge.c +++ b/ntoskrnl/ke/i386/patpge.c @@ -16,6 +16,7 @@ ULONG_PTR NTAPI +INIT_FUNCTION Ki386EnableGlobalPage(IN volatile ULONG_PTR Context) { volatile PLONG Count = (PLONG)Context; @@ -52,6 +53,7 @@ Ki386EnableGlobalPage(IN volatile ULONG_PTR Context) VOID NTAPI +INIT_FUNCTION KiInitializePAT(VOID) { /* FIXME: Support this */ diff --git a/ntoskrnl/ke/i386/thrdini.c b/ntoskrnl/ke/i386/thrdini.c index 219e2883922..b90ae664d96 100644 --- a/ntoskrnl/ke/i386/thrdini.c +++ b/ntoskrnl/ke/i386/thrdini.c @@ -42,6 +42,20 @@ typedef struct _KKINIT_FRAME FX_SAVE_AREA FxSaveArea; } KKINIT_FRAME, *PKKINIT_FRAME; +VOID +FASTCALL +KiSwitchThreads( + IN PKTHREAD OldThread, + IN PKTHREAD NewThread +); + +VOID +FASTCALL +KiRetireDpcListInDpcStack( + IN PKPRCB Prcb, + IN PVOID DpcStack +); + /* FUNCTIONS *****************************************************************/ VOID @@ -249,6 +263,253 @@ KiInitializeContextThread(IN PKTHREAD Thread, Thread->KernelStack = (PVOID)CtxSwitchFrame; } +VOID +FASTCALL +KiIdleLoop(VOID) +{ + PKPRCB Prcb = KeGetCurrentPrcb(); + PKTHREAD OldThread, NewThread; + + /* Initialize the idle loop: disable interrupts */ + _enable(); + YieldProcessor(); + YieldProcessor(); + _disable(); + + /* Now loop forever */ + while (TRUE) + { + /* Check for pending timers, pending DPCs, or pending ready threads */ + if ((Prcb->DpcData[0].DpcQueueDepth) || + (Prcb->TimerRequest) || + (Prcb->DeferredReadyListHead.Next)) + { + /* Quiesce the DPC software interrupt */ + HalClearSoftwareInterrupt(DISPATCH_LEVEL); + + /* Handle it */ + KiRetireDpcList(Prcb); + } + + /* Check if a new thread is scheduled for execution */ + if (Prcb->NextThread) + { + /* Enable interupts */ + _enable(); + + /* Capture current thread data */ + OldThread = Prcb->CurrentThread; + NewThread = Prcb->NextThread; + + /* Set new thread data */ + Prcb->NextThread = NULL; + Prcb->CurrentThread = NewThread; + + /* The thread is now running */ + NewThread->State = Running; + + /* Switch away from the idle thread */ + KiSwapContext(APC_LEVEL, OldThread); + + /* We are back in the idle thread -- disable interrupts again */ + _enable(); + YieldProcessor(); + YieldProcessor(); + _disable(); + } + else + { + /* Continue staying idle. Note the HAL returns with interrupts on */ + Prcb->PowerState.IdleFunction(&Prcb->PowerState); + } + } +} + +BOOLEAN +FASTCALL +KiSwapContextExit(IN PKTHREAD OldThread, + IN PKSWITCHFRAME SwitchFrame) +{ + PKIPCR Pcr = (PKIPCR)KeGetPcr(); + PKPROCESS OldProcess, NewProcess; + PKGDTENTRY GdtEntry; + PKTHREAD NewThread; + PKUINIT_FRAME InitFrame; + + /* We are on the new thread stack now */ + NewThread = Pcr->PrcbData.CurrentThread; + + /* Now we are the new thread. Check if it's in a new process */ + OldProcess = OldThread->ApcState.Process; + NewProcess = NewThread->ApcState.Process; + if (OldProcess != NewProcess) + { + /* Check if there is a different LDT */ + if (*(PULONGLONG)&OldProcess->LdtDescriptor != *(PULONGLONG)&NewProcess->LdtDescriptor) + { + DPRINT1("LDT switch not implemented\n"); + ASSERT(FALSE); + } + + /* Switch address space and flush TLB */ + __writecr3(NewProcess->DirectoryTableBase[0]); + } + + /* Clear GS */ + Ke386SetGs(0); + + /* Set the TEB */ + Pcr->NtTib.Self = (PVOID)NewThread->Teb; + GdtEntry = &Pcr->GDT[KGDT_R3_TEB / sizeof(KGDTENTRY)]; + GdtEntry->BaseLow = (USHORT)((ULONG_PTR)NewThread->Teb & 0xFFFF); + GdtEntry->HighWord.Bytes.BaseMid = (UCHAR)((ULONG_PTR)NewThread->Teb >> 16); + GdtEntry->HighWord.Bytes.BaseHi = (UCHAR)((ULONG_PTR)NewThread->Teb >> 24); + + /* Set new TSS fields */ + InitFrame = (PKUINIT_FRAME)NewThread->InitialStack - 1; + Pcr->TSS->Esp0 = (ULONG_PTR)&InitFrame->TrapFrame; + if (!(InitFrame->TrapFrame.EFlags & EFLAGS_V86_MASK)) + { + Pcr->TSS->Esp0 -= (FIELD_OFFSET(KTRAP_FRAME, V86Gs) - FIELD_OFFSET(KTRAP_FRAME, HardwareSegSs)); + } + Pcr->TSS->IoMapBase = NewProcess->IopmOffset; + + /* Increase thread context switches */ + NewThread->ContextSwitches++; + + /* Load data from switch frame */ + Pcr->NtTib.ExceptionList = SwitchFrame->ExceptionList; + + /* DPCs shouldn't be active */ + if (Pcr->PrcbData.DpcRoutineActive) + { + /* Crash the machine */ + KeBugCheckEx(ATTEMPTED_SWITCH_FROM_DPC, + (ULONG_PTR)OldThread, + (ULONG_PTR)NewThread, + (ULONG_PTR)OldThread->InitialStack, + 0); + } + + /* Kernel APCs may be pending */ + if (NewThread->ApcState.KernelApcPending) + { + /* Are APCs enabled? */ + if (!NewThread->SpecialApcDisable) + { + /* Request APC delivery */ + if (!SwitchFrame->ApcBypassDisable) HalRequestSoftwareInterrupt(APC_LEVEL); + return TRUE; + } + } + + /* Return */ + return FALSE; +} + +VOID +FASTCALL +KiSwapContextEntry(IN PKSWITCHFRAME SwitchFrame, + IN ULONG_PTR OldThreadAndApcFlag) +{ + PKIPCR Pcr = (PKIPCR)KeGetPcr(); + PKTHREAD OldThread, NewThread; + ULONG Cr0, NewCr0; + + /* Save APC bypass disable */ + SwitchFrame->ApcBypassDisable = OldThreadAndApcFlag & 3; + SwitchFrame->ExceptionList = Pcr->NtTib.ExceptionList; + + /* Increase context switch count and check if tracing is enabled */ + Pcr->ContextSwitches++; + if (Pcr->PerfGlobalGroupMask) + { + /* We don't support this yet on x86 either */ + DPRINT1("WMI Tracing not supported\n"); + ASSERT(FALSE); + } + + /* Get thread pointers */ + OldThread = (PKTHREAD)(OldThreadAndApcFlag & ~3); + NewThread = Pcr->PrcbData.CurrentThread; + + /* Get the old thread and set its kernel stack */ + OldThread->KernelStack = SwitchFrame; + + /* ISRs can change FPU state, so disable interrupts while checking */ + _disable(); + + /* Get current and new CR0 and check if they've changed */ + Cr0 = __readcr0(); + NewCr0 = NewThread->NpxState | + (Cr0 & ~(CR0_MP | CR0_EM | CR0_TS)) | + ((PKUINIT_FRAME)NewThread->InitialStack - 1)->FxSaveArea.Cr0NpxState; + if (Cr0 != NewCr0) __writecr0(NewCr0); + + /* Now enable interrupts and do the switch */ + _enable(); + KiSwitchThreads(OldThread, NewThread->KernelStack); +} + +VOID +NTAPI +KiDispatchInterrupt(VOID) +{ + PKIPCR Pcr = (PKIPCR)KeGetPcr(); + PKPRCB Prcb = &Pcr->PrcbData; + PVOID OldHandler; + PKTHREAD NewThread, OldThread; + + /* Disable interrupts */ + _disable(); + + /* Check for pending timers, pending DPCs, or pending ready threads */ + if ((Prcb->DpcData[0].DpcQueueDepth) || + (Prcb->TimerRequest) || + (Prcb->DeferredReadyListHead.Next)) + { + /* Switch to safe execution context */ + OldHandler = Pcr->NtTib.ExceptionList; + Pcr->NtTib.ExceptionList = EXCEPTION_CHAIN_END; + + /* Retire DPCs while under the DPC stack */ + KiRetireDpcListInDpcStack(Prcb, Prcb->DpcStack); + + /* Restore context */ + Pcr->NtTib.ExceptionList = OldHandler; + } + + /* Re-enable interrupts */ + _enable(); + + /* Check for quantum end */ + if (Prcb->QuantumEnd) + { + /* Handle quantum end */ + Prcb->QuantumEnd = FALSE; + KiQuantumEnd(); + } + else if (Prcb->NextThread) + { + /* Capture current thread data */ + OldThread = Prcb->CurrentThread; + NewThread = Prcb->NextThread; + + /* Set new thread data */ + Prcb->NextThread = NULL; + Prcb->CurrentThread = NewThread; + + /* The thread is now running */ + NewThread->State = Running; + OldThread->WaitReason = WrDispatchInt; + + /* Make the old thread ready */ + KxQueueReadyThread(OldThread, Prcb); + + /* Swap to the new thread */ + KiSwapContext(APC_LEVEL, OldThread); + } +} + + /* EOF */ - - diff --git a/ntoskrnl/ke/krnlinit.c b/ntoskrnl/ke/krnlinit.c index 55ec779251d..d22fe7e2fd8 100644 --- a/ntoskrnl/ke/krnlinit.c +++ b/ntoskrnl/ke/krnlinit.c @@ -57,6 +57,7 @@ KSPIN_LOCK KiReverseStallIpiLock; VOID NTAPI +INIT_FUNCTION KiInitSystem(VOID) { ULONG i; @@ -108,6 +109,7 @@ KiInitSystem(VOID) LARGE_INTEGER NTAPI +INIT_FUNCTION KiComputeReciprocal(IN LONG Divisor, OUT PUCHAR Shift) { @@ -171,6 +173,7 @@ KiComputeReciprocal(IN LONG Divisor, VOID NTAPI +INIT_FUNCTION KiInitSpinLocks(IN PKPRCB Prcb, IN CCHAR Number) { @@ -276,6 +279,7 @@ KiInitSpinLocks(IN PKPRCB Prcb, BOOLEAN NTAPI +INIT_FUNCTION KeInitSystem(VOID) { /* Check if Threaded DPCs are enabled */ diff --git a/ntoskrnl/ke/thrdschd.c b/ntoskrnl/ke/thrdschd.c index 040073cdb09..d100c3b8900 100644 --- a/ntoskrnl/ke/thrdschd.c +++ b/ntoskrnl/ke/thrdschd.c @@ -387,7 +387,7 @@ KiSwapThread(IN PKTHREAD CurrentThread, WaitIrql = CurrentThread->WaitIrql; /* Swap contexts */ - ApcState = KiSwapContext(CurrentThread, NextThread); + ApcState = KiSwapContext(WaitIrql, CurrentThread); /* Get the wait status */ WaitStatus = CurrentThread->WaitStatus; @@ -754,7 +754,7 @@ NtYieldExecution(VOID) ASSERT(OldIrql <= DISPATCH_LEVEL); /* Swap to new thread */ - KiSwapContext(Thread, NextThread); + KiSwapContext(APC_LEVEL, Thread); Status = STATUS_SUCCESS; } else diff --git a/ntoskrnl/ke/wait.c b/ntoskrnl/ke/wait.c index a4737b0b7fa..3fc51062ba4 100644 --- a/ntoskrnl/ke/wait.c +++ b/ntoskrnl/ke/wait.c @@ -249,7 +249,7 @@ KiExitDispatcher(IN KIRQL OldIrql) Thread->WaitIrql = OldIrql; /* Swap threads and check if APCs were pending */ - PendingApc = KiSwapContext(Thread, NextThread); + PendingApc = KiSwapContext(OldIrql, Thread); if (PendingApc) { /* Lower only to APC */ diff --git a/ntoskrnl/lpc/port.c b/ntoskrnl/lpc/port.c index b179fd30b48..77517ded394 100644 --- a/ntoskrnl/lpc/port.c +++ b/ntoskrnl/lpc/port.c @@ -33,6 +33,7 @@ static GENERIC_MAPPING LpcpPortMapping = BOOLEAN NTAPI +INIT_FUNCTION LpcInitSystem(VOID) { OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; diff --git a/ntoskrnl/mm/ARM3/contmem.c b/ntoskrnl/mm/ARM3/contmem.c index da277565861..79eacda42a0 100644 --- a/ntoskrnl/mm/ARM3/contmem.c +++ b/ntoskrnl/mm/ARM3/contmem.c @@ -30,13 +30,16 @@ MiFindContiguousPages(IN PFN_NUMBER LowestPfn, ULONG i = 0; PMMPFN Pfn1, EndPfn; KIRQL OldIrql; - PAGED_CODE (); + PAGED_CODE(); ASSERT(SizeInPages != 0); // // Convert the boundary PFN into an alignment mask // BoundaryMask = ~(BoundaryPfn - 1); + + /* Disable APCs */ + KeEnterGuardedRegion(); // // Loop all the physical memory blocks @@ -69,12 +72,16 @@ MiFindContiguousPages(IN PFN_NUMBER LowestPfn, // Now scan all the relevant PFNs in this run // Length = 0; - for (Pfn1 = MiGetPfnEntry(Page); Page < LastPage; Page++, Pfn1++) + for (Pfn1 = MI_PFN_ELEMENT(Page); Page < LastPage; Page++, Pfn1++) { // // If this PFN is in use, ignore it // - if (MiIsPfnInUse(Pfn1)) continue; + if (MiIsPfnInUse(Pfn1)) + { + Length = 0; + continue; + } // // If we haven't chosen a start PFN yet and the caller specified an @@ -130,6 +137,8 @@ MiFindContiguousPages(IN PFN_NUMBER LowestPfn, // // This PFN is now a used page, set it up // + MI_SET_USAGE(MI_USAGE_CONTINOUS_ALLOCATION); + MI_SET_PROCESS2("Kernel Driver"); MiUnlinkFreeOrZeroedPage(Pfn1); Pfn1->u3.e2.ReferenceCount = 1; Pfn1->u2.ShareCount = 1; @@ -162,14 +171,17 @@ MiFindContiguousPages(IN PFN_NUMBER LowestPfn, // Quick sanity check that the last PFN is consistent // EndPfn = Pfn1 + SizeInPages; - ASSERT(EndPfn == MiGetPfnEntry(Page + 1)); + ASSERT(EndPfn == MI_PFN_ELEMENT(Page + 1)); // // Compute the first page, and make sure it's consistent // - Page -= SizeInPages - 1; - ASSERT(Pfn1 == MiGetPfnEntry(Page)); + Page = Page - SizeInPages + 1; + ASSERT(Pfn1 == MI_PFN_ELEMENT(Page)); ASSERT(Page != 0); + + /* Enable APCs and return the page */ + KeLeaveGuardedRegion(); return Page; } @@ -354,7 +366,7 @@ MiFindContiguousMemory(IN PFN_NUMBER LowestPfn, /* Write the PTE address */ Pfn1->PteAddress = PointerPte; Pfn1->u4.PteFrame = PFN_FROM_PTE(MiAddressToPte(PointerPte++)); - } while (Pfn1++ < EndPfn); + } while (++Pfn1 < EndPfn); /* Return the address */ return BaseAddress; diff --git a/ntoskrnl/mm/ARM3/expool.c b/ntoskrnl/mm/ARM3/expool.c index 4a93c072a86..79e5ef95dc7 100644 --- a/ntoskrnl/mm/ARM3/expool.c +++ b/ntoskrnl/mm/ARM3/expool.c @@ -288,6 +288,7 @@ ExpCheckPoolBlocks(IN PVOID Block) VOID NTAPI +INIT_FUNCTION ExInitializePoolDescriptor(IN PPOOL_DESCRIPTOR PoolDescriptor, IN POOL_TYPE PoolType, IN ULONG PoolIndex, @@ -333,6 +334,7 @@ ExInitializePoolDescriptor(IN PPOOL_DESCRIPTOR PoolDescriptor, VOID NTAPI +INIT_FUNCTION InitializePool(IN POOL_TYPE PoolType, IN ULONG Threshold) { diff --git a/ntoskrnl/mm/ARM3/i386/init.c b/ntoskrnl/mm/ARM3/i386/init.c index 1d0a41c79ac..70707a6e98a 100644 --- a/ntoskrnl/mm/ARM3/i386/init.c +++ b/ntoskrnl/mm/ARM3/i386/init.c @@ -24,6 +24,7 @@ MMPTE ValidKernelPte = {.u.Hard.Valid = 1, .u.Hard.Write = 1, .u.Hard.Dirty = 1, /* Template PDE for a demand-zero page */ MMPDE DemandZeroPde = {.u.Long = (MM_READWRITE << MM_PTE_SOFTWARE_PROTECTION_BITS)}; +MMPTE DemandZeroPte = {.u.Long = (MM_READWRITE << MM_PTE_SOFTWARE_PROTECTION_BITS)}; /* Template PTE for prototype page */ MMPTE PrototypePte = {.u.Long = (MM_READWRITE << MM_PTE_SOFTWARE_PROTECTION_BITS) | PTE_PROTOTYPE | (MI_PTE_LOOKUP_NEEDED << PAGE_SHIFT)}; @@ -32,6 +33,7 @@ MMPTE PrototypePte = {.u.Long = (MM_READWRITE << MM_PTE_SOFTWARE_PROTECTION_BITS VOID NTAPI +INIT_FUNCTION MiComputeNonPagedPoolVa(IN ULONG FreePages) { IN PFN_NUMBER PoolPages; @@ -147,6 +149,7 @@ MiComputeNonPagedPoolVa(IN ULONG FreePages) NTSTATUS NTAPI +INIT_FUNCTION MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { PLIST_ENTRY NextEntry; @@ -157,7 +160,9 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock) MMPTE TempPde, TempPte; PVOID NonPagedPoolExpansionVa; KIRQL OldIrql; - + PMMPFN Pfn1; + ULONG Flags; + /* Check for kernel stack size that's too big */ if (MmLargeStackSize > (KERNEL_LARGE_STACK_SIZE / _1KB)) { @@ -196,7 +201,7 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock) // // Set CR3 for the system process // - PointerPte = MiAddressToPde(PTE_BASE); + PointerPte = MiAddressToPde(PDE_BASE); PageFrameIndex = PFN_FROM_PTE(PointerPte) << PAGE_SHIFT; PsGetCurrentProcess()->Pcb.DirectoryTableBase[0] = PageFrameIndex; @@ -307,11 +312,10 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock) MiComputeColorInformation(); // - // Calculate the number of bytes for the PFN database, double it for ARM3, + // Calculate the number of bytes for the PFN database // then add the color tables and convert to pages // MxPfnAllocation = (MmHighestPhysicalPage + 1) * sizeof(MMPFN); - //MxPfnAllocation <<= 1; MxPfnAllocation += (MmSecondaryColors * sizeof(MMCOLOR_TABLES) * 2); MxPfnAllocation >>= PAGE_SHIFT; @@ -531,6 +535,8 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock) OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); /* Allocate a page for hyperspace and create it */ + MI_SET_USAGE(MI_USAGE_PAGE_TABLE); + MI_SET_PROCESS2("Kernel"); PageFrameIndex = MiRemoveAnyPage(0); TempPde.u.Hard.PageFrameNumber = PageFrameIndex; TempPde.u.Hard.Global = FALSE; // Hyperspace is local! @@ -554,6 +560,9 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock) MmFirstReservedMappingPte = MiAddressToPte(MI_MAPPING_RANGE_START); MmLastReservedMappingPte = MiAddressToPte(MI_MAPPING_RANGE_END); MmFirstReservedMappingPte->u.Hard.PageFrameNumber = MI_HYPERSPACE_PTES; + + /* Set the working set address */ + MmWorkingSetList = (PVOID)MI_WORKING_SET_LIST; // // Reserve system PTEs for zeroing PTEs and clear them @@ -567,6 +576,28 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock) // MiFirstReservedZeroingPte->u.Hard.PageFrameNumber = MI_ZERO_PTES - 1; + /* Lock PFN database */ + OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); + + /* Reset the ref/share count so that MmInitializeProcessAddressSpace works */ + Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(MiAddressToPde(PDE_BASE))); + Pfn1->u2.ShareCount = 0; + Pfn1->u3.e2.ReferenceCount = 0; + + /* Get a page for the working set list */ + MI_SET_USAGE(MI_USAGE_PAGE_TABLE); + MI_SET_PROCESS2("Kernel WS List"); + PageFrameIndex = MiRemoveAnyPage(0); + TempPte.u.Hard.PageFrameNumber = PageFrameIndex; + + /* Map the working set list */ + PointerPte = MiAddressToPte(MmWorkingSetList); + MI_WRITE_VALID_PTE(PointerPte, TempPte); + + /* Zero it out, and save the frame index */ + RtlZeroMemory(MiPteToAddress(PointerPte), PAGE_SIZE); + PsGetCurrentProcess()->WorkingSetPage = PageFrameIndex; + /* Check for Pentium LOCK errata */ if (KiI386PentiumLockErrataPresent) { @@ -577,6 +608,43 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock) PointerPte->u.Hard.WriteThrough = 1; } + /* Release the lock */ + KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); + + /* Initialize the bogus address space */ + Flags = 0; + MmInitializeProcessAddressSpace(PsGetCurrentProcess(), NULL, NULL, &Flags, NULL); + + /* Make sure the color lists are valid */ + ASSERT(MmFreePagesByColor[0] < (PMMCOLOR_TABLES)PTE_BASE); + StartPde = MiAddressToPde(MmFreePagesByColor[0]); + ASSERT(StartPde->u.Hard.Valid == 1); + PointerPte = MiAddressToPte(MmFreePagesByColor[0]); + ASSERT(PointerPte->u.Hard.Valid == 1); + LastPte = MiAddressToPte((ULONG_PTR)&MmFreePagesByColor[1][MmSecondaryColors] - 1); + ASSERT(LastPte->u.Hard.Valid == 1); + + /* Loop the color list PTEs */ + while (PointerPte <= LastPte) + { + /* Get the PFN entry */ + Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte)); + if (!Pfn1->u3.e2.ReferenceCount) + { + /* Fill it out */ + Pfn1->u4.PteFrame = PFN_FROM_PTE(StartPde); + Pfn1->PteAddress = PointerPte; + Pfn1->u2.ShareCount++; + Pfn1->u3.e2.ReferenceCount = 1; + Pfn1->u3.e1.PageLocation = ActiveAndValid; + Pfn1->u3.e1.CacheAttribute = MiCached; + } + + /* Keep going */ + PointerPte++; + } + + /* All done */ return STATUS_SUCCESS; } diff --git a/ntoskrnl/mm/ARM3/largepag.c b/ntoskrnl/mm/ARM3/largepag.c index 01917b89876..601542b4005 100644 --- a/ntoskrnl/mm/ARM3/largepag.c +++ b/ntoskrnl/mm/ARM3/largepag.c @@ -31,6 +31,7 @@ BOOLEAN MiLargePageAllDrivers; VOID NTAPI +INIT_FUNCTION MiInitializeLargePageSupport(VOID) { #if _MI_PAGING_LEVELS > 2 @@ -50,6 +51,7 @@ MiInitializeLargePageSupport(VOID) VOID NTAPI +INIT_FUNCTION MiSyncCachedRanges(VOID) { ULONG i; @@ -64,6 +66,7 @@ MiSyncCachedRanges(VOID) VOID NTAPI +INIT_FUNCTION MiInitializeDriverLargePageList(VOID) { PWCHAR p, pp; diff --git a/ntoskrnl/mm/ARM3/mdlsup.c b/ntoskrnl/mm/ARM3/mdlsup.c index 6d63db132b7..b3449a366dc 100644 --- a/ntoskrnl/mm/ARM3/mdlsup.c +++ b/ntoskrnl/mm/ARM3/mdlsup.c @@ -1343,7 +1343,7 @@ MmUnlockPages(IN PMDL Mdl) InterlockedExchangeAddSizeT(&MmSystemLockPagesCount, -1); /* Do the last dereference, we're done here */ - MiDecrementReferenceCount(Pfn1, *MdlPages); + MiDecrementReferenceCount(Pfn1, MiGetPfnEntryIndex(Pfn1)); } else { diff --git a/ntoskrnl/mm/ARM3/miarm.h b/ntoskrnl/mm/ARM3/miarm.h index c736bc38c80..119ae547475 100644 --- a/ntoskrnl/mm/ARM3/miarm.h +++ b/ntoskrnl/mm/ARM3/miarm.h @@ -403,6 +403,7 @@ extern MMPTE HyperTemplatePte; extern MMPDE ValidKernelPde; extern MMPTE ValidKernelPte; extern MMPDE DemandZeroPde; +extern MMPTE DemandZeroPte; extern MMPTE PrototypePte; extern BOOLEAN MmLargeSystemCache; extern BOOLEAN MmZeroPageFile; @@ -512,6 +513,7 @@ extern BOOLEAN MmZeroingPageThreadActive; extern KEVENT MmZeroingPageEvent; extern ULONG MmSystemPageColor; extern ULONG MmProcessColorSeed; +extern PMMWSL MmWorkingSetList; // // Figures out the hardware bits for a PTE @@ -849,6 +851,18 @@ MI_GET_PROTOTYPE_PTE_FOR_VPN(IN PMMVAD Vad, return ProtoPte; } +// +// Returns the PFN Database entry for the given page number +// Warning: This is not necessarily a valid PFN database entry! +// +FORCEINLINE +PMMPFN +MI_PFN_ELEMENT(IN PFN_NUMBER Pfn) +{ + /* Get the entry */ + return &MmPfnDatabase[Pfn]; +}; + BOOLEAN NTAPI MmArmInitSystem( diff --git a/ntoskrnl/mm/ARM3/mminit.c b/ntoskrnl/mm/ARM3/mminit.c index 2a63047f837..6a36dd3acc8 100644 --- a/ntoskrnl/mm/ARM3/mminit.c +++ b/ntoskrnl/mm/ARM3/mminit.c @@ -365,6 +365,7 @@ FALSE; PFN_NUMBER NTAPI +INIT_FUNCTION MxGetNextPage(IN PFN_NUMBER PageCount) { PFN_NUMBER Pfn; @@ -389,6 +390,7 @@ MxGetNextPage(IN PFN_NUMBER PageCount) VOID NTAPI +INIT_FUNCTION MiComputeColorInformation(VOID) { ULONG L2Associativity; @@ -442,6 +444,7 @@ MiComputeColorInformation(VOID) VOID NTAPI +INIT_FUNCTION MiInitializeColorTables(VOID) { ULONG i; @@ -491,6 +494,7 @@ MiInitializeColorTables(VOID) BOOLEAN NTAPI +INIT_FUNCTION MiIsRegularMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PFN_NUMBER Pfn) { @@ -549,6 +553,7 @@ MiIsRegularMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock, VOID NTAPI +INIT_FUNCTION MiMapPfnDatabase(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { ULONG FreePage, FreePageCount, PagesLeft, BasePage, PageCount; @@ -644,6 +649,7 @@ MiMapPfnDatabase(IN PLOADER_PARAMETER_BLOCK LoaderBlock) VOID NTAPI +INIT_FUNCTION MiBuildPfnDatabaseFromPages(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { PMMPDE PointerPde; @@ -678,6 +684,10 @@ MiBuildPfnDatabaseFromPages(IN PLOADER_PARAMETER_BLOCK LoaderBlock) Pfn1->u3.e2.ReferenceCount = 1; Pfn1->u3.e1.PageLocation = ActiveAndValid; Pfn1->u3.e1.CacheAttribute = MiNonCached; +#if MI_TRACE_PFNS + Pfn1->PfnUsage = MI_USAGE_INIT_MEMORY; + memcpy(Pfn1->ProcessName, "Initial PDE", 16); +#endif } else { @@ -721,6 +731,10 @@ MiBuildPfnDatabaseFromPages(IN PLOADER_PARAMETER_BLOCK LoaderBlock) Pfn2->u3.e2.ReferenceCount = 1; Pfn2->u3.e1.PageLocation = ActiveAndValid; Pfn2->u3.e1.CacheAttribute = MiNonCached; +#if MI_TRACE_PFNS + Pfn2->PfnUsage = MI_USAGE_INIT_MEMORY; + memcpy(Pfn1->ProcessName, "Initial PTE", 16); +#endif } } } @@ -744,6 +758,7 @@ MiBuildPfnDatabaseFromPages(IN PLOADER_PARAMETER_BLOCK LoaderBlock) VOID NTAPI +INIT_FUNCTION MiBuildPfnDatabaseZeroPage(VOID) { PMMPFN Pfn1; @@ -766,6 +781,7 @@ MiBuildPfnDatabaseZeroPage(VOID) VOID NTAPI +INIT_FUNCTION MiBuildPfnDatabaseFromLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { PLIST_ENTRY NextEntry; @@ -876,6 +892,9 @@ MiBuildPfnDatabaseFromLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock) Pfn1->u3.e2.ReferenceCount = 1; Pfn1->u3.e1.PageLocation = ActiveAndValid; Pfn1->u3.e1.CacheAttribute = MiNonCached; +#if MI_TRACE_PFNS + Pfn1->PfnUsage = MI_USAGE_BOOT_DRIVER; +#endif /* Check for RAM disk page */ if (MdBlock->MemoryType == LoaderXIPRom) @@ -906,6 +925,7 @@ MiBuildPfnDatabaseFromLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock) VOID NTAPI +INIT_FUNCTION MiBuildPfnDatabaseSelf(VOID) { PMMPTE PointerPte, LastPte; @@ -923,6 +943,9 @@ MiBuildPfnDatabaseSelf(VOID) Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber); Pfn1->u2.ShareCount = 1; Pfn1->u3.e2.ReferenceCount = 1; +#if MI_TRACE_PFNS + Pfn1->PfnUsage = MI_USAGE_PFN_DATABASE; +#endif } /* Next */ @@ -932,6 +955,7 @@ MiBuildPfnDatabaseSelf(VOID) VOID NTAPI +INIT_FUNCTION MiInitializePfnDatabase(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { /* Scan memory and start setting up PFN entries */ @@ -949,6 +973,7 @@ MiInitializePfnDatabase(IN PLOADER_PARAMETER_BLOCK LoaderBlock) VOID NTAPI +INIT_FUNCTION MiAdjustWorkingSetManagerParameters(IN BOOLEAN Client) { /* This function needs to do more work, for now, we tune page minimums */ @@ -963,6 +988,7 @@ MiAdjustWorkingSetManagerParameters(IN BOOLEAN Client) VOID NTAPI +INIT_FUNCTION MiNotifyMemoryEvents(VOID) { /* Are we in a low-memory situation? */ @@ -988,6 +1014,7 @@ MiNotifyMemoryEvents(VOID) NTSTATUS NTAPI +INIT_FUNCTION MiCreateMemoryEvent(IN PUNICODE_STRING Name, OUT PKEVENT *Event) { @@ -1082,6 +1109,7 @@ CleanUp: BOOLEAN NTAPI +INIT_FUNCTION MiInitializeMemoryEvents(VOID) { UNICODE_STRING LowString = RTL_CONSTANT_STRING(L"\\KernelObjects\\LowMemoryCondition"); @@ -1160,6 +1188,7 @@ MiInitializeMemoryEvents(VOID) VOID NTAPI +INIT_FUNCTION MiAddHalIoMappings(VOID) { PVOID BaseAddress; @@ -1215,24 +1244,53 @@ MiAddHalIoMappings(VOID) VOID NTAPI -MmDumpArmPfnDatabase(VOID) +MmDumpArmPfnDatabase(IN BOOLEAN StatusOnly) { ULONG i; PMMPFN Pfn1; PCHAR Consumer = "Unknown"; KIRQL OldIrql; ULONG ActivePages = 0, FreePages = 0, OtherPages = 0; - - KeRaiseIrql(HIGH_LEVEL, &OldIrql); - +#if MI_TRACE_PFNS + ULONG UsageBucket[MI_USAGE_FREE_PAGE + 1] = {0}; + PCHAR MI_USAGE_TEXT[MI_USAGE_FREE_PAGE + 1] = + { + "Not set", + "Paged Pool", + "Nonpaged Pool", + "Nonpaged Pool Ex", + "Kernel Stack", + "Kernel Stack Ex", + "System PTE", + "VAD", + "PEB/TEB", + "Section", + "Page Table", + "Page Directory", + "Old Page Table", + "Driver Page", + "Contiguous Alloc", + "MDL", + "Demand Zero", + "Zero Loop", + "Cache", + "PFN Database", + "Boot Driver", + "Initial Memory", + "Free Page" + }; +#endif // // Loop the PFN database // + KeRaiseIrql(HIGH_LEVEL, &OldIrql); for (i = 0; i <= MmHighestPhysicalPage; i++) { Pfn1 = MiGetPfnEntry(i); if (!Pfn1) continue; - +#if MI_TRACE_PFNS + ASSERT(Pfn1->PfnUsage <= MI_USAGE_FREE_PAGE); +#endif // // Get the page location // @@ -1243,12 +1301,18 @@ MmDumpArmPfnDatabase(VOID) Consumer = "Active and Valid"; ActivePages++; break; - + + case ZeroedPageList: + + Consumer = "Zero Page List"; + FreePages++; + break;//continue; + case FreePageList: Consumer = "Free Page List"; FreePages++; - break; + break;//continue; default: @@ -1256,23 +1320,55 @@ MmDumpArmPfnDatabase(VOID) OtherPages++; break; } - + +#if MI_TRACE_PFNS + /* Add into bucket */ + UsageBucket[Pfn1->PfnUsage]++; +#endif + // // Pretty-print the page // - DbgPrint("0x%08p:\t%20s\t(%02d.%02d) [%08p-%08p])\n", + if (!StatusOnly) + DbgPrint("0x%08p:\t%20s\t(%04d.%04d)\t[%16s - %16s])\n", i << PAGE_SHIFT, Consumer, Pfn1->u3.e2.ReferenceCount, - Pfn1->u2.ShareCount, - Pfn1->PteAddress, - Pfn1->u4.PteFrame); + Pfn1->u2.ShareCount == LIST_HEAD ? 0xFFFF : Pfn1->u2.ShareCount, +#if MI_TRACE_PFNS + MI_USAGE_TEXT[Pfn1->PfnUsage], + Pfn1->ProcessName); +#else + "Page tracking", + "is disabled"); +#endif } - DbgPrint("Active: %d pages\t[%d KB]\n", ActivePages, (ActivePages << PAGE_SHIFT) / 1024); - DbgPrint("Free: %d pages\t[%d KB]\n", FreePages, (FreePages << PAGE_SHIFT) / 1024); - DbgPrint("Other: %d pages\t[%d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024); - + DbgPrint("Active: %5d pages\t[%6d KB]\n", ActivePages, (ActivePages << PAGE_SHIFT) / 1024); + DbgPrint("Free: %5d pages\t[%6d KB]\n", FreePages, (FreePages << PAGE_SHIFT) / 1024); + DbgPrint("-----------------------------------------\n"); +#if MI_TRACE_PFNS + OtherPages = UsageBucket[MI_USAGE_BOOT_DRIVER]; + DbgPrint("Boot Images: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024); + OtherPages = UsageBucket[MI_USAGE_DRIVER_PAGE]; + DbgPrint("System Drivers: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024); + OtherPages = UsageBucket[MI_USAGE_PFN_DATABASE]; + DbgPrint("PFN Database: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024); + OtherPages = UsageBucket[MI_USAGE_PAGE_TABLE] + UsageBucket[MI_USAGE_LEGACY_PAGE_DIRECTORY]; + DbgPrint("Page Tables: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024); + OtherPages = UsageBucket[MI_USAGE_NONPAGED_POOL] + UsageBucket[MI_USAGE_NONPAGED_POOL_EXPANSION]; + DbgPrint("NonPaged Pool: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024); + OtherPages = UsageBucket[MI_USAGE_PAGED_POOL]; + DbgPrint("Paged Pool: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024); + OtherPages = UsageBucket[MI_USAGE_KERNEL_STACK] + UsageBucket[MI_USAGE_KERNEL_STACK_EXPANSION]; + DbgPrint("Kernel Stack: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024); + OtherPages = UsageBucket[MI_USAGE_INIT_MEMORY]; + DbgPrint("Init Memory: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024); + OtherPages = UsageBucket[MI_USAGE_SECTION]; + DbgPrint("Sections: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024); + OtherPages = UsageBucket[MI_USAGE_CACHE]; + DbgPrint("Cache: %5d pages\t[%6d KB]\n", OtherPages, (OtherPages << PAGE_SHIFT) / 1024); +#endif KeLowerIrql(OldIrql); } @@ -1320,6 +1416,7 @@ MiPagesInLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock, PPHYSICAL_MEMORY_DESCRIPTOR NTAPI +INIT_FUNCTION MmInitializeMemoryLimits(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PBOOLEAN IncludeType) { @@ -1456,6 +1553,7 @@ MmInitializeMemoryLimits(IN PLOADER_PARAMETER_BLOCK LoaderBlock, VOID NTAPI +INIT_FUNCTION MiBuildPagedPool(VOID) { PMMPTE PointerPte, PointerPde; @@ -1565,6 +1663,8 @@ MiBuildPagedPool(VOID) OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); /* Allocate a page and map the first paged pool PDE */ + MI_SET_USAGE(MI_USAGE_PAGED_POOL); + MI_SET_PROCESS2("Kernel"); PageFrameIndex = MiRemoveZeroPage(0); TempPte.u.Hard.PageFrameNumber = PageFrameIndex; MI_WRITE_VALID_PTE(PointerPde, TempPte); @@ -1664,6 +1764,7 @@ MiBuildPagedPool(VOID) VOID NTAPI +INIT_FUNCTION MiDbgDumpMemoryDescriptors(VOID) { PLIST_ENTRY NextEntry; @@ -1715,6 +1816,7 @@ MiDbgDumpMemoryDescriptors(VOID) BOOLEAN NTAPI +INIT_FUNCTION MmArmInitSystem(IN ULONG Phase, IN PLOADER_PARAMETER_BLOCK LoaderBlock) { diff --git a/ntoskrnl/mm/ARM3/pagfault.c b/ntoskrnl/mm/ARM3/pagfault.c index 50304dad896..41cce6dcfc7 100644 --- a/ntoskrnl/mm/ARM3/pagfault.c +++ b/ntoskrnl/mm/ARM3/pagfault.c @@ -18,6 +18,10 @@ /* GLOBALS ********************************************************************/ +#if MI_TRACE_PFNS +BOOLEAN UserPdeFault = FALSE; +#endif + /* PRIVATE FUNCTIONS **********************************************************/ PMMPTE @@ -256,6 +260,12 @@ MiResolveDemandZeroFault(IN PVOID Address, /* Do we need a zero page? */ ASSERT(PointerPte->u.Hard.Valid == 0); +#if MI_TRACE_PFNS + if (UserPdeFault) MI_SET_USAGE(MI_USAGE_PAGE_TABLE); + if (!UserPdeFault) MI_SET_USAGE(MI_USAGE_DEMAND_ZERO); +#endif + if (Process) MI_SET_PROCESS2(Process->ImageFileName); + if (!Process) MI_SET_PROCESS2("Kernel Demand 0"); if ((NeedZero) && (Process)) { /* Try to get one, if we couldn't grab a free page and zero it */ @@ -594,13 +604,13 @@ MiDispatchFault(IN BOOLEAN StoreInstruction, PointerPte, Process, MM_NOIRQL); - ASSERT(KeAreAllApcsDisabled () == TRUE); + ASSERT(KeAreAllApcsDisabled() == TRUE); if (NT_SUCCESS(Status)) { // // Make sure we're returning in a sane state and pass the status down // - ASSERT(OldIrql == KeGetCurrentIrql ()); + ASSERT(OldIrql == KeGetCurrentIrql()); ASSERT(KeGetCurrentIrql() <= APC_LEVEL); return Status; } @@ -892,6 +902,9 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction, MI_WRITE_INVALID_PTE(PointerPde, DemandZeroPde); /* And go dispatch the fault on the PDE. This should handle the demand-zero */ +#if MI_TRACE_PFNS + UserPdeFault = TRUE; +#endif Status = MiDispatchFault(TRUE, PointerPte, PointerPde, @@ -900,7 +913,9 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction, PsGetCurrentProcess(), TrapInformation, NULL); - +#if MI_TRACE_PFNS + UserPdeFault = FALSE; +#endif /* We should come back with APCs enabled, and with a valid PDE */ ASSERT(KeAreAllApcsDisabled() == TRUE); #if (_MI_PAGING_LEVELS >= 3) @@ -976,6 +991,14 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction, MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread); return Status; } + + /* Is this a user address? */ + if (Address <= MM_HIGHEST_USER_ADDRESS) + { + /* Add an additional page table reference */ + MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++; + ASSERT(MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] <= PTE_COUNT); + } /* Did we get a prototype PTE back? */ if (!ProtoPte) @@ -987,6 +1010,8 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction, OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); /* Try to get a zero page */ + MI_SET_USAGE(MI_USAGE_PEB_TEB); + MI_SET_PROCESS2(CurrentProcess->ImageFileName); Color = MI_GET_NEXT_PROCESS_COLOR(CurrentProcess); PageFrameIndex = MiRemoveZeroPageSafe(Color); if (!PageFrameIndex) diff --git a/ntoskrnl/mm/ARM3/pfnlist.c b/ntoskrnl/mm/ARM3/pfnlist.c index 0a1d426637c..9c2f5bdbe18 100644 --- a/ntoskrnl/mm/ARM3/pfnlist.c +++ b/ntoskrnl/mm/ARM3/pfnlist.c @@ -55,6 +55,10 @@ PMMPFNLIST MmPageLocationList[] = NULL, NULL }; + +ULONG MI_PFN_CURRENT_USAGE; +CHAR MI_PFN_CURRENT_PROCESS_NAME[16] = "None yet"; + /* FUNCTIONS ******************************************************************/ VOID @@ -109,7 +113,7 @@ MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry) if (OldFlink != LIST_HEAD) { /* It is not, so set the backlink of the actual entry, to our backlink */ - MiGetPfnEntry(OldFlink)->u2.Blink = OldBlink; + MI_PFN_ELEMENT(OldFlink)->u2.Blink = OldBlink; } else { @@ -121,7 +125,7 @@ MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry) if (OldBlink != LIST_HEAD) { /* It is not, so set the backlink of the actual entry, to our backlink */ - MiGetPfnEntry(OldBlink)->u1.Flink = OldFlink; + MI_PFN_ELEMENT(OldBlink)->u1.Flink = OldFlink; } else { @@ -145,7 +149,7 @@ MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry) if (ColorTable->Flink != LIST_HEAD) { /* And make the previous link point to the head now */ - MiGetPfnEntry(ColorTable->Flink)->u4.PteFrame = COLORED_LIST_HEAD; + MI_PFN_ELEMENT(ColorTable->Flink)->u4.PteFrame = COLORED_LIST_HEAD; } else { @@ -159,14 +163,14 @@ MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry) ASSERT(Entry->u4.PteFrame != COLORED_LIST_HEAD); /* Make the back link point to whoever the next page is */ - Pfn1 = MiGetPfnEntry(Entry->u4.PteFrame); + Pfn1 = MI_PFN_ELEMENT(Entry->u4.PteFrame); Pfn1->OriginalPte.u.Long = Entry->OriginalPte.u.Long; /* Check if this page was pointing to the head */ if (Entry->OriginalPte.u.Long != LIST_HEAD) { /* Make the back link point to the head */ - Pfn1 = MiGetPfnEntry(Entry->OriginalPte.u.Long); + Pfn1 = MI_PFN_ELEMENT(Entry->OriginalPte.u.Long); Pfn1->u4.PteFrame = Entry->u4.PteFrame; } else @@ -204,6 +208,14 @@ MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry) { /* FIXME: Should wake up the MPW and working set manager, if we had one */ } + +#if MI_TRACE_PFNS + ASSERT(MI_PFN_CURRENT_USAGE != MI_USAGE_NOT_SET); + Entry->PfnUsage = MI_PFN_CURRENT_USAGE; + memcpy(Entry->ProcessName, MI_PFN_CURRENT_PROCESS_NAME, 16); +// MI_PFN_CURRENT_USAGE = MI_USAGE_NOT_SET; +// memcpy(MI_PFN_CURRENT_PROCESS_NAME, "Not Set", 16); +#endif } PFN_NUMBER @@ -223,7 +235,7 @@ MiRemovePageByColor(IN PFN_NUMBER PageIndex, ASSERT(Color < MmSecondaryColors); /* Get the PFN entry */ - Pfn1 = MiGetPfnEntry(PageIndex); + Pfn1 = MI_PFN_ELEMENT(PageIndex); ASSERT(Pfn1->u3.e1.RemovalRequested == 0); ASSERT(Pfn1->u3.e1.Rom == 0); @@ -248,19 +260,19 @@ MiRemovePageByColor(IN PFN_NUMBER PageIndex, if (OldFlink != LIST_HEAD) { /* It is not, so set the backlink of the actual entry, to our backlink */ - MiGetPfnEntry(OldFlink)->u2.Blink = OldBlink; + MI_PFN_ELEMENT(OldFlink)->u2.Blink = OldBlink; } else { /* Set the list head's backlink instead */ - ListHead->Blink = OldFlink; + ListHead->Blink = OldBlink; } /* Check if the back entry is the list head */ if (OldBlink != LIST_HEAD) { /* It is not, so set the backlink of the actual entry, to our backlink */ - MiGetPfnEntry(OldBlink)->u1.Flink = OldFlink; + MI_PFN_ELEMENT(OldBlink)->u1.Flink = OldFlink; } else { @@ -294,7 +306,7 @@ MiRemovePageByColor(IN PFN_NUMBER PageIndex, else { /* The list is empty, so we are the first page */ - MiGetPfnEntry(ColorTable->Flink)->u4.PteFrame = COLORED_LIST_HEAD; + MI_PFN_ELEMENT(ColorTable->Flink)->u4.PteFrame = COLORED_LIST_HEAD; } /* One less page */ @@ -321,6 +333,14 @@ MiRemovePageByColor(IN PFN_NUMBER PageIndex, /* FIXME: Should wake up the MPW and working set manager, if we had one */ } +#if MI_TRACE_PFNS + //ASSERT(MI_PFN_CURRENT_USAGE != MI_USAGE_NOT_SET); + Pfn1->PfnUsage = MI_PFN_CURRENT_USAGE; + memcpy(Pfn1->ProcessName, MI_PFN_CURRENT_PROCESS_NAME, 16); + //MI_PFN_CURRENT_USAGE = MI_USAGE_NOT_SET; + //memcpy(MI_PFN_CURRENT_PROCESS_NAME, "Not Set", 16); +#endif + /* Return the page */ return PageIndex; } @@ -336,18 +356,15 @@ MiRemoveAnyPage(IN ULONG Color) ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); ASSERT(MmAvailablePages != 0); ASSERT(Color < MmSecondaryColors); -#if 0 + /* Check the colored free list */ PageIndex = MmFreePagesByColor[FreePageList][Color].Flink; - DPRINT1("Found free page: %lx\n", PageIndex); if (PageIndex == LIST_HEAD) { /* Check the colored zero list */ PageIndex = MmFreePagesByColor[ZeroedPageList][Color].Flink; - DPRINT1("Found zero page: %lx\n", PageIndex); if (PageIndex == LIST_HEAD) { -#endif /* Check the free list */ ASSERT_LIST_INVARIANT(&MmFreePageListHead); PageIndex = MmFreePageListHead.Flink; @@ -365,15 +382,14 @@ MiRemoveAnyPage(IN ULONG Color) ASSERT(MmZeroedPageListHead.Total == 0); } } -#if 0 } } -#endif + /* Remove the page from its list */ PageIndex = MiRemovePageByColor(PageIndex, Color); /* Sanity checks */ - Pfn1 = MiGetPfnEntry(PageIndex); + Pfn1 = MI_PFN_ELEMENT(PageIndex); ASSERT((Pfn1->u3.e1.PageLocation == FreePageList) || (Pfn1->u3.e1.PageLocation == ZeroedPageList)); ASSERT(Pfn1->u3.e2.ReferenceCount == 0); @@ -399,11 +415,9 @@ MiRemoveZeroPage(IN ULONG Color) ASSERT(Color < MmSecondaryColors); /* Check the colored zero list */ -#if 0 PageIndex = MmFreePagesByColor[ZeroedPageList][Color].Flink; if (PageIndex == LIST_HEAD) { -#endif /* Check the zero list */ ASSERT_LIST_INVARIANT(&MmZeroedPageListHead); PageIndex = MmZeroedPageListHead.Flink; @@ -413,12 +427,11 @@ MiRemoveZeroPage(IN ULONG Color) /* This means there's no zero pages, we have to look for free ones */ ASSERT(MmZeroedPageListHead.Total == 0); Zero = TRUE; -#if 0 + /* Check the colored free list */ PageIndex = MmFreePagesByColor[FreePageList][Color].Flink; if (PageIndex == LIST_HEAD) { -#endif /* Check the free list */ ASSERT_LIST_INVARIANT(&MmFreePageListHead); PageIndex = MmFreePageListHead.Flink; @@ -429,22 +442,18 @@ MiRemoveZeroPage(IN ULONG Color) /* FIXME: Should check the standby list */ ASSERT(MmZeroedPageListHead.Total == 0); } -#if 0 } -#endif } -#if 0 } -#endif /* Sanity checks */ - Pfn1 = MiGetPfnEntry(PageIndex); + Pfn1 = MI_PFN_ELEMENT(PageIndex); ASSERT((Pfn1->u3.e1.PageLocation == FreePageList) || (Pfn1->u3.e1.PageLocation == ZeroedPageList)); /* Remove the page from its list */ PageIndex = MiRemovePageByColor(PageIndex, Color); - ASSERT(Pfn1 == MiGetPfnEntry(PageIndex)); + ASSERT(Pfn1 == MI_PFN_ELEMENT(PageIndex)); /* Zero it, if needed */ if (Zero) MiZeroPhysicalPage(PageIndex); @@ -477,7 +486,7 @@ MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex) (PageFrameIndex >= MmLowestPhysicalPage)); /* Get the PFN entry */ - Pfn1 = MiGetPfnEntry(PageFrameIndex); + Pfn1 = MI_PFN_ELEMENT(PageFrameIndex); /* Sanity checks that a right kind of page is being inserted here */ ASSERT(Pfn1->u4.MustBeCached == 0); @@ -496,7 +505,7 @@ MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex) if (LastPage != LIST_HEAD) { /* Link us with the previous page, so we're at the end now */ - MiGetPfnEntry(LastPage)->u1.Flink = PageFrameIndex; + MI_PFN_ELEMENT(LastPage)->u1.Flink = PageFrameIndex; } else { @@ -551,19 +560,15 @@ MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex) /* Get the previous page */ Blink = (PMMPFN)ColorTable->Blink; - /* Make it link to us */ - Pfn1->u4.PteFrame = MiGetPfnEntryIndex(Blink); - - /* If there is an original pte, it should be an old link, NOT a ReactOS RMAP */ - ASSERT(Blink->u4.AweAllocation == FALSE); + /* Make it link to us, and link back to it */ Blink->OriginalPte.u.Long = PageFrameIndex; + Pfn1->u4.PteFrame = MiGetPfnEntryIndex(Blink); } /* Now initialize our own list pointers */ ColorTable->Blink = Pfn1; - /* If there is an original pte, it should be an old link, NOT a ReactOS RMAP */ - ASSERT(Pfn1->u4.AweAllocation == FALSE); + /* This page is now the last */ Pfn1->OriginalPte.u.Long = LIST_HEAD; /* And increase the count in the colored list */ @@ -576,6 +581,11 @@ MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex) MmZeroingPageThreadActive = TRUE; KeSetEvent(&MmZeroingPageEvent, IO_NO_INCREMENT, FALSE); } + +#if MI_TRACE_PFNS + Pfn1->PfnUsage = MI_USAGE_FREE_PAGE; + RtlZeroMemory(Pfn1->ProcessName, 16); +#endif } /* Note: This function is hardcoded only for the zeroed page list, for now */ @@ -602,7 +612,7 @@ MiInsertPageInList(IN PMMPFNLIST ListHead, (PageFrameIndex >= MmLowestPhysicalPage)); /* Page should be unused */ - Pfn1 = MiGetPfnEntry(PageFrameIndex); + Pfn1 = MI_PFN_ELEMENT(PageFrameIndex); ASSERT(Pfn1->u3.e2.ReferenceCount == 0); ASSERT(Pfn1->u3.e1.Rom != 1); @@ -626,7 +636,7 @@ MiInsertPageInList(IN PMMPFNLIST ListHead, if (Flink != LIST_HEAD) { /* It wasn't, so update the backlink of the previous head page */ - Pfn2 = MiGetPfnEntry(Flink); + Pfn2 = MI_PFN_ELEMENT(Flink); Pfn2->u2.Blink = PageFrameIndex; } else @@ -666,9 +676,6 @@ MiInsertPageInList(IN PMMPFNLIST ListHead, /* Get the old head */ Flink = ColorHead->Flink; - /* If there is an original pte, it should be an old link, NOT a ReactOS RMAP */ - ASSERT(Pfn1->u4.AweAllocation == FALSE); - /* Make this page point back to the list, and point forwards to the old head */ Pfn1->OriginalPte.u.Long = Flink; Pfn1->u4.PteFrame = COLORED_LIST_HEAD; @@ -680,7 +687,7 @@ MiInsertPageInList(IN PMMPFNLIST ListHead, if (Flink != LIST_HEAD) { /* No, so make the old head point to this page */ - Pfn2 = MiGetPfnEntry(Flink); + Pfn2 = MI_PFN_ELEMENT(Flink); Pfn2->u4.PteFrame = PageFrameIndex; } else @@ -691,6 +698,13 @@ MiInsertPageInList(IN PMMPFNLIST ListHead, /* One more paged on the colored list */ ColorHead->Count++; + +#if MI_TRACE_PFNS + //ASSERT(MI_PFN_CURRENT_USAGE == MI_USAGE_NOT_SET); + Pfn1->PfnUsage = MI_USAGE_FREE_PAGE; + MI_PFN_CURRENT_USAGE = MI_USAGE_NOT_SET; + RtlZeroMemory(Pfn1->ProcessName, 16); +#endif } VOID @@ -705,7 +719,7 @@ MiInitializePfn(IN PFN_NUMBER PageFrameIndex, ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); /* Setup the PTE */ - Pfn1 = MiGetPfnEntry(PageFrameIndex); + Pfn1 = MI_PFN_ELEMENT(PageFrameIndex); Pfn1->PteAddress = PointerPte; /* Check if this PFN is part of a valid address space */ @@ -756,7 +770,7 @@ MiInitializePfn(IN PFN_NUMBER PageFrameIndex, Pfn1->u4.PteFrame = PageFrameIndex; /* Increase its share count so we don't get rid of it */ - Pfn1 = MiGetPfnEntry(PageFrameIndex); + Pfn1 = MI_PFN_ELEMENT(PageFrameIndex); Pfn1->u2.ShareCount++; } @@ -810,8 +824,9 @@ MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex) { ASSERT(PageFrameIndex > 0); - ASSERT(MiGetPfnEntry(PageFrameIndex) != NULL); - ASSERT(Pfn1 == MiGetPfnEntry(PageFrameIndex)); + ASSERT(MI_PFN_ELEMENT(PageFrameIndex) != NULL); + ASSERT(Pfn1 == MI_PFN_ELEMENT(PageFrameIndex)); + ASSERT(MI_IS_ROS_PFN(Pfn1) == FALSE); /* Page must be in-use */ if ((Pfn1->u3.e1.PageLocation != ActiveAndValid) && @@ -847,13 +862,7 @@ MiDecrementShareCount(IN PMMPFN Pfn1, /* Clear the last reference */ Pfn1->u3.e2.ReferenceCount = 0; - - /* - * OriginalPte is used by AweReferenceCount in ReactOS, but either - * ways we shouldn't be seeing RMAP entries at this point - */ ASSERT(Pfn1->OriginalPte.u.Soft.Prototype == 0); - ASSERT(Pfn1->u4.AweAllocation == FALSE); /* Mark the page temporarily as valid, we're going to make it free soon */ Pfn1->u3.e1.PageLocation = ActiveAndValid; @@ -879,7 +888,7 @@ MiDecrementReferenceCount(IN PMMPFN Pfn1, /* Sanity checks on the page */ ASSERT(PageFrameIndex < MmHighestPhysicalPage); - ASSERT(Pfn1 == MiGetPfnEntry(PageFrameIndex)); + ASSERT(Pfn1 == MI_PFN_ELEMENT(PageFrameIndex)); ASSERT(Pfn1->u3.e2.ReferenceCount != 0); /* Dereference the page, bail out if it's still alive */ @@ -921,7 +930,7 @@ MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex, PMMPFN Pfn1; /* Setup the PTE */ - Pfn1 = MiGetPfnEntry(PageFrameIndex); + Pfn1 = MI_PFN_ELEMENT(PageFrameIndex); Pfn1->PteAddress = PointerPte; /* Make this a software PTE */ @@ -942,7 +951,7 @@ MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex, Pfn1->u4.PteFrame = PteFrame; /* Increase its share count so we don't get rid of it */ - Pfn1 = MiGetPfnEntry(PteFrame); + Pfn1 = MI_PFN_ELEMENT(PteFrame); Pfn1->u2.ShareCount++; } } diff --git a/ntoskrnl/mm/ARM3/pool.c b/ntoskrnl/mm/ARM3/pool.c index 8156f6748f7..a808ff5d98d 100644 --- a/ntoskrnl/mm/ARM3/pool.c +++ b/ntoskrnl/mm/ARM3/pool.c @@ -177,6 +177,7 @@ MiProtectedPoolRemoveEntryList(IN PLIST_ENTRY Entry) VOID NTAPI +INIT_FUNCTION MiInitializeNonPagedPoolThresholds(VOID) { PFN_NUMBER Size = MmMaximumNonPagedPoolInPages; @@ -193,6 +194,7 @@ MiInitializeNonPagedPoolThresholds(VOID) VOID NTAPI +INIT_FUNCTION MiInitializePoolEvents(VOID) { KIRQL OldIrql; @@ -267,6 +269,7 @@ MiInitializePoolEvents(VOID) VOID NTAPI +INIT_FUNCTION MiInitializeNonPagedPool(VOID) { ULONG i; @@ -476,11 +479,10 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType, ASSERT(PointerPde->u.Hard.Valid == 0); /* Request a page */ - DPRINT1("Requesting %d PDEs\n", i); + MI_SET_USAGE(MI_USAGE_PAGED_POOL); + MI_SET_PROCESS2("Kernel"); PageFrameNumber = MiRemoveAnyPage(MI_GET_NEXT_COLOR()); TempPde.u.Hard.PageFrameNumber = PageFrameNumber; - DPRINT1("We have a PDE: %lx\n", PageFrameNumber); - #if (_MI_PAGING_LEVELS >= 3) /* On PAE/x64 systems, there's no double-buffering */ ASSERT(FALSE); @@ -773,6 +775,8 @@ MiAllocatePoolPages(IN POOL_TYPE PoolType, do { /* Allocate a page */ + MI_SET_USAGE(MI_USAGE_PAGED_POOL); + MI_SET_PROCESS2("Kernel"); PageFrameNumber = MiRemoveAnyPage(MI_GET_NEXT_COLOR()); /* Get the PFN entry for it and fill it out */ diff --git a/ntoskrnl/mm/ARM3/procsup.c b/ntoskrnl/mm/ARM3/procsup.c index 7fdca8d0d83..aec5af6e413 100644 --- a/ntoskrnl/mm/ARM3/procsup.c +++ b/ntoskrnl/mm/ARM3/procsup.c @@ -19,6 +19,7 @@ /* GLOBALS ********************************************************************/ ULONG MmProcessColorSeed = 0x12345678; +PMMWSL MmWorkingSetList; /* PRIVATE FUNCTIONS **********************************************************/ @@ -190,6 +191,7 @@ MmDeleteTeb(IN PEPROCESS Process, ASSERT((Vad->StartingVpn == ((ULONG_PTR)Teb >> PAGE_SHIFT) && (Vad->EndingVpn == (TebEnd >> PAGE_SHIFT)))); ASSERT(Vad->u.VadFlags.NoChange == TRUE); + ASSERT(Vad->u2.VadFlags2.OneSecured == TRUE); ASSERT(Vad->u2.VadFlags2.MultipleSecured == FALSE); /* Lock the working set */ @@ -362,6 +364,8 @@ MmCreateKernelStack(IN BOOLEAN GuiStack, PointerPte++; /* Get a page and write the current invalid PTE */ + MI_SET_USAGE(MI_USAGE_KERNEL_STACK); + MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName); PageFrameIndex = MiRemoveAnyPage(MI_GET_NEXT_COLOR()); MI_WRITE_INVALID_PTE(PointerPte, InvalidPte); @@ -446,6 +450,8 @@ MmGrowKernelStackEx(IN PVOID StackPointer, while (LimitPte >= NewLimitPte) { /* Get a page and write the current invalid PTE */ + MI_SET_USAGE(MI_USAGE_KERNEL_STACK_EXPANSION); + MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName); PageFrameIndex = MiRemoveAnyPage(MI_GET_NEXT_COLOR()); MI_WRITE_INVALID_PTE(LimitPte, InvalidPte); @@ -887,6 +893,32 @@ MmCreateTeb(IN PEPROCESS Process, return Status; } +VOID +NTAPI +MiInitializeWorkingSetList(IN PEPROCESS CurrentProcess) +{ + PMMPFN Pfn1; + + /* Setup some bogus list data */ + MmWorkingSetList->LastEntry = CurrentProcess->Vm.MinimumWorkingSetSize; + MmWorkingSetList->HashTable = NULL; + MmWorkingSetList->HashTableSize = 0; + MmWorkingSetList->NumberOfImageWaiters = 0; + MmWorkingSetList->Wsle = (PVOID)0xDEADBABE; + MmWorkingSetList->VadBitMapHint = 1; + MmWorkingSetList->HashTableStart = (PVOID)0xBADAB00B; + MmWorkingSetList->HighestPermittedHashAddress = (PVOID)0xCAFEBABE; + MmWorkingSetList->FirstFree = 1; + MmWorkingSetList->FirstDynamic = 2; + MmWorkingSetList->NextSlot = 3; + MmWorkingSetList->LastInitializedWsle = 4; + + /* The rule is that the owner process is always in the FLINK of the PDE's PFN entry */ + Pfn1 = MiGetPfnEntry(MiAddressToPte(PDE_BASE)->u.Hard.PageFrameNumber); + ASSERT(Pfn1->u4.PteFrame == MiGetPfnEntryIndex(Pfn1)); + Pfn1->u1.Event = (PKEVENT)CurrentProcess; +} + NTSTATUS NTAPI MmInitializeProcessAddressSpace(IN PEPROCESS Process, @@ -907,6 +939,7 @@ MmInitializeProcessAddressSpace(IN PEPROCESS Process, PWCHAR Source; PCHAR Destination; USHORT Length = 0; + MMPTE TempPte; /* We should have a PDE */ ASSERT(Process->Pcb.DirectoryTableBase[0] != 0); @@ -939,6 +972,22 @@ MmInitializeProcessAddressSpace(IN PEPROCESS Process, PointerPde = MiAddressToPde(HYPER_SPACE); PageFrameNumber = PFN_FROM_PTE(PointerPde); MiInitializePfn(PageFrameNumber, PointerPde, TRUE); + + /* Setup the PFN for the PTE for the working set */ + PointerPte = MiAddressToPte(MI_WORKING_SET_LIST); + MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, MM_READWRITE, 0); + ASSERT(PointerPte->u.Long != 0); + PageFrameNumber = PFN_FROM_PTE(PointerPte); + MI_WRITE_INVALID_PTE(PointerPte, DemandZeroPte); + MiInitializePfn(PageFrameNumber, PointerPte, TRUE); + TempPte.u.Hard.PageFrameNumber = PageFrameNumber; + MI_WRITE_VALID_PTE(PointerPte, TempPte); + + /* Now initialize the working set list */ + MiInitializeWorkingSetList(Process); + + /* Sanity check */ + ASSERT(Process->PhysicalVadRoot == NULL); /* Release PFN lock */ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); @@ -1018,6 +1067,7 @@ MmInitializeProcessAddressSpace(IN PEPROCESS Process, NTSTATUS NTAPI +INIT_FUNCTION MmInitializeHandBuiltProcess(IN PEPROCESS Process, IN PULONG_PTR DirectoryTableBase) { @@ -1039,6 +1089,7 @@ MmInitializeHandBuiltProcess(IN PEPROCESS Process, NTSTATUS NTAPI +INIT_FUNCTION MmInitializeHandBuiltProcess2(IN PEPROCESS Process) { /* Lock the VAD, ARM3-owned ranges away */ @@ -1055,12 +1106,13 @@ MmCreateProcessAddressSpace(IN ULONG MinWs, OUT PULONG_PTR DirectoryTableBase) { KIRQL OldIrql; - PFN_NUMBER PdeIndex, HyperIndex; + PFN_NUMBER PdeIndex, HyperIndex, WsListIndex; PMMPTE PointerPte; MMPTE TempPte, PdePte; ULONG PdeOffset; - PMMPTE SystemTable; + PMMPTE SystemTable, HyperTable; ULONG Color; + PMMPFN Pfn1; /* Choose a process color */ Process->NextPageColor = RtlRandom(&MmProcessColorSeed); @@ -1073,6 +1125,7 @@ MmCreateProcessAddressSpace(IN ULONG MinWs, /* Get a zero page for the PDE, if possible */ Color = MI_GET_NEXT_PROCESS_COLOR(Process); + MI_SET_USAGE(MI_USAGE_PAGE_DIRECTORY); PdeIndex = MiRemoveZeroPageSafe(Color); if (!PdeIndex) { @@ -1086,6 +1139,7 @@ MmCreateProcessAddressSpace(IN ULONG MinWs, } /* Get a zero page for hyperspace, if possible */ + MI_SET_USAGE(MI_USAGE_PAGE_DIRECTORY); Color = MI_GET_NEXT_PROCESS_COLOR(Process); HyperIndex = MiRemoveZeroPageSafe(Color); if (!HyperIndex) @@ -1096,6 +1150,21 @@ MmCreateProcessAddressSpace(IN ULONG MinWs, /* Zero it outside the PFN lock */ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); MiZeroPhysicalPage(HyperIndex); + OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); + } + + /* Get a zero page for the woring set list, if possible */ + MI_SET_USAGE(MI_USAGE_PAGE_TABLE); + Color = MI_GET_NEXT_PROCESS_COLOR(Process); + WsListIndex = MiRemoveZeroPageSafe(Color); + if (!WsListIndex) + { + /* No zero pages, grab a free one */ + WsListIndex = MiRemoveAnyPage(Color); + + /* Zero it outside the PFN lock */ + KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); + MiZeroPhysicalPage(WsListIndex); } else { @@ -1108,11 +1177,42 @@ MmCreateProcessAddressSpace(IN ULONG MinWs, Process->AddressSpaceInitialized = 1; /* Set the base directory pointers */ + Process->WorkingSetPage = WsListIndex; DirectoryTableBase[0] = PdeIndex << PAGE_SHIFT; DirectoryTableBase[1] = HyperIndex << PAGE_SHIFT; /* Make sure we don't already have a page directory setup */ ASSERT(Process->Pcb.DirectoryTableBase[0] == 0); + + /* Get a PTE to map hyperspace */ + PointerPte = MiReserveSystemPtes(1, SystemPteSpace); + ASSERT(PointerPte != NULL); + + /* Build it */ + MI_MAKE_HARDWARE_PTE_KERNEL(&PdePte, + PointerPte, + MM_READWRITE, + HyperIndex); + + /* Set it dirty and map it */ + PdePte.u.Hard.Dirty = TRUE; + MI_WRITE_VALID_PTE(PointerPte, PdePte); + + /* Now get hyperspace's page table */ + HyperTable = MiPteToAddress(PointerPte); + + /* Now write the PTE/PDE entry for the working set list index itself */ + TempPte = ValidKernelPte; + TempPte.u.Hard.PageFrameNumber = WsListIndex; + PdeOffset = MiAddressToPteOffset(MmWorkingSetList); + HyperTable[PdeOffset] = TempPte; + + /* Let go of the system PTE */ + MiReleaseSystemPtes(PointerPte, 1, SystemPteSpace); + + /* Save the PTE address of the page directory itself */ + Pfn1 = MiGetPfnEntry(PdeIndex); + Pfn1->PteAddress = (PMMPTE)PDE_BASE; /* Insert us into the Mm process list */ InsertTailList(&MmProcessList, &Process->MmProcessLinks); @@ -1169,9 +1269,15 @@ MmCleanProcessAddressSpace(IN PEPROCESS Process) PMM_AVL_TABLE VadTree; PETHREAD Thread = PsGetCurrentThread(); + /* Only support this */ + ASSERT(Process->AddressSpaceInitialized == 2); + /* Lock the process address space from changes */ MmLockAddressSpace(&Process->Vm); + /* VM is deleted now */ + Process->VmDeleted = TRUE; + /* Enumerate the VADs */ VadTree = &Process->VadRoot; while (VadTree->NumberGenericTableElements) diff --git a/ntoskrnl/mm/ARM3/section.c b/ntoskrnl/mm/ARM3/section.c index 30f6b4c0a03..872c10e27a2 100644 --- a/ntoskrnl/mm/ARM3/section.c +++ b/ntoskrnl/mm/ARM3/section.c @@ -339,6 +339,8 @@ MiFillSystemPageDirectory(IN PVOID Base, if (SystemMapPde->u.Hard.Valid == 0) { /* Grab a page for it */ + MI_SET_USAGE(MI_USAGE_PAGE_TABLE); + MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName); PageFrameIndex = MiRemoveZeroPage(MI_GET_NEXT_COLOR()); ASSERT(PageFrameIndex); TempPde.u.Hard.PageFrameNumber = PageFrameIndex; diff --git a/ntoskrnl/mm/ARM3/sysldr.c b/ntoskrnl/mm/ARM3/sysldr.c index 7990b82d2e6..673ef30afa1 100644 --- a/ntoskrnl/mm/ARM3/sysldr.c +++ b/ntoskrnl/mm/ARM3/sysldr.c @@ -166,12 +166,24 @@ MiLoadImageSection(IN OUT PVOID *SectionPtr, /* The driver is here */ *ImageBase = DriverBase; + DPRINT1("Loading: %wZ at %p with %lx pages\n", FileName, DriverBase, PteCount); /* Loop the new driver PTEs */ TempPte = ValidKernelPte; while (PointerPte < LastPte) { /* Allocate a page */ + MI_SET_USAGE(MI_USAGE_DRIVER_PAGE); +#if MI_TRACE_PFNS + PWCHAR pos = NULL; + ULONG len = 0; + if (FileName->Buffer) + { + pos = wcsrchr(FileName->Buffer, '\\'); + len = wcslen(pos) * sizeof(WCHAR); + if (pos) snprintf(MI_PFN_CURRENT_PROCESS_NAME, min(16, len), "%S", pos); + } +#endif TempPte.u.Hard.PageFrameNumber = MiAllocatePfn(PointerPte, MM_EXECUTE); /* Write it */ @@ -551,6 +563,7 @@ MiProcessLoaderEntry(IN PLDR_DATA_TABLE_ENTRY LdrEntry, VOID NTAPI +INIT_FUNCTION MiUpdateThunks(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PVOID OldBase, IN PVOID NewBase, @@ -1286,7 +1299,7 @@ CheckDllState: /* Check if we have an import list */ if (LoadedImports) { - /* Reset the count again, and loop entries*/ + /* Reset the count again, and loop entries */ ImportCount = 0; for (i = 0; i < LoadedImports->Count; i++) { @@ -1352,6 +1365,7 @@ CheckDllState: VOID NTAPI +INIT_FUNCTION MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { PLIST_ENTRY NextEntry; @@ -1385,6 +1399,23 @@ MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock) (ULONG_PTR)LdrEntry->DllBase + LdrEntry->SizeOfImage, &LdrEntry->FullDllName); + /* Get the first PTE and the number of PTEs we'll need */ + PointerPte = StartPte = MiAddressToPte(LdrEntry->DllBase); + PteCount = ROUND_TO_PAGES(LdrEntry->SizeOfImage) >> PAGE_SHIFT; + LastPte = StartPte + PteCount; + +#if MI_TRACE_PFNS + /* Loop the PTEs */ + while (PointerPte < LastPte) + { + ULONG len; + ASSERT(PointerPte->u.Hard.Valid == 1); + Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte)); + len = wcslen(LdrEntry->BaseDllName.Buffer) * sizeof(WCHAR); + snprintf(Pfn1->ProcessName, min(16, len), "%S", LdrEntry->BaseDllName.Buffer); + PointerPte++; + } +#endif /* Skip kernel and HAL */ /* ROS HACK: Skip BOOTVID/KDCOM too */ i++; @@ -1424,12 +1455,8 @@ MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock) /* Remember the original address */ DllBase = LdrEntry->DllBase; - /* Get the first PTE and the number of PTEs we'll need */ - PointerPte = StartPte = MiAddressToPte(LdrEntry->DllBase); - PteCount = ROUND_TO_PAGES(LdrEntry->SizeOfImage) >> PAGE_SHIFT; - LastPte = StartPte + PteCount; - /* Loop the PTEs */ + PointerPte = StartPte; while (PointerPte < LastPte) { /* Mark the page modified in the PFN database */ @@ -1527,6 +1554,7 @@ MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock) NTSTATUS NTAPI +INIT_FUNCTION MiBuildImportsForBootDrivers(VOID) { PLIST_ENTRY NextEntry, NextEntry2; @@ -1792,6 +1820,7 @@ MiBuildImportsForBootDrivers(VOID) VOID NTAPI +INIT_FUNCTION MiLocateKernelSections(IN PLDR_DATA_TABLE_ENTRY LdrEntry) { ULONG_PTR DllBase; @@ -1852,6 +1881,7 @@ MiLocateKernelSections(IN PLDR_DATA_TABLE_ENTRY LdrEntry) BOOLEAN NTAPI +INIT_FUNCTION MiInitializeLoadedModuleList(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { PLDR_DATA_TABLE_ENTRY LdrEntry, NewEntry; diff --git a/ntoskrnl/mm/ARM3/syspte.c b/ntoskrnl/mm/ARM3/syspte.c index a70ebda3c07..401550d8edf 100644 --- a/ntoskrnl/mm/ARM3/syspte.c +++ b/ntoskrnl/mm/ARM3/syspte.c @@ -366,6 +366,7 @@ MiReleaseSystemPtes(IN PMMPTE StartingPte, VOID NTAPI +INIT_FUNCTION MiInitializeSystemPtes(IN PMMPTE StartingPte, IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE PoolType) diff --git a/ntoskrnl/mm/ARM3/virtual.c b/ntoskrnl/mm/ARM3/virtual.c index 16bbad16350..809d7e501c0 100644 --- a/ntoskrnl/mm/ARM3/virtual.c +++ b/ntoskrnl/mm/ARM3/virtual.c @@ -160,7 +160,7 @@ MiDeleteSystemPageableVm(IN PMMPTE PointerPte, MiDecrementShareCount(Pfn1, PageFrameIndex); /* Decrement the page table too */ - DPRINT("FIXME: ARM3 should decrement the PT refcount for: %p\n", Pfn2); + DPRINT("FIXME: ARM3 should decrement the pool PDE refcount for: %p\n", PageTableIndex); #if 0 // ARM3: Dont't trust this yet MiDecrementShareCount(Pfn2, PageTableIndex); #endif @@ -184,7 +184,7 @@ MiDeleteSystemPageableVm(IN PMMPTE PointerPte, * * Right now, we shouldn't expect any page file information in the PTE */ - ASSERT(PointerPte->u.Soft.PageFileHigh == 0); + ASSERT(PointerPte->u.Soft.PageFileHigh == 0); /* Destroy the PTE */ PointerPte->u.Long = 0; @@ -259,7 +259,7 @@ MiDeletePte(IN PMMPTE PointerPte, } #endif /* FIXME: Drop the reference on the page table. For now, leak it until RosMM is gone */ - //MiDecrementShareCount(MiGetPfnEntry(PFN_FROM_PTE(PointerPde)), PFN_FROM_PDE(PointerPde)); + //MiDecrementShareCount(MiGetPfnEntry(PFN_FROM_PTE(PointerPde)), PFN_FROM_PTE(PointerPde)); /* Drop the share count */ MiDecrementShareCount(Pfn1, PageFrameIndex); diff --git a/ntoskrnl/mm/ARM3/zeropage.c b/ntoskrnl/mm/ARM3/zeropage.c index 4735cfbadf4..5a7aee0d3a6 100644 --- a/ntoskrnl/mm/ARM3/zeropage.c +++ b/ntoskrnl/mm/ARM3/zeropage.c @@ -39,6 +39,7 @@ MmZeroPageThread(VOID) /* FIXME: Get the discardable sections to free them */ // MiFindInitializationCode(&StartAddress, &EndAddress); // if (StartAddress) MiFreeInitializationCode(StartAddress, EndAddress); + DPRINT1("Free non-cache pages: %lx\n", MmAvailablePages + MiMemoryConsumers[MC_CACHE].PagesUsed); /* Set our priority to 0 */ Thread->BasePriority = 0; @@ -71,6 +72,8 @@ MmZeroPageThread(VOID) PageIndex = MmFreePageListHead.Flink; ASSERT(PageIndex != LIST_HEAD); Pfn1 = MiGetPfnEntry(PageIndex); + MI_SET_USAGE(MI_USAGE_ZERO_LOOP); + MI_SET_PROCESS2("Kernel 0 Loop"); FreePage = MiRemoveAnyPage(MI_GET_PAGE_COLOR(PageIndex)); /* The first global free page should also be the first on its own list */ diff --git a/ntoskrnl/mm/anonmem.c b/ntoskrnl/mm/anonmem.c index 5f44fc745fd..766a8fc17c2 100644 --- a/ntoskrnl/mm/anonmem.c +++ b/ntoskrnl/mm/anonmem.c @@ -367,6 +367,8 @@ MmNotPresentFaultVirtualMemory(PMMSUPPORT AddressSpace, /* * Try to allocate a page */ + MI_SET_USAGE(MI_USAGE_VAD); + MI_SET_PROCESS2(Process->ImageFileName); Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page); if (Status == STATUS_NO_MEMORY) { diff --git a/ntoskrnl/mm/freelist.c b/ntoskrnl/mm/freelist.c index e7bf276600a..7eef9593f95 100644 --- a/ntoskrnl/mm/freelist.c +++ b/ntoskrnl/mm/freelist.c @@ -79,6 +79,8 @@ MmGetLRUFirstUserPage(VOID) if (Position == 0xFFFFFFFF) return 0; /* Return it */ + ASSERT(Position != 0); + ASSERT_IS_ROS_PFN(MiGetPfnEntry(Position)); return Position; } @@ -89,6 +91,8 @@ MmInsertLRULastUserPage(PFN_NUMBER Pfn) KIRQL OldIrql; /* Set the page as a user page */ + ASSERT(Pfn != 0); + ASSERT_IS_ROS_PFN(MiGetPfnEntry(Pfn)); OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); RtlSetBit(&MiUserPfnBitMap, Pfn); KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); @@ -108,6 +112,8 @@ MmGetLRUNextUserPage(PFN_NUMBER PreviousPfn) if (Position == 0xFFFFFFFF) return 0; /* Return it */ + ASSERT(Position != 0); + ASSERT_IS_ROS_PFN(MiGetPfnEntry(Position)); return Position; } @@ -116,6 +122,8 @@ NTAPI MmRemoveLRUUserPage(PFN_NUMBER Page) { /* Unset the page as a user page */ + ASSERT(Page != 0); + ASSERT_IS_ROS_PFN(MiGetPfnEntry(Page)); RtlClearBit(&MiUserPfnBitMap, Page); } @@ -222,6 +230,8 @@ MiAllocatePagesForMdl(IN PHYSICAL_ADDRESS LowAddress, while (PagesFound < PageCount) { /* Grab a page */ + MI_SET_USAGE(MI_USAGE_MDL); + MI_SET_PROCESS2("Kernel"); Page = MiRemoveAnyPage(0); if (Page == 0) { @@ -238,12 +248,14 @@ MiAllocatePagesForMdl(IN PHYSICAL_ADDRESS LowAddress, // ASSERT(Pfn1->u3.e2.ReferenceCount == 0); - // - // Allocate it and mark it - // + /* Now setup the page and mark it */ + Pfn1->u3.e2.ReferenceCount = 1; + Pfn1->u2.ShareCount = 1; + MI_SET_PFN_DELETED(Pfn1); + Pfn1->u4.PteFrame = 0x1FFEDCB; Pfn1->u3.e1.StartOfAllocation = 1; Pfn1->u3.e1.EndOfAllocation = 1; - Pfn1->u3.e2.ReferenceCount = 1; + Pfn1->u4.VerifierAllocation = 0; // // Save it into the MDL @@ -278,6 +290,8 @@ MiAllocatePagesForMdl(IN PHYSICAL_ADDRESS LowAddress, /* Remove the page from the free or zero list */ ASSERT(Pfn1->u3.e1.ReadInProgress == 0); + MI_SET_USAGE(MI_USAGE_MDL); + MI_SET_PROCESS2("Kernel"); MiUnlinkFreeOrZeroedPage(Pfn1); // @@ -362,21 +376,13 @@ MiAllocatePagesForMdl(IN PHYSICAL_ADDRESS LowAddress, } // - // We're done, mark the pages as locked (should we lock them, though???) + // We're done, mark the pages as locked // Mdl->Process = NULL; Mdl->MdlFlags |= MDL_PAGES_LOCKED; return Mdl; } -VOID -NTAPI -MmDumpPfnDatabase(VOID) -{ - /* Pretty useless for now, to be improved later */ - return; -} - VOID NTAPI MmSetRmapListHeadPage(PFN_NUMBER Pfn, PMM_RMAP_ENTRY ListHead) diff --git a/ntoskrnl/mm/i386/page.c b/ntoskrnl/mm/i386/page.c index e096fcf3f56..a7dbce4127e 100644 --- a/ntoskrnl/mm/i386/page.c +++ b/ntoskrnl/mm/i386/page.c @@ -223,6 +223,9 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create) MmDeleteHyperspaceMapping(PageDir); return NULL; } + MI_SET_USAGE(MI_USAGE_LEGACY_PAGE_DIRECTORY); + if (Process) MI_SET_PROCESS2(Process->ImageFileName); + if (!Process) MI_SET_PROCESS2("Kernel Legacy"); Status = MmRequestPageMemoryConsumer(MC_SYSTEM, FALSE, &Pfn); if (!NT_SUCCESS(Status) || Pfn == 0) { @@ -258,6 +261,9 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create) { return NULL; } + MI_SET_USAGE(MI_USAGE_LEGACY_PAGE_DIRECTORY); + if (Process) MI_SET_PROCESS2(Process->ImageFileName); + if (!Process) MI_SET_PROCESS2("Kernel Legacy"); Status = MmRequestPageMemoryConsumer(MC_SYSTEM, FALSE, &Pfn); if (!NT_SUCCESS(Status) || Pfn == 0) { @@ -280,6 +286,9 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create) { return NULL; } + MI_SET_USAGE(MI_USAGE_LEGACY_PAGE_DIRECTORY); + if (Process) MI_SET_PROCESS2(Process->ImageFileName); + if (!Process) MI_SET_PROCESS2("Kernel Legacy"); Status = MmRequestPageMemoryConsumer(MC_SYSTEM, FALSE, &Pfn); if (!NT_SUCCESS(Status) || Pfn == 0) { @@ -465,6 +474,18 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN FreePage, } } +VOID +NTAPI +MmGetPageFileMapping(PEPROCESS Process, PVOID Address, + SWAPENTRY* SwapEntry) +/* + * FUNCTION: Get a page file mapping + */ +{ + ULONG Entry = MmGetPageEntryForProcess(Process, Address); + *SwapEntry = Entry >> 1; +} + VOID NTAPI MmDeletePageFileMapping(PEPROCESS Process, PVOID Address, diff --git a/ntoskrnl/mm/marea.c b/ntoskrnl/mm/marea.c index e2a8243ab97..cacf2ae667e 100644 --- a/ntoskrnl/mm/marea.c +++ b/ntoskrnl/mm/marea.c @@ -493,13 +493,16 @@ MmFindGapBottomUp( break; AlignedAddress = MM_ROUND_UP(PreviousNode->EndingAddress, Granularity); - if (Node->StartingAddress > AlignedAddress && - (ULONG_PTR)Node->StartingAddress - (ULONG_PTR)AlignedAddress >= Length) + if (AlignedAddress >= LowestAddress) { - DPRINT("MmFindGapBottomUp: %p\n", AlignedAddress); - return AlignedAddress; + if (Node->StartingAddress > AlignedAddress && + (ULONG_PTR)Node->StartingAddress - (ULONG_PTR)AlignedAddress >= Length) + { + DPRINT("MmFindGapBottomUp: %p\n", AlignedAddress); + ASSERT(AlignedAddress >= LowestAddress); + return AlignedAddress; + } } - PreviousNode = Node; } @@ -509,6 +512,7 @@ MmFindGapBottomUp( (ULONG_PTR)HighestAddress - (ULONG_PTR)AlignedAddress >= Length) { DPRINT("MmFindGapBottomUp: %p\n", AlignedAddress); + ASSERT(AlignedAddress >= LowestAddress); return AlignedAddress; } @@ -518,6 +522,7 @@ MmFindGapBottomUp( (ULONG_PTR)FirstNode->StartingAddress - (ULONG_PTR)AlignedAddress >= Length) { DPRINT("MmFindGapBottomUp: %p\n", AlignedAddress); + ASSERT(AlignedAddress >= LowestAddress); return AlignedAddress; } diff --git a/ntoskrnl/mm/mmfault.c b/ntoskrnl/mm/mmfault.c index bf8b2e014c7..9a3ecf9f0ef 100644 --- a/ntoskrnl/mm/mmfault.c +++ b/ntoskrnl/mm/mmfault.c @@ -9,6 +9,9 @@ /* INCLUDES *******************************************************************/ #include +#ifdef NEWCC +#include "../cache/section/newmm.h" +#endif #define NDEBUG #include @@ -85,6 +88,18 @@ MmpAccessFault(KPROCESSOR_MODE Mode, Status = STATUS_ACCESS_VIOLATION; break; +#ifdef NEWCC + case MEMORY_AREA_CACHE: + // This code locks for itself to keep from having to break a lock + // passed in. + if (!FromMdl) + MmUnlockAddressSpace(AddressSpace); + Status = MmAccessFaultCacheSection(Mode, Address, Locked); + if (!FromMdl) + MmLockAddressSpace(AddressSpace); + break; +#endif + default: Status = STATUS_ACCESS_VIOLATION; break; @@ -175,6 +190,18 @@ MmNotPresentFault(KPROCESSOR_MODE Mode, Locked); break; +#ifdef NEWCC + case MEMORY_AREA_CACHE: + // This code locks for itself to keep from having to break a lock + // passed in. + if (!FromMdl) + MmUnlockAddressSpace(AddressSpace); + Status = MmNotPresentFaultCacheSection(Mode, Address, Locked); + if (!FromMdl) + MmLockAddressSpace(AddressSpace); + break; +#endif + default: Status = STATUS_ACCESS_VIOLATION; break; diff --git a/ntoskrnl/mm/mminit.c b/ntoskrnl/mm/mminit.c index df2140c9cc7..1ad5b5cc0d4 100644 --- a/ntoskrnl/mm/mminit.c +++ b/ntoskrnl/mm/mminit.c @@ -231,6 +231,7 @@ MiInitSystemMemoryAreas() VOID NTAPI +INIT_FUNCTION MiDbgDumpAddressSpace(VOID) { // @@ -302,12 +303,17 @@ MmMpwThreadMain(PVOID Ignored) PagesWritten = 0; +#ifndef NEWCC + // XXX arty -- we flush when evicting pages or destorying cache + // sections. CcRosFlushDirtyPages(128, &PagesWritten); +#endif } } NTSTATUS NTAPI +INIT_FUNCTION MmInitMpwThread(VOID) { KPRIORITY Priority; @@ -339,6 +345,7 @@ MmInitMpwThread(VOID) NTSTATUS NTAPI +INIT_FUNCTION MmInitBsmThread(VOID) { NTSTATUS Status; @@ -362,6 +369,7 @@ MmInitBsmThread(VOID) BOOLEAN NTAPI +INIT_FUNCTION MmInitSystem(IN ULONG Phase, IN PLOADER_PARAMETER_BLOCK LoaderBlock) { diff --git a/ntoskrnl/mm/pagefile.c b/ntoskrnl/mm/pagefile.c index a9c1c6ab0f9..2b3274aad67 100644 --- a/ntoskrnl/mm/pagefile.c +++ b/ntoskrnl/mm/pagefile.c @@ -252,6 +252,7 @@ MmWriteToSwapPage(SWAPENTRY SwapEntry, PFN_NUMBER Page) MmInitializeMdl(Mdl, NULL, PAGE_SIZE); MmBuildMdlFromPages(Mdl, &Page); + MmReferencePage(Page); Mdl->MdlFlags |= MDL_PAGES_LOCKED; file_offset.QuadPart = offset * PAGE_SIZE; @@ -313,6 +314,7 @@ MmReadFromSwapPage(SWAPENTRY SwapEntry, PFN_NUMBER Page) MmInitializeMdl(Mdl, NULL, PAGE_SIZE); MmBuildMdlFromPages(Mdl, &Page); + MmReferencePage(Page); Mdl->MdlFlags |= MDL_PAGES_LOCKED; file_offset.QuadPart = offset * PAGE_SIZE; diff --git a/ntoskrnl/mm/rmap.c b/ntoskrnl/mm/rmap.c index aa2f96ee3b4..8d6867e50cc 100644 --- a/ntoskrnl/mm/rmap.c +++ b/ntoskrnl/mm/rmap.c @@ -10,6 +10,9 @@ /* INCLUDES *****************************************************************/ #include +#ifdef NEWCC +#include "../cache/section/newmm.h" +#endif #define NDEBUG #include @@ -21,8 +24,8 @@ /* GLOBALS ******************************************************************/ -static FAST_MUTEX RmapListLock; static NPAGED_LOOKASIDE_LIST RmapLookasideList; +FAST_MUTEX RmapListLock; /* FUNCTIONS ****************************************************************/ @@ -65,6 +68,7 @@ MmPageOutPhysicalAddress(PFN_NUMBER Page) Process = entry->Process; Address = entry->Address; + if ((((ULONG_PTR)Address) & 0xFFF) != 0) { KeBugCheck(MEMORY_MANAGEMENT); @@ -193,8 +197,11 @@ MmSetCleanAllRmaps(PFN_NUMBER Page) } while (current_entry != NULL) { - MmSetCleanPage(current_entry->Process, current_entry->Address); - current_entry = current_entry->Next; +#ifdef NEWCC + if (!RMAP_IS_SEGMENT(current_entry->Address)) +#endif + MmSetCleanPage(current_entry->Process, current_entry->Address); + current_entry = current_entry->Next; } ExReleaseFastMutex(&RmapListLock); } @@ -214,7 +221,10 @@ MmSetDirtyAllRmaps(PFN_NUMBER Page) } while (current_entry != NULL) { - MmSetDirtyPage(current_entry->Process, current_entry->Address); +#ifdef NEWCC + if (!RMAP_IS_SEGMENT(current_entry->Address)) +#endif + MmSetDirtyPage(current_entry->Process, current_entry->Address); current_entry = current_entry->Next; } ExReleaseFastMutex(&RmapListLock); @@ -235,7 +245,11 @@ MmIsDirtyPageRmap(PFN_NUMBER Page) } while (current_entry != NULL) { - if (MmIsDirtyPage(current_entry->Process, current_entry->Address)) + if ( +#ifdef NEWCC + !RMAP_IS_SEGMENT(current_entry->Address) && +#endif + MmIsDirtyPage(current_entry->Process, current_entry->Address)) { ExReleaseFastMutex(&RmapListLock); return(TRUE); @@ -254,8 +268,10 @@ MmInsertRmap(PFN_NUMBER Page, PEPROCESS Process, PMM_RMAP_ENTRY current_entry; PMM_RMAP_ENTRY new_entry; ULONG PrevSize; - - Address = (PVOID)PAGE_ROUND_DOWN(Address); +#ifdef NEWCC + if (!RMAP_IS_SEGMENT(Address)) +#endif + Address = (PVOID)PAGE_ROUND_DOWN(Address); new_entry = ExAllocateFromNPagedLookasideList(&RmapLookasideList); if (new_entry == NULL) @@ -272,7 +288,11 @@ MmInsertRmap(PFN_NUMBER Page, PEPROCESS Process, #endif #endif - if (MmGetPfnForProcess(Process, Address) != Page) + if ( +#ifdef NEWCC + !RMAP_IS_SEGMENT(Address) && +#endif + MmGetPfnForProcess(Process, Address) != Page) { DPRINT1("Insert rmap (%d, 0x%.8X) 0x%.8X which doesn't match physical " "address 0x%.8X\n", Process->UniqueProcessId, Address, @@ -302,17 +322,22 @@ MmInsertRmap(PFN_NUMBER Page, PEPROCESS Process, #endif MmSetRmapListHeadPage(Page, new_entry); ExReleaseFastMutex(&RmapListLock); - if (Process == NULL) +#ifdef NEWCC + if (!RMAP_IS_SEGMENT(Address)) +#endif { - Process = PsInitialSystemProcess; - } - if (Process) - { - PrevSize = InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, PAGE_SIZE); - if (PrevSize >= Process->Vm.PeakWorkingSetSize) - { - Process->Vm.PeakWorkingSetSize = PrevSize + PAGE_SIZE; - } + if (Process == NULL) + { + Process = PsInitialSystemProcess; + } + if (Process) + { + PrevSize = InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, PAGE_SIZE); + if (PrevSize >= Process->Vm.PeakWorkingSetSize) + { + Process->Vm.PeakWorkingSetSize = PrevSize + PAGE_SIZE; + } + } } } @@ -339,21 +364,32 @@ MmDeleteAllRmaps(PFN_NUMBER Page, PVOID Context, { previous_entry = current_entry; current_entry = current_entry->Next; - if (DeleteMapping) - { - DeleteMapping(Context, previous_entry->Process, - previous_entry->Address); - } - Process = previous_entry->Process; - ExFreeToNPagedLookasideList(&RmapLookasideList, previous_entry); - if (Process == NULL) - { - Process = PsInitialSystemProcess; - } - if (Process) - { - (void)InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, -PAGE_SIZE); - } +#ifdef NEWCC + if (!RMAP_IS_SEGMENT(current_entry->Address)) +#endif + { + if (DeleteMapping) + { + DeleteMapping(Context, previous_entry->Process, + previous_entry->Address); + } + Process = previous_entry->Process; + ExFreeToNPagedLookasideList(&RmapLookasideList, previous_entry); + if (Process == NULL) + { + Process = PsInitialSystemProcess; + } + if (Process) + { + (void)InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, -PAGE_SIZE); + } + } +#ifdef NEWCC + else + { + ExFreeToNPagedLookasideList(&RmapLookasideList, previous_entry); + } +#endif } } @@ -383,14 +419,19 @@ MmDeleteRmap(PFN_NUMBER Page, PEPROCESS Process, } ExReleaseFastMutex(&RmapListLock); ExFreeToNPagedLookasideList(&RmapLookasideList, current_entry); - if (Process == NULL) - { - Process = PsInitialSystemProcess; - } - if (Process) - { - (void)InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, -PAGE_SIZE); - } +#ifdef NEWCC + if (!RMAP_IS_SEGMENT(Address)) +#endif + { + if (Process == NULL) + { + Process = PsInitialSystemProcess; + } + if (Process) + { + (void)InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, -PAGE_SIZE); + } + } return; } previous_entry = current_entry; @@ -398,3 +439,63 @@ MmDeleteRmap(PFN_NUMBER Page, PEPROCESS Process, } KeBugCheck(MEMORY_MANAGEMENT); } + +#ifdef NEWCC +PVOID +NTAPI +MmGetSegmentRmap(PFN_NUMBER Page, PULONG RawOffset) +{ + PCACHE_SECTION_PAGE_TABLE Result = NULL; + PMM_RMAP_ENTRY current_entry, previous_entry; + + ExAcquireFastMutex(&RmapListLock); + previous_entry = NULL; + current_entry = MmGetRmapListHeadPage(Page); + while (current_entry != NULL) + { + if (RMAP_IS_SEGMENT(current_entry->Address)) + { + Result = (PCACHE_SECTION_PAGE_TABLE)current_entry->Process; + *RawOffset = (ULONG_PTR)current_entry->Address & ~RMAP_SEGMENT_MASK; + InterlockedIncrementUL(&Result->Segment->ReferenceCount); + ExReleaseFastMutex(&RmapListLock); + return Result; + } + previous_entry = current_entry; + current_entry = current_entry->Next; + } + ExReleaseFastMutex(&RmapListLock); + return NULL; +} + +VOID +NTAPI +MmDeleteSectionAssociation(PFN_NUMBER Page) +{ + PMM_RMAP_ENTRY current_entry, previous_entry; + + ExAcquireFastMutex(&RmapListLock); + previous_entry = NULL; + current_entry = MmGetRmapListHeadPage(Page); + while (current_entry != NULL) + { + if (RMAP_IS_SEGMENT(current_entry->Address)) + { + if (previous_entry == NULL) + { + MmSetRmapListHeadPage(Page, current_entry->Next); + } + else + { + previous_entry->Next = current_entry->Next; + } + ExReleaseFastMutex(&RmapListLock); + ExFreeToNPagedLookasideList(&RmapLookasideList, current_entry); + return; + } + previous_entry = current_entry; + current_entry = current_entry->Next; + } + ExReleaseFastMutex(&RmapListLock); +} +#endif diff --git a/ntoskrnl/mm/section.c b/ntoskrnl/mm/section.c index 5dad201e343..bef77f4cad5 100644 --- a/ntoskrnl/mm/section.c +++ b/ntoskrnl/mm/section.c @@ -45,6 +45,9 @@ /* INCLUDES *****************************************************************/ #include +#ifdef NEWCC +#include "../cache/section/newmm.h" +#endif #define NDEBUG #include #include @@ -745,7 +748,7 @@ MmspCompleteAndReleasePageOp(PMM_PAGEOP PageOp) * ARGUMENTS: PFILE_OBJECT to wait for. * RETURNS: Status of the wait. */ -static NTSTATUS +NTSTATUS MmspWaitForFileLock(PFILE_OBJECT File) { return STATUS_SUCCESS; @@ -979,7 +982,11 @@ MmUnsharePageEntrySectionSegment(PROS_SECTION_OBJECT Section, NTSTATUS Status; Bcb = FileObject->SectionObjectPointer->SharedCacheMap; IsDirectMapped = TRUE; +#ifndef NEWCC Status = CcRosUnmapCacheSegment(Bcb, FileOffset, Dirty); +#else + Status = STATUS_SUCCESS; +#endif if (!NT_SUCCESS(Status)) { DPRINT1("CcRosUnmapCacheSegment failed, status = %x\n", Status); @@ -1057,6 +1064,7 @@ MmUnsharePageEntrySectionSegment(PROS_SECTION_OBJECT Section, BOOLEAN MiIsPageFromCache(PMEMORY_AREA MemoryArea, ULONG SegOffset) { +#ifndef NEWCC if (!(MemoryArea->Data.SectionData.Segment->Characteristics & IMAGE_SCN_MEM_SHARED)) { PBCB Bcb; @@ -1069,6 +1077,7 @@ BOOLEAN MiIsPageFromCache(PMEMORY_AREA MemoryArea, return TRUE; } } +#endif return FALSE; } @@ -1091,6 +1100,7 @@ MiCopyFromUserPage(PFN_NUMBER DestPage, PVOID SourceAddress) return(STATUS_SUCCESS); } +#ifndef NEWCC NTSTATUS NTAPI MiReadPage(PMEMORY_AREA MemoryArea, @@ -1183,6 +1193,8 @@ MiReadPage(PMEMORY_AREA MemoryArea, * Allocate a page, this is rather complicated by the possibility * we might have to move other things out of memory */ + MI_SET_USAGE(MI_USAGE_SECTION); + MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName); Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, Page); if (!NT_SUCCESS(Status)) { @@ -1267,6 +1279,35 @@ MiReadPage(PMEMORY_AREA MemoryArea, } return(STATUS_SUCCESS); } +#else +NTSTATUS +NTAPI +MiReadPage(PMEMORY_AREA MemoryArea, + ULONG SegOffset, + PPFN_NUMBER Page) +/* + * FUNCTION: Read a page for a section backed memory area. + * PARAMETERS: + * MemoryArea - Memory area to read the page for. + * Offset - Offset of the page to read. + * Page - Variable that receives a page contains the read data. + */ +{ + MM_REQUIRED_RESOURCES Resources = { }; + + Resources.Context = MemoryArea->Data.SectionData.Section->FileObject; + Resources.FileOffset.QuadPart = SegOffset + + MemoryArea->Data.SectionData.Segment->FileOffset; + Resources.Consumer = MC_USER; + Resources.Amount = PAGE_SIZE; + + DPRINT1("%S, offset %x, len %d, page %x\n", ((PFILE_OBJECT)Resources.Context)->FileName.Buffer, Resources.FileOffset.LowPart, Resources.Amount, Resources.Page[0]); + + NTSTATUS Status = MiReadFilePage(NULL, NULL, &Resources); + *Page = Resources.Page[0]; + return Status; +} +#endif NTSTATUS NTAPI @@ -1447,6 +1488,9 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, MmDeletePageFileMapping(Process, (PVOID)PAddress, &SwapEntry); MmUnlockAddressSpace(AddressSpace); + MI_SET_USAGE(MI_USAGE_SECTION); + if (Process) MI_SET_PROCESS2(Process->ImageFileName); + if (!Process) MI_SET_PROCESS2("Kernel Section"); Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page); if (!NT_SUCCESS(Status)) { @@ -1528,6 +1572,9 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, if (Segment->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) { MmUnlockSectionSegment(Segment); + MI_SET_USAGE(MI_USAGE_SECTION); + if (Process) MI_SET_PROCESS2(Process->ImageFileName); + if (!Process) MI_SET_PROCESS2("Kernel Section"); Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page); if (!NT_SUCCESS(Status)) { @@ -1582,11 +1629,15 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, if ((Segment->Flags & MM_PAGEFILE_SEGMENT) || (Offset >= PAGE_ROUND_UP(Segment->RawLength) && Section->AllocationAttributes & SEC_IMAGE)) { + MI_SET_USAGE(MI_USAGE_SECTION); + if (Process) MI_SET_PROCESS2(Process->ImageFileName); + if (!Process) MI_SET_PROCESS2("Kernel Section"); Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page); if (!NT_SUCCESS(Status)) { DPRINT1("MmRequestPageMemoryConsumer failed (Status %x)\n", Status); } + } else { @@ -1624,7 +1675,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, if (Entry != Entry1) { DPRINT1("Someone changed ppte entry while we slept\n"); - KeBugCheck(MEMORY_MANAGEMENT); + KeBugCheck(MEMORY_MANAGEMENT); } /* @@ -1664,7 +1715,9 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, MmUnlockSectionSegment(Segment); MmUnlockAddressSpace(AddressSpace); - + MI_SET_USAGE(MI_USAGE_SECTION); + if (Process) MI_SET_PROCESS2(Process->ImageFileName); + if (!Process) MI_SET_PROCESS2("Kernel Section"); Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page); if (!NT_SUCCESS(Status)) { @@ -1872,6 +1925,9 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace, /* * Allocate a page */ + MI_SET_USAGE(MI_USAGE_SECTION); + if (Process) MI_SET_PROCESS2(Process->ImageFileName); + if (!Process) MI_SET_PROCESS2("Kernel Section"); Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &NewPage); if (!NT_SUCCESS(Status)) { @@ -2151,7 +2207,11 @@ MmPageOutSectionView(PMMSUPPORT AddressSpace, Address); KeBugCheck(MEMORY_MANAGEMENT); } +#ifndef NEWCC Status = CcRosUnmapCacheSegment(Bcb, FileOffset, FALSE); +#else + Status = STATUS_SUCCESS; +#endif if (!NT_SUCCESS(Status)) { DPRINT1("CCRosUnmapCacheSegment failed, status = %x\n", Status); @@ -2429,7 +2489,9 @@ MmWritePageSectionView(PMMSUPPORT AddressSpace, if (DirectMapped && !Private) { ASSERT(SwapEntry == 0); +#ifndef NEWCC CcRosMarkDirtyCacheSegment(Bcb, Offset + Segment->FileOffset); +#endif PageOp->Status = STATUS_SUCCESS; MmspCompleteAndReleasePageOp(PageOp); return(STATUS_SUCCESS); @@ -2717,7 +2779,9 @@ MmpDeleteSection(PVOID ObjectBody) } if (Section->FileObject != NULL) { +#ifndef NEWCC CcRosDereferenceCache(Section->FileObject); +#endif ObDereferenceObject(Section->FileObject); Section->FileObject = NULL; } @@ -3122,7 +3186,9 @@ MmCreateDataFileSection(PROS_SECTION_OBJECT *SectionObject, MmUnlockSectionSegment(Segment); Section->FileObject = FileObject; Section->MaximumSize = MaximumSize; +#ifndef NEWCC CcRosReferenceCache(FileObject); +#endif //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE); *SectionObject = Section; return(STATUS_SUCCESS); @@ -3853,11 +3919,15 @@ MmCreateImageSection(PROS_SECTION_OBJECT *SectionObject, Section->SectionPageProtection = SectionPageProtection; Section->AllocationAttributes = AllocationAttributes; +#ifndef NEWCC /* * Initialized caching for this file object if previously caching * was initialized for the same on disk file */ Status = CcTryToInitializeFileCache(FileObject); +#else + Status = STATUS_SUCCESS; +#endif if (!NT_SUCCESS(Status) || FileObject->SectionObjectPointer->ImageSectionObject == NULL) { @@ -3950,7 +4020,9 @@ MmCreateImageSection(PROS_SECTION_OBJECT *SectionObject, Status = STATUS_SUCCESS; } Section->FileObject = FileObject; +#ifndef NEWCC CcRosReferenceCache(FileObject); +#endif //KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE); *SectionObject = Section; return(Status); @@ -4062,7 +4134,9 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, { FileObject = MemoryArea->Data.SectionData.Section->FileObject; Bcb = FileObject->SectionObjectPointer->SharedCacheMap; +#ifndef NEWCC CcRosMarkDirtyCacheSegment(Bcb, Offset + Segment->FileOffset); +#endif ASSERT(SwapEntry == 0); } } @@ -4749,7 +4823,9 @@ MmFlushImageSection (IN PSECTION_OBJECT_POINTERS SectionObjectPointer, { return FALSE; } +#ifndef NEWCC CcRosSetRemoveOnClose(SectionObjectPointer); +#endif return TRUE; case MmFlushForWrite: break; diff --git a/ntoskrnl/ntoskrnl_i386.lnk b/ntoskrnl/ntoskrnl_i386.lnk index c759babe6b9..788cda743c1 100644 --- a/ntoskrnl/ntoskrnl_i386.lnk +++ b/ntoskrnl/ntoskrnl_i386.lnk @@ -19,12 +19,6 @@ SECTIONS *(.gcc_exc) __text_end__ = .; *(.gcc_except_table) - } - init BLOCK(__section_alignment__) : - { - __init_start__ = . ; - *(init) - __init_end__ = . ; } /* The Cygwin32 library uses a section to avoid copying certain data on fork. This used to be named ".data". The linker used @@ -101,5 +95,11 @@ SECTIONS { [ .stabstr ] } + INIT BLOCK(__section_alignment__) : + { + __init_start__ = . ; + *(INIT) + __init_end__ = . ; + } } diff --git a/ntoskrnl/ob/obname.c b/ntoskrnl/ob/obname.c index c97d4cea5be..a514af7b195 100644 --- a/ntoskrnl/ob/obname.c +++ b/ntoskrnl/ob/obname.c @@ -33,6 +33,7 @@ UNICODE_STRING ObpDosDevicesShortName = NTSTATUS NTAPI +INIT_FUNCTION ObpCreateDosDevicesDirectory(VOID) { OBJECT_ATTRIBUTES ObjectAttributes; diff --git a/ntoskrnl/ob/obsdcach.c b/ntoskrnl/ob/obsdcach.c index 8e51d967622..1e8f9dad198 100644 --- a/ntoskrnl/ob/obsdcach.c +++ b/ntoskrnl/ob/obsdcach.c @@ -57,6 +57,7 @@ ObpSdReleaseLockShared(IN POB_SD_CACHE_LIST CacheEntry) NTSTATUS NTAPI +INIT_FUNCTION ObpInitSdCache(VOID) { ULONG i; diff --git a/ntoskrnl/po/poshtdwn.c b/ntoskrnl/po/poshtdwn.c index dd5113e1bb3..919ffd4eefb 100644 --- a/ntoskrnl/po/poshtdwn.c +++ b/ntoskrnl/po/poshtdwn.c @@ -9,6 +9,9 @@ /* INCLUDES ******************************************************************/ #include +#ifdef NEWCC +#include "../cache/newcc.h" +#endif #define NDEBUG #include @@ -154,6 +157,10 @@ PopGracefulShutdown(IN PVOID Context) IoShutdownSystem(1); CcWaitForCurrentLazyWriterActivity(); +#ifdef NEWCC + CcShutdownSystem(); +#endif + /* Note that here, we should broadcast the power IRP to devices */ /* In this step, the HAL disables any wake timers */ diff --git a/ntoskrnl/po/power.c b/ntoskrnl/po/power.c index a163b98bc48..359a035f294 100644 --- a/ntoskrnl/po/power.c +++ b/ntoskrnl/po/power.c @@ -127,6 +127,7 @@ PopSetSystemPowerState(SYSTEM_POWER_STATE PowerState) BOOLEAN NTAPI +INIT_FUNCTION PoInitSystem(IN ULONG BootPhase) { PVOID NotificationEntry; @@ -216,6 +217,7 @@ PopIdle0(IN PPROCESSOR_POWER_STATE PowerState) VOID NTAPI +INIT_FUNCTION PoInitializePrcb(IN PKPRCB Prcb) { /* Initialize the Power State */ @@ -744,8 +746,10 @@ NtSetSystemPowerState(IN POWER_ACTION SystemAction, /* Check if we're still in an invalid status */ if (!NT_SUCCESS(Status)) break; +#ifndef NEWCC /* Flush dirty cache pages */ CcRosFlushDirtyPages(-1, &Dummy); +#endif /* Flush all volumes and the registry */ DPRINT1("Flushing volumes, cache flushed %d pages\n", Dummy); diff --git a/ntoskrnl/ps/job.c b/ntoskrnl/ps/job.c index 52f4f2715be..7bded05b5ef 100644 --- a/ntoskrnl/ps/job.c +++ b/ntoskrnl/ps/job.c @@ -72,6 +72,7 @@ PspDeleteJob ( PVOID ObjectBody ) VOID NTAPI +INIT_FUNCTION PspInitializeJobStructures(VOID) { InitializeListHead(&PsJobListHead); diff --git a/ntoskrnl/ps/kill.c b/ntoskrnl/ps/kill.c index b1ea95fb361..7efbc761ad7 100644 --- a/ntoskrnl/ps/kill.c +++ b/ntoskrnl/ps/kill.c @@ -1012,6 +1012,13 @@ PspTerminateThreadByPointer(IN PETHREAD Thread, return Status; } +BOOLEAN +NTAPI +PspIsProcessExiting(IN PEPROCESS Process) +{ + return Process->Flags & PSF_PROCESS_EXITING_BIT; +} + VOID NTAPI PspExitProcess(IN BOOLEAN LastThread, diff --git a/ntoskrnl/ps/process.c b/ntoskrnl/ps/process.c index 0c557c3699e..01f9a77b17a 100644 --- a/ntoskrnl/ps/process.c +++ b/ntoskrnl/ps/process.c @@ -669,6 +669,13 @@ PspCreateProcess(OUT PHANDLE ProcessHandle, } } +#if MI_TRACE_PFNS + /* Copy the process name now that we have it */ + memcpy(MiGetPfnEntry(Process->Pcb.DirectoryTableBase[0] >> PAGE_SHIFT)->ProcessName, Process->ImageFileName, 16); + if (Process->Pcb.DirectoryTableBase[1]) memcpy(MiGetPfnEntry(Process->Pcb.DirectoryTableBase[1] >> PAGE_SHIFT)->ProcessName, Process->ImageFileName, 16); + if (Process->WorkingSetPage) memcpy(MiGetPfnEntry(Process->WorkingSetPage)->ProcessName, Process->ImageFileName, 16); +#endif + /* Check if we have a section object and map the system DLL */ if (SectionObject) PspMapSystemDll(Process, NULL, FALSE); diff --git a/ntoskrnl/ps/psmgr.c b/ntoskrnl/ps/psmgr.c index dbc9a660cfc..156982ed565 100644 --- a/ntoskrnl/ps/psmgr.c +++ b/ntoskrnl/ps/psmgr.c @@ -65,6 +65,7 @@ BOOLEAN PspDoingGiveBacks; USHORT NTAPI +INIT_FUNCTION NameToOrdinal(IN PCHAR Name, IN PVOID DllBase, IN ULONG NumberOfNames, @@ -107,6 +108,7 @@ NameToOrdinal(IN PCHAR Name, NTSTATUS NTAPI +INIT_FUNCTION LookupEntryPoint(IN PVOID DllBase, IN PCHAR Name, OUT PVOID *EntryPoint) @@ -158,6 +160,7 @@ LookupEntryPoint(IN PVOID DllBase, NTSTATUS NTAPI +INIT_FUNCTION PspLookupSystemDllEntryPoint(IN PCHAR Name, IN PVOID *EntryPoint) { @@ -167,6 +170,7 @@ PspLookupSystemDllEntryPoint(IN PCHAR Name, NTSTATUS NTAPI +INIT_FUNCTION PspLookupKernelUserEntryPoints(VOID) { NTSTATUS Status; @@ -239,6 +243,7 @@ PspLookupKernelUserEntryPoints(VOID) NTSTATUS NTAPI +INIT_FUNCTION PspMapSystemDll(IN PEPROCESS Process, IN PVOID *DllBase, IN BOOLEAN UseLargePages) @@ -272,6 +277,7 @@ PspMapSystemDll(IN PEPROCESS Process, NTSTATUS NTAPI +INIT_FUNCTION PsLocateSystemDll(VOID) { OBJECT_ATTRIBUTES ObjectAttributes; @@ -357,6 +363,7 @@ PsLocateSystemDll(VOID) NTSTATUS NTAPI +INIT_FUNCTION PspInitializeSystemDll(VOID) { NTSTATUS Status; @@ -389,6 +396,7 @@ PspInitializeSystemDll(VOID) BOOLEAN NTAPI +INIT_FUNCTION PspInitPhase1() { /* Initialize the System DLL and return status of operation */ @@ -398,6 +406,7 @@ PspInitPhase1() BOOLEAN NTAPI +INIT_FUNCTION PspInitPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { NTSTATUS Status; @@ -616,6 +625,7 @@ PspInitPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock) BOOLEAN NTAPI +INIT_FUNCTION PsInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { /* Check the initialization phase */ diff --git a/ntoskrnl/ps/quota.c b/ntoskrnl/ps/quota.c index 772ae7e6bcf..8814104c147 100644 --- a/ntoskrnl/ps/quota.c +++ b/ntoskrnl/ps/quota.c @@ -98,6 +98,7 @@ PspReturnProcessQuotaSpecifiedPool(IN PEPROCESS Process, VOID NTAPI +INIT_FUNCTION PsInitializeQuotaSystem(VOID) { RtlZeroMemory(&PspDefaultQuotaBlock, sizeof(PspDefaultQuotaBlock)); diff --git a/ntoskrnl/se/semgr.c b/ntoskrnl/se/semgr.c index 406003b0af9..2795f01e0c8 100644 --- a/ntoskrnl/se/semgr.c +++ b/ntoskrnl/se/semgr.c @@ -86,6 +86,7 @@ SepInitExports(VOID) BOOLEAN NTAPI +INIT_FUNCTION SepInitializationPhase0(VOID) { PAGED_CODE(); @@ -117,6 +118,7 @@ SepInitializationPhase0(VOID) BOOLEAN NTAPI +INIT_FUNCTION SepInitializationPhase1(VOID) { NTSTATUS Status; @@ -139,6 +141,7 @@ SepInitializationPhase1(VOID) BOOLEAN NTAPI +INIT_FUNCTION SeInitSystem(VOID) { /* Check the initialization phase */ @@ -168,6 +171,7 @@ SeInitSystem(VOID) BOOLEAN NTAPI +INIT_FUNCTION SeInitSRM(VOID) { OBJECT_ATTRIBUTES ObjectAttributes; diff --git a/ntoskrnl/vdm/vdmmain.c b/ntoskrnl/vdm/vdmmain.c index c7aa0a2500d..e9136599791 100644 --- a/ntoskrnl/vdm/vdmmain.c +++ b/ntoskrnl/vdm/vdmmain.c @@ -15,11 +15,11 @@ /* GLOBALS *******************************************************************/ - /* PRIVATE FUNCTIONS *********************************************************/ VOID NTAPI +INIT_FUNCTION Ki386VdmEnablePentiumExtentions(IN BOOLEAN Enable) { ULONG EFlags, Cr4; @@ -38,6 +38,7 @@ Ki386VdmEnablePentiumExtentions(IN BOOLEAN Enable) VOID NTAPI +INIT_FUNCTION KeI386VdmInitialize(VOID) { NTSTATUS Status; @@ -84,6 +85,7 @@ KeI386VdmInitialize(VOID) NTSTATUS NTAPI +INIT_FUNCTION VdmpInitialize(PVOID ControlData) { OBJECT_ATTRIBUTES ObjectAttributes; diff --git a/subsystems/win32/win32k/eng/bitblt.c b/subsystems/win32/win32k/eng/bitblt.c index e6dd4970d5c..3525a2caf2a 100644 --- a/subsystems/win32/win32k/eng/bitblt.c +++ b/subsystems/win32/win32k/eng/bitblt.c @@ -370,6 +370,7 @@ EngBitBlt(SURFOBJ *DestObj, } else { + InputPoint.x = InputPoint.y = 0; InputRect.left = 0; InputRect.right = DestRect->right - DestRect->left; InputRect.top = 0; diff --git a/subsystems/win32/win32k/eng/device.c b/subsystems/win32/win32k/eng/device.c index 0965a967fc8..730b2ffaa3a 100644 --- a/subsystems/win32/win32k/eng/device.c +++ b/subsystems/win32/win32k/eng/device.c @@ -20,15 +20,16 @@ static PGRAPHICS_DEVICE gpGraphicsDeviceLast = NULL; static HSEMAPHORE ghsemGraphicsDeviceList; static ULONG giDevNum = 1; -BOOL +INIT_FUNCTION +NTSTATUS NTAPI InitDeviceImpl() { ghsemGraphicsDeviceList = EngCreateSemaphore(); if (!ghsemGraphicsDeviceList) - return FALSE; + return STATUS_INSUFFICIENT_RESOURCES; - return TRUE; + return STATUS_SUCCESS; } @@ -51,7 +52,7 @@ EngpRegisterGraphicsDevice( PDEVMODEW pdm, pdmEnd; PLDEVOBJ pldev; - DPRINT1("EngpRegisterGraphicsDevice(%S)\n", pustrDeviceName->Buffer); + DPRINT("EngpRegisterGraphicsDevice(%wZ)\n", pustrDeviceName); /* Allocate a GRAPHICS_DEVICE structure */ pGraphicsDevice = ExAllocatePoolWithTag(PagedPool, @@ -70,7 +71,7 @@ EngpRegisterGraphicsDevice( &pDeviceObject); if (!NT_SUCCESS(Status)) { - DPRINT1("Could not open driver, 0x%lx\n", Status); + DPRINT1("Could not open driver %wZ, 0x%lx\n", pustrDeviceName, Status); ExFreePoolWithTag(pGraphicsDevice, GDITAG_GDEVICE); return NULL; } diff --git a/subsystems/win32/win32k/eng/ldevobj.c b/subsystems/win32/win32k/eng/ldevobj.c index 6296a01b385..0e6c0eea540 100644 --- a/subsystems/win32/win32k/eng/ldevobj.c +++ b/subsystems/win32/win32k/eng/ldevobj.c @@ -26,7 +26,8 @@ LDEVOBJ *gpldevWin32k = NULL; /** Private functions *********************************************************/ -BOOL +INIT_FUNCTION +NTSTATUS NTAPI InitLDEVImpl() { @@ -34,7 +35,7 @@ InitLDEVImpl() ghsemLDEVList = EngCreateSemaphore(); if (!ghsemLDEVList) { - return FALSE; + return STATUS_INSUFFICIENT_RESOURCES; } /* Allocate a LDEVOBJ for win32k */ @@ -44,7 +45,7 @@ InitLDEVImpl() GDITAG_LDEV); if (!gpldevWin32k) { - return FALSE; + return STATUS_NO_MEMORY; } /* Initialize the LDEVOBJ for win32k */ @@ -62,7 +63,7 @@ InitLDEVImpl() gpldevWin32k->pGdiDriverInfo->ExportSectionPointer = NULL; gpldevWin32k->pGdiDriverInfo->ImageLength = 0; // FIXME; - return TRUE; + return STATUS_SUCCESS; } PLDEVOBJ diff --git a/subsystems/win32/win32k/eng/pdevobj.c b/subsystems/win32/win32k/eng/pdevobj.c index 26c0f4b8416..2da468ee3fb 100644 --- a/subsystems/win32/win32k/eng/pdevobj.c +++ b/subsystems/win32/win32k/eng/pdevobj.c @@ -18,12 +18,14 @@ PPDEVOBJ gppdevPrimary = NULL; static PPDEVOBJ gppdevList = NULL; static HSEMAPHORE ghsemPDEV; -BOOL +INIT_FUNCTION +NTSTATUS NTAPI InitPDEVImpl() { ghsemPDEV = EngCreateSemaphore(); - return TRUE; + if (!ghsemPDEV) return STATUS_INSUFFICIENT_RESOURCES; + return STATUS_SUCCESS; } diff --git a/subsystems/win32/win32k/eng/xlate.c b/subsystems/win32/win32k/eng/xlate.c index 8f9962341e3..f15d757cb3d 100644 --- a/subsystems/win32/win32k/eng/xlate.c +++ b/subsystems/win32/win32k/eng/xlate.c @@ -634,11 +634,13 @@ EXLATEOBJ_vCleanup(PEXLATEOBJ pexlo) pexlo->xlo.pulXlate = pexlo->aulXlate; } -VOID +INIT_FUNCTION +NTSTATUS +NTAPI InitXlateImpl(VOID) { - EXLATEOBJ_vInitTrivial(&gexloTrivial); + return STATUS_SUCCESS; } diff --git a/subsystems/win32/win32k/include/accelerator.h b/subsystems/win32/win32k/include/accelerator.h index f9aea474215..48de41329da 100644 --- a/subsystems/win32/win32k/include/accelerator.h +++ b/subsystems/win32/win32k/include/accelerator.h @@ -11,7 +11,9 @@ typedef struct _ACCELERATOR_TABLE LPACCEL Table; } ACCELERATOR_TABLE, *PACCELERATOR_TABLE; -NTSTATUS FASTCALL +INIT_FUNCTION +NTSTATUS +NTAPI InitAcceleratorImpl(VOID); NTSTATUS FASTCALL diff --git a/subsystems/win32/win32k/include/dc.h b/subsystems/win32/win32k/include/dc.h index 8150b169900..b1f8cd1838a 100644 --- a/subsystems/win32/win32k/include/dc.h +++ b/subsystems/win32/win32k/include/dc.h @@ -159,7 +159,7 @@ typedef struct _DC extern PDC defaultDCstate; -NTSTATUS FASTCALL InitDcImpl(VOID); +INIT_FUNCTION NTSTATUS NTAPI InitDcImpl(); PPDEVOBJ FASTCALL IntEnumHDev(VOID); PDC NTAPI DC_AllocDcWithHandle(); VOID FASTCALL DC_InitDC(HDC DCToInit); diff --git a/subsystems/win32/win32k/include/desktop.h b/subsystems/win32/win32k/include/desktop.h index 83ec40ceaf8..12911139223 100644 --- a/subsystems/win32/win32k/include/desktop.h +++ b/subsystems/win32/win32k/include/desktop.h @@ -45,7 +45,9 @@ typedef struct _SHELL_HOOK_WINDOW HWND hWnd; } SHELL_HOOK_WINDOW, *PSHELL_HOOK_WINDOW; -NTSTATUS FASTCALL +INIT_FUNCTION +NTSTATUS +NTAPI InitDesktopImpl(VOID); NTSTATUS FASTCALL diff --git a/subsystems/win32/win32k/include/device.h b/subsystems/win32/win32k/include/device.h index cdf60d7f80a..2ad19b278a7 100644 --- a/subsystems/win32/win32k/include/device.h +++ b/subsystems/win32/win32k/include/device.h @@ -30,7 +30,8 @@ EngpRegisterGraphicsDevice( PUNICODE_STRING pustrDescription, PDEVMODEW pdmDefault); -BOOL +INIT_FUNCTION +NTSTATUS NTAPI InitDeviceImpl(); diff --git a/subsystems/win32/win32k/include/gdiobj.h b/subsystems/win32/win32k/include/gdiobj.h index a1a56b7ae24..e736391322e 100644 --- a/subsystems/win32/win32k/include/gdiobj.h +++ b/subsystems/win32/win32k/include/gdiobj.h @@ -59,6 +59,8 @@ enum BASEFLAGS BASEFLAG_READY_TO_DIE = 0x1000 }; +extern PSECTION_OBJECT GdiTableSection; + BOOL INTERNAL_CALL GDIOBJ_OwnedByCurrentProcess(HGDIOBJ ObjectHandle); BOOL INTERNAL_CALL GDIOBJ_SetOwnership(HGDIOBJ ObjectHandle, PEPROCESS Owner); BOOL INTERNAL_CALL GDIOBJ_CopyOwnership(HGDIOBJ CopyFrom, HGDIOBJ CopyTo); @@ -75,6 +77,11 @@ VOID INTERNAL_CALL GDIOBJ_LockMultipleObjs(ULONG ulCount, IN HGDIOBJ* ahObj, OUT PVOID INTERNAL_CALL GDI_MapHandleTable(PSECTION_OBJECT SectionObject, PEPROCESS Process); +INIT_FUNCTION +NTSTATUS +NTAPI +InitGdiHandleTable(); + #define GDIOBJ_GetObjectType(Handle) \ GDI_HANDLE_GET_TYPE(Handle) diff --git a/subsystems/win32/win32k/include/guicheck.h b/subsystems/win32/win32k/include/guicheck.h index 5e1c5c9c385..8548ab6732c 100644 --- a/subsystems/win32/win32k/include/guicheck.h +++ b/subsystems/win32/win32k/include/guicheck.h @@ -4,6 +4,9 @@ BOOL FASTCALL co_IntGraphicsCheck(BOOL Create); BOOL FASTCALL IntCreatePrimarySurface(VOID); VOID FASTCALL IntDestroyPrimarySurface(VOID); -NTSTATUS FASTCALL InitGuiCheckImpl (VOID); +INIT_FUNCTION +NTSTATUS +NTAPI +InitGuiCheckImpl (VOID); /* EOF */ diff --git a/subsystems/win32/win32k/include/hotkey.h b/subsystems/win32/win32k/include/hotkey.h index c03e6ebc010..74f19a2b2a7 100644 --- a/subsystems/win32/win32k/include/hotkey.h +++ b/subsystems/win32/win32k/include/hotkey.h @@ -13,7 +13,9 @@ typedef struct _HOT_KEY_ITEM UINT vk; } HOT_KEY_ITEM, *PHOT_KEY_ITEM; -NTSTATUS FASTCALL +INIT_FUNCTION +NTSTATUS +NTAPI InitHotkeyImpl(VOID); //NTSTATUS FASTCALL diff --git a/subsystems/win32/win32k/include/input.h b/subsystems/win32/win32k/include/input.h index 2a00fe20e9e..60056046d1a 100644 --- a/subsystems/win32/win32k/include/input.h +++ b/subsystems/win32/win32k/include/input.h @@ -27,10 +27,16 @@ extern PATTACHINFO gpai; #define KBL_PRELOAD 2 #define KBL_RESET 4 -NTSTATUS FASTCALL +INIT_FUNCTION +NTSTATUS +NTAPI InitInputImpl(VOID); -NTSTATUS FASTCALL + +INIT_FUNCTION +NTSTATUS +NTAPI InitKeyboardImpl(VOID); + PUSER_MESSAGE_QUEUE W32kGetPrimitiveMessageQueue(VOID); VOID W32kUnregisterPrimitiveMessageQueue(VOID); PKBL W32kGetDefaultKeyLayout(VOID); diff --git a/subsystems/win32/win32k/include/inteng.h b/subsystems/win32/win32k/include/inteng.h index 9bcfc0ab838..1d8610d2dac 100644 --- a/subsystems/win32/win32k/include/inteng.h +++ b/subsystems/win32/win32k/include/inteng.h @@ -82,32 +82,6 @@ IntEngGradientFill(SURFOBJ *psoDest, POINTL *pptlDitherOrg, ULONG ulMode); -VOID InitXlateImpl(VOID); - -XLATEOBJ* FASTCALL -IntEngCreateXlate(USHORT DestPalType, - USHORT SourcePalType, - HPALETTE PaletteDest, - HPALETTE PaletteSource); - -XLATEOBJ* FASTCALL -IntEngCreateMonoXlate(USHORT SourcePalType, - HPALETTE PaletteDest, - HPALETTE PaletteSource, - ULONG BackgroundColor); - -XLATEOBJ* FASTCALL -IntEngCreateSrcMonoXlate(HPALETTE PaletteDest, - ULONG Color0, - ULONG Color1); - -XLATEOBJ* -IntCreateBrushXlate(BRUSH *pbrush, SURFACE * psurf, COLORREF crBackgroundClr); - -HPALETTE FASTCALL -IntEngGetXlatePalette(XLATEOBJ *XlateObj, - ULONG Palette); - BOOL APIENTRY IntEngPolyline(SURFOBJ *DestSurf, CLIPOBJ *Clip, diff --git a/subsystems/win32/win32k/include/ldevobj.h b/subsystems/win32/win32k/include/ldevobj.h index 40070db631c..6bae83ab8a0 100644 --- a/subsystems/win32/win32k/include/ldevobj.h +++ b/subsystems/win32/win32k/include/ldevobj.h @@ -63,7 +63,8 @@ LDEVOBJ_pdmiGetModes( PLDEVOBJ pldev, HANDLE hDriver); -BOOL +INIT_FUNCTION +NTSTATUS NTAPI InitLDEVImpl(); diff --git a/subsystems/win32/win32k/include/menu.h b/subsystems/win32/win32k/include/menu.h index 6b86b62e8ad..10fe2294fba 100644 --- a/subsystems/win32/win32k/include/menu.h +++ b/subsystems/win32/win32k/include/menu.h @@ -104,7 +104,9 @@ IntInsertMenuItem(PMENU_OBJECT MenuObject, UINT uItem, BOOL fByPosition, PROSMENUITEMINFO ItemInfo); -NTSTATUS FASTCALL +INIT_FUNCTION +NTSTATUS +NTAPI InitMenuImpl(VOID); NTSTATUS FASTCALL diff --git a/subsystems/win32/win32k/include/monitor.h b/subsystems/win32/win32k/include/monitor.h index 6c4282885ca..04a9a3ffc36 100644 --- a/subsystems/win32/win32k/include/monitor.h +++ b/subsystems/win32/win32k/include/monitor.h @@ -32,7 +32,10 @@ typedef struct _MONITOR } MONITOR, *PMONITOR; /* functions */ -NTSTATUS InitMonitorImpl(); +INIT_FUNCTION +NTSTATUS +NTAPI +InitMonitorImpl(); NTSTATUS CleanupMonitorImpl(); NTSTATUS IntAttachMonitor(PDEVOBJ *pGdiDevice, ULONG DisplayNumber); diff --git a/subsystems/win32/win32k/include/msgqueue.h b/subsystems/win32/win32k/include/msgqueue.h index 569f1028d83..0c6cc8b7240 100644 --- a/subsystems/win32/win32k/include/msgqueue.h +++ b/subsystems/win32/win32k/include/msgqueue.h @@ -127,7 +127,7 @@ co_MsqFindMessage(IN PUSER_MESSAGE_QUEUE MessageQueue, IN PWND Window, IN UINT MsgFilterLow, IN UINT MsgFilterHigh, - OUT PUSER_MESSAGE* Message); + OUT PMSG Message); BOOLEAN FASTCALL MsqInitializeMessageQueue(struct _ETHREAD *Thread, PUSER_MESSAGE_QUEUE MessageQueue); VOID FASTCALL @@ -138,7 +138,9 @@ VOID FASTCALL MsqDestroyMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue); PUSER_MESSAGE_QUEUE FASTCALL MsqGetHardwareMessageQueue(VOID); -NTSTATUS FASTCALL +INIT_FUNCTION +NTSTATUS +NTAPI MsqInitializeImpl(VOID); BOOLEAN FASTCALL co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue); @@ -194,7 +196,7 @@ co_MsqPostKeyboardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); VOID FASTCALL MsqPostHotKeyMessage(PVOID Thread, HWND hWnd, WPARAM wParam, LPARAM lParam); VOID FASTCALL -MsqInsertSystemMessage(MSG* Msg); +MsqInsertMouseMessage(MSG* Msg); BOOL FASTCALL MsqIsClkLck(LPMSG Msg, BOOL Remove); BOOL FASTCALL diff --git a/subsystems/win32/win32k/include/ntuser.h b/subsystems/win32/win32k/include/ntuser.h index 58a911d6f82..83b21556862 100644 --- a/subsystems/win32/win32k/include/ntuser.h +++ b/subsystems/win32/win32k/include/ntuser.h @@ -11,7 +11,7 @@ extern PSERVERINFO gpsi; -NTSTATUS FASTCALL InitUserImpl(VOID); +INIT_FUNCTION NTSTATUS NTAPI InitUserImpl(VOID); VOID FASTCALL CleanupUserImpl(VOID); VOID FASTCALL UserEnterShared(VOID); VOID FASTCALL UserEnterExclusive(VOID); diff --git a/subsystems/win32/win32k/include/palette.h b/subsystems/win32/win32k/include/palette.h index 82fcb3ca05b..3fad906ff45 100644 --- a/subsystems/win32/win32k/include/palette.h +++ b/subsystems/win32/win32k/include/palette.h @@ -74,8 +74,7 @@ HPALETTE FASTCALL PALETTE_AllocPaletteIndexedRGB(ULONG NumColors, GDIOBJ_ShareUnlockObjByPtr(&ppal->BaseObject) BOOL INTERNAL_CALL PALETTE_Cleanup(PVOID ObjectBody); - -HPALETTE FASTCALL PALETTE_Init (VOID); +INIT_FUNCTION NTSTATUS NTAPI InitPaletteImpl(); VOID FASTCALL PALETTE_ValidateFlags (PALETTEENTRY* lpPalE, INT size); INT FASTCALL PALETTE_ToPhysical (PDC dc, COLORREF color); diff --git a/subsystems/win32/win32k/include/pdevobj.h b/subsystems/win32/win32k/include/pdevobj.h index 6a19a1bffec..bece851460a 100644 --- a/subsystems/win32/win32k/include/pdevobj.h +++ b/subsystems/win32/win32k/include/pdevobj.h @@ -174,18 +174,11 @@ PDEVOBJ_vGetDeviceCaps( PPDEVOBJ ppdev, PDEVCAPS pDevCaps); -BOOL +INIT_FUNCTION +NTSTATUS NTAPI InitPDEVImpl(); -BOOL -NTAPI -InitLDEVImpl(); - -BOOL -NTAPI -InitDeviceImpl(); - PSIZEL FASTCALL PDEVOBJ_sizl(PPDEVOBJ, PSIZEL); diff --git a/subsystems/win32/win32k/include/timer.h b/subsystems/win32/win32k/include/timer.h index 20faa683526..c88da4a987d 100644 --- a/subsystems/win32/win32k/include/timer.h +++ b/subsystems/win32/win32k/include/timer.h @@ -26,7 +26,10 @@ typedef struct _TIMER extern PKTIMER MasterTimer; -NTSTATUS FASTCALL InitTimerImpl(VOID); +INIT_FUNCTION +NTSTATUS +NTAPI +InitTimerImpl(VOID); BOOL FASTCALL DestroyTimersForThread(PTHREADINFO pti); BOOL FASTCALL DestroyTimersForWindow(PTHREADINFO pti, PWND Window); BOOL FASTCALL IntKillTimer(PWND Window, UINT_PTR IDEvent, BOOL SystemTimer); diff --git a/subsystems/win32/win32k/include/win32kp.h b/subsystems/win32/win32k/include/win32kp.h index 8bcf046195b..b84a319947f 100644 --- a/subsystems/win32/win32k/include/win32kp.h +++ b/subsystems/win32/win32k/include/win32kp.h @@ -11,6 +11,13 @@ #pragma once #define INTERNAL_CALL APIENTRY +#ifndef _MSC_VER +#define PLACE_IN_SECTION(s) __attribute__((section(s))) +#define INIT_FUNCTION PLACE_IN_SECTION("INIT") +#else +#define INIT_FUNCTION +#endif + /* Internal Win32k Headers */ #include #include diff --git a/subsystems/win32/win32k/include/window.h b/subsystems/win32/win32k/include/window.h index 39a55b26e00..0e2073d3df1 100644 --- a/subsystems/win32/win32k/include/window.h +++ b/subsystems/win32/win32k/include/window.h @@ -50,7 +50,9 @@ IntIsWindow(HWND hWnd); HWND* FASTCALL IntWinListChildren(PWND Window); -NTSTATUS FASTCALL +INIT_FUNCTION +NTSTATUS +NTAPI InitWindowImpl (VOID); NTSTATUS FASTCALL diff --git a/subsystems/win32/win32k/include/winsta.h b/subsystems/win32/win32k/include/winsta.h index da944af3a46..a50a23ed6b7 100644 --- a/subsystems/win32/win32k/include/winsta.h +++ b/subsystems/win32/win32k/include/winsta.h @@ -62,7 +62,9 @@ typedef struct _WINSTATION_OBJECT extern WINSTATION_OBJECT *InputWindowStation; extern PPROCESSINFO LogonProcess; -NTSTATUS FASTCALL +INIT_FUNCTION +NTSTATUS +NTAPI InitWindowStationImpl(VOID); NTSTATUS FASTCALL diff --git a/subsystems/win32/win32k/include/xlateobj.h b/subsystems/win32/win32k/include/xlateobj.h index 18d2f240012..ea7d32035eb 100644 --- a/subsystems/win32/win32k/include/xlateobj.h +++ b/subsystems/win32/win32k/include/xlateobj.h @@ -47,5 +47,9 @@ VOID NTAPI EXLATEOBJ_vInitialize(PEXLATEOBJ pexlo, PALETTE *ppalSrc, PALETTE *pp VOID NTAPI EXLATEOBJ_vInitXlateFromDCs(PEXLATEOBJ pexlo, PDC pdcSrc, PDC pdcDst); VOID NTAPI EXLATEOBJ_vInitSrcMonoXlate(PEXLATEOBJ pexlo, PPALETTE ppalDst, ULONG Color0, ULONG Color1); VOID NTAPI EXLATEOBJ_vCleanup(PEXLATEOBJ pexlo); +INIT_FUNCTION +NTSTATUS +NTAPI +InitXlateImpl(VOID); //#define XLATEOBJ_iXlate(pxo, Color) ((EXLATEOBJ*)pxo)->pfnXlate(pxo, Color) diff --git a/subsystems/win32/win32k/main/dllmain.c b/subsystems/win32/win32k/main/dllmain.c index b12d96fa8ba..5ed49f112e8 100644 --- a/subsystems/win32/win32k/main/dllmain.c +++ b/subsystems/win32/win32k/main/dllmain.c @@ -1,23 +1,9 @@ /* - * ReactOS W32 Subsystem - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 ReactOS Team - * - * 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. - */ -/* - * Entry Point for win32k.sys + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Driver entry and initialization of win32k + * FILE: subsystems/win32/win32k/main/main.c + * PROGRAMER: */ #include @@ -30,17 +16,12 @@ HANDLE hModuleWin; PGDI_HANDLE_TABLE INTERNAL_CALL GDIOBJ_iAllocHandleTable(OUT PSECTION_OBJECT *SectionObject); BOOL INTERNAL_CALL GDI_CleanupForProcess (struct _EPROCESS *Process); -/* FIXME */ -PGDI_HANDLE_TABLE GdiHandleTable = NULL; -PSECTION_OBJECT GdiTableSection = NULL; HANDLE GlobalUserHeap = NULL; PSECTION_OBJECT GlobalUserHeapSection = NULL; PSERVERINFO gpsi = NULL; // Global User Server Information. -HSEMAPHORE hsemDriverMgmt = NULL; - SHORT gusLanguageID; extern ULONG_PTR Win32kSSDT[]; @@ -77,92 +58,101 @@ Win32kProcessCallback(struct _EPROCESS *Process, /* FIXME - unlock the process */ } - if (Create) + if (Create) { - SIZE_T ViewSize = 0; - LARGE_INTEGER Offset; - PVOID UserBase = NULL; - NTSTATUS Status; - extern PSECTION_OBJECT GlobalUserHeapSection; - DPRINT("Creating W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql()); + SIZE_T ViewSize = 0; + LARGE_INTEGER Offset; + PVOID UserBase = NULL; + NTSTATUS Status; + extern PSECTION_OBJECT GlobalUserHeapSection; + DPRINT("Creating W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql()); - /* map the global heap into the process */ - Offset.QuadPart = 0; - Status = MmMapViewOfSection(GlobalUserHeapSection, - PsGetCurrentProcess(), - &UserBase, - 0, - 0, - &Offset, - &ViewSize, - ViewUnmap, - SEC_NO_CHANGE, - PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */ - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to map the global heap! 0x%x\n", Status); - RETURN(Status); - } - Win32Process->HeapMappings.Next = NULL; - Win32Process->HeapMappings.KernelMapping = (PVOID)GlobalUserHeap; - Win32Process->HeapMappings.UserMapping = UserBase; - Win32Process->HeapMappings.Count = 1; + /* map the global heap into the process */ + Offset.QuadPart = 0; + Status = MmMapViewOfSection(GlobalUserHeapSection, + PsGetCurrentProcess(), + &UserBase, + 0, + 0, + &Offset, + &ViewSize, + ViewUnmap, + SEC_NO_CHANGE, + PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */ + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to map the global heap! 0x%x\n", Status); + RETURN(Status); + } + Win32Process->HeapMappings.Next = NULL; + Win32Process->HeapMappings.KernelMapping = (PVOID)GlobalUserHeap; + Win32Process->HeapMappings.UserMapping = UserBase; + Win32Process->HeapMappings.Count = 1; - InitializeListHead(&Win32Process->ClassList); + InitializeListHead(&Win32Process->ClassList); - InitializeListHead(&Win32Process->MenuListHead); + InitializeListHead(&Win32Process->MenuListHead); - InitializeListHead(&Win32Process->GDIBrushAttrFreeList); - InitializeListHead(&Win32Process->GDIDcAttrFreeList); + InitializeListHead(&Win32Process->GDIBrushAttrFreeList); + InitializeListHead(&Win32Process->GDIDcAttrFreeList); - InitializeListHead(&Win32Process->PrivateFontListHead); - ExInitializeFastMutex(&Win32Process->PrivateFontListLock); + InitializeListHead(&Win32Process->PrivateFontListHead); + ExInitializeFastMutex(&Win32Process->PrivateFontListLock); - InitializeListHead(&Win32Process->DriverObjListHead); - ExInitializeFastMutex(&Win32Process->DriverObjListLock); + InitializeListHead(&Win32Process->DriverObjListHead); + ExInitializeFastMutex(&Win32Process->DriverObjListLock); - Win32Process->KeyboardLayout = W32kGetDefaultKeyLayout(); + Win32Process->KeyboardLayout = W32kGetDefaultKeyLayout(); + EngCreateEvent((PEVENT *)&Win32Process->InputIdleEvent); + KeInitializeEvent(Win32Process->InputIdleEvent, NotificationEvent, FALSE); - if(Process->Peb != NULL) - { - /* map the gdi handle table to user land */ - Process->Peb->GdiSharedHandleTable = GDI_MapHandleTable(GdiTableSection, Process); - Process->Peb->GdiDCAttributeList = GDI_BATCH_LIMIT; - } + if(Process->Peb != NULL) + { + /* map the gdi handle table to user land */ + Process->Peb->GdiSharedHandleTable = GDI_MapHandleTable(GdiTableSection, Process); + Process->Peb->GdiDCAttributeList = GDI_BATCH_LIMIT; + } - Win32Process->peProcess = Process; - /* setup process flags */ - Win32Process->W32PF_flags = 0; + Win32Process->peProcess = Process; + /* setup process flags */ + Win32Process->W32PF_flags = 0; } - else + else { - DPRINT("Destroying W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql()); - IntCleanupMenus(Process, Win32Process); - IntCleanupCurIcons(Process, Win32Process); - CleanupMonitorImpl(); + DPRINT("Destroying W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql()); + Win32Process->W32PF_flags |= W32PF_TERMINATED; + if (Win32Process->InputIdleEvent) + { + EngFreeMem((PVOID)Win32Process->InputIdleEvent); + Win32Process->InputIdleEvent = NULL; + } - /* no process windows should exist at this point, or the function will assert! */ - DestroyProcessClasses(Win32Process); + IntCleanupMenus(Process, Win32Process); + IntCleanupCurIcons(Process, Win32Process); + CleanupMonitorImpl(); - GDI_CleanupForProcess(Process); + /* no process windows should exist at this point, or the function will assert! */ + DestroyProcessClasses(Win32Process); - co_IntGraphicsCheck(FALSE); + GDI_CleanupForProcess(Process); - /* - * Deregister logon application automatically - */ - if(LogonProcess == Win32Process) - { - LogonProcess = NULL; - } + co_IntGraphicsCheck(FALSE); + + /* + * Deregister logon application automatically + */ + if(LogonProcess == Win32Process) + { + LogonProcess = NULL; + } } - RETURN( STATUS_SUCCESS); + RETURN( STATUS_SUCCESS); CLEANUP: - UserLeave(); - DPRINT("Leave Win32kProcessCallback, ret=%i\n",_ret_); - END_CLEANUP; + UserLeave(); + DPRINT("Leave Win32kProcessCallback, ret=%i\n",_ret_); + END_CLEANUP; } @@ -199,208 +189,240 @@ Win32kThreadCallback(struct _ETHREAD *Thread, PsSetThreadWin32Thread(Thread, Win32Thread); /* FIXME - unlock the process */ } - if (Type == PsW32ThreadCalloutInitialize) + if (Type == PsW32ThreadCalloutInitialize) { - HWINSTA hWinSta = NULL; - PTEB pTeb; - HDESK hDesk = NULL; - NTSTATUS Status; - PUNICODE_STRING DesktopPath; - PRTL_USER_PROCESS_PARAMETERS ProcessParams = (Process->Peb ? Process->Peb->ProcessParameters : NULL); + HWINSTA hWinSta = NULL; + PTEB pTeb; + HDESK hDesk = NULL; + NTSTATUS Status; + PUNICODE_STRING DesktopPath; + PRTL_USER_PROCESS_PARAMETERS ProcessParams = (Process->Peb ? Process->Peb->ProcessParameters : NULL); - DPRINT("Creating W32 thread TID:%d at IRQ level: %lu\n", Thread->Cid.UniqueThread, KeGetCurrentIrql()); + DPRINT("Creating W32 thread TID:%d at IRQ level: %lu\n", Thread->Cid.UniqueThread, KeGetCurrentIrql()); - InitializeListHead(&Win32Thread->WindowListHead); - InitializeListHead(&Win32Thread->W32CallbackListHead); - InitializeListHead(&Win32Thread->PtiLink); - for (i = 0; i < NB_HOOKS; i++) - { - InitializeListHead(&Win32Thread->aphkStart[i]); - } - - /* - * inherit the thread desktop and process window station (if not yet inherited) from the process startup - * info structure. See documentation of CreateProcess() - */ - DesktopPath = (ProcessParams ? ((ProcessParams->DesktopInfo.Length > 0) ? &ProcessParams->DesktopInfo : NULL) : NULL); - Status = IntParseDesktopPath(Process, - DesktopPath, - &hWinSta, - &hDesk); - if(NT_SUCCESS(Status)) - { - if(hWinSta != NULL) + InitializeListHead(&Win32Thread->WindowListHead); + InitializeListHead(&Win32Thread->W32CallbackListHead); + InitializeListHead(&Win32Thread->PtiLink); + for (i = 0; i < NB_HOOKS; i++) { - if(Process != CsrProcess) - { - HWINSTA hProcessWinSta = (HWINSTA)InterlockedCompareExchangePointer((PVOID)&Process->Win32WindowStation, (PVOID)hWinSta, NULL); - if(hProcessWinSta != NULL) - { - /* our process is already assigned to a different window station, we don't need the handle anymore */ - NtClose(hWinSta); - } - } - else - { - NtClose(hWinSta); - } + InitializeListHead(&Win32Thread->aphkStart[i]); } - if (hDesk != NULL) + /* + * inherit the thread desktop and process window station (if not yet inherited) from the process startup + * info structure. See documentation of CreateProcess() + */ + DesktopPath = (ProcessParams ? ((ProcessParams->DesktopInfo.Length > 0) ? &ProcessParams->DesktopInfo : NULL) : NULL); + Status = IntParseDesktopPath(Process, + DesktopPath, + &hWinSta, + &hDesk); + if(NT_SUCCESS(Status)) { - PDESKTOP DesktopObject; - Win32Thread->rpdesk = NULL; - Status = ObReferenceObjectByHandle(hDesk, - 0, - ExDesktopObjectType, - KernelMode, - (PVOID*)&DesktopObject, - NULL); - NtClose(hDesk); - if(NT_SUCCESS(Status)) - { - if (!IntSetThreadDesktop(DesktopObject, - FALSE)) + if(hWinSta != NULL) { - DPRINT1("Unable to set thread desktop\n"); + if(Process != CsrProcess) + { + HWINSTA hProcessWinSta = (HWINSTA)InterlockedCompareExchangePointer((PVOID)&Process->Win32WindowStation, (PVOID)hWinSta, NULL); + if(hProcessWinSta != NULL) + { + /* our process is already assigned to a different window station, we don't need the handle anymore */ + NtClose(hWinSta); + } + } + else + { + NtClose(hWinSta); + } + } + + if (hDesk != NULL) + { + PDESKTOP DesktopObject; + Win32Thread->rpdesk = NULL; + Status = ObReferenceObjectByHandle(hDesk, + 0, + ExDesktopObjectType, + KernelMode, + (PVOID*)&DesktopObject, + NULL); + NtClose(hDesk); + if(NT_SUCCESS(Status)) + { + if (!IntSetThreadDesktop(DesktopObject, + FALSE)) + { + DPRINT1("Unable to set thread desktop\n"); + } + } + else + { + DPRINT1("Unable to reference thread desktop handle 0x%x\n", hDesk); + } } - } - else - { - DPRINT1("Unable to reference thread desktop handle 0x%x\n", hDesk); - } } - } - Win32Thread->TIF_flags &= ~TIF_INCLEANUP; - co_IntDestroyCaret(Win32Thread); - Win32Thread->ppi = PsGetCurrentProcessWin32Process(); - pTeb = NtCurrentTeb(); - if (pTeb) - { - Win32Thread->pClientInfo = (PCLIENTINFO)pTeb->Win32ClientInfo; - Win32Thread->pClientInfo->pClientThreadInfo = NULL; - } - Win32Thread->MessageQueue = MsqCreateMessageQueue(Thread); - Win32Thread->KeyboardLayout = W32kGetDefaultKeyLayout(); - Win32Thread->pEThread = Thread; + else + { + DPRINT1("No Desktop handle for this Thread!\n"); + } + Win32Thread->TIF_flags &= ~TIF_INCLEANUP; + co_IntDestroyCaret(Win32Thread); + Win32Thread->ppi = PsGetCurrentProcessWin32Process(); + if (Win32Thread->rpdesk && !Win32Thread->pDeskInfo) + { + Win32Thread->pDeskInfo = Win32Thread->rpdesk->pDeskInfo; + } + Win32Thread->MessageQueue = MsqCreateMessageQueue(Thread); + Win32Thread->KeyboardLayout = W32kGetDefaultKeyLayout(); + pTeb = NtCurrentTeb(); + if (pTeb) + { /* Attempt to startup client support which should have been initialized in IntSetThreadDesktop. */ + PCLIENTINFO pci = (PCLIENTINFO)pTeb->Win32ClientInfo; + Win32Thread->pClientInfo = pci; + pci->pClientThreadInfo = NULL; + pci->ppi = Win32Thread->ppi; + pci->fsHooks = Win32Thread->fsHooks; + if (Win32Thread->KeyboardLayout) pci->hKL = Win32Thread->KeyboardLayout->hkl; + pci->dwTIFlags = Win32Thread->TIF_flags; + /* CI may not have been initialized. */ + if (!pci->pDeskInfo && Win32Thread->pDeskInfo) + { + if (!pci->ulClientDelta) pci->ulClientDelta = DesktopHeapGetUserDelta(); + + pci->pDeskInfo = (PVOID)((ULONG_PTR)Win32Thread->pDeskInfo - pci->ulClientDelta); + } + } + else + { + DPRINT1("No TEB for this Thread!\n"); + } + Win32Thread->pEThread = Thread; } - else + else { - PSINGLE_LIST_ENTRY e; + PSINGLE_LIST_ENTRY e; - DPRINT("Destroying W32 thread TID:%d at IRQ level: %lu\n", Thread->Cid.UniqueThread, KeGetCurrentIrql()); + DPRINT("Destroying W32 thread TID:%d at IRQ level: %lu\n", Thread->Cid.UniqueThread, KeGetCurrentIrql()); - Win32Thread->TIF_flags |= TIF_INCLEANUP; - DceFreeThreadDCE(Win32Thread); - HOOK_DestroyThreadHooks(Thread); - EVENT_DestroyThreadEvents(Thread); - /* Cleanup timers */ - DestroyTimersForThread(Win32Thread); - KeSetEvent(Win32Thread->MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE); - UnregisterThreadHotKeys(Thread); - /* what if this co_ func crash in umode? what will clean us up then? */ - co_DestroyThreadWindows(Thread); - IntBlockInput(Win32Thread, FALSE); - MsqDestroyMessageQueue(Win32Thread->MessageQueue); - IntCleanupThreadCallbacks(Win32Thread); + Win32Thread->TIF_flags |= TIF_INCLEANUP; + DceFreeThreadDCE(Win32Thread); + HOOK_DestroyThreadHooks(Thread); + EVENT_DestroyThreadEvents(Thread); + /* Cleanup timers */ + DestroyTimersForThread(Win32Thread); + KeSetEvent(Win32Thread->MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE); + UnregisterThreadHotKeys(Thread); + /* what if this co_ func crash in umode? what will clean us up then? */ + co_DestroyThreadWindows(Thread); + IntBlockInput(Win32Thread, FALSE); + MsqDestroyMessageQueue(Win32Thread->MessageQueue); + IntCleanupThreadCallbacks(Win32Thread); - /* cleanup user object references stack */ - e = PopEntryList(&Win32Thread->ReferencesList); - while (e) - { - PUSER_REFERENCE_ENTRY ref = CONTAINING_RECORD(e, USER_REFERENCE_ENTRY, Entry); - DPRINT("thread clean: remove reference obj 0x%x\n",ref->obj); - UserDereferenceObject(ref->obj); + /* cleanup user object references stack */ + e = PopEntryList(&Win32Thread->ReferencesList); + while (e) + { + PUSER_REFERENCE_ENTRY ref = CONTAINING_RECORD(e, USER_REFERENCE_ENTRY, Entry); + DPRINT("thread clean: remove reference obj 0x%x\n",ref->obj); + UserDereferenceObject(ref->obj); - e = PopEntryList(&Win32Thread->ReferencesList); - } + e = PopEntryList(&Win32Thread->ReferencesList); + } - IntSetThreadDesktop(NULL, - TRUE); + IntSetThreadDesktop(NULL, + TRUE); - PsSetThreadWin32Thread(Thread, NULL); + PsSetThreadWin32Thread(Thread, NULL); } - RETURN( STATUS_SUCCESS); + RETURN( STATUS_SUCCESS); CLEANUP: - UserLeave(); - DPRINT("Leave Win32kThreadCallback, ret=%i\n",_ret_); - END_CLEANUP; + UserLeave(); + DPRINT("Leave Win32kThreadCallback, ret=%i\n",_ret_); + END_CLEANUP; } -/* Only used in ntuser/input.c KeyboardThreadMain(). If it's - not called there anymore, please delete */ NTSTATUS Win32kInitWin32Thread(PETHREAD Thread) { - PEPROCESS Process; + PEPROCESS Process; - Process = Thread->ThreadsProcess; + Process = Thread->ThreadsProcess; - if (Process->Win32Process == NULL) + if (Process->Win32Process == NULL) { - /* FIXME - lock the process */ - Process->Win32Process = ExAllocatePoolWithTag(NonPagedPool, sizeof(PROCESSINFO), USERTAG_PROCESSINFO); + /* FIXME - lock the process */ + Process->Win32Process = ExAllocatePoolWithTag(NonPagedPool, sizeof(PROCESSINFO), USERTAG_PROCESSINFO); - if (Process->Win32Process == NULL) - return STATUS_NO_MEMORY; + if (Process->Win32Process == NULL) + return STATUS_NO_MEMORY; - RtlZeroMemory(Process->Win32Process, sizeof(PROCESSINFO)); - /* FIXME - unlock the process */ + RtlZeroMemory(Process->Win32Process, sizeof(PROCESSINFO)); + /* FIXME - unlock the process */ - Win32kProcessCallback(Process, TRUE); + Win32kProcessCallback(Process, TRUE); } - if (Thread->Tcb.Win32Thread == NULL) + if (Thread->Tcb.Win32Thread == NULL) { - Thread->Tcb.Win32Thread = ExAllocatePoolWithTag(NonPagedPool, sizeof(THREADINFO), USERTAG_THREADINFO); - if (Thread->Tcb.Win32Thread == NULL) - return STATUS_NO_MEMORY; + Thread->Tcb.Win32Thread = ExAllocatePoolWithTag(NonPagedPool, sizeof(THREADINFO), USERTAG_THREADINFO); + if (Thread->Tcb.Win32Thread == NULL) + return STATUS_NO_MEMORY; - RtlZeroMemory(Thread->Tcb.Win32Thread, sizeof(THREADINFO)); + RtlZeroMemory(Thread->Tcb.Win32Thread, sizeof(THREADINFO)); - Win32kThreadCallback(Thread, PsW32ThreadCalloutInitialize); + Win32kThreadCallback(Thread, PsW32ThreadCalloutInitialize); } - return(STATUS_SUCCESS); + return(STATUS_SUCCESS); } C_ASSERT(sizeof(SERVERINFO) <= PAGE_SIZE); +// Return on failure +#define NT_ROF(x) \ + Status = (x); \ + if (!NT_SUCCESS(Status)) \ + { \ + DPRINT1("Failed '%s' (0x%lx)\n", #x, Status); \ + return Status; \ + } + /* * This definition doesn't work */ -NTSTATUS APIENTRY -DriverEntry ( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath) +INIT_FUNCTION +NTSTATUS +APIENTRY +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) { - NTSTATUS Status; - BOOLEAN Result; - WIN32_CALLOUTS_FPNS CalloutData = {0}; - PVOID GlobalUserHeapBase = NULL; + NTSTATUS Status; + BOOLEAN Result; + WIN32_CALLOUTS_FPNS CalloutData = {0}; + PVOID GlobalUserHeapBase = NULL; - /* - * Register user mode call interface - * (system service table index = 1) - */ - Result = KeAddSystemServiceTable (Win32kSSDT, - NULL, - Win32kNumberOfSysCalls, - Win32kSSPT, - 1); - if (Result == FALSE) + /* + * Register user mode call interface + * (system service table index = 1) + */ + Result = KeAddSystemServiceTable(Win32kSSDT, + NULL, + Win32kNumberOfSysCalls, + Win32kSSPT, + 1); + if (Result == FALSE) { - DPRINT1("Adding system services failed!\n"); - return STATUS_UNSUCCESSFUL; + DPRINT1("Adding system services failed!\n"); + return STATUS_UNSUCCESSFUL; } - hModuleWin = MmPageEntireDriver(DriverEntry); - DPRINT("Win32k hInstance 0x%x!\n",hModuleWin); - /* - * Register Object Manager Callbacks - */ + hModuleWin = MmPageEntireDriver(DriverEntry); + DPRINT("Win32k hInstance 0x%x!\n",hModuleWin); + + /* Register Object Manager Callbacks */ CalloutData.WindowStationParseProcedure = IntWinStaObjectParse; CalloutData.WindowStationDeleteProcedure = IntWinStaObjectDelete; CalloutData.DesktopDeleteProcedure = IntDesktopObjectDelete; @@ -408,11 +430,10 @@ DriverEntry ( CalloutData.ThreadCallout = Win32kThreadCallback; CalloutData.BatchFlushRoutine = NtGdiFlushUserBatch; - /* - * Register our per-process and per-thread structures. - */ + /* Register our per-process and per-thread structures. */ PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS)&CalloutData); + /* Create the global USER heap */ GlobalUserHeap = UserCreateHeap(&GlobalUserHeapSection, &GlobalUserHeapBase, 1 * 1024 * 1024); /* FIXME - 1 MB for now... */ @@ -422,150 +443,54 @@ DriverEntry ( return STATUS_UNSUCCESSFUL; } - if (!gpsi) - { - gpsi = UserHeapAlloc(sizeof(SERVERINFO)); - if (gpsi) - { - RtlZeroMemory(gpsi, sizeof(SERVERINFO)); - DPRINT("Global Server Data -> %x\n", gpsi); - } - else - { - ASSERT(FALSE); - } - } - - if(!hsemDriverMgmt) hsemDriverMgmt = EngCreateSemaphore(); - - GdiHandleTable = GDIOBJ_iAllocHandleTable(&GdiTableSection); - if (GdiHandleTable == NULL) - { - DPRINT1("Failed to initialize the GDI handle table.\n"); - return STATUS_UNSUCCESSFUL; - } - - /* Initialize default palettes */ - PALETTE_Init(); - - /* Create stock objects, ie. precreated objects commonly - used by win32 applications */ - CreateStockObjects(); - CreateSysColorObjects(); - - InitXlateImpl(); - InitPDEVImpl(); - InitLDEVImpl(); - InitDeviceImpl(); - - Status = InitDcImpl(); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to initialize Device context implementation!\n"); - return STATUS_UNSUCCESSFUL; - } - - Status = InitUserImpl(); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to initialize user implementation!\n"); - return STATUS_UNSUCCESSFUL; - } - - Status = InitHotkeyImpl(); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to initialize hotkey implementation!\n"); - return STATUS_UNSUCCESSFUL; - } - - Status = InitWindowStationImpl(); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to initialize window station implementation!\n"); - return STATUS_UNSUCCESSFUL; - } - - Status = InitDesktopImpl(); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to initialize desktop implementation!\n"); - return STATUS_UNSUCCESSFUL; - } - - Status = InitWindowImpl(); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to initialize window implementation!\n"); - return STATUS_UNSUCCESSFUL; - } - - Status = InitMenuImpl(); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to initialize menu implementation!\n"); - return STATUS_UNSUCCESSFUL; - } - - Status = InitInputImpl(); - if (!NT_SUCCESS(Status)) + /* Allocate global server info structure */ + gpsi = UserHeapAlloc(sizeof(SERVERINFO)); + if (!gpsi) { - DPRINT1("Failed to initialize input implementation.\n"); - return(Status); + DPRINT1("Failed allocate server info structure!\n"); + return STATUS_UNSUCCESSFUL; } - Status = InitKeyboardImpl(); - if (!NT_SUCCESS(Status)) + RtlZeroMemory(gpsi, sizeof(SERVERINFO)); + DPRINT("Global Server Data -> %x\n", gpsi); + + NT_ROF(InitGdiHandleTable()); + NT_ROF(InitPaletteImpl()); + + /* Create stock objects, ie. precreated objects commonly + used by win32 applications */ + CreateStockObjects(); + CreateSysColorObjects(); + + NT_ROF(InitXlateImpl()); + NT_ROF(InitPDEVImpl()); + NT_ROF(InitLDEVImpl()); + NT_ROF(InitDeviceImpl()); + NT_ROF(InitDcImpl()); + NT_ROF(InitUserImpl()); + NT_ROF(InitHotkeyImpl()); + NT_ROF(InitWindowStationImpl()); + NT_ROF(InitDesktopImpl()); + NT_ROF(InitWindowImpl()); + NT_ROF(InitMenuImpl()); + NT_ROF(InitInputImpl()); + NT_ROF(InitKeyboardImpl()); + NT_ROF(InitMonitorImpl()); + NT_ROF(MsqInitializeImpl()); + NT_ROF(InitTimerImpl()); + NT_ROF(InitAcceleratorImpl()); + NT_ROF(InitGuiCheckImpl()); + + /* Initialize FreeType library */ + if (!InitFontSupport()) { - DPRINT1("Failed to initialize keyboard implementation.\n"); - return(Status); + DPRINT1("Unable to initialize font support\n"); + return Status; } - Status = InitMonitorImpl(); - if (!NT_SUCCESS(Status)) - { - DbgPrint("Failed to initialize monitor implementation!\n"); - return STATUS_UNSUCCESSFUL; - } + gusLanguageID = IntGdiGetLanguageID(); - Status = MsqInitializeImpl(); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to initialize message queue implementation.\n"); - return(Status); - } - - Status = InitTimerImpl(); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to initialize timer implementation.\n"); - return(Status); - } - - Status = InitAcceleratorImpl(); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to initialize accelerator implementation.\n"); - return(Status); - } - - Status = InitGuiCheckImpl(); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to initialize GUI check implementation.\n"); - return(Status); - } - - /* Initialize FreeType library */ - if (! InitFontSupport()) - { - DPRINT1("Unable to initialize font support\n"); - return STATUS_UNSUCCESSFUL; - } - - gusLanguageID = IntGdiGetLanguageID(); - - return STATUS_SUCCESS; + return STATUS_SUCCESS; } /* EOF */ diff --git a/subsystems/win32/win32k/ntuser/accelerator.c b/subsystems/win32/win32k/ntuser/accelerator.c index a913de1ebfa..cb0eca60d00 100644 --- a/subsystems/win32/win32k/ntuser/accelerator.c +++ b/subsystems/win32/win32k/ntuser/accelerator.c @@ -56,7 +56,9 @@ /* FUNCTIONS *****************************************************************/ -NTSTATUS FASTCALL +INIT_FUNCTION +NTSTATUS +NTAPI InitAcceleratorImpl(VOID) { return(STATUS_SUCCESS); diff --git a/subsystems/win32/win32k/ntuser/callback.c b/subsystems/win32/win32k/ntuser/callback.c index 2b4f2409a8b..bb087f074f5 100644 --- a/subsystems/win32/win32k/ntuser/callback.c +++ b/subsystems/win32/win32k/ntuser/callback.c @@ -335,6 +335,7 @@ co_IntCallHookProc(INT HookId, PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra = NULL; PTHREADINFO pti; PWND pWnd; + PMSG pMsg = NULL; BOOL Hit = FALSE; ASSERT(Proc); @@ -346,11 +347,12 @@ co_IntCallHookProc(INT HookId, return 0; } - ArgumentLength = sizeof(HOOKPROC_CALLBACK_ARGUMENTS) - sizeof(WCHAR) - + ModuleName->Length; + ArgumentLength = sizeof(HOOKPROC_CALLBACK_ARGUMENTS); + switch(HookId) { case WH_CBT: + DPRINT("WH_CBT: Code %d\n", Code); switch(Code) { case HCBT_CREATEWND: @@ -360,6 +362,7 @@ co_IntCallHookProc(INT HookId, DPRINT1("WH_CBT HCBT_CREATEWND wParam bad hWnd!\n"); goto Fault_Exit; } + DPRINT("HCBT_CREATEWND AnsiCreator %s, AnsiHook %s\n", pWnd->state & WNDS_ANSICREATOR ? "True" : "False", Ansi ? "True" : "False"); // Due to KsStudio.exe, just pass the callers original pointers // except class which point to kernel space if not an atom. // Found by, Olaf Siejka @@ -432,24 +435,20 @@ co_IntCallHookProc(INT HookId, Common->lParam = lParam; Common->Proc = Proc; Common->Ansi = Ansi; - Common->ModuleNameLength = ModuleName->Length; - if (ModuleName->Buffer) - RtlCopyMemory(Common->ModuleName, ModuleName->Buffer, ModuleName->Length); - Extra = (PCHAR) Common->ModuleName + Common->ModuleNameLength; + Extra = (PCHAR) Common + sizeof(HOOKPROC_CALLBACK_ARGUMENTS); switch(HookId) { case WH_CBT: switch(Code) - { + { // Need to remember this is not the first time through! Call Next Hook? case HCBT_CREATEWND: - Common->lParam = (LPARAM) (Extra - (PCHAR) Common); CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS) Extra; RtlCopyMemory( &CbtCreatewndExtra->Cs, CbtCreateWnd->lpcs, sizeof(CREATESTRUCTW) ); CbtCreatewndExtra->WndInsertAfter = CbtCreateWnd->hwndInsertAfter; - CbtCreatewndExtra->Cs.lpszClass = CbtCreateWnd->lpcs->lpszClass; // if Atom + CbtCreatewndExtra->Cs.lpszClass = CbtCreateWnd->lpcs->lpszClass; CbtCreatewndExtra->Cs.lpszName = CbtCreateWnd->lpcs->lpszName; - Extra = (PCHAR) (CbtCreatewndExtra + 1); + Common->lParam = (LPARAM) (Extra - (PCHAR) Common); break; case HCBT_CLICKSKIPPED: RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MOUSEHOOKSTRUCT)); @@ -488,7 +487,8 @@ co_IntCallHookProc(INT HookId, case WH_MSGFILTER: case WH_SYSMSGFILTER: case WH_GETMESSAGE: - RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MSG)); + pMsg = (PMSG)lParam; + RtlCopyMemory(Extra, (PVOID) pMsg, sizeof(MSG)); Common->lParam = (LPARAM) (Extra - (PCHAR) Common); break; case WH_FOREGROUNDIDLE: @@ -525,6 +525,7 @@ co_IntCallHookProc(INT HookId, if (!NT_SUCCESS(Status)) { + DPRINT1("Failure to make Callback! Status 0x%x",Status); goto Fault_Exit; } /* Support write backs... SEH is in UserCallNextHookEx. */ @@ -548,9 +549,9 @@ co_IntCallHookProc(INT HookId, break; // "The GetMsgProc hook procedure can examine or modify the message." case WH_GETMESSAGE: - if (lParam) + if (pMsg) { - RtlCopyMemory((PVOID) lParam, Extra, sizeof(MSG)); + RtlCopyMemory((PVOID) pMsg, Extra, sizeof(MSG)); } break; } diff --git a/subsystems/win32/win32k/ntuser/cursoricon.c b/subsystems/win32/win32k/ntuser/cursoricon.c index 2d8ff953a06..37af3f00690 100644 --- a/subsystems/win32/win32k/ntuser/cursoricon.c +++ b/subsystems/win32/win32k/ntuser/cursoricon.c @@ -217,7 +217,7 @@ BOOL UserSetCursorPos( INT x, INT y, BOOL SendMouseMoveMsg) Msg.wParam = CurInfo->ButtonsDown; Msg.lParam = MAKELPARAM(x, y); Msg.pt = pt; - MsqInsertSystemMessage(&Msg); + MsqInsertMouseMessage(&Msg); } /* Store the new cursor position */ diff --git a/subsystems/win32/win32k/ntuser/desktop.c b/subsystems/win32/win32k/ntuser/desktop.c index 894245d219b..91b5a53224a 100644 --- a/subsystems/win32/win32k/ntuser/desktop.c +++ b/subsystems/win32/win32k/ntuser/desktop.c @@ -170,8 +170,9 @@ IntDesktopObjectDelete(PWIN32_DELETEMETHOD_PARAMETERS Parameters) /* PRIVATE FUNCTIONS **********************************************************/ +INIT_FUNCTION NTSTATUS -FASTCALL +NTAPI InitDesktopImpl(VOID) { /* Set Desktop Object Attributes */ @@ -879,14 +880,24 @@ NtUserCreateDesktop( PUNICODE_STRING lpszDesktopName = NULL; UNICODE_STRING ClassName, MenuName; LARGE_STRING WindowName; + BOOL NoHooks = FALSE; PWND pWnd = NULL; CREATESTRUCTW Cs; INT i; + PTHREADINFO ptiCurrent; DECLARE_RETURN(HDESK); DPRINT("Enter NtUserCreateDesktop: %wZ\n", lpszDesktopName); UserEnterExclusive(); + ptiCurrent = PsGetCurrentThreadWin32Thread(); + if (ptiCurrent) + { + /* Turn off hooks when calling any CreateWindowEx from inside win32k. */ + NoHooks = (ptiCurrent->TIF_flags & TIF_DISABLEHOOKS); + ptiCurrent->TIF_flags |= TIF_DISABLEHOOKS; + } + _SEH2_TRY { ProbeForRead( poa, @@ -1101,6 +1112,7 @@ NtUserCreateDesktop( RETURN( Desktop); CLEANUP: + if (!NoHooks && ptiCurrent) ptiCurrent->TIF_flags &= ~TIF_DISABLEHOOKS; DPRINT("Leave NtUserCreateDesktop, ret=%i\n",_ret_); UserLeave(); END_CLEANUP; diff --git a/subsystems/win32/win32k/ntuser/display.c b/subsystems/win32/win32k/ntuser/display.c index 7ab53638f1a..f5770a7ce2c 100644 --- a/subsystems/win32/win32k/ntuser/display.c +++ b/subsystems/win32/win32k/ntuser/display.c @@ -147,10 +147,9 @@ InitDisplayDriver( return pGraphicsDevice; } -BOOL -InitVideo( - PUNICODE_STRING pustrRegPath, - FLONG flags) +NTSTATUS +NTAPI +InitVideo() { ULONG iDevNum, iVGACompatible = -1, ulMaxObjectNumber = 0; WCHAR awcDeviceName[20]; @@ -160,8 +159,9 @@ InitVideo( ULONG cbValue; HKEY hkey; - DPRINT1("----------------------------- InitVideo() -------------------------------\n"); + DPRINT("----------------------------- InitVideo() -------------------------------\n"); + /* Open the key for the boot command line */ Status = RegOpenKey(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control", &hkey); if (NT_SUCCESS(Status)) { @@ -185,7 +185,7 @@ InitVideo( if (!NT_SUCCESS(Status)) { DPRINT1("Could not open device registry key!\n"); - ASSERT(FALSE); + return Status; } /* Read the name of the VGA adapter */ @@ -206,16 +206,23 @@ InitVideo( DPRINT("Found %ld devices\n", ulMaxObjectNumber); /* Loop through all adapters */ - cbValue = 256; for (iDevNum = 0; iDevNum <= ulMaxObjectNumber; iDevNum++) { /* Create the adapter's key name */ swprintf(awcDeviceName, L"\\Device\\Video%lu", iDevNum); /* Read the reg key name */ + cbValue = sizeof(awcBuffer); Status = RegQueryValue(hkey, awcDeviceName, REG_SZ, awcBuffer, &cbValue); + if (!NT_SUCCESS(Status)) + { + DPRINT1("failed to query the registry path:0x%lx\n", Status); + continue; + } + /* Initialize the driver for this device */ pGraphicsDevice = InitDisplayDriver(awcDeviceName, awcBuffer); + if (!pGraphicsDevice) continue; /* Check if this is the VGA adapter */ if (iDevNum == iVGACompatible) @@ -230,8 +237,16 @@ InitVideo( gpPrimaryGraphicsDevice = pGraphicsDevice; } + /* Close the device map registry key */ ZwClose(hkey); + /* Check if we had any success */ + if (!gpPrimaryGraphicsDevice) + { + DPRINT1("No usable display driver was found.\n"); + return STATUS_UNSUCCESSFUL; + } + if (gbBaseVideo) { if (gpVgaGraphicsDevice) diff --git a/subsystems/win32/win32k/ntuser/event.c b/subsystems/win32/win32k/ntuser/event.c index e768c2e09d0..cdc2092439a 100644 --- a/subsystems/win32/win32k/ntuser/event.c +++ b/subsystems/win32/win32k/ntuser/event.c @@ -120,7 +120,7 @@ IntCallLowLevelEvent( PEVENTHOOK pEH, event, 0, (LPARAM)pEP, - 5000, + 300, TRUE, MSQ_ISEVENT, &uResult); diff --git a/subsystems/win32/win32k/ntuser/guicheck.c b/subsystems/win32/win32k/ntuser/guicheck.c index e3766d8c4b2..50421737fb9 100644 --- a/subsystems/win32/win32k/ntuser/guicheck.c +++ b/subsystems/win32/win32k/ntuser/guicheck.c @@ -130,7 +130,9 @@ IntUserManualGuiCheck(LONG Check) } -NTSTATUS FASTCALL +INIT_FUNCTION +NTSTATUS +NTAPI InitGuiCheckImpl (VOID) { return STATUS_SUCCESS; diff --git a/subsystems/win32/win32k/ntuser/hook.c b/subsystems/win32/win32k/ntuser/hook.c index ed2a30e6271..f41d7bad0ce 100644 --- a/subsystems/win32/win32k/ntuser/hook.c +++ b/subsystems/win32/win32k/ntuser/hook.c @@ -21,6 +21,7 @@ typedef struct _HOOKPACK { PHOOK pHk; LPARAM lParam; + PVOID pHookStructs; } HOOKPACK, *PHOOKPACK; /* PRIVATE FUNCTIONS *********************************************************/ @@ -36,6 +37,9 @@ IntCallLowLevelHook( PHOOK Hook, NTSTATUS Status; PTHREADINFO pti; PHOOKPACK pHP; + INT Size; + UINT uTimeout = 300; + BOOL Block = FALSE; ULONG_PTR uResult = 0; if (Hook->Thread) @@ -48,6 +52,40 @@ IntCallLowLevelHook( PHOOK Hook, pHP->pHk = Hook; pHP->lParam = lParam; + pHP->pHookStructs = NULL; + Size = 0; + +// This prevents stack corruption from the caller. + switch(Hook->HookId) + { + case WH_JOURNALPLAYBACK: + case WH_JOURNALRECORD: + uTimeout = 0; + Size = sizeof(EVENTMSG); + break; + case WH_KEYBOARD_LL: + Size = sizeof(KBDLLHOOKSTRUCT); + break; + case WH_MOUSE_LL: + Size = sizeof(MSLLHOOKSTRUCT); + break; + case WH_MOUSE: + uTimeout = 200; + Block = TRUE; + Size = sizeof(MOUSEHOOKSTRUCT); + break; + case WH_KEYBOARD: + uTimeout = 200; + Block = TRUE; + Size = sizeof(KBDLLHOOKSTRUCT); + break; + } + + if (Size) + { + pHP->pHookStructs = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_HOOK); + if (pHP->pHookStructs) RtlCopyMemory(pHP->pHookStructs, (PVOID)lParam, Size); + } /* FIXME should get timeout from * HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */ @@ -55,43 +93,20 @@ IntCallLowLevelHook( PHOOK Hook, IntToPtr(Code), // hWnd Hook->HookId, // Msg wParam, - (LPARAM)pHP, - 5000, - TRUE, + (LPARAM)pHP, + uTimeout, + Block, MSQ_ISHOOK, &uResult); if (!NT_SUCCESS(Status)) { DPRINT1("Error Hook Call SendMsg. %d Status: 0x%x\n", Hook->HookId, Status); + if (pHP->pHookStructs) ExFreePoolWithTag(pHP->pHookStructs, TAG_HOOK); ExFreePoolWithTag(pHP, TAG_HOOK); } return NT_SUCCESS(Status) ? uResult : 0; } -static -LRESULT -FASTCALL -co_HOOK_CallHookNext( PHOOK Hook, - INT Code, - WPARAM wParam, - LPARAM lParam) -{ - if ( (Hook->Thread != PsGetCurrentThread()) && (Hook->Thread != NULL) ) - { - DPRINT1("Calling Next HOOK from another Thread. %d\n", Hook->HookId); - return IntCallLowLevelHook(Hook, Code, wParam, lParam); - } - - DPRINT("Calling Next HOOK %d\n", Hook->HookId); - - return co_IntCallHookProc( Hook->HookId, - Code, - wParam, - lParam, - Hook->Proc, - Hook->Ansi, - &Hook->ModuleName); -} // // Dispatch MsgQueue Hook Call processor! @@ -108,19 +123,54 @@ co_CallHook( INT HookId, PHOOKPACK pHP = (PHOOKPACK)lParam; phk = pHP->pHk; + lParam = pHP->lParam; + + switch(HookId) + { + case WH_JOURNALPLAYBACK: + case WH_JOURNALRECORD: + case WH_KEYBOARD: + case WH_KEYBOARD_LL: + case WH_MOUSE_LL: + case WH_MOUSE: + lParam = (LPARAM)pHP->pHookStructs; + break; + } + /* The odds are high for this to be a Global call. */ Result = co_IntCallHookProc( HookId, Code, wParam, - pHP->lParam, + lParam, phk->Proc, phk->Ansi, &phk->ModuleName); + /* The odds so high, no one is waiting for the results. */ + if (pHP->pHookStructs) ExFreePoolWithTag(pHP->pHookStructs, TAG_HOOK); ExFreePoolWithTag(pHP, TAG_HOOK); return Result; } +static +LRESULT +FASTCALL +co_HOOK_CallHookNext( PHOOK Hook, + INT Code, + WPARAM wParam, + LPARAM lParam) +{ + DPRINT("Calling Next HOOK %d\n", Hook->HookId); + + return co_IntCallHookProc( Hook->HookId, + Code, + wParam, + lParam, + Hook->Proc, + Hook->Ansi, + &Hook->ModuleName); +} + LRESULT FASTCALL IntCallDebugHook( PHOOK Hook, @@ -704,6 +754,20 @@ IntGetFirstHook(PLIST_ENTRY Table) return Elem == Table ? NULL : CONTAINING_RECORD(Elem, HOOK, Chain); } +static +PHOOK +FASTCALL +IntGetNextGlobalHook(PHOOK Hook, PDESKTOP pdo) +{ + int HookId = Hook->HookId; + PLIST_ENTRY Elem; + + Elem = Hook->Chain.Flink; + if (Elem != &pdo->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]) + return CONTAINING_RECORD(Elem, HOOK, Chain); + return NULL; +} + /* find the next hook in the chain */ PHOOK FASTCALL @@ -724,10 +788,7 @@ IntGetNextHook(PHOOK Hook) else { pti = PsGetCurrentThreadWin32Thread(); - - Elem = Hook->Chain.Flink; - if (Elem != &pti->rpdesk->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]) - return CONTAINING_RECORD(Elem, HOOK, Chain); + return IntGetNextGlobalHook(Hook, pti->rpdesk); } return NULL; } @@ -756,6 +817,7 @@ IntRemoveHook(PHOOK Hook) { INT HookId; PTHREADINFO pti; + PDESKTOP pdo; HookId = Hook->HookId; @@ -783,13 +845,13 @@ IntRemoveHook(PHOOK Hook) { IntFreeHook( Hook); - pti = PsGetCurrentThreadWin32Thread(); + pdo = IntGetActiveDesktop(); - if ( pti->rpdesk && - pti->rpdesk->pDeskInfo && - IsListEmpty(&pti->rpdesk->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]) ) + if ( pdo && + pdo->pDeskInfo && + IsListEmpty(&pdo->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]) ) { - pti->rpdesk->pDeskInfo->fsHooks &= ~HOOKID_TO_FLAG(HookId); + pdo->pDeskInfo->fsHooks &= ~HOOKID_TO_FLAG(HookId); return TRUE; } } @@ -801,12 +863,20 @@ FASTCALL HOOK_DestroyThreadHooks(PETHREAD Thread) { PTHREADINFO pti; + PDESKTOP pdo; int HookId; PHOOK HookObj; PLIST_ENTRY pElem; pti = Thread->Tcb.Win32Thread; - if (!pti || !pti->pDeskInfo) return; + pdo = IntGetActiveDesktop(); + + if (!pti || !pdo) + { + DPRINT1("Kill Thread Hooks pti 0x%x pdo 0x%x\n",pti,pdo); + return; + } + ObReferenceObject(Thread); // Local Thread cleanup. if (pti->fsHooks) @@ -831,11 +901,11 @@ HOOK_DestroyThreadHooks(PETHREAD Thread) pti->fsHooks = 0; } // Global search based on Thread and cleanup. - if (pti->rpdesk->pDeskInfo->fsHooks) + if (pdo->pDeskInfo->fsHooks) { for (HookId = WH_MINHOOK; HookId <= WH_MAXHOOK; HookId++) { - PLIST_ENTRY pGLE = &pti->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]; + PLIST_ENTRY pGLE = &pdo->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]; if (IsListEmpty(pGLE)) continue; @@ -854,6 +924,7 @@ HOOK_DestroyThreadHooks(PETHREAD Thread) while (pElem != pGLE); } } + ObDereferenceObject(Thread); return; } @@ -871,6 +942,7 @@ co_HOOK_CallHooks( INT HookId, PTHREADINFO pti; PCLIENTINFO ClientInfo; PLIST_ENTRY pLLE, pGLE; + PDESKTOP pdo; BOOL Local = FALSE, Global = FALSE; LRESULT Result = 0; @@ -878,10 +950,27 @@ co_HOOK_CallHooks( INT HookId, pti = PsGetCurrentThreadWin32Thread(); if (!pti || !pti->rpdesk || !pti->rpdesk->pDeskInfo) - goto Exit; // Must have a desktop running for hooks. + { + pdo = IntGetActiveDesktop(); + /* If KeyboardThread|MouseThread|(RawInputThread or RIT) aka system threads, + pti->fsHooks most likely, is zero. So process KbT & MsT to "send" the message. + */ + if ( !pti || !pdo || (!(HookId == WH_KEYBOARD_LL) && !(HookId == WH_MOUSE_LL)) ) + { + DPRINT("No PDO %d\n", HookId); + goto Exit; + } + } + else + { + pdo = pti->rpdesk; + } - if ( pti->TIF_flags & TIF_INCLEANUP) + if ( pti->TIF_flags & (TIF_INCLEANUP|TIF_DISABLEHOOKS)) + { + DPRINT("Hook Thread dead %d\n", HookId); goto Exit; + } if ( ISITHOOKED(HookId) ) { @@ -889,7 +978,7 @@ co_HOOK_CallHooks( INT HookId, Local = TRUE; } - if ( pti->rpdesk->pDeskInfo->fsHooks & HOOKID_TO_FLAG(HookId) ) + if ( pdo->pDeskInfo->fsHooks & HOOKID_TO_FLAG(HookId) ) { DPRINT("Global Hooker %d\n", HookId); Global = TRUE; @@ -897,8 +986,6 @@ co_HOOK_CallHooks( INT HookId, if ( !Local && !Global ) goto Exit; // No work! - pLLE = &pti->aphkStart[HOOKID_TO_INDEX(HookId)]; - pGLE = &pti->rpdesk->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]; Hook = NULL; /* SetWindowHookEx sorts out the Thread issue by placing the Hook to @@ -906,6 +993,7 @@ co_HOOK_CallHooks( INT HookId, */ if ( Local ) { + pLLE = &pti->aphkStart[HOOKID_TO_INDEX(HookId)]; Hook = IntGetFirstHook(pLLE); if (!Hook) { @@ -959,6 +1047,7 @@ co_HOOK_CallHooks( INT HookId, { PTHREADINFO ptiHook; + pGLE = &pdo->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]; Hook = IntGetFirstHook(pGLE); if (!Hook) { @@ -977,19 +1066,28 @@ co_HOOK_CallHooks( INT HookId, /* "Global hook monitors messages for all threads in the same desktop * as the calling thread." */ - if ( ptiHook->TIF_flags & TIF_INCLEANUP || - ptiHook->rpdesk != pti->rpdesk) + if ( ptiHook->TIF_flags & (TIF_INCLEANUP|TIF_DISABLEHOOKS) || + ptiHook->rpdesk != pdo) { - Hook = IntGetNextHook(Hook); + DPRINT("Next Hook 0x%x, 0x%x\n",ptiHook->rpdesk,pdo); + Hook = IntGetNextGlobalHook(Hook, pdo); if (!Hook) break; continue; } // Lockup the thread while this links through user world. ObReferenceObject(ptiHook->pEThread); if (ptiHook != pti ) - { - DPRINT("\nGlobal Hook posting to another Thread! %d\n",HookId ); - Result = IntCallLowLevelHook(Hook, Code, wParam, lParam); + { // Block | TimeOut + if ( HookId == WH_JOURNALPLAYBACK || // 1 | 0 + HookId == WH_JOURNALRECORD || // 1 | 0 + HookId == WH_KEYBOARD || // 1 | 200 + HookId == WH_MOUSE || // 1 | 200 + HookId == WH_KEYBOARD_LL || // 0 | 300 + HookId == WH_MOUSE_LL ) // 0 | 300 + { + DPRINT("\nGlobal Hook posting to another Thread! %d\n",HookId ); + Result = IntCallLowLevelHook(Hook, Code, wParam, lParam); + } } else { /* Make the direct call. */ @@ -1003,7 +1101,7 @@ co_HOOK_CallHooks( INT HookId, &Hook->ModuleName); } ObDereferenceObject(ptiHook->pEThread); - Hook = IntGetNextHook(Hook); + Hook = IntGetNextGlobalHook(Hook, pdo); } while ( Hook ); DPRINT("Ret: Global HookId %d Result 0x%x\n", HookId,Result); @@ -1158,7 +1256,7 @@ NtUserSetWindowsHookEx( HINSTANCE Mod, DPRINT("Enter NtUserSetWindowsHookEx\n"); UserEnterExclusive(); - ptiCurrent = GetW32ThreadInfo(); + ptiCurrent = PsGetCurrentThreadWin32Thread(); if (HookId < WH_MINHOOK || WH_MAXHOOK < HookId ) { @@ -1237,7 +1335,7 @@ NtUserSetWindowsHookEx( HINSTANCE Mod, } } else /* system-global hook */ - { + { pti = ptiCurrent; // gptiCurrent; if ( !Mod && (HookId == WH_GETMESSAGE || @@ -1283,6 +1381,8 @@ NtUserSetWindowsHookEx( HINSTANCE Mod, Hook->Proc = HookProc; Hook->Ansi = Ansi; + DPRINT("Set Hook Desk 0x%x DeskInfo 0x%x Handle Desk 0x%x\n",pti->rpdesk, pti->pDeskInfo,Hook->head.rpdesk); + if (ThreadId) /* thread-local hook */ { InsertHeadList(&pti->aphkStart[HOOKID_TO_INDEX(HookId)], &Hook->Chain); @@ -1297,7 +1397,7 @@ NtUserSetWindowsHookEx( HINSTANCE Mod, _SEH2_TRY { pti->pClientInfo->fsHooks = pti->fsHooks; - pti->pClientInfo->phkCurrent = 0; + pti->pClientInfo->phkCurrent = NULL; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -1315,7 +1415,7 @@ NtUserSetWindowsHookEx( HINSTANCE Mod, _SEH2_TRY { pti->pClientInfo->fsHooks = pti->fsHooks; - pti->pClientInfo->phkCurrent = 0; + pti->pClientInfo->phkCurrent = NULL; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -1332,10 +1432,12 @@ NtUserSetWindowsHookEx( HINSTANCE Mod, } else { - InsertHeadList(&pti->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)], &Hook->Chain); + InsertHeadList(&pti->rpdesk->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)], &Hook->Chain); Hook->ptiHooked = NULL; //gptiCurrent->pDeskInfo->fsHooks |= HOOKID_TO_FLAG(HookId); - pti->pDeskInfo->fsHooks |= HOOKID_TO_FLAG(HookId); + pti->rpdesk->pDeskInfo->fsHooks |= HOOKID_TO_FLAG(HookId); + pti->sphkCurrent = NULL; + pti->pClientInfo->phkCurrent = NULL; } RtlInitUnicodeString(&Hook->ModuleName, NULL); @@ -1382,7 +1484,7 @@ NtUserSetWindowsHookEx( HINSTANCE Mod, else Hook->offPfn = 0; - DPRINT1("Installing: HookId %d Global %s\n", HookId, !ThreadId ? "TRUE" : "FALSE"); + DPRINT("Installing: HookId %d Global %s\n", HookId, !ThreadId ? "TRUE" : "FALSE"); RETURN( Handle); CLEANUP: diff --git a/subsystems/win32/win32k/ntuser/hotkey.c b/subsystems/win32/win32k/ntuser/hotkey.c index adfc6a5c3e1..0b8a68efc84 100644 --- a/subsystems/win32/win32k/ntuser/hotkey.c +++ b/subsystems/win32/win32k/ntuser/hotkey.c @@ -51,7 +51,9 @@ LIST_ENTRY gHotkeyList; /* FUNCTIONS *****************************************************************/ -NTSTATUS FASTCALL +INIT_FUNCTION +NTSTATUS +NTAPI InitHotkeyImpl(VOID) { InitializeListHead(&gHotkeyList); diff --git a/subsystems/win32/win32k/ntuser/input.c b/subsystems/win32/win32k/ntuser/input.c index 9a4339d1981..e47339cad3a 100644 --- a/subsystems/win32/win32k/ntuser/input.c +++ b/subsystems/win32/win32k/ntuser/input.c @@ -22,6 +22,8 @@ extern NTSTATUS Win32kInitWin32Thread(PETHREAD Thread); /* GLOBALS *******************************************************************/ PTHREADINFO ptiRawInput; +PTHREADINFO ptiKeyboard; +PTHREADINFO ptiMouse; PKTIMER MasterTimer = NULL; PATTACHINFO gpai = NULL; @@ -234,6 +236,18 @@ MouseThreadMain(PVOID StartContext) FILE_SYNCHRONOUS_IO_ALERT); } while (!NT_SUCCESS(Status)); + /* Need to setup basic win32k for this thread to process WH_MOUSE_LL messages. */ + Status = Win32kInitWin32Thread(PsGetCurrentThread()); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Win32K: Failed making mouse thread a win32 thread.\n"); + return; //(Status); + } + + ptiMouse = PsGetCurrentThreadWin32Thread(); + ptiMouse->TIF_flags |= TIF_SYSTEMTHREAD; + DPRINT1("\nMouse Thread 0x%x \n", ptiMouse); + KeSetPriorityThread(&PsGetCurrentThread()->Tcb, LOW_REALTIME_PRIORITY + 3); @@ -530,6 +544,10 @@ KeyboardThreadMain(PVOID StartContext) return; //(Status); } + ptiKeyboard = PsGetCurrentThreadWin32Thread(); + ptiKeyboard->TIF_flags |= TIF_SYSTEMTHREAD; + DPRINT1("\nKeyboard Thread 0x%x \n", ptiKeyboard); + KeSetPriorityThread(&PsGetCurrentThread()->Tcb, LOW_REALTIME_PRIORITY + 3); @@ -890,8 +908,8 @@ RawInputThreadMain(PVOID StartContext) } ptiRawInput = PsGetCurrentThreadWin32Thread(); - DPRINT("\nRaw Input Thread 0x%x \n", ptiRawInput); - + ptiRawInput->TIF_flags |= TIF_SYSTEMTHREAD; + DPRINT1("\nRaw Input Thread 0x%x \n", ptiRawInput); KeSetPriorityThread(&PsGetCurrentThread()->Tcb, LOW_REALTIME_PRIORITY + 3); @@ -922,7 +940,9 @@ RawInputThreadMain(PVOID StartContext) DPRINT1("Raw Input Thread Exit!\n"); } -NTSTATUS FASTCALL +INIT_FUNCTION +NTSTATUS +NTAPI InitInputImpl(VOID) { NTSTATUS Status; @@ -1136,7 +1156,7 @@ IntMouseInput(MOUSEINPUT *mi) Msg.message = SwapBtnMsg[0][SwapButtons]; CurInfo->ButtonsDown |= SwapBtn[SwapButtons]; Msg.wParam |= CurInfo->ButtonsDown; - MsqInsertSystemMessage(&Msg); + MsqInsertMouseMessage(&Msg); } else if(mi->dwFlags & MOUSEEVENTF_LEFTUP) { @@ -1144,7 +1164,7 @@ IntMouseInput(MOUSEINPUT *mi) Msg.message = SwapBtnMsg[1][SwapButtons]; CurInfo->ButtonsDown &= ~SwapBtn[SwapButtons]; Msg.wParam |= CurInfo->ButtonsDown; - MsqInsertSystemMessage(&Msg); + MsqInsertMouseMessage(&Msg); } if(mi->dwFlags & MOUSEEVENTF_MIDDLEDOWN) { @@ -1152,7 +1172,7 @@ IntMouseInput(MOUSEINPUT *mi) Msg.message = WM_MBUTTONDOWN; CurInfo->ButtonsDown |= MK_MBUTTON; Msg.wParam |= CurInfo->ButtonsDown; - MsqInsertSystemMessage(&Msg); + MsqInsertMouseMessage(&Msg); } else if(mi->dwFlags & MOUSEEVENTF_MIDDLEUP) { @@ -1160,7 +1180,7 @@ IntMouseInput(MOUSEINPUT *mi) Msg.message = WM_MBUTTONUP; CurInfo->ButtonsDown &= ~MK_MBUTTON; Msg.wParam |= CurInfo->ButtonsDown; - MsqInsertSystemMessage(&Msg); + MsqInsertMouseMessage(&Msg); } if(mi->dwFlags & MOUSEEVENTF_RIGHTDOWN) { @@ -1168,7 +1188,7 @@ IntMouseInput(MOUSEINPUT *mi) Msg.message = SwapBtnMsg[0][!SwapButtons]; CurInfo->ButtonsDown |= SwapBtn[!SwapButtons]; Msg.wParam |= CurInfo->ButtonsDown; - MsqInsertSystemMessage(&Msg); + MsqInsertMouseMessage(&Msg); } else if(mi->dwFlags & MOUSEEVENTF_RIGHTUP) { @@ -1176,7 +1196,7 @@ IntMouseInput(MOUSEINPUT *mi) Msg.message = SwapBtnMsg[1][!SwapButtons]; CurInfo->ButtonsDown &= ~SwapBtn[!SwapButtons]; Msg.wParam |= CurInfo->ButtonsDown; - MsqInsertSystemMessage(&Msg); + MsqInsertMouseMessage(&Msg); } if((mi->dwFlags & (MOUSEEVENTF_XDOWN | MOUSEEVENTF_XUP)) && @@ -1194,14 +1214,14 @@ IntMouseInput(MOUSEINPUT *mi) gQueueKeyStateTable[VK_XBUTTON1] |= 0xc0; CurInfo->ButtonsDown |= MK_XBUTTON1; Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON1); - MsqInsertSystemMessage(&Msg); + MsqInsertMouseMessage(&Msg); } if(mi->mouseData & XBUTTON2) { gQueueKeyStateTable[VK_XBUTTON2] |= 0xc0; CurInfo->ButtonsDown |= MK_XBUTTON2; Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON2); - MsqInsertSystemMessage(&Msg); + MsqInsertMouseMessage(&Msg); } } else if(mi->dwFlags & MOUSEEVENTF_XUP) @@ -1212,21 +1232,21 @@ IntMouseInput(MOUSEINPUT *mi) gQueueKeyStateTable[VK_XBUTTON1] &= ~0x80; CurInfo->ButtonsDown &= ~MK_XBUTTON1; Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON1); - MsqInsertSystemMessage(&Msg); + MsqInsertMouseMessage(&Msg); } if(mi->mouseData & XBUTTON2) { gQueueKeyStateTable[VK_XBUTTON2] &= ~0x80; CurInfo->ButtonsDown &= ~MK_XBUTTON2; Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON2); - MsqInsertSystemMessage(&Msg); + MsqInsertMouseMessage(&Msg); } } if(mi->dwFlags & MOUSEEVENTF_WHEEL) { Msg.message = WM_MOUSEWHEEL; Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, mi->mouseData); - MsqInsertSystemMessage(&Msg); + MsqInsertMouseMessage(&Msg); } return TRUE; diff --git a/subsystems/win32/win32k/ntuser/keyboard.c b/subsystems/win32/win32k/ntuser/keyboard.c index 04be007a32d..49a65450be5 100644 --- a/subsystems/win32/win32k/ntuser/keyboard.c +++ b/subsystems/win32/win32k/ntuser/keyboard.c @@ -58,7 +58,10 @@ BYTE gQueueKeyStateTable[256]; /* FUNCTIONS *****************************************************************/ /* Initialization -- Right now, just zero the key state and init the lock */ -NTSTATUS FASTCALL InitKeyboardImpl(VOID) +INIT_FUNCTION +NTSTATUS +NTAPI +InitKeyboardImpl(VOID) { RtlZeroMemory(&gQueueKeyStateTable,0x100); return STATUS_SUCCESS; diff --git a/subsystems/win32/win32k/ntuser/menu.c b/subsystems/win32/win32k/ntuser/menu.c index 06618296b49..49e643ec596 100644 --- a/subsystems/win32/win32k/ntuser/menu.c +++ b/subsystems/win32/win32k/ntuser/menu.c @@ -86,7 +86,9 @@ UserMenuInfo( ( ((r).bottom >= y)) && \ ( ((r).top <= y)) ) -NTSTATUS FASTCALL +INIT_FUNCTION +NTSTATUS +NTAPI InitMenuImpl(VOID) { return(STATUS_SUCCESS); diff --git a/subsystems/win32/win32k/ntuser/message.c b/subsystems/win32/win32k/ntuser/message.c index 88ef49554f6..4fbdb42f4e9 100644 --- a/subsystems/win32/win32k/ntuser/message.c +++ b/subsystems/win32/win32k/ntuser/message.c @@ -15,6 +15,8 @@ #define NDEBUG #include +BOOLEAN NTAPI PsGetProcessExitProcessCalled(PEPROCESS Process); + #define PM_BADMSGFLAGS ~((QS_RAWINPUT << 16)|PM_QS_SENDMESSAGE|PM_QS_PAINT|PM_QS_POSTMESSAGE|PM_QS_INPUT|PM_NOYIELD|PM_REMOVE) typedef struct @@ -323,6 +325,52 @@ UnpackParam(LPARAM lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL No return STATUS_INVALID_PARAMETER; } +// +// Wakeup any thread/process waiting on idle input. +// +VOID FASTCALL +IdlePing(VOID) +{ + PPROCESSINFO ppi = PsGetCurrentProcessWin32Process(); + PUSER_MESSAGE_QUEUE ForegroundQueue; + PTHREADINFO pti, ptiForeground = NULL; + + ForegroundQueue = IntGetFocusMessageQueue(); + + if (ForegroundQueue) + ptiForeground = ForegroundQueue->Thread->Tcb.Win32Thread; + + pti = PsGetCurrentThreadWin32Thread(); + + if ( pti && pti->pDeskInfo && pti == ptiForeground ) + { + if ( pti->fsHooks & HOOKID_TO_FLAG(WH_FOREGROUNDIDLE) || + pti->pDeskInfo->fsHooks & HOOKID_TO_FLAG(WH_FOREGROUNDIDLE) ) + { + co_HOOK_CallHooks(WH_FOREGROUNDIDLE,HC_ACTION,0,0); + } + } + + DPRINT("IdlePing ppi 0x%x\n",ppi); + if ( ppi && ppi->InputIdleEvent ) + { + DPRINT("InputIdleEvent\n"); + KeSetEvent( ppi->InputIdleEvent, IO_NO_INCREMENT, FALSE); + } +} + +VOID FASTCALL +IdlePong(VOID) +{ + PPROCESSINFO ppi = PsGetCurrentProcessWin32Process(); + + DPRINT("IdlePong ppi 0x%x\n",ppi); + if ( ppi && ppi->InputIdleEvent ) + { + KeClearEvent(ppi->InputIdleEvent); + } +} + static VOID FASTCALL IntCallWndProc( PWND Window, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { @@ -839,7 +887,7 @@ BOOL ProcessHardwareMessage(MSG* Msg, BOOLEAN RemoveMessages) * Internal version of PeekMessage() doing all the work */ BOOL FASTCALL -co_IntPeekMessage( PUSER_MESSAGE Msg, +co_IntPeekMessage( PMSG Msg, PWND Window, UINT MsgFilterMin, UINT MsgFilterMax, @@ -848,7 +896,6 @@ co_IntPeekMessage( PUSER_MESSAGE Msg, PTHREADINFO pti; LARGE_INTEGER LargeTickCount; PUSER_MESSAGE_QUEUE ThreadQueue; - PUSER_MESSAGE Message; BOOL RemoveMessages; pti = PsGetCurrentThreadWin32Thread(); @@ -856,6 +903,8 @@ co_IntPeekMessage( PUSER_MESSAGE Msg, RemoveMessages = RemoveMsg & PM_REMOVE; + IdlePong(); + do { KeQueryTickCount(&LargeTickCount); @@ -870,10 +919,10 @@ co_IntPeekMessage( PUSER_MESSAGE Msg, { /* According to the PSDK, WM_QUIT messages are always returned, regardless of the filter specified */ - Msg->Msg.hwnd = NULL; - Msg->Msg.message = WM_QUIT; - Msg->Msg.wParam = ThreadQueue->QuitExitCode; - Msg->Msg.lParam = 0; + Msg->hwnd = NULL; + Msg->message = WM_QUIT; + Msg->wParam = ThreadQueue->QuitExitCode; + Msg->lParam = 0; if (RemoveMessages) { ThreadQueue->QuitPosted = FALSE; @@ -889,14 +938,9 @@ co_IntPeekMessage( PUSER_MESSAGE Msg, Window, MsgFilterMin, MsgFilterMax, - &Message )) + Msg )) { - RtlCopyMemory(Msg, Message, sizeof(USER_MESSAGE)); - if (RemoveMessages) - { - MsqDestroyMessage(Message); - } - break; + return TRUE; } /* Check for hardware events. */ @@ -906,18 +950,13 @@ co_IntPeekMessage( PUSER_MESSAGE Msg, Window, MsgFilterMin, MsgFilterMax, - &Message )) + Msg )) { - RtlCopyMemory(Msg, Message, sizeof(USER_MESSAGE)); - if (RemoveMessages) - { - MsqDestroyMessage(Message); - } - if(!ProcessHardwareMessage(&Msg->Msg, RemoveMessages)) + if(!ProcessHardwareMessage(Msg, RemoveMessages)) continue; - break; + return TRUE; } /* Check for sent messages again. */ @@ -929,10 +968,10 @@ co_IntPeekMessage( PUSER_MESSAGE Msg, MsgFilterMin, MsgFilterMax, pti, - &Msg->Msg, + Msg, RemoveMessages)) { - break; + return TRUE; } if (PostTimerMessages(Window)) @@ -944,10 +983,6 @@ co_IntPeekMessage( PUSER_MESSAGE Msg, } while (TRUE); - // The WH_GETMESSAGE hook enables an application to monitor messages about to - // be returned by the GetMessage or PeekMessage function. - - co_HOOK_CallHooks( WH_GETMESSAGE, HC_ACTION, RemoveMsg & PM_REMOVE, (LPARAM)&Msg->Msg); return TRUE; } @@ -1053,7 +1088,7 @@ co_IntWaitMessage( PWND Window, PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue; NTSTATUS Status = STATUS_SUCCESS; - USER_MESSAGE Msg; + MSG Msg; pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; @@ -1068,6 +1103,7 @@ co_IntWaitMessage( PWND Window, { return TRUE; } + /* Nothing found. Wait for new messages. */ Status = co_MsqWaitForNewMessages( ThreadQueue, Window, @@ -1094,9 +1130,8 @@ co_IntGetPeekMessage( PMSG pMsg, UINT RemoveMsg, BOOL bGMSG ) { - BOOL Present; PWND Window; - USER_MESSAGE Msg; + BOOL Present = FALSE; if ( hWnd == HWND_TOPMOST || hWnd == HWND_BROADCAST ) hWnd = HWND_BOTTOM; @@ -1125,40 +1160,45 @@ co_IntGetPeekMessage( PMSG pMsg, do { - Present = co_IntPeekMessage( &Msg, + Present = co_IntPeekMessage( pMsg, Window, MsgFilterMin, MsgFilterMax, RemoveMsg ); if (Present) { - RtlCopyMemory( pMsg, &Msg.Msg, sizeof(MSG)); + // The WH_GETMESSAGE hook enables an application to monitor messages about to + // be returned by the GetMessage or PeekMessage function. - if (bGMSG) - return (WM_QUIT != pMsg->message); - else - return TRUE; + co_HOOK_CallHooks( WH_GETMESSAGE, HC_ACTION, RemoveMsg & PM_REMOVE, (LPARAM)pMsg); + + if ( bGMSG ) + return (WM_QUIT != pMsg->message); } - if ( bGMSG && !co_IntWaitMessage(Window, MsgFilterMin, MsgFilterMax) ) + if ( bGMSG ) { - return -1; + if ( !co_IntWaitMessage(Window, MsgFilterMin, MsgFilterMax) ) + return -1; } else { - if (!(RemoveMsg & PM_NOYIELD)) - { - // Yield this thread! - UserLeave(); - ZwYieldExecution(); - UserEnterExclusive(); - // Fall through to fail. - } + if (!(RemoveMsg & PM_NOYIELD)) + { + IdlePing(); + // Yield this thread! + UserLeave(); + ZwYieldExecution(); + UserEnterExclusive(); + // Fall through to exit. + IdlePong(); + } + break; } } while( bGMSG && !Present ); - return FALSE; + return Present; } BOOL FASTCALL @@ -1868,9 +1908,6 @@ IntGetQueueStatus(BOOL ClearChanges) PTHREADINFO pti; PUSER_MESSAGE_QUEUE Queue; DWORD Result; - DECLARE_RETURN(DWORD); - - DPRINT("Enter IntGetQueueStatus\n"); pti = PsGetCurrentThreadWin32Thread(); Queue = pti->MessageQueue; @@ -1881,19 +1918,17 @@ IntGetQueueStatus(BOOL ClearChanges) Queue->ChangedBits = 0; } - RETURN(Result); - -CLEANUP: - DPRINT("Leave IntGetQueueStatus, ret=%i\n",_ret_); - END_CLEANUP; + return Result; } BOOL APIENTRY IntInitMessagePumpHook() { - if (((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti) + PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); + + if (pti->pcti) { - ((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti->dwcPumpHook++; + pti->pcti->dwcPumpHook++; return TRUE; } return FALSE; @@ -1902,13 +1937,15 @@ IntInitMessagePumpHook() BOOL APIENTRY IntUninitMessagePumpHook() { - if (((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti) + PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); + + if (pti->pcti) { - if (((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti->dwcPumpHook <= 0) + if (pti->pcti->dwcPumpHook <= 0) { return FALSE; } - ((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti->dwcPumpHook--; + pti->pcti->dwcPumpHook--; return TRUE; } return FALSE; @@ -1922,17 +1959,15 @@ NtUserPostMessage(HWND hWnd, WPARAM wParam, LPARAM lParam) { - DECLARE_RETURN(BOOL); + BOOL ret; - DPRINT("Enter NtUserPostMessage\n"); UserEnterExclusive(); - RETURN( UserPostMessage(hWnd, Msg, wParam, lParam)); + ret = UserPostMessage(hWnd, Msg, wParam, lParam); -CLEANUP: - DPRINT("Leave NtUserPostMessage, ret=%i\n",_ret_); UserLeave(); - END_CLEANUP; + + return ret; } BOOL APIENTRY @@ -1941,20 +1976,15 @@ NtUserPostThreadMessage(DWORD idThread, WPARAM wParam, LPARAM lParam) { - DECLARE_RETURN(BOOL); + BOOL ret; - DPRINT("Enter NtUserPostThreadMessage\n"); UserEnterExclusive(); - RETURN( UserPostThreadMessage( idThread, - Msg, - wParam, - lParam)); + ret = UserPostThreadMessage( idThread, Msg, wParam, lParam); -CLEANUP: - DPRINT("Leave NtUserPostThreadMessage, ret=%i\n",_ret_); UserLeave(); - END_CLEANUP; + + return ret; } DWORD APIENTRY @@ -1979,31 +2009,34 @@ NtUserSendMessageTimeout( HWND hWnd, { DOSENDMESSAGE dsm; LRESULT Result; - DECLARE_RETURN(BOOL); DPRINT("Enter NtUserSendMessageTimeout\n"); - UserEnterExclusive(); dsm.uFlags = uFlags; dsm.uTimeout = uTimeout; + + UserEnterExclusive(); + Result = co_IntDoSendMessage(hWnd, Msg, wParam, lParam, &dsm, UnsafeInfo); + + UserLeave(); + if(uResult != NULL && Result != 0) { - NTSTATUS Status; - - Status = MmCopyToCaller(uResult, &dsm.Result, sizeof(ULONG_PTR)); - if(!NT_SUCCESS(Status)) + _SEH2_TRY { - SetLastWin32Error(ERROR_INVALID_PARAMETER); - RETURN( FALSE); + ProbeForWrite(uResult, sizeof(ULONG_PTR), 1); + RtlCopyMemory(uResult, &dsm.Result, sizeof(ULONG_PTR)); } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER);; + Result = FALSE; + } + _SEH2_END; } - RETURN( Result); -CLEANUP: - DPRINT("Leave NtUserSendMessageTimeout, ret=%i\n",_ret_); - UserLeave(); - END_CLEANUP; + return Result; } LRESULT APIENTRY @@ -2013,34 +2046,30 @@ NtUserSendMessage( HWND Wnd, LPARAM lParam, PNTUSERSENDMESSAGEINFO UnsafeInfo ) { - DECLARE_RETURN(BOOL); + BOOL ret; - DPRINT("Enter NtUserSendMessage\n"); UserEnterExclusive(); - RETURN(co_IntDoSendMessage(Wnd, Msg, wParam, lParam, NULL, UnsafeInfo)); + ret = co_IntDoSendMessage(Wnd, Msg, wParam, lParam, NULL, UnsafeInfo); -CLEANUP: - DPRINT("Leave NtUserSendMessage, ret=%i\n",_ret_); UserLeave(); - END_CLEANUP; + + return ret; } ////////// BOOL APIENTRY NtUserWaitMessage(VOID) { - DECLARE_RETURN(BOOL); + BOOL ret; - DPRINT("EnterNtUserWaitMessage\n"); UserEnterExclusive(); - RETURN(co_IntWaitMessage(NULL, 0, 0)); + ret = co_IntWaitMessage(NULL, 0, 0); -CLEANUP: - DPRINT("Leave NtUserWaitMessage, ret=%i\n",_ret_); UserLeave(); - END_CLEANUP; + + return ret; } @@ -2060,97 +2089,83 @@ NtUserGetMessage( PNTUSERGETMESSAGEINFO UnsafeInfo, * retrieved. */ { - BOOL GotMessage; NTUSERGETMESSAGEINFO Info; NTSTATUS Status; /* FIXME: if initialization is removed, gcc complains that this may be used before initialization. Please review */ - PWND Window = NULL; PMSGMEMORY MsgMemoryEntry; PVOID UserMem; - UINT Size; - USER_MESSAGE Msg; - DECLARE_RETURN(BOOL); - // USER_REFERENCE_ENTRY Ref; + ULONG Size; + MSG Msg; + BOOL GotMessage; + + if ( (MsgFilterMin|MsgFilterMax) & ~WM_MAXIMUM ) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return FALSE; + } - DPRINT("Enter NtUserGetMessage\n"); UserEnterExclusive(); - /* Validate input */ - if (hWnd && !(Window = UserGetWindowObject(hWnd))) - { - RETURN(-1); - } + RtlZeroMemory(&Msg, sizeof(MSG)); - // if (Window) UserRefObjectCo(Window, &Ref); + GotMessage = co_IntGetPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, PM_REMOVE, TRUE); - if (MsgFilterMax < MsgFilterMin) - { - MsgFilterMin = 0; - MsgFilterMax = 0; - } + UserLeave(); - do + Info.Msg = Msg; //.Msg; + /* See if this message type is present in the table */ + MsgMemoryEntry = FindMsgMemory(Info.Msg.message); + + _SEH2_TRY { - GotMessage = co_IntPeekMessage(&Msg, Window, MsgFilterMin, MsgFilterMax, PM_REMOVE); - if (GotMessage) + ProbeForWrite(UnsafeInfo, sizeof(NTUSERGETMESSAGEINFO), 1); + RtlCopyMemory(UnsafeInfo, &Info, sizeof(NTUSERGETMESSAGEINFO)); + + if (NULL == MsgMemoryEntry) { - Info.Msg = Msg.Msg; - /* See if this message type is present in the table */ - MsgMemoryEntry = FindMsgMemory(Info.Msg.message); - if (NULL == MsgMemoryEntry) - { - /* Not present, no copying needed */ - Info.LParamSize = 0; - } - else - { - /* Determine required size */ - Size = MsgMemorySize(MsgMemoryEntry, Info.Msg.wParam, - Info.Msg.lParam); - /* Allocate required amount of user-mode memory */ - Info.LParamSize = Size; - UserMem = NULL; - Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem, 0, - &Info.LParamSize, MEM_COMMIT, PAGE_READWRITE); + /* Not present, no copying needed */ + UnsafeInfo->LParamSize = 0; + } + else + { + /* Determine required size */ + Size = MsgMemorySize(MsgMemoryEntry, Info.Msg.wParam, Info.Msg.lParam); - if (! NT_SUCCESS(Status)) - { - SetLastNtError(Status); - RETURN( (BOOL) -1); - } - /* Transfer lParam data to user-mode mem */ - Status = MmCopyToCaller(UserMem, (PVOID) Info.Msg.lParam, Size); - if (! NT_SUCCESS(Status)) - { - ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID *) &UserMem, - &Info.LParamSize, MEM_DECOMMIT); - SetLastNtError(Status); - RETURN( (BOOL) -1); - } - Info.Msg.lParam = (LPARAM) UserMem; - } - Status = MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERGETMESSAGEINFO)); + /* Allocate required amount of user-mode memory */ + Status = ZwAllocateVirtualMemory(NtCurrentProcess(), + &UserMem, + 0, + &Size, + MEM_COMMIT, + PAGE_READWRITE); if (! NT_SUCCESS(Status)) { SetLastNtError(Status); - RETURN( (BOOL) -1); + _SEH2_YIELD(return (BOOL) -1); } - } - else if (! co_IntWaitMessage(Window, MsgFilterMin, MsgFilterMax)) - { - RETURN( (BOOL) -1); + + /* Transfer lParam data to user-mode mem */ + ProbeForWrite(UserMem, Size, 1); + RtlCopyMemory(UserMem, (PVOID)Info.Msg.lParam, Size); + + UnsafeInfo->LParamSize = Size; + UnsafeInfo->Msg.lParam = (LPARAM) UserMem; } } - while (! GotMessage); + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastNtError(_SEH2_GetExceptionCode()); - RETURN( WM_QUIT != Info.Msg.message); + if(UserMem != NULL) + { + ZwFreeVirtualMemory(NtCurrentProcess(), &UserMem, &Size, MEM_RELEASE); + } -CLEANUP: - // if (Window) UserDerefObjectCo(Window); - - DPRINT("Leave NtUserGetMessage\n"); - UserLeave(); - END_CLEANUP; + _SEH2_YIELD(return (BOOL) -1); + } + _SEH2_END; + + return GotMessage; } @@ -2161,22 +2176,22 @@ NtUserGetMessageX(PMSG pMsg, UINT MsgFilterMax) { MSG Msg; - BOOL Ret = FALSE; - DECLARE_RETURN(BOOL); - - DPRINT("Enter NtUserGetMessage\n"); - UserEnterExclusive(); + BOOL Ret; if ( (MsgFilterMin|MsgFilterMax) & ~WM_MAXIMUM ) { SetLastWin32Error(ERROR_INVALID_PARAMETER); - RETURN( Ret); + return FALSE; } + UserEnterExclusive(); + RtlZeroMemory(&Msg, sizeof(MSG)); Ret = co_IntGetPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, PM_REMOVE, TRUE); + UserLeave(); + if (Ret) { _SEH2_TRY @@ -2191,12 +2206,8 @@ NtUserGetMessageX(PMSG pMsg, } _SEH2_END; } - RETURN( Ret); -CLEANUP: - DPRINT("Leave NtUserGetMessage\n"); - UserLeave(); - END_CLEANUP; + return Ret; } BOOL APIENTRY @@ -2207,92 +2218,83 @@ NtUserPeekMessage(PNTUSERGETMESSAGEINFO UnsafeInfo, UINT RemoveMsg) { NTSTATUS Status; - BOOL Present; NTUSERGETMESSAGEINFO Info; - PWND Window; PMSGMEMORY MsgMemoryEntry; - PVOID UserMem; - UINT Size; - USER_MESSAGE Msg; - DECLARE_RETURN(BOOL); + PVOID UserMem = NULL; + ULONG Size; + MSG Msg; + BOOL Ret; + + if ( RemoveMsg & PM_BADMSGFLAGS ) + { + SetLastWin32Error(ERROR_INVALID_FLAGS); + return FALSE; + } - DPRINT("Enter NtUserPeekMessage\n"); UserEnterExclusive(); - if (hWnd == (HWND)-1 || hWnd == (HWND)0x0000FFFF || hWnd == (HWND)0xFFFFFFFF) - hWnd = (HWND)1; + RtlZeroMemory(&Msg, sizeof(MSG)); - /* Validate input */ - if (hWnd && hWnd != (HWND)1) - { - if (!(Window = UserGetWindowObject(hWnd))) - { - RETURN(-1); - } - } - else - { - Window = (PWND)hWnd; - } + Ret = co_IntGetPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, RemoveMsg, FALSE); - if (MsgFilterMax < MsgFilterMin) - { - MsgFilterMin = 0; - MsgFilterMax = 0; - } + UserLeave(); - Present = co_IntPeekMessage(&Msg, Window, MsgFilterMin, MsgFilterMax, RemoveMsg); - if (Present) + if (Ret) { - - Info.Msg = Msg.Msg; + Info.Msg = Msg; /* See if this message type is present in the table */ MsgMemoryEntry = FindMsgMemory(Info.Msg.message); - if (NULL == MsgMemoryEntry) + + _SEH2_TRY { - /* Not present, no copying needed */ - Info.LParamSize = 0; - } - else - { - /* Determine required size */ - Size = MsgMemorySize(MsgMemoryEntry, Info.Msg.wParam, - Info.Msg.lParam); - /* Allocate required amount of user-mode memory */ - Info.LParamSize = Size; - UserMem = NULL; - Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem, 0, - &Info.LParamSize, MEM_COMMIT, PAGE_READWRITE); - if (! NT_SUCCESS(Status)) + ProbeForWrite(UnsafeInfo, sizeof(NTUSERGETMESSAGEINFO), 1); + RtlCopyMemory(UnsafeInfo, &Info, sizeof(NTUSERGETMESSAGEINFO)); + + if (NULL == MsgMemoryEntry) { - SetLastNtError(Status); - RETURN( (BOOL) -1); + /* Not present, no copying needed */ + UnsafeInfo->LParamSize = 0; } - /* Transfer lParam data to user-mode mem */ - Status = MmCopyToCaller(UserMem, (PVOID) Info.Msg.lParam, Size); - if (! NT_SUCCESS(Status)) + else { - ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID *) &UserMem, - &Info.LParamSize, MEM_RELEASE); - SetLastNtError(Status); - RETURN( (BOOL) -1); + /* Determine required size */ + Size = MsgMemorySize(MsgMemoryEntry, Info.Msg.wParam, Info.Msg.lParam); + + /* Allocate required amount of user-mode memory */ + Status = ZwAllocateVirtualMemory(NtCurrentProcess(), + &UserMem, + 0, + &Size, + MEM_COMMIT, + PAGE_READWRITE); + if (! NT_SUCCESS(Status)) + { + SetLastNtError(Status); + _SEH2_YIELD(return (BOOL) -1); + } + + /* Transfer lParam data to user-mode mem */ + ProbeForWrite(UserMem, Size, 1); + RtlCopyMemory(UserMem, (PVOID)Info.Msg.lParam, Size); + + UnsafeInfo->LParamSize = Size; + UnsafeInfo->Msg.lParam = (LPARAM) UserMem; } - Info.Msg.lParam = (LPARAM) UserMem; } - Status = MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERGETMESSAGEINFO)); - if (! NT_SUCCESS(Status)) + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - SetLastNtError(Status); - RETURN( (BOOL) -1); + SetLastNtError(_SEH2_GetExceptionCode()); + Ret = (BOOL) -1; + + if(UserMem != NULL) + { + ZwFreeVirtualMemory(NtCurrentProcess(), &UserMem, &Size, MEM_RELEASE); + } } + _SEH2_END; } - RETURN( Present); - -CLEANUP: - DPRINT("Leave NtUserPeekMessage, ret=%i\n",_ret_); - UserLeave(); - END_CLEANUP; + return Ret; } BOOL APIENTRY @@ -2303,22 +2305,22 @@ NtUserPeekMessageX( PMSG pMsg, UINT RemoveMsg) { MSG Msg; - BOOL Ret = FALSE; - DECLARE_RETURN(BOOL); - - DPRINT("Enter NtUserPeekMessage\n"); - UserEnterExclusive(); + BOOL Ret; if ( RemoveMsg & PM_BADMSGFLAGS ) { SetLastWin32Error(ERROR_INVALID_FLAGS); - RETURN( Ret); + return FALSE; } + UserEnterExclusive(); + RtlZeroMemory(&Msg, sizeof(MSG)); Ret = co_IntGetPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, RemoveMsg, FALSE); + UserLeave(); + if (Ret) { _SEH2_TRY @@ -2333,40 +2335,28 @@ NtUserPeekMessageX( PMSG pMsg, } _SEH2_END; } - RETURN( Ret); - -CLEANUP: - DPRINT("Leave NtUserPeekMessage, ret=%i\n",_ret_); - UserLeave(); - END_CLEANUP; + + return Ret; } BOOL APIENTRY NtUserCallMsgFilter( LPMSG lpmsg, INT code) { - BOOL BadChk = FALSE, Ret = FALSE; + BOOL Ret = FALSE; MSG Msg; - DECLARE_RETURN(BOOL); - DPRINT("Enter NtUserCallMsgFilter\n"); - UserEnterExclusive(); - if (lpmsg) + _SEH2_TRY { - _SEH2_TRY - { - ProbeForRead(lpmsg, sizeof(MSG), 1); - RtlCopyMemory( &Msg, lpmsg, sizeof(MSG)); - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - BadChk = TRUE; - } - _SEH2_END; + ProbeForRead(lpmsg, sizeof(MSG), 1); + RtlCopyMemory( &Msg, lpmsg, sizeof(MSG)); } - else - RETURN( FALSE); + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + _SEH2_YIELD(return FALSE); + } + _SEH2_END; - if (BadChk) RETURN( FALSE); + UserEnterExclusive(); if ( co_HOOK_CallHooks( WH_SYSMSGFILTER, code, 0, (LPARAM)&Msg)) { @@ -2377,6 +2367,8 @@ NtUserCallMsgFilter( LPMSG lpmsg, INT code) Ret = co_HOOK_CallHooks( WH_MSGFILTER, code, 0, (LPARAM)&Msg); } + UserLeave(); + _SEH2_TRY { ProbeForWrite(lpmsg, sizeof(MSG), 1); @@ -2384,26 +2376,19 @@ NtUserCallMsgFilter( LPMSG lpmsg, INT code) } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - BadChk = TRUE; + Ret = FALSE; } _SEH2_END; - if (BadChk) RETURN( FALSE); - RETURN( Ret) -CLEANUP: - DPRINT("Leave NtUserCallMsgFilter. ret=%i\n", _ret_); - UserLeave(); - END_CLEANUP; + return Ret; } LRESULT APIENTRY NtUserDispatchMessage(PMSG UnsafeMsgInfo) { LRESULT Res = 0; - BOOL Hit = FALSE; MSG SafeMsg; - UserEnterExclusive(); _SEH2_TRY { ProbeForRead(UnsafeMsgInfo, sizeof(MSG), 1); @@ -2412,11 +2397,13 @@ NtUserDispatchMessage(PMSG UnsafeMsgInfo) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { SetLastNtError(_SEH2_GetExceptionCode()); - Hit = TRUE; + _SEH2_YIELD(return FALSE); } _SEH2_END; - if (!Hit) Res = IntDispatchMessage(&SafeMsg); + UserEnterExclusive(); + + Res = IntDispatchMessage(&SafeMsg); UserLeave(); return Res; @@ -2426,26 +2413,28 @@ NtUserDispatchMessage(PMSG UnsafeMsgInfo) BOOL APIENTRY NtUserTranslateMessage(LPMSG lpMsg, UINT flags) { - NTSTATUS Status; MSG SafeMsg; - DECLARE_RETURN(BOOL); + BOOL Ret; + + _SEH2_TRY + { + ProbeForRead(lpMsg, sizeof(MSG), 1); + RtlCopyMemory(&SafeMsg, lpMsg, sizeof(MSG)); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastNtError(_SEH2_GetExceptionCode()); + _SEH2_YIELD(return FALSE); + } + _SEH2_END; - DPRINT("Enter NtUserTranslateMessage\n"); UserEnterExclusive(); - Status = MmCopyFromCaller(&SafeMsg, lpMsg, sizeof(MSG)); - if(!NT_SUCCESS(Status)) - { - SetLastNtError(Status); - RETURN( FALSE); - } + Ret = IntTranslateKbdMessage(&SafeMsg, flags); - RETURN( IntTranslateKbdMessage(&SafeMsg, flags)); - -CLEANUP: - DPRINT("Leave NtUserTranslateMessage: ret=%i\n",_ret_); UserLeave(); - END_CLEANUP; + + return Ret; } BOOL APIENTRY @@ -2459,7 +2448,6 @@ NtUserMessageCall( HWND hWnd, { LRESULT lResult = 0; BOOL Ret = FALSE; - BOOL BadChk = FALSE; PWND Window = NULL; USER_REFERENCE_ENTRY Ref; @@ -2501,10 +2489,10 @@ NtUserMessageCall( HWND hWnd, } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - BadChk = TRUE; + Ret = FALSE; + _SEH2_YIELD(break); } _SEH2_END; - if (BadChk) break; } else break; @@ -2531,7 +2519,7 @@ NtUserMessageCall( HWND hWnd, { co_IntSendMessageTimeout( HWND_BROADCAST, Msg, - wParam, + wParam, lParam, SMTO_NOTIMEOUTIFNOTHUNG, 2000, @@ -2657,7 +2645,7 @@ NtUserMessageCall( HWND hWnd, } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - BadChk = TRUE; + Ret = FALSE; } _SEH2_END; } @@ -2668,7 +2656,7 @@ NtUserMessageCall( HWND hWnd, UserLeave(); - return BadChk ? FALSE : Ret; + return Ret; } #define INFINITE 0xFFFFFFFF @@ -2682,10 +2670,10 @@ NtUserWaitForInputIdle( IN HANDLE hProcess, { PEPROCESS Process; PPROCESSINFO W32Process; + PTHREADINFO pti; NTSTATUS Status; - HANDLE Handles[2]; + HANDLE Handles[3]; LARGE_INTEGER Timeout; - ULONGLONG StartTime, Run, Elapsed = 0; UserEnterExclusive(); @@ -2703,8 +2691,13 @@ NtUserWaitForInputIdle( IN HANDLE hProcess, return WAIT_FAILED; } + pti = PsGetCurrentThreadWin32Thread(); + W32Process = (PPROCESSINFO)Process->Win32Process; - if (!W32Process) + + if ( PsGetProcessExitProcessCalled(Process) || + !W32Process || + pti->ppi == W32Process) { ObDereferenceObject(Process); UserLeave(); @@ -2712,10 +2705,9 @@ NtUserWaitForInputIdle( IN HANDLE hProcess, return WAIT_FAILED; } - EngCreateEvent((PEVENT *)&W32Process->InputIdleEvent); - Handles[0] = Process; Handles[1] = W32Process->InputIdleEvent; + Handles[2] = pti->MessageQueue->NewMessages; // pEventQueueServer; IntMsqSetWakeMask returns hEventQueueClient if (!Handles[1]) { @@ -2724,16 +2716,15 @@ NtUserWaitForInputIdle( IN HANDLE hProcess, return STATUS_SUCCESS; /* no event to wait on */ } - StartTime = EngGetTickCount(); - - Run = dwMilliseconds; + if (dwMilliseconds != INFINITE) + Timeout.QuadPart = (LONGLONG) dwMilliseconds * (LONGLONG) -10000; + DPRINT("WFII: ppi 0x%x\n",W32Process); DPRINT("WFII: waiting for %p\n", Handles[1] ); do { - Timeout.QuadPart = Run - Elapsed; UserLeave(); - Status = KeWaitForMultipleObjects( 2, + Status = KeWaitForMultipleObjects( 3, Handles, WaitAny, UserRequest, @@ -2753,21 +2744,19 @@ NtUserWaitForInputIdle( IN HANDLE hProcess, switch (Status) { case STATUS_WAIT_0: - Status = WAIT_FAILED; goto WaitExit; case STATUS_WAIT_2: { - USER_MESSAGE Msg; - co_IntPeekMessage( &Msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE ); - break; + MSG Msg; + co_IntPeekMessage( &Msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE ); + DPRINT1("WFII: WAIT 2\n"); } + break; - case STATUS_USER_APC: - case STATUS_ALERTED: case STATUS_TIMEOUT: DPRINT1("WFII: timeout\n"); - Status = STATUS_TIMEOUT; + case WAIT_FAILED: goto WaitExit; default: @@ -2775,24 +2764,10 @@ NtUserWaitForInputIdle( IN HANDLE hProcess, Status = STATUS_SUCCESS; goto WaitExit; } - - if (dwMilliseconds != INFINITE) - { - Elapsed = EngGetTickCount() - StartTime; - - if (Elapsed > Run) - Status = STATUS_TIMEOUT; - break; - } } - while (1); + while (TRUE); WaitExit: - if (W32Process->InputIdleEvent) - { - EngFreeMem((PVOID)W32Process->InputIdleEvent); - W32Process->InputIdleEvent = NULL; - } ObDereferenceObject(Process); UserLeave(); return Status; diff --git a/subsystems/win32/win32k/ntuser/monitor.c b/subsystems/win32/win32k/ntuser/monitor.c index e35d36aece1..b766e951da9 100644 --- a/subsystems/win32/win32k/ntuser/monitor.c +++ b/subsystems/win32/win32k/ntuser/monitor.c @@ -28,7 +28,9 @@ static PMONITOR gMonitorList = NULL; /* INITALIZATION FUNCTIONS ****************************************************/ +INIT_FUNCTION NTSTATUS +NTAPI InitMonitorImpl() { DPRINT("Initializing monitor implementation...\n"); diff --git a/subsystems/win32/win32k/ntuser/msgqueue.c b/subsystems/win32/win32k/ntuser/msgqueue.c index 0f102a1c51d..77d809658d7 100644 --- a/subsystems/win32/win32k/ntuser/msgqueue.c +++ b/subsystems/win32/win32k/ntuser/msgqueue.c @@ -62,32 +62,6 @@ static PAGED_LOOKASIDE_LIST MessageLookasideList; /* FUNCTIONS *****************************************************************/ -// -// Wakeup any thread/process waiting on idle input. -// -static VOID FASTCALL -IdlePing(VOID) -{ - HWND hWnd; - PWND Window; - PPROCESSINFO W32d = PsGetCurrentProcessWin32Process(); - - hWnd = UserGetForegroundWindow(); - - Window = UserGetWindowObject(hWnd); - - if (Window && Window->head.pti) - { - if (Window->head.pti->fsHooks & HOOKID_TO_FLAG(WH_FOREGROUNDIDLE)) - { - co_HOOK_CallHooks(WH_FOREGROUNDIDLE,HC_ACTION,0,0); - } - } - - if (W32d && W32d->InputIdleEvent) - KePulseEvent( W32d->InputIdleEvent, EVENT_INCREMENT, TRUE); -} - HANDLE FASTCALL IntMsqSetWakeMask(DWORD WakeMask) { @@ -140,7 +114,9 @@ MsqDecPaintCountQueue(PUSER_MESSAGE_QUEUE Queue) } -NTSTATUS FASTCALL +INIT_FUNCTION +NTSTATUS +NTAPI MsqInitializeImpl(VOID) { /*CurrentFocusMessageQueue = NULL;*/ @@ -161,7 +137,7 @@ MsqInitializeImpl(VOID) } VOID FASTCALL -MsqInsertSystemMessage(MSG* Msg) +MsqInsertMouseMessage(MSG* Msg) { LARGE_INTEGER LargeTickCount; KIRQL OldIrql; @@ -559,7 +535,7 @@ co_MsqTranslateMouseMessage(PUSER_MESSAGE_QUEUE MessageQueue, PWND Window, UINT BOOL APIENTRY co_MsqPeekHardwareMessage(PUSER_MESSAGE_QUEUE MessageQueue, PWND Window, UINT FilterLow, UINT FilterHigh, BOOL Remove, - PUSER_MESSAGE* Message) + PMSG Message) { KIRQL OldIrql; POINT ScreenPoint; @@ -576,8 +552,6 @@ co_MsqPeekHardwareMessage(PUSER_MESSAGE_QUEUE MessageQueue, PWND Window, WaitObjects[0] = &HardwareMessageQueueLock; do { - IdlePing(); - UserLeaveCo(); WaitStatus = KeWaitForMultipleObjects(2, WaitObjects, WaitAny, UserRequest, @@ -613,14 +587,15 @@ co_MsqPeekHardwareMessage(PUSER_MESSAGE_QUEUE MessageQueue, PWND Window, DesktopWindow, &ScreenPoint, FALSE, &CurrentEntry); if (Accept) { + *Message = Current->Msg; if (Remove) { RemoveEntryList(&Current->ListEntry); + MsqDestroyMessage(Current); } IntUnLockHardwareMessageQueue(MessageQueue); IntUnLockSystemHardwareMessageQueueLock(FALSE); - *Message = Current; - + if (Desk) Desk->LastInputWasKbd = FALSE; @@ -630,13 +605,14 @@ co_MsqPeekHardwareMessage(PUSER_MESSAGE_QUEUE MessageQueue, PWND Window, } else { + *Message = Current->Msg; if (Remove) { RemoveEntryList(&Current->ListEntry); + MsqDestroyMessage(Current); } IntUnLockHardwareMessageQueue(MessageQueue); IntUnLockSystemHardwareMessageQueueLock(FALSE); - *Message = Current; RETURN(TRUE); } @@ -719,7 +695,12 @@ co_MsqPeekHardwareMessage(PUSER_MESSAGE_QUEUE MessageQueue, PWND Window, IntUnLockHardwareMessageQueue(MessageQueue); } IntUnLockSystemHardwareMessageQueueLock(FALSE); - *Message = Current; + *Message = Current->Msg; + + if (Remove) + { + MsqDestroyMessage(Current); + } RETURN(TRUE); } @@ -1183,8 +1164,6 @@ co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue, if(Block) { - IdlePing(); - UserLeaveCo(); /* don't process messages sent to the thread */ @@ -1246,8 +1225,6 @@ co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue, WaitObjects[1] = ThreadQueue->NewMessages; do { - IdlePing(); - UserLeaveCo(); WaitStatus = KeWaitForMultipleObjects(2, WaitObjects, WaitAny, UserRequest, @@ -1355,7 +1332,7 @@ co_MsqFindMessage(IN PUSER_MESSAGE_QUEUE MessageQueue, IN PWND Window, IN UINT MsgFilterLow, IN UINT MsgFilterHigh, - OUT PUSER_MESSAGE* Message) + OUT PMSG Message) { PLIST_ENTRY CurrentEntry; PUSER_MESSAGE CurrentMessage; @@ -1389,7 +1366,13 @@ co_MsqFindMessage(IN PUSER_MESSAGE_QUEUE MessageQueue, RemoveEntryList(&CurrentMessage->ListEntry); } - *Message = CurrentMessage; + *Message= CurrentMessage->Msg; + + if (Remove) + { + MsqDestroyMessage(CurrentMessage); + } + return(TRUE); } CurrentEntry = CurrentEntry->Flink; @@ -1405,8 +1388,6 @@ co_MsqWaitForNewMessages(PUSER_MESSAGE_QUEUE MessageQueue, PWND WndFilter, PVOID WaitObjects[2] = {MessageQueue->NewMessages, &HardwareMessageEvent}; NTSTATUS ret; - IdlePing(); // Going to wait so send Idle ping. - UserLeaveCo(); ret = KeWaitForMultipleObjects(2, diff --git a/subsystems/win32/win32k/ntuser/ntuser.c b/subsystems/win32/win32k/ntuser/ntuser.c index 1ca06aba1cc..d28aa33e2e6 100644 --- a/subsystems/win32/win32k/ntuser/ntuser.c +++ b/subsystems/win32/win32k/ntuser/ntuser.c @@ -53,8 +53,10 @@ InitUserAtoms(VOID) /* FUNCTIONS *****************************************************************/ - -NTSTATUS FASTCALL InitUserImpl(VOID) +INIT_FUNCTION +NTSTATUS +NTAPI +InitUserImpl(VOID) { NTSTATUS Status; @@ -80,8 +82,9 @@ NTSTATUS FASTCALL InitUserImpl(VOID) return STATUS_SUCCESS; } -BOOL -InitVideo(ULONG); +NTSTATUS +NTAPI +InitVideo(); NTSTATUS NTAPI @@ -89,11 +92,16 @@ UserInitialize( HANDLE hPowerRequestEvent, HANDLE hMediaRequestEvent) { + NTSTATUS Status; + // Set W32PF_Flags |= (W32PF_READSCREENACCESSGRANTED | W32PF_IOWINSTA) // Create Object Directory,,, Looks like create workstation. "\\Windows\\WindowStations" // Create Event for Diconnect Desktop. - InitVideo(0); -// Initialize Video. + + /* Initialize Video. */ + Status = InitVideo(); + if (!NT_SUCCESS(Status)) return Status; + // { // DrvInitConsole. // DrvChangeDisplaySettings. diff --git a/subsystems/win32/win32k/ntuser/timer.c b/subsystems/win32/win32k/ntuser/timer.c index f9d83d6f27f..b3a7fbde3bc 100644 --- a/subsystems/win32/win32k/ntuser/timer.c +++ b/subsystems/win32/win32k/ntuser/timer.c @@ -527,7 +527,9 @@ IntKillTimer(PWND Window, UINT_PTR IDEvent, BOOL SystemTimer) return pTmr ? TRUE : FALSE; } -NTSTATUS FASTCALL +INIT_FUNCTION +NTSTATUS +NTAPI InitTimerImpl(VOID) { ULONG BitmapBytes; diff --git a/subsystems/win32/win32k/ntuser/window.c b/subsystems/win32/win32k/ntuser/window.c index f6e588fa1d8..046515ce454 100644 --- a/subsystems/win32/win32k/ntuser/window.c +++ b/subsystems/win32/win32k/ntuser/window.c @@ -29,7 +29,9 @@ * Initialize windowing implementation. */ -NTSTATUS FASTCALL +INIT_FUNCTION +NTSTATUS +NTAPI InitWindowImpl(VOID) { return STATUS_SUCCESS; @@ -400,8 +402,6 @@ static LRESULT co_UserFreeWindow(PWND Window, DestroyTimersForWindow(ThreadData, Window); - HOOK_DestroyThreadHooks(ThreadData->pEThread); // This is needed here too! - /* flush the message queue */ MsqRemoveWindowMessagesFromQueue(Window); @@ -1908,9 +1908,9 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, LRESULT Result; USER_REFERENCE_ENTRY ParentRef, Ref; PTHREADINFO pti; - ANSI_STRING asClassName; DWORD dwShowMode = SW_SHOW; CREATESTRUCTW *pCsw; + PVOID pszClass = NULL, pszName = NULL; DECLARE_RETURN(PWND); /* Get the current window station and reference it */ @@ -1925,7 +1925,6 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, pCsw = NULL; pCbtCreate = NULL; - RtlInitAnsiString(&asClassName, NULL); /* Get the class and reference it*/ Class = IntGetAndReferenceClass(ClassName, Cs->hInstance); @@ -2006,17 +2005,58 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, pCsw->dwExStyle = Cs->dwExStyle; dwStyle = Cs->style; // Save it anyway. pCsw->style = Window->style; /* HCBT_CREATEWND needs the real window style */ + pCsw->lpszName = Cs->lpszName; + pCsw->lpszClass = Cs->lpszClass; - pCsw->lpszName = (LPCWSTR) WindowName->Buffer; - pCsw->lpszClass = (LPCWSTR) ClassName->Buffer; - - if (Window->state & WNDS_ANSICREATOR) + // Based on the assumption this is from "unicode source" user32, ReactOS, answer is yes. + if (!IS_ATOM(ClassName->Buffer)) { - if (!IS_ATOM(ClassName->Buffer)) + if (Window->state & WNDS_ANSICREATOR) { - RtlUnicodeStringToAnsiString(&asClassName, ClassName, TRUE); - pCsw->lpszClass = (LPCWSTR) asClassName.Buffer; + ANSI_STRING AnsiString; + AnsiString.MaximumLength = RtlUnicodeStringToAnsiSize(ClassName)+sizeof(CHAR); + pszClass = UserHeapAlloc(AnsiString.MaximumLength); + RtlZeroMemory(pszClass, AnsiString.MaximumLength); + AnsiString.Buffer = (PCHAR)pszClass; + RtlUnicodeStringToAnsiString(&AnsiString, ClassName, FALSE); } + else + { + UNICODE_STRING UnicodeString; + UnicodeString.MaximumLength = ClassName->Length + sizeof(UNICODE_NULL); + pszClass = UserHeapAlloc(UnicodeString.MaximumLength); + RtlZeroMemory(pszClass, UnicodeString.MaximumLength); + UnicodeString.Buffer = (PWSTR)pszClass; + RtlCopyUnicodeString(&UnicodeString, ClassName); + } + if (pszClass) pCsw->lpszClass = UserHeapAddressToUser(pszClass); + } + if (WindowName->Length) + { + UNICODE_STRING Name; + Name.Buffer = WindowName->Buffer; + Name.Length = WindowName->Length; + Name.MaximumLength = WindowName->MaximumLength; + + if (Window->state & WNDS_ANSICREATOR) + { + ANSI_STRING AnsiString; + AnsiString.MaximumLength = RtlUnicodeStringToAnsiSize(&Name)+sizeof(CHAR); + pszName = UserHeapAlloc(AnsiString.MaximumLength); + RtlZeroMemory(pszName, AnsiString.MaximumLength); + AnsiString.Buffer = (PCHAR)pszName; + RtlUnicodeStringToAnsiString(&AnsiString, &Name, FALSE); + } + else + { + UNICODE_STRING UnicodeString; + UnicodeString.MaximumLength = Name.Length + sizeof(UNICODE_NULL); + pszName = UserHeapAlloc(UnicodeString.MaximumLength); + RtlZeroMemory(pszName, UnicodeString.MaximumLength); + UnicodeString.Buffer = (PWSTR)pszName; + RtlCopyUnicodeString(&UnicodeString, &Name); + } + if (pszName) pCsw->lpszName = UserHeapAddressToUser(pszName); } pCbtCreate->lpcs = pCsw; @@ -2035,7 +2075,10 @@ co_UserCreateWindowEx(CREATESTRUCTW* Cs, Cs->y = pCsw->y; hwndInsertAfter = pCbtCreate->hwndInsertAfter; - Cs->style = dwStyle; /* NCCREATE and WM_NCCALCSIZE need the original values*/ + /* NCCREATE and WM_NCCALCSIZE need the original values */ + Cs->style = dwStyle; + Cs->lpszName = (LPCWSTR) WindowName; + Cs->lpszClass = (LPCWSTR) ClassName; /* Send the WM_GETMINMAXINFO message*/ Size.cx = Cs->cx; @@ -2185,7 +2228,8 @@ CLEANUP: if (pCsw) ExFreePoolWithTag(pCsw, TAG_HOOK); if (pCbtCreate) ExFreePoolWithTag(pCbtCreate, TAG_HOOK); - RtlFreeAnsiString(&asClassName); + if (pszName) UserHeapFree(pszName); + if (pszClass) UserHeapFree(pszClass); if (Window) { @@ -2335,10 +2379,11 @@ NtUserCreateWindowEx( Cs.cy = nHeight; Cs.x = x; Cs.y = y; -// Cs.lpszName = (LPCWSTR) WindowName->Buffer; -// Cs.lpszClass = (LPCWSTR) ClassName->Buffer; - Cs.lpszName = (LPCWSTR) plstrWindowName; - Cs.lpszClass = (LPCWSTR) &ustrClassName; + Cs.lpszName = (LPCWSTR) plstrWindowName->Buffer; + if (IS_ATOM(plstrClassName)) + Cs.lpszClass = (LPCWSTR) plstrClassName; + else + Cs.lpszClass = (LPCWSTR) plstrClassName->Buffer; Cs.dwExStyle = dwExStyle; UserEnterExclusive(); @@ -2522,7 +2567,7 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window) msg.wParam = IntGetSysCursorInfo()->ButtonsDown; msg.lParam = MAKELPARAM(gpsi->ptCursor.x, gpsi->ptCursor.y); msg.pt = gpsi->ptCursor; - MsqInsertSystemMessage(&msg); + MsqInsertMouseMessage(&msg); if (!IntIsWindow(Window->head.h)) { diff --git a/subsystems/win32/win32k/ntuser/winsta.c b/subsystems/win32/win32k/ntuser/winsta.c index 09810d2c82a..ca99f797c00 100644 --- a/subsystems/win32/win32k/ntuser/winsta.c +++ b/subsystems/win32/win32k/ntuser/winsta.c @@ -56,7 +56,9 @@ static GENERIC_MAPPING IntWindowStationMapping = }; -NTSTATUS FASTCALL +INIT_FUNCTION +NTSTATUS +NTAPI InitWindowStationImpl(VOID) { OBJECT_ATTRIBUTES ObjectAttributes; diff --git a/subsystems/win32/win32k/objects/dclife.c b/subsystems/win32/win32k/objects/dclife.c index 75113441b85..589e92c594f 100644 --- a/subsystems/win32/win32k/objects/dclife.c +++ b/subsystems/win32/win32k/objects/dclife.c @@ -58,7 +58,9 @@ static const MATRIX gmxWorldToPageDefault = /** Internal functions ********************************************************/ +INIT_FUNCTION NTSTATUS +NTAPI InitDcImpl() { psurfDefaultBitmap = SURFACE_ShareLockSurface(StockObjects[DEFAULT_BITMAP]); diff --git a/subsystems/win32/win32k/objects/gdiobj.c b/subsystems/win32/win32k/objects/gdiobj.c index f9bacf092e5..5eb43dd6feb 100644 --- a/subsystems/win32/win32k/objects/gdiobj.c +++ b/subsystems/win32/win32k/objects/gdiobj.c @@ -8,7 +8,7 @@ /** INCLUDES ******************************************************************/ -#define GDI_DEBUG +//#define GDI_DEBUG #include #define NDEBUG @@ -81,6 +81,8 @@ OBJ_TYPE_INFO ObjTypeInfo[BASE_OBJTYPE_COUNT] = }; static LARGE_INTEGER ShortDelay; +PGDI_HANDLE_TABLE GdiHandleTable = NULL; +PSECTION_OBJECT GdiTableSection = NULL; /** INTERNAL FUNCTIONS ********************************************************/ @@ -151,7 +153,9 @@ GDI_CleanupDummy(PVOID ObjectBody) * Allocate GDI object table. * \param Size - number of entries in the object table. */ -PGDI_HANDLE_TABLE INTERNAL_CALL +INIT_FUNCTION +PGDI_HANDLE_TABLE +INTERNAL_CALL GDIOBJ_iAllocHandleTable(OUT PSECTION_OBJECT *SectionObject) { PGDI_HANDLE_TABLE HandleTable = NULL; @@ -221,6 +225,23 @@ GDIOBJ_iAllocHandleTable(OUT PSECTION_OBJECT *SectionObject) return HandleTable; } +INIT_FUNCTION +NTSTATUS +NTAPI +InitGdiHandleTable() +{ + /* Create the GDI handle table */ + GdiHandleTable = GDIOBJ_iAllocHandleTable(&GdiTableSection); + if (GdiHandleTable == NULL) + { + DPRINT1("Failed to initialize the GDI handle table.\n"); + return STATUS_UNSUCCESSFUL; + } + + return STATUS_SUCCESS; +} + + static void FASTCALL LockErrorDebugOutput(HGDIOBJ hObj, PGDI_TABLE_ENTRY Entry, LPSTR Function) { diff --git a/subsystems/win32/win32k/objects/palette.c b/subsystems/win32/win32k/objects/palette.c index 47dbd28eaa6..e930bc116f9 100644 --- a/subsystems/win32/win32k/objects/palette.c +++ b/subsystems/win32/win32k/objects/palette.c @@ -57,7 +57,10 @@ unsigned short GetNumberOfBits(unsigned int dwMask) } // Create the system palette -HPALETTE FASTCALL PALETTE_Init(VOID) +INIT_FUNCTION +NTSTATUS +NTAPI +InitPaletteImpl() { int i; HPALETTE hpalette; @@ -68,7 +71,7 @@ HPALETTE FASTCALL PALETTE_Init(VOID) sizeof(LOGPALETTE) + (NB_RESERVED_COLORS * sizeof(PALETTEENTRY)), TAG_PALETTE); - if (!palPtr) return FALSE; + if (!palPtr) return STATUS_NO_MEMORY; palPtr->palVersion = 0x300; palPtr->palNumEntries = NB_RESERVED_COLORS; @@ -131,7 +134,7 @@ HPALETTE FASTCALL PALETTE_Init(VOID) appalSurfaceDefault[BMF_JPEG] = &gpalRGB; appalSurfaceDefault[BMF_PNG] = &gpalRGB; - return hpalette; + return STATUS_SUCCESS; } VOID FASTCALL PALETTE_ValidateFlags(PALETTEENTRY* lpPalE, INT size)