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

wined3d_main.c
Go to the documentation of this file.
00001 /*
00002  * Direct3D wine internal interface main
00003  *
00004  * Copyright 2002-2003 The wine-d3d team
00005  * Copyright 2002-2003 Raphael Junqueira
00006  * Copyright 2004      Jason Edmeades
00007  * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
00008  * Copyright 2009 Henri Verbeet for CodeWeavers
00009  *
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or (at your option) any later version.
00014  *
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00023  */
00024 
00025 #include "config.h"
00026 
00027 #include "initguid.h"
00028 #include "wined3d_private.h"
00029 
00030 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
00031 WINE_DECLARE_DEBUG_CHANNEL(winediag);
00032 
00033 struct wined3d_wndproc
00034 {
00035     HWND window;
00036     BOOL unicode;
00037     WNDPROC proc;
00038     struct wined3d_device *device;
00039 };
00040 
00041 struct wined3d_wndproc_table
00042 {
00043     struct wined3d_wndproc *entries;
00044     unsigned int count;
00045     unsigned int size;
00046 };
00047 
00048 static struct wined3d_wndproc_table wndproc_table;
00049 
00050 int num_lock = 0;
00051 void (CDECL *wine_tsx11_lock_ptr)(void) = NULL;
00052 void (CDECL *wine_tsx11_unlock_ptr)(void) = NULL;
00053 
00054 static CRITICAL_SECTION wined3d_cs;
00055 static CRITICAL_SECTION_DEBUG wined3d_cs_debug =
00056 {
00057     0, 0, &wined3d_cs,
00058     {&wined3d_cs_debug.ProcessLocksList,
00059     &wined3d_cs_debug.ProcessLocksList},
00060     0, 0, {(DWORD_PTR)(__FILE__ ": wined3d_cs")}
00061 };
00062 static CRITICAL_SECTION wined3d_cs = {&wined3d_cs_debug, -1, 0, 0, 0, 0};
00063 
00064 static CRITICAL_SECTION wined3d_wndproc_cs;
00065 static CRITICAL_SECTION_DEBUG wined3d_wndproc_cs_debug =
00066 {
00067     0, 0, &wined3d_wndproc_cs,
00068     {&wined3d_wndproc_cs_debug.ProcessLocksList,
00069     &wined3d_wndproc_cs_debug.ProcessLocksList},
00070     0, 0, {(DWORD_PTR)(__FILE__ ": wined3d_wndproc_cs")}
00071 };
00072 static CRITICAL_SECTION wined3d_wndproc_cs = {&wined3d_wndproc_cs_debug, -1, 0, 0, 0, 0};
00073 
00074 /* When updating default value here, make sure to update winecfg as well,
00075  * where appropriate. */
00076 struct wined3d_settings wined3d_settings =
00077 {
00078     VS_HW,          /* Hardware by default */
00079     PS_HW,          /* Hardware by default */
00080     TRUE,           /* Use of GLSL enabled by default */
00081     ORM_FBO,        /* Use FBOs to do offscreen rendering */
00082     RTL_READTEX,    /* Default render target locking method */
00083     PCI_VENDOR_NONE,/* PCI Vendor ID */
00084     PCI_DEVICE_NONE,/* PCI Device ID */
00085     0,              /* The default of memory is set in init_driver_info */
00086     NULL,           /* No wine logo by default */
00087     TRUE,           /* Multisampling enabled by default. */
00088     FALSE,          /* No strict draw ordering. */
00089     FALSE,          /* Try to render onscreen by default. */
00090 };
00091 
00092 /* Do not call while under the GL lock. */
00093 struct wined3d * CDECL wined3d_create(UINT version, DWORD flags, void *parent)
00094 {
00095     struct wined3d *object;
00096     HRESULT hr;
00097 
00098     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
00099     if (!object)
00100     {
00101         ERR("Failed to allocate wined3d object memory.\n");
00102         return NULL;
00103     }
00104 
00105     hr = wined3d_init(object, version, flags, parent);
00106     if (FAILED(hr))
00107     {
00108         WARN("Failed to initialize wined3d object, hr %#x.\n", hr);
00109         HeapFree(GetProcessHeap(), 0, object);
00110         return NULL;
00111     }
00112 
00113     TRACE("Created wined3d object %p for d3d%d support.\n", object, version);
00114 
00115     return object;
00116 }
00117 
00118 static DWORD get_config_key(HKEY defkey, HKEY appkey, const char *name, char *buffer, DWORD size)
00119 {
00120     if (appkey && !RegQueryValueExA(appkey, name, 0, NULL, (BYTE *)buffer, &size)) return 0;
00121     if (defkey && !RegQueryValueExA(defkey, name, 0, NULL, (BYTE *)buffer, &size)) return 0;
00122     return ERROR_FILE_NOT_FOUND;
00123 }
00124 
00125 static DWORD get_config_key_dword(HKEY defkey, HKEY appkey, const char *name, DWORD *data)
00126 {
00127     DWORD type;
00128     DWORD size = sizeof(DWORD);
00129     if (appkey && !RegQueryValueExA(appkey, name, 0, &type, (BYTE *)data, &size) && (type == REG_DWORD)) return 0;
00130     if (defkey && !RegQueryValueExA(defkey, name, 0, &type, (BYTE *)data, &size) && (type == REG_DWORD)) return 0;
00131     return ERROR_FILE_NOT_FOUND;
00132 }
00133 
00134 static void CDECL wined3d_do_nothing(void)
00135 {
00136 }
00137 
00138 static BOOL wined3d_dll_init(HINSTANCE hInstDLL)
00139 {
00140     DWORD wined3d_context_tls_idx;
00141     HMODULE mod;
00142     char buffer[MAX_PATH+10];
00143     DWORD size = sizeof(buffer);
00144     HKEY hkey = 0;
00145     HKEY appkey = 0;
00146     DWORD len, tmpvalue;
00147     WNDCLASSA wc;
00148 
00149     wined3d_context_tls_idx = TlsAlloc();
00150     if (wined3d_context_tls_idx == TLS_OUT_OF_INDEXES)
00151     {
00152         DWORD err = GetLastError();
00153         ERR("Failed to allocate context TLS index, err %#x.\n", err);
00154         return FALSE;
00155     }
00156     context_set_tls_idx(wined3d_context_tls_idx);
00157 
00158     /* We need our own window class for a fake window which we use to retrieve GL capabilities */
00159     /* We might need CS_OWNDC in the future if we notice strange things on Windows.
00160      * Various articles/posts about OpenGL problems on Windows recommend this. */
00161     wc.style                = CS_HREDRAW | CS_VREDRAW;
00162     wc.lpfnWndProc          = DefWindowProcA;
00163     wc.cbClsExtra           = 0;
00164     wc.cbWndExtra           = 0;
00165     wc.hInstance            = hInstDLL;
00166     wc.hIcon                = LoadIconA(NULL, (LPCSTR)IDI_WINLOGO);
00167     wc.hCursor              = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
00168     wc.hbrBackground        = NULL;
00169     wc.lpszMenuName         = NULL;
00170     wc.lpszClassName        = WINED3D_OPENGL_WINDOW_CLASS_NAME;
00171 
00172     if (!RegisterClassA(&wc))
00173     {
00174         ERR("Failed to register window class 'WineD3D_OpenGL'!\n");
00175         if (!TlsFree(wined3d_context_tls_idx))
00176         {
00177             DWORD err = GetLastError();
00178             ERR("Failed to free context TLS index, err %#x.\n", err);
00179         }
00180         return FALSE;
00181     }
00182 
00183     DisableThreadLibraryCalls(hInstDLL);
00184 
00185     mod = GetModuleHandleA( "winex11.drv" );
00186     if (mod)
00187     {
00188         wine_tsx11_lock_ptr   = (void *)GetProcAddress( mod, "wine_tsx11_lock" );
00189         wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" );
00190     }
00191     else /* We are most likely on Windows */
00192     {
00193         wine_tsx11_lock_ptr   = wined3d_do_nothing;
00194         wine_tsx11_unlock_ptr = wined3d_do_nothing;
00195     }
00196     /* @@ Wine registry key: HKCU\Software\Wine\Direct3D */
00197     if ( RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Direct3D", &hkey ) ) hkey = 0;
00198 
00199     len = GetModuleFileNameA( 0, buffer, MAX_PATH );
00200     if (len && len < MAX_PATH)
00201     {
00202         HKEY tmpkey;
00203         /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\Direct3D */
00204         if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
00205         {
00206             char *p, *appname = buffer;
00207             if ((p = strrchr( appname, '/' ))) appname = p + 1;
00208             if ((p = strrchr( appname, '\\' ))) appname = p + 1;
00209             strcat( appname, "\\Direct3D" );
00210             TRACE("appname = [%s]\n", appname);
00211             if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
00212             RegCloseKey( tmpkey );
00213         }
00214     }
00215 
00216     if (hkey || appkey)
00217     {
00218         if ( !get_config_key( hkey, appkey, "VertexShaderMode", buffer, size) )
00219         {
00220             if (!strcmp(buffer,"none"))
00221             {
00222                 TRACE("Disable vertex shaders\n");
00223                 wined3d_settings.vs_mode = VS_NONE;
00224             }
00225         }
00226         if ( !get_config_key( hkey, appkey, "PixelShaderMode", buffer, size) )
00227         {
00228             if (!strcmp(buffer,"enabled"))
00229             {
00230                 TRACE("Allow pixel shaders\n");
00231                 wined3d_settings.ps_mode = PS_HW;
00232             }
00233             if (!strcmp(buffer,"disabled"))
00234             {
00235                 TRACE("Disable pixel shaders\n");
00236                 wined3d_settings.ps_mode = PS_NONE;
00237             }
00238         }
00239         if ( !get_config_key( hkey, appkey, "UseGLSL", buffer, size) )
00240         {
00241             if (!strcmp(buffer,"disabled"))
00242             {
00243                 ERR_(winediag)("The GLSL shader backend has been disabled. You get to keep all the pieces if it breaks.\n");
00244                 TRACE("Use of GL Shading Language disabled\n");
00245                 wined3d_settings.glslRequested = FALSE;
00246             }
00247         }
00248         if ( !get_config_key( hkey, appkey, "OffscreenRenderingMode", buffer, size) )
00249         {
00250             if (!strcmp(buffer,"backbuffer"))
00251             {
00252                 TRACE("Using the backbuffer for offscreen rendering\n");
00253                 wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER;
00254             }
00255             else if (!strcmp(buffer,"fbo"))
00256             {
00257                 TRACE("Using FBOs for offscreen rendering\n");
00258                 wined3d_settings.offscreen_rendering_mode = ORM_FBO;
00259             }
00260         }
00261         if ( !get_config_key( hkey, appkey, "RenderTargetLockMode", buffer, size) )
00262         {
00263             if (!strcmp(buffer,"readdraw"))
00264             {
00265                 TRACE("Using glReadPixels for render target reading and glDrawPixels for writing\n");
00266                 wined3d_settings.rendertargetlock_mode = RTL_READDRAW;
00267             }
00268             else if (!strcmp(buffer,"readtex"))
00269             {
00270                 TRACE("Using glReadPixels for render target reading and textures for writing\n");
00271                 wined3d_settings.rendertargetlock_mode = RTL_READTEX;
00272             }
00273         }
00274         if ( !get_config_key_dword( hkey, appkey, "VideoPciDeviceID", &tmpvalue) )
00275         {
00276             int pci_device_id = tmpvalue;
00277 
00278             /* A pci device id is 16-bit */
00279             if(pci_device_id > 0xffff)
00280             {
00281                 ERR("Invalid value for VideoPciDeviceID. The value should be smaller or equal to 65535 or 0xffff\n");
00282             }
00283             else
00284             {
00285                 TRACE("Using PCI Device ID %04x\n", pci_device_id);
00286                 wined3d_settings.pci_device_id = pci_device_id;
00287             }
00288         }
00289         if ( !get_config_key_dword( hkey, appkey, "VideoPciVendorID", &tmpvalue) )
00290         {
00291             int pci_vendor_id = tmpvalue;
00292 
00293             /* A pci device id is 16-bit */
00294             if(pci_vendor_id > 0xffff)
00295             {
00296                 ERR("Invalid value for VideoPciVendorID. The value should be smaller or equal to 65535 or 0xffff\n");
00297             }
00298             else
00299             {
00300                 TRACE("Using PCI Vendor ID %04x\n", pci_vendor_id);
00301                 wined3d_settings.pci_vendor_id = pci_vendor_id;
00302             }
00303         }
00304         if ( !get_config_key( hkey, appkey, "VideoMemorySize", buffer, size) )
00305         {
00306             int TmpVideoMemorySize = atoi(buffer);
00307             if(TmpVideoMemorySize > 0)
00308             {
00309                 wined3d_settings.emulated_textureram = TmpVideoMemorySize *1024*1024;
00310                 TRACE("Use %iMB = %d byte for emulated_textureram\n",
00311                         TmpVideoMemorySize,
00312                         wined3d_settings.emulated_textureram);
00313             }
00314             else
00315                 ERR("VideoMemorySize is %i but must be >0\n", TmpVideoMemorySize);
00316         }
00317         if ( !get_config_key( hkey, appkey, "WineLogo", buffer, size) )
00318         {
00319             size_t len = strlen(buffer) + 1;
00320 
00321             wined3d_settings.logo = HeapAlloc(GetProcessHeap(), 0, len);
00322             if (!wined3d_settings.logo) ERR("Failed to allocate logo path memory.\n");
00323             else memcpy(wined3d_settings.logo, buffer, len);
00324         }
00325         if ( !get_config_key( hkey, appkey, "Multisampling", buffer, size) )
00326         {
00327             if (!strcmp(buffer, "disabled"))
00328             {
00329                 TRACE("Multisampling disabled.\n");
00330                 wined3d_settings.allow_multisampling = FALSE;
00331             }
00332         }
00333         if (!get_config_key(hkey, appkey, "StrictDrawOrdering", buffer, size)
00334                 && !strcmp(buffer,"enabled"))
00335         {
00336             TRACE("Enforcing strict draw ordering.\n");
00337             wined3d_settings.strict_draw_ordering = TRUE;
00338         }
00339         if (!get_config_key(hkey, appkey, "AlwaysOffscreen", buffer, size)
00340                 && !strcmp(buffer,"enabled"))
00341         {
00342             TRACE("Always rendering backbuffers offscreen.\n");
00343             wined3d_settings.always_offscreen = TRUE;
00344         }
00345     }
00346     if (wined3d_settings.vs_mode == VS_HW)
00347         TRACE("Allow HW vertex shaders\n");
00348     if (wined3d_settings.ps_mode == PS_NONE)
00349         TRACE("Disable pixel shaders\n");
00350     if (wined3d_settings.glslRequested)
00351         TRACE("If supported by your system, GL Shading Language will be used\n");
00352 
00353     if (appkey) RegCloseKey( appkey );
00354     if (hkey) RegCloseKey( hkey );
00355 
00356     return TRUE;
00357 }
00358 
00359 static BOOL wined3d_dll_destroy(HINSTANCE hInstDLL)
00360 {
00361     DWORD wined3d_context_tls_idx = context_get_tls_idx();
00362     unsigned int i;
00363 
00364     if (!TlsFree(wined3d_context_tls_idx))
00365     {
00366         DWORD err = GetLastError();
00367         ERR("Failed to free context TLS index, err %#x.\n", err);
00368     }
00369 
00370     for (i = 0; i < wndproc_table.count; ++i)
00371     {
00372         /* Trying to unregister these would be futile. These entries can only
00373          * exist if either we skipped them in wined3d_unregister_window() due
00374          * to the application replacing the wndproc after the entry was
00375          * registered, or if the application still has an active wined3d
00376          * device. In the latter case the application has bigger problems than
00377          * these entries. */
00378         WARN("Leftover wndproc table entry %p.\n", &wndproc_table.entries[i]);
00379     }
00380     HeapFree(GetProcessHeap(), 0, wndproc_table.entries);
00381 
00382     HeapFree(GetProcessHeap(), 0, wined3d_settings.logo);
00383     UnregisterClassA(WINED3D_OPENGL_WINDOW_CLASS_NAME, hInstDLL);
00384 
00385     DeleteCriticalSection(&wined3d_wndproc_cs);
00386     DeleteCriticalSection(&wined3d_cs);
00387     return TRUE;
00388 }
00389 
00390 void WINAPI wined3d_mutex_lock(void)
00391 {
00392     EnterCriticalSection(&wined3d_cs);
00393 }
00394 
00395 void WINAPI wined3d_mutex_unlock(void)
00396 {
00397     LeaveCriticalSection(&wined3d_cs);
00398 }
00399 
00400 static void wined3d_wndproc_mutex_lock(void)
00401 {
00402     EnterCriticalSection(&wined3d_wndproc_cs);
00403 }
00404 
00405 static void wined3d_wndproc_mutex_unlock(void)
00406 {
00407     LeaveCriticalSection(&wined3d_wndproc_cs);
00408 }
00409 
00410 static struct wined3d_wndproc *wined3d_find_wndproc(HWND window)
00411 {
00412     unsigned int i;
00413 
00414     for (i = 0; i < wndproc_table.count; ++i)
00415     {
00416         if (wndproc_table.entries[i].window == window)
00417         {
00418             return &wndproc_table.entries[i];
00419         }
00420     }
00421 
00422     return NULL;
00423 }
00424 
00425 static LRESULT CALLBACK wined3d_wndproc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
00426 {
00427     struct wined3d_wndproc *entry;
00428     struct wined3d_device *device;
00429     BOOL unicode;
00430     WNDPROC proc;
00431 
00432     wined3d_wndproc_mutex_lock();
00433     entry = wined3d_find_wndproc(window);
00434 
00435     if (!entry)
00436     {
00437         wined3d_wndproc_mutex_unlock();
00438         ERR("Window %p is not registered with wined3d.\n", window);
00439         return DefWindowProcW(window, message, wparam, lparam);
00440     }
00441 
00442     device = entry->device;
00443     unicode = entry->unicode;
00444     proc = entry->proc;
00445     wined3d_wndproc_mutex_unlock();
00446 
00447     return device_process_message(device, window, unicode, message, wparam, lparam, proc);
00448 }
00449 
00450 BOOL wined3d_register_window(HWND window, struct wined3d_device *device)
00451 {
00452     struct wined3d_wndproc *entry;
00453 
00454     wined3d_wndproc_mutex_lock();
00455 
00456     if (wined3d_find_wndproc(window))
00457     {
00458         wined3d_wndproc_mutex_unlock();
00459         WARN("Window %p is already registered with wined3d.\n", window);
00460         return TRUE;
00461     }
00462 
00463     if (wndproc_table.size == wndproc_table.count)
00464     {
00465         unsigned int new_size = max(1, wndproc_table.size * 2);
00466         struct wined3d_wndproc *new_entries;
00467 
00468         if (!wndproc_table.entries) new_entries = HeapAlloc(GetProcessHeap(), 0, new_size * sizeof(*new_entries));
00469         else new_entries = HeapReAlloc(GetProcessHeap(), 0, wndproc_table.entries, new_size * sizeof(*new_entries));
00470 
00471         if (!new_entries)
00472         {
00473             wined3d_wndproc_mutex_unlock();
00474             ERR("Failed to grow table.\n");
00475             return FALSE;
00476         }
00477 
00478         wndproc_table.entries = new_entries;
00479         wndproc_table.size = new_size;
00480     }
00481 
00482     entry = &wndproc_table.entries[wndproc_table.count++];
00483     entry->window = window;
00484     entry->unicode = IsWindowUnicode(window);
00485     /* Set a window proc that matches the window. Some applications (e.g. NoX)
00486      * replace the window proc after we've set ours, and expect to be able to
00487      * call the previous one (ours) directly, without using CallWindowProc(). */
00488     if (entry->unicode)
00489         entry->proc = (WNDPROC)SetWindowLongPtrW(window, GWLP_WNDPROC, (LONG_PTR)wined3d_wndproc);
00490     else
00491         entry->proc = (WNDPROC)SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)wined3d_wndproc);
00492     entry->device = device;
00493 
00494     wined3d_wndproc_mutex_unlock();
00495 
00496     return TRUE;
00497 }
00498 
00499 void wined3d_unregister_window(HWND window)
00500 {
00501     struct wined3d_wndproc *entry, *last;
00502     LONG_PTR proc;
00503 
00504     wined3d_wndproc_mutex_lock();
00505 
00506     if (!(entry = wined3d_find_wndproc(window)))
00507     {
00508         wined3d_wndproc_mutex_unlock();
00509         ERR("Window %p is not registered with wined3d.\n", window);
00510         return;
00511     }
00512 
00513     if (entry->unicode)
00514     {
00515         proc = GetWindowLongPtrW(window, GWLP_WNDPROC);
00516         if (proc != (LONG_PTR)wined3d_wndproc)
00517         {
00518             wined3d_wndproc_mutex_unlock();
00519             WARN("Not unregistering window %p, window proc %#lx doesn't match wined3d window proc %p.\n",
00520                     window, proc, wined3d_wndproc);
00521             return;
00522         }
00523 
00524         SetWindowLongPtrW(window, GWLP_WNDPROC, (LONG_PTR)entry->proc);
00525     }
00526     else
00527     {
00528         proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
00529         if (proc != (LONG_PTR)wined3d_wndproc)
00530         {
00531             wined3d_wndproc_mutex_unlock();
00532             WARN("Not unregistering window %p, window proc %#lx doesn't match wined3d window proc %p.\n",
00533                     window, proc, wined3d_wndproc);
00534             return;
00535         }
00536 
00537         SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)entry->proc);
00538     }
00539 
00540     last = &wndproc_table.entries[--wndproc_table.count];
00541     if (entry != last) *entry = *last;
00542 
00543     wined3d_wndproc_mutex_unlock();
00544 }
00545 
00546 /* At process attach */
00547 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
00548 {
00549     TRACE("WineD3D DLLMain Reason=%u\n", fdwReason);
00550 
00551     switch (fdwReason)
00552     {
00553         case DLL_PROCESS_ATTACH:
00554             return wined3d_dll_init(hInstDLL);
00555 
00556         case DLL_PROCESS_DETACH:
00557             return wined3d_dll_destroy(hInstDLL);
00558 
00559         case DLL_THREAD_DETACH:
00560         {
00561             if (!context_set_current(NULL))
00562             {
00563                 ERR("Failed to clear current context.\n");
00564             }
00565             return TRUE;
00566         }
00567 
00568         default:
00569             return TRUE;
00570     }
00571 }

Generated on Thu May 24 2012 04:22:39 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.