ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

mui.c
Go to the documentation of this file.
00001 /*
00002  *  ReactOS kernel
00003  *  Copyright (C) 2008 ReactOS Team
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License along
00016  *  with this program; if not, write to the Free Software Foundation, Inc.,
00017  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00018  */
00019 /*
00020  * COPYRIGHT:       See COPYING in the top level directory
00021  * PROJECT:         ReactOS text-mode setup
00022  * FILE:            subsys/system/usetup/mui.c
00023  * PURPOSE:         Text-mode setup
00024  * PROGRAMMER:
00025  */
00026 
00027 #include "usetup.h"
00028 #include "muifonts.h"
00029 #include "muilanguages.h"
00030 
00031 #define NDEBUG
00032 #include <debug.h>
00033 
00034 extern
00035 VOID
00036 PopupError(IN PCCH Text,
00037            IN PCCH Status,
00038            IN PINPUT_RECORD Ir,
00039            IN ULONG WaitEvent);
00040 
00041 static
00042 ULONG
00043 FindLanguageIndex(VOID)
00044 {
00045     ULONG lngIndex = 0;
00046 
00047     if (SelectedLanguageId == NULL)
00048     {
00049         /* default to english */
00050         return 0;
00051     }
00052 
00053     do
00054     {
00055         if (_wcsicmp(LanguageList[lngIndex].LanguageID , SelectedLanguageId) == 0)
00056         {
00057             return lngIndex;
00058         }
00059 
00060         lngIndex++;
00061     }while (LanguageList[lngIndex].MuiPages != NULL);
00062 
00063     return 0;
00064 }
00065 
00066 BOOLEAN
00067 IsLanguageAvailable(PWCHAR LanguageId)
00068 {
00069     ULONG lngIndex = 0;
00070 
00071     do
00072     {
00073         if (_wcsicmp(LanguageList[lngIndex].LanguageID , LanguageId) == 0)
00074             return TRUE;
00075 
00076         lngIndex++;
00077     }while (LanguageList[lngIndex].MuiPages != NULL);
00078 
00079     return FALSE;
00080 }
00081 
00082 
00083 static
00084 const MUI_ENTRY *
00085 FindMUIEntriesOfPage(IN ULONG PageNumber)
00086 {
00087     ULONG muiIndex = 0;
00088     ULONG lngIndex;
00089     const MUI_PAGE * Pages = NULL;
00090 
00091     lngIndex = max(FindLanguageIndex(), 0);
00092     Pages = LanguageList[lngIndex].MuiPages;
00093 
00094     do
00095     {
00096          if (Pages[muiIndex].Number == PageNumber)
00097              return Pages[muiIndex].MuiEntry;
00098 
00099          muiIndex++;
00100     }while (Pages[muiIndex].MuiEntry != NULL);
00101 
00102     return NULL;
00103 }
00104 
00105 static
00106 const MUI_ERROR *
00107 FindMUIErrorEntries(VOID)
00108 {
00109     ULONG lngIndex = max(FindLanguageIndex(), 0);
00110     return LanguageList[lngIndex].MuiErrors;
00111 }
00112 
00113 static
00114 const MUI_STRING *
00115 FindMUIStringEntries(VOID)
00116 {
00117     ULONG lngIndex = max(FindLanguageIndex(), 0);
00118     return LanguageList[lngIndex].MuiStrings;
00119 }
00120 
00121 LPCWSTR
00122 MUIDefaultKeyboardLayout(VOID)
00123 {
00124     ULONG lngIndex = max(FindLanguageIndex(), 0);
00125     return LanguageList[lngIndex].MuiLayouts[0].LayoutID;
00126 }
00127 
00128 PWCHAR
00129 MUIGetGeoID(VOID)
00130 {
00131     ULONG lngIndex = max(FindLanguageIndex(), 0);
00132     return LanguageList[lngIndex].GeoID;
00133 }
00134 
00135 const MUI_LAYOUTS *
00136 MUIGetLayoutsList(VOID)
00137 {
00138     ULONG lngIndex = max(FindLanguageIndex(), 0);
00139     return LanguageList[lngIndex].MuiLayouts;
00140 }
00141 
00142 VOID
00143 MUIClearPage(IN ULONG page)
00144 {
00145     const MUI_ENTRY * entry;
00146     int index;
00147 
00148     entry = FindMUIEntriesOfPage(page);
00149     if (!entry)
00150     {
00151         PopupError("Error: Failed to find translated page",
00152                    NULL,
00153                    NULL,
00154                    POPUP_WAIT_NONE);
00155         return;
00156     }
00157 
00158     index = 0;
00159     do
00160     {
00161         CONSOLE_ClearStyledText(entry[index].X,
00162                                 entry[index].Y,
00163                                 entry[index].Flags,
00164                                 strlen(entry[index].Buffer));
00165         index++;
00166     }
00167     while (entry[index].Buffer != NULL);
00168 }
00169 
00170 VOID
00171 MUIDisplayPage(IN ULONG page)
00172 {
00173     const MUI_ENTRY * entry;
00174     int index;
00175 
00176     entry = FindMUIEntriesOfPage(page);
00177     if (!entry)
00178     {
00179         PopupError("Error: Failed to find translated page",
00180                    NULL,
00181                    NULL,
00182                    POPUP_WAIT_NONE);
00183         return;
00184     }
00185 
00186     index = 0;
00187     do
00188     {
00189         CONSOLE_SetStyledText(entry[index].X,
00190                               entry[index].Y,
00191                               entry[index].Flags,
00192                               entry[index].Buffer);
00193 
00194         index++;
00195     }
00196     while (entry[index].Buffer != NULL);
00197 }
00198 
00199 VOID
00200 MUIDisplayError(IN ULONG ErrorNum, OUT PINPUT_RECORD Ir, IN ULONG WaitEvent)
00201 {
00202     const MUI_ERROR * entry;
00203 
00204     if (ErrorNum >= ERROR_LAST_ERROR_CODE)
00205     {
00206         PopupError("Invalid error number provided",
00207                    "Press ENTER to continue",
00208                    Ir,
00209                    POPUP_WAIT_ENTER);
00210 
00211         return;
00212     }
00213 
00214     entry = FindMUIErrorEntries();
00215     if (!entry)
00216     {
00217         PopupError("Error: Failed to find translated error message",
00218                    NULL,
00219                    NULL,
00220                    POPUP_WAIT_NONE);
00221         return;
00222     }
00223 
00224     PopupError(entry[ErrorNum].ErrorText,
00225                entry[ErrorNum].ErrorStatus,
00226                Ir,
00227                WaitEvent);
00228 }
00229 
00230 LPSTR
00231 MUIGetString(ULONG Number)
00232 {
00233     ULONG i;
00234     const MUI_STRING * entry;
00235     CHAR szErr[100];
00236 
00237     entry = FindMUIStringEntries();
00238     if (entry)
00239     {
00240         for (i = 0; entry[i].Number != 0; i++)
00241         {
00242             if (entry[i].Number == Number)
00243             {
00244                 return entry[i].String;
00245             }
00246         }
00247     }
00248 
00249     sprintf(szErr, "Error: failed find string id %lu for language index %lu\n", Number, FindLanguageIndex());
00250 
00251     PopupError(szErr,
00252                 NULL,
00253                 NULL,
00254                 POPUP_WAIT_NONE);
00255 
00256     return "<nostring>";
00257 }
00258 
00259 static BOOLEAN
00260 AddHotkeySettings(IN LPCWSTR Hotkey, IN LPCWSTR LangHotkey, IN LPCWSTR LayoutHotkey)
00261 {
00262     OBJECT_ATTRIBUTES ObjectAttributes;
00263     UNICODE_STRING KeyName;
00264     UNICODE_STRING ValueName;
00265     HANDLE KeyHandle;
00266     ULONG Disposition;
00267     NTSTATUS Status;
00268 
00269     RtlInitUnicodeString(&KeyName,
00270                          L"\\Registry\\User\\.DEFAULT\\Keyboard Layout\\Toggle");
00271     InitializeObjectAttributes(&ObjectAttributes,
00272                                &KeyName,
00273                                OBJ_CASE_INSENSITIVE,
00274                                NULL,
00275                                NULL);
00276 
00277     Status =  NtCreateKey(&KeyHandle,
00278                           KEY_SET_VALUE,
00279                           &ObjectAttributes,
00280                           0,
00281                           NULL,
00282                           0,
00283                           &Disposition);
00284 
00285     if(!NT_SUCCESS(Status))
00286     {
00287         DPRINT1("NtCreateKey() failed (Status %lx)\n", Status);
00288         return FALSE;
00289     }
00290 
00291     RtlInitUnicodeString(&ValueName,
00292                          L"Hotkey");
00293 
00294     Status = NtSetValueKey(KeyHandle,
00295                            &ValueName,
00296                            0,
00297                            REG_SZ,
00298                            (PVOID)Hotkey,
00299                            (1 + 1) * sizeof(WCHAR));
00300     if (!NT_SUCCESS(Status))
00301     {
00302         DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
00303         NtClose(KeyHandle);
00304         return FALSE;
00305     }
00306 
00307     RtlInitUnicodeString(&ValueName,
00308                          L"Language Hotkey");
00309 
00310     Status = NtSetValueKey(KeyHandle,
00311                            &ValueName,
00312                            0,
00313                            REG_SZ,
00314                            (PVOID)LangHotkey,
00315                            (1 + 1) * sizeof(WCHAR));
00316     if (!NT_SUCCESS(Status))
00317     {
00318         DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
00319         NtClose(KeyHandle);
00320         return FALSE;
00321     }
00322 
00323     RtlInitUnicodeString(&ValueName,
00324                          L"Layout Hotkey");
00325 
00326     Status = NtSetValueKey(KeyHandle,
00327                            &ValueName,
00328                            0,
00329                            REG_SZ,
00330                            (PVOID)LayoutHotkey,
00331                            (1 + 1) * sizeof(WCHAR));
00332     if (!NT_SUCCESS(Status))
00333     {
00334         DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
00335         NtClose(KeyHandle);
00336         return FALSE;
00337     }
00338 
00339     NtClose(KeyHandle);
00340     return TRUE;
00341 }
00342 
00343 BOOLEAN
00344 AddKbLayoutsToRegistry(IN const MUI_LAYOUTS * MuiLayouts)
00345 {
00346     OBJECT_ATTRIBUTES ObjectAttributes;
00347     UNICODE_STRING KeyName;
00348     UNICODE_STRING ValueName;
00349     HANDLE KeyHandle;
00350     HANDLE SubKeyHandle;
00351     NTSTATUS Status;
00352     ULONG Disposition;
00353     ULONG uIndex = 0;
00354     ULONG uCount = 0;
00355     WCHAR szKeyName[48] = L"\\Registry\\User\\.DEFAULT\\Keyboard Layout";
00356     WCHAR szValueName[3 + 1];
00357     WCHAR szLangID[8 + 1];
00358 
00359     // Open the keyboard layout key
00360     RtlInitUnicodeString(&KeyName,
00361                          szKeyName);
00362     InitializeObjectAttributes(&ObjectAttributes,
00363                                &KeyName,
00364                                OBJ_CASE_INSENSITIVE,
00365                                NULL,
00366                                NULL);
00367 
00368     Status =  NtCreateKey(&KeyHandle,
00369                           KEY_CREATE_SUB_KEY,
00370                           &ObjectAttributes,
00371                           0,
00372                           NULL,
00373                           0,
00374                           &Disposition);
00375 
00376     if(NT_SUCCESS(Status))
00377         NtClose(KeyHandle);
00378     else
00379     {
00380         DPRINT1("NtCreateKey() failed (Status %lx)\n", Status);
00381         return FALSE;
00382     }
00383 
00384     KeyName.MaximumLength = sizeof(szKeyName);
00385     Status = RtlAppendUnicodeToString(&KeyName, L"\\Preload");
00386 
00387     if(!NT_SUCCESS(Status))
00388     {
00389         DPRINT1("RtlAppend failed! (%lx)\n", Status);
00390         DPRINT1("String is %wZ\n", &KeyName);
00391         return FALSE;
00392     }
00393 
00394     InitializeObjectAttributes(&ObjectAttributes,
00395                                &KeyName,
00396                                OBJ_CASE_INSENSITIVE,
00397                                NULL,
00398                                NULL);
00399 
00400     Status = NtCreateKey(&KeyHandle,
00401                          KEY_SET_VALUE,
00402                          &ObjectAttributes,
00403                          0,
00404                          NULL,
00405                          0,
00406                          &Disposition);
00407 
00408     if (!NT_SUCCESS(Status))
00409     {
00410         DPRINT1("NtCreateKey() failed (Status %lx)\n", Status);
00411         return FALSE;
00412     }
00413 
00414     RtlInitUnicodeString(&KeyName, L"\\Registry\\User\\.DEFAULT\\Keyboard Layout\\Substitutes");
00415     InitializeObjectAttributes(&ObjectAttributes,
00416                                &KeyName,
00417                                OBJ_CASE_INSENSITIVE,
00418                                NULL,
00419                                NULL);
00420 
00421     Status =  NtCreateKey(&SubKeyHandle,
00422                           KEY_SET_VALUE,
00423                           &ObjectAttributes,
00424                           0,
00425                           NULL,
00426                           0,
00427                           &Disposition);
00428 
00429     if(!NT_SUCCESS(Status))
00430     {
00431         DPRINT1("NtCreateKey() failed (Status %lx)\n", Status);
00432         NtClose(SubKeyHandle);
00433         NtClose(KeyHandle);
00434         return FALSE;
00435     }
00436 
00437     do
00438     {
00439         if (uIndex > 19) break;
00440 
00441         swprintf(szValueName, L"%u", uIndex + 1);
00442         RtlInitUnicodeString(&ValueName, szValueName);
00443 
00444         swprintf(szLangID, L"0000%s", MuiLayouts[uIndex].LangID);
00445 
00446         if (_wcsicmp(szLangID, MuiLayouts[uIndex].LayoutID) == 0)
00447         {
00448             Status = NtSetValueKey(KeyHandle,
00449                                    &ValueName,
00450                                    0,
00451                                    REG_SZ,
00452                                    (PVOID)MuiLayouts[uIndex].LayoutID,
00453                                    (wcslen(MuiLayouts[uIndex].LayoutID)+1) * sizeof(WCHAR));
00454             if (!NT_SUCCESS(Status))
00455             {
00456                 DPRINT1("NtSetValueKey() failed (Status = %lx, uIndex = %d)\n", Status, uIndex);
00457                 NtClose(SubKeyHandle);
00458                 NtClose(KeyHandle);
00459                 return FALSE;
00460             }
00461         }
00462         else
00463         {
00464             swprintf(szLangID, L"d%03u%s", uCount, MuiLayouts[uIndex].LangID);
00465             Status = NtSetValueKey(KeyHandle,
00466                                    &ValueName,
00467                                    0,
00468                                    REG_SZ,
00469                                    (PVOID)szLangID,
00470                                    (wcslen(szLangID)+1) * sizeof(WCHAR));
00471             if (!NT_SUCCESS(Status))
00472             {
00473                 DPRINT1("NtSetValueKey() failed (Status = %lx, uIndex = %d)\n", Status, uIndex);
00474                 NtClose(SubKeyHandle);
00475                 NtClose(KeyHandle);
00476                 return FALSE;
00477             }
00478 
00479             RtlInitUnicodeString(&ValueName, szLangID);
00480 
00481             Status = NtSetValueKey(SubKeyHandle,
00482                                    &ValueName,
00483                                    0,
00484                                    REG_SZ,
00485                                    (PVOID)MuiLayouts[uIndex].LayoutID,
00486                                    (wcslen(MuiLayouts[uIndex].LayoutID)+1) * sizeof(WCHAR));
00487             if (!NT_SUCCESS(Status))
00488             {
00489                 DPRINT1("NtSetValueKey() failed (Status = %lx, uIndex = %u)\n", Status, uIndex);
00490                 NtClose(SubKeyHandle);
00491                 NtClose(KeyHandle);
00492                 return FALSE;
00493             }
00494 
00495             uCount++;
00496         }
00497 
00498         uIndex++;
00499     }
00500     while (MuiLayouts[uIndex].LangID != NULL);
00501 
00502     if (uIndex > 1)
00503         AddHotkeySettings(L"2", L"2", L"1");
00504     else
00505         AddHotkeySettings(L"3", L"3", L"3");
00506 
00507     NtClose(SubKeyHandle);
00508     NtClose(KeyHandle);
00509     return TRUE;
00510 }
00511 
00512 BOOLEAN
00513 AddKeyboardLayouts(VOID)
00514 {
00515     ULONG lngIndex = 0;
00516     do
00517     {
00518         if (_wcsicmp(LanguageList[lngIndex].LanguageID , SelectedLanguageId) == 0)
00519         {
00520             return AddKbLayoutsToRegistry(LanguageList[lngIndex].MuiLayouts);
00521         }
00522 
00523         lngIndex++;
00524     }
00525     while (LanguageList[lngIndex].MuiPages != NULL);
00526 
00527     return FALSE;
00528 }
00529 
00530 static BOOLEAN
00531 AddCodepageToRegistry(IN LPCWSTR ACPage, IN LPCWSTR OEMCPage, IN LPCWSTR MACCPage)
00532 {
00533     OBJECT_ATTRIBUTES ObjectAttributes;
00534     UNICODE_STRING KeyName;
00535     UNICODE_STRING ValueName;
00536     HANDLE KeyHandle;
00537     NTSTATUS Status;
00538 
00539     // Open the nls codepage key
00540     RtlInitUnicodeString(&KeyName,
00541                          L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage");
00542     InitializeObjectAttributes(&ObjectAttributes,
00543                                &KeyName,
00544                                OBJ_CASE_INSENSITIVE,
00545                                NULL,
00546                                NULL);
00547     Status =  NtOpenKey(&KeyHandle,
00548                         KEY_WRITE,
00549                         &ObjectAttributes);
00550     if (!NT_SUCCESS(Status))
00551     {
00552         DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
00553         return FALSE;
00554     }
00555 
00556     // Set ANSI codepage
00557     RtlInitUnicodeString(&ValueName, L"ACP");
00558     Status = NtSetValueKey(KeyHandle,
00559                            &ValueName,
00560                            0,
00561                            REG_SZ,
00562                            (PVOID)ACPage,
00563                            (wcslen(ACPage)+1) * sizeof(WCHAR));
00564     if (!NT_SUCCESS(Status))
00565     {
00566         DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
00567         NtClose(KeyHandle);
00568         return FALSE;
00569     }
00570 
00571     // Set OEM codepage
00572     RtlInitUnicodeString(&ValueName, L"OEMCP");
00573     Status = NtSetValueKey(KeyHandle,
00574                            &ValueName,
00575                            0,
00576                            REG_SZ,
00577                            (PVOID)OEMCPage,
00578                            (wcslen(OEMCPage)+1) * sizeof(WCHAR));
00579     if (!NT_SUCCESS(Status))
00580     {
00581         DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
00582         NtClose(KeyHandle);
00583         return FALSE;
00584     }
00585 
00586     // Set MAC codepage
00587     RtlInitUnicodeString(&ValueName, L"MACCP");
00588     Status = NtSetValueKey(KeyHandle,
00589                            &ValueName,
00590                            0,
00591                            REG_SZ,
00592                            (PVOID)MACCPage,
00593                            (wcslen(MACCPage)+1) * sizeof(WCHAR));
00594     if (!NT_SUCCESS(Status))
00595     {
00596         DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
00597         NtClose(KeyHandle);
00598         return FALSE;
00599     }
00600 
00601     NtClose(KeyHandle);
00602 
00603     return TRUE;
00604 }
00605 
00606 static BOOLEAN
00607 AddFontsSettingsToRegistry(IN const MUI_SUBFONT * MuiSubFonts)
00608 {
00609     OBJECT_ATTRIBUTES ObjectAttributes;
00610     UNICODE_STRING KeyName;
00611     UNICODE_STRING ValueName;
00612     HANDLE KeyHandle;
00613     NTSTATUS Status;
00614     ULONG uIndex = 0;
00615 
00616     RtlInitUnicodeString(&KeyName,
00617                          L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SysFontSubstitutes");
00618     InitializeObjectAttributes(&ObjectAttributes,
00619                                &KeyName,
00620                                OBJ_CASE_INSENSITIVE,
00621                                NULL,
00622                                NULL);
00623     Status =  NtOpenKey(&KeyHandle,
00624                         KEY_WRITE,
00625                         &ObjectAttributes);
00626     if (!NT_SUCCESS(Status))
00627     {
00628         DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
00629         return FALSE;
00630     }
00631 
00632     do
00633     {
00634         RtlInitUnicodeString(&ValueName, MuiSubFonts[uIndex].FontName);
00635         Status = NtSetValueKey(KeyHandle,
00636                                &ValueName,
00637                                0,
00638                                REG_SZ,
00639                                (PVOID)MuiSubFonts[uIndex].SubFontName,
00640                                (wcslen(MuiSubFonts[uIndex].SubFontName)+1) * sizeof(WCHAR));
00641         if (!NT_SUCCESS(Status))
00642         {
00643             DPRINT1("NtSetValueKey() failed (Status = %lx, uIndex = %d)\n", Status, uIndex);
00644             NtClose(KeyHandle);
00645             return FALSE;
00646         }
00647 
00648         uIndex++;
00649     }
00650     while (MuiSubFonts[uIndex].FontName != NULL);
00651 
00652     NtClose(KeyHandle);
00653 
00654     return TRUE;
00655 }
00656 
00657 BOOLEAN
00658 AddCodePage(VOID)
00659 {
00660     ULONG lngIndex = 0;
00661     do
00662     {
00663         if (_wcsicmp(LanguageList[lngIndex].LanguageID , SelectedLanguageId) == 0)
00664         {
00665             if (AddCodepageToRegistry(LanguageList[lngIndex].ACPage,
00666                                       LanguageList[lngIndex].OEMCPage,
00667                                       LanguageList[lngIndex].MACCPage)&&
00668                 AddFontsSettingsToRegistry(LanguageList[lngIndex].MuiSubFonts))
00669             {
00670                 return TRUE;
00671             }
00672             else
00673             {
00674                 return FALSE;
00675             }
00676         }
00677 
00678         lngIndex++;
00679     }
00680     while (LanguageList[lngIndex].MuiPages != NULL);
00681 
00682     return FALSE;
00683 }
00684 
00685 VOID
00686 SetConsoleCodePage(VOID)
00687 {
00688     ULONG lngIndex = 0;
00689     UINT wCodePage;
00690 
00691     do
00692     {
00693         if (_wcsicmp(LanguageList[lngIndex].LanguageID , SelectedLanguageId) == 0)
00694         {
00695             wCodePage = (UINT) wcstoul(LanguageList[lngIndex].OEMCPage, NULL, 10);
00696             SetConsoleOutputCP(wCodePage);
00697             return;
00698         }
00699 
00700         lngIndex++;
00701     }
00702     while (LanguageList[lngIndex].MuiPages != NULL);
00703 }
00704 
00705 /* EOF */

Generated on Sat May 26 2012 04:16:58 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.