[Section]
Name = Mozilla Firefox 3.6
- Version = 3.6.10
+ Version = 3.6.11
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.10/win32/en-US/Firefox%20Setup%203.6.10.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.11/win32/en-US/Firefox%20Setup%203.6.11.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.10/win32/de/Firefox%20Setup%203.6.10.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.11/win32/de/Firefox%20Setup%203.6.11.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.10/win32/es-ES/Firefox%20Setup%203.6.10.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.11/win32/es-ES/Firefox%20Setup%203.6.11.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.10/win32/nb-NO/Firefox%20Setup%203.6.10.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.11/win32/nb-NO/Firefox%20Setup%203.6.11.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.10/win32/pl/Firefox%20Setup%203.6.10.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.11/win32/pl/Firefox%20Setup%203.6.11.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.10/win32/ru/Firefox%20Setup%203.6.10.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.11/win32/ru/Firefox%20Setup%203.6.11.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.10/win32/uk/Firefox%20Setup%203.6.10.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.11/win32/uk/Firefox%20Setup%203.6.11.exe
[Section]
Name = LibreOffice
- Version = 3.3.0 Beta 1
+ Version = 3.3.0 Beta 2
Licence = LGPL
Description = Former called OpenOffice. Open Source Office Suite.
- Size = 138.0MB
+ Size = 318.0MB
Category = 6
URLSite = http://www.documentfoundation.org/
- URLDownload = http://download.documentfoundation.org/libreoffice/testing/LO_3.3.0-beta1_Win_x86_install_en-US.exe
+ URLDownload = http://download.documentfoundation.org/libreoffice/testing/3.3.0-beta2/win/x86/LibO_3.3.0_beta2_Win_x86_install_multi.exe
CDPath = none
[Section.0407]
[Section]
Name = Miranda IM
- Version = 0.9.5
+ Version = 0.9.8
Licence = GPL
Description = Open source multiprotocol instant messaging application - May not work completely.
- Size = 2.2MB
+ Size = 3.0MB
Category = 5
URLSite = http://www.miranda-im.org/
- URLDownload = http://miranda.googlecode.com/files/miranda-im-v0.9.5-unicode.exe
+ URLDownload = http://miranda.googlecode.com/files/miranda-im-v0.9.8-unicode.exe
CDPath = none
[Section.0407]
[Section]
Name = mIRC
- Version = 7.1
+ Version = 7.14
Licence = Shareware
Description = The most popular client for the Internet Relay Chat (IRC).
- Size = 1.8M
+ Size = 2.0M
Category = 5
URLSite = http://www.mirc.com/
- URLDownload = http://download.mirc.com/mirc71.exe
+ URLDownload = http://download.mirc.com/mirc714.exe
CDPath = none
[Section.0407]
[Section]
Name = Opera
- Version = 10.62
+ Version = 10.63
Licence = Freeware
Description = The popular Opera Browser with many advanced features and including a Mail and BitTorrent client.
Size = 12.7M
Category = 5
URLSite = http://www.opera.com/
- URLDownload = http://get4.opera.com/pub/opera/win/1062/int/Opera_1062_int_Setup.exe
+ URLDownload = http://get4.opera.com/pub/opera/win/1063/int/Opera_1063_int_Setup.exe
CDPath = none
[Section.0407]
[Section]
Name = ScummVM
- Version = 1.1.1
+ Version = 1.2.0
Licence = GPL
Description = Sam and Max, Day of the Tentacle, etc on ReactOS.
- Size = 3.3MB
+ Size = 3.5MB
Category = 4
URLSite = http://scummvm.org/
- URLDownload = http://dfn.dl.sourceforge.net/project/scummvm/scummvm/1.1.1/scummvm-1.1.1-win32.exe
+ URLDownload = http://dfn.dl.sourceforge.net/project/scummvm/scummvm/1.2.0/scummvm-1.2.0-win32.exe
CDPath = none
[Section.0407]
[Section]
Name = Mozilla SeaMonkey
- Version = 2.0.8
+ Version = 2.0.9
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.8/win32/en-US/SeaMonkey%20Setup%202.0.8.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.9/win32/en-US/SeaMonkey%20Setup%202.0.9.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.8/win32/de/SeaMonkey%20Setup%202.0.8.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.9/win32/de/SeaMonkey%20Setup%202.0.9.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.8/win32/es-ES/SeaMonkey%20Setup%202.0.8.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.9/win32/es-ES/SeaMonkey%20Setup%202.0.9.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.8/win32/pl/SeaMonkey%20Setup%202.0.8.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.9/win32/pl/SeaMonkey%20Setup%202.0.9.exe
[Section.0419]
Description = Продолжение Mozilla Suite. Включает браузер, почтовый клиент, IRC-клиент и HTML-редактор.
Size = 10.4MB
- URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.8/win32/ru/SeaMonkey%20Setup%202.0.8.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.9/win32/ru/SeaMonkey%20Setup%202.0.9.exe
[Section]
Name = Mozilla Thunderbird
- Version = 3.1.4
+ Version = 3.1.5
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.4/win32/en-US/Thunderbird%20Setup%203.1.4.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.5/win32/en-US/Thunderbird%20Setup%203.1.5.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.4/win32/de/Thunderbird%20Setup%203.1.4.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.5/win32/de/Thunderbird%20Setup%203.1.5.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.4/win32/es-ES/Thunderbird%20Setup%203.1.4.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.5/win32/es-ES/Thunderbird%20Setup%203.1.5.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.4/win32/pl/Thunderbird%20Setup%203.1.4.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.5/win32/pl/Thunderbird%20Setup%203.1.5.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.4/win32/ru/Thunderbird%20Setup%203.1.4.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.5/win32/ru/Thunderbird%20Setup%203.1.5.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.4/win32/uk/Thunderbird%20Setup%203.1.4.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.5/win32/uk/Thunderbird%20Setup%203.1.5.exe
explorer_show_frame(SW_SHOWNORMAL);
break;
+ case WM_DISPLAYCHANGE:
+ MoveWindow(_hwnd, 0, 0, LOWORD(lparam), HIWORD(lparam), TRUE);
+ MoveWindow(g_Globals._hwndShellView, 0, 0, LOWORD(lparam), HIWORD(lparam), TRUE);
+ MoveWindow(_desktopBar, 0, HIWORD(lparam) - DESKTOPBARBAR_HEIGHT, LOWORD(lparam), DESKTOPBARBAR_HEIGHT, TRUE);
+ break;
+
case WM_GETISHELLBROWSER:
return (LRESULT)static_cast<IShellBrowser*>(this);
--- /dev/null
-
- /* FIXME: Insert more data here */
-
+/*
+ * PROJECT: ReactOS Service Control Manager
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: base/system/services/rpcserver.c
+ * PURPOSE: RPC server interface for the advapi32 calls
+ * COPYRIGHT: Copyright 2005-2006 Eric Kohl
+ * Copyright 2006-2007 Hervé Poussineau <hpoussin@reactos.org>
+ * Copyright 2007 Ged Murphy <gedmurphy@reactos.org>
+ */
+
+/* INCLUDES ****************************************************************/
+
+#include "services.h"
+#include "svcctl_s.h"
+
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS *****************************************************************/
+
+#define MANAGER_TAG 0x72674D68 /* 'hMgr' */
+#define SERVICE_TAG 0x63765368 /* 'hSvc' */
+
+typedef struct _SCMGR_HANDLE
+{
+ DWORD Tag;
+ DWORD DesiredAccess;
+} SCMGR_HANDLE;
+
+
+typedef struct _MANAGER_HANDLE
+{
+ SCMGR_HANDLE Handle;
-
+ WCHAR DatabaseName[1];
+} MANAGER_HANDLE, *PMANAGER_HANDLE;
+
+
+typedef struct _SERVICE_HANDLE
+{
+ SCMGR_HANDLE Handle;
-
- /* FIXME: Insert more data here */
-
+ PSERVICE ServiceEntry;
- if (_wcsicmp(lpDatabaseName,SERVICES_FAILED_DATABASEW)==0)
+} SERVICE_HANDLE, *PSERVICE_HANDLE;
+
+
+#define SC_MANAGER_READ \
+ (STANDARD_RIGHTS_READ | \
+ SC_MANAGER_QUERY_LOCK_STATUS | \
+ SC_MANAGER_ENUMERATE_SERVICE)
+
+#define SC_MANAGER_WRITE \
+ (STANDARD_RIGHTS_WRITE | \
+ SC_MANAGER_MODIFY_BOOT_CONFIG | \
+ SC_MANAGER_CREATE_SERVICE)
+
+#define SC_MANAGER_EXECUTE \
+ (STANDARD_RIGHTS_EXECUTE | \
+ SC_MANAGER_LOCK | \
+ SC_MANAGER_ENUMERATE_SERVICE | \
+ SC_MANAGER_CONNECT | \
+ SC_MANAGER_CREATE_SERVICE)
+
+
+#define SERVICE_READ \
+ (STANDARD_RIGHTS_READ | \
+ SERVICE_INTERROGATE | \
+ SERVICE_ENUMERATE_DEPENDENTS | \
+ SERVICE_QUERY_STATUS | \
+ SERVICE_QUERY_CONFIG)
+
+#define SERVICE_WRITE \
+ (STANDARD_RIGHTS_WRITE | \
+ SERVICE_CHANGE_CONFIG)
+
+#define SERVICE_EXECUTE \
+ (STANDARD_RIGHTS_EXECUTE | \
+ SERVICE_USER_DEFINED_CONTROL | \
+ SERVICE_PAUSE_CONTINUE | \
+ SERVICE_STOP | \
+ SERVICE_START)
+
+
+/* VARIABLES ***************************************************************/
+
+static GENERIC_MAPPING
+ScmManagerMapping = {SC_MANAGER_READ,
+ SC_MANAGER_WRITE,
+ SC_MANAGER_EXECUTE,
+ SC_MANAGER_ALL_ACCESS};
+
+static GENERIC_MAPPING
+ScmServiceMapping = {SERVICE_READ,
+ SERVICE_WRITE,
+ SERVICE_EXECUTE,
+ SC_MANAGER_ALL_ACCESS};
+
+
+/* FUNCTIONS ***************************************************************/
+
+VOID
+ScmStartRpcServer(VOID)
+{
+ RPC_STATUS Status;
+
+ DPRINT("ScmStartRpcServer() called\n");
+
+ Status = RpcServerUseProtseqEpW(L"ncacn_np",
+ 10,
+ L"\\pipe\\ntsvcs",
+ NULL);
+ if (Status != RPC_S_OK)
+ {
+ DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
+ return;
+ }
+
+ Status = RpcServerRegisterIf(svcctl_v2_0_s_ifspec,
+ NULL,
+ NULL);
+ if (Status != RPC_S_OK)
+ {
+ DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status);
+ return;
+ }
+
+ Status = RpcServerListen(1, 20, TRUE);
+ if (Status != RPC_S_OK)
+ {
+ DPRINT1("RpcServerListen() failed (Status %lx)\n", Status);
+ return;
+ }
+
+ DPRINT("ScmStartRpcServer() done\n");
+}
+
+
+static DWORD
+ScmCreateManagerHandle(LPWSTR lpDatabaseName,
+ SC_HANDLE *Handle)
+{
+ PMANAGER_HANDLE Ptr;
+
+ if (lpDatabaseName == NULL)
+ lpDatabaseName = SERVICES_ACTIVE_DATABASEW;
+
- /* FIXME: initialize more data here */
-
++ if (_wcsicmp(lpDatabaseName, SERVICES_FAILED_DATABASEW) == 0)
+ {
+ DPRINT("Database %S, does not exist\n",lpDatabaseName);
+ return ERROR_DATABASE_DOES_NOT_EXIST;
+ }
+ else if (_wcsicmp(lpDatabaseName, SERVICES_ACTIVE_DATABASEW) != 0)
+ {
+ DPRINT("Invalid Database name %S.\n",lpDatabaseName);
+ return ERROR_INVALID_NAME;
+ }
+
+ Ptr = (MANAGER_HANDLE*) HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof(MANAGER_HANDLE) + (wcslen(lpDatabaseName) + 1) * sizeof(WCHAR));
+ if (Ptr == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ Ptr->Handle.Tag = MANAGER_TAG;
+
- /* FIXME: initialize more data here */
+ wcscpy(Ptr->DatabaseName, lpDatabaseName);
+
+ *Handle = (SC_HANDLE)Ptr;
+
+ return ERROR_SUCCESS;
+}
+
+
+static DWORD
+ScmCreateServiceHandle(PSERVICE lpServiceEntry,
+ SC_HANDLE *Handle)
+{
+ PSERVICE_HANDLE Ptr;
+
+ Ptr = (SERVICE_HANDLE*) HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof(SERVICE_HANDLE));
+ if (Ptr == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ Ptr->Handle.Tag = SERVICE_TAG;
+
- hManager = (PMANAGER_HANDLE)*hSCObject;
- hService = (PSERVICE_HANDLE)*hSCObject;
- if (hManager->Handle.Tag == MANAGER_TAG)
+ Ptr->ServiceEntry = lpServiceEntry;
+
+ *Handle = (SC_HANDLE)Ptr;
+
+ return ERROR_SUCCESS;
+}
+
+
+static PMANAGER_HANDLE
+ScmGetServiceManagerFromHandle(SC_RPC_HANDLE Handle)
+{
+ PMANAGER_HANDLE pManager = NULL;
+
+ _SEH2_TRY
+ {
+ if (((PMANAGER_HANDLE)Handle)->Handle.Tag == MANAGER_TAG)
+ pManager = (PMANAGER_HANDLE)Handle;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ DPRINT1("Exception: Invalid Service Manager handle!\n");
+ }
+ _SEH2_END;
+
+ return pManager;
+}
+
+
+static PSERVICE_HANDLE
+ScmGetServiceFromHandle(SC_RPC_HANDLE Handle)
+{
+ PSERVICE_HANDLE pService = NULL;
+
+ _SEH2_TRY
+ {
+ if (((PSERVICE_HANDLE)Handle)->Handle.Tag == SERVICE_TAG)
+ pService = (PSERVICE_HANDLE)Handle;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ DPRINT1("Exception: Invalid Service handle!\n");
+ }
+ _SEH2_END;
+
+ return pService;
+}
+
+
+static DWORD
+ScmCheckAccess(SC_HANDLE Handle,
+ DWORD dwDesiredAccess)
+{
+ PMANAGER_HANDLE hMgr;
+
+ hMgr = (PMANAGER_HANDLE)Handle;
+ if (hMgr->Handle.Tag == MANAGER_TAG)
+ {
+ RtlMapGenericMask(&dwDesiredAccess,
+ &ScmManagerMapping);
+
+ hMgr->Handle.DesiredAccess = dwDesiredAccess;
+
+ return ERROR_SUCCESS;
+ }
+ else if (hMgr->Handle.Tag == SERVICE_TAG)
+ {
+ RtlMapGenericMask(&dwDesiredAccess,
+ &ScmServiceMapping);
+
+ hMgr->Handle.DesiredAccess = dwDesiredAccess;
+
+ return ERROR_SUCCESS;
+ }
+
+ return ERROR_INVALID_HANDLE;
+}
+
+
+DWORD
+ScmAssignNewTag(PSERVICE lpService)
+{
+ /* FIXME */
+ DPRINT("Assigning new tag to service %S\n", lpService->lpServiceName);
+ lpService->dwTag = 0;
+ return ERROR_SUCCESS;
+}
+
+
+/* Internal recursive function */
+/* Need to search for every dependency on every service */
+static DWORD
+Int_EnumDependentServicesW(HKEY hServicesKey,
+ PSERVICE lpService,
+ DWORD dwServiceState,
+ PSERVICE *lpServices,
+ LPDWORD pcbBytesNeeded,
+ LPDWORD lpServicesReturned)
+{
+ DWORD dwError = ERROR_SUCCESS;
+ WCHAR szNameBuf[MAX_PATH];
+ WCHAR szValueBuf[MAX_PATH];
+ WCHAR *lpszNameBuf = szNameBuf;
+ WCHAR *lpszValueBuf = szValueBuf;
+ DWORD dwSize;
+ DWORD dwNumSubKeys;
+ DWORD dwIteration;
+ PSERVICE lpCurrentService;
+ HKEY hServiceEnumKey;
+ DWORD dwCurrentServiceState = SERVICE_ACTIVE;
+ DWORD dwDependServiceStrPtr = 0;
+ DWORD dwRequiredSize = 0;
+
+ /* Get the number of service keys */
+ dwError = RegQueryInfoKeyW(hServicesKey,
+ NULL,
+ NULL,
+ NULL,
+ &dwNumSubKeys,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT("ERROR! Unable to get number of services keys.\n");
+ return dwError;
+ }
+
+ /* Iterate the service keys to see if another service depends on the this service */
+ for (dwIteration = 0; dwIteration < dwNumSubKeys; dwIteration++)
+ {
+ dwSize = MAX_PATH;
+ dwError = RegEnumKeyExW(hServicesKey,
+ dwIteration,
+ lpszNameBuf,
+ &dwSize,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (dwError != ERROR_SUCCESS)
+ return dwError;
+
+ /* Open the Service key */
+ dwError = RegOpenKeyExW(hServicesKey,
+ lpszNameBuf,
+ 0,
+ KEY_READ,
+ &hServiceEnumKey);
+ if (dwError != ERROR_SUCCESS)
+ return dwError;
+
+ dwSize = MAX_PATH;
+
+ /* Check for the DependOnService Value */
+ dwError = RegQueryValueExW(hServiceEnumKey,
+ L"DependOnService",
+ NULL,
+ NULL,
+ (LPBYTE)lpszValueBuf,
+ &dwSize);
+
+ /* FIXME: Handle load order. */
+
+ /* If the service found has a DependOnService value */
+ if (dwError == ERROR_SUCCESS)
+ {
+ dwDependServiceStrPtr = 0;
+
+ /* Can be more than one Dependencies in the DependOnService string */
+ while (wcslen(lpszValueBuf + dwDependServiceStrPtr) > 0)
+ {
+ if (_wcsicmp(lpszValueBuf + dwDependServiceStrPtr, lpService->lpServiceName) == 0)
+ {
+ /* Get the current enumed service pointer */
+ lpCurrentService = ScmGetServiceEntryByName(lpszNameBuf);
+
+ /* Check for valid Service */
+ if (!lpCurrentService)
+ {
+ /* This should never happen! */
+ DPRINT("This should not happen at this point, report to Developer\n");
+ return ERROR_NOT_FOUND;
+ }
+
+ /* Determine state the service is in */
+ if (lpCurrentService->Status.dwCurrentState == SERVICE_STOPPED)
+ dwCurrentServiceState = SERVICE_INACTIVE;
+
+ /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */
+ if ((dwCurrentServiceState == dwServiceState) ||
+ (dwServiceState == SERVICE_STATE_ALL))
+ {
+ /* Calculate the required size */
+ dwRequiredSize += sizeof(SERVICE_STATUS);
+ dwRequiredSize += ((wcslen(lpCurrentService->lpServiceName) + 1) * sizeof(WCHAR));
+ dwRequiredSize += ((wcslen(lpCurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
+
+ /* Add the size for service name and display name pointers */
+ dwRequiredSize += (2 * sizeof(PVOID));
+
+ /* increase the BytesNeeded size */
+ *pcbBytesNeeded = *pcbBytesNeeded + dwRequiredSize;
+
+ /* Don't fill callers buffer yet, as MSDN read that the last service with dependency
+ comes first */
+
+ /* Recursive call to check for its dependencies */
+ Int_EnumDependentServicesW(hServicesKey,
+ lpCurrentService,
+ dwServiceState,
+ lpServices,
+ pcbBytesNeeded,
+ lpServicesReturned);
+
+ /* If the lpServices is valid set the service pointer */
+ if (lpServices)
+ lpServices[*lpServicesReturned] = lpCurrentService;
+
+ *lpServicesReturned = *lpServicesReturned + 1;
+ }
+ }
+
+ dwDependServiceStrPtr += (wcslen(lpszValueBuf + dwDependServiceStrPtr) + 1);
+ }
+ }
+ else if (*pcbBytesNeeded)
+ {
+ dwError = ERROR_SUCCESS;
+ }
+
+ RegCloseKey(hServiceEnumKey);
+ }
+
+ return dwError;
+}
+
+
+/* Function 0 */
+DWORD RCloseServiceHandle(
+ LPSC_RPC_HANDLE hSCObject)
+{
+ PMANAGER_HANDLE hManager;
+ PSERVICE_HANDLE hService;
+ PSERVICE lpService;
+ HKEY hServicesKey;
+ DWORD dwError;
+ DWORD pcbBytesNeeded = 0;
+ DWORD dwServicesReturned = 0;
+
+ DPRINT("RCloseServiceHandle() called\n");
+
+ DPRINT("hSCObject = %p\n", *hSCObject);
+
+ if (*hSCObject == 0)
+ return ERROR_INVALID_HANDLE;
+
- else if (hService->Handle.Tag == SERVICE_TAG)
++ hManager = ScmGetServiceManagerFromHandle(*hSCObject);
++ hService = ScmGetServiceFromHandle(*hSCObject);
++
++ if (hManager != NULL)
+ {
+ DPRINT("Found manager handle\n");
+
+ /* FIXME: add handle cleanup code */
+
+ HeapFree(GetProcessHeap(), 0, hManager);
+ hManager = NULL;
+
+ DPRINT("RCloseServiceHandle() done\n");
+ return ERROR_SUCCESS;
+ }
++ else if (hService != NULL)
+ {
+ DPRINT("Found service handle\n");
+
+ /* Get the pointer to the service record */
+ lpService = hService->ServiceEntry;
+
+ /* FIXME: add handle cleanup code */
+
+ /* Free the handle */
+ HeapFree(GetProcessHeap(), 0, hService);
+ hService = NULL;
+
+ ASSERT(lpService->dwRefCount > 0);
+
+ lpService->dwRefCount--;
+ DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n",
+ lpService->dwRefCount);
+
+ if (lpService->dwRefCount == 0)
+ {
+ /* If this service has been marked for deletion */
+ if (lpService->bDeleted)
+ {
+ /* Open the Services Reg key */
+ dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ L"System\\CurrentControlSet\\Services",
+ 0,
+ KEY_SET_VALUE | KEY_READ,
+ &hServicesKey);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT("Failed to open services key\n");
+ return dwError;
+ }
+
+ /* Call the internal function with NULL, just to get bytes we need */
+ Int_EnumDependentServicesW(hServicesKey,
+ lpService,
+ SERVICE_ACTIVE,
+ NULL,
+ &pcbBytesNeeded,
+ &dwServicesReturned);
+
+ /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service*/
+ if (pcbBytesNeeded)
+ {
+ DPRINT("Deletion failed due to running dependencies.\n");
+ RegCloseKey(hServicesKey);
+ return ERROR_SUCCESS;
+ }
+
+ /* There are no references and no runnning dependencies,
+ it is now safe to delete the service */
+
+ /* Delete the Service Key */
+ dwError = RegDeleteKeyW(hServicesKey,
+ lpService->lpServiceName);
+
+ RegCloseKey(hServicesKey);
+
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT("Failed to Delete the Service Registry key\n");
+ return dwError;
+ }
+
+ /* Delete the Service */
+ ScmDeleteServiceRecord(lpService);
+ }
+ }
+
+ DPRINT("RCloseServiceHandle() done\n");
+ return ERROR_SUCCESS;
+ }
+
+ DPRINT("Invalid handle tag (Tag %lx)\n", hManager->Handle.Tag);
+
+ return ERROR_INVALID_HANDLE;
+}
+
+
+/* Function 1 */
+DWORD RControlService(
+ SC_RPC_HANDLE hService,
+ DWORD dwControl,
+ LPSERVICE_STATUS lpServiceStatus)
+{
+ PSERVICE_HANDLE hSvc;
+ PSERVICE lpService;
+ ACCESS_MASK DesiredAccess;
+ DWORD dwError = ERROR_SUCCESS;
+ DWORD pcbBytesNeeded = 0;
+ DWORD dwServicesReturned = 0;
++ DWORD dwControlsAccepted;
++ DWORD dwCurrentState;
+ HKEY hServicesKey = NULL;
+
+ DPRINT("RControlService() called\n");
+
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
+
+ /* Check the service handle */
+ hSvc = ScmGetServiceFromHandle(hService);
+ if (hSvc == NULL)
+ {
+ DPRINT1("Invalid service handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+
+ /* Check the service entry point */
+ lpService = hSvc->ServiceEntry;
+ if (lpService == NULL)
+ {
+ DPRINT1("lpService == NULL!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ /* Check access rights */
+ switch (dwControl)
+ {
+ case SERVICE_CONTROL_STOP:
+ DesiredAccess = SERVICE_STOP;
+ break;
+
+ case SERVICE_CONTROL_PAUSE:
+ case SERVICE_CONTROL_CONTINUE:
+ DesiredAccess = SERVICE_PAUSE_CONTINUE;
+ break;
+
+ case SERVICE_INTERROGATE:
+ DesiredAccess = SERVICE_INTERROGATE;
+ break;
+
+ default:
+ if (dwControl >= 128 && dwControl <= 255)
+ DesiredAccess = SERVICE_USER_DEFINED_CONTROL;
+ else
+ DesiredAccess = SERVICE_QUERY_CONFIG |
+ SERVICE_CHANGE_CONFIG |
+ SERVICE_QUERY_STATUS |
+ SERVICE_START |
+ SERVICE_PAUSE_CONTINUE;
+ break;
+ }
+
+ if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+ DesiredAccess))
+ return ERROR_ACCESS_DENIED;
+
+ if (dwControl == SERVICE_CONTROL_STOP)
+ {
+ /* Check if the service has dependencies running as windows
+ doesn't stop a service that does */
+
+ /* Open the Services Reg key */
+ dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ L"System\\CurrentControlSet\\Services",
+ 0,
+ KEY_READ,
+ &hServicesKey);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT("Failed to open services key\n");
+ return dwError;
+ }
+
+ /* Call the internal function with NULL, just to get bytes we need */
+ Int_EnumDependentServicesW(hServicesKey,
+ lpService,
+ SERVICE_ACTIVE,
+ NULL,
+ &pcbBytesNeeded,
+ &dwServicesReturned);
+
+ RegCloseKey(hServicesKey);
+
+ /* If pcbBytesNeeded is not zero then there are services running that
+ are dependent on this service */
+ if (pcbBytesNeeded != 0)
+ {
+ DPRINT("Service has running dependencies. Failed to stop service.\n");
+ return ERROR_DEPENDENT_SERVICES_RUNNING;
+ }
+ }
+
+ if (lpService->Status.dwServiceType & SERVICE_DRIVER)
+ {
+ /* Send control code to the driver */
+ dwError = ScmControlDriver(lpService,
+ dwControl,
+ lpServiceStatus);
+ }
+ else
+ {
++ dwControlsAccepted = lpService->Status.dwControlsAccepted;
++ dwCurrentState = lpService->Status.dwCurrentState;
++
++ /* Check the current state before sending a control request */
++ switch (dwCurrentState)
++ {
++ case SERVICE_STOP_PENDING:
++ case SERVICE_STOPPED:
++ return ERROR_SERVICE_CANNOT_ACCEPT_CTRL;
++
++ case SERVICE_START_PENDING:
++ switch (dwControl)
++ {
++ case SERVICE_CONTROL_STOP:
++ break;
++
++ case SERVICE_CONTROL_INTERROGATE:
++ RtlCopyMemory(lpServiceStatus,
++ &lpService->Status,
++ sizeof(SERVICE_STATUS));
++ return ERROR_SUCCESS;
++
++ default:
++ return ERROR_SERVICE_CANNOT_ACCEPT_CTRL;
++ }
++ break;
++ }
++
++ /* Check if the control code is acceptable to the service */
++ switch (dwControl)
++ {
++ case SERVICE_CONTROL_STOP:
++ if ((dwControlsAccepted & SERVICE_ACCEPT_STOP) == 0)
++ return ERROR_INVALID_SERVICE_CONTROL;
++ break;
++
++ case SERVICE_CONTROL_PAUSE:
++ case SERVICE_CONTROL_CONTINUE:
++ if ((dwControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE) == 0)
++ return ERROR_INVALID_SERVICE_CONTROL;
++ break;
++ }
++
+ /* Send control code to the service */
+ dwError = ScmControlService(lpService,
+ dwControl);
+
+ /* Return service status information */
+ RtlCopyMemory(lpServiceStatus,
+ &lpService->Status,
+ sizeof(SERVICE_STATUS));
+ }
+
+ if ((dwError == ERROR_SUCCESS) && (pcbBytesNeeded))
+ dwError = ERROR_DEPENDENT_SERVICES_RUNNING;
+
+ if (dwError == ERROR_SUCCESS &&
+ dwControl == SERVICE_CONTROL_STOP &&
+ lpServiceStatus->dwCurrentState == SERVICE_STOPPED)
+ {
+ lpService->ProcessId = 0; /* FIXME */
+ lpService->ThreadId = 0;
+ }
+
+
+ return dwError;
+}
+
+
+/* Function 2 */
+DWORD RDeleteService(
+ SC_RPC_HANDLE hService)
+{
+ PSERVICE_HANDLE hSvc;
+ PSERVICE lpService;
+ DWORD dwError;
+
+ DPRINT("RDeleteService() called\n");
+
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
+
+ hSvc = ScmGetServiceFromHandle(hService);
+ if (hSvc == NULL)
+ {
+ DPRINT1("Invalid service handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+ DELETE))
+ return ERROR_ACCESS_DENIED;
+
+ lpService = hSvc->ServiceEntry;
+ if (lpService == NULL)
+ {
+ DPRINT("lpService == NULL!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ /* FIXME: Acquire service database lock exclusively */
+
+ if (lpService->bDeleted)
+ {
+ DPRINT("The service has already been marked for delete!\n");
+ return ERROR_SERVICE_MARKED_FOR_DELETE;
+ }
+
+ /* Mark service for delete */
+ lpService->bDeleted = TRUE;
+
+ dwError = ScmMarkServiceForDelete(lpService);
+
+ /* FIXME: Release service database lock */
+
+ DPRINT("RDeleteService() done\n");
+
+ return dwError;
+}
+
+
+/* Function 3 */
+DWORD RLockServiceDatabase(
+ SC_RPC_HANDLE hSCManager,
+ LPSC_RPC_LOCK lpLock)
+{
+ PMANAGER_HANDLE hMgr;
+
+ DPRINT("RLockServiceDatabase() called\n");
+
+ *lpLock = 0;
+
+ hMgr = ScmGetServiceManagerFromHandle(hSCManager);
+ if (hMgr == NULL)
+ {
+ DPRINT1("Invalid service manager handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ if (!RtlAreAllAccessesGranted(hMgr->Handle.DesiredAccess,
+ SC_MANAGER_LOCK))
+ return ERROR_ACCESS_DENIED;
+
+// return ScmLockDatabase(0, hMgr->0xC, hLock);
+
+ /* FIXME: Lock the database */
+ *lpLock = (SC_RPC_LOCK)0x12345678; /* Dummy! */
+
+ return ERROR_SUCCESS;
+}
+
+
+/* Function 4 */
+DWORD RQueryServiceObjectSecurity(
+ SC_RPC_HANDLE hService,
+ SECURITY_INFORMATION dwSecurityInformation,
+ LPBYTE lpSecurityDescriptor,
+ DWORD cbBufSize,
+ LPBOUNDED_DWORD_256K pcbBytesNeeded)
+{
+ PSERVICE_HANDLE hSvc;
+ PSERVICE lpService;
+ ULONG DesiredAccess = 0;
+ NTSTATUS Status;
+ DWORD dwBytesNeeded;
+ DWORD dwError;
+
+
+ SECURITY_DESCRIPTOR ObjectDescriptor;
+
+ DPRINT("RQueryServiceObjectSecurity() called\n");
+
+ hSvc = ScmGetServiceFromHandle(hService);
+ if (hSvc == NULL)
+ {
+ DPRINT1("Invalid service handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ if (dwSecurityInformation & (DACL_SECURITY_INFORMATION ||
+ GROUP_SECURITY_INFORMATION ||
+ OWNER_SECURITY_INFORMATION))
+ DesiredAccess |= READ_CONTROL;
+
+ if (dwSecurityInformation & SACL_SECURITY_INFORMATION)
+ DesiredAccess |= ACCESS_SYSTEM_SECURITY;
+
+ if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+ DesiredAccess))
+ {
+ DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ lpService = hSvc->ServiceEntry;
+ if (lpService == NULL)
+ {
+ DPRINT("lpService == NULL!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ /* FIXME: Lock the service list */
+
+ /* hack */
+ Status = RtlCreateSecurityDescriptor(&ObjectDescriptor, SECURITY_DESCRIPTOR_REVISION);
+
+ Status = RtlQuerySecurityObject(&ObjectDescriptor /* lpService->lpSecurityDescriptor */,
+ dwSecurityInformation,
+ (PSECURITY_DESCRIPTOR)lpSecurityDescriptor,
+ cbBufSize,
+ &dwBytesNeeded);
+
+ /* FIXME: Unlock the service list */
+
+ if (NT_SUCCESS(Status))
+ {
+ *pcbBytesNeeded = dwBytesNeeded;
+ dwError = STATUS_SUCCESS;
+ }
+ else if (Status == STATUS_BUFFER_TOO_SMALL)
+ {
+ *pcbBytesNeeded = dwBytesNeeded;
+ dwError = ERROR_INSUFFICIENT_BUFFER;
+ }
+ else if (Status == STATUS_BAD_DESCRIPTOR_FORMAT)
+ {
+ dwError = ERROR_GEN_FAILURE;
+ }
+ else
+ {
+ dwError = RtlNtStatusToDosError(Status);
+ }
+
+ return dwError;
+}
+
+
+/* Function 5 */
+DWORD RSetServiceObjectSecurity(
+ SC_RPC_HANDLE hService,
+ DWORD dwSecurityInformation,
+ LPBYTE lpSecurityDescriptor,
+ DWORD dwSecuityDescriptorSize)
+{
+ PSERVICE_HANDLE hSvc;
+ PSERVICE lpService;
+ ULONG DesiredAccess = 0;
+ /* HANDLE hToken = NULL; */
+ HKEY hServiceKey;
+ /* NTSTATUS Status; */
+ DWORD dwError;
+
+ DPRINT("RSetServiceObjectSecurity() called\n");
+
+ hSvc = ScmGetServiceFromHandle(hService);
+ if (hSvc == NULL)
+ {
+ DPRINT1("Invalid service handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ if (dwSecurityInformation == 0 ||
+ dwSecurityInformation & ~(OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION
+ | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION))
+ return ERROR_INVALID_PARAMETER;
+
+ if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR)lpSecurityDescriptor))
+ return ERROR_INVALID_PARAMETER;
+
+ if (dwSecurityInformation & SACL_SECURITY_INFORMATION)
+ DesiredAccess |= ACCESS_SYSTEM_SECURITY;
+
+ if (dwSecurityInformation & DACL_SECURITY_INFORMATION)
+ DesiredAccess |= WRITE_DAC;
+
+ if (dwSecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION))
+ DesiredAccess |= WRITE_OWNER;
+
+ if ((dwSecurityInformation & OWNER_SECURITY_INFORMATION) &&
+ (((PISECURITY_DESCRIPTOR)lpSecurityDescriptor)->Owner == NULL))
+ return ERROR_INVALID_PARAMETER;
+
+ if ((dwSecurityInformation & GROUP_SECURITY_INFORMATION) &&
+ (((PISECURITY_DESCRIPTOR)lpSecurityDescriptor)->Group == NULL))
+ return ERROR_INVALID_PARAMETER;
+
+ if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+ DesiredAccess))
+ {
+ DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ lpService = hSvc->ServiceEntry;
+ if (lpService == NULL)
+ {
+ DPRINT("lpService == NULL!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ if (lpService->bDeleted)
+ return ERROR_SERVICE_MARKED_FOR_DELETE;
+
+#if 0
+ RpcImpersonateClient(NULL);
+
+ Status = NtOpenThreadToken(NtCurrentThread(),
+ 8,
+ TRUE,
+ &hToken);
+ if (!NT_SUCCESS(Status))
+ return RtlNtStatusToDosError(Status);
+
+ RpcRevertToSelf();
+
+ /* FIXME: Lock service database */
+
+ Status = RtlSetSecurityObject(dwSecurityInformation,
+ (PSECURITY_DESCRIPTOR)lpSecurityDescriptor,
+ &lpService->lpSecurityDescriptor,
+ &ScmServiceMapping,
+ hToken);
+ if (!NT_SUCCESS(Status))
+ {
+ dwError = RtlNtStatusToDosError(Status);
+ goto Done;
+ }
+#endif
+
+ dwError = ScmOpenServiceKey(lpService->lpServiceName,
+ READ_CONTROL | KEY_CREATE_SUB_KEY | KEY_SET_VALUE,
+ &hServiceKey);
+ if (dwError != ERROR_SUCCESS)
+ goto Done;
+
+ UNIMPLEMENTED;
+ dwError = ERROR_SUCCESS;
+// dwError = ScmWriteSecurityDescriptor(hServiceKey,
+// lpService->lpSecurityDescriptor);
+
+ RegFlushKey(hServiceKey);
+ RegCloseKey(hServiceKey);
+
+Done:
+
+#if 0
+ if (hToken != NULL)
+ NtClose(hToken);
+#endif
+
+ /* FIXME: Unlock service database */
+
+ DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError);
+
+ return dwError;
+}
+
+
+/* Function 6 */
+DWORD RQueryServiceStatus(
+ SC_RPC_HANDLE hService,
+ LPSERVICE_STATUS lpServiceStatus)
+{
+ PSERVICE_HANDLE hSvc;
+ PSERVICE lpService;
+
+ DPRINT("RQueryServiceStatus() called\n");
+
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
+
+ hSvc = ScmGetServiceFromHandle(hService);
+ if (hSvc == NULL)
+ {
+ DPRINT1("Invalid service handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+ SERVICE_QUERY_STATUS))
+ {
+ DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ lpService = hSvc->ServiceEntry;
+ if (lpService == NULL)
+ {
+ DPRINT("lpService == NULL!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ ScmLockDatabaseShared();
+
+ /* Return service status information */
+ RtlCopyMemory(lpServiceStatus,
+ &lpService->Status,
+ sizeof(SERVICE_STATUS));
+
+ ScmUnlockDatabase();
+
+ return ERROR_SUCCESS;
+}
+
+
+static BOOL
+ScmIsValidServiceState(DWORD dwCurrentState)
+{
+ switch (dwCurrentState)
+ {
+ case SERVICE_STOPPED:
+ case SERVICE_START_PENDING:
+ case SERVICE_STOP_PENDING:
+ case SERVICE_RUNNING:
+ case SERVICE_CONTINUE_PENDING:
+ case SERVICE_PAUSE_PENDING:
+ case SERVICE_PAUSED:
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+
+/* Function 7 */
+DWORD RSetServiceStatus(
+ RPC_SERVICE_STATUS_HANDLE hServiceStatus,
+ LPSERVICE_STATUS lpServiceStatus)
+{
+ PSERVICE lpService;
+
+ DPRINT("RSetServiceStatus() called\n");
+ DPRINT("hServiceStatus = %p\n", hServiceStatus);
+ DPRINT("dwServiceType = %lu\n", lpServiceStatus->dwServiceType);
+ DPRINT("dwCurrentState = %lu\n", lpServiceStatus->dwCurrentState);
+ DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus->dwControlsAccepted);
+ DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus->dwWin32ExitCode);
+ DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus->dwServiceSpecificExitCode);
+ DPRINT("dwCheckPoint = %lu\n", lpServiceStatus->dwCheckPoint);
+ DPRINT("dwWaitHint = %lu\n", lpServiceStatus->dwWaitHint);
+
+ if (hServiceStatus == 0)
+ {
+ DPRINT("hServiceStatus == NULL!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ lpService = (PSERVICE)hServiceStatus;
+ if (lpService == NULL)
+ {
+ DPRINT("lpService == NULL!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ /* Check current state */
+ if (!ScmIsValidServiceState(lpServiceStatus->dwCurrentState))
+ {
+ DPRINT("Invalid service state!\n");
+ return ERROR_INVALID_DATA;
+ }
+
+ /* Check service type */
+ if (!(lpServiceStatus->dwServiceType & SERVICE_WIN32) &&
+ (lpServiceStatus->dwServiceType & SERVICE_DRIVER))
+ {
+ DPRINT("Invalid service type!\n");
+ return ERROR_INVALID_DATA;
+ }
+
+ /* Check accepted controls */
+ if (lpServiceStatus->dwControlsAccepted & ~0xFF)
+ {
+ DPRINT("Invalid controls accepted!\n");
+ return ERROR_INVALID_DATA;
+ }
+
+ ScmLockDatabaseExclusive();
+
+ RtlCopyMemory(&lpService->Status,
+ lpServiceStatus,
+ sizeof(SERVICE_STATUS));
+
+ ScmUnlockDatabase();
+
+ DPRINT("Set %S to %lu\n", lpService->lpDisplayName, lpService->Status.dwCurrentState);
+ DPRINT("RSetServiceStatus() done\n");
+
+ return ERROR_SUCCESS;
+}
+
+
+/* Function 8 */
+DWORD RUnlockServiceDatabase(
+ LPSC_RPC_LOCK Lock)
+{
+ UNIMPLEMENTED;
+ return ERROR_SUCCESS;
+}
+
+
+/* Function 9 */
+DWORD RNotifyBootConfigStatus(
+ SVCCTL_HANDLEW lpMachineName,
+ DWORD BootAcceptable)
+{
+ UNIMPLEMENTED;
+ return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 10 */
+DWORD RI_ScSetServiceBitsW(
+ RPC_SERVICE_STATUS_HANDLE hServiceStatus,
+ DWORD dwServiceBits,
+ int bSetBitsOn,
+ int bUpdateImmediately,
+ wchar_t *lpString)
+{
+ UNIMPLEMENTED;
+ return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 11 */
+DWORD RChangeServiceConfigW(
+ SC_RPC_HANDLE hService,
+ DWORD dwServiceType,
+ DWORD dwStartType,
+ DWORD dwErrorControl,
+ LPWSTR lpBinaryPathName,
+ LPWSTR lpLoadOrderGroup,
+ LPDWORD lpdwTagId,
+ LPBYTE lpDependencies,
+ DWORD dwDependSize,
+ LPWSTR lpServiceStartName,
+ LPBYTE lpPassword,
+ DWORD dwPwSize,
+ LPWSTR lpDisplayName)
+{
+ DWORD dwError = ERROR_SUCCESS;
+ PSERVICE_HANDLE hSvc;
+ PSERVICE lpService = NULL;
+ HKEY hServiceKey = NULL;
+ LPWSTR lpDisplayNameW = NULL;
+
+ DPRINT("RChangeServiceConfigW() called\n");
+ DPRINT("dwServiceType = %lu\n", dwServiceType);
+ DPRINT("dwStartType = %lu\n", dwStartType);
+ DPRINT("dwErrorControl = %lu\n", dwErrorControl);
+ DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName);
+ DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup);
+ DPRINT("lpDisplayName = %S\n", lpDisplayName);
+
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
+
+ hSvc = ScmGetServiceFromHandle(hService);
+ if (hSvc == NULL)
+ {
+ DPRINT1("Invalid service handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+ SERVICE_CHANGE_CONFIG))
+ {
+ DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ lpService = hSvc->ServiceEntry;
+ if (lpService == NULL)
+ {
+ DPRINT("lpService == NULL!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ /* FIXME: Lock database exclusively */
+
+ if (lpService->bDeleted)
+ {
+ /* FIXME: Unlock database */
+ DPRINT("The service has already been marked for delete!\n");
+ return ERROR_SERVICE_MARKED_FOR_DELETE;
+ }
+
+ /* Open the service key */
+ dwError = ScmOpenServiceKey(lpService->szServiceName,
+ KEY_SET_VALUE,
+ &hServiceKey);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ /* Write service data to the registry */
+ /* Set the display name */
+ if (lpDisplayName != NULL && *lpDisplayName != 0)
+ {
+ RegSetValueExW(hServiceKey,
+ L"DisplayName",
+ 0,
+ REG_SZ,
+ (LPBYTE)lpDisplayName,
+ (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
+
+ /* Update the display name */
+ lpDisplayNameW = (LPWSTR)HeapAlloc(GetProcessHeap(),
+ 0,
+ (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
+ if (lpDisplayNameW == NULL)
+ {
+ dwError = ERROR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+
+ if (lpService->lpDisplayName != lpService->lpServiceName)
+ HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName);
+
+ lpService->lpDisplayName = lpDisplayNameW;
+ }
+
+ if (dwServiceType != SERVICE_NO_CHANGE)
+ {
+ /* Set the service type */
+ dwError = RegSetValueExW(hServiceKey,
+ L"Type",
+ 0,
+ REG_DWORD,
+ (LPBYTE)&dwServiceType,
+ sizeof(DWORD));
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ lpService->Status.dwServiceType = dwServiceType;
+ }
+
+ if (dwStartType != SERVICE_NO_CHANGE)
+ {
+ /* Set the start value */
+ dwError = RegSetValueExW(hServiceKey,
+ L"Start",
+ 0,
+ REG_DWORD,
+ (LPBYTE)&dwStartType,
+ sizeof(DWORD));
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ lpService->dwStartType = dwStartType;
+ }
+
+ if (dwErrorControl != SERVICE_NO_CHANGE)
+ {
+ /* Set the error control value */
+ dwError = RegSetValueExW(hServiceKey,
+ L"ErrorControl",
+ 0,
+ REG_DWORD,
+ (LPBYTE)&dwErrorControl,
+ sizeof(DWORD));
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ lpService->dwErrorControl = dwErrorControl;
+ }
+
+#if 0
+ /* FIXME: set the new ImagePath value */
+
+ /* Set the image path */
+ if (dwServiceType & SERVICE_WIN32)
+ {
+ if (lpBinaryPathName != NULL && *lpBinaryPathName != 0)
+ {
+ dwError = RegSetValueExW(hServiceKey,
+ L"ImagePath",
+ 0,
+ REG_EXPAND_SZ,
+ (LPBYTE)lpBinaryPathName,
+ (wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR));
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
+ }
+ else if (dwServiceType & SERVICE_DRIVER)
+ {
+ if (lpImagePath != NULL && *lpImagePath != 0)
+ {
+ dwError = RegSetValueExW(hServiceKey,
+ L"ImagePath",
+ 0,
+ REG_EXPAND_SZ,
+ (LPBYTE)lpImagePath,
+ (wcslen(lpImagePath) + 1) *sizeof(WCHAR));
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
+ }
+#endif
+
+ /* Set the group name */
+ if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
+ {
+ dwError = RegSetValueExW(hServiceKey,
+ L"Group",
+ 0,
+ REG_SZ,
+ (LPBYTE)lpLoadOrderGroup,
+ (wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR));
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ dwError = ScmSetServiceGroup(lpService,
+ lpLoadOrderGroup);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
+
+ if (lpdwTagId != NULL)
+ {
+ dwError = ScmAssignNewTag(lpService);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ dwError = RegSetValueExW(hServiceKey,
+ L"Tag",
+ 0,
+ REG_DWORD,
+ (LPBYTE)&lpService->dwTag,
+ sizeof(DWORD));
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ *lpdwTagId = lpService->dwTag;
+ }
+
+ /* Write dependencies */
+ if (lpDependencies != NULL && *lpDependencies != 0)
+ {
+ dwError = ScmWriteDependencies(hServiceKey,
+ (LPWSTR)lpDependencies,
+ dwDependSize);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
+
+ if (lpPassword != NULL)
+ {
+ /* FIXME: Write password */
+ }
+
+ /* FIXME: Unlock database */
+
+done:
+ if (hServiceKey != NULL)
+ RegCloseKey(hServiceKey);
+
+ DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError);
+
+ return dwError;
+}
+
+
+/* Create a path suitable for the bootloader out of the full path */
+DWORD
+ScmConvertToBootPathName(wchar_t *CanonName, wchar_t **RelativeName)
+{
+ DWORD ServiceNameLen, BufferSize, ExpandedLen;
+ WCHAR Dest;
+ WCHAR *Expanded;
+ UNICODE_STRING NtPathName, SystemRoot, LinkTarget;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+ HANDLE SymbolicLinkHandle;
+
+ DPRINT("ScmConvertToBootPathName %S\n", CanonName);
+
+ ServiceNameLen = wcslen(CanonName);
+
+ /* First check, if it's already good */
+ if (ServiceNameLen > 12 &&
+ !_wcsnicmp(L"\\SystemRoot\\", CanonName, 12))
+ {
+ *RelativeName = LocalAlloc(LMEM_ZEROINIT, ServiceNameLen * sizeof(WCHAR) + sizeof(WCHAR));
+ if (*RelativeName == NULL)
+ {
+ DPRINT("Error allocating memory for boot driver name!\n");
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ /* Copy it */
+ wcscpy(*RelativeName, CanonName);
+
+ DPRINT("Bootdriver name %S\n", *RelativeName);
+ return ERROR_SUCCESS;
+ }
+
+ /* If it has %SystemRoot% prefix, substitute it to \System*/
+ if (ServiceNameLen > 13 &&
+ !_wcsnicmp(L"%SystemRoot%\\", CanonName, 13))
+ {
+ /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
+ *RelativeName = LocalAlloc(LMEM_ZEROINIT, ServiceNameLen * sizeof(WCHAR));
+
+ if (*RelativeName == NULL)
+ {
+ DPRINT("Error allocating memory for boot driver name!\n");
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ /* Copy it */
+ wcscpy(*RelativeName, L"\\SystemRoot\\");
+ wcscat(*RelativeName, CanonName + 13);
+
+ DPRINT("Bootdriver name %S\n", *RelativeName);
+ return ERROR_SUCCESS;
+ }
+
+ /* Get buffer size needed for expanding env strings */
+ BufferSize = ExpandEnvironmentStringsW(L"%SystemRoot%\\", &Dest, 1);
+
+ if (BufferSize <= 1)
+ {
+ DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
+ return ERROR_INVALID_ENVIRONMENT;
+ }
+
+ /* Allocate memory, since the size is known now */
+ Expanded = LocalAlloc(LMEM_ZEROINIT, BufferSize * sizeof(WCHAR) + sizeof(WCHAR));
+ if (!Expanded)
+ {
+ DPRINT("Error allocating memory for boot driver name!\n");
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ /* Expand it */
+ if (ExpandEnvironmentStringsW(L"%SystemRoot%\\", Expanded, BufferSize) >
+ BufferSize)
+ {
+ DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
+ LocalFree(Expanded);
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ /* Convert to NY-style path */
+ if (!RtlDosPathNameToNtPathName_U(Expanded, &NtPathName, NULL, NULL))
+ {
+ DPRINT("Error during a call to RtlDosPathNameToNtPathName_U()\n");
+ return ERROR_INVALID_ENVIRONMENT;
+ }
+
+ DPRINT("Converted to NT-style %wZ\n", &NtPathName);
+
+ /* No need to keep the dos-path anymore */
+ LocalFree(Expanded);
+
+ /* Copy it to the allocated place */
+ Expanded = LocalAlloc(LMEM_ZEROINIT, NtPathName.Length + sizeof(WCHAR));
+ if (!Expanded)
+ {
+ DPRINT("Error allocating memory for boot driver name!\n");
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ ExpandedLen = NtPathName.Length / sizeof(WCHAR);
+ wcsncpy(Expanded, NtPathName.Buffer, ExpandedLen);
+ Expanded[ExpandedLen] = 0;
+
+ if (ServiceNameLen > ExpandedLen &&
+ !_wcsnicmp(Expanded, CanonName, ExpandedLen))
+ {
+ /* Only \SystemRoot\ is missing */
+ *RelativeName = LocalAlloc(LMEM_ZEROINIT,
+ (ServiceNameLen - ExpandedLen) * sizeof(WCHAR) + 13*sizeof(WCHAR));
+ if (*RelativeName == NULL)
+ {
+ DPRINT("Error allocating memory for boot driver name!\n");
+ LocalFree(Expanded);
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ wcscpy(*RelativeName, L"\\SystemRoot\\");
+ wcscat(*RelativeName, CanonName + ExpandedLen);
+
+ RtlFreeUnicodeString(&NtPathName);
+ return ERROR_SUCCESS;
+ }
+
+ /* The most complex case starts here */
+ RtlInitUnicodeString(&SystemRoot, L"\\SystemRoot");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &SystemRoot,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ /* Open this symlink */
+ Status = NtOpenSymbolicLinkObject(&SymbolicLinkHandle, SYMBOLIC_LINK_QUERY, &ObjectAttributes);
+
+ if (NT_SUCCESS(Status))
+ {
+ LinkTarget.Length = 0;
+ LinkTarget.MaximumLength = 0;
+
+ DPRINT("Opened symbolic link object\n");
+
+ Status = NtQuerySymbolicLinkObject(SymbolicLinkHandle, &LinkTarget, &BufferSize);
+ if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_TOO_SMALL)
+ {
+ /* Check if required buffer size is sane */
+ if (BufferSize > 0xFFFD)
+ {
+ DPRINT("Too large buffer required\n");
+ *RelativeName = 0;
+
+ if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
+ LocalFree(Expanded);
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ /* Alloc the string */
+ LinkTarget.Buffer = LocalAlloc(LMEM_ZEROINIT, BufferSize + sizeof(WCHAR));
+ if (!LinkTarget.Buffer)
+ {
+ DPRINT("Unable to alloc buffer\n");
+ if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
+ LocalFree(Expanded);
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ /* Do a real query now */
+ LinkTarget.Length = BufferSize;
+ LinkTarget.MaximumLength = LinkTarget.Length + sizeof(WCHAR);
+
+ Status = NtQuerySymbolicLinkObject(SymbolicLinkHandle, &LinkTarget, &BufferSize);
+ if (NT_SUCCESS(Status))
+ {
+ DPRINT("LinkTarget: %wZ\n", &LinkTarget);
+
+ ExpandedLen = LinkTarget.Length / sizeof(WCHAR);
+ if ((ServiceNameLen > ExpandedLen) &&
+ !_wcsnicmp(LinkTarget.Buffer, CanonName, ExpandedLen))
+ {
+ *RelativeName = LocalAlloc(LMEM_ZEROINIT,
+ (ServiceNameLen - ExpandedLen) * sizeof(WCHAR) + 13*sizeof(WCHAR));
+
+ if (*RelativeName == NULL)
+ {
+ DPRINT("Unable to alloc buffer\n");
+ if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
+ LocalFree(Expanded);
+ RtlFreeUnicodeString(&NtPathName);
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ /* Copy it over, substituting the first part
+ with SystemRoot */
+ wcscpy(*RelativeName, L"\\SystemRoot\\");
+ wcscat(*RelativeName, CanonName+ExpandedLen+1);
+
+ /* Cleanup */
+ if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
+ LocalFree(Expanded);
+ RtlFreeUnicodeString(&NtPathName);
+
+ /* Return success */
+ return ERROR_SUCCESS;
+ }
+ else
+ {
+ if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
+ LocalFree(Expanded);
+ RtlFreeUnicodeString(&NtPathName);
+ return ERROR_INVALID_PARAMETER;
+ }
+ }
+ else
+ {
+ DPRINT("Error, Status = %08X\n", Status);
+ if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
+ LocalFree(Expanded);
+ RtlFreeUnicodeString(&NtPathName);
+ return ERROR_INVALID_PARAMETER;
+ }
+ }
+ else
+ {
+ DPRINT("Error, Status = %08X\n", Status);
+ if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
+ LocalFree(Expanded);
+ RtlFreeUnicodeString(&NtPathName);
+ return ERROR_INVALID_PARAMETER;
+ }
+ }
+ else
+ {
+ DPRINT("Error, Status = %08X\n", Status);
+ LocalFree(Expanded);
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ /* Failure */
+ *RelativeName = NULL;
+ return ERROR_INVALID_PARAMETER;
+}
+
+DWORD
+ScmCanonDriverImagePath(DWORD dwStartType,
+ const wchar_t *lpServiceName,
+ wchar_t **lpCanonName)
+{
+ DWORD ServiceNameLen, Result;
+ UNICODE_STRING NtServiceName;
+ WCHAR *RelativeName;
+ const WCHAR *SourceName = lpServiceName;
+
+ /* Calculate the length of the service's name */
+ ServiceNameLen = wcslen(lpServiceName);
+
+ /* 12 is wcslen(L"\\SystemRoot\\") */
+ if (ServiceNameLen > 12 &&
+ !_wcsnicmp(L"\\SystemRoot\\", lpServiceName, 12))
+ {
+ /* SystemRoot prefix is already included */
+
+ *lpCanonName = LocalAlloc(LMEM_ZEROINIT, ServiceNameLen * sizeof(WCHAR) + sizeof(WCHAR));
+
+ if (*lpCanonName == NULL)
+ {
+ DPRINT("Error allocating memory for canonized service name!\n");
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ /* If it's a boot-time driver, it must be systemroot relative */
+ if (dwStartType == SERVICE_BOOT_START)
+ SourceName += 12;
+
+ /* Copy it */
+ wcscpy(*lpCanonName, SourceName);
+
+ DPRINT("Canonicalized name %S\n", *lpCanonName);
+ return NO_ERROR;
+ }
+
+ /* Check if it has %SystemRoot% (len=13) */
+ if (ServiceNameLen > 13 &&
+ !_wcsnicmp(L"%%SystemRoot%%\\", lpServiceName, 13))
+ {
+ /* Substitute %SystemRoot% with \\SystemRoot\\ */
+ *lpCanonName = LocalAlloc(LMEM_ZEROINIT, ServiceNameLen * sizeof(WCHAR) + sizeof(WCHAR));
+
+ if (*lpCanonName == NULL)
+ {
+ DPRINT("Error allocating memory for canonized service name!\n");
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ /* If it's a boot-time driver, it must be systemroot relative */
+ if (dwStartType == SERVICE_BOOT_START)
+ wcscpy(*lpCanonName, L"\\SystemRoot\\");
+
+ wcscat(*lpCanonName, lpServiceName + 13);
+
+ DPRINT("Canonicalized name %S\n", *lpCanonName);
+ return NO_ERROR;
+ }
+
+ /* Check if it's a relative path name */
+ if (lpServiceName[0] != L'\\' && lpServiceName[1] != L':')
+ {
+ *lpCanonName = LocalAlloc(LMEM_ZEROINIT, ServiceNameLen * sizeof(WCHAR) + sizeof(WCHAR));
+
+ if (*lpCanonName == NULL)
+ {
+ DPRINT("Error allocating memory for canonized service name!\n");
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ /* Just copy it over without changing */
+ wcscpy(*lpCanonName, lpServiceName);
+
+ return NO_ERROR;
+ }
+
+ /* It seems to be a DOS path, convert it */
+ if (!RtlDosPathNameToNtPathName_U(lpServiceName, &NtServiceName, NULL, NULL))
+ {
+ DPRINT("RtlDosPathNameToNtPathName_U() failed!\n");
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ *lpCanonName = LocalAlloc(LMEM_ZEROINIT, NtServiceName.Length + sizeof(WCHAR));
+
+ if (*lpCanonName == NULL)
+ {
+ DPRINT("Error allocating memory for canonized service name!\n");
+ RtlFreeUnicodeString(&NtServiceName);
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ /* Copy the string */
+ wcsncpy(*lpCanonName, NtServiceName.Buffer, NtServiceName.Length / sizeof(WCHAR));
+
+ /* The unicode string is not needed anymore */
+ RtlFreeUnicodeString(&NtServiceName);
+
+ if (dwStartType != SERVICE_BOOT_START)
+ {
+ DPRINT("Canonicalized name %S\n", *lpCanonName);
+ return NO_ERROR;
+ }
+
+ /* The service is boot-started, so must be relative */
+ Result = ScmConvertToBootPathName(*lpCanonName, &RelativeName);
+ if (Result)
+ {
+ /* There is a problem, free name and return */
+ LocalFree(*lpCanonName);
+ DPRINT("Error converting named!\n");
+ return Result;
+ }
+
+ ASSERT(RelativeName);
+
+ /* Copy that string */
+ wcscpy(*lpCanonName, RelativeName + 12);
+
+ /* Free the allocated buffer */
+ LocalFree(RelativeName);
+
+ DPRINT("Canonicalized name %S\n", *lpCanonName);
+
+ /* Success */
+ return NO_ERROR;
+}
+
+
+/* Function 12 */
+DWORD RCreateServiceW(
+ SC_RPC_HANDLE hSCManager,
+ LPCWSTR lpServiceName,
+ LPCWSTR lpDisplayName,
+ DWORD dwDesiredAccess,
+ DWORD dwServiceType,
+ DWORD dwStartType,
+ DWORD dwErrorControl,
+ LPCWSTR lpBinaryPathName,
+ LPCWSTR lpLoadOrderGroup,
+ LPDWORD lpdwTagId,
+ LPBYTE lpDependencies,
+ DWORD dwDependSize,
+ LPCWSTR lpServiceStartName,
+ LPBYTE lpPassword,
+ DWORD dwPwSize,
+ LPSC_RPC_HANDLE lpServiceHandle)
+{
+ PMANAGER_HANDLE hManager;
+ DWORD dwError = ERROR_SUCCESS;
+ PSERVICE lpService = NULL;
+ SC_HANDLE hServiceHandle = NULL;
+ LPWSTR lpImagePath = NULL;
+ HKEY hServiceKey = NULL;
+ LPWSTR lpObjectName;
+
+ DPRINT("RCreateServiceW() called\n");
+ DPRINT("lpServiceName = %S\n", lpServiceName);
+ DPRINT("lpDisplayName = %S\n", lpDisplayName);
+ DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess);
+ DPRINT("dwServiceType = %lu\n", dwServiceType);
+ DPRINT("dwStartType = %lu\n", dwStartType);
+ DPRINT("dwErrorControl = %lu\n", dwErrorControl);
+ DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName);
+ DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup);
+
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
+
+ hManager = ScmGetServiceManagerFromHandle(hSCManager);
+ if (hManager == NULL)
+ {
+ DPRINT1("Invalid service manager handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ /* Check access rights */
+ if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
+ SC_MANAGER_CREATE_SERVICE))
+ {
+ DPRINT("Insufficient access rights! 0x%lx\n",
+ hManager->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ if (wcslen(lpServiceName) == 0)
+ {
+ return ERROR_INVALID_NAME;
+ }
+
+ if (wcslen(lpBinaryPathName) == 0)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ if ((dwServiceType == (SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS)) &&
+ (lpServiceStartName))
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ if ((dwServiceType > SERVICE_WIN32_SHARE_PROCESS) &&
+ (dwServiceType != (SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS)) &&
+ (dwServiceType != (SERVICE_WIN32_SHARE_PROCESS | SERVICE_INTERACTIVE_PROCESS)))
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ if (dwStartType > SERVICE_DISABLED)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ lpService = ScmGetServiceEntryByName(lpServiceName);
+ if (lpService)
+ {
+ /* check if it is marked for deletion */
+ if (lpService->bDeleted)
+ return ERROR_SERVICE_MARKED_FOR_DELETE;
+ /* Return Error exist */
+ return ERROR_SERVICE_EXISTS;
+ }
+
+ if (lpDisplayName != NULL &&
+ ScmGetServiceEntryByDisplayName(lpDisplayName) != NULL)
+ return ERROR_DUPLICATE_SERVICE_NAME;
+
+ if (dwServiceType & SERVICE_DRIVER)
+ {
+ dwError = ScmCanonDriverImagePath(dwStartType,
+ lpBinaryPathName,
+ &lpImagePath);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
+ else
+ {
+ if (dwStartType == SERVICE_BOOT_START ||
+ dwStartType == SERVICE_SYSTEM_START)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+ }
+
+ /* Allocate a new service entry */
+ dwError = ScmCreateNewServiceRecord(lpServiceName,
+ &lpService);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ /* Fill the new service entry */
+ lpService->Status.dwServiceType = dwServiceType;
+ lpService->dwStartType = dwStartType;
+ lpService->dwErrorControl = dwErrorControl;
+
+ /* Fill the display name */
+ if (lpDisplayName != NULL &&
+ *lpDisplayName != 0 &&
+ _wcsicmp(lpService->lpDisplayName, lpDisplayName) != 0)
+ {
+ lpService->lpDisplayName = (WCHAR*) HeapAlloc(GetProcessHeap(), 0,
+ (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
+ if (lpService->lpDisplayName == NULL)
+ {
+ dwError = ERROR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+ wcscpy(lpService->lpDisplayName, lpDisplayName);
+ }
+
+ /* Assign the service to a group */
+ if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
+ {
+ dwError = ScmSetServiceGroup(lpService,
+ lpLoadOrderGroup);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
+
+ /* Assign a new tag */
+ if (lpdwTagId != NULL)
+ {
+ dwError = ScmAssignNewTag(lpService);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
+
+ /* Write service data to the registry */
+ /* Create the service key */
+ dwError = ScmCreateServiceKey(lpServiceName,
+ KEY_WRITE,
+ &hServiceKey);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ /* Set the display name */
+ if (lpDisplayName != NULL && *lpDisplayName != 0)
+ {
+ RegSetValueExW(hServiceKey,
+ L"DisplayName",
+ 0,
+ REG_SZ,
+ (LPBYTE)lpDisplayName,
+ (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
+ }
+
+ /* Set the service type */
+ dwError = RegSetValueExW(hServiceKey,
+ L"Type",
+ 0,
+ REG_DWORD,
+ (LPBYTE)&dwServiceType,
+ sizeof(DWORD));
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ /* Set the start value */
+ dwError = RegSetValueExW(hServiceKey,
+ L"Start",
+ 0,
+ REG_DWORD,
+ (LPBYTE)&dwStartType,
+ sizeof(DWORD));
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ /* Set the error control value */
+ dwError = RegSetValueExW(hServiceKey,
+ L"ErrorControl",
+ 0,
+ REG_DWORD,
+ (LPBYTE)&dwErrorControl,
+ sizeof(DWORD));
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ /* Set the image path */
+ if (dwServiceType & SERVICE_WIN32)
+ {
+ dwError = RegSetValueExW(hServiceKey,
+ L"ImagePath",
+ 0,
+ REG_EXPAND_SZ,
+ (LPBYTE)lpBinaryPathName,
+ (wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR));
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
+ else if (dwServiceType & SERVICE_DRIVER)
+ {
+ dwError = RegSetValueExW(hServiceKey,
+ L"ImagePath",
+ 0,
+ REG_EXPAND_SZ,
+ (LPBYTE)lpImagePath,
+ (wcslen(lpImagePath) + 1) * sizeof(WCHAR));
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
+
+ /* Set the group name */
+ if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
+ {
+ dwError = RegSetValueExW(hServiceKey,
+ L"Group",
+ 0,
+ REG_SZ,
+ (LPBYTE)lpLoadOrderGroup,
+ (wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR));
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
+
+ if (lpdwTagId != NULL)
+ {
+ dwError = RegSetValueExW(hServiceKey,
+ L"Tag",
+ 0,
+ REG_DWORD,
+ (LPBYTE)&lpService->dwTag,
+ sizeof(DWORD));
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
+
+ /* Write dependencies */
+ if (lpDependencies != NULL && *lpDependencies != 0)
+ {
+ dwError = ScmWriteDependencies(hServiceKey,
+ (LPWSTR)lpDependencies,
+ dwDependSize);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
+
+ /* Write service start name */
+ if (dwServiceType & SERVICE_WIN32)
+ {
+ lpObjectName = (lpServiceStartName != NULL) ? (LPWSTR)lpServiceStartName : L"LocalSystem";
+ dwError = RegSetValueExW(hServiceKey,
+ L"ObjectName",
+ 0,
+ REG_SZ,
+ (LPBYTE)lpObjectName,
+ (wcslen(lpObjectName) + 1) * sizeof(WCHAR));
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
+
+ if (lpPassword != NULL)
+ {
+ /* FIXME: Write password */
+ }
+
+ dwError = ScmCreateServiceHandle(lpService,
+ &hServiceHandle);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ dwError = ScmCheckAccess(hServiceHandle,
+ dwDesiredAccess);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ lpService->dwRefCount = 1;
+ DPRINT("CreateService - lpService->dwRefCount %u\n", lpService->dwRefCount);
+
+done:;
+ if (hServiceKey != NULL)
+ RegCloseKey(hServiceKey);
+
+ if (dwError == ERROR_SUCCESS)
+ {
+ DPRINT("hService %p\n", hServiceHandle);
+ *lpServiceHandle = (SC_RPC_HANDLE)hServiceHandle;
+
+ if (lpdwTagId != NULL)
+ *lpdwTagId = lpService->dwTag;
+ }
+ else
+ {
+ /* Release the display name buffer */
+ if (lpService->lpServiceName != NULL)
+ HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName);
+
+ if (hServiceHandle)
+ {
+ /* Remove the service handle */
+ HeapFree(GetProcessHeap(), 0, hServiceHandle);
+ }
+
+ if (lpService != NULL)
+ {
+ /* FIXME: remove the service entry */
+ }
+ }
+
+ if (lpImagePath != NULL)
+ HeapFree(GetProcessHeap(), 0, lpImagePath);
+
+ DPRINT("RCreateServiceW() done (Error %lu)\n", dwError);
+
+ return dwError;
+}
+
+
+/* Function 13 */
+DWORD REnumDependentServicesW(
+ SC_RPC_HANDLE hService,
+ DWORD dwServiceState,
+ LPBYTE lpServices,
+ DWORD cbBufSize,
+ LPBOUNDED_DWORD_256K pcbBytesNeeded,
+ LPBOUNDED_DWORD_256K lpServicesReturned)
+{
+ DWORD dwError = ERROR_SUCCESS;
+ DWORD dwServicesReturned = 0;
+ DWORD dwServiceCount;
+ HKEY hServicesKey = NULL;
+ PSERVICE_HANDLE hSvc;
+ PSERVICE lpService = NULL;
+ PSERVICE *lpServicesArray = NULL;
+ LPENUM_SERVICE_STATUSW lpServicesPtr = NULL;
+ LPWSTR lpStr;
+
+ *pcbBytesNeeded = 0;
+ *lpServicesReturned = 0;
+
+ DPRINT("REnumDependentServicesW() called\n");
+
+ hSvc = ScmGetServiceFromHandle(hService);
+ if (hSvc == NULL)
+ {
+ DPRINT1("Invalid service handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ lpService = hSvc->ServiceEntry;
+
+ /* Check access rights */
+ if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+ SC_MANAGER_ENUMERATE_SERVICE))
+ {
+ DPRINT("Insufficient access rights! 0x%lx\n",
+ hSvc->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ /* Open the Services Reg key */
+ dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ L"System\\CurrentControlSet\\Services",
+ 0,
+ KEY_READ,
+ &hServicesKey);
+ if (dwError != ERROR_SUCCESS)
+ return dwError;
+
+ /* First determine the bytes needed and get the number of dependent services */
+ dwError = Int_EnumDependentServicesW(hServicesKey,
+ lpService,
+ dwServiceState,
+ NULL,
+ pcbBytesNeeded,
+ &dwServicesReturned);
+ if (dwError != ERROR_SUCCESS)
+ goto Done;
+
+ /* If buffer size is less than the bytes needed or pointer is null */
+ if ((!lpServices) || (cbBufSize < *pcbBytesNeeded))
+ {
+ dwError = ERROR_MORE_DATA;
+ goto Done;
+ }
+
+ /* Allocate memory for array of service pointers */
+ lpServicesArray = HeapAlloc(GetProcessHeap(),
+ 0,
+ (dwServicesReturned + 1) * sizeof(PSERVICE));
+ if (!lpServicesArray)
+ {
+ DPRINT("Could not allocate a buffer!!\n");
+ dwError = ERROR_NOT_ENOUGH_MEMORY;
+ goto Done;
+ }
+
+ dwServicesReturned = 0;
+ *pcbBytesNeeded = 0;
+
+ dwError = Int_EnumDependentServicesW(hServicesKey,
+ lpService,
+ dwServiceState,
+ lpServicesArray,
+ pcbBytesNeeded,
+ &dwServicesReturned);
+ if (dwError != ERROR_SUCCESS)
+ {
+ goto Done;
+ }
+
+ lpServicesPtr = (LPENUM_SERVICE_STATUSW) lpServices;
+ lpStr = (LPWSTR)(lpServices + (dwServicesReturned * sizeof(ENUM_SERVICE_STATUSW)));
+
+ /* Copy EnumDepenedentService to Buffer */
+ for (dwServiceCount = 0; dwServiceCount < dwServicesReturned; dwServiceCount++)
+ {
+ lpService = lpServicesArray[dwServiceCount];
+
+ /* Copy status info */
+ memcpy(&lpServicesPtr->ServiceStatus,
+ &lpService->Status,
+ sizeof(SERVICE_STATUS));
+
+ /* Copy display name */
+ wcscpy(lpStr, lpService->lpDisplayName);
+ lpServicesPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices);
+ lpStr += (wcslen(lpService->lpDisplayName) + 1);
+
+ /* Copy service name */
+ wcscpy(lpStr, lpService->lpServiceName);
+ lpServicesPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices);
+ lpStr += (wcslen(lpService->lpServiceName) + 1);
+
+ lpServicesPtr ++;
+ }
+
+ *lpServicesReturned = dwServicesReturned;
+
+Done:
+ if (lpServicesArray != NULL)
+ HeapFree(GetProcessHeap(), 0, lpServicesArray);
+
+ RegCloseKey(hServicesKey);
+
+ DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError);
+
+ return dwError;
+}
+
+
+/* Function 14 */
+DWORD REnumServicesStatusW(
+ SC_RPC_HANDLE hSCManager,
+ DWORD dwServiceType,
+ DWORD dwServiceState,
+ LPBYTE lpBuffer,
+ DWORD dwBufSize,
+ LPBOUNDED_DWORD_256K pcbBytesNeeded,
+ LPBOUNDED_DWORD_256K lpServicesReturned,
+ LPBOUNDED_DWORD_256K lpResumeHandle)
+{
+ PMANAGER_HANDLE hManager;
+ PSERVICE lpService;
+ DWORD dwError = ERROR_SUCCESS;
+ PLIST_ENTRY ServiceEntry;
+ PSERVICE CurrentService;
+ DWORD dwState;
+ DWORD dwRequiredSize;
+ DWORD dwServiceCount;
+ DWORD dwSize;
+ DWORD dwLastResumeCount = 0;
+ LPENUM_SERVICE_STATUSW lpStatusPtr;
+ LPWSTR lpStringPtr;
+
+ DPRINT("REnumServicesStatusW() called\n");
+
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
+
+ hManager = ScmGetServiceManagerFromHandle(hSCManager);
+ if (hManager == NULL)
+ {
+ DPRINT1("Invalid service manager handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+
+ *pcbBytesNeeded = 0;
+ *lpServicesReturned = 0;
+
+ if ((dwServiceType!=SERVICE_DRIVER) && (dwServiceType!=SERVICE_WIN32))
+ {
+ DPRINT("Not a valid Service Type!\n");
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ if ((dwServiceState<SERVICE_ACTIVE) || (dwServiceState>SERVICE_STATE_ALL))
+ {
+ DPRINT("Not a valid Service State!\n");
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ /* Check access rights */
+ if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
+ SC_MANAGER_ENUMERATE_SERVICE))
+ {
+ DPRINT("Insufficient access rights! 0x%lx\n",
+ hManager->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ if (lpResumeHandle)
+ dwLastResumeCount = *lpResumeHandle;
+
+ /* FIXME: Lock the service list shared */
+
+ lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount);
+ if (lpService == NULL)
+ {
+ dwError = ERROR_SUCCESS;
+ goto Done;
+ }
+
+ dwRequiredSize = 0;
+ dwServiceCount = 0;
+
+ for (ServiceEntry = &lpService->ServiceListEntry;
+ ServiceEntry != &ServiceListHead;
+ ServiceEntry = ServiceEntry->Flink)
+ {
+ CurrentService = CONTAINING_RECORD(ServiceEntry,
+ SERVICE,
+ ServiceListEntry);
+
+ if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
+ continue;
+
+ dwState = SERVICE_ACTIVE;
+ if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
+ dwState = SERVICE_INACTIVE;
+
+ if ((dwState & dwServiceState) == 0)
+ continue;
+
+ dwSize = sizeof(ENUM_SERVICE_STATUSW) +
+ ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
+ ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
+
+ if (dwRequiredSize + dwSize > dwBufSize)
+ {
+ DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName);
+ break;
+ }
+
+ DPRINT("Service name: %S fit\n", CurrentService->lpServiceName);
+ dwRequiredSize += dwSize;
+ dwServiceCount++;
+ dwLastResumeCount = CurrentService->dwResumeCount;
+ }
+
+ DPRINT("dwRequiredSize: %lu\n", dwRequiredSize);
+ DPRINT("dwServiceCount: %lu\n", dwServiceCount);
+
+ for (;
+ ServiceEntry != &ServiceListHead;
+ ServiceEntry = ServiceEntry->Flink)
+ {
+ CurrentService = CONTAINING_RECORD(ServiceEntry,
+ SERVICE,
+ ServiceListEntry);
+
+ if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
+ continue;
+
+ dwState = SERVICE_ACTIVE;
+ if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
+ dwState = SERVICE_INACTIVE;
+
+ if ((dwState & dwServiceState) == 0)
+ continue;
+
+ dwRequiredSize += (sizeof(ENUM_SERVICE_STATUSW) +
+ ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
+ ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
+
+ dwError = ERROR_MORE_DATA;
+ }
+
+ DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
+
+ if (lpResumeHandle)
+ *lpResumeHandle = dwLastResumeCount;
+
+ *lpServicesReturned = dwServiceCount;
+ *pcbBytesNeeded = dwRequiredSize;
+
+ lpStatusPtr = (LPENUM_SERVICE_STATUSW)lpBuffer;
+ lpStringPtr = (LPWSTR)((ULONG_PTR)lpBuffer +
+ dwServiceCount * sizeof(ENUM_SERVICE_STATUSW));
+
+ dwRequiredSize = 0;
+ for (ServiceEntry = &lpService->ServiceListEntry;
+ ServiceEntry != &ServiceListHead;
+ ServiceEntry = ServiceEntry->Flink)
+ {
+ CurrentService = CONTAINING_RECORD(ServiceEntry,
+ SERVICE,
+ ServiceListEntry);
+
+ if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
+ continue;
+
+ dwState = SERVICE_ACTIVE;
+ if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
+ dwState = SERVICE_INACTIVE;
+
+ if ((dwState & dwServiceState) == 0)
+ continue;
+
+ dwSize = sizeof(ENUM_SERVICE_STATUSW) +
+ ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
+ ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
+
+ if (dwRequiredSize + dwSize > dwBufSize)
+ break;
+
+ /* Copy the service name */
+ wcscpy(lpStringPtr, CurrentService->lpServiceName);
+ lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
+ lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
+
+ /* Copy the display name */
+ wcscpy(lpStringPtr, CurrentService->lpDisplayName);
+ lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
+ lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
+
+ /* Copy the status information */
+ memcpy(&lpStatusPtr->ServiceStatus,
+ &CurrentService->Status,
+ sizeof(SERVICE_STATUS));
+
+ lpStatusPtr++;
+ dwRequiredSize += dwSize;
+ }
+
+ if (dwError == 0)
+ {
+ *pcbBytesNeeded = 0;
+ if (lpResumeHandle) *lpResumeHandle = 0;
+ }
+
+Done:;
+ /* FIXME: Unlock the service list */
+
+ DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError);
+
+ return dwError;
+}
+
+
+/* Function 15 */
+DWORD ROpenSCManagerW(
+ LPWSTR lpMachineName,
+ LPWSTR lpDatabaseName,
+ DWORD dwDesiredAccess,
+ LPSC_RPC_HANDLE lpScHandle)
+{
+ DWORD dwError;
+ SC_HANDLE hHandle;
+
+ DPRINT("ROpenSCManagerW() called\n");
+ DPRINT("lpMachineName = %p\n", lpMachineName);
+ DPRINT("lpMachineName: %S\n", lpMachineName);
+ DPRINT("lpDataBaseName = %p\n", lpDatabaseName);
+ DPRINT("lpDataBaseName: %S\n", lpDatabaseName);
+ DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
+
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
+
+ if (!lpScHandle)
+ return ERROR_INVALID_PARAMETER;
+
+ dwError = ScmCreateManagerHandle(lpDatabaseName,
+ &hHandle);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError);
+ return dwError;
+ }
+
+ /* Check the desired access */
+ dwError = ScmCheckAccess(hHandle,
+ dwDesiredAccess | SC_MANAGER_CONNECT);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError);
+ HeapFree(GetProcessHeap(), 0, hHandle);
+ return dwError;
+ }
+
+ *lpScHandle = (SC_RPC_HANDLE)hHandle;
+ DPRINT("*hScm = %p\n", *lpScHandle);
+
+ DPRINT("ROpenSCManagerW() done\n");
+
+ return ERROR_SUCCESS;
+}
+
+
+/* Function 16 */
+DWORD ROpenServiceW(
+ SC_RPC_HANDLE hSCManager,
+ LPWSTR lpServiceName,
+ DWORD dwDesiredAccess,
+ LPSC_RPC_HANDLE lpServiceHandle)
+{
+ PSERVICE lpService;
+ PMANAGER_HANDLE hManager;
+ SC_HANDLE hHandle;
+ DWORD dwError;
+
+ DPRINT("ROpenServiceW() called\n");
+ DPRINT("hSCManager = %p\n", hSCManager);
+ DPRINT("lpServiceName = %p\n", lpServiceName);
+ DPRINT("lpServiceName: %S\n", lpServiceName);
+ DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
+
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
+
+ hManager = ScmGetServiceManagerFromHandle(hSCManager);
+ if (hManager == NULL)
+ {
+ DPRINT1("Invalid service manager handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ if (!lpServiceHandle)
+ return ERROR_INVALID_PARAMETER;
+
+ if (!lpServiceName)
+ return ERROR_INVALID_ADDRESS;
+
+ /* FIXME: Lock the service list */
+
+ /* Get service database entry */
+ lpService = ScmGetServiceEntryByName(lpServiceName);
+ if (lpService == NULL)
+ {
+ DPRINT("Could not find a service!\n");
+ return ERROR_SERVICE_DOES_NOT_EXIST;
+ }
+
+ /* Create a service handle */
+ dwError = ScmCreateServiceHandle(lpService,
+ &hHandle);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError);
+ return dwError;
+ }
+
+ /* Check the desired access */
+ dwError = ScmCheckAccess(hHandle,
+ dwDesiredAccess);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError);
+ HeapFree(GetProcessHeap(), 0, hHandle);
+ return dwError;
+ }
+
+ lpService->dwRefCount++;
+ DPRINT("OpenService - lpService->dwRefCount %u\n",lpService->dwRefCount);
+
+ *lpServiceHandle = (SC_RPC_HANDLE)hHandle;
+ DPRINT("*hService = %p\n", *lpServiceHandle);
+
+ DPRINT("ROpenServiceW() done\n");
+
+ return ERROR_SUCCESS;
+}
+
+
+/* Function 17 */
+DWORD RQueryServiceConfigW(
+ SC_RPC_HANDLE hService,
+ LPQUERY_SERVICE_CONFIGW lpServiceConfig,
+ DWORD cbBufSize,
+ LPBOUNDED_DWORD_8K pcbBytesNeeded)
+{
+ DWORD dwError = ERROR_SUCCESS;
+ PSERVICE_HANDLE hSvc;
+ PSERVICE lpService = NULL;
+ HKEY hServiceKey = NULL;
+ LPWSTR lpImagePath = NULL;
+ LPWSTR lpServiceStartName = NULL;
+ LPWSTR lpDependencies = NULL;
+ DWORD dwDependenciesLength = 0;
+ DWORD dwRequiredSize;
+ LPQUERY_SERVICE_CONFIGW lpConfig = NULL;
+ WCHAR lpEmptyString[] = {0,0};
+ LPWSTR lpStr;
+
+ DPRINT("RQueryServiceConfigW() called\n");
+
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
+
+ hSvc = ScmGetServiceFromHandle(hService);
+ if (hSvc == NULL)
+ {
+ DPRINT1("Invalid service handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+ SERVICE_QUERY_CONFIG))
+ {
+ DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ lpService = hSvc->ServiceEntry;
+ if (lpService == NULL)
+ {
+ DPRINT("lpService == NULL!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ /* FIXME: Lock the service database shared */
+
+ dwError = ScmOpenServiceKey(lpService->lpServiceName,
+ KEY_READ,
+ &hServiceKey);
+ if (dwError != ERROR_SUCCESS)
+ goto Done;
+
+ /* Read the image path */
+ dwError = ScmReadString(hServiceKey,
+ L"ImagePath",
+ &lpImagePath);
+ if (dwError != ERROR_SUCCESS)
+ goto Done;
+
+ /* Read the service start name */
+ ScmReadString(hServiceKey,
+ L"ObjectName",
+ &lpServiceStartName);
+
+ /* Read the dependencies */
+ ScmReadDependencies(hServiceKey,
+ &lpDependencies,
+ &dwDependenciesLength);
+
+ dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGW);
+
+ if (lpImagePath != NULL)
+ dwRequiredSize += ((wcslen(lpImagePath) + 1) * sizeof(WCHAR));
+ else
+ dwRequiredSize += 2 * sizeof(WCHAR);
+
+ if (lpService->lpGroup != NULL)
+ dwRequiredSize += ((wcslen(lpService->lpGroup->lpGroupName) + 1) * sizeof(WCHAR));
+ else
+ dwRequiredSize += 2 * sizeof(WCHAR);
+
+ if (lpDependencies != NULL)
+ dwRequiredSize += dwDependenciesLength * sizeof(WCHAR);
+ else
+ dwRequiredSize += 2 * sizeof(WCHAR);
+
+ if (lpServiceStartName != NULL)
+ dwRequiredSize += ((wcslen(lpServiceStartName) + 1) * sizeof(WCHAR));
+ else
+ dwRequiredSize += 2 * sizeof(WCHAR);
+
+ if (lpService->lpDisplayName != NULL)
+ dwRequiredSize += ((wcslen(lpService->lpDisplayName) + 1) * sizeof(WCHAR));
+ else
+ dwRequiredSize += 2 * sizeof(WCHAR);
+
+ if (lpServiceConfig == NULL || cbBufSize < dwRequiredSize)
+ {
+ dwError = ERROR_INSUFFICIENT_BUFFER;
+ }
+ else
+ {
+ lpConfig = (LPQUERY_SERVICE_CONFIGW)lpServiceConfig;
+ lpConfig->dwServiceType = lpService->Status.dwServiceType;
+ lpConfig->dwStartType = lpService->dwStartType;
+ lpConfig->dwErrorControl = lpService->dwErrorControl;
+ lpConfig->dwTagId = lpService->dwTag;
+
+ lpStr = (LPWSTR)(lpConfig + 1);
+
+ /* Append the image path */
+ if (lpImagePath != NULL)
+ {
+ wcscpy(lpStr, lpImagePath);
+ }
+ else
+ {
+ wcscpy(lpStr, lpEmptyString);
+ }
+
+ lpConfig->lpBinaryPathName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
+ lpStr += (wcslen(lpStr) + 1);
+
+ /* Append the group name */
+ if (lpService->lpGroup != NULL)
+ {
+ wcscpy(lpStr, lpService->lpGroup->lpGroupName);
+ }
+ else
+ {
+ wcscpy(lpStr, lpEmptyString);
+ }
+
+ lpConfig->lpLoadOrderGroup = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
+ lpStr += (wcslen(lpStr) + 1);
+
+ /* Append Dependencies */
+ if (lpDependencies != NULL)
+ {
+ memcpy(lpStr,
+ lpDependencies,
+ dwDependenciesLength * sizeof(WCHAR));
+ }
+ else
+ {
+ wcscpy(lpStr, lpEmptyString);
+ }
+
+ lpConfig->lpDependencies = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
+ if (lpDependencies != NULL)
+ lpStr += dwDependenciesLength * sizeof(WCHAR);
+ else
+ lpStr += (wcslen(lpStr) + 1);
+
+ /* Append the service start name */
+ if (lpServiceStartName != NULL)
+ {
+ wcscpy(lpStr, lpServiceStartName);
+ }
+ else
+ {
+ wcscpy(lpStr, lpEmptyString);
+ }
+
+ lpConfig->lpServiceStartName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
+ lpStr += (wcslen(lpStr) + 1);
+
+ /* Append the display name */
+ if (lpService->lpDisplayName != NULL)
+ {
+ wcscpy(lpStr, lpService->lpDisplayName);
+ }
+ else
+ {
+ wcscpy(lpStr, lpEmptyString);
+ }
+
+ lpConfig->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
+ }
+
+ if (pcbBytesNeeded != NULL)
+ *pcbBytesNeeded = dwRequiredSize;
+
+Done:;
+ if (lpImagePath != NULL)
+ HeapFree(GetProcessHeap(), 0, lpImagePath);
+
+ if (lpServiceStartName != NULL)
+ HeapFree(GetProcessHeap(), 0, lpServiceStartName);
+
+ if (lpDependencies != NULL)
+ HeapFree(GetProcessHeap(), 0, lpDependencies);
+
+ if (hServiceKey != NULL)
+ RegCloseKey(hServiceKey);
+
+ /* FIXME: Unlock the service database */
+
+ DPRINT("RQueryServiceConfigW() done\n");
+
+ return dwError;
+}
+
+
+/* Function 18 */
+DWORD RQueryServiceLockStatusW(
+ SC_RPC_HANDLE hSCManager,
+ LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
+ DWORD cbBufSize,
+ LPBOUNDED_DWORD_4K pcbBytesNeeded)
+{
+ UNIMPLEMENTED;
+ return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 19 */
+DWORD RStartServiceW(
+ SC_RPC_HANDLE hService,
+ DWORD argc,
+ LPSTRING_PTRSW argv)
+{
+ DWORD dwError = ERROR_SUCCESS;
+ PSERVICE_HANDLE hSvc;
+ PSERVICE lpService = NULL;
+
+ DPRINT("RStartServiceW() called\n");
+
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
+
+ hSvc = ScmGetServiceFromHandle(hService);
+ if (hSvc == NULL)
+ {
+ DPRINT1("Invalid service handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+ SERVICE_START))
+ {
+ DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ lpService = hSvc->ServiceEntry;
+ if (lpService == NULL)
+ {
+ DPRINT("lpService == NULL!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ if (lpService->dwStartType == SERVICE_DISABLED)
+ return ERROR_SERVICE_DISABLED;
+
+ if (lpService->bDeleted)
+ return ERROR_SERVICE_MARKED_FOR_DELETE;
+
+ if (argv) {
+ UNIMPLEMENTED;
+ argv = NULL;
+ }
+
+ /* Start the service */
+ dwError = ScmStartService(lpService, argc, (LPWSTR *)argv);
+
+ return dwError;
+}
+
+
+/* Function 20 */
+DWORD RGetServiceDisplayNameW(
+ SC_RPC_HANDLE hSCManager,
+ LPCWSTR lpServiceName,
+ LPWSTR lpDisplayName,
+ DWORD *lpcchBuffer)
+{
+// PMANAGER_HANDLE hManager;
+ PSERVICE lpService;
+ DWORD dwLength;
+ DWORD dwError;
+
+ DPRINT("RGetServiceDisplayNameW() called\n");
+ DPRINT("hSCManager = %p\n", hSCManager);
+ DPRINT("lpServiceName: %S\n", lpServiceName);
+ DPRINT("lpDisplayName: %p\n", lpDisplayName);
+ DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
+
+// hManager = (PMANAGER_HANDLE)hSCManager;
+// if (hManager->Handle.Tag != MANAGER_TAG)
+// {
+// DPRINT("Invalid manager handle!\n");
+// return ERROR_INVALID_HANDLE;
+// }
+
+ /* Get service database entry */
+ lpService = ScmGetServiceEntryByName(lpServiceName);
+ if (lpService == NULL)
+ {
+ DPRINT("Could not find a service!\n");
+
+ /* If the service could not be found and lpcchBuffer is less than 2, windows
+ puts null in lpDisplayName and puts 2 in lpcchBuffer */
+ if (*lpcchBuffer < 2)
+ {
+ *lpcchBuffer = 2;
+ if (lpDisplayName != NULL)
+ {
+ *lpDisplayName = '\0';
+ }
+ }
+
+ return ERROR_SERVICE_DOES_NOT_EXIST;
+ }
+
+ if (!lpService->lpDisplayName)
+ {
+ dwLength = wcslen(lpService->lpServiceName);
+
+ if (lpDisplayName != NULL &&
+ *lpcchBuffer > dwLength)
+ {
+ wcscpy(lpDisplayName, lpService->lpServiceName);
+ }
+ }
+ else
+ {
+ dwLength = wcslen(lpService->lpDisplayName);
+
+ if (lpDisplayName != NULL &&
+ *lpcchBuffer > dwLength)
+ {
+ wcscpy(lpDisplayName, lpService->lpDisplayName);
+ }
+ }
+
+ dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
+
+ *lpcchBuffer = dwLength;
+
+ return dwError;
+}
+
+
+/* Function 21 */
+DWORD RGetServiceKeyNameW(
+ SC_RPC_HANDLE hSCManager,
+ LPCWSTR lpDisplayName,
+ LPWSTR lpServiceName,
+ DWORD *lpcchBuffer)
+{
+// PMANAGER_HANDLE hManager;
+ PSERVICE lpService;
+ DWORD dwLength;
+ DWORD dwError;
+
+ DPRINT("RGetServiceKeyNameW() called\n");
+ DPRINT("hSCManager = %p\n", hSCManager);
+ DPRINT("lpDisplayName: %S\n", lpDisplayName);
+ DPRINT("lpServiceName: %p\n", lpServiceName);
+ DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
+
+// hManager = (PMANAGER_HANDLE)hSCManager;
+// if (hManager->Handle.Tag != MANAGER_TAG)
+// {
+// DPRINT("Invalid manager handle!\n");
+// return ERROR_INVALID_HANDLE;
+// }
+
+ /* Get service database entry */
+ lpService = ScmGetServiceEntryByDisplayName(lpDisplayName);
+ if (lpService == NULL)
+ {
+ DPRINT("Could not find a service!\n");
+
+ /* If the service could not be found and lpcchBuffer is less than 2, windows
+ puts null in lpDisplayName and puts 2 in lpcchBuffer */
+ if (*lpcchBuffer < 2)
+ {
+ *lpcchBuffer = 2;
+ if (lpServiceName != NULL)
+ {
+ *lpServiceName = '\0';
+ }
+ }
+
+ return ERROR_SERVICE_DOES_NOT_EXIST;
+ }
+
+ dwLength = wcslen(lpService->lpServiceName);
+
+ if (lpServiceName != NULL &&
+ *lpcchBuffer > dwLength)
+ {
+ wcscpy(lpServiceName, lpService->lpServiceName);
+ *lpcchBuffer = dwLength;
+ return ERROR_SUCCESS;
+ }
+
+ dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
+
+ *lpcchBuffer = dwLength;
+
+ return dwError;
+}
+
+
+/* Function 22 */
+DWORD RI_ScSetServiceBitsA(
+ RPC_SERVICE_STATUS_HANDLE hServiceStatus,
+ DWORD dwServiceBits,
+ int bSetBitsOn,
+ int bUpdateImmediately,
+ char *lpString)
+{
+ UNIMPLEMENTED;
+ return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 23 */
+DWORD RChangeServiceConfigA(
+ SC_RPC_HANDLE hService,
+ DWORD dwServiceType,
+ DWORD dwStartType,
+ DWORD dwErrorControl,
+ LPSTR lpBinaryPathName,
+ LPSTR lpLoadOrderGroup,
+ LPDWORD lpdwTagId,
+ LPSTR lpDependencies,
+ DWORD dwDependSize,
+ LPSTR lpServiceStartName,
+ LPBYTE lpPassword,
+ DWORD dwPwSize,
+ LPSTR lpDisplayName)
+{
+ DWORD dwError = ERROR_SUCCESS;
+ PSERVICE_HANDLE hSvc;
+ PSERVICE lpService = NULL;
+ HKEY hServiceKey = NULL;
+ LPWSTR lpDisplayNameW = NULL;
+ // LPWSTR lpBinaryPathNameW = NULL;
+ LPWSTR lpLoadOrderGroupW = NULL;
+ LPWSTR lpDependenciesW = NULL;
+ // LPWSTR lpPasswordW = NULL;
+
+ DPRINT("RChangeServiceConfigA() called\n");
+ DPRINT("dwServiceType = %lu\n", dwServiceType);
+ DPRINT("dwStartType = %lu\n", dwStartType);
+ DPRINT("dwErrorControl = %lu\n", dwErrorControl);
+ DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName);
+ DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup);
+ DPRINT("lpDisplayName = %s\n", lpDisplayName);
+
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
+
+ hSvc = ScmGetServiceFromHandle(hService);
+ if (hSvc == NULL)
+ {
+ DPRINT1("Invalid service handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+ SERVICE_CHANGE_CONFIG))
+ {
+ DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ lpService = hSvc->ServiceEntry;
+ if (lpService == NULL)
+ {
+ DPRINT("lpService == NULL!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ /* FIXME: Lock database exclusively */
+
+ if (lpService->bDeleted)
+ {
+ /* FIXME: Unlock database */
+ DPRINT("The service has already been marked for delete!\n");
+ return ERROR_SERVICE_MARKED_FOR_DELETE;
+ }
+
+ /* Open the service key */
+ dwError = ScmOpenServiceKey(lpService->szServiceName,
+ KEY_SET_VALUE,
+ &hServiceKey);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ /* Write service data to the registry */
+
+ if (lpDisplayName != NULL && *lpDisplayName != 0)
+ {
+ /* Set the display name */
+ lpDisplayNameW = HeapAlloc(GetProcessHeap(),
+ 0,
+ (strlen(lpDisplayName) + 1) * sizeof(WCHAR));
+ if (lpDisplayNameW == NULL)
+ {
+ dwError = ERROR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+
+ MultiByteToWideChar(CP_ACP,
+ 0,
+ lpDisplayName,
+ -1,
+ lpDisplayNameW,
+ strlen(lpDisplayName) + 1);
+
+ RegSetValueExW(hServiceKey,
+ L"DisplayName",
+ 0,
+ REG_SZ,
+ (LPBYTE)lpDisplayNameW,
+ (wcslen(lpDisplayNameW) + 1) * sizeof(WCHAR));
+
+ /* Update lpService->lpDisplayName */
+ if (lpService->lpDisplayName)
+ HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName);
+
+ lpService->lpDisplayName = lpDisplayNameW;
+ }
+
+ if (dwServiceType != SERVICE_NO_CHANGE)
+ {
+ /* Set the service type */
+ dwError = RegSetValueExW(hServiceKey,
+ L"Type",
+ 0,
+ REG_DWORD,
+ (LPBYTE)&dwServiceType,
+ sizeof(DWORD));
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ lpService->Status.dwServiceType = dwServiceType;
+ }
+
+ if (dwStartType != SERVICE_NO_CHANGE)
+ {
+ /* Set the start value */
+ dwError = RegSetValueExW(hServiceKey,
+ L"Start",
+ 0,
+ REG_DWORD,
+ (LPBYTE)&dwStartType,
+ sizeof(DWORD));
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ lpService->dwStartType = dwStartType;
+ }
+
+ if (dwErrorControl != SERVICE_NO_CHANGE)
+ {
+ /* Set the error control value */
+ dwError = RegSetValueExW(hServiceKey,
+ L"ErrorControl",
+ 0,
+ REG_DWORD,
+ (LPBYTE)&dwErrorControl,
+ sizeof(DWORD));
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ lpService->dwErrorControl = dwErrorControl;
+ }
+
+#if 0
+ /* FIXME: set the new ImagePath value */
+
+ /* Set the image path */
+ if (dwServiceType & SERVICE_WIN32)
+ {
+ if (lpBinaryPathName != NULL && *lpBinaryPathName != 0)
+ {
+ lpBinaryPathNameW=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName)+1) * sizeof(WCHAR));
+ MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, lpBinaryPathNameW, strlen(lpBinaryPathName)+1);
+ dwError = RegSetValueExW(hServiceKey,
+ L"ImagePath",
+ 0,
+ REG_EXPAND_SZ,
+ (LPBYTE)lpBinaryPathNameW,
+ (wcslen(lpBinaryPathNameW) + 1) * sizeof(WCHAR));
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
+ }
+ else if (dwServiceType & SERVICE_DRIVER)
+ {
+ if (lpImagePath != NULL && *lpImagePath != 0)
+ {
+ dwError = RegSetValueExW(hServiceKey,
+ L"ImagePath",
+ 0,
+ REG_EXPAND_SZ,
+ (LPBYTE)lpImagePath,
+ (wcslen(lpImagePath) + 1) *sizeof(WCHAR));
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
+ }
+#endif
+
+ /* Set the group name */
+ if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
+ {
+ lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(),
+ 0,
+ (strlen(lpLoadOrderGroup) + 1) * sizeof(WCHAR));
+ if (lpLoadOrderGroupW == NULL)
+ {
+ dwError = ERROR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+
+ MultiByteToWideChar(CP_ACP,
+ 0,
+ lpLoadOrderGroup,
+ -1,
+ lpLoadOrderGroupW,
+ strlen(lpLoadOrderGroup) + 1);
+
+ dwError = RegSetValueExW(hServiceKey,
+ L"Group",
+ 0,
+ REG_SZ,
+ (LPBYTE)lpLoadOrderGroupW,
+ (wcslen(lpLoadOrderGroupW) + 1) * sizeof(WCHAR));
+ if (dwError != ERROR_SUCCESS)
+ {
+ HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW);
+ goto done;
+ }
+
+ dwError = ScmSetServiceGroup(lpService,
+ lpLoadOrderGroupW);
+
+ HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW);
+
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
+
+ if (lpdwTagId != NULL)
+ {
+ dwError = ScmAssignNewTag(lpService);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ dwError = RegSetValueExW(hServiceKey,
+ L"Tag",
+ 0,
+ REG_DWORD,
+ (LPBYTE)&lpService->dwTag,
+ sizeof(DWORD));
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ *lpdwTagId = lpService->dwTag;
+ }
+
+ /* Write dependencies */
+ if (lpDependencies != NULL && *lpDependencies != 0)
+ {
+ lpDependenciesW = HeapAlloc(GetProcessHeap(),
+ 0,
+ (strlen(lpDependencies) + 1) * sizeof(WCHAR));
+ if (lpDependenciesW == NULL)
+ {
+ dwError = ERROR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+
+ MultiByteToWideChar(CP_ACP,
+ 0,
+ lpDependencies,
+ dwDependSize,
+ lpDependenciesW,
+ strlen(lpDependencies) + 1);
+
+ dwError = ScmWriteDependencies(hServiceKey,
+ (LPWSTR)lpDependenciesW,
+ dwDependSize);
+
+ HeapFree(GetProcessHeap(), 0, lpDependenciesW);
+ }
+
+ if (lpPassword != NULL)
+ {
+ /* FIXME: Write password */
+ }
+
+ /* FIXME: Unlock database */
+
+done:
+ if (hServiceKey != NULL)
+ RegCloseKey(hServiceKey);
+
+ DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError);
+
+ return dwError;
+}
+
+
+/* Function 24 */
+DWORD RCreateServiceA(
+ SC_RPC_HANDLE hSCManager,
+ LPSTR lpServiceName,
+ LPSTR lpDisplayName,
+ DWORD dwDesiredAccess,
+ DWORD dwServiceType,
+ DWORD dwStartType,
+ DWORD dwErrorControl,
+ LPSTR lpBinaryPathName,
+ LPSTR lpLoadOrderGroup,
+ LPDWORD lpdwTagId,
+ LPBYTE lpDependencies,
+ DWORD dwDependSize,
+ LPSTR lpServiceStartName,
+ LPBYTE lpPassword,
+ DWORD dwPwSize,
+ LPSC_RPC_HANDLE lpServiceHandle)
+{
+ DWORD dwError = ERROR_SUCCESS;
+ LPWSTR lpServiceNameW = NULL;
+ LPWSTR lpDisplayNameW = NULL;
+ LPWSTR lpBinaryPathNameW = NULL;
+ LPWSTR lpLoadOrderGroupW = NULL;
+ LPWSTR lpDependenciesW = NULL;
+ LPWSTR lpServiceStartNameW = NULL;
+ DWORD dwDependenciesLength = 0;
+ DWORD dwLength;
+ int len;
+ LPSTR lpStr;
+
+ if (lpServiceName)
+ {
+ len = MultiByteToWideChar(CP_ACP, 0, lpServiceName, -1, NULL, 0);
+ lpServiceNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if (!lpServiceNameW)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ MultiByteToWideChar(CP_ACP, 0, lpServiceName, -1, lpServiceNameW, len);
+ }
+
+ if (lpDisplayName)
+ {
+ len = MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, NULL, 0);
+ lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if (!lpDisplayNameW)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, lpDisplayNameW, len);
+ }
+
+ if (lpBinaryPathName)
+ {
+ len = MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, NULL, 0);
+ lpBinaryPathNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if (!lpBinaryPathNameW)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, lpBinaryPathNameW, len);
+ }
+
+ if (lpLoadOrderGroup)
+ {
+ len = MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, NULL, 0);
+ lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if (!lpLoadOrderGroupW)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, lpLoadOrderGroupW, len);
+ }
+
+ if (lpDependencies)
+ {
+ lpStr = (LPSTR)lpDependencies;
+ while (*lpStr)
+ {
+ dwLength = strlen(lpStr) + 1;
+ dwDependenciesLength += dwLength;
+ lpStr = lpStr + dwLength;
+ }
+ dwDependenciesLength++;
+
+ lpDependenciesW = HeapAlloc(GetProcessHeap(), 0, dwDependenciesLength * sizeof(WCHAR));
+ if (!lpDependenciesW)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ MultiByteToWideChar(CP_ACP, 0, (LPSTR)lpDependencies, dwDependenciesLength, lpDependenciesW, dwDependenciesLength);
+ }
+
+ if (lpServiceStartName)
+ {
+ len = MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, NULL, 0);
+ lpServiceStartNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if (!lpServiceStartNameW)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, lpServiceStartNameW, len);
+ }
+
+ dwError = RCreateServiceW(hSCManager,
+ lpServiceNameW,
+ lpDisplayNameW,
+ dwDesiredAccess,
+ dwServiceType,
+ dwStartType,
+ dwErrorControl,
+ lpBinaryPathNameW,
+ lpLoadOrderGroupW,
+ lpdwTagId,
+ (LPBYTE)lpDependenciesW,
+ dwDependenciesLength,
+ lpServiceStartNameW,
+ lpPassword,
+ dwPwSize,
+ lpServiceHandle);
+
+cleanup:
+ if (lpServiceNameW !=NULL)
+ HeapFree(GetProcessHeap(), 0, lpServiceNameW);
+
+ if (lpDisplayNameW != NULL)
+ HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
+
+ if (lpBinaryPathNameW != NULL)
+ HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW);
+
+ if (lpLoadOrderGroupW != NULL)
+ HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW);
+
+ if (lpDependenciesW != NULL)
+ HeapFree(GetProcessHeap(), 0, lpDependenciesW);
+
+ if (lpServiceStartNameW != NULL)
+ HeapFree(GetProcessHeap(), 0, lpServiceStartNameW);
+
+ return dwError;
+}
+
+
+/* Function 25 */
+DWORD REnumDependentServicesA(
+ SC_RPC_HANDLE hService,
+ DWORD dwServiceState,
+ LPBYTE lpServices,
+ DWORD cbBufSize,
+ LPBOUNDED_DWORD_256K pcbBytesNeeded,
+ LPBOUNDED_DWORD_256K lpServicesReturned)
+{
+ DWORD dwError = ERROR_SUCCESS;
+ DWORD dwServicesReturned = 0;
+ DWORD dwServiceCount;
+ HKEY hServicesKey = NULL;
+ PSERVICE_HANDLE hSvc;
+ PSERVICE lpService = NULL;
+ PSERVICE *lpServicesArray = NULL;
+ LPENUM_SERVICE_STATUSA lpServicesPtr = NULL;
+ LPSTR lpStr;
+
+ *pcbBytesNeeded = 0;
+ *lpServicesReturned = 0;
+
+ DPRINT("REnumDependentServicesA() called\n");
+
+ hSvc = ScmGetServiceFromHandle(hService);
+ if (hSvc == NULL)
+ {
+ DPRINT1("Invalid service handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ lpService = hSvc->ServiceEntry;
+
+ /* Check access rights */
+ if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+ SC_MANAGER_ENUMERATE_SERVICE))
+ {
+ DPRINT("Insufficient access rights! 0x%lx\n",
+ hSvc->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ /* Open the Services Reg key */
+ dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ L"System\\CurrentControlSet\\Services",
+ 0,
+ KEY_READ,
+ &hServicesKey);
+
+ if (dwError != ERROR_SUCCESS)
+ return dwError;
+
+ /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
+ both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
+ are the same for both. Verified in WINXP. */
+
+ /* First determine the bytes needed and get the number of dependent services*/
+ dwError = Int_EnumDependentServicesW(hServicesKey,
+ lpService,
+ dwServiceState,
+ NULL,
+ pcbBytesNeeded,
+ &dwServicesReturned);
+ if (dwError != ERROR_SUCCESS)
+ goto Done;
+
+ /* If buffer size is less than the bytes needed or pointer is null*/
+ if ((!lpServices) || (cbBufSize < *pcbBytesNeeded))
+ {
+ dwError = ERROR_MORE_DATA;
+ goto Done;
+ }
+
+ /* Allocate memory for array of service pointers */
+ lpServicesArray = HeapAlloc(GetProcessHeap(),
+ 0,
+ (dwServicesReturned + 1) * sizeof(PSERVICE));
+ if (!lpServicesArray)
+ {
+ DPRINT("Could not allocate a buffer!!\n");
+ dwError = ERROR_NOT_ENOUGH_MEMORY;
+ goto Done;
+ }
+
+ dwServicesReturned = 0;
+ *pcbBytesNeeded = 0;
+
+ dwError = Int_EnumDependentServicesW(hServicesKey,
+ lpService,
+ dwServiceState,
+ lpServicesArray,
+ pcbBytesNeeded,
+ &dwServicesReturned);
+ if (dwError != ERROR_SUCCESS)
+ {
+ goto Done;
+ }
+
+ lpServicesPtr = (LPENUM_SERVICE_STATUSA)lpServices;
+ lpStr = (LPSTR)(lpServices + (dwServicesReturned * sizeof(ENUM_SERVICE_STATUSA)));
+
+ /* Copy EnumDepenedentService to Buffer */
+ for (dwServiceCount = 0; dwServiceCount < dwServicesReturned; dwServiceCount++)
+ {
+ lpService = lpServicesArray[dwServiceCount];
+
+ /* Copy the status info */
+ memcpy(&lpServicesPtr->ServiceStatus,
+ &lpService->Status,
+ sizeof(SERVICE_STATUS));
+
+ /* Copy display name */
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ lpService->lpDisplayName,
+ -1,
+ lpStr,
+ wcslen(lpService->lpDisplayName),
+ 0,
+ 0);
+ lpServicesPtr->lpDisplayName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices);
+ lpStr += strlen(lpStr) + 1;
+
+ /* Copy service name */
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ lpService->lpServiceName,
+ -1,
+ lpStr,
+ wcslen(lpService->lpServiceName),
+ 0,
+ 0);
+ lpServicesPtr->lpServiceName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices);
+ lpStr += strlen(lpStr) + 1;
+
+ lpServicesPtr ++;
+ }
+
+ *lpServicesReturned = dwServicesReturned;
+
+Done:
+ if (lpServicesArray)
+ HeapFree(GetProcessHeap(), 0, lpServicesArray);
+
+ RegCloseKey(hServicesKey);
+
+ DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError);
+
+ return dwError;
+}
+
+
+/* Function 26 */
+DWORD REnumServicesStatusA(
+ SC_RPC_HANDLE hSCManager,
+ DWORD dwServiceType,
+ DWORD dwServiceState,
+ LPBYTE lpBuffer,
+ DWORD dwBufSize,
+ LPBOUNDED_DWORD_256K pcbBytesNeeded,
+ LPBOUNDED_DWORD_256K lpServicesReturned,
+ LPBOUNDED_DWORD_256K lpResumeHandle)
+{
+ LPENUM_SERVICE_STATUSW lpStatusPtrW = NULL;
+ LPENUM_SERVICE_STATUSA lpStatusPtrA = NULL;
+ LPWSTR lpStringPtrW;
+ LPSTR lpStringPtrA;
+ DWORD dwError;
+ DWORD dwServiceCount;
+
+ DPRINT("REnumServicesStatusA() called\n");
+
+ if ((dwBufSize > 0) && (lpBuffer))
+ {
+ lpStatusPtrW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufSize);
+ if (!lpStatusPtrW)
+ {
+ DPRINT("Failed to allocate buffer!\n");
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+ }
+
+ dwError = REnumServicesStatusW(hSCManager,
+ dwServiceType,
+ dwServiceState,
+ (LPBYTE)lpStatusPtrW,
+ dwBufSize,
+ pcbBytesNeeded,
+ lpServicesReturned,
+ lpResumeHandle);
+
+ /* if no services were returned then we are Done */
+ if (*lpServicesReturned == 0)
+ goto Done;
+
+ lpStatusPtrA = (LPENUM_SERVICE_STATUSA)lpBuffer;
+ lpStringPtrA = (LPSTR)((ULONG_PTR)lpBuffer +
+ *lpServicesReturned * sizeof(ENUM_SERVICE_STATUSA));
+ lpStringPtrW = (LPWSTR)((ULONG_PTR)lpStatusPtrW +
+ *lpServicesReturned * sizeof(ENUM_SERVICE_STATUSW));
+
+ for (dwServiceCount = 0; dwServiceCount < *lpServicesReturned; dwServiceCount++)
+ {
+ /* Copy the service name */
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ lpStringPtrW,
+ -1,
+ lpStringPtrA,
+ wcslen(lpStringPtrW),
+ 0,
+ 0);
+
+ lpStatusPtrA->lpServiceName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer);
+ lpStringPtrA += wcslen(lpStringPtrW) + 1;
+ lpStringPtrW += wcslen(lpStringPtrW) + 1;
+
+ /* Copy the display name */
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ lpStringPtrW,
+ -1,
+ lpStringPtrA,
+ wcslen(lpStringPtrW),
+ 0,
+ 0);
+
+ lpStatusPtrA->lpDisplayName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer);
+ lpStringPtrA += wcslen(lpStringPtrW) + 1;
+ lpStringPtrW += wcslen(lpStringPtrW) + 1;
+
+ /* Copy the status information */
+ memcpy(&lpStatusPtrA->ServiceStatus,
+ &lpStatusPtrW->ServiceStatus,
+ sizeof(SERVICE_STATUS));
+
+ lpStatusPtrA++;
+ }
+
+Done:;
+ if (lpStatusPtrW)
+ HeapFree(GetProcessHeap(), 0, lpStatusPtrW);
+
+ DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError);
+
+ return dwError;
+}
+
+
+/* Function 27 */
+DWORD ROpenSCManagerA(
+ LPSTR lpMachineName,
+ LPSTR lpDatabaseName,
+ DWORD dwDesiredAccess,
+ LPSC_RPC_HANDLE lpScHandle)
+{
+ UNICODE_STRING MachineName;
+ UNICODE_STRING DatabaseName;
+ DWORD dwError;
+
+ DPRINT("ROpenSCManagerA() called\n");
+
+ if (lpMachineName)
+ RtlCreateUnicodeStringFromAsciiz(&MachineName,
+ lpMachineName);
+
+ if (lpDatabaseName)
+ RtlCreateUnicodeStringFromAsciiz(&DatabaseName,
+ lpDatabaseName);
+
+ dwError = ROpenSCManagerW(lpMachineName ? MachineName.Buffer : NULL,
+ lpDatabaseName ? DatabaseName.Buffer : NULL,
+ dwDesiredAccess,
+ lpScHandle);
+
+ if (lpMachineName)
+ RtlFreeUnicodeString(&MachineName);
+
+ if (lpDatabaseName)
+ RtlFreeUnicodeString(&DatabaseName);
+
+ return dwError;
+}
+
+
+/* Function 28 */
+DWORD ROpenServiceA(
+ SC_RPC_HANDLE hSCManager,
+ LPSTR lpServiceName,
+ DWORD dwDesiredAccess,
+ LPSC_RPC_HANDLE lpServiceHandle)
+{
+ UNICODE_STRING ServiceName;
+ DWORD dwError;
+
+ DPRINT("ROpenServiceA() called\n");
+
+ if (lpServiceName)
+ RtlCreateUnicodeStringFromAsciiz(&ServiceName,
+ lpServiceName);
+
+ dwError = ROpenServiceW(hSCManager,
+ lpServiceName ? ServiceName.Buffer : NULL,
+ dwDesiredAccess,
+ lpServiceHandle);
+
+ if (lpServiceName)
+ RtlFreeUnicodeString(&ServiceName);
+
+ return dwError;
+}
+
+
+/* Function 29 */
+DWORD RQueryServiceConfigA(
+ SC_RPC_HANDLE hService,
+ LPQUERY_SERVICE_CONFIGA lpServiceConfig,
+ DWORD cbBufSize,
+ LPBOUNDED_DWORD_8K pcbBytesNeeded)
+{
+ DWORD dwError = ERROR_SUCCESS;
+ PSERVICE_HANDLE hSvc;
+ PSERVICE lpService = NULL;
+ HKEY hServiceKey = NULL;
+ LPWSTR lpImagePath = NULL;
+ LPWSTR lpServiceStartName = NULL;
+ LPWSTR lpDependencies = NULL;
+ DWORD dwDependenciesLength = 0;
+ DWORD dwRequiredSize;
+ LPQUERY_SERVICE_CONFIGA lpConfig = NULL;
+ CHAR lpEmptyString[]={0,0};
+ LPSTR lpStr;
+
+ DPRINT("RQueryServiceConfigA() called\n");
+
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
+
+ hSvc = ScmGetServiceFromHandle(hService);
+ if (hSvc == NULL)
+ {
+ DPRINT1("Invalid service handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+ SERVICE_QUERY_CONFIG))
+ {
+ DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ lpService = hSvc->ServiceEntry;
+ if (lpService == NULL)
+ {
+ DPRINT("lpService == NULL!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ /* FIXME: Lock the service database shared */
+
+ dwError = ScmOpenServiceKey(lpService->lpServiceName,
+ KEY_READ,
+ &hServiceKey);
+ if (dwError != ERROR_SUCCESS)
+ goto Done;
+
+ /* Read the image path */
+ dwError = ScmReadString(hServiceKey,
+ L"ImagePath",
+ &lpImagePath);
+ if (dwError != ERROR_SUCCESS)
+ goto Done;
+
+ /* Read the service start name */
+ ScmReadString(hServiceKey,
+ L"ObjectName",
+ &lpServiceStartName);
+
+ /* Read the dependencies */
+ ScmReadDependencies(hServiceKey,
+ &lpDependencies,
+ &dwDependenciesLength);
+
+ dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGW);
+
+ if (lpImagePath != NULL)
+ dwRequiredSize += wcslen(lpImagePath) + 1;
+ else
+ dwRequiredSize += 2;
+
+ if ((lpService->lpGroup != NULL) && (lpService->lpGroup->lpGroupName != NULL))
+ dwRequiredSize += wcslen(lpService->lpGroup->lpGroupName) + 1;
+ else
+ dwRequiredSize += 2;
+
+ /* Add Dependencies length */
+ if (lpDependencies != NULL)
+ dwRequiredSize += dwDependenciesLength;
+ else
+ dwRequiredSize += 2;
+
+ if (lpServiceStartName != NULL)
+ dwRequiredSize += wcslen(lpServiceStartName) + 1;
+ else
+ dwRequiredSize += 2;
+
+ if (lpService->lpDisplayName != NULL)
+ dwRequiredSize += wcslen(lpService->lpDisplayName) + 1;
+ else
+ dwRequiredSize += 2;
+
+ if (lpServiceConfig == NULL || cbBufSize < dwRequiredSize)
+ {
+ dwError = ERROR_INSUFFICIENT_BUFFER;
+ }
+ else
+ {
+ lpConfig = (LPQUERY_SERVICE_CONFIGA)lpServiceConfig;
+ lpConfig->dwServiceType = lpService->Status.dwServiceType;
+ lpConfig->dwStartType = lpService->dwStartType;
+ lpConfig->dwErrorControl = lpService->dwErrorControl;
+ lpConfig->dwTagId = lpService->dwTag;
+
+ lpStr = (LPSTR)(lpServiceConfig + 1);
+
+ /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
+ Verified in WINXP*/
+
+ if (lpImagePath)
+ {
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ lpImagePath,
+ -1,
+ lpStr,
+ wcslen(lpImagePath) + 1,
+ 0,
+ 0);
+ }
+ else
+ {
+ strcpy(lpStr, lpEmptyString);
+ }
+
+ lpConfig->lpBinaryPathName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
+ lpStr += (strlen((LPSTR)lpStr) + 1);
+
+ if (lpService->lpGroup && lpService->lpGroup->lpGroupName)
+ {
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ lpService->lpGroup->lpGroupName,
+ -1,
+ lpStr,
+ wcslen(lpService->lpGroup->lpGroupName) + 1,
+ 0,
+ 0);
+ }
+ else
+ {
+ strcpy(lpStr, lpEmptyString);
+ }
+
+ lpConfig->lpLoadOrderGroup = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
+ lpStr += (strlen(lpStr) + 1);
+
+ /* Append Dependencies */
+ if (lpDependencies)
+ {
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ lpDependencies,
+ dwDependenciesLength,
+ lpStr,
+ dwDependenciesLength,
+ 0,
+ 0);
+ }
+ else
+ {
+ strcpy(lpStr, lpEmptyString);
+ }
+
+ lpConfig->lpDependencies = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
+ if (lpDependencies)
+ lpStr += dwDependenciesLength;
+ else
+ lpStr += (strlen(lpStr) + 1);
+
+ if (lpServiceStartName)
+ {
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ lpServiceStartName,
+ -1,
+ lpStr,
+ wcslen(lpServiceStartName) + 1,
+ 0,
+ 0);
+ }
+ else
+ {
+ strcpy(lpStr, lpEmptyString);
+ }
+
+ lpConfig->lpServiceStartName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
+ lpStr += (strlen(lpStr) + 1);
+
+ if (lpService->lpDisplayName)
+ {
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ lpService->lpDisplayName,
+ -1,
+ lpStr,
+ wcslen(lpService->lpDisplayName) + 1,
+ 0,
+ 0);
+ }
+ else
+ {
+ strcpy(lpStr, lpEmptyString);
+ }
+
+ lpConfig->lpDisplayName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
+ }
+
+ if (pcbBytesNeeded != NULL)
+ *pcbBytesNeeded = dwRequiredSize;
+
+Done:;
+ if (lpImagePath != NULL)
+ HeapFree(GetProcessHeap(), 0, lpImagePath);
+
+ if (lpServiceStartName != NULL)
+ HeapFree(GetProcessHeap(), 0, lpServiceStartName);
+
+ if (lpDependencies != NULL)
+ HeapFree(GetProcessHeap(), 0, lpDependencies);
+
+ if (hServiceKey != NULL)
+ RegCloseKey(hServiceKey);
+
+ /* FIXME: Unlock the service database */
+
+ DPRINT("RQueryServiceConfigA() done\n");
+
+ return dwError;
+}
+
+
+/* Function 30 */
+DWORD RQueryServiceLockStatusA(
+ SC_RPC_HANDLE hSCManager,
+ LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
+ DWORD cbBufSize,
+ LPBOUNDED_DWORD_4K pcbBytesNeeded)
+{
+ UNIMPLEMENTED;
+ return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 31 */
+DWORD RStartServiceA(
+ SC_RPC_HANDLE hService,
+ DWORD argc,
+ LPSTRING_PTRSA argv)
+{
+ DWORD dwError = ERROR_SUCCESS;
+ PSERVICE_HANDLE hSvc;
+ PSERVICE lpService = NULL;
+
+ DPRINT("RStartServiceA() called\n");
+
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
+
+ hSvc = ScmGetServiceFromHandle(hService);
+ if (hSvc == NULL)
+ {
+ DPRINT1("Invalid service handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+ SERVICE_START))
+ {
+ DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ lpService = hSvc->ServiceEntry;
+ if (lpService == NULL)
+ {
+ DPRINT("lpService == NULL!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ if (lpService->dwStartType == SERVICE_DISABLED)
+ return ERROR_SERVICE_DISABLED;
+
+ if (lpService->bDeleted)
+ return ERROR_SERVICE_MARKED_FOR_DELETE;
+
+ /* FIXME: Convert argument vector to Unicode */
+
+ /* Start the service */
+ dwError = ScmStartService(lpService, 0, NULL);
+
+ /* FIXME: Free argument vector */
+
+ return dwError;
+}
+
+
+/* Function 32 */
+DWORD RGetServiceDisplayNameA(
+ SC_RPC_HANDLE hSCManager,
+ LPCSTR lpServiceName,
+ LPSTR lpDisplayName,
+ LPBOUNDED_DWORD_4K lpcchBuffer)
+{
+// PMANAGER_HANDLE hManager;
+ PSERVICE lpService = NULL;
+ DWORD dwLength;
+ DWORD dwError;
+ LPWSTR lpServiceNameW;
+
+ DPRINT("RGetServiceDisplayNameA() called\n");
+ DPRINT("hSCManager = %p\n", hSCManager);
+ DPRINT("lpServiceName: %s\n", lpServiceName);
+ DPRINT("lpDisplayName: %p\n", lpDisplayName);
+ DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
+
+// hManager = (PMANAGER_HANDLE)hSCManager;
+// if (hManager->Handle.Tag != MANAGER_TAG)
+// {
+// DPRINT("Invalid manager handle!\n");
+// return ERROR_INVALID_HANDLE;
+// }
+
+ if (lpServiceName != NULL)
+ {
+ dwLength = strlen(lpServiceName) + 1;
+ lpServiceNameW = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ dwLength * sizeof(WCHAR));
+ if (!lpServiceNameW)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ MultiByteToWideChar(CP_ACP,
+ 0,
+ lpServiceName,
+ -1,
+ lpServiceNameW,
+ dwLength);
+
+ lpService = ScmGetServiceEntryByName(lpServiceNameW);
+
+ HeapFree(GetProcessHeap(), 0, lpServiceNameW);
+ }
+
+ if (lpService == NULL)
+ {
+ DPRINT("Could not find a service!\n");
+
+ /* If the service could not be found and lpcchBuffer is 0, windows
+ puts null in lpDisplayName and puts 1 in lpcchBuffer */
+ if (*lpcchBuffer == 0)
+ {
+ *lpcchBuffer = 1;
+ if (lpDisplayName != NULL)
+ {
+ *lpDisplayName = '\0';
+ }
+ }
+ return ERROR_SERVICE_DOES_NOT_EXIST;
+ }
+
+ if (!lpService->lpDisplayName)
+ {
+ dwLength = wcslen(lpService->lpServiceName);
+ if (lpDisplayName != NULL &&
+ *lpcchBuffer > dwLength)
+ {
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ lpService->lpServiceName,
+ wcslen(lpService->lpServiceName),
+ lpDisplayName,
+ dwLength + 1,
+ NULL,
+ NULL);
+ return ERROR_SUCCESS;
+ }
+ }
+ else
+ {
+ dwLength = wcslen(lpService->lpDisplayName);
+ if (lpDisplayName != NULL &&
+ *lpcchBuffer > dwLength)
+ {
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ lpService->lpDisplayName,
+ wcslen(lpService->lpDisplayName),
+ lpDisplayName,
+ dwLength + 1,
+ NULL,
+ NULL);
+ return ERROR_SUCCESS;
+ }
+ }
+
+ dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
+
+ *lpcchBuffer = dwLength * 2;
+
+ return dwError;
+}
+
+
+/* Function 33 */
+DWORD RGetServiceKeyNameA(
+ SC_RPC_HANDLE hSCManager,
+ LPCSTR lpDisplayName,
+ LPSTR lpServiceName,
+ LPBOUNDED_DWORD_4K lpcchBuffer)
+{
+ PSERVICE lpService;
+ DWORD dwLength;
+ DWORD dwError;
+ LPWSTR lpDisplayNameW;
+
+ DPRINT("RGetServiceKeyNameA() called\n");
+ DPRINT("hSCManager = %p\n", hSCManager);
+ DPRINT("lpDisplayName: %s\n", lpDisplayName);
+ DPRINT("lpServiceName: %p\n", lpServiceName);
+ DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
+
+ dwLength = strlen(lpDisplayName) + 1;
+ lpDisplayNameW = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ dwLength * sizeof(WCHAR));
+ if (!lpDisplayNameW)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ MultiByteToWideChar(CP_ACP,
+ 0,
+ lpDisplayName,
+ -1,
+ lpDisplayNameW,
+ dwLength);
+
+ lpService = ScmGetServiceEntryByDisplayName(lpDisplayNameW);
+
+ HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
+
+ if (lpService == NULL)
+ {
+ DPRINT("Could not find the service!\n");
+
+ /* If the service could not be found and lpcchBuffer is 0,
+ put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
+ if (*lpcchBuffer == 0)
+ {
+ *lpcchBuffer = 1;
+ if (lpServiceName != NULL)
+ {
+ *lpServiceName = '\0';
+ }
+ }
+
+ return ERROR_SERVICE_DOES_NOT_EXIST;
+ }
+
+ dwLength = wcslen(lpService->lpServiceName);
+ if (lpServiceName != NULL &&
+ *lpcchBuffer > dwLength)
+ {
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ lpService->lpServiceName,
+ wcslen(lpService->lpServiceName),
+ lpServiceName,
+ dwLength + 1,
+ NULL,
+ NULL);
+ return ERROR_SUCCESS;
+ }
+
+ dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
+
+ *lpcchBuffer = dwLength * 2;
+
+ return dwError;
+}
+
+
+/* Function 34 */
+DWORD RI_ScGetCurrentGroupStateW(
+ SC_RPC_HANDLE hSCManager,
+ LPWSTR lpLoadOrderGroup,
+ LPDWORD lpState)
+{
+ UNIMPLEMENTED;
+ return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 35 */
+DWORD REnumServiceGroupW(
+ SC_RPC_HANDLE hSCManager,
+ DWORD dwServiceType,
+ DWORD dwServiceState,
+ LPBYTE lpBuffer,
+ DWORD cbBufSize,
+ LPBOUNDED_DWORD_256K pcbBytesNeeded,
+ LPBOUNDED_DWORD_256K lpServicesReturned,
+ LPBOUNDED_DWORD_256K lpResumeIndex,
+ LPCWSTR pszGroupName)
+{
+ UNIMPLEMENTED;
+ return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+//
+// WARNING: This function is untested
+//
+/* Function 36 */
+DWORD RChangeServiceConfig2A(
+ SC_RPC_HANDLE hService,
+ SC_RPC_CONFIG_INFOA Info)
+{
+ SC_RPC_CONFIG_INFOW InfoW;
+ DWORD dwRet, dwLength;
+ PVOID ptr = NULL;
+
+ DPRINT("RChangeServiceConfig2A() called\n");
+ DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel);
+
+ InfoW.dwInfoLevel = Info.dwInfoLevel;
+
+ if (InfoW.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
+ {
+ LPSERVICE_DESCRIPTIONW lpServiceDescriptonW;
+ LPSERVICE_DESCRIPTIONA lpServiceDescriptonA;
+
+ lpServiceDescriptonA = Info.psd;
+
+ ///if (lpServiceDescriptonA &&
+ ///lpServiceDescriptonA->lpDescription)
+ ///{
+ dwLength = (strlen(Info.lpDescription) + 1) * sizeof(WCHAR);
+
+ lpServiceDescriptonW = HeapAlloc(GetProcessHeap(),
+ 0,
+ dwLength + sizeof(SERVICE_DESCRIPTIONW));
+ if (!lpServiceDescriptonW)
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ lpServiceDescriptonW->lpDescription = (LPWSTR)(lpServiceDescriptonW + 1);
+
+ MultiByteToWideChar(CP_ACP,
+ 0,
+ Info.lpDescription,
+ -1,
+ lpServiceDescriptonW->lpDescription,
+ dwLength);
+
+ ptr = lpServiceDescriptonW;
+ InfoW.psd = lpServiceDescriptonW;
+ ///}
+ }
+ else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
+ {
+ LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW;
+ LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA;
+ DWORD dwRebootLen = 0;
+ DWORD dwCommandLen = 0;
+
+ lpServiceFailureActionsA = Info.psfa;
+
+ if (lpServiceFailureActionsA)
+ {
+ if (lpServiceFailureActionsA->lpRebootMsg)
+ {
+ dwRebootLen = (strlen(lpServiceFailureActionsA->lpRebootMsg) + 1) * sizeof(WCHAR);
+ }
+ if (lpServiceFailureActionsA->lpCommand)
+ {
+ dwCommandLen = (strlen(lpServiceFailureActionsA->lpCommand) + 1) * sizeof(WCHAR);
+ }
+ dwLength = dwRebootLen + dwCommandLen + sizeof(SERVICE_FAILURE_ACTIONSW);
+
+ lpServiceFailureActionsW = HeapAlloc(GetProcessHeap(),
+ 0,
+ dwLength);
+ if (!lpServiceFailureActionsW)
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ lpServiceFailureActionsW->cActions = lpServiceFailureActionsA->cActions;
+ lpServiceFailureActionsW->dwResetPeriod = lpServiceFailureActionsA->dwResetPeriod;
+ CopyMemory(lpServiceFailureActionsW->lpsaActions, lpServiceFailureActionsA->lpsaActions, sizeof(SC_ACTION));
+
+ if (lpServiceFailureActionsA->lpRebootMsg)
+ {
+ MultiByteToWideChar(CP_ACP,
+ 0,
+ lpServiceFailureActionsA->lpRebootMsg,
+ -1,
+ lpServiceFailureActionsW->lpRebootMsg,
+ dwRebootLen);
+ }
+
+ if (lpServiceFailureActionsA->lpCommand)
+ {
+ MultiByteToWideChar(CP_ACP,
+ 0,
+ lpServiceFailureActionsA->lpCommand,
+ -1,
+ lpServiceFailureActionsW->lpCommand,
+ dwCommandLen);
+ }
+
+ ptr = lpServiceFailureActionsW;
+ }
+ }
+
+ dwRet = RChangeServiceConfig2W(hService, InfoW);
+
+ HeapFree(GetProcessHeap(), 0, ptr);
+
+ return dwRet;
+}
+
+
+/* Function 37 */
+DWORD RChangeServiceConfig2W(
+ SC_RPC_HANDLE hService,
+ SC_RPC_CONFIG_INFOW Info)
+{
+ DWORD dwError = ERROR_SUCCESS;
+ PSERVICE_HANDLE hSvc;
+ PSERVICE lpService = NULL;
+ HKEY hServiceKey = NULL;
+
+ DPRINT("RChangeServiceConfig2W() called\n");
+ DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel);
+
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
+
+ hSvc = ScmGetServiceFromHandle(hService);
+ if (hSvc == NULL)
+ {
+ DPRINT1("Invalid service handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+ SERVICE_CHANGE_CONFIG))
+ {
+ DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ lpService = hSvc->ServiceEntry;
+ if (lpService == NULL)
+ {
+ DPRINT("lpService == NULL!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ /* FIXME: Lock database exclusively */
+
+ if (lpService->bDeleted)
+ {
+ /* FIXME: Unlock database */
+ DPRINT("The service has already been marked for delete!\n");
+ return ERROR_SERVICE_MARKED_FOR_DELETE;
+ }
+
+ /* Open the service key */
+ dwError = ScmOpenServiceKey(lpService->szServiceName,
+ KEY_SET_VALUE,
+ &hServiceKey);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ if (Info.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
+ {
+ LPSERVICE_DESCRIPTIONW lpServiceDescription;
+
+ lpServiceDescription = (LPSERVICE_DESCRIPTIONW)Info.psd;
+ lpServiceDescription->lpDescription = (LPWSTR)((ULONG_PTR)lpServiceDescription + sizeof(LPSERVICE_DESCRIPTIONW));
+
+ if (lpServiceDescription != NULL &&
+ lpServiceDescription->lpDescription != NULL)
+ {
+ DPRINT("Setting value %S\n", lpServiceDescription->lpDescription);
+ RegSetValueExW(hServiceKey,
+ L"Description",
+ 0,
+ REG_SZ,
+ (LPBYTE)lpServiceDescription->lpDescription,
+ (wcslen(lpServiceDescription->lpDescription) + 1) * sizeof(WCHAR));
+
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
+ }
+ else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
+ {
+ UNIMPLEMENTED;
+ dwError = ERROR_CALL_NOT_IMPLEMENTED;
+ goto done;
+ }
+
+done:
+ /* FIXME: Unlock database */
+ if (hServiceKey != NULL)
+ RegCloseKey(hServiceKey);
+
+ DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError);
+
+ return dwError;
+}
+
+
+/* Function 38 */
+DWORD RQueryServiceConfig2A(
+ SC_RPC_HANDLE hService,
+ DWORD dwInfoLevel,
+ LPBYTE lpBuffer,
+ DWORD cbBufSize,
+ LPBOUNDED_DWORD_8K pcbBytesNeeded)
+{
+ DWORD dwError = ERROR_SUCCESS;
+ PSERVICE_HANDLE hSvc;
+ PSERVICE lpService = NULL;
+ HKEY hServiceKey = NULL;
+ LPWSTR lpDescriptionW = NULL;
+ LPSTR lpDescription = NULL;
+
+ DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
+ hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
+
+ if (!lpBuffer)
+ return ERROR_INVALID_ADDRESS;
+
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
+
+ hSvc = ScmGetServiceFromHandle(hService);
+ if (hSvc == NULL)
+ {
+ DPRINT1("Invalid service handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+ SERVICE_QUERY_CONFIG))
+ {
+ DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ lpService = hSvc->ServiceEntry;
+ if (lpService == NULL)
+ {
+ DPRINT("lpService == NULL!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ /* FIXME: Lock the service database shared */
+
+ dwError = ScmOpenServiceKey(lpService->lpServiceName,
+ KEY_READ,
+ &hServiceKey);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
+ {
+ LPSERVICE_DESCRIPTIONA lpServiceDescription = (LPSERVICE_DESCRIPTIONA)lpBuffer;
+ LPSTR lpStr;
+
+ *pcbBytesNeeded = sizeof(SERVICE_DESCRIPTIONA);
+
+ dwError = ScmReadString(hServiceKey,
+ L"Description",
+ &lpDescriptionW);
+ if (dwError == ERROR_SUCCESS)
+ {
+ *pcbBytesNeeded += ((wcslen(lpDescriptionW) + 1) * sizeof(WCHAR));
+ }
+
+ if (cbBufSize >= *pcbBytesNeeded)
+ {
+
+ if (dwError == ERROR_SUCCESS)
+ {
+ lpStr = (LPSTR)(lpServiceDescription + 1);
+
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ lpDescriptionW,
+ -1,
+ lpStr,
+ wcslen(lpDescriptionW),
+ NULL,
+ NULL);
+ lpServiceDescription->lpDescription = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceDescription);
+ }
+ else
+ {
+ lpServiceDescription->lpDescription = NULL;
+ goto done;
+ }
+ }
+ else
+ {
+ dwError = ERROR_INSUFFICIENT_BUFFER;
+ goto done;
+ }
+ }
+ else if (dwInfoLevel & SERVICE_CONFIG_FAILURE_ACTIONS)
+ {
+ UNIMPLEMENTED;
+ dwError = ERROR_CALL_NOT_IMPLEMENTED;
+ goto done;
+ }
+
+done:
+ if (lpDescription != NULL)
+ HeapFree(GetProcessHeap(), 0, lpDescription);
+
+ if (hServiceKey != NULL)
+ RegCloseKey(hServiceKey);
+
+ /* FIXME: Unlock database */
+
+ DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError);
+
+ return dwError;
+}
+
+
+/* Function 39 */
+DWORD RQueryServiceConfig2W(
+ SC_RPC_HANDLE hService,
+ DWORD dwInfoLevel,
+ LPBYTE lpBuffer,
+ DWORD cbBufSize,
+ LPBOUNDED_DWORD_8K pcbBytesNeeded)
+{
+ DWORD dwError = ERROR_SUCCESS;
+ PSERVICE_HANDLE hSvc;
+ PSERVICE lpService = NULL;
+ HKEY hServiceKey = NULL;
+ DWORD dwRequiredSize;
+ LPWSTR lpDescription = NULL;
+ LPWSTR lpFailureCommand = NULL;
+ LPWSTR lpRebootMessage = NULL;
+
+ DPRINT("RQueryServiceConfig2W() called\n");
+
+ if (!lpBuffer)
+ return ERROR_INVALID_ADDRESS;
+
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
+
+ hSvc = ScmGetServiceFromHandle(hService);
+ if (hSvc == NULL)
+ {
+ DPRINT1("Invalid service handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+ SERVICE_QUERY_CONFIG))
+ {
+ DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ lpService = hSvc->ServiceEntry;
+ if (lpService == NULL)
+ {
+ DPRINT("lpService == NULL!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ /* FIXME: Lock the service database shared */
+
+ dwError = ScmOpenServiceKey(lpService->lpServiceName,
+ KEY_READ,
+ &hServiceKey);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
+ {
+ LPSERVICE_DESCRIPTIONW lpServiceDescription = (LPSERVICE_DESCRIPTIONW)lpBuffer;
+ LPWSTR lpStr;
+
+ dwError = ScmReadString(hServiceKey,
+ L"Description",
+ &lpDescription);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ dwRequiredSize = sizeof(SERVICE_DESCRIPTIONW) + ((wcslen(lpDescription) + 1) * sizeof(WCHAR));
+
+ if (cbBufSize < dwRequiredSize)
+ {
+ *pcbBytesNeeded = dwRequiredSize;
+ dwError = ERROR_INSUFFICIENT_BUFFER;
+ goto done;
+ }
+
+ lpStr = (LPWSTR)(lpServiceDescription + 1);
+ wcscpy(lpStr, lpDescription);
+ lpServiceDescription->lpDescription = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceDescription);
+ }
+ else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
+ {
+ LPWSTR lpStr;
+ LPSERVICE_FAILURE_ACTIONSW lpFailureActions = (LPSERVICE_FAILURE_ACTIONSW)lpBuffer;
+
+ UNIMPLEMENTED;
+
+ dwError = ScmReadString(hServiceKey,
+ L"FailureCommand",
+ &lpFailureCommand);
+
+ dwError = ScmReadString(hServiceKey,
+ L"RebootMessage",
+ &lpRebootMessage);
+
+ dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW);
+
+ if (lpFailureCommand)
+ dwRequiredSize += (wcslen(lpFailureCommand) + 1) * sizeof(WCHAR);
+
+ if (lpRebootMessage)
+ dwRequiredSize += (wcslen(lpRebootMessage) + 1) * sizeof(WCHAR);
+
+ if (cbBufSize < dwRequiredSize)
+ {
+ *pcbBytesNeeded = dwRequiredSize;
+ dwError = ERROR_INSUFFICIENT_BUFFER;
+ goto done;
+ }
+
+ lpFailureActions->cActions = 0;
+ lpFailureActions->dwResetPeriod = 0;
+ lpFailureActions->lpCommand = NULL;
+ lpFailureActions->lpRebootMsg = NULL;
+ lpFailureActions->lpsaActions = NULL;
+
+ lpStr = (LPWSTR)(lpFailureActions + 1);
+ if (lpRebootMessage)
+ {
+ wcscpy(lpStr, lpRebootMessage);
+ lpFailureActions->lpRebootMsg = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpRebootMessage);
+ lpStr += wcslen(lpRebootMessage) + 1;
+ }
+
+ if (lpFailureCommand)
+ {
+ wcscpy(lpStr, lpFailureCommand);
+ lpFailureActions->lpCommand = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureCommand);
+ lpStr += wcslen(lpRebootMessage) + 1;
+ }
+ dwError = STATUS_SUCCESS;
+ goto done;
+ }
+
+done:
+ if (lpDescription != NULL)
+ HeapFree(GetProcessHeap(), 0, lpDescription);
+
+ if (lpRebootMessage != NULL)
+ HeapFree(GetProcessHeap(), 0, lpRebootMessage);
+
+ if (lpFailureCommand != NULL)
+ HeapFree(GetProcessHeap(), 0, lpFailureCommand);
+
+ if (hServiceKey != NULL)
+ RegCloseKey(hServiceKey);
+
+ /* FIXME: Unlock database */
+
+ DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError);
+
+ return dwError;
+}
+
+
+/* Function 40 */
+DWORD RQueryServiceStatusEx(
+ SC_RPC_HANDLE hService,
+ SC_STATUS_TYPE InfoLevel,
+ LPBYTE lpBuffer,
+ DWORD cbBufSize,
+ LPBOUNDED_DWORD_8K pcbBytesNeeded)
+{
+ LPSERVICE_STATUS_PROCESS lpStatus;
+ PSERVICE_HANDLE hSvc;
+ PSERVICE lpService;
+
+ DPRINT("RQueryServiceStatusEx() called\n");
+
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
+
+ if (InfoLevel != SC_STATUS_PROCESS_INFO)
+ return ERROR_INVALID_LEVEL;
+
+ *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS);
+
+ if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
+ return ERROR_INSUFFICIENT_BUFFER;
+
+ hSvc = ScmGetServiceFromHandle(hService);
+ if (hSvc == NULL)
+ {
+ DPRINT1("Invalid service handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+ SERVICE_QUERY_STATUS))
+ {
+ DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ lpService = hSvc->ServiceEntry;
+ if (lpService == NULL)
+ {
+ DPRINT("lpService == NULL!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ lpStatus = (LPSERVICE_STATUS_PROCESS)lpBuffer;
+
+ /* Return service status information */
+ RtlCopyMemory(lpStatus,
+ &lpService->Status,
+ sizeof(SERVICE_STATUS));
+
+ lpStatus->dwProcessId = lpService->ProcessId; /* FIXME */
+ lpStatus->dwServiceFlags = 0; /* FIXME */
+
+ return ERROR_SUCCESS;
+}
+
+
+/* Function 41 */
+DWORD REnumServicesStatusExA(
+ SC_RPC_HANDLE hSCManager,
+ SC_ENUM_TYPE InfoLevel,
+ DWORD dwServiceType,
+ DWORD dwServiceState,
+ LPBYTE lpBuffer,
+ DWORD cbBufSize,
+ LPBOUNDED_DWORD_256K pcbBytesNeeded,
+ LPBOUNDED_DWORD_256K lpServicesReturned,
+ LPBOUNDED_DWORD_256K lpResumeIndex,
+ LPCSTR pszGroupName)
+{
+ LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW = NULL;
+ LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA = NULL;
+ LPWSTR lpStringPtrW;
+ LPSTR lpStringPtrA;
+ LPWSTR pszGroupNameW = NULL;
+ DWORD dwError;
+ DWORD dwServiceCount;
+
+ DPRINT("REnumServicesStatusExA() called\n");
+
+ if (pszGroupName)
+ {
+ pszGroupNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (strlen(pszGroupName) + 1) * sizeof(WCHAR));
+ if (!pszGroupNameW)
+ {
+ DPRINT("Failed to allocate buffer!\n");
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ MultiByteToWideChar(CP_ACP,
+ 0,
+ pszGroupName,
+ -1,
+ pszGroupNameW,
+ strlen(pszGroupName) + 1);
+ }
+
+ if ((cbBufSize > 0) && (lpBuffer))
+ {
+ lpStatusPtrW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbBufSize);
+ if (!lpStatusPtrW)
+ {
+ DPRINT("Failed to allocate buffer!\n");
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+ }
+
+ dwError = REnumServicesStatusExW(hSCManager,
+ InfoLevel,
+ dwServiceType,
+ dwServiceState,
+ (LPBYTE)lpStatusPtrW,
+ cbBufSize,
+ pcbBytesNeeded,
+ lpServicesReturned,
+ lpResumeIndex,
+ pszGroupNameW);
+
+ /* if no services were returned then we are Done */
+ if (*lpServicesReturned == 0)
+ goto Done;
+
+ lpStatusPtrA = (LPENUM_SERVICE_STATUS_PROCESSA)lpBuffer;
+ lpStringPtrA = (LPSTR)((ULONG_PTR)lpBuffer +
+ *lpServicesReturned * sizeof(ENUM_SERVICE_STATUS_PROCESSA));
+ lpStringPtrW = (LPWSTR)((ULONG_PTR)lpStatusPtrW +
+ *lpServicesReturned * sizeof(ENUM_SERVICE_STATUS_PROCESSW));
+
+ for (dwServiceCount = 0; dwServiceCount < *lpServicesReturned; dwServiceCount++)
+ {
+ /* Copy the service name */
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ lpStringPtrW,
+ -1,
+ lpStringPtrA,
+ wcslen(lpStringPtrW),
+ 0,
+ 0);
+
+ lpStatusPtrA->lpServiceName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer);
+ lpStringPtrA += wcslen(lpStringPtrW) + 1;
+ lpStringPtrW += wcslen(lpStringPtrW) + 1;
+
+ /* Copy the display name */
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ lpStringPtrW,
+ -1,
+ lpStringPtrA,
+ wcslen(lpStringPtrW),
+ 0,
+ 0);
+
+ lpStatusPtrA->lpDisplayName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer);
+ lpStringPtrA += wcslen(lpStringPtrW) + 1;
+ lpStringPtrW += wcslen(lpStringPtrW) + 1;
+
+ /* Copy the status information */
+ memcpy(&lpStatusPtrA->ServiceStatusProcess,
+ &lpStatusPtrW->ServiceStatusProcess,
+ sizeof(SERVICE_STATUS));
+
+ lpStatusPtrA->ServiceStatusProcess.dwProcessId = lpStatusPtrW->ServiceStatusProcess.dwProcessId; /* FIXME */
+ lpStatusPtrA->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */
+ lpStatusPtrA++;
+ }
+
+Done:;
+ if (pszGroupNameW)
+ HeapFree(GetProcessHeap(), 0, pszGroupNameW);
+
+ if (lpStatusPtrW)
+ HeapFree(GetProcessHeap(), 0, lpStatusPtrW);
+
+ DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError);
+
+ return dwError;
+}
+
+
+/* Function 42 */
+DWORD REnumServicesStatusExW(
+ SC_RPC_HANDLE hSCManager,
+ SC_ENUM_TYPE InfoLevel,
+ DWORD dwServiceType,
+ DWORD dwServiceState,
+ LPBYTE lpBuffer,
+ DWORD cbBufSize,
+ LPBOUNDED_DWORD_256K pcbBytesNeeded,
+ LPBOUNDED_DWORD_256K lpServicesReturned,
+ LPBOUNDED_DWORD_256K lpResumeIndex,
+ LPCWSTR pszGroupName)
+{
+ PMANAGER_HANDLE hManager;
+ PSERVICE lpService;
+ DWORD dwError = ERROR_SUCCESS;
+ PLIST_ENTRY ServiceEntry;
+ PSERVICE CurrentService;
+ DWORD dwState;
+ DWORD dwRequiredSize;
+ DWORD dwServiceCount;
+ DWORD dwSize;
+ DWORD dwLastResumeCount = 0;
+ LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr;
+ LPWSTR lpStringPtr;
+
+ DPRINT("REnumServicesStatusExW() called\n");
+
+ if (ScmShutdown)
+ return ERROR_SHUTDOWN_IN_PROGRESS;
+
+ if (InfoLevel != SC_ENUM_PROCESS_INFO)
+ return ERROR_INVALID_LEVEL;
+
+ hManager = ScmGetServiceManagerFromHandle(hSCManager);
+ if (hManager == NULL)
+ {
+ DPRINT1("Invalid service manager handle!\n");
+ return ERROR_INVALID_HANDLE;
+ }
+
+ *pcbBytesNeeded = 0;
+ *lpServicesReturned = 0;
+
+ if ((dwServiceType!=SERVICE_DRIVER) && (dwServiceType!=SERVICE_WIN32))
+ {
+ DPRINT("Not a valid Service Type!\n");
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ if ((dwServiceState<SERVICE_ACTIVE) || (dwServiceState>SERVICE_STATE_ALL))
+ {
+ DPRINT("Not a valid Service State!\n");
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ /* Check access rights */
+ if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
+ SC_MANAGER_ENUMERATE_SERVICE))
+ {
+ DPRINT("Insufficient access rights! 0x%lx\n",
+ hManager->Handle.DesiredAccess);
+ return ERROR_ACCESS_DENIED;
+ }
+
+ if (lpResumeIndex) dwLastResumeCount = *lpResumeIndex;
+
+ /* Lock the service list shared */
+
+ lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount);
+ if (lpService == NULL)
+ {
+ dwError = ERROR_SUCCESS;
+ goto Done;
+ }
+
+ dwRequiredSize = 0;
+ dwServiceCount = 0;
+
+ for (ServiceEntry = &lpService->ServiceListEntry;
+ ServiceEntry != &ServiceListHead;
+ ServiceEntry = ServiceEntry->Flink)
+ {
+ CurrentService = CONTAINING_RECORD(ServiceEntry,
+ SERVICE,
+ ServiceListEntry);
+
+ if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
+ continue;
+
+ dwState = SERVICE_ACTIVE;
+ if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
+ dwState = SERVICE_INACTIVE;
+
+ if ((dwState & dwServiceState) == 0)
+ continue;
+
+ if (pszGroupName)
+ {
+ if (*pszGroupName == 0)
+ {
+ if (CurrentService->lpGroup != NULL)
+ continue;
+ }
+ else
+ {
+ if ((CurrentService->lpGroup == NULL) ||
+ _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
+ continue;
+ }
+ }
+
+ dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
+ ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
+ ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
+
+ if (dwRequiredSize + dwSize <= cbBufSize)
+ {
+ DPRINT("Service name: %S fit\n", CurrentService->lpServiceName);
+ dwRequiredSize += dwSize;
+ dwServiceCount++;
+ dwLastResumeCount = CurrentService->dwResumeCount;
+ }
+ else
+ {
+ DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName);
+ break;
+ }
+
+ }
+
+ DPRINT("dwRequiredSize: %lu\n", dwRequiredSize);
+ DPRINT("dwServiceCount: %lu\n", dwServiceCount);
+
+ for (;
+ ServiceEntry != &ServiceListHead;
+ ServiceEntry = ServiceEntry->Flink)
+ {
+ CurrentService = CONTAINING_RECORD(ServiceEntry,
+ SERVICE,
+ ServiceListEntry);
+
+ if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
+ continue;
+
+ dwState = SERVICE_ACTIVE;
+ if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
+ dwState = SERVICE_INACTIVE;
+
+ if ((dwState & dwServiceState) == 0)
+ continue;
+
+ if (pszGroupName)
+ {
+ if (*pszGroupName == 0)
+ {
+ if (CurrentService->lpGroup != NULL)
+ continue;
+ }
+ else
+ {
+ if ((CurrentService->lpGroup == NULL) ||
+ _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
+ continue;
+ }
+ }
+
+ dwRequiredSize += (sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
+ ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
+ ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
+
+ dwError = ERROR_MORE_DATA;
+ }
+
+ DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
+
+ if (lpResumeIndex)
+ *lpResumeIndex = dwLastResumeCount;
+
+ *lpServicesReturned = dwServiceCount;
+ *pcbBytesNeeded = dwRequiredSize;
+
+ /* If there was no services that matched */
+ if ((!dwServiceCount) && (dwError != ERROR_MORE_DATA))
+ {
+ dwError = ERROR_SERVICE_DOES_NOT_EXIST;
+ goto Done;
+ }
+
+ lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpBuffer;
+ lpStringPtr = (LPWSTR)((ULONG_PTR)lpBuffer +
+ dwServiceCount * sizeof(ENUM_SERVICE_STATUS_PROCESSW));
+
+ dwRequiredSize = 0;
+ for (ServiceEntry = &lpService->ServiceListEntry;
+ ServiceEntry != &ServiceListHead;
+ ServiceEntry = ServiceEntry->Flink)
+ {
+ CurrentService = CONTAINING_RECORD(ServiceEntry,
+ SERVICE,
+ ServiceListEntry);
+
+ if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
+ continue;
+
+ dwState = SERVICE_ACTIVE;
+ if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
+ dwState = SERVICE_INACTIVE;
+
+ if ((dwState & dwServiceState) == 0)
+ continue;
+
+ if (pszGroupName)
+ {
+ if (*pszGroupName == 0)
+ {
+ if (CurrentService->lpGroup != NULL)
+ continue;
+ }
+ else
+ {
+ if ((CurrentService->lpGroup == NULL) ||
+ _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
+ continue;
+ }
+ }
+
+ dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
+ ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
+ ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
+
+ if (dwRequiredSize + dwSize <= cbBufSize)
+ {
+ /* Copy the service name */
+ wcscpy(lpStringPtr,
+ CurrentService->lpServiceName);
+ lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
+ lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
+
+ /* Copy the display name */
+ wcscpy(lpStringPtr,
+ CurrentService->lpDisplayName);
+ lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
+ lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
+
+ /* Copy the status information */
+ memcpy(&lpStatusPtr->ServiceStatusProcess,
+ &CurrentService->Status,
+ sizeof(SERVICE_STATUS));
+ lpStatusPtr->ServiceStatusProcess.dwProcessId = CurrentService->ProcessId; /* FIXME */
+ lpStatusPtr->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */
+
+ lpStatusPtr++;
+ dwRequiredSize += dwSize;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (dwError == 0)
+ {
+ *pcbBytesNeeded = 0;
+ if (lpResumeIndex)
+ *lpResumeIndex = 0;
+ }
+
+Done:;
+ /* Unlock the service list */
+
+ DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError);
+
+ return dwError;
+}
+
+
+/* Function 43 */
+DWORD RSendTSMessage(
+ handle_t BindingHandle) /* FIXME */
+{
+ UNIMPLEMENTED;
+ return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 44 */
+DWORD RCreateServiceWOW64A(
+ handle_t BindingHandle,
+ LPSTR lpServiceName,
+ LPSTR lpDisplayName,
+ DWORD dwDesiredAccess,
+ DWORD dwServiceType,
+ DWORD dwStartType,
+ DWORD dwErrorControl,
+ LPSTR lpBinaryPathName,
+ LPSTR lpLoadOrderGroup,
+ LPDWORD lpdwTagId,
+ LPBYTE lpDependencies,
+ DWORD dwDependSize,
+ LPSTR lpServiceStartName,
+ LPBYTE lpPassword,
+ DWORD dwPwSize,
+ LPSC_RPC_HANDLE lpServiceHandle)
+{
+ UNIMPLEMENTED;
+ return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 45 */
+DWORD RCreateServiceWOW64W(
+ handle_t BindingHandle,
+ LPWSTR lpServiceName,
+ LPWSTR lpDisplayName,
+ DWORD dwDesiredAccess,
+ DWORD dwServiceType,
+ DWORD dwStartType,
+ DWORD dwErrorControl,
+ LPWSTR lpBinaryPathName,
+ LPWSTR lpLoadOrderGroup,
+ LPDWORD lpdwTagId,
+ LPBYTE lpDependencies,
+ DWORD dwDependSize,
+ LPWSTR lpServiceStartName,
+ LPBYTE lpPassword,
+ DWORD dwPwSize,
+ LPSC_RPC_HANDLE lpServiceHandle)
+{
+ UNIMPLEMENTED;
+ return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 46 */
+DWORD RQueryServiceTagInfo(
+ handle_t BindingHandle) /* FIXME */
+{
+ UNIMPLEMENTED;
+ return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 47 */
+DWORD RNotifyServiceStatusChange(
+ SC_RPC_HANDLE hService,
+ SC_RPC_NOTIFY_PARAMS NotifyParams,
+ GUID *pClientProcessGuid,
+ GUID *pSCMProcessGuid,
+ PBOOL pfCreateRemoteQueue,
+ LPSC_NOTIFY_RPC_HANDLE phNotify)
+{
+ UNIMPLEMENTED;
+ return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 48 */
+DWORD RGetNotifyResults(
+ SC_NOTIFY_RPC_HANDLE hNotify,
+ PSC_RPC_NOTIFY_PARAMS_LIST *ppNotifyParams)
+{
+ UNIMPLEMENTED;
+ return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 49 */
+DWORD RCloseNotifyHandle(
+ LPSC_NOTIFY_RPC_HANDLE phNotify,
+ PBOOL pfApcFired)
+{
+ UNIMPLEMENTED;
+ return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 50 */
+DWORD RControlServiceExA(
+ SC_RPC_HANDLE hService,
+ DWORD dwControl,
+ DWORD dwInfoLevel)
+{
+ UNIMPLEMENTED;
+ return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 51 */
+DWORD RControlServiceExW(
+ SC_RPC_HANDLE hService,
+ DWORD dwControl,
+ DWORD dwInfoLevel)
+{
+ UNIMPLEMENTED;
+ return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 52 */
+DWORD RSendPnPMessage(
+ handle_t BindingHandle) /* FIXME */
+{
+ UNIMPLEMENTED;
+ return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 53 */
+DWORD RValidatePnPService(
+ handle_t BindingHandle) /* FIXME */
+{
+ UNIMPLEMENTED;
+ return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 54 */
+DWORD ROpenServiceStatusHandle(
+ handle_t BindingHandle) /* FIXME */
+{
+ UNIMPLEMENTED;
+ return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 55 */
+DWORD RFunction55(
+ handle_t BindingHandle) /* FIXME */
+{
+ UNIMPLEMENTED;
+ return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
+{
+ return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
+}
+
+
+void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
+{
+ HeapFree(GetProcessHeap(), 0, ptr);
+}
+
+
+void __RPC_USER SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject)
+{
+}
+
+
+void __RPC_USER SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock)
+{
+}
+
+
+void __RPC_USER SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify)
+{
+}
+
+/* EOF */
HKLM,"SYSTEM\CurrentControlSet\Services\Blue","ErrorControl",0x00010001,0x00000000
HKLM,"SYSTEM\CurrentControlSet\Services\Blue","Group",0x00000000,"Video Init"
HKLM,"SYSTEM\CurrentControlSet\Services\Blue","ImagePath",0x00020000,"system32\drivers\blue.sys"
- HKLM,"SYSTEM\CurrentControlSet\Services\Blue","Start",0x00010001,0x00000004
+ HKLM,"SYSTEM\CurrentControlSet\Services\Blue","Start",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\Blue","Type",0x00010001,0x00000001
; Cdfs (ISO96660) filesystem driver
media\fonts\tahoma.ttf 3
media\fonts\tahomabd.ttf 3
+ media\vgafonts\vgafonts.cab 4
+
media\nls\c_037.nls 1
media\nls\c_424.nls 1
media\nls\c_500.nls 1
typedef BOOL (WINAPI *SEEKPRINTER) (HANDLE,LARGE_INTEGER,PLARGE_INTEGER,DWORD,BOOL);
typedef BOOL (WINAPI *SPLREADPRINTER) (HANDLE,LPBYTE *,DWORD);
// Same as ddk/winsplp.h DriverUnloadComplete?
- typedef BOOL (WINAPI *SPLDRIVERUNLOADCOMPLETE) (LPWSTR);
+ typedef BOOL (WINAPI *SPLDRIVERUNLOADCOMPLETE) (LPWSTR);
// Driver support:
// DrvDocumentEvent api/winddiui.h not W2k8 DocumentEventAW
typedef INT (WINAPI *DOCUMENTEVENT) (HANDLE,HDC,INT,ULONG,PVOID,ULONG,PVOID);
VOID
HEAP_free(LPVOID memory);
- VOID
+ VOID
FASTCALL
FONT_TextMetricWToA(
- const TEXTMETRICW *ptmW,
+ const TEXTMETRICW *ptmW,
LPTEXTMETRICA ptmA
);
GdiSetLastError( DWORD dwErrCode );
DWORD WINAPI GdiGetCodePage(HDC);
- UINT FASTCALL DIB_BitmapBitsSize( PBITMAPINFO );
+ UINT FASTCALL DIB_BitmapBitsSize( CONST BITMAPINFO* );
int
WINAPI
INT iPixelFormat,
CONST PIXELFORMATDESCRIPTOR * ppfd)
{
+ /* Can only be set once */
+ INT current = GetPixelFormat(hdc);
+ if(current) return current == iPixelFormat ;
+
if (glSetPixelFormat == NULL)
if (OpenGLEnable() == FALSE)
return(0);
UINT
FASTCALL
- DIB_BitmapBitsSize( PBITMAPINFO Info )
+ DIB_BitmapBitsSize( CONST BITMAPINFO* Info )
{
UINT Ret;
if ( Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{
PBITMAPCOREHEADER Core = (PBITMAPCOREHEADER)Info;
- Ret = Core->bcHeight *
+ Ret = Core->bcHeight *
((Core->bcWidth * Core->bcPlanes * Core->bcBitCount + 31) & ~31 ) / 8;
}
else /* assume BITMAPINFOHEADER */
{
- if ((Info->bmiHeader.biCompression) &&
+ if ((Info->bmiHeader.biCompression) &&
(Info->bmiHeader.biCompression != BI_BITFIELDS))
return Info->bmiHeader.biSizeImage;
// Make Height positive always....
- Ret = abs(Info->bmiHeader.biHeight) *
+ Ret = abs(Info->bmiHeader.biHeight) *
((Info->bmiHeader.biWidth * Info->bmiHeader.biPlanes * Info->bmiHeader.biBitCount + 31) & ~31 ) / 8;
}
return Ret;
GdiGetBitmapBitsSize(BITMAPINFO *lpbmi)
{
int retSize;
-
+
if (lpbmi->bmiHeader.biSize == FIELD_OFFSET(BITMAPINFOHEADER, biPlanes))
{
/* Calc the bits Size and align it*/
- retSize = HIWORD(lpbmi->bmiHeader.biWidth) * ((LOWORD(lpbmi->bmiHeader.biWidth) *
- LOWORD(lpbmi->bmiHeader.biHeight) * HIWORD(lpbmi->bmiHeader.biHeight) + 31)
+ retSize = HIWORD(lpbmi->bmiHeader.biWidth) * ((LOWORD(lpbmi->bmiHeader.biWidth) *
+ LOWORD(lpbmi->bmiHeader.biHeight) * HIWORD(lpbmi->bmiHeader.biHeight) + 31)
& -32) / 8;
}
else
if (lpbmi->bmiHeader.biHeight >=0 )
{
/* Calc the bits Size and align it*/
- retSize = lpbmi->bmiHeader.biHeight * ((lpbmi->bmiHeader.biWidth *
+ retSize = lpbmi->bmiHeader.biHeight * ((lpbmi->bmiHeader.biWidth *
lpbmi->bmiHeader.biPlanes * lpbmi->bmiHeader.biBitCount + 31) & -32) / 8;
}
else
{
/* Make height postiive if it negitve then calc the bits Size and align it*/
- retSize = (-lpbmi->bmiHeader.biHeight) * ((lpbmi->bmiHeader.biWidth *
+ retSize = (-lpbmi->bmiHeader.biHeight) * ((lpbmi->bmiHeader.biWidth *
lpbmi->bmiHeader.biPlanes * lpbmi->bmiHeader.biBitCount + 31) & -32) / 8;
}
}
{ // Verify header due to converted may == info.
if ( pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
{
- if ( pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
+ if ( pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
pConvertedInfo->bmiHeader.biCompression == BI_PNG )
{
SetLastError(ERROR_INVALID_PARAMETER);
(!(pbm->bmWidthBytes & 1)) )
{
-
+
bitmap = CreateBitmap(pbm->bmWidth,
pbm->bmHeight,
pbm->bmPlanes,
{
if ( lpbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
{
- if ( lpbmi->bmiHeader.biCompression == BI_JPEG ||
+ if ( lpbmi->bmiHeader.biCompression == BI_JPEG ||
lpbmi->bmiHeader.biCompression == BI_PNG )
{
SetLastError(ERROR_INVALID_PARAMETER);
LONG width, height, compr, dibsize;
WORD planes, bpp;
// PDC_ATTR pDc_Attr;
- PBITMAPINFO pConvertedInfo;
- UINT ConvertedInfoSize;
- UINT cjBmpScanSize;
- PVOID pvSafeBits = NULL;
+ UINT InfoSize = 0;
+ UINT cjBmpScanSize = 0;
HBITMAP hBmp;
+ NTSTATUS Status = STATUS_SUCCESS;
if (!Header) return 0;
- pConvertedInfo = ConvertBitmapInfo(Data, ColorUse,
- &ConvertedInfoSize, FALSE);
-
if (DIB_GetBitmapInfo(Header, &width, &height, &planes, &bpp, &compr, &dibsize) == -1)
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
- if ( pConvertedInfo )
- {
- if ( pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
- {
- if ( pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
- pConvertedInfo->bmiHeader.biCompression == BI_PNG )
- {
- hBmp = NULL;
- goto Exit;
- }
- }
- }
-
// For Icm support.
// GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
- cjBmpScanSize = DIB_BitmapBitsSize((LPBITMAPINFO)pConvertedInfo);
- DPRINT("pBMI %x, Size bpp %d, dibsize %d, Conv %d, BSS %d\n", pConvertedInfo,bpp,dibsize,ConvertedInfoSize,cjBmpScanSize);
+ if(Data)
+ {
+ _SEH2_TRY
+ {
+ cjBmpScanSize = DIB_BitmapBitsSize(Data);
+ CalculateColorTableSize(&Data->bmiHeader, &ColorUse, &InfoSize);
+ InfoSize += Data->bmiHeader.biSize;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END
+ }
+
+ if(!NT_SUCCESS(Status))
+ {
+ GdiSetLastError(ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ DPRINT("pBMI %x, Size bpp %d, dibsize %d, Conv %d, BSS %d\n", Data,bpp,dibsize,InfoSize,cjBmpScanSize);
if ( !width || !height )
hBmp = GetStockObject(DEFAULT_BITMAP);
else
{
- if ( Bits && Init == CBM_INIT )
- {
- pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
- if (pvSafeBits == NULL)
- {
- hBmp = NULL;
- goto Exit;
- }
- else
- {
- RtlCopyMemory( pvSafeBits, Bits, cjBmpScanSize);
- }
- }
-
hBmp = NtGdiCreateDIBitmapInternal(hDC,
width,
height,
Init,
- (LPBYTE)pvSafeBits,
- (PBITMAPINFO)pConvertedInfo,
+ (LPBYTE)Bits,
+ (LPBITMAPINFO)Data,
ColorUse,
- ConvertedInfoSize,
+ InfoSize,
cjBmpScanSize,
0,
0);
-
- if ( Bits && Init == CBM_INIT )
- RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
}
- Exit:
- if (Data != pConvertedInfo)
- RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
return hBmp;
}
if ( hOldBitmap )
{
- if ( hDC )
+ if ( hDC )
hPal = SelectPalette(SavehDC, (HPALETTE)GetDCObject(hDC, GDI_OBJECT_TYPE_PALETTE), FALSE);
if ( lpbmi->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
/*
if ( !pDc_Attr ||
((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
- (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
+ (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
{
LinesCopied = NtGdiSetDIBitsToDeviceInternal( hdc,
RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
if (lpbmi != pConvertedInfo)
RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
-
+
return LinesCopied;
}
}
}
#endif
- if ( iUsage ) // Save time, we only look at non RGB.
- {
- pConvertedInfo = ConvertBitmapInfo(lpBitsInfo, iUsage,
- &ConvertedInfoSize, FALSE);
- if (!pConvertedInfo)
- {
+ pConvertedInfo = ConvertBitmapInfo(lpBitsInfo, iUsage,
+ &ConvertedInfoSize, FALSE);
+ if (!pConvertedInfo)
+ {
return 0;
- }
- }
- else
- pConvertedInfo = (PBITMAPINFO)lpBitsInfo;
+ }
cjBmpScanSize = DIB_BitmapBitsSize((LPBITMAPINFO)pConvertedInfo);
/*
if ( !pDc_Attr ||
((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
- (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
+ (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
{
LinesCopied = NtGdiStretchDIBitsInternal( hdc,
{
UNICODE_STRING Device, Output;
HDC hDC = NULL;
- BOOL Display = FALSE, Default = TRUE;
+ BOOL Display = FALSE, Default = FALSE;
ULONG UMdhpdev = 0;
HANDLE hspool = NULL;
if ((!lpwszDevice) && (!lpwszDriver))
{
- Default = FALSE; // Ask Win32k to set Default device.
+ Default = TRUE; // Ask Win32k to set Default device.
Display = TRUE; // Most likely to be DISPLAY.
}
else
DPRINT1("Not a DISPLAY device! %wZ\n", &Device);
}
- hDC = NtGdiOpenDCW( (Default ? &Device : NULL),
+ hDC = NtGdiOpenDCW( (Default ? NULL : &Device),
(PDEVMODEW) lpInitData,
(lpwszOutput ? &Output : NULL),
iType, // DCW 0 and ICW 1.
DeleteObject(HGDIOBJ hObject)
{
UINT Type = 0;
-
+
/* From Wine: DeleteObject does not SetLastError() on a null object */
if(!hObject) return FALSE;
Type = GDI_HANDLE_GET_TYPE(hObject);
- if ((Type == GDI_OBJECT_TYPE_METAFILE) ||
+ if ((Type == GDI_OBJECT_TYPE_METAFILE) ||
(Type == GDI_OBJECT_TYPE_ENHMETAFILE))
return FALSE;
case GDI_OBJECT_TYPE_METADC:
return MFDRV_DeleteObject( hObject );
case GDI_OBJECT_TYPE_EMF:
- {
+ {
PLDC pLDC = GdiGetLDC(hObject);
if ( !pLDC ) return FALSE;
return EMFDRV_DeleteObject( hObject );
return NtGdiGetDeviceCaps(hDC,i);
}
DPRINT("Device CAPS2\n");
-
+
switch (i)
{
case DRIVERVERSION:
#if 0
case GDI_OBJECT_TYPE_METADC:
- return MFDRV_SelectObject( hDC, hGdiObj);
+ return MFDRV_SelectObject( hDC, hGdiObj);
case GDI_OBJECT_TYPE_EMF:
PLDC pLDC = GdiGetLDC(hDC);
if ( !pLDC ) return NULL;
HCURSOR
- CursorIconToCursor(HICON hIcon, BOOL SemiTransparent);
+ CursorIconToCursor(HICON hIcon,
+ BOOL SemiTransparent);
+
+ HICON CreateCursorIconFromData(PVOID ImageData,
+ ICONIMAGE* IconImage,
+ int cxDesired,
+ int cyDesired,
+ int xHotspot,
+ int yHotspot,
+ BOOL fIcon);
+
#include <pseh/pseh2.h>
#define HOOKID_TO_FLAG(HookId) (1 << ((HookId) + 1))
- #define ISITHOOKED(HookId) (GetWin32ClientInfo()->fsHooks & HOOKID_TO_FLAG(HookId))
+ #define ISITHOOKED(HookId) (GetWin32ClientInfo()->fsHooks & HOOKID_TO_FLAG(HookId) ||\
+ (GetWin32ClientInfo()->pDeskInfo && GetWin32ClientInfo()->pDeskInfo->fsHooks & HOOKID_TO_FLAG(HookId)))
/* Temporarily in here for now. */
typedef struct _USERAPIHOOKINFO
static __inline BOOL
IsThreadHooked(PCLIENTINFO pci)
{
- return pci->fsHooks != 0;
+ return (pci->fsHooks|pci->pDeskInfo->fsHooks) != 0;
}
static __inline PDESKTOPINFO
BOOL FASTCALL DefSetText(HWND hWnd, PCWSTR String, BOOL Ansi);
BOOL FASTCALL TestWindowProcess(PWND);
VOID UserGetWindowBorders(DWORD, DWORD, SIZE *, BOOL);
+ VOID FASTCALL IntNotifyWinEvent(DWORD, HWND, LONG, LONG, DWORD);
#define NtUserGetCursorPos(lpPoint) \
(BOOL)NtUserCallOneParam((DWORD_PTR)lpPoint, ONEPARAM_ROUTINE_GETCURSORPOSITION)
- #define NtUserIsWindowInDestroy(hWnd) \
- (BOOL)NtUserCallOneParam((DWORD_PTR)hWnd, ONEPARAM_ROUTINE_ISWINDOWINDESTROY)
-
#define NtUserEnableProcessWindowGhosting(bEnable) \
NtUserCallOneParam((DWORD_PTR)bEnable, ONEPARAM_ROUTINE_ENABLEPROCWNDGHSTING)
LONG rc;
UNICODE_STRING DeviceName;
PUNICODE_STRING pDeviceName = &DeviceName;
- LPDEVMODEW pDevModeW;
if (lpszDeviceName != NULL)
{
pDeviceName = NULL;
if (lpDevMode != NULL)
+ {
+ LPDEVMODEW pDevModeW;
pDevModeW = GdiConvertToDevmodeW(lpDevMode);
+ if(pDevModeW)
+ {
+ rc = NtUserChangeDisplaySettings ( pDeviceName, pDevModeW, hwnd, dwflags, lParam );
+ RtlFreeHeap(GetProcessHeap(), 0, pDevModeW);
+ }
+ else
+ rc = DISP_CHANGE_SUCCESSFUL;
+ }
else
- pDevModeW = NULL;
-
- rc = NtUserChangeDisplaySettings ( pDeviceName, pDevModeW, hwnd, dwflags, lParam );
-
- if (pDevModeW != NULL)
- RtlFreeHeap(GetProcessHeap(), 0, pDevModeW);
+ rc = NtUserChangeDisplaySettings ( pDeviceName, NULL, hwnd, dwflags, lParam );
if (lpszDeviceName != NULL)
RtlFreeUnicodeString ( &DeviceName );
DWORD dwflags)
{
if(lpDevMode)
- lpDevMode->dmDriverExtra = 0;
+ lpDevMode->dmDriverExtra = 0;
return ChangeDisplaySettingsExW ( NULL, lpDevMode, NULL, dwflags, 0 );
}
static const BOOL g_ObjectHeapTypeShared[VALIDATE_TYPE_EVENT + 1] =
{
FALSE, /* VALIDATE_TYPE_FREE (not used) */
- FALSE, /* VALIDATE_TYPE_WIN FALSE */
+ FALSE, /* VALIDATE_TYPE_WIN */
TRUE, /* VALIDATE_TYPE_MENU FALSE */
TRUE, /* VALIDATE_TYPE_CURSOR */
TRUE, /* VALIDATE_TYPE_MWPOS */
- TRUE, /* VALIDATE_TYPE_HOOK FALSE */
+ FALSE, /* VALIDATE_TYPE_HOOK */
FALSE, /* (not used) */
- TRUE, /* VALIDATE_TYPE_CALLPROC FALSE */
+ FALSE, /* VALIDATE_TYPE_CALLPROC */
TRUE, /* VALIDATE_TYPE_ACCEL */
FALSE, /* (not used) */
FALSE, /* (not used) */
}
return Ret;
}
- // Wine Class tests:
+ // Wine Class tests:
/* Edit controls are special - they return a wndproc handle when
GetWindowLongPtr is called with a different A/W.
On the other hand there is no W->A->W conversion so this control
int SmallIconWidth;
int SmallIconHeight;
BITMAP StdBitmapInfo;
- HDC hInfoDc = NULL;
HDC hSourceDc = NULL;
HDC hDestDc = NULL;
ICONINFO SmallInfo;
return StdIcon;
}
- /* Get a handle to a info DC and handles to DCs which can be used to
- select a bitmap into. This is done to avoid triggering a switch to
- graphics mode (if we're currently in text/blue screen mode) */
- hInfoDc = CreateICW(NULL, NULL, NULL, NULL);
- if (NULL == hInfoDc)
- {
- ERR("Failed to create info DC\n");
- goto cleanup;
- }
hSourceDc = CreateCompatibleDC(NULL);
if (NULL == hSourceDc)
{
ERR("Failed to select source color bitmap\n");
goto cleanup;
}
- SmallInfo.hbmColor = CreateCompatibleBitmap(hInfoDc, SmallIconWidth,
+ SmallInfo.hbmColor = CreateCompatibleBitmap(hSourceDc, SmallIconWidth,
SmallIconHeight);
if (NULL == SmallInfo.hbmColor)
{
ERR("Failed to select source mask bitmap\n");
goto cleanup;
}
- SmallInfo.hbmMask = CreateBitmap(SmallIconWidth, SmallIconHeight, 1, 1,
- NULL);
+ SmallInfo.hbmMask = CreateCompatibleBitmap(hSourceDc, SmallIconWidth, SmallIconHeight);
if (NULL == SmallInfo.hbmMask)
{
ERR("Failed to create mask bitmap\n");
{
DeleteDC(hSourceDc);
}
- if (NULL != hInfoDc)
- {
- DeleteDC(hInfoDc);
- }
return SmallIcon;
}
clsMenuName.pszClientAnsiMenuName = AnsiMenuName.Buffer;
clsMenuName.pwszClientUnicodeMenuName = MenuName.Buffer;
clsMenuName.pusMenuName = &MenuName;
-
+
Atom = NtUserRegisterClassExWOW( &WndClass,
- &ClassName,
+ &ClassName,
NULL, //PUNICODE_STRING ClsNVersion,
&clsMenuName,
fnID,
void *color_bits, *mask_bits;
BOOL ret = FALSE;
HDC hdc = 0;
+ static HDC hScreenDC = 0;
if (!(info = HeapAlloc( GetProcessHeap(), 0, max( size, FIELD_OFFSET( BITMAPINFO, bmiColors[2] )))))
return FALSE;
- if (!(hdc = CreateCompatibleDC( 0 ))) goto done;
+ if(!hScreenDC)
+ {
+ hScreenDC = GetDC(0);
+ if(!hScreenDC) goto done;
+ }
+ if (!(hdc = CreateCompatibleDC(hScreenDC))) goto done;
memcpy( info, bmi, size );
info->bmiHeader.biHeight /= 2;
else
{
if (!(*mask = CreateBitmap( width, height, 1, 1, NULL ))) goto done;
- if (!(*color = CreateBitmap( width, height, bmi->bmiHeader.biPlanes,
- bmi->bmiHeader.biBitCount, NULL )))
+ if (!(*color = CreateBitmap( width, height, GetDeviceCaps(hScreenDC, PLANES),
+ GetDeviceCaps(hScreenDC, BITSPIXEL), NULL )))
{
DeleteObject( *mask );
goto done;
ret = TRUE;
done:
- DeleteDC( hdc );
+ if(hdc) DeleteDC( hdc );
HeapFree( GetProcessHeap(), 0, info );
return ret;
}
FASTCALL
DefSetText(HWND hWnd, PCWSTR String, BOOL Ansi)
{
+ BOOL Ret;
LARGE_STRING lsString;
if ( String )
else
RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&lsString, String, 0);
}
- return NtUserDefSetText(hWnd, (String ? &lsString : NULL));
+ Ret = NtUserDefSetText(hWnd, (String ? &lsString : NULL));
+
+ if (Ret)
+ IntNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hWnd, OBJID_WINDOW, CHILDID_SELF, 0);
+
+ return Ret;
}
void
{
DefWndNCPaint(hWnd, (HRGN)1, -1);
}
-
Result = 1;
break;
}
}
if (flags & DSS_DISABLED)
- hbrtmp = CreateSolidBrush(GetSysColor(COLOR_3DHILIGHT));
+ hbrtmp = GetSysColorBrush(COLOR_3DHILIGHT);
else if (flags & DSS_DEFAULT)
- hbrtmp = CreateSolidBrush(GetSysColor(COLOR_3DSHADOW));
+ hbrtmp = GetSysColorBrush(COLOR_3DSHADOW);
/* Draw light or dark shadow */
if (flags & (DSS_DISABLED|DSS_DEFAULT))
if(!BitBlt(hdc, x+1, y+1, cx, cy, memdc, 0, 0, 0x00B8074A))
goto cleanup;
SelectObject(hdc, hbsave);
- DeleteObject(hbrtmp);
- hbrtmp = 0;
}
if (flags & DSS_DISABLED)
{
- hbr = hbrtmp = CreateSolidBrush(GetSysColor(COLOR_3DSHADOW));
+ hbr = hbrtmp = GetSysColorBrush(COLOR_3DSHADOW);
if(!hbrtmp)
goto cleanup;
}
SelectObject(hdc, hbsave);
if(hbmsave)
SelectObject(memdc, hbmsave);
- if(hbrtmp)
- DeleteObject(hbrtmp);
if(hbm)
DeleteObject(hbm);
if(memdc)
WINE_DEFAULT_DEBUG_CHANNEL(user32);
+ typedef struct _NOTIFYEVENT
+ {
+ DWORD event;
+ LONG idObject;
+ LONG idChild;
+ DWORD flags;
+ } NOTIFYEVENT, *PNOTIFYEVENT;
+
/* PRIVATE FUNCTIONS *********************************************************/
static
return NtUserSetWindowsHookEx(hMod, &USModuleName, dwThreadId, idHook, lpfn, bAnsi);
}
+ /*
+ Since ReactOS uses User32 as the main message source this was needed.
+ Base on the funny rules from the wine tests it left it with this option.
+ 8^(
+ */
+ VOID
+ FASTCALL
+ IntNotifyWinEvent(
+ DWORD event,
+ HWND hwnd,
+ LONG idObject,
+ LONG idChild,
+ DWORD flags
+ )
+ {
+ NOTIFYEVENT ne;
+ ne.event = event;
+ ne.idObject = idObject;
+ ne.idChild = idChild;
+ ne.flags = flags;
+ if (gpsi->dwInstalledEventHooks & GetMaskFromEvent(event))
+ NtUserCallHwndParam(hwnd, (DWORD)&ne, HWNDPARAM_ROUTINE_ROS_NOTIFYWINEVENT);
+ }
/* FUNCTIONS *****************************************************************/
{
PCLIENTINFO ClientInfo;
DWORD Flags, Save;
- PHOOK pHook;
+ PHOOK pHook, phkNext;
LRESULT lResult = 0;
GetConnected();
if (!ClientInfo->phkCurrent) return 0;
- pHook = SharedPtrToUser(ClientInfo->phkCurrent);
+ pHook = DesktopPtrToUser(ClientInfo->phkCurrent);
+
+ if (!pHook->phkNext) return 0; // Nothing to do....
+
+ phkNext = DesktopPtrToUser(pHook->phkNext);
- if (pHook->HookId == WH_CALLWNDPROC || pHook->HookId == WH_CALLWNDPROCRET)
+ if ( phkNext->HookId == WH_CALLWNDPROC ||
+ phkNext->HookId == WH_CALLWNDPROCRET)
{
Save = ClientInfo->dwHookData;
Flags = ClientInfo->CI_flags & CI_CURTHPRHOOK;
if (wParam) ClientInfo->CI_flags |= CI_CURTHPRHOOK;
else ClientInfo->CI_flags &= ~CI_CURTHPRHOOK;
- if (pHook->HookId == WH_CALLWNDPROC)
+ if (phkNext->HookId == WH_CALLWNDPROC)
{
PCWPSTRUCT pCWP = (PCWPSTRUCT)lParam;
pCWP->lParam,
(ULONG_PTR)&lResult,
FNID_CALLWNDPROC,
- pHook->Ansi);
+ phkNext->Ansi);
}
else
{
pCWPR->lParam,
(ULONG_PTR)&lResult,
FNID_CALLWNDPROCRET,
- pHook->Ansi);
+ phkNext->Ansi);
}
ClientInfo->CI_flags ^= ((ClientInfo->CI_flags ^ Flags) & CI_CURTHPRHOOK);
ClientInfo->dwHookData = Save;
/*
- * @unimplemented
+ * @implemented
*/
HHOOK
WINAPI
SetWindowsHookW(int idHook, HOOKPROC lpfn)
{
- return IntSetWindowsHook(idHook, lpfn, NULL, 0, FALSE);
+ DWORD ThreadId = PtrToUint(NtCurrentTeb()->ClientId.UniqueThread);
+ return IntSetWindowsHook(idHook, lpfn, NULL, ThreadId, FALSE);
+ // return NtUserSetWindowsHookAW(idHook, lpfn, FALSE);
}
/*
- * @unimplemented
+ * @implemented
*/
HHOOK
WINAPI
SetWindowsHookA(int idHook, HOOKPROC lpfn)
{
- return IntSetWindowsHook(idHook, lpfn, NULL, 0, TRUE);
+ DWORD ThreadId = PtrToUint(NtCurrentTeb()->ClientId.UniqueThread);
+ return IntSetWindowsHook(idHook, lpfn, NULL, ThreadId, TRUE);
+ // return NtUserSetWindowsHookAW(idHook, lpfn, TRUE);
}
/*
}
/*
- * @unimplemented
+ * @implemented
*/
HHOOK
WINAPI
/*
- * @unimplemented
+ * @implemented
*/
HHOOK
WINAPI
User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
{
PHOOKPROC_CALLBACK_ARGUMENTS Common;
- LRESULT Result;
CREATESTRUCTW Csw;
CBT_CREATEWNDW CbtCreatewndw;
- CREATESTRUCTA Csa;
- CBT_CREATEWNDA CbtCreatewnda;
PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra = NULL;
- WPARAM wParam = 0;
- LPARAM lParam = 0;
- PKBDLLHOOKSTRUCT KeyboardLlData;
- PMSLLHOOKSTRUCT MouseLlData;
- PMSG Msg;
- PMOUSEHOOKSTRUCT MHook;
- PCWPSTRUCT CWP;
- PCWPRETSTRUCT CWPR;
+ KBDLLHOOKSTRUCT KeyboardLlData, *pKeyboardLlData;
+ MSLLHOOKSTRUCT MouseLlData, *pMouseLlData;
+ MSG Msg, *pMsg;
+ PMOUSEHOOKSTRUCT pMHook;
+ CWPSTRUCT CWP, *pCWP;
+ CWPRETSTRUCT CWPR, *pCWPR;
PRECTL prl;
LPCBTACTIVATESTRUCT pcbtas;
+ WPARAM wParam = 0;
+ LPARAM lParam = 0;
+ LRESULT Result = 0;
+ BOOL Hit = FALSE;
Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Arguments;
CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS)
((PCHAR) Common + Common->lParam);
Csw = CbtCreatewndExtra->Cs;
- if (NULL != CbtCreatewndExtra->Cs.lpszName)
- {
- Csw.lpszName = (LPCWSTR)((PCHAR) CbtCreatewndExtra
- + (ULONG_PTR) CbtCreatewndExtra->Cs.lpszName);
- }
- if (0 != HIWORD(CbtCreatewndExtra->Cs.lpszClass))
- {
- Csw.lpszClass = (LPCWSTR)((PCHAR) CbtCreatewndExtra
- + LOWORD((ULONG_PTR) CbtCreatewndExtra->Cs.lpszClass));
- }
+ Csw.lpszName = CbtCreatewndExtra->Cs.lpszName;
+ Csw.lpszClass = CbtCreatewndExtra->Cs.lpszClass;
wParam = Common->wParam;
- if (Common->Ansi)
- {
- memcpy(&Csa, &Csw, sizeof(CREATESTRUCTW));
- CbtCreatewnda.lpcs = &Csa;
- CbtCreatewnda.hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
- lParam = (LPARAM) &CbtCreatewnda;
- }
- else
- {
- CbtCreatewndw.lpcs = &Csw;
- CbtCreatewndw.hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
- lParam = (LPARAM) &CbtCreatewndw;
- }
+ CbtCreatewndw.lpcs = &Csw;
+ CbtCreatewndw.hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
+ lParam = (LPARAM) &CbtCreatewndw;
break;
case HCBT_CLICKSKIPPED:
- MHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam);
- lParam = (LPARAM) MHook;
+ pMHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam);
+ lParam = (LPARAM) pMHook;
break;
case HCBT_MOVESIZE:
prl = (PRECTL)((PCHAR) Common + Common->lParam);
pcbtas = (LPCBTACTIVATESTRUCT)((PCHAR) Common + Common->lParam);
lParam = (LPARAM) pcbtas;
break;
- case HCBT_KEYSKIPPED:
+ case HCBT_KEYSKIPPED: /* The rest SEH support */
case HCBT_MINMAX:
case HCBT_SETFOCUS:
case HCBT_SYSCOMMAND:
}
if (Common->Proc)
- Result = Common->Proc(Common->Code, wParam, lParam);
+ {
+ _SEH2_TRY
+ {
+ Result = Common->Proc(Common->Code, wParam, lParam);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Hit = TRUE;
+ }
+ _SEH2_END;
+ }
else
{
ERR("Common = 0x%x, Proc = 0x%x\n",Common,Common->Proc);
{
case HCBT_CREATEWND:
CbtCreatewndExtra->WndInsertAfter = CbtCreatewndw.hwndInsertAfter;
+ CbtCreatewndExtra->Cs.x = CbtCreatewndw.lpcs->x;
+ CbtCreatewndExtra->Cs.y = CbtCreatewndw.lpcs->y;
+ CbtCreatewndExtra->Cs.cx = CbtCreatewndw.lpcs->cx;
+ CbtCreatewndExtra->Cs.cy = CbtCreatewndw.lpcs->cy;
break;
}
break;
}
case WH_KEYBOARD_LL:
- KeyboardLlData = (PKBDLLHOOKSTRUCT)((PCHAR) Common + Common->lParam);
- Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) KeyboardLlData);
+ 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:
- MouseLlData = (PMSLLHOOKSTRUCT)((PCHAR) Common + Common->lParam);
- Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) MouseLlData);
+ pMouseLlData = (PMSLLHOOKSTRUCT)((PCHAR) Common + Common->lParam);
+ RtlCopyMemory(&MouseLlData, pMouseLlData, sizeof(MSLLHOOKSTRUCT));
+ Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &MouseLlData);
break;
- case WH_MOUSE:
- MHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam);
- Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) MHook);
+ case WH_MOUSE: /* SEH support */
+ pMHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam);
+ _SEH2_TRY
+ {
+ Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) pMHook);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Hit = TRUE;
+ }
+ _SEH2_END;
break;
case WH_CALLWNDPROC:
- CWP = (PCWPSTRUCT)((PCHAR) Common + Common->lParam);
- Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) CWP);
+ 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);
break;
case WH_CALLWNDPROCRET:
- CWPR = (PCWPRETSTRUCT)((PCHAR) Common + Common->lParam);
- Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) CWPR);
+ pCWPR = (PCWPRETSTRUCT)((PCHAR) Common + Common->lParam);
+ RtlCopyMemory(&CWPR, pCWPR, sizeof(CWPRETSTRUCT));
+ Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &CWPR);
break;
- case WH_MSGFILTER:
+ case WH_MSGFILTER: /* All SEH support */
+ ERR("WH_MSGFILTER: Code %d, wParam %d\n",Common->Code,Common->wParam);
case WH_SYSMSGFILTER:
case WH_GETMESSAGE:
- Msg = (PMSG)((PCHAR) Common + Common->lParam);
- // FIXME("UHOOK Memory: %x: %x\n",Common, Msg);
- Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) Msg);
+ pMsg = (PMSG)((PCHAR) Common + Common->lParam);
+ RtlCopyMemory(&Msg, pMsg, sizeof(MSG));
+ _SEH2_TRY
+ {
+ Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &Msg);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Hit = TRUE;
+ }
+ _SEH2_END;
+ if (!Hit && Common->HookId == WH_GETMESSAGE)
+ RtlCopyMemory(pMsg, &Msg, sizeof(MSG));
break;
- case WH_FOREGROUNDIDLE:
+ case WH_FOREGROUNDIDLE: /* <-- SEH support */
case WH_KEYBOARD:
case WH_SHELL:
- Result = Common->Proc(Common->Code, Common->wParam, Common->lParam);
+ _SEH2_TRY
+ {
+ Result = Common->Proc(Common->Code, Common->wParam, Common->lParam);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Hit = TRUE;
+ }
+ _SEH2_END;
break;
default:
return ZwCallbackReturn(NULL, 0, STATUS_NOT_SUPPORTED);
}
-
+ if (Hit)
+ {
+ ERR("Hook Exception! Id: %d, Code %d, Proc 0x%x\n",Common->HookId,Common->Code,Common->Proc);
+ }
return ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS);
}
if (Update)
{
+ IntNotifyWinEvent(EVENT_OBJECT_STATECHANGE, hWnd, OBJID_WINDOW, CHILDID_SELF, 0);
SendMessageW(hWnd, WM_ENABLE, (LPARAM)bEnable, 0);
}
// Return nonzero if it was disabled, or zero if it wasn't:
top_popup_hmenu = hmenu;
}
+ IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPSTART, MenuInfo.Wnd, OBJID_CLIENT, CHILDID_SELF, 0);
+
/* Display the window */
SetWindowPos( MenuInfo.Wnd, HWND_TOPMOST, 0, 0, 0, 0,
if (MenuInfo.Flags & MF_POPUP)
{
+ IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPEND, MenuInfo.Wnd, OBJID_CLIENT, CHILDID_SELF, 0);
DestroyWindow(MenuInfo.Wnd);
MenuInfo.Wnd = NULL;
MenuInfo.Wnd = hWnd;
MenuSetRosMenuInfo(&MenuInfo);
}
-
+
+ IntNotifyWinEvent( EVENT_SYSTEM_MENUSTART,
+ hWnd,
+ MenuInfo.Flags & MF_SYSMENU ? OBJID_SYSMENU : OBJID_MENU,
+ CHILDID_SELF, 0);
return TRUE;
}
/***********************************************************************
{
TRACE("hwnd=%p\n", hWnd);
+ IntNotifyWinEvent( EVENT_SYSTEM_MENUEND, hWnd, OBJID_WINDOW, CHILDID_SELF, 0);
SendMessageW( hWnd, WM_EXITMENULOOP, bPopup, 0 );
ShowCaret(0);
top_popup = 0;
{
BOOL ret = FALSE;
- if (!IsMenu(Menu))
+ if (!IsMenu(Menu))
{
SetLastError( ERROR_INVALID_MENU_HANDLE );
return FALSE;
if (Wnd != HWND_BROADCAST && (Msg < WM_DDE_FIRST || Msg > WM_DDE_LAST))
{
- if (Window != NULL && Window->head.pti == ti && !IsThreadHooked(GetWin32ClientInfo()))
+ if ( Window != NULL &&
+ Window->head.pti == ti &&
+ !IsThreadHooked(GetWin32ClientInfo()) &&
+ !(Window->state & WNDS_SERVERSIDEWINDOWPROC) )
{
/* NOTE: We can directly send messages to the window procedure
if *all* the following conditions are met:
* Window belongs to calling thread
* The calling thread is not being hooked
+ * Not calling a server side proc:
+ Desktop, Switch, ScrollBar, Menu, IconTitle, or hWndMessage
*/
return IntCallMessageProc(Window, Wnd, Msg, wParam, lParam, FALSE);
if (Wnd != HWND_BROADCAST && (Msg < WM_DDE_FIRST || Msg > WM_DDE_LAST))
{
- if (Window != NULL && Window->head.pti == ti && !IsThreadHooked(GetWin32ClientInfo()))
+ if ( Window != NULL &&
+ Window->head.pti == ti &&
+ !IsThreadHooked(GetWin32ClientInfo()) &&
+ !(Window->state & WNDS_SERVERSIDEWINDOWPROC) )
{
/* NOTE: We can directly send messages to the window procedure
if *all* the following conditions are met:
* Window belongs to calling thread
* The calling thread is not being hooked
+ * Not calling a server side proc:
+ Desktop, Switch, ScrollBar, Menu, IconTitle, or hWndMessage
*/
return IntCallMessageProc(Window, Wnd, Msg, wParam, lParam, TRUE);
BOOL WINAPI
IsWindowInDestroy(HWND hWnd)
{
- return NtUserIsWindowInDestroy(hWnd);
+ PWND pwnd;
+ pwnd = ValidateHwnd(hWnd);
+ if (!pwnd)
+ return FALSE;
+ return ((pwnd->state2 & WNDS2_INDESTROY) == WNDS2_INDESTROY);
}
/*
IoStatus->Information = PropertySet[Index].PropertyItem[ItemIndex].MinData;
return STATUS_MORE_ENTRIES;
}
+
+ /* store property set */
+ *Set = (PKSPROPERTY_SET)&PropertySet[Index];
+
+ if (Property->Flags & KSPROPERTY_TYPE_SET)
+ {
+ /* store property handler */
+ *PropertyHandler = PropertySet[Index].PropertyItem[ItemIndex].SetPropertyHandler;
+ return STATUS_SUCCESS;
+ }
+
+ if (Property->Flags & KSPROPERTY_TYPE_GET)
+ {
+ /* store property handler */
+ *PropertyHandler = PropertySet[Index].PropertyItem[ItemIndex].GetPropertyHandler;
+ return STATUS_SUCCESS;
+ }
+
+
if (Property->Flags & KSPROPERTY_TYPE_BASICSUPPORT)
{
PULONG Flags;
/* clear flags */
*Flags = 0;
+ IoStatus->Information = sizeof(ULONG);
+
+ if (PropertySet[Index].PropertyItem[ItemIndex].SupportHandler)
+ {
+ /* use support handler from driver */
+ *PropertyHandler = PropertySet[Index].PropertyItem[ItemIndex].SupportHandler;
+ return STATUS_SUCCESS;
+ }
+
if (PropertySet[Index].PropertyItem[ItemIndex].GetSupported)
*Flags |= KSPROPERTY_TYPE_GET;
if (PropertySet[Index].PropertyItem[ItemIndex].SetSupported)
*Flags |= KSPROPERTY_TYPE_SET;
- IoStatus->Information = sizeof(ULONG);
-
if (OutputBufferLength >= sizeof(KSPROPERTY_DESCRIPTION))
{
/* get output buffer */
}
return STATUS_SUCCESS;
}
- if (Property->Flags & KSPROPERTY_TYPE_SET)
- *PropertyHandler = PropertySet[Index].PropertyItem[ItemIndex].SetPropertyHandler;
-
- if (Property->Flags & KSPROPERTY_TYPE_GET)
- *PropertyHandler = PropertySet[Index].PropertyItem[ItemIndex].GetPropertyHandler;
-
- *Set = (PKSPROPERTY_SET)&PropertySet[Index];
- return STATUS_SUCCESS;
}
}
}
}
}
}
- else if (IsEqualGUIDAligned(&Property->Set, &GUID_NULL) && Property->Id == 0 && Property->Flags == KSPROPERTY_TYPE_SETSUPPORT)
+ else if (IsEqualGUIDAligned(&Property->Set, &GUID_NULL) && Property->Id == 0 && (Property->Flags & KSPROPERTY_TYPE_SETSUPPORT) == KSPROPERTY_TYPE_SETSUPPORT)
{
// store output size
Irp->IoStatus.Information = sizeof(GUID) * PropertySetsCount;
{
RtlMoveMemory(&Guid[Index], PropertySet[Index].Set, sizeof(GUID));
}
- return STATUS_SUCCESS;
+ Status = STATUS_SUCCESS;
}
/* done */
NTSTATUS
NTAPI
CPortFilterWaveCyclic::FreePin(
- IN struct IPortPinWaveCyclic* Pin)
+ IN PPORTPINWAVECYCLIC Pin)
{
ULONG Index;
return STATUS_UNSUCCESSFUL;
}
- if (m_Pins[ConnectDetails->PinId] && m_Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount)
+ if (m_Pins[ConnectDetails->PinId] &&
+ (m_Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount == m_Descriptor->Factory.Instances[ConnectDetails->PinId].MaxFilterInstanceCount))
{
- // release existing instance
- PC_ASSERT(0);
- m_Pins[ConnectDetails->PinId]->Close(DeviceObject, NULL);
+ // no available instance
+ return STATUS_UNSUCCESSFUL;
}
+
// now create the pin
Status = NewPortPinWavePci(&Pin);
if (!NT_SUCCESS(Status))
return STATUS_SUCCESS;
}
+ NTSTATUS
+ NTAPI
+ CPortFilterWavePci::FreePin(
+ IN struct IPortPinWavePci* Pin)
+ {
+ ULONG Index;
+
+ for(Index = 0; Index < m_Descriptor->Factory.PinDescriptorCount; Index++)
+ {
+ if (m_Pins[Index] == Pin)
+ {
+ m_Descriptor->Factory.Instances[Index].CurrentPinInstanceCount--;
+ m_Pins[Index] = NULL;
+ return STATUS_SUCCESS;
+ }
+ }
+ return STATUS_UNSUCCESSFUL;
+ }
+
+
NTSTATUS
NewPortFilterWavePci(
OUT IPortFilterWavePci ** OutFilter)
const GUID KSPROPSETID_Pin = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
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 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}};
STDMETHOD_(NTSTATUS, Init)(THIS_
IN KSPIN_CONNECT *ConnectDetails,
IN ULONG FrameSize,
- IN ULONG Alignment,
- IN PVOID SilenceBuffer) PURE;
+ IN ULONG Alignment) PURE;
STDMETHOD_(NTSTATUS, AddMapping)(THIS_
IN PIRP Irp,
STDMETHODIMP_(NTSTATUS) Init(THIS_ \
IN KSPIN_CONNECT *ConnectDetails, \
IN ULONG FrameSize, \
- IN ULONG Alignment, \
- IN PVOID SilenceBuffer); \
+ IN ULONG Alignment); \
\
STDMETHODIMP_(NTSTATUS) AddMapping(THIS_ \
IN PIRP Irp, \
#undef INTERFACE
#define INTERFACE IPortFilterWavePci
+ struct IPortPinWavePci;
+
DECLARE_INTERFACE_(IPortFilterWavePci, IIrpTarget)
{
DEFINE_ABSTRACT_UNKNOWN()
STDMETHOD_(NTSTATUS, Init)(THIS_
IN PPORTWAVEPCI Port)PURE;
+
+ STDMETHOD_(NTSTATUS, FreePin)(THIS_
+ IN struct IPortPinWavePci* Pin)PURE;
};
typedef IPortFilterWavePci *PPORTFILTERWAVEPCI;
#define IMP_IPortFilterPci \
IMP_IIrpTarget; \
STDMETHODIMP_(NTSTATUS) Init(THIS_ \
- IN PPORTWAVEPCI Port)
+ IN PPORTWAVEPCI Port); \
+ STDMETHODIMP_(NTSTATUS) FreePin(THIS_ \
+ IN struct IPortPinWavePci* Pin)
+
/*****************************************************************************
* IPortPinWavePci
LIST_ENTRY m_IrpList;
LIST_ENTRY m_FreeIrpList;
PIRP m_Irp;
- PVOID m_SilenceBuffer;
ULONG m_OutOfMapping;
ULONG m_MaxFrameSize;
CIrpQueue::Init(
IN KSPIN_CONNECT *ConnectDetails,
IN ULONG FrameSize,
- IN ULONG Alignment,
- IN PVOID SilenceBuffer)
+ IN ULONG Alignment)
{
m_ConnectDetails = ConnectDetails;
m_MaxFrameSize = FrameSize;
- m_SilenceBuffer = SilenceBuffer;
m_Alignment = Alignment;
InitializeListHead(&m_IrpList);
m_CurrentOffset = Offset = 0;
}
- if (!Irp && m_SilenceBuffer && m_MaxFrameSize)
- {
- DPRINT("NoIrp\n");
- // no irp available, use silence buffer
- *Buffer = (PUCHAR)m_SilenceBuffer;
- *BufferSize = m_MaxFrameSize;
- return STATUS_SUCCESS;
- }
-
if (!Irp)
{
// no irp buffer available
+ DPRINT("NoIrp\n");
return STATUS_UNSUCCESSFUL;
}
-
// get stream header
StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2];
}
}
- Status = m_IrpQueue->Init(ConnectDetails, 0, 0, NULL);
+ Status = m_IrpQueue->Init(ConnectDetails, 0, 0);
if (!NT_SUCCESS(Status))
{
DPRINT("IrpQueue_Init failed with %x\n", Status);
ULONG m_StopCount;
KSAUDIO_POSITION m_Position;
KSALLOCATOR_FRAMING m_AllocatorFraming;
- SUBDEVICE_DESCRIPTOR m_Descriptor;
+ PSUBDEVICE_DESCRIPTOR m_Descriptor;
KSPIN_LOCK m_EventListLock;
LIST_ENTRY m_EventList;
NTSTATUS NTAPI PinWaveCyclicAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
NTSTATUS NTAPI PinWaveCyclicAddEndOfStreamEvent(IN PIRP Irp, IN PKSEVENTDATA EventData, IN PKSEVENT_ENTRY EventEntry);
NTSTATUS NTAPI PinWaveCyclicAddLoopedStreamEvent(IN PIRP Irp, IN PKSEVENTDATA EventData, IN PKSEVENT_ENTRY EventEntry);
+ NTSTATUS NTAPI PinWaveCyclicDRMHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
DEFINE_KSPROPERTY_CONNECTIONSET(PinWaveCyclicConnectionSet, PinWaveCyclicState, PinWaveCyclicDataFormat, PinWaveCyclicAllocatorFraming);
DEFINE_KSPROPERTY_AUDIOSET(PinWaveCyclicAudioSet, PinWaveCyclicAudioPosition);
+ DEFINE_KSPROPERTY_DRMSET(PinWaveCyclicDRMSet, PinWaveCyclicDRMHandler);
KSEVENT_ITEM PinWaveCyclicConnectionEventSet =
{
(const KSPROPERTY_ITEM*)&PinWaveCyclicAudioSet,
0,
NULL
+ },
+ {
+ &KSPROPSETID_DrmAudioStream,
+ sizeof(PinWaveCyclicDRMSet) / sizeof(KSPROPERTY_ITEM),
+ (const KSPROPERTY_ITEM*)&PinWaveCyclicDRMSet,
+ 0,
+ NULL
}
};
return STATUS_UNSUCCESSFUL;
}
+ NTSTATUS
+ NTAPI
+ PinWaveCyclicDRMHandler(
+ IN PIRP Irp,
+ IN PKSIDENTIFIER Request,
+ IN OUT PVOID Data)
+ {
+ DPRINT1("PinWaveCyclicDRMHandler\n");
+ ASSERT(0);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+
NTSTATUS
NTAPI
PinWaveCyclicAddEndOfStreamEvent(
{
// FIXME
// complete with successful state
+ Pin->m_Stream->Silence(Pin->m_CommonBuffer, Pin->m_CommonBufferSize);
Pin->m_IrpQueue->CancelBuffers();
Pin->m_Position.PlayOffset = 0;
Pin->m_Position.WriteOffset = 0;
}
else if (Pin->m_State == KSSTATE_STOP)
{
+ Pin->m_Stream->Silence(Pin->m_CommonBuffer, Pin->m_CommonBufferSize);
Pin->m_IrpQueue->CancelBuffers();
Pin->m_Position.PlayOffset = 0;
Pin->m_Position.WriteOffset = 0;
ULONG BufferLength;
ULONG BytesToCopy;
ULONG BufferSize;
+ ULONG Gap;
PUCHAR Buffer;
NTSTATUS Status;
{
Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
if (!NT_SUCCESS(Status))
- return;
+ {
+ Gap = Position - m_CommonBufferOffset;
+ if (Gap > m_FrameSize)
+ {
+ // insert silence samples
+ DPRINT1("Inserting Silence Buffer Offset %lu GapLength %lu\n", m_CommonBufferOffset, BufferLength);
+ m_Stream->Silence((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, BufferLength);
+
+ m_CommonBufferOffset += BufferLength;
+ break;
+ }
+ }
BytesToCopy = min(BufferLength, BufferSize);
m_IrpQueue->UpdateMapping(BytesToCopy);
m_CommonBufferOffset += BytesToCopy;
- BufferLength = Position - m_CommonBufferOffset;
+ BufferLength -= BytesToCopy;
m_Position.PlayOffset += BytesToCopy;
if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
{
Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
if (!NT_SUCCESS(Status))
- return;
+ {
+ Gap = m_CommonBufferSize - m_CommonBufferOffset + Position;
+ if (Gap > m_FrameSize)
+ {
+ // insert silence samples
+ DPRINT1("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;
+ }
+ break;
+ }
BytesToCopy = min(BufferLength, BufferSize);
m_CommonBufferOffset += BytesToCopy;
m_Position.PlayOffset += BytesToCopy;
- BufferLength = m_CommonBufferSize - m_CommonBufferOffset;
+ BufferLength -=BytesToCopy;
if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
{
m_Position.PlayOffset = m_Position.PlayOffset % m_Position.WriteOffset;
}
}
-
}
if (Gap == Length)
{
ULONG Position;
NTSTATUS Status;
- PUCHAR Buffer;
- ULONG BufferSize;
ULONGLONG OldOffset, NewOffset;
PC_ASSERT_IRQL(DISPATCH_LEVEL);
if (m_State == KSSTATE_RUN)
{
- Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
- if (!NT_SUCCESS(Status))
- {
- return;
- }
-
Status = m_Stream->GetPosition(&Position);
- DPRINT("Position %u Buffer %p BufferSize %u ActiveIrpOffset %u Capture %u\n", Position, Buffer, m_CommonBufferSize, BufferSize, m_Capture);
OldOffset = m_Position.PlayOffset;
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
{
/* handle property with subdevice descriptor */
- Status = PcHandlePropertyWithTable(Irp, m_Descriptor.FilterPropertySetCount, m_Descriptor.FilterPropertySet, &m_Descriptor);
+ Status = PcHandlePropertyWithTable(Irp, m_Descriptor->FilterPropertySetCount, m_Descriptor->FilterPropertySet, m_Descriptor);
if (Status == STATUS_NOT_FOUND)
{
}
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
{
- Status = PcHandleEnableEventWithTable(Irp, &m_Descriptor);
+ Status = PcHandleEnableEventWithTable(Irp, m_Descriptor);
}
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT)
{
- Status = PcHandleDisableEventWithTable(Irp, &m_Descriptor);
+ Status = PcHandleDisableEventWithTable(Irp, m_Descriptor);
}
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE)
{
{
// free format
FreeItem(m_Format, TAG_PORTCLASS);
+
+ // format is freed
m_Format = NULL;
}
if (m_IrpQueue)
{
- // fixme cancel irps
- m_IrpQueue->Release();
- }
+ // cancel remaining irps
+ m_IrpQueue->CancelBuffers();
+ // release irp queue
+ m_IrpQueue->Release();
- if (m_Port)
- {
- // release reference to port driver
- m_Port->Release();
- m_Port = NULL;
+ // queue is freed
+ m_IrpQueue = NULL;
}
if (m_ServiceGroup)
{
// remove member from service group
m_ServiceGroup->RemoveMember(PSERVICESINK(this));
+
+ // do not release service group, it is released by the miniport object
m_ServiceGroup = NULL;
}
// set state to stop
m_State = KSSTATE_STOP;
-
DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
+
// release stream
m_Stream->Release();
+ // stream is now freed
+ m_Stream = NULL;
}
if (m_Filter)
{
- // release reference to filter instance
+ // disconnect pin from filter
m_Filter->FreePin((PPORTPINWAVECYCLIC)this);
+
+ // release filter reference
m_Filter->Release();
+
+ // pin is done with filter
m_Filter = NULL;
}
+ if (m_Port)
+ {
+ // release reference to port driver
+ m_Port->Release();
+
+ // work is done for port
+ m_Port = NULL;
+ }
+
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
PKSDATAFORMAT DataFormat;
PDEVICE_OBJECT DeviceObject;
BOOLEAN Capture;
- PVOID SilenceBuffer;
PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor = NULL;
//IDrmAudioStream * DrmAudio = NULL;
#endif
DPRINT1("CPortPinWaveCyclic::Init Status %x PinId %u Capture %u\n", Status, ConnectDetails->PinId, Capture);
- DPRINT1("Bits %u Samples %u Channels %u Tag %u FrameSize %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.wBitsPerSample, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.nSamplesPerSec, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.nChannels, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.wFormatTag, m_FrameSize);
if (!NT_SUCCESS(Status))
return Status;
InitializeListHead(&m_EventList);
KeInitializeSpinLock(&m_EventListLock);
- /* set up subdevice descriptor */
- RtlZeroMemory(&m_Descriptor, sizeof(SUBDEVICE_DESCRIPTOR));
- m_Descriptor.FilterPropertySet = PinWaveCyclicPropertySet;
- m_Descriptor.FilterPropertySetCount = sizeof(PinWaveCyclicPropertySet) / sizeof(KSPROPERTY_SET);
- m_Descriptor.UnknownStream = (PUNKNOWN)m_Stream;
- m_Descriptor.DeviceDescriptor = SubDeviceDescriptor->DeviceDescriptor;
- m_Descriptor.UnknownMiniport = SubDeviceDescriptor->UnknownMiniport;
- m_Descriptor.PortPin = (PVOID)this;
- m_Descriptor.EventSetCount = sizeof(PinWaveCyclicEventSet) / sizeof(KSEVENT_SET);
- m_Descriptor.EventSet = PinWaveCyclicEventSet;
- m_Descriptor.EventList = &m_EventList;
- m_Descriptor.EventListLock = &m_EventListLock;
+ Status = PcCreateSubdeviceDescriptor(&m_Descriptor,
+ SubDeviceDescriptor->InterfaceCount,
+ SubDeviceDescriptor->Interfaces,
+ 0, /* FIXME KSINTERFACE_STANDARD with KSINTERFACE_STANDARD_STREAMING / KSINTERFACE_STANDARD_LOOPED_STREAMING */
+ NULL,
+ sizeof(PinWaveCyclicPropertySet) / sizeof(KSPROPERTY_SET),
+ PinWaveCyclicPropertySet,
+ 0,
+ 0,
+ 0,
+ NULL,
+ sizeof(PinWaveCyclicEventSet) / sizeof(KSEVENT_SET),
+ PinWaveCyclicEventSet,
+ SubDeviceDescriptor->DeviceDescriptor);
+
+ m_Descriptor->UnknownStream = (PUNKNOWN)m_Stream;
+ m_Descriptor->UnknownMiniport = SubDeviceDescriptor->UnknownMiniport;
+ m_Descriptor->PortPin = (PVOID)this;
+ m_Descriptor->EventList = &m_EventList;
+ m_Descriptor->EventListLock = &m_EventListLock;
// initialize reset state
m_ResetState = KSRESET_END;
PC_ASSERT(NT_SUCCESS(Status));
PC_ASSERT(m_FrameSize);
- SilenceBuffer = AllocateItem(NonPagedPool, m_FrameSize, TAG_PORTCLASS);
- if (!SilenceBuffer)
- return STATUS_INSUFFICIENT_RESOURCES;
+ 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);
/* set up allocator framing */
m_AllocatorFraming.Reserved = 0;
m_AllocatorFraming.FrameSize = m_FrameSize;
- m_Stream->Silence(SilenceBuffer, m_FrameSize);
m_Stream->Silence(m_CommonBuffer, m_CommonBufferSize);
- Status = m_IrpQueue->Init(ConnectDetails, m_FrameSize, 0, SilenceBuffer);
+ Status = m_IrpQueue->Init(ConnectDetails, m_FrameSize, 0);
if (!NT_SUCCESS(Status))
{
m_IrpQueue->Release();
m_Port = Port;
m_Filter = Filter;
- //DPRINT("Setting state to acquire %x\n", m_Stream->SetState(KSSTATE_ACQUIRE));
- //DPRINT("Setting state to pause %x\n", m_Stream->SetState(KSSTATE_PAUSE));
-
return STATUS_SUCCESS;
}
KSAUDIO_POSITION m_Position;
ULONG m_StopCount;
- ULONG m_Delay;
-
BOOL m_bUsePrefetch;
ULONG m_PrefetchOffset;
SUBDEVICE_DESCRIPTOR m_Descriptor;
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
- ISubdevice *SubDevice;
NTSTATUS Status;
- PSUBDEVICE_DESCRIPTOR Descriptor;
+
+ if (m_Format)
+ {
+ // free format
+ FreeItem(m_Format, TAG_PORTCLASS);
+
+ // format is freed
+ m_Format = NULL;
+ }
+
+ if (m_IrpQueue)
+ {
+ // cancel remaining irps
+ m_IrpQueue->CancelBuffers();
+
+ // release irp queue
+ m_IrpQueue->Release();
+
+ // queue is freed
+ m_IrpQueue = NULL;
+ }
+
if (m_ServiceGroup)
{
+ // remove member from service group
m_ServiceGroup->RemoveMember(PSERVICESINK(this));
+
+ // do not release service group, it is released by the miniport object
+ m_ServiceGroup = NULL;
}
if (m_Stream)
{
if (m_State != KSSTATE_STOP)
{
- m_Stream->SetState(KSSTATE_STOP);
+ // stop stream
+ Status = m_Stream->SetState(KSSTATE_STOP);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Warning: failed to stop stream with %x\n", Status);
+ PC_ASSERT(0);
+ }
}
+ // set state to stop
+ m_State = KSSTATE_STOP;
+
+ DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
+
+ // release stream
m_Stream->Release();
+
+ // stream is now freed
+ m_Stream = NULL;
}
- Status = m_Port->QueryInterface(IID_ISubdevice, (PVOID*)&SubDevice);
- if (NT_SUCCESS(Status))
+ if (m_Filter)
{
- Status = SubDevice->GetDescriptor(&Descriptor);
- if (NT_SUCCESS(Status))
- {
- Descriptor->Factory.Instances[m_ConnectDetails->PinId].CurrentPinInstanceCount--;
- }
- SubDevice->Release();
+ // disconnect pin from filter
+ m_Filter->FreePin((PPORTPINWAVEPCI)this);
+
+ // release filter reference
+ m_Filter->Release();
+
+ // pin is done with filter
+ m_Filter = NULL;
}
- if (m_Format)
+ if (m_Port)
{
- FreeItem(m_Format, TAG_PORTCLASS);
- m_Format = NULL;
+ // release reference to port driver
+ m_Port->Release();
+
+ // work is done for port
+ m_Port = NULL;
}
+ // successfully complete irp
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
NTSTATUS Status;
PKSDATAFORMAT DataFormat;
BOOLEAN Capture;
+ ISubdevice * Subdevice = NULL;
+ PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor = NULL;
+ // check if it is a source / sink pin
+ if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
+ {
+ // sink pin
+ Capture = FALSE;
+ }
+ else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
+ {
+ // source pin
+ Capture = TRUE;
+ }
+ else
+ {
+ DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
+ DbgBreakPoint();
+ while(TRUE);
+ }
+
+ // add port / filter reference
Port->AddRef();
Filter->AddRef();
+ // initialize pin
m_Port = Port;
m_Filter = Filter;
m_KsPinDescriptor = KsPinDescriptor;
m_ConnectDetails = ConnectDetails;
m_Miniport = GetWavePciMiniport(Port);
m_DeviceObject = DeviceObject;
-
- DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
+ m_State = KSSTATE_STOP;
+ m_Capture = Capture;
DPRINT("IPortPinWavePci_fnInit entered\n");
+ // get dataformat
+ DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
+
+ // allocate data format
m_Format = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
if (!m_Format)
- return STATUS_INSUFFICIENT_RESOURCES;
+ {
+ // release references
+ m_Port->Release();
+ m_Filter->Release();
- RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
+ // no dangling pointers
+ Port = NULL;
+ Filter = NULL;
- if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
- {
- Capture = FALSE;
- }
- else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
- {
- Capture = TRUE;
- }
- else
- {
- DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
- DbgBreakPoint();
- while(TRUE);
+ // failed to allocate data format
+ return STATUS_INSUFFICIENT_RESOURCES;
}
+ // copy data format
+ RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
+
+ // allocate new stream
Status = m_Miniport->NewStream(&m_Stream,
NULL,
NonPagedPool,
DPRINT("IPortPinWavePci_fnInit Status %x\n", Status);
if (!NT_SUCCESS(Status))
+ {
+ // free references
+ Port->Release();
+ Filter->Release();
+
+ // free data format
+ FreeItem(m_Format, TAG_PORTCLASS);
+
+ // no dangling pointers
+ m_Port = NULL;
+ m_Filter = NULL;
+ m_Format = NULL;
+
+ // failed to allocate stream
return Status;
+ }
- if (m_ServiceGroup)
+ // get allocator requirements for pin
+ Status = m_Stream->GetAllocatorFraming(&m_AllocatorFraming);
+ if (NT_SUCCESS(Status))
{
- Status = m_ServiceGroup->AddMember(PSERVICESINK(this));
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Failed to add pin to service group\n");
- return Status;
- }
+ DPRINT("OptionFlags %x RequirementsFlag %x PoolType %x Frames %lu FrameSize %lu FileAlignment %lu\n",
+ m_AllocatorFraming.OptionsFlags, m_AllocatorFraming.RequirementsFlags, m_AllocatorFraming.PoolType, m_AllocatorFraming.Frames, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment);
}
- // delay of 10 milisec
- m_Delay = Int32x32To64(10, -10000);
-
- Status = m_Stream->GetAllocatorFraming(&m_AllocatorFraming);
+ // allocate new irp queue
+ Status = NewIrpQueue(&m_IrpQueue);
if (!NT_SUCCESS(Status))
{
- DPRINT("GetAllocatorFraming failed with %x\n", Status);
+ // free references
+ Port->Release();
+ Filter->Release();
+ m_Stream->Release();
+
+ // free data format
+ FreeItem(m_Format, TAG_PORTCLASS);
+
+ // no dangling pointers
+ m_Port = NULL;
+ m_Filter = NULL;
+ m_Format = NULL;
+ m_Stream = NULL;
+
+ // failed to allocate irp queue
+ return Status;
}
- DPRINT("OptionFlags %x RequirementsFlag %x PoolType %x Frames %lu FrameSize %lu FileAlignment %lu\n",
- m_AllocatorFraming.OptionsFlags, m_AllocatorFraming.RequirementsFlags, m_AllocatorFraming.PoolType, m_AllocatorFraming.Frames, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment);
+ // initialize irp queue
+ Status = m_IrpQueue->Init(ConnectDetails, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment);
+ if (!NT_SUCCESS(Status))
+ {
+ // this should never happen
+ ASSERT(0);
+ }
- ISubdevice * Subdevice = NULL;
// get subdevice interface
Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&Subdevice);
if (!NT_SUCCESS(Status))
- return Status;
-
- PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor = NULL;
+ {
+ // this function should never fail
+ ASSERT(0);
+ }
+ // get subdevice descriptor
Status = Subdevice->GetDescriptor(&SubDeviceDescriptor);
if (!NT_SUCCESS(Status))
{
- // failed to get descriptor
- Subdevice->Release();
- return Status;
+ // this function should never fail
+ ASSERT(0);
}
+ // release subdevice
+ Subdevice->Release();
+
/* set up subdevice descriptor */
RtlZeroMemory(&m_Descriptor, sizeof(SUBDEVICE_DESCRIPTOR));
m_Descriptor.FilterPropertySet = PinWavePciPropertySet;
m_Descriptor.UnknownMiniport = SubDeviceDescriptor->UnknownMiniport;
m_Descriptor.PortPin = (PVOID)this;
+ if (m_ServiceGroup)
+ {
+ Status = m_ServiceGroup->AddMember(PSERVICESINK(this));
+ if (!NT_SUCCESS(Status))
+ {
+ // free references
+ m_Stream->Release();
+ Port->Release();
+ Filter->Release();
+ // free data format
+ FreeItem(m_Format, TAG_PORTCLASS);
- Status = NewIrpQueue(&m_IrpQueue);
- if (!NT_SUCCESS(Status))
- return Status;
+ // no dangling pointers
+ m_Stream = NULL;
+ m_Port = NULL;
+ m_Filter = NULL;
+ m_Format = NULL;
- Status = m_IrpQueue->Init(ConnectDetails, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment, NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("IrpQueue_Init failed with %x\n", Status);
- return Status;
+ // failed to add to service group
+ return Status;
+ }
}
- m_State = KSSTATE_STOP;
- m_Capture = Capture;
return STATUS_SUCCESS;
}
goto cleanup;
}
- Status = m_IrpQueue->Init(ConnectDetails, 0, 0, NULL);
+ Status = m_IrpQueue->Init(ConnectDetails, 0, 0);
if (!NT_SUCCESS(Status))
{
goto cleanup;
}
// create the subdevice descriptor
- Status = PcCreateSubdeviceDescriptor(&m_SubDeviceDescriptor,
+ Status = PcCreateSubdeviceDescriptor(&m_SubDeviceDescriptor,
4,
InterfaceGuids,
- 0,
+ 0,
NULL,
- 2,
+ 2,
WaveCyclicPropertySet,
0,
0,
DEFINE_KSPROPERTY_ITEM_AUDIO_POSITION(PropPositionHandler, PropPositionHandler)\
}
+
+ #define DEFINE_KSPROPERTY_ITEM_DRMAUDIOSTREAM_CONTENTID(SetHandler)\
+ DEFINE_KSPROPERTY_ITEM(\
+ KSPROPERTY_DRMAUDIOSTREAM_CONTENTID,\
+ NULL,\
+ sizeof(KSPROPERTY),\
+ sizeof(ULONG),\
+ (SetHandler),\
+ NULL, 0, NULL, NULL, 0)
+
+ #define DEFINE_KSPROPERTY_DRMSET(PinSet,\
+ PropPositionHandler)\
+ DEFINE_KSPROPERTY_TABLE(PinSet) {\
+ DEFINE_KSPROPERTY_ITEM_DRMAUDIOSTREAM_CONTENTID(PropPositionHandler)\
+ }
+
#define DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PinSet,\
PropGeneral, PropInstances, PropIntersection)\
DEFINE_KSPROPERTY_TABLE(PinSet) {\
#include "private.hpp"
-
- KSPIN_INTERFACE PinInterfaces[] =
- {
- {
- {STATIC_KSINTERFACESETID_Standard},
- KSINTERFACE_STANDARD_STREAMING,
- 0
- },
- {
- {STATIC_KSINTERFACESETID_Standard},
- KSINTERFACE_STANDARD_LOOPED_STREAMING,
- 0
- }
- };
-
-
NTSTATUS
NTAPI
KsoDispatchCreateWithGenericFactory(
}
NTSTATUS
- PcHandleGuidNullRequest(
- IN OUT PIRP Irp,
+ NTAPI
+ PcHandlePropertyWithTable(
+ IN PIRP Irp,
+ IN ULONG PropertySetCount,
+ IN PKSPROPERTY_SET PropertySet,
IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor)
{
- PPCNODE_DESCRIPTOR Node;
- PPCPROPERTY_ITEM PropertyItem;
PIO_STACK_LOCATION IoStack;
- PKSP_NODE Property;
- LPGUID Buffer;
- ULONG Count = 0, SubIndex, Index;
// get current irp stack location
IoStack = IoGetCurrentIrpStackLocation(Irp);
-
- // access property
- Property = (PKSP_NODE)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
-
- if (Property->NodeId >= SubDeviceDescriptor->DeviceDescriptor->NodeCount)
+ if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY))
{
- // request is out of bounds
- Irp->IoStatus.Information = 0;
+ // certainly an invalid request
return STATUS_INVALID_PARAMETER;
}
- Node = (PPCNODE_DESCRIPTOR)((ULONG_PTR)SubDeviceDescriptor->DeviceDescriptor->Nodes + (Property->NodeId * SubDeviceDescriptor->DeviceDescriptor->NodeSize));
+ // store device descriptor
+ KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (PKSPROPERTY_ITEM)SubDeviceDescriptor;
- if (!Node->AutomationTable)
- {
- // request is out of bounds
- Irp->IoStatus.Information = 0;
- return STATUS_INVALID_PARAMETER;
- }
+ // then try KsPropertyHandler
+ return KsPropertyHandler(Irp, PropertySetCount, PropertySet);
+ }
- PC_ASSERT(Node->AutomationTable);
- PC_ASSERT(Node->AutomationTable->PropertyCount);
- PC_ASSERT(Node->AutomationTable->PropertyItemSize);
-
- Buffer = (LPGUID)AllocateItem(NonPagedPool, sizeof (GUID) * Node->AutomationTable->PropertyCount, TAG_PORTCLASS);
- if (!Buffer)
- return STATUS_INSUFFICIENT_RESOURCES;
-
- PropertyItem = (PCPROPERTY_ITEM*)Node->AutomationTable->Properties;
- for (Index = 0; Index < Node->AutomationTable->PropertyCount; Index++)
- {
- BOOL Found = FALSE;
- for (SubIndex = 0; SubIndex < Count; SubIndex++)
- {
- if (IsEqualGUIDAligned(Buffer[SubIndex], *PropertyItem->Set))
- {
- Found = TRUE;
- break;
- }
- }
- if (!Found)
- {
- RtlMoveMemory(&Buffer[Count], PropertyItem->Set, sizeof (GUID));
- Count++;
- }
- PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + Node->AutomationTable->PropertyItemSize);
- }
-
- // store result length
- Irp->IoStatus.Information = sizeof (GUID) * Count;
- if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof (GUID) * Count)
- {
- // buffer too small
- FreeItem(Buffer, TAG_PORTCLASS);
- return STATUS_MORE_ENTRIES;
- }
-
- RtlMoveMemory(Irp->UserBuffer, Buffer, sizeof (GUID) * Count);
- FreeItem(Buffer, TAG_PORTCLASS);
- return STATUS_SUCCESS;
+ VOID
+ NTAPI
+ PcAcquireFormatResources(
+ LONG Unknown,
+ LONG Unknown2,
+ LONG Unknown3,
+ LONG Unknown4)
+ {
+ UNIMPLEMENTED;
}
NTSTATUS
- PcFindNodePropertyHandler(
- PIRP Irp,
- PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor,
- OUT PPCPROPERTY_ITEM * OutPropertyItem)
+ PcAddToEventTable(
+ PVOID Ptr,
+ LONG Unknown2,
+ ULONG Length,
+ LONG Unknown3,
+ LONG Unknown4,
+ LONG Unknown5,
+ LONG Unknown6,
+ LONG Unknown7)
{
- PPCNODE_DESCRIPTOR Node;
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+ NTSTATUS
+ NTAPI
+ PropertyItemDispatch(
+ IN PIRP Irp,
+ IN PKSIDENTIFIER Request,
+ IN OUT PVOID Data)
+ {
+ PPCPROPERTY_REQUEST PropertyRequest;
+ PSUBDEVICE_DESCRIPTOR Descriptor;
+ PKSPROPERTY Property;
+ PPCNODE_DESCRIPTOR NodeDescriptor;
+ PKSNODEPROPERTY NodeProperty;
+ PKSPROPERTY_SET PropertySet;
PPCPROPERTY_ITEM PropertyItem;
+ PPCAUTOMATION_TABLE NodeAutomation;
PIO_STACK_LOCATION IoStack;
- PKSP_NODE Property;
- ULONG Index;
+ ULONG InstanceSize, ValueSize, Index;
+ PVOID Instance;
+ NTSTATUS Status;
- // get current irp stack location
+ // allocate a property request
+ PropertyRequest = (PPCPROPERTY_REQUEST)AllocateItem(NonPagedPool, sizeof(PCPROPERTY_REQUEST), TAG_PORTCLASS);
+ if (!PropertyRequest)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ // grab device descriptor
+ Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
+
+ // get current irp stack
IoStack = IoGetCurrentIrpStackLocation(Irp);
- // access property
- Property = (PKSP_NODE)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
+ // get input property request
+ Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
- if (Property->NodeId >= SubDeviceDescriptor->DeviceDescriptor->NodeCount)
+ // get property set
+ PropertySet = (PKSPROPERTY_SET)KSPROPERTY_SET_IRP_STORAGE(Irp);
+
+ // sanity check
+ PC_ASSERT(Descriptor);
+ PC_ASSERT(Descriptor->UnknownMiniport);
+
+ // get instance / value size
+ InstanceSize = IoStack->Parameters.DeviceIoControl.InputBufferLength;
+ Instance = Data;
+ ValueSize = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
+
+ // initialize property request
+ PropertyRequest->MajorTarget = Descriptor->UnknownMiniport;
+ PropertyRequest->MinorTarget = Descriptor->UnknownStream;
+ PropertyRequest->Irp = Irp;
+ PropertyRequest->Verb = Property->Flags;
+
+
+ // check if this is filter / pin property request
+ if (!(Property->Flags & KSPROPERTY_TYPE_TOPOLOGY))
{
- // request is out of bounds
- DPRINT("InvalidIndex %u %u\n", Property->NodeId, SubDeviceDescriptor->DeviceDescriptor->NodeCount);
- return STATUS_INVALID_PARAMETER;
+ // adjust input buffer size
+ InstanceSize -= sizeof(KSPROPERTY);
+ Instance = (PVOID)((ULONG_PTR)Instance + sizeof(KSPROPERTY));
+
+ // filter / pin property request dont use node field
+ PropertyRequest->Node = MAXULONG;
+ }
+ else if (InstanceSize >= sizeof(KSNODEPROPERTY))
+ {
+ // request is for a node
+ InstanceSize -= sizeof(KSNODEPROPERTY);
+ Instance = (PVOID)((ULONG_PTR)Instance + sizeof(KSNODEPROPERTY));
+
+ // cast node property request
+ NodeProperty = (PKSNODEPROPERTY)Request;
+
+ // store node id
+ PropertyRequest->Node = NodeProperty->NodeId;
+ }
+ else
+ {
+ // invalid buffer size
+ return STATUS_INVALID_BUFFER_SIZE;
}
- Node = (PPCNODE_DESCRIPTOR)((ULONG_PTR)SubDeviceDescriptor->DeviceDescriptor->Nodes + (Property->NodeId * SubDeviceDescriptor->DeviceDescriptor->NodeSize));
+ // store instance size
+ PropertyRequest->InstanceSize = InstanceSize;
+ PropertyRequest->Instance = (InstanceSize != 0 ? Instance : NULL);
- if (!Node->AutomationTable)
+ // store value size
+ PropertyRequest->ValueSize = ValueSize;
+ PropertyRequest->Value = (ValueSize != 0 ? Irp->UserBuffer : NULL);
+
+ // now scan the property set for the attached property set item stored in Relations member
+ if (PropertySet)
{
- // request is out of bounds
- Irp->IoStatus.Information = 0;
- return STATUS_NOT_FOUND;
+ // sanity check
+ PC_ASSERT(IsEqualGUIDAligned(Property->Set, *PropertySet->Set));
+
+ for(Index = 0; Index < PropertySet->PropertiesCount; Index++)
+ {
+ // check if they got the same property id
+ if (PropertySet->PropertyItem[Index].PropertyId == Property->Id)
+ {
+ // found item
+ PropertyRequest->PropertyItem = (const PCPROPERTY_ITEM*)PropertySet->PropertyItem[Index].Relations;
+
+ // done
+ break;
+ }
+ }
}
- // sanity checks
- PC_ASSERT(Node->AutomationTable);
- PC_ASSERT(Node->AutomationTable->PropertyCount);
- PC_ASSERT(Node->AutomationTable->PropertyItemSize);
+ // check if there has been a property set item attached
+ if (!PropertyRequest->PropertyItem)
+ {
+ // is topology node id valid
+ if (PropertyRequest->Node < Descriptor->DeviceDescriptor->NodeCount)
+ {
+ // get node descriptor
+ NodeDescriptor = (PPCNODE_DESCRIPTOR) ((ULONG_PTR)Descriptor->DeviceDescriptor->Nodes + PropertyRequest->Node * Descriptor->DeviceDescriptor->NodeSize);
- PropertyItem = (PCPROPERTY_ITEM*)Node->AutomationTable->Properties;
+ // get node automation table
+ NodeAutomation = (PPCAUTOMATION_TABLE)NodeDescriptor->AutomationTable;
- DPRINT("NodeId %u PropertyCount %u\n", Property->NodeId, Node->AutomationTable->PropertyCount);
- for(Index = 0; Index < Node->AutomationTable->PropertyCount; Index++)
+ // has it got a automation table
+ if (NodeAutomation)
+ {
+ // now scan the properties and check if it supports this request
+ PropertyItem = (PPCPROPERTY_ITEM)NodeAutomation->Properties;
+ for(Index = 0; Index < NodeAutomation->PropertyCount; Index++)
+ {
+ // are they same property
+ if (IsEqualGUIDAligned(*PropertyItem->Set, Property->Set))
+ {
+ if (PropertyItem->Id == Property->Id)
+ {
+ // found match
+ PropertyRequest->PropertyItem = PropertyItem;
+
+ // done
+ break;
+ }
+ }
+
+ // move to next property item
+ PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + NodeAutomation->PropertyItemSize);
+ }
+ }
+ }
+ }
+
+ if (PropertyRequest->PropertyItem && PropertyRequest->PropertyItem->Handler)
{
- if (IsEqualGUIDAligned(*PropertyItem->Set, Property->Property.Set) && PropertyItem->Id == Property->Property.Id)
+ // now call the handler
+ UNICODE_STRING GuidBuffer;
+ RtlStringFromGUID(Property->Set, &GuidBuffer);
+ DPRINT1("Calling Node %lu MajorTarget %p MinorTarget %p PropertySet %S PropertyId %lu PropertyFlags %lx InstanceSize %lu ValueSize %lu Handler %p PropertyRequest %p\n",
+ PropertyRequest->Node, PropertyRequest->MajorTarget, PropertyRequest->MinorTarget, GuidBuffer.Buffer, Property->Id, Property->Flags, PropertyRequest->InstanceSize, PropertyRequest->ValueSize,
+ PropertyRequest->PropertyItem->Handler, PropertyRequest);
+ #if 0
+ Status = PropertyRequest->PropertyItem->Handler(PropertyRequest);
+ #else
+ Status = STATUS_NOT_FOUND;
+ #endif
+ Irp->IoStatus.Information = PropertyRequest->ValueSize;
+
+ if (Status != STATUS_PENDING)
{
- //found property handler
- *OutPropertyItem = PropertyItem;
- return STATUS_SUCCESS;
+ // free property request
+ FreeItem(PropertyRequest, TAG_PORTCLASS);
}
- PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + Node->AutomationTable->PropertyItemSize);
+ }
+ else
+ {
+ FreeItem(PropertyRequest, TAG_PORTCLASS);
+ Status = STATUS_NOT_FOUND;
}
- // no handler yet found
- DPRINT("NotFound\n");
- return STATUS_NOT_FOUND;
+ /* done */
+ return Status;
}
NTSTATUS
- PcNodeBasicSupportHandler(
- PIRP Irp,
- PPCPROPERTY_ITEM PropertyItem)
+ PcAddToPropertyTable(
+ IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor,
+ IN PPCPROPERTY_ITEM PropertyItem,
+ IN ULONG bNode)
{
- PULONG Flags;
- PIO_STACK_LOCATION IoStack;
- PKSPROPERTY_DESCRIPTION Description;
- PKSP_NODE Property;
+ ULONG bFound = FALSE;
+ ULONG Index, PropertySetIndex, PropertySetItemIndex;
+ PKSPROPERTY_SET NewPropertySet;
+ PKSPROPERTY_ITEM FilterPropertyItem, NewFilterPropertyItem;
+ LPGUID Guid;
+ //UNICODE_STRING GuidBuffer;
- // get current irp stack location
- IoStack = IoGetCurrentIrpStackLocation(Irp);
-
- // access property
- Property = (PKSP_NODE)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
+ ASSERT(PropertyItem->Set);
+ // RtlStringFromGUID(*PropertyItem->Set, &GuidBuffer);
+ // DPRINT1("PcAddToPropertyTable Adding Item Set %S Id %lu Flags %lx\n", GuidBuffer.Buffer, PropertyItem->Id, PropertyItem->Flags);
- PC_ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(ULONG));
- Flags= (PULONG)Irp->UserBuffer;
- // reset flags
- *Flags = 0;
- if (PropertyItem->Flags & KSPROPERTY_TYPE_SET)
- *Flags |= KSPROPERTY_TYPE_SET;
+ //DPRINT1("FilterPropertySetCount %lu\n", SubDeviceDescriptor->FilterPropertySetCount);
+ // first step check if the property set is present already
+ for(Index = 0; Index < SubDeviceDescriptor->FilterPropertySetCount; Index++)
+ {
- if (PropertyItem->Flags & KSPROPERTY_TYPE_GET)
- *Flags |= KSPROPERTY_TYPE_GET;
+ //RtlStringFromGUID(*SubDeviceDescriptor->FilterPropertySet[Index].Set, &GuidBuffer);
+ //DPRINT1("FilterProperty Set %S PropertyCount %lu\n", GuidBuffer.Buffer, SubDeviceDescriptor->FilterPropertySet[Index].PropertiesCount);
+ if (IsEqualGUIDAligned(*SubDeviceDescriptor->FilterPropertySet[Index].Set, *PropertyItem->Set))
+ {
+ // property set is already present
+ bFound = TRUE;
+ PropertySetIndex = Index;
- // store result length
- Irp->IoStatus.Information = sizeof(ULONG);
+ // break out
+ break;
+ }
+ }
- if (IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(KSPROPERTY_DESCRIPTION))
+ // is the property set present
+ if (!bFound)
{
- // get output buffer
- Description = (PKSPROPERTY_DESCRIPTION)Irp->UserBuffer;
-
- // store result
- Description->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION);
- Description->PropTypeSet.Set = KSPROPTYPESETID_General;
- Description->PropTypeSet.Id = 0;
- Description->PropTypeSet.Flags = 0;
- Description->MembersListCount = 0;
- Description->Reserved = 0;
-
- Irp->IoStatus.Information = sizeof(KSPROPERTY_DESCRIPTION);
- }
- return STATUS_SUCCESS;
- }
+ // need to allocate a property set
+ NewPropertySet = (PKSPROPERTY_SET)AllocateItem(NonPagedPool, (SubDeviceDescriptor->FilterPropertySetCount + 1) * sizeof(KSPROPERTY_SET), TAG_PORTCLASS);
+ if (!NewPropertySet)
+ {
+ // out of memory
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ // need to allocate property set guid
+ Guid = (LPGUID)AllocateItem(NonPagedPool, sizeof(GUID), TAG_PORTCLASS);
+ if (!Guid)
+ {
+ // out of memory
+ FreeItem(NewPropertySet, TAG_PORTCLASS);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
- NTSTATUS
- PcHandleNodePropertyRequest(
- PIRP Irp,
- IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor)
- {
- PIO_STACK_LOCATION IoStack;
- PPCPROPERTY_ITEM PropertyItem;
- PPCPROPERTY_REQUEST PropertyRequest;
- PKSP_NODE Property;
- NTSTATUS Status;
+ // are any existing property sets
+ if (SubDeviceDescriptor->FilterPropertySetCount)
+ {
+ // copy property sets
+ RtlMoveMemory(NewPropertySet, SubDeviceDescriptor->FilterPropertySet, SubDeviceDescriptor->FilterPropertySetCount * sizeof(KSPROPERTY_SET));
- // get current irp stack location
- IoStack = IoGetCurrentIrpStackLocation(Irp);
+ // release memory
+ FreeItem(SubDeviceDescriptor->FilterPropertySet, TAG_PORTCLASS);
+ }
- if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSP_NODE))
- {
- // certainly not a node property request
- return STATUS_NOT_FOUND;
- }
+ // store new property set descriptors
+ SubDeviceDescriptor->FilterPropertySet = NewPropertySet;
- // access property
- Property = (PKSP_NODE)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
+ // store index
+ PropertySetIndex = SubDeviceDescriptor->FilterPropertySetCount;
- if (IsEqualGUIDAligned(Property->Property.Set, GUID_NULL) && Property->Property.Id == 0 && Property->Property.Flags == (KSPROPERTY_TYPE_SETSUPPORT | KSPROPERTY_TYPE_TOPOLOGY))
- {
- return PcHandleGuidNullRequest(Irp, SubDeviceDescriptor);
+ // increment property set count
+ SubDeviceDescriptor->FilterPropertySetCount++;
+
+ // copy property guid
+ RtlMoveMemory(Guid, PropertyItem->Set, sizeof(GUID));
+
+ // initialize property set
+ SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].Set = Guid;
+ SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount = 0;
}
- // find property handler
- Status = PcFindNodePropertyHandler(Irp, SubDeviceDescriptor, &PropertyItem);
+ // as the property set has been indentified, now search for duplicate property set item entries
+ FilterPropertyItem = (PKSPROPERTY_ITEM)SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem;
+ bFound = FALSE;
- // check for success
- if (!NT_SUCCESS(Status))
+ for(Index = 0; Index < SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount; Index++)
{
- // might not be a node property request
- DPRINT("NotFound\n");
- return STATUS_NOT_FOUND;
+ // now search for an equal property set item
+ if (FilterPropertyItem->PropertyId == PropertyItem->Id)
+ {
+ // found existing property set item
+ bFound = TRUE;
+ PropertySetItemIndex = Index;
+ break;
+ }
+
+ // move to next entry
+ FilterPropertyItem++;
}
- if (Property->Property.Flags & KSPROPERTY_TYPE_BASICSUPPORT)
+ if (!bFound)
{
- // caller issued a basic property request
- if (!(PropertyItem->Flags & KSPROPERTY_TYPE_BASICSUPPORT))
+ // need to allocate memory for new property set item
+ NewFilterPropertyItem = (PKSPROPERTY_ITEM)AllocateItem(NonPagedPool, (SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount + 1) * sizeof(KSPROPERTY_ITEM), TAG_PORTCLASS);
+ if (!NewFilterPropertyItem)
{
- // driver does not have a basic support handler
- return PcNodeBasicSupportHandler(Irp, PropertyItem);
+ // out of memory
+ return STATUS_INSUFFICIENT_RESOURCES;
}
- }
- // sanity check
- PC_ASSERT(SubDeviceDescriptor->UnknownMiniport);
+ // are any existing property set items
+ if (SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount)
+ {
+ // copy property item sets
+ RtlMoveMemory(NewFilterPropertyItem,
+ (PVOID)SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem,
+ SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount * sizeof(KSPROPERTY_ITEM));
- // allocate a property request
- PropertyRequest = (PPCPROPERTY_REQUEST)AllocateItem(NonPagedPool, sizeof(PCPROPERTY_REQUEST), TAG_PORTCLASS);
- if (!PropertyRequest)
- return STATUS_INSUFFICIENT_RESOURCES;
+ // release old descriptors
+ FreeItem((PVOID)SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem, TAG_PORTCLASS);
+ }
- // initialize property request
- PropertyRequest->MajorTarget = SubDeviceDescriptor->UnknownMiniport;
- PropertyRequest->MinorTarget = SubDeviceDescriptor->UnknownStream;
- PropertyRequest->Irp = Irp;
- PropertyRequest->Node = Property->NodeId;
- PropertyRequest->PropertyItem = PropertyItem;
- PropertyRequest->Verb = Property->Property.Flags;
- PropertyRequest->InstanceSize = IoStack->Parameters.DeviceIoControl.InputBufferLength - sizeof(KSNODEPROPERTY);
- PropertyRequest->Instance = (PVOID)((ULONG_PTR)IoStack->Parameters.DeviceIoControl.Type3InputBuffer + sizeof(KSNODEPROPERTY));
- PropertyRequest->ValueSize = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
- PropertyRequest->Value = Irp->UserBuffer;
-
- Status = PropertyItem->Handler(PropertyRequest);
-
- if (Status != STATUS_PENDING)
- {
- //request completed
- Irp->IoStatus.Information = PropertyRequest->ValueSize;
- FreeItem(PropertyRequest, TAG_PORTCLASS);
- }
+ // store new descriptor
+ SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem = NewFilterPropertyItem;
- // done
- DPRINT("Status %x\n", Status);
- return Status;
- }
+ // store index
+ PropertySetItemIndex = SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount;
- NTSTATUS
- NTAPI
- PcHandlePropertyWithTable(
- IN PIRP Irp,
- IN ULONG PropertySetCount,
- IN PKSPROPERTY_SET PropertySet,
- IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor)
- {
- NTSTATUS Status;
+ // increment property item set count
+ SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount++;
- // try handle it as node property request
- Status = PcHandleNodePropertyRequest(Irp, SubDeviceDescriptor);
+ // now initialize property item
+ FilterPropertyItem = (PKSPROPERTY_ITEM)&SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem[PropertySetItemIndex];
+ FilterPropertyItem->PropertyId = PropertyItem->Id;
+ FilterPropertyItem->MinProperty = sizeof(KSPROPERTY);
+ FilterPropertyItem->MinData = 0;
- if (Status == STATUS_NOT_FOUND)
- {
- // store device descriptor
- KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (PKSPROPERTY_ITEM)SubDeviceDescriptor;
+ // are any set operations supported
+ if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_SET)
+ {
+ // setup handler
+ FilterPropertyItem->SetPropertyHandler = PropertyItemDispatch;
+ }
- /* then try KsPropertyHandler */
- Status = KsPropertyHandler(Irp, PropertySetCount, PropertySet);
- }
+ // are set operation supported
+ if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_GET)
+ {
+ // setup handler
+ FilterPropertyItem->GetPropertyHandler = PropertyItemDispatch;
+ }
- return Status;
- }
+ // are get operations supported
+ if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_GET)
+ {
+ // setup handler
+ FilterPropertyItem->GetPropertyHandler = PropertyItemDispatch;
+ }
- VOID
- NTAPI
- PcAcquireFormatResources(
- LONG Unknown,
- LONG Unknown2,
- LONG Unknown3,
- LONG Unknown4)
- {
- UNIMPLEMENTED;
- }
+ // are basic support operations supported
+ if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_BASICSUPPORT)
+ {
+ // setup handler
+ FilterPropertyItem->SupportHandler = PropertyItemDispatch;
+ }
- NTSTATUS
- PcAddToEventTable(
- PVOID Ptr,
- LONG Unknown2,
- ULONG Length,
- LONG Unknown3,
- LONG Unknown4,
- LONG Unknown5,
- LONG Unknown6,
- LONG Unknown7)
- {
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
- }
+ if (!bNode)
+ {
+ // store property item in relations
+ // only store property item of filter properties / pin properties
+ // because filter & pin properties do not require a specific context
+ // on the other hand node properties are specifically bound to a node
+
+ FilterPropertyItem->Relations = (const KSPROPERTY*)PropertyItem;
+ }
+ }
+ else
+ {
+ // property set item handler already present
- NTSTATUS
- PcAddToPropertyTable(
- PVOID Ptr,
- LONG Unknown,
- LONG Unknown2,
- LONG Unknown3,
- CHAR Unknown4)
- {
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ if (bNode)
+ {
+ // filter & pin properties should not be exposed on a node
+ ASSERT(SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem[PropertySetItemIndex].Relations == NULL);
+ }
+ else
+ {
+ // node properties should not be exposed on a filter & pin
+ ASSERT(SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem[PropertySetItemIndex].Relations != NULL);
+ }
+ }
+
+ // done
+ return STATUS_SUCCESS;
}
NTSTATUS
EventItem = (PPCEVENT_ITEM)((ULONG_PTR)EventItem + NodeDescriptor->AutomationTable->EventItemSize);
}
+ DPRINT1(" Index %u PropertyCount %u\n", Index, NodeDescriptor->AutomationTable->PropertyCount);
+ PropertyItem = (PPCPROPERTY_ITEM)NodeDescriptor->AutomationTable->Properties;
+ for(SubIndex = 0; SubIndex < NodeDescriptor->AutomationTable->PropertyCount; SubIndex++)
+ {
+ RtlStringFromGUID(*PropertyItem->Set, &GuidString);
+ DPRINT1(" PropertyIndex %u GUID %S Id %u Flags %x\n", SubIndex, GuidString.Buffer, PropertyItem->Id, PropertyItem->Flags);
+
+ PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + NodeDescriptor->AutomationTable->PropertyItemSize);
+ }
}
IN PPCFILTER_DESCRIPTOR FilterDescription)
{
SUBDEVICE_DESCRIPTOR * Descriptor;
- ULONG Index;
+ ULONG Index, SubIndex;
NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
PPCPIN_DESCRIPTOR SrcDescriptor;
+ PPCNODE_DESCRIPTOR NodeDescriptor;
+ PPCPROPERTY_ITEM PropertyItem;
+ // allocate subdevice descriptor
Descriptor = (PSUBDEVICE_DESCRIPTOR)AllocateItem(NonPagedPool, sizeof(SUBDEVICE_DESCRIPTOR), TAG_PORTCLASS);
if (!Descriptor)
return STATUS_INSUFFICIENT_RESOURCES;
InitializeListHead(&Descriptor->SymbolicLinkList);
InitializeListHead(&Descriptor->PhysicalConnectionList);
+ //FIXME add driver category guids
Descriptor->Interfaces = (GUID*)AllocateItem(NonPagedPool, sizeof(GUID) * InterfaceCount, TAG_PORTCLASS);
if (!Descriptor->Interfaces)
goto cleanup;
RtlCopyMemory(Descriptor->Interfaces, InterfaceGuids, sizeof(GUID) * InterfaceCount);
Descriptor->InterfaceCount = InterfaceCount;
+ //DumpFilterDescriptor(FilterDescription);
+
+ // are any property sets supported by the portcls
if (FilterPropertiesCount)
{
- /// FIXME
- /// handle driver properties
-
- DumpFilterDescriptor(FilterDescription);
-
+ // first allocate filter properties set
Descriptor->FilterPropertySet = (PKSPROPERTY_SET)AllocateItem(NonPagedPool, sizeof(KSPROPERTY_SET) * FilterPropertiesCount, TAG_PORTCLASS);
if (! Descriptor->FilterPropertySet)
goto cleanup;
+ // now copy all filter property sets
Descriptor->FilterPropertySetCount = FilterPropertiesCount;
for(Index = 0; Index < FilterPropertiesCount; Index++)
{
+ // copy property set
RtlMoveMemory(&Descriptor->FilterPropertySet[Index], &FilterProperties[Index], sizeof(KSPROPERTY_SET));
- }
- }
-
- Descriptor->Topology = (PKSTOPOLOGY)AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY), TAG_PORTCLASS);
- if (!Descriptor->Topology)
- goto cleanup;
- if (FilterDescription->ConnectionCount)
- {
- Descriptor->Topology->TopologyConnections = (PKSTOPOLOGY_CONNECTION)AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY_CONNECTION) * FilterDescription->ConnectionCount, TAG_PORTCLASS);
- if (!Descriptor->Topology->TopologyConnections)
- goto cleanup;
-
- RtlMoveMemory((PVOID)Descriptor->Topology->TopologyConnections, FilterDescription->Connections, FilterDescription->ConnectionCount * sizeof(PCCONNECTION_DESCRIPTOR));
- Descriptor->Topology->TopologyConnectionsCount = FilterDescription->ConnectionCount;
+ if (Descriptor->FilterPropertySet[Index].PropertiesCount)
+ {
+ // copy property items to make sure they are dynamically allocated
+ Descriptor->FilterPropertySet[Index].PropertyItem = (PKSPROPERTY_ITEM)AllocateItem(NonPagedPool, FilterProperties[Index].PropertiesCount * sizeof(KSPROPERTY_ITEM), TAG_PORTCLASS);
+ if (!Descriptor->FilterPropertySet[Index].PropertyItem)
+ {
+ // no memory
+ goto cleanup;
+ }
+
+ // copy filter property items
+ RtlMoveMemory((PVOID)Descriptor->FilterPropertySet[Index].PropertyItem, FilterProperties[Index].PropertyItem, FilterProperties[Index].PropertiesCount * sizeof(KSPROPERTY_ITEM));
+ }
+ }
}
- if (FilterDescription->NodeCount)
+ // now check if the filter descriptor supports filter properties
+ if (FilterDescription->AutomationTable)
{
- Descriptor->Topology->TopologyNodes = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS);
- if (!Descriptor->Topology->TopologyNodes)
- goto cleanup;
+ // get first entry
+ PropertyItem = (PPCPROPERTY_ITEM)FilterDescription->AutomationTable->Properties;
- Descriptor->Topology->TopologyNodesNames = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS);
- if (!Descriptor->Topology->TopologyNodesNames)
- goto cleanup;
-
- for(Index = 0; Index < FilterDescription->NodeCount; Index++)
+ // copy driver filter property sets
+ for(Index = 0; Index < FilterDescription->AutomationTable->PropertyCount; Index++)
{
- if (FilterDescription->Nodes[Index].Type)
- {
- RtlMoveMemory((PVOID)&Descriptor->Topology->TopologyNodes[Index], FilterDescription->Nodes[Index].Type, sizeof(GUID));
- }
- if (FilterDescription->Nodes[Index].Name)
+ // add the property item
+ Status = PcAddToPropertyTable(Descriptor, PropertyItem, FALSE);
+
+ // check for success
+ if (Status != STATUS_SUCCESS)
{
- RtlMoveMemory((PVOID)&Descriptor->Topology->TopologyNodesNames[Index], FilterDescription->Nodes[Index].Name, sizeof(GUID));
+ // goto cleanup
+ goto cleanup;
}
+
+ // move to next entry
+ PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + FilterDescription->AutomationTable->PropertyItemSize);
}
- Descriptor->Topology->TopologyNodesCount = FilterDescription->NodeCount;
}
+ // check if the filter has pins
if (FilterDescription->PinCount)
{
+ // allocate pin factory descriptors
Descriptor->Factory.KsPinDescriptor = (PKSPIN_DESCRIPTOR)AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR) * FilterDescription->PinCount, TAG_PORTCLASS);
if (!Descriptor->Factory.KsPinDescriptor)
goto cleanup;
+ // allocate pin instance info
Descriptor->Factory.Instances = (PPIN_INSTANCE_INFO)AllocateItem(NonPagedPool, FilterDescription->PinCount * sizeof(PIN_INSTANCE_INFO), TAG_PORTCLASS);
if (!Descriptor->Factory.Instances)
goto cleanup;
+ // initialize pin factory descriptor
Descriptor->Factory.PinDescriptorCount = FilterDescription->PinCount;
Descriptor->Factory.PinDescriptorSize = sizeof(KSPIN_DESCRIPTOR);
+ // grab first entry
SrcDescriptor = (PPCPIN_DESCRIPTOR)FilterDescription->Pins;
- DPRINT("Size %u Expected %u\n", FilterDescription->PinSize, sizeof(PCPIN_DESCRIPTOR));
// copy pin factories
for(Index = 0; Index < FilterDescription->PinCount; Index++)
{
+ // copy pin descriptor
RtlMoveMemory(&Descriptor->Factory.KsPinDescriptor[Index], &SrcDescriptor->KsPinDescriptor, sizeof(KSPIN_DESCRIPTOR));
- Descriptor->Factory.KsPinDescriptor[Index].Interfaces = PinInterfaces;
- Descriptor->Factory.KsPinDescriptor[Index].InterfacesCount = sizeof(PinInterfaces) / sizeof(KSPIN_INTERFACE);
-
- DPRINT("Index %u DataRangeCount %u\n", Index, SrcDescriptor->KsPinDescriptor.DataRangesCount);
-
+ // initialize pin factory instance data
Descriptor->Factory.Instances[Index].CurrentPinInstanceCount = 0;
Descriptor->Factory.Instances[Index].MaxFilterInstanceCount = SrcDescriptor->MaxFilterInstanceCount;
Descriptor->Factory.Instances[Index].MaxGlobalInstanceCount = SrcDescriptor->MaxGlobalInstanceCount;
Descriptor->Factory.Instances[Index].MinFilterInstanceCount = SrcDescriptor->MinFilterInstanceCount;
+
+ // check if the descriptor has an automation table
+ if (SrcDescriptor->AutomationTable)
+ {
+ // it has, grab first entry
+ PropertyItem = (PPCPROPERTY_ITEM)SrcDescriptor->AutomationTable->Properties;
+
+ // now add all supported property items
+ for(SubIndex = 0; SubIndex < SrcDescriptor->AutomationTable->PropertyCount; SubIndex++)
+ {
+ // add the property item to the table
+ Status = PcAddToPropertyTable(Descriptor, PropertyItem, FALSE);
+
+ // check for success
+ if (Status != STATUS_SUCCESS)
+ {
+ // goto cleanup
+ goto cleanup;
+ }
+
+ // move to next entry
+ PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + SrcDescriptor->AutomationTable->PropertyItemSize);
+ }
+ }
+
+ // move to next entry
SrcDescriptor = (PPCPIN_DESCRIPTOR)((ULONG_PTR)SrcDescriptor + FilterDescription->PinSize);
}
}
+ // allocate topology descriptor
+ Descriptor->Topology = (PKSTOPOLOGY)AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY), TAG_PORTCLASS);
+ if (!Descriptor->Topology)
+ goto cleanup;
+
+ // are there any connections
+ if (FilterDescription->ConnectionCount)
+ {
+ // allocate connection descriptor
+ Descriptor->Topology->TopologyConnections = (PKSTOPOLOGY_CONNECTION)AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY_CONNECTION) * FilterDescription->ConnectionCount, TAG_PORTCLASS);
+ if (!Descriptor->Topology->TopologyConnections)
+ goto cleanup;
+
+ // copy connection descriptor
+ RtlMoveMemory((PVOID)Descriptor->Topology->TopologyConnections, FilterDescription->Connections, FilterDescription->ConnectionCount * sizeof(PCCONNECTION_DESCRIPTOR));
+
+ // store connection count
+ Descriptor->Topology->TopologyConnectionsCount = FilterDescription->ConnectionCount;
+ }
+
+ // does the filter have nodes
+ if (FilterDescription->NodeCount)
+ {
+ // allocate topology node types array
+ Descriptor->Topology->TopologyNodes = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS);
+ if (!Descriptor->Topology->TopologyNodes)
+ goto cleanup;
+
+ // allocate topology node names array
+ Descriptor->Topology->TopologyNodesNames = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS);
+ if (!Descriptor->Topology->TopologyNodesNames)
+ goto cleanup;
+
+ // grab first entry
+ NodeDescriptor = (PPCNODE_DESCRIPTOR)FilterDescription->Nodes;
+
+ // iterate all nodes and copy node types / names and node properties
+ for(Index = 0; Index < FilterDescription->NodeCount; Index++)
+ {
+ // does it have a type
+ if (NodeDescriptor->Type)
+ {
+ // copy node type
+ RtlMoveMemory((PVOID)&Descriptor->Topology->TopologyNodes[Index], NodeDescriptor->Type, sizeof(GUID));
+ }
+
+ // does it have a node name
+ if (NodeDescriptor->Name)
+ {
+ // copy node name
+ RtlMoveMemory((PVOID)&Descriptor->Topology->TopologyNodesNames[Index], NodeDescriptor->Name, sizeof(GUID));
+ }
+
+ // check if has an automation table
+ if (NodeDescriptor->AutomationTable)
+ {
+ // grab first entry
+ PropertyItem = (PPCPROPERTY_ITEM)NodeDescriptor->AutomationTable->Properties;
+
+ // copy all node properties into the global property set
+ for(SubIndex = 0; SubIndex < NodeDescriptor->AutomationTable->PropertyCount; SubIndex++)
+ {
+ // add to property set
+ Status = PcAddToPropertyTable(Descriptor, PropertyItem, TRUE);
+
+ // check for success
+ if (Status != STATUS_SUCCESS)
+ {
+ // failed
+ goto cleanup;
+ }
+
+ // move to next property item
+ PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + NodeDescriptor->AutomationTable->PropertyItemSize);
+ }
+ }
+
+ // move to next descriptor
+ NodeDescriptor = (PPCNODE_DESCRIPTOR)((ULONG_PTR)NodeDescriptor + FilterDescription->NodeSize);
+ }
+
+ // now store the topology node count
+ Descriptor->Topology->TopologyNodesCount = FilterDescription->NodeCount;
+ }
+
+ // store descriptor
Descriptor->DeviceDescriptor = FilterDescription;
+
+ // store result
*OutSubdeviceDescriptor = Descriptor;
+ // done
return STATUS_SUCCESS;
cleanup:
if (!HalpGetInfoFromACPI)
{
/* No, so use our local table */
- Port = HalpComPortIrqMapping[0][0];
- for (i = 0; Port; i++)
+ for (i = 0, Port = HalpComPortIrqMapping[i][0];
+ Port;
+ i++, Port = HalpComPortIrqMapping[i][0])
{
/* Is this the port we want? */
if (Port == (ULONG_PTR)KdComPortInUse)
PRIMARY_VECTOR_BASE,
HIGH_LEVEL);
}
-
- /* Next port */
- Port = HalpComPortIrqMapping[i][0];
}
}
}
IN PVOID Handler,
IN KINTERRUPT_MODE Mode)
{
+ /* Set the IDT_LATCHED flag for latched interrupts */
+ if (Mode == Latched) Flags |= IDT_LATCHED;
+
/* Register the vector */
HalpRegisterVector(Flags, BusVector, SystemVector, Irql);
KSPROPERTY_DIRECTSOUND3DLISTENER_VELOCITY
*/
- #define KSPROPSETID_DrmAudioStream
- /*
- KSPROPERTY_DRMAUDIOSTREAM_CONTENTID
- */
-
#define KSPROPSETID_Hrtf3d
/*
KSPROPERTY_HRTF3D_FILTER_FORMAT
#endif // !_NTDDK_
} LOOPEDSTREAMING_POSITION_EVENT_DATA, *PLOOPEDSTREAMING_POSITION_EVENT_DATA ;
+ #define STATIC_KSPROPSETID_DrmAudioStream\
+ 0x2f2c8ddd, 0x4198, 0x4fac, 0xba, 0x29, 0x61, 0xbb, 0x5, 0xb7, 0xde, 0x6
+ DEFINE_GUIDSTRUCT("2F2C8DDD-4198-4fac-BA29-61BB05B7DE06", KSPROPSETID_DrmAudioStream);
+ #define KSPROPSETID_DrmAudioStream DEFINE_GUIDNAMED(KSPROPSETID_DrmAudioStream)
+
+ typedef enum {
+ KSPROPERTY_DRMAUDIOSTREAM_CONTENTID
+ } KSPROPERTY_DRMAUDIOSTREAM;
+
/*
SysAudio Properties
VOID NTAPI RtlInitLargeUnicodeString(IN OUT PLARGE_UNICODE_STRING,IN PCWSTR,IN INT);
BOOL NTAPI RtlLargeStringToUnicodeString( PUNICODE_STRING, PLARGE_STRING);
+ #define NB_HOOKS (WH_MAXHOOK-WH_MINHOOK+1)
+
typedef struct _DESKTOPINFO
{
PVOID pvDesktopBase;
PVOID pvDesktopLimit;
struct _WND *spwnd;
DWORD fsHooks;
- struct tagHOOK * aphkStart[16];
+ LIST_ENTRY aphkStart[NB_HOOKS];
HWND hTaskManWindow;
HWND hProgmanWindow;
/* Window Client Information structure */
struct _ETHREAD;
+ #define WEF_SETBYWNDPTI 0x0001
+
typedef struct tagHOOK
{
THRDESKHEAD head;
+ struct tagHOOK *phkNext; /* This is for user space. */
+ int HookId; /* Hook table index */
+ ULONG_PTR offPfn;
+ ULONG flags; /* Some internal flags */
+ INT ihmod;
+ PTHREADINFO ptiHooked;
+ struct _DESKTOP *rpdesk;
+ /* ReactOS */
LIST_ENTRY Chain; /* Hook chain entry */
struct _ETHREAD* Thread; /* Thread owning the hook */
- int HookId; /* Hook table index */
HOOKPROC Proc; /* Hook function */
BOOLEAN Ansi; /* Is it an Ansi hook? */
- ULONG Flags; /* Some internal flags */
UNICODE_STRING ModuleName; /* Module name for global hooks */
} HOOK, *PHOOK;
#define NOPARAM_ROUTINE_ANYPOPUP 0xffff0006
#define ONEPARAM_ROUTINE_CSRSS_GUICHECK 0xffff0008
#define ONEPARAM_ROUTINE_SWITCHCARETSHOWING 0xfffe0008
- #define ONEPARAM_ROUTINE_ISWINDOWINDESTROY 0xfffe000c
#define ONEPARAM_ROUTINE_ENABLEPROCWNDGHSTING 0xfffe000d
#define ONEPARAM_ROUTINE_GETDESKTOPMAPPING 0xfffe000e
#define ONEPARAM_ROUTINE_MSQSETWAKEMASK 0xfffe0027
#define TWOPARAM_ROUTINE_SETCARETPOS 0xfffd0060
#define TWOPARAM_ROUTINE_REGISTERLOGONPROC 0xfffd0062
#define TWOPARAM_ROUTINE_ROS_UPDATEUISTATE 0x1004
+ #define HWNDPARAM_ROUTINE_ROS_NOTIFYWINEVENT 0x1005
DWORD
NTAPI
IN PDEVICE_NODE DeviceNode
);
+ NTSTATUS
+ NTAPI
+ IopCreateResourceListFromRequirements(
+ IN PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList,
+ OUT PCM_RESOURCE_LIST *ResourceList
+ );
+
+ NTSTATUS
+ NTAPI
+ IopDetectResourceConflict(
+ IN PCM_RESOURCE_LIST ResourceList,
+ IN BOOLEAN Silent,
+ OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
+ );
+
//
// PNP Routines
//
}
/*
- * @unimplemented
+ * @halfplemented
*/
NTSTATUS NTAPI
IoReportResourceUsage(PUNICODE_STRING DriverClassName,
* a conflict is detected with another driver.
*/
{
- UNIMPLEMENTED;
- *ConflictDetected = FALSE;
- return STATUS_SUCCESS;
+ NTSTATUS Status;
+ PCM_RESOURCE_LIST ResourceList;
+
+ DPRINT1("IoReportResourceUsage is halfplemented!\n");
+
+ if (!DriverList && !DeviceList)
+ return STATUS_INVALID_PARAMETER;
+
+ if (DeviceList)
+ ResourceList = DeviceList;
+ else
+ ResourceList = DriverList;
+
+ Status = IopDetectResourceConflict(ResourceList, FALSE, NULL);
+ if (Status == STATUS_CONFLICTING_ADDRESSES)
+ {
+ *ConflictDetected = TRUE;
+
+ if (!OverrideConflict)
+ {
+ DPRINT1("Denying an attempt to claim resources currently in use by another device!\n");
+ return STATUS_CONFLICTING_ADDRESSES;
+ }
+ else
+ {
+ DPRINT1("Proceeding with conflicting resources\n");
+ }
+ }
+ else if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* TODO: Claim resources in registry */
+
+ *ConflictDetected = FALSE;
+
+ return STATUS_SUCCESS;
}
/*
- * @unimplemented
+ * @halfplemented
*/
NTSTATUS NTAPI
IoAssignResources(PUNICODE_STRING RegistryPath,
PIO_RESOURCE_REQUIREMENTS_LIST RequestedResources,
PCM_RESOURCE_LIST* AllocatedResources)
{
- UNIMPLEMENTED;
- return(STATUS_NOT_IMPLEMENTED);
+ NTSTATUS Status;
+
+ DPRINT1("IoAssignResources is halfplemented!\n");
+
+ Status = IopCreateResourceListFromRequirements(RequestedResources,
+ AllocatedResources);
+ if (!NT_SUCCESS(Status))
+ {
+ if (Status == STATUS_CONFLICTING_ADDRESSES)
+ DPRINT1("Denying an attempt to claim resources currently in use by another device!\n");
+
+ return Status;
+ }
+
+ /* TODO: Claim resources in registry */
+
+ return STATUS_SUCCESS;
}
/*
IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
PVOID Context);
- NTSTATUS
- IopDetectResourceConflict(IN PCM_RESOURCE_LIST ResourceList);
-
NTSTATUS
PpSetCustomTargetEvent(IN PDEVICE_OBJECT DeviceObject,
IN OUT PKEVENT SyncEvent OPTIONAL,
ResourceList = DriverList;
/* Look for a resource conflict */
- Status = IopDetectResourceConflict(ResourceList);
+ Status = IopDetectResourceConflict(ResourceList, FALSE, NULL);
if (Status == STATUS_CONFLICTING_ADDRESSES)
{
/* Oh noes */
#define NDEBUG
#include <debug.h>
- NTSTATUS
- IopDetectResourceConflict(
- IN PCM_RESOURCE_LIST ResourceList,
- IN BOOLEAN Silent,
- OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor);
-
static
BOOLEAN
IopCheckDescriptorForConflict(PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc, OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor)
return FALSE;
}
- static
- NTSTATUS
+
+ NTSTATUS NTAPI
IopCreateResourceListFromRequirements(
IN PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList,
OUT PCM_RESOURCE_LIST *ResourceList)
ULONG i, ii;
BOOLEAN Result = FALSE;
- if (ResDesc->ShareDisposition == CmResourceShareShared)
- return FALSE;
-
for (i = 0; i < ResourceList->Count; i++)
{
PCM_PARTIAL_RESOURCE_LIST ResList = &ResourceList->List[i].PartialResourceList;
if (DeviceNode->ResourceList)
{
- PWCHAR DeviceName = NULL;
UNICODE_STRING NameU;
- UNICODE_STRING Suffix;
+ UNICODE_STRING RawSuffix, TranslatedSuffix;
ULONG OldLength = 0;
ASSERT(DeviceNode->ResourceListTranslated);
+
+ RtlInitUnicodeString(&TranslatedSuffix, L".Translated");
+ RtlInitUnicodeString(&RawSuffix, L".Raw");
Status = IoGetDeviceProperty(DeviceNode->PhysicalDeviceObject,
DevicePropertyPhysicalDeviceObjectName,
0,
NULL,
&OldLength);
- if ((OldLength != 0) && (Status == STATUS_BUFFER_TOO_SMALL))
- {
- DeviceName = ExAllocatePool(NonPagedPool, OldLength);
- ASSERT(DeviceName);
-
- IoGetDeviceProperty(DeviceNode->PhysicalDeviceObject,
- DevicePropertyPhysicalDeviceObjectName,
- OldLength,
- DeviceName,
- &OldLength);
-
- RtlInitUnicodeString(&NameU, DeviceName);
- }
- else
- {
- /* Some failure */
- ASSERT(!NT_SUCCESS(Status));
- return Status;
- }
-
- RtlInitUnicodeString(&Suffix, L".Raw");
- RtlAppendUnicodeStringToString(&NameU, &Suffix);
+ if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
+ {
+ ASSERT(OldLength);
+
+ NameU.Buffer = ExAllocatePool(PagedPool, OldLength + TranslatedSuffix.Length);
+ if (!NameU.Buffer)
+ {
+ ZwClose(PnpMgrLevel2);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ NameU.Length = 0;
+ NameU.MaximumLength = OldLength + TranslatedSuffix.Length;
+
+ Status = IoGetDeviceProperty(DeviceNode->PhysicalDeviceObject,
+ DevicePropertyPhysicalDeviceObjectName,
+ NameU.MaximumLength,
+ NameU.Buffer,
+ &OldLength);
+ if (!NT_SUCCESS(Status))
+ {
+ ZwClose(PnpMgrLevel2);
+ ExFreePool(NameU.Buffer);
+ return Status;
+ }
+ }
+ else if (!NT_SUCCESS(Status))
+ {
+ /* Some failure */
+ ZwClose(PnpMgrLevel2);
+ return Status;
+ }
+ else
+ {
+ /* This should never happen */
+ ASSERT(FALSE);
+ }
+
+ NameU.Length = OldLength;
+
+ RtlAppendUnicodeStringToString(&NameU, &RawSuffix);
Status = ZwSetValueKey(PnpMgrLevel2,
&NameU,
if (!NT_SUCCESS(Status))
{
ZwClose(PnpMgrLevel2);
+ ExFreePool(NameU.Buffer);
return Status;
}
/* "Remove" the suffix by setting the length back to what it used to be */
- NameU.Length = (USHORT)OldLength;
+ NameU.Length = OldLength;
- RtlInitUnicodeString(&Suffix, L".Translated");
- RtlAppendUnicodeStringToString(&NameU, &Suffix);
+ RtlAppendUnicodeStringToString(&NameU, &TranslatedSuffix);
Status = ZwSetValueKey(PnpMgrLevel2,
&NameU,
DeviceNode->ResourceListTranslated,
PnpDetermineResourceListSize(DeviceNode->ResourceListTranslated));
ZwClose(PnpMgrLevel2);
- ASSERT(DeviceName);
- ExFreePool(DeviceName);
+ ExFreePool(NameU.Buffer);
+
if (!NT_SUCCESS(Status))
return Status;
}
DeviceNode->ResourceListTranslated = ExAllocatePool(PagedPool, ListSize);
if (!DeviceNode->ResourceListTranslated)
{
- Status =STATUS_NO_MEMORY;
+ Status = STATUS_NO_MEMORY;
goto cleanup;
}
RtlCopyMemory(DeviceNode->ResourceListTranslated, DeviceNode->ResourceList, ListSize);
&DescriptorTranslated->u.Port.Start))
{
Status = STATUS_UNSUCCESSFUL;
+ DPRINT1("Failed to translate port resource (Start: 0xI64x)\n", DescriptorRaw->u.Port.Start.QuadPart);
goto cleanup;
}
break;
DescriptorRaw->u.Interrupt.Vector,
(PKIRQL)&DescriptorTranslated->u.Interrupt.Level,
&DescriptorTranslated->u.Interrupt.Affinity);
+
+ if (!DescriptorTranslated->u.Interrupt.Vector)
+ {
+ Status = STATUS_UNSUCCESSFUL;
+ DPRINT1("Failed to translate interrupt resource (Vector: 0x%x | Level: 0x%x)\n", DescriptorRaw->u.Interrupt.Vector,
+ DescriptorRaw->u.Interrupt.Level);
+ goto cleanup;
+ }
break;
}
case CmResourceTypeMemory:
&DescriptorTranslated->u.Memory.Start))
{
Status = STATUS_UNSUCCESSFUL;
+ DPRINT1("Failed to translate memory resource (Start: 0xI64x)\n", DescriptorRaw->u.Memory.Start.QuadPart);
goto cleanup;
}
}
Status = IopCreateResourceListFromRequirements(DeviceNode->ResourceRequirements,
&DeviceNode->ResourceList);
if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create a resource list from supplied resources for %wZ\n", &DeviceNode->InstancePath);
goto ByeBye;
+ }
- Status = IopDetectResourceConflict(DeviceNode->ResourceList, FALSE, NULL);
- if (!NT_SUCCESS(Status))
- goto ByeBye;
+ /* IopCreateResourceListFromRequirements should NEVER succeed with a conflicting list */
+ ASSERT(IopDetectResourceConflict(DeviceNode->ResourceList, FALSE, NULL) != STATUS_CONFLICTING_ADDRESSES);
Finish:
Status = IopTranslateDeviceResources(DeviceNode);
if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to translate resources for %wZ\n", &DeviceNode->InstancePath);
goto ByeBye;
+ }
Status = IopUpdateResourceMapForPnPDevice(DeviceNode);
if (!NT_SUCCESS(Status))
return Result;
}
- NTSTATUS
+ NTSTATUS NTAPI
IopDetectResourceConflict(
IN PCM_RESOURCE_LIST ResourceList,
IN BOOLEAN Silent,
return STATUS_SUCCESS;
}
+ ULONG
+ NTAPI
+ MiGetPageProtection(IN PMMPTE PointerPte)
+ {
+ MMPTE TempPte;
+ PMMPFN Pfn;
+ PAGED_CODE();
+
+ /* Copy this PTE's contents */
+ TempPte = *PointerPte;
+
+ /* Assure it's not totally zero */
+ ASSERT(TempPte.u.Long);
+
+ /* Check for a special prototype format */
+ if (TempPte.u.Soft.Valid == 0 &&
+ TempPte.u.Soft.Prototype == 1)
+ {
+ /* Unsupported now */
+ UNIMPLEMENTED;
+ ASSERT(FALSE);
+ }
+
+ /* In the easy case of transition or demand zero PTE just return its protection */
+ if (!TempPte.u.Hard.Valid) return MmProtectToValue[TempPte.u.Soft.Protection];
+
+ /* If we get here, the PTE is valid, so look up the page in PFN database */
+ Pfn = MiGetPfnEntry(TempPte.u.Hard.PageFrameNumber);
+
+ if (!Pfn->u3.e1.PrototypePte)
+ {
+ /* Return protection of the original pte */
+ return MmProtectToValue[Pfn->OriginalPte.u.Soft.Protection];
+ }
+
+ /* This is hardware PTE */
+ UNIMPLEMENTED;
+ ASSERT(FALSE);
+
+ return PAGE_NOACCESS;
+ }
+
ULONG
NTAPI
MiQueryAddressState(IN PVOID Va,
{
/* This means it's committed */
State = MEM_COMMIT;
-
- /* For now, we lie about the protection */
- Protect = PAGE_EXECUTE_READWRITE;
+
+ /* Get protection state of this page */
+ Protect = MiGetPageProtection(PointerPte);
}
else
{
NTSTATUS Status;
PMMVAD Vad = NULL;
PVOID Address, NextAddress;
- BOOLEAN Found;
+ BOOLEAN Found = FALSE;
ULONG NewProtect, NewState, BaseVpn;
MEMORY_BASIC_INFORMATION MemoryInfo;
KAPC_STATE ApcState;
if ((BaseAddress > MM_HIGHEST_VAD_ADDRESS) ||
(PAGE_ALIGN(BaseAddress) == (PVOID)USER_SHARED_DATA))
{
- /* FIXME: We should return some bogus info structure */
- UNIMPLEMENTED;
- while (TRUE);
+ Address = PAGE_ALIGN(BaseAddress);
+
+ /* Make up an info structure describing this range */
+ MemoryInfo.BaseAddress = Address;
+ MemoryInfo.AllocationProtect = PAGE_READONLY;
+ MemoryInfo.Type = MEM_PRIVATE;
+
+ /* Special case for shared data */
+ if (Address == (PVOID)USER_SHARED_DATA)
+ {
+ MemoryInfo.AllocationBase = (PVOID)USER_SHARED_DATA;
+ MemoryInfo.State = MEM_COMMIT;
+ MemoryInfo.Protect = PAGE_READONLY;
+ MemoryInfo.RegionSize = PAGE_SIZE;
+ }
+ else
+ {
+ MemoryInfo.AllocationBase = (PCHAR)MM_HIGHEST_VAD_ADDRESS + 1;
+ MemoryInfo.State = MEM_RESERVE;
+ MemoryInfo.Protect = PAGE_NOACCESS;
+ MemoryInfo.RegionSize = (ULONG_PTR)MemoryInfo.AllocationBase - (ULONG_PTR)Address;
+ }
+
+ /* Return the data (FIXME: Use SEH) */
+ *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
+ if (ReturnLength) *ReturnLength = sizeof(MEMORY_BASIC_INFORMATION);
+
+ return STATUS_SUCCESS;
}
/* Check if this is for a local or remote process */
/* Was a VAD found? */
if (!Found)
{
- /* We don't handle this yet */
- UNIMPLEMENTED;
- while (TRUE);
+ Address = PAGE_ALIGN(BaseAddress);
+
+ /* Calculate region size */
+ if (Vad)
+ {
+ if (Vad->StartingVpn >= BaseVpn)
+ {
+ /* Region size is the free space till the start of that VAD */
+ MemoryInfo.RegionSize = (ULONG_PTR)(Vad->StartingVpn << PAGE_SHIFT) - (ULONG_PTR)Address;
+ }
+ else
+ {
+ /* Get the next VAD */
+ Vad = (PMMVAD)MiGetNextNode((PMMADDRESS_NODE)Vad);
+ if (Vad)
+ {
+ /* Region size is the free space till the start of that VAD */
+ MemoryInfo.RegionSize = (ULONG_PTR)(Vad->StartingVpn << PAGE_SHIFT) - (ULONG_PTR)Address;
+ }
+ else
+ {
+ /* Maximum possible region size with that base address */
+ MemoryInfo.RegionSize = (PCHAR)MM_HIGHEST_VAD_ADDRESS + 1 - (PCHAR)Address;
+ }
+ }
+ }
+ else
+ {
+ /* Maximum possible region size with that base address */
+ MemoryInfo.RegionSize = (PCHAR)MM_HIGHEST_VAD_ADDRESS + 1 - (PCHAR)Address;
+ }
+
+ /* Check if we were attached */
+ if (ProcessHandle != NtCurrentProcess())
+ {
+ /* Detach and derefernece the process */
+ KeUnstackDetachProcess(&ApcState);
+ ObDereferenceObject(TargetProcess);
+ }
+
+ /* Build the rest of the initial information block */
+ MemoryInfo.BaseAddress = Address;
+ MemoryInfo.AllocationBase = NULL;
+ MemoryInfo.AllocationProtect = 0;
+ MemoryInfo.State = MEM_FREE;
+ MemoryInfo.Protect = PAGE_NOACCESS;
+ MemoryInfo.Type = 0;
+
+ /* Return the data (FIXME: Use SEH) */
+ *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
+ if (ReturnLength) *ReturnLength = sizeof(MEMORY_BASIC_INFORMATION);
+
+ return STATUS_SUCCESS;
}
-
+
/* This must be a VM VAD */
ASSERT(Vad->u.VadFlags.PrivateMemory);
case WM_CLOSE:
return 0;
+ case WM_DISPLAYCHANGE:
+ MoveWindow(Wnd, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
+ break;
+
case WM_NOTIFY:
{
PPRIVATE_NOTIFY_DESKTOP nmh = (PPRIVATE_NOTIFY_DESKTOP)lParam;
--- /dev/null
- dib/dib1bpp.c
+
+
+
+include_directories(.)
+include_directories(include)
+include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include)
+include_directories(${REACTOS_SOURCE_DIR}/lib/3rdparty/freetype/include)
+include_directories(${REACTOS_SOURCE_DIR}/include/reactos/subsys)
+include_directories(${REACTOS_SOURCE_DIR}/include/reactos/drivers)
+
+add_definitions(-DLANGPACK)
+add_definitions(-D_WIN32K_)
+
+list(APPEND SOURCE
- ldr/loader.c
++ dib/alphablend.c
++ dib/dib1bpp.c
+ dib/dib4bpp.c
+ dib/dib8bpp.c
+ dib/dib16bpp.c
+ dib/dib24bpp.c
+ dib/dib32bpp.c
+ dib/dib.c
+ dib/floodfill.c
+ dib/stretchblt.c
+ eng/alphablend.c
+ eng/bitblt.c
+ eng/engbrush.c
+ eng/engevent.c
+ eng/clip.c
+ eng/copybits.c
+ eng/debug.c
+ eng/device.c
+ eng/driverobj.c
+ eng/error.c
+ eng/float.c
+ eng/gradient.c
+ eng/lineto.c
++ eng/ldevobj.c
+ eng/mapping.c
+ eng/mem.c
+ eng/engmisc.c
+ eng/mouse.c
+ eng/paint.c
++ eng/pdevobj.c
+ eng/perfcnt.c
++ eng/rlecomp.c
+ eng/semaphor.c
+ eng/sort.c
+ eng/string.c
+ eng/stretchblt.c
+ eng/surface.c
+ eng/transblt.c
+ eng/engwindow.c
+ eng/xlate.c
+ main/dllmain.c
+ misc/driver.c
+ misc/err.c
+ misc/file.c
+ misc/math.c
+ misc/rtlstr.c
+ misc/copy.c
+ misc/registry.c
+ misc/usrheap.c
+ ntddraw/ddraw.c
+ ntddraw/dd.c
+ ntddraw/ddsurf.c
+ ntddraw/d3d.c
+ ntddraw/dvp.c
+ ntddraw/mocomp.c
+ ntddraw/eng.c
+ ntddraw/dxeng.c
+ ntuser/accelerator.c
+ ntuser/callback.c
+ ntuser/callproc.c
+ ntuser/caret.c
+ ntuser/class.c
+ ntuser/clipboard.c
+ ntuser/csr.c
+ ntuser/cursoricon.c
+ ntuser/defwnd.c
+ ntuser/desktop.c
+ ntuser/display.c
+ ntuser/event.c
+ ntuser/focus.c
+ ntuser/guicheck.c
+ ntuser/hook.c
+ ntuser/hotkey.c
+ ntuser/input.c
+ ntuser/keyboard.c
+ ntuser/kbdlayout.c
+ ntuser/menu.c
+ ntuser/message.c
+ ntuser/metric.c
+ ntuser/misc.c
+ ntuser/monitor.c
+ ntuser/msgqueue.c
+ ntuser/ntstubs.c
+ ntuser/ntuser.c
+ ntuser/painting.c
+ ntuser/prop.c
+ ntuser/scrollbar.c
+ ntuser/session.c
+ ntuser/simplecall.c
+ ntuser/sysparams.c
+ ntuser/timer.c
+ ntuser/useratom.c
+ ntuser/vis.c
+ ntuser/windc.c
+ ntuser/window.c
+ ntuser/winpos.c
+ ntuser/winsta.c
+ ntuser/object.c
+ objects/arc.c
+ objects/bezier.c
+ objects/bitblt.c
+ objects/bitmaps.c
+ objects/brush.c
+ objects/cliprgn.c
+ objects/coord.c
+ objects/dcattr.c
+ objects/dclife.c
+ objects/dcobjs.c
+ objects/dcstate.c
+ objects/dcutil.c
+ objects/device.c
+ objects/dibobj.c
+ objects/drawing.c
+ objects/fillshap.c
+ objects/font.c
+ objects/freetype.c
+ objects/gdibatch.c
+ objects/gdiobj.c
+ objects/icm.c
+ objects/line.c
+ objects/metafile.c
+ objects/palette.c
+ objects/path.c
+ objects/pen.c
+ objects/polyfill.c
+ objects/print.c
+ objects/rect.c
+ objects/region.c
+ objects/stockobj.c
+ objects/text.c
+ objects/wingl.c
+ objects/xformobj.c
+ stubs/stubs.c
+ stubs/umpdstubs.c
+ win32k.rc)
+
+list(APPEND GENDIB_GENERATED
+ ${CMAKE_CURRENT_BINARY_DIR}/dib/dib8gen.c
+ ${CMAKE_CURRENT_BINARY_DIR}/dib/dib16gen.c
+ ${CMAKE_CURRENT_BINARY_DIR}/dib/dib32gen.c)
+
+set_source_files_properties(${GENDIB_GENERATED} PROPERTIES GENERATED TRUE)
+
+list(APPEND SOURCE ${GENDIB_GENERATED})
+
+if(ARCH MATCHES i386)
+list(APPEND SOURCE
+ dib/i386/dib24bpp_hline.s
+ dib/i386/dib32bpp_hline.s
+ dib/i386/dib32bpp_colorfill.s
+ eng/i386/floatobj.S
+ misc/i386/cos_asm.s
+ misc/i386/sin_asm.s
+ misc/i386/atan2_asm.s
+ misc/i386/floor_asm.s
+ misc/i386/ceil_asm.s)
+else()
+list(APPEND SOURCE
+ dib/dib24bppc.c
+ dib/dib32bppc.c)
+endif(ARCH MATCHES i386)
+
+add_library(win32k SHARED
+ ${CMAKE_CURRENT_BINARY_DIR}/win32k_pch.h.gch
+ ${SOURCE})
+
+set_target_properties(win32k PROPERTIES LINK_FLAGS "-Wl,-entry,_DriverEntry@8 -Wl,--image-base,0x00010000 -Wl,--subsystem,native" SUFFIX ".sys")
+
+target_link_libraries(win32k
+ ${CMAKE_CURRENT_SOURCE_DIR}/win32k_i386.def
+ pseh
+ -lntoskrnl
+ -lhal
+ -lftfd
+ dxguid
+ libcntpr)
+
+add_pch(win32k ${CMAKE_CURRENT_SOURCE_DIR}/pch.h ${SOURCE})
+add_dependencies(win32k psdk gendib_generated bugcodes subsystem_napi buildno_header)
+add_livecd_target(win32k reactos/system32)
--- /dev/null
+ /*
+ * PROJECT: Win32 subsystem
+ * LICENSE: See COPYING in the top level directory
+ * FILE: subsystems/win32/win32k/dib/stretchblt.c
+ * PURPOSE: AlphaBlend implementation suitable for all bit depths
+ * PROGRAMMERS: Jérôme Gardou
+ */
+
+ #include <win32k.h>
+
+ #define NDEBUG
+ #include <debug.h>
+
+ typedef union
+ {
+ ULONG ul;
+ struct
+ {
+ UCHAR red;
+ UCHAR green;
+ UCHAR blue;
+ UCHAR alpha;
+ } col;
+ } NICEPIXEL32;
+
+ static __inline UCHAR
+ Clamp8(ULONG val)
+ {
+ return (val > 255) ? 255 : val;
+ }
+
+ BOOLEAN
+ DIB_XXBPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
+ RECTL* SourceRect, CLIPOBJ* ClipRegion,
+ XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
+ {
+ INT DstX, DstY, SrcX, SrcY;
+ BLENDFUNCTION BlendFunc;
+ register NICEPIXEL32 DstPixel32;
+ register NICEPIXEL32 SrcPixel32;
+ UCHAR Alpha, SrcBpp = BitsPerFormat(Source->iBitmapFormat);
+ EXLATEOBJ* pexlo;
+ EXLATEOBJ exloSrcRGB, exloDstRGB, exloRGBSrc;
+ PFN_DIB_PutPixel pfnDibPutPixel = DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_PutPixel;
+
+ DPRINT("DIB_16BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
+ SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
+ DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
+
+ BlendFunc = BlendObj->BlendFunction;
+ if (BlendFunc.BlendOp != AC_SRC_OVER)
+ {
+ DPRINT1("BlendOp != AC_SRC_OVER\n");
+ return FALSE;
+ }
+ if (BlendFunc.BlendFlags != 0)
+ {
+ DPRINT1("BlendFlags != 0\n");
+ return FALSE;
+ }
+ if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0)
+ {
+ DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat);
+ return FALSE;
+ }
+ if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 &&
+ SrcBpp != 32)
+ {
+ DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n");
+ return FALSE;
+ }
+
+ if (!ColorTranslation)
+ {
+ DPRINT1("ColorTranslation must not be NULL!\n");
+ return FALSE;
+ }
+
+ pexlo = CONTAINING_RECORD(ColorTranslation, EXLATEOBJ, xlo);
+ EXLATEOBJ_vInitialize(&exloSrcRGB, pexlo->ppalSrc, &gpalRGB, 0, 0, 0);
+ EXLATEOBJ_vInitialize(&exloDstRGB, pexlo->ppalDst, &gpalRGB, 0, 0, 0);
+ EXLATEOBJ_vInitialize(&exloRGBSrc, &gpalRGB, pexlo->ppalSrc, 0, 0, 0);
+
+ SrcY = SourceRect->top;
+ DstY = DestRect->top;
+ while ( DstY < DestRect->bottom )
+ {
+ SrcX = SourceRect->left;
+ DstX = DestRect->left;
+ while(DstX < DestRect->right)
+ {
+ SrcPixel32.ul = DIB_GetSource(Source, SrcX, SrcY, &exloSrcRGB.xlo);
+ SrcPixel32.col.red = (SrcPixel32.col.red * BlendFunc.SourceConstantAlpha) / 255;
+ SrcPixel32.col.green = (SrcPixel32.col.green * BlendFunc.SourceConstantAlpha) / 255;
+ SrcPixel32.col.blue = (SrcPixel32.col.blue * BlendFunc.SourceConstantAlpha) / 255;
+
+ Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
+ (SrcPixel32.col.alpha * BlendFunc.SourceConstantAlpha) / 255 :
+ BlendFunc.SourceConstantAlpha ;
+
+ DstPixel32.ul = DIB_GetSource(Dest, DstX, DstY, &exloDstRGB.xlo);
+ DstPixel32.col.red = Clamp8((DstPixel32.col.red * (255 - Alpha)) / 255 + SrcPixel32.col.red) ;
+ DstPixel32.col.green = Clamp8((DstPixel32.col.green * (255 - Alpha)) / 255 + SrcPixel32.col.green) ;
+ DstPixel32.col.blue = Clamp8((DstPixel32.col.blue * (255 - Alpha)) / 255 + SrcPixel32.col.blue) ;
+ DstPixel32.ul = XLATEOBJ_iXlate(&exloRGBSrc.xlo, DstPixel32.ul);
+ pfnDibPutPixel(Dest, DstX, DstY, XLATEOBJ_iXlate(ColorTranslation, DstPixel32.ul));
+
+ DstX++;
+ SrcX = SourceRect->left + ((DstX-DestRect->left)*(SourceRect->right - SourceRect->left))
+ /(DestRect->right-DestRect->left);
+ }
+ DstY++;
+ SrcY = SourceRect->top + ((DstY-DestRect->top)*(SourceRect->bottom - SourceRect->top))
+ /(DestRect->bottom-DestRect->top);
+ }
+
+ EXLATEOBJ_vCleanup(&exloDstRGB);
+ EXLATEOBJ_vCleanup(&exloRGBSrc);
+ EXLATEOBJ_vCleanup(&exloSrcRGB);
+
+ return TRUE;
+ }
+
{
DIB_1BPP_PutPixel, DIB_1BPP_GetPixel, DIB_1BPP_HLine, DIB_1BPP_VLine,
DIB_1BPP_BitBlt, DIB_1BPP_BitBltSrcCopy, DIB_XXBPP_StretchBlt,
- DIB_1BPP_TransparentBlt, DIB_1BPP_ColorFill, DIB_1BPP_AlphaBlend
+ DIB_1BPP_TransparentBlt, DIB_1BPP_ColorFill, DIB_XXBPP_AlphaBlend
},
/* BMF_4BPP */
{
DIB_4BPP_PutPixel, DIB_4BPP_GetPixel, DIB_4BPP_HLine, DIB_4BPP_VLine,
DIB_4BPP_BitBlt, DIB_4BPP_BitBltSrcCopy, DIB_XXBPP_StretchBlt,
- DIB_4BPP_TransparentBlt, DIB_4BPP_ColorFill, DIB_4BPP_AlphaBlend
+ DIB_4BPP_TransparentBlt, DIB_4BPP_ColorFill, DIB_XXBPP_AlphaBlend
},
/* BMF_8BPP */
{
DIB_8BPP_PutPixel, DIB_8BPP_GetPixel, DIB_8BPP_HLine, DIB_8BPP_VLine,
DIB_8BPP_BitBlt, DIB_8BPP_BitBltSrcCopy, DIB_XXBPP_StretchBlt,
- DIB_8BPP_TransparentBlt, DIB_8BPP_ColorFill, DIB_8BPP_AlphaBlend
+ DIB_8BPP_TransparentBlt, DIB_8BPP_ColorFill, DIB_XXBPP_AlphaBlend
},
/* BMF_16BPP */
{
DIB_16BPP_PutPixel, DIB_16BPP_GetPixel, DIB_16BPP_HLine, DIB_16BPP_VLine,
DIB_16BPP_BitBlt, DIB_16BPP_BitBltSrcCopy, DIB_XXBPP_StretchBlt,
- DIB_16BPP_TransparentBlt, DIB_16BPP_ColorFill, DIB_16BPP_AlphaBlend
+ DIB_16BPP_TransparentBlt, DIB_16BPP_ColorFill, DIB_XXBPP_AlphaBlend
},
/* BMF_24BPP */
{
BOOLEAN DIB_1BPP_BitBltSrcCopy(PBLTINFO);
BOOLEAN DIB_1BPP_TransparentBlt(SURFOBJ*,SURFOBJ*,RECTL*,RECTL*,XLATEOBJ*,ULONG);
BOOLEAN DIB_1BPP_ColorFill(SURFOBJ*, RECTL*, ULONG);
- BOOLEAN DIB_1BPP_AlphaBlend(SURFOBJ*, SURFOBJ*, RECTL*, RECTL*, CLIPOBJ*, XLATEOBJ*, BLENDOBJ*);
VOID DIB_4BPP_PutPixel(SURFOBJ*,LONG,LONG,ULONG);
ULONG DIB_4BPP_GetPixel(SURFOBJ*,LONG,LONG);
BOOLEAN DIB_4BPP_BitBltSrcCopy(PBLTINFO);
BOOLEAN DIB_4BPP_TransparentBlt(SURFOBJ*,SURFOBJ*,RECTL*,RECTL*,XLATEOBJ*,ULONG);
BOOLEAN DIB_4BPP_ColorFill(SURFOBJ*, RECTL*, ULONG);
- BOOLEAN DIB_4BPP_AlphaBlend(SURFOBJ*, SURFOBJ*, RECTL*, RECTL*, CLIPOBJ*, XLATEOBJ*, BLENDOBJ*);
VOID DIB_8BPP_PutPixel(SURFOBJ*,LONG,LONG,ULONG);
ULONG DIB_8BPP_GetPixel(SURFOBJ*,LONG,LONG);
BOOLEAN DIB_8BPP_BitBltSrcCopy(PBLTINFO);
BOOLEAN DIB_8BPP_TransparentBlt(SURFOBJ*,SURFOBJ*,RECTL*,RECTL*,XLATEOBJ*,ULONG);
BOOLEAN DIB_8BPP_ColorFill(SURFOBJ*, RECTL*, ULONG);
- BOOLEAN DIB_8BPP_AlphaBlend(SURFOBJ*, SURFOBJ*, RECTL*, RECTL*, CLIPOBJ*, XLATEOBJ*, BLENDOBJ*);
VOID DIB_16BPP_PutPixel(SURFOBJ*,LONG,LONG,ULONG);
ULONG DIB_16BPP_GetPixel(SURFOBJ*,LONG,LONG);
BOOLEAN DIB_16BPP_BitBltSrcCopy(PBLTINFO);
BOOLEAN DIB_16BPP_TransparentBlt(SURFOBJ*,SURFOBJ*,RECTL*,RECTL*,XLATEOBJ*,ULONG);
BOOLEAN DIB_16BPP_ColorFill(SURFOBJ*, RECTL*, ULONG);
- BOOLEAN DIB_16BPP_AlphaBlend(SURFOBJ*, SURFOBJ*, RECTL*, RECTL*, CLIPOBJ*, XLATEOBJ*, BLENDOBJ*);
VOID DIB_24BPP_PutPixel(SURFOBJ*,LONG,LONG,ULONG);
ULONG DIB_24BPP_GetPixel(SURFOBJ*,LONG,LONG);
BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ*,SURFOBJ*,SURFOBJ*,SURFOBJ*,RECTL*,RECTL*,POINTL*,BRUSHOBJ*,POINTL*,XLATEOBJ*,ROP4);
BOOLEAN DIB_XXBPP_FloodFillSolid(SURFOBJ*, BRUSHOBJ*, RECTL*, POINTL*, ULONG, UINT);
+ BOOLEAN DIB_XXBPP_AlphaBlend(SURFOBJ*, SURFOBJ*, RECTL*, RECTL*, CLIPOBJ*, XLATEOBJ*, BLENDOBJ*);
extern unsigned char notmask[2];
extern unsigned char altnotmask[2];
return TRUE;
}
- typedef union
- {
- ULONG ul;
- struct
- {
- UCHAR red;
- UCHAR green;
- UCHAR blue;
- UCHAR alpha;
- } col;
- } NICEPIXEL32;
-
- typedef union
- {
- USHORT us;
- struct
- {
- USHORT red:5,
- green:6,
- blue:5;
- } col;
- } NICEPIXEL16;
-
- static __inline UCHAR
- Clamp5(ULONG val)
- {
- return (val > 31) ? 31 : val;
- }
-
- static __inline UCHAR
- Clamp8(ULONG val)
- {
- return (val > 255) ? 255 : val;
- }
-
- static __inline UCHAR
- Clamp6(ULONG val)
- {
- return (val > 63) ? 63 : val;
- }
-
- BOOLEAN
- DIB_16BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
- RECTL* SourceRect, CLIPOBJ* ClipRegion,
- XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
- {
- INT Rows, Cols, SrcX, SrcY;
- register PUSHORT Dst;
- ULONG DstDelta;
- BLENDFUNCTION BlendFunc;
- register NICEPIXEL16 SrcPixel16;
- register NICEPIXEL16 DstPixel16;
- register NICEPIXEL32 SrcPixel32;
- register NICEPIXEL32 DstPixel32;
- UCHAR Alpha, SrcBpp;
- EXLATEOBJ *pexlo;
- EXLATEOBJ exloDst2Src;
-
- DPRINT("DIB_16BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
- SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
- DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
-
- ASSERT(DestRect->bottom - DestRect->top == SourceRect->bottom - SourceRect->top &&
- DestRect->right - DestRect->left == SourceRect->right - SourceRect->left);
-
- BlendFunc = BlendObj->BlendFunction;
- if (BlendFunc.BlendOp != AC_SRC_OVER)
- {
- DPRINT1("BlendOp != AC_SRC_OVER\n");
- return FALSE;
- }
- if (BlendFunc.BlendFlags != 0)
- {
- DPRINT1("BlendFlags != 0\n");
- return FALSE;
- }
- if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0)
- {
- DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat);
- return FALSE;
- }
- if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 &&
- BitsPerFormat(Source->iBitmapFormat) != 32)
- {
- DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n");
- return FALSE;
- }
-
- if (!ColorTranslation)
- {
- DPRINT1("ColorTranslation must not be NULL!\n");
- return FALSE;
- }
-
- pexlo = CONTAINING_RECORD(ColorTranslation, EXLATEOBJ, xlo);
- EXLATEOBJ_vInitialize(&exloDst2Src, pexlo->ppalDst, pexlo->ppalSrc, 0, 0, 0);
-
- Dst = (PUSHORT)((ULONG_PTR)Dest->pvScan0 + (DestRect->top * Dest->lDelta) +
- (DestRect->left << 1));
- DstDelta = Dest->lDelta - ((DestRect->right - DestRect->left) << 1);
- SrcBpp = BitsPerFormat(Source->iBitmapFormat);
-
- Rows = DestRect->bottom - DestRect->top;
- SrcY = SourceRect->top;
- while (--Rows >= 0)
- {
- Cols = DestRect->right - DestRect->left;
- SrcX = SourceRect->left;
- while (--Cols >= 0)
- {
- if (SrcBpp <= 16)
- {
- SrcPixel16.us = DIB_GetSource(Source, SrcX++, SrcY, ColorTranslation);
- SrcPixel32.col.red = (SrcPixel16.col.red << 3);
- SrcPixel32.col.green = (SrcPixel16.col.green << 2);
- SrcPixel32.col.blue = (SrcPixel16.col.blue << 3);
-
- SrcPixel32.col.red = SrcPixel32.col.red * BlendFunc.SourceConstantAlpha / 255;
- SrcPixel32.col.green = SrcPixel32.col.green * BlendFunc.SourceConstantAlpha / 255;
- SrcPixel32.col.blue = SrcPixel32.col.blue * BlendFunc.SourceConstantAlpha / 255;
- SrcPixel32.col.alpha = (SrcBpp == 32) ?
- (SrcPixel32.col.alpha * BlendFunc.SourceConstantAlpha / 255) :
- BlendFunc.SourceConstantAlpha;
-
- Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
- SrcPixel32.col.alpha : BlendFunc.SourceConstantAlpha;
-
- DstPixel16.us = *Dst;
- DstPixel16.col.red = Clamp5(DstPixel16.col.red * (255 - Alpha) / 255 +
- (SrcPixel32.col.red >> 3));
-
- DstPixel16.col.green = Clamp6(DstPixel16.col.green * (255 - Alpha) / 255 +
- (SrcPixel32.col.green >> 2));
-
- DstPixel16.col.blue = Clamp5(DstPixel16.col.blue * (255 - Alpha) / 255 +
- (SrcPixel32.col.blue >> 3));
-
- *Dst++ = DstPixel16.us;
- }
- else
- {
- SrcPixel32.ul = DIB_GetSourceIndex(Source, SrcX++, SrcY);
-
- SrcPixel32.col.red = SrcPixel32.col.red * BlendFunc.SourceConstantAlpha / 255;
- SrcPixel32.col.green = SrcPixel32.col.green * BlendFunc.SourceConstantAlpha / 255;
- SrcPixel32.col.blue = SrcPixel32.col.blue * BlendFunc.SourceConstantAlpha / 255;
- SrcPixel32.col.alpha = (SrcBpp == 32) ?
- (SrcPixel32.col.alpha * BlendFunc.SourceConstantAlpha / 255) :
- BlendFunc.SourceConstantAlpha;
-
- Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
- SrcPixel32.col.alpha : BlendFunc.SourceConstantAlpha;
-
- DstPixel32.ul = XLATEOBJ_iXlate(&exloDst2Src.xlo, *Dst);
- SrcPixel32.col.red = Clamp8(DstPixel32.col.red * (255 - Alpha) / 255 + SrcPixel32.col.red);
- SrcPixel32.col.green = Clamp8(DstPixel32.col.green * (255 - Alpha) / 255 + SrcPixel32.col.green);
- SrcPixel32.col.blue = Clamp8(DstPixel32.col.blue * (255 - Alpha) / 255 + SrcPixel32.col.blue);
- *Dst++ = XLATEOBJ_iXlate(ColorTranslation, SrcPixel32.ul);
- }
- }
-
- Dst = (PUSHORT)((ULONG_PTR)Dst + DstDelta);
- SrcY++;
- }
-
- EXLATEOBJ_vCleanup(&exloDst2Src);
-
- return TRUE;
- }
-
/* EOF */
VOID
DIB_1BPP_HLine(SURFOBJ *SurfObj, LONG x1, LONG x2, LONG y, ULONG c)
{
- while(x1 < x2)
+ while(x1 < x2)
{
DIB_1BPP_PutPixel(SurfObj, x1, y, c);
x1++;
VOID
DIB_1BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
{
- while(y1 < y2)
+ while(y1 < y2)
{
DIB_1BPP_PutPixel(SurfObj, x, y1, c);
y1++;
return FALSE;
}
- BOOLEAN
- DIB_1BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
- RECTL* SourceRect, CLIPOBJ* ClipRegion,
- XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
- {
- UNIMPLEMENTED;
- return FALSE;
- }
-
/* EOF */
LONG lDelta = SurfObj->lDelta;
c &= 0xFFFFFF;
- while(y1++ < y2)
+ while(y1++ < y2)
{
*(PUSHORT)(addr) = c & 0xFFFF;
*(addr + 2) = c >> 16;
{
INT Rows, Cols, SrcX, SrcY;
register PUCHAR Dst;
- ULONG DstDelta;
BLENDFUNCTION BlendFunc;
register NICEPIXEL32 DstPixel, SrcPixel;
UCHAR Alpha, SrcBpp;
SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
- ASSERT(DestRect->bottom - DestRect->top == SourceRect->bottom - SourceRect->top &&
- DestRect->right - DestRect->left == SourceRect->right - SourceRect->left);
-
BlendFunc = BlendObj->BlendFunction;
if (BlendFunc.BlendOp != AC_SRC_OVER)
{
Dst = (PUCHAR)((ULONG_PTR)Dest->pvScan0 + (DestRect->top * Dest->lDelta) +
(DestRect->left * 3));
- DstDelta = Dest->lDelta - ((DestRect->right - DestRect->left) * 3);
SrcBpp = BitsPerFormat(Source->iBitmapFormat);
- Rows = DestRect->bottom - DestRect->top;
+ Rows = 0;
SrcY = SourceRect->top;
- while (--Rows >= 0)
- {
- Cols = DestRect->right - DestRect->left;
- SrcX = SourceRect->left;
- while (--Cols >= 0)
+ while (++Rows <= DestRect->bottom - DestRect->top)
+ {
+ Cols = 0;
+ SrcX = SourceRect->left;
+ while (++Cols <= DestRect->right - DestRect->left)
+ {
+ SrcPixel.ul = DIB_GetSource(Source, SrcX, SrcY, ColorTranslation);
+ SrcPixel.col.red = (SrcPixel.col.red * BlendFunc.SourceConstantAlpha) / 255;
+ SrcPixel.col.green = (SrcPixel.col.green * BlendFunc.SourceConstantAlpha) / 255;
+ SrcPixel.col.blue = (SrcPixel.col.blue * BlendFunc.SourceConstantAlpha) / 255;
+ if (!(BlendFunc.AlphaFormat & AC_SRC_ALPHA))
{
- SrcPixel.ul = DIB_GetSource(Source, SrcX++, SrcY, ColorTranslation);
- SrcPixel.col.red = SrcPixel.col.red * BlendFunc.SourceConstantAlpha / 255;
- SrcPixel.col.green = SrcPixel.col.green * BlendFunc.SourceConstantAlpha / 255;
- SrcPixel.col.blue = SrcPixel.col.blue * BlendFunc.SourceConstantAlpha / 255;
- SrcPixel.col.alpha = (SrcBpp == 32) ? (SrcPixel.col.alpha * BlendFunc.SourceConstantAlpha / 255) : BlendFunc.SourceConstantAlpha;
-
- Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
- SrcPixel.col.alpha : BlendFunc.SourceConstantAlpha;
-
- /* copy only 24bits of dst */
- DstPixel.ul = *(PUSHORT)(Dst) + (*(Dst+2) << 16);
- DstPixel.col.red = Clamp8(DstPixel.col.red * (255 - Alpha) / 255 + SrcPixel.col.red);
- DstPixel.col.green = Clamp8(DstPixel.col.green * (255 - Alpha) / 255 + SrcPixel.col.green);
- DstPixel.col.blue = Clamp8(DstPixel.col.blue * (255 - Alpha) / 255 + SrcPixel.col.blue);
- /* copy back 24bits of result */
- *(PUSHORT)(Dst) = (USHORT)(DstPixel.ul & 0xFFFF);
- *(Dst + 2) = (UCHAR)((DstPixel.ul >> 16) & 0xFF);
- Dst = (PUCHAR)((ULONG_PTR)Dst + 3);
+ Alpha = BlendFunc.SourceConstantAlpha ;
}
- Dst = (PUCHAR)((ULONG_PTR)Dst + DstDelta);
- SrcY++;
- }
+ else
+ {
+ Alpha = (SrcPixel.col.alpha * BlendFunc.SourceConstantAlpha) / 255;
+ }
+
+ DstPixel.col.red = Clamp8((*Dst * (255 - Alpha)) / 255 + SrcPixel.col.red) ;
+ DstPixel.col.green = Clamp8((*(Dst+1) * (255 - Alpha) / 255 + SrcPixel.col.green)) ;
+ DstPixel.col.blue = Clamp8((*(Dst+2) * (255 - Alpha)) / 255 + SrcPixel.col.blue) ;
+ *Dst++ = DstPixel.col.red;
+ *Dst++ = DstPixel.col.green;
+ *Dst++ = DstPixel.col.blue;
+ SrcX = SourceRect->left + (Cols*(SourceRect->right - SourceRect->left))/(DestRect->right - DestRect->left);
+ }
+ Dst = (PUCHAR)((ULONG_PTR)Dest->pvScan0 + ((DestRect->top + Rows) * Dest->lDelta) +
+ (DestRect->left*3));
+ SrcY = SourceRect->top + (Rows*(SourceRect->bottom - SourceRect->top))/(DestRect->bottom - DestRect->top);
+ }
return TRUE;
}
PBYTE SourceBits_4BPP, SourceLine_4BPP;
PDWORD Source32, Dest32;
- DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
- + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta)
+ DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
+ + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta)
+ 4 * BltInfo->DestRect.left;
switch (BltInfo->SourceSurface->iBitmapFormat)
break;
case BMF_4BPP:
- SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0
- + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
+ SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0
+ + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
+ (BltInfo->SourcePoint.x >> 1);
for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
break;
case BMF_24BPP:
- SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0
- + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
+ SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0
+ + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
+ 3 * BltInfo->SourcePoint.x;
DestLine = DestBits;
break;
case BMF_32BPP:
- if (NULL == BltInfo->XlateSourceToDest ||
+ if (NULL == BltInfo->XlateSourceToDest ||
0 != (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL))
{
if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
}
else
{
- SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
- + ((BltInfo->SourcePoint.y
- + BltInfo->DestRect.bottom
- - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta)
+ SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
+ + ((BltInfo->SourcePoint.y
+ + BltInfo->DestRect.bottom
+ - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta)
+ 4 * BltInfo->SourcePoint.x;
DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + 4 * BltInfo->DestRect.left;
for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
{
INT Rows, Cols, SrcX, SrcY;
register PULONG Dst;
- ULONG DstDelta;
BLENDFUNCTION BlendFunc;
register NICEPIXEL32 DstPixel, SrcPixel;
UCHAR Alpha, SrcBpp;
SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
- ASSERT(DestRect->bottom - DestRect->top == SourceRect->bottom - SourceRect->top &&
- DestRect->right - DestRect->left == SourceRect->right - SourceRect->left);
-
BlendFunc = BlendObj->BlendFunction;
if (BlendFunc.BlendOp != AC_SRC_OVER)
{
Dst = (PULONG)((ULONG_PTR)Dest->pvScan0 + (DestRect->top * Dest->lDelta) +
(DestRect->left << 2));
- DstDelta = Dest->lDelta - ((DestRect->right - DestRect->left) << 2);
SrcBpp = BitsPerFormat(Source->iBitmapFormat);
- Rows = DestRect->bottom - DestRect->top;
- SrcY = SourceRect->top;
- while (--Rows >= 0)
+ Rows = 0;
+ SrcY = SourceRect->top;
+ while (++Rows <= DestRect->bottom - DestRect->top)
{
- Cols = DestRect->right - DestRect->left;
+ Cols = 0;
SrcX = SourceRect->left;
- while (--Cols >= 0)
+ while (++Cols <= DestRect->right - DestRect->left)
{
- SrcPixel.ul = DIB_GetSource(Source, SrcX++, SrcY, ColorTranslation);
- SrcPixel.col.red = SrcPixel.col.red * BlendFunc.SourceConstantAlpha / 255;
- SrcPixel.col.green = SrcPixel.col.green * BlendFunc.SourceConstantAlpha / 255;
- SrcPixel.col.blue = SrcPixel.col.blue * BlendFunc.SourceConstantAlpha / 255;
- SrcPixel.col.alpha = (SrcBpp == 32) ? (SrcPixel.col.alpha * BlendFunc.SourceConstantAlpha / 255) : BlendFunc.SourceConstantAlpha;
+ SrcPixel.ul = DIB_GetSource(Source, SrcX, SrcY, ColorTranslation);
+ SrcPixel.col.red = (SrcPixel.col.red * BlendFunc.SourceConstantAlpha) / 255;
+ SrcPixel.col.green = (SrcPixel.col.green * BlendFunc.SourceConstantAlpha) / 255;
+ SrcPixel.col.blue = (SrcPixel.col.blue * BlendFunc.SourceConstantAlpha) / 255;
+ SrcPixel.col.alpha = (32 == SrcBpp) ?
+ (SrcPixel.col.alpha * BlendFunc.SourceConstantAlpha) / 255 :
+ BlendFunc.SourceConstantAlpha ;
Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
- SrcPixel.col.alpha : BlendFunc.SourceConstantAlpha;
+ SrcPixel.col.alpha : BlendFunc.SourceConstantAlpha ;
DstPixel.ul = *Dst;
- DstPixel.col.red = Clamp8(DstPixel.col.red * (255 - Alpha) / 255 + SrcPixel.col.red);
- DstPixel.col.green = Clamp8(DstPixel.col.green * (255 - Alpha) / 255 + SrcPixel.col.green);
- DstPixel.col.blue = Clamp8(DstPixel.col.blue * (255 - Alpha) / 255 + SrcPixel.col.blue);
- DstPixel.col.alpha = Clamp8(DstPixel.col.alpha * (255 - Alpha) / 255 + SrcPixel.col.alpha);
+ DstPixel.col.red = Clamp8((DstPixel.col.red * (255 - Alpha)) / 255 + SrcPixel.col.red) ;
+ DstPixel.col.green = Clamp8((DstPixel.col.green * (255 - Alpha)) / 255 + SrcPixel.col.green) ;
+ DstPixel.col.blue = Clamp8((DstPixel.col.blue * (255 - Alpha)) / 255 + SrcPixel.col.blue) ;
+ DstPixel.col.alpha = Clamp8((DstPixel.col.alpha * (255 - Alpha)) / 255 + SrcPixel.col.alpha) ;
*Dst++ = DstPixel.ul;
+ SrcX = SourceRect->left + (Cols*(SourceRect->right - SourceRect->left))/(DestRect->right - DestRect->left);
}
- Dst = (PULONG)((ULONG_PTR)Dst + DstDelta);
- SrcY++;
+ Dst = (PULONG)((ULONG_PTR)Dest->pvScan0 + ((DestRect->top + Rows) * Dest->lDelta) +
+ (DestRect->left << 2));
+ SrcY = SourceRect->top + (Rows*(SourceRect->bottom - SourceRect->top))/(DestRect->bottom - DestRect->top);
}
return TRUE;
PBYTE addr = (PBYTE)SurfObj->pvScan0 + (x1>>1) + y * SurfObj->lDelta;
LONG cx = x1;
- while(cx < x2)
+ while(cx < x2)
{
*addr = (*addr & notmask[x1&1]) | (c << ((1-(x1&1))<<2));
if((++x1 & 1) == 0)
int lDelta = SurfObj->lDelta;
addr += (x>>1) + y1 * lDelta;
- while(y1++ < y2)
+ while(y1++ < y2)
{
*addr = (*addr & notmask[x&1]) | (c << ((1-(x&1))<<2));
addr += lDelta;
if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
{
DIB_4BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 0));
- }
- else
+ }
+ else
{
DIB_4BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
}
return FALSE;
}
- BOOLEAN
- DIB_4BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
- RECTL* SourceRect, CLIPOBJ* ClipRegion,
- XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
- {
- UNIMPLEMENTED;
- return FALSE;
- }
-
/* EOF */
LONG lDelta = SurfObj->lDelta;
byteaddr = addr;
- while(y1++ < y2)
+ while(y1++ < y2)
{
*addr = c;
if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
{
DIB_8BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 0));
- }
- else
+ }
+ else
{
DIB_8BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
}
return TRUE;
}
- typedef union {
- ULONG ul;
- struct {
- UCHAR red;
- UCHAR green;
- UCHAR blue;
- UCHAR alpha;
- } col;
- } NICEPIXEL32;
-
- typedef union {
- USHORT us;
- struct {
- USHORT red:5,
- green:6,
- blue:5;
- } col;
- } NICEPIXEL16;
-
- static __inline UCHAR
- Clamp8(ULONG val)
- {
- return (val > 255) ? 255 : val;
- }
-
- BOOLEAN
- DIB_8BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
- RECTL* SourceRect, CLIPOBJ* ClipRegion,
- XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
- {
- INT Rows, Cols, SrcX, SrcY;
- register PUCHAR Dst;
- ULONG DstDelta;
- BLENDFUNCTION BlendFunc;
- register NICEPIXEL32 DstPixel32;
- register NICEPIXEL32 SrcPixel32;
- register NICEPIXEL16 SrcPixel16;
- UCHAR Alpha, SrcBpp;
- EXLATEOBJ exloDst2Src;
- EXLATEOBJ* pexlo;
-
- DPRINT("DIB_8BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
- SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
- DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
-
- ASSERT(DestRect->bottom - DestRect->top == SourceRect->bottom - SourceRect->top &&
- DestRect->right - DestRect->left == SourceRect->right - SourceRect->left);
-
- BlendFunc = BlendObj->BlendFunction;
- if (BlendFunc.BlendOp != AC_SRC_OVER)
- {
- DPRINT1("BlendOp != AC_SRC_OVER\n");
- return FALSE;
- }
- if (BlendFunc.BlendFlags != 0)
- {
- DPRINT1("BlendFlags != 0\n");
- return FALSE;
- }
- if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0)
- {
- DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat);
- return FALSE;
- }
- if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 &&
- BitsPerFormat(Source->iBitmapFormat) != 32)
- {
- DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n");
- return FALSE;
- }
- if (!ColorTranslation)
- {
- DPRINT1("ColorTranslation must not be NULL!\n");
- return FALSE;
- }
-
- pexlo = CONTAINING_RECORD(ColorTranslation, EXLATEOBJ, xlo);
- EXLATEOBJ_vInitialize(&exloDst2Src, pexlo->ppalDst, pexlo->ppalSrc, 0, 0, 0);
-
- Dst = (PUCHAR)((ULONG_PTR)Dest->pvScan0 + (DestRect->top * Dest->lDelta) +
- DestRect->left);
- DstDelta = Dest->lDelta - (DestRect->right - DestRect->left);
- SrcBpp = BitsPerFormat(Source->iBitmapFormat);
-
- Rows = DestRect->bottom - DestRect->top;
- SrcY = SourceRect->top;
- while (--Rows >= 0)
- {
- Cols = DestRect->right - DestRect->left;
- SrcX = SourceRect->left;
- while (--Cols >= 0)
- {
- if (SrcBpp <= 16)
- {
- SrcPixel16.us = DIB_GetSource(Source, SrcX++, SrcY, ColorTranslation);
- SrcPixel32.col.red = (SrcPixel16.col.red << 3) | (SrcPixel16.col.red >> 2);
- SrcPixel32.col.green = (SrcPixel16.col.green << 2) | (SrcPixel16.col.green >> 4);
- SrcPixel32.col.blue = (SrcPixel16.col.blue << 3) | (SrcPixel16.col.blue >> 2);
- }
- else
- {
- SrcPixel32.ul = DIB_GetSourceIndex(Source, SrcX++, SrcY);
- }
- SrcPixel32.col.red = SrcPixel32.col.red * BlendFunc.SourceConstantAlpha / 255;
- SrcPixel32.col.green = SrcPixel32.col.green * BlendFunc.SourceConstantAlpha / 255;
- SrcPixel32.col.blue = SrcPixel32.col.blue * BlendFunc.SourceConstantAlpha / 255;
- SrcPixel32.col.alpha = (SrcBpp == 32) ? (SrcPixel32.col.alpha * BlendFunc.SourceConstantAlpha / 255) : BlendFunc.SourceConstantAlpha;
-
- Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
- SrcPixel32.col.alpha : BlendFunc.SourceConstantAlpha;
-
- DstPixel32.ul = XLATEOBJ_iXlate(&exloDst2Src.xlo, *Dst);
- SrcPixel32.col.red = Clamp8(DstPixel32.col.red * (255 - Alpha) / 255 + SrcPixel32.col.red);
- SrcPixel32.col.green = Clamp8(DstPixel32.col.green * (255 - Alpha) / 255 + SrcPixel32.col.green);
- SrcPixel32.col.blue = Clamp8(DstPixel32.col.blue * (255 - Alpha) / 255 + SrcPixel32.col.blue);
- *Dst++ = XLATEOBJ_iXlate(ColorTranslation, SrcPixel32.ul);
- }
- Dst = (PUCHAR)((ULONG_PTR)Dst + DstDelta);
- SrcY++;
- }
-
- EXLATEOBJ_vCleanup(&exloDst2Src);
-
- return TRUE;
- }
-
/* EOF */
- /*
+ /*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: GDI alpha blending functions
IN PRECTL SourceRect,
IN BLENDOBJ *BlendObj)
{
- RECTL SourceStretchedRect;
- SIZEL SourceStretchedSize;
- HBITMAP SourceStretchedBitmap = 0;
- SURFOBJ* SourceStretchedObj = NULL;
RECTL InputRect;
RECTL OutputRect;
RECTL ClipRect;
INTENG_ENTER_LEAVE EnterLeaveDest;
SURFOBJ* InputObj;
SURFOBJ* OutputObj;
- LONG Width;
LONG ClippingType;
RECT_ENUM RectEnum;
BOOL EnumMore;
InputRect = *SourceRect;
if ( (InputRect.top < 0) || (InputRect.bottom < 0) ||
(InputRect.left < 0) || (InputRect.right < 0) ||
- InputRect.right > psoSource->sizlBitmap.cx ||
+ InputRect.right > psoSource->sizlBitmap.cx ||
InputRect.bottom > psoSource->sizlBitmap.cy )
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return TRUE;
}
- /* Stretch source if needed */
- if (OutputRect.right - OutputRect.left != InputRect.right - InputRect.left ||
- OutputRect.bottom - OutputRect.top != InputRect.bottom - InputRect.top)
- {
- SourceStretchedSize.cx = OutputRect.right - OutputRect.left;
- SourceStretchedSize.cy = OutputRect.bottom - OutputRect.top;
- Width = DIB_GetDIBWidthBytes(SourceStretchedSize.cx, BitsPerFormat(psoSource->iBitmapFormat));
- /* FIXME: Maybe it is a good idea to use EngCreateDeviceBitmap and IntEngStretchBlt
- if possible to get a HW accelerated stretch. */
- SourceStretchedBitmap = EngCreateBitmap(SourceStretchedSize, Width, psoSource->iBitmapFormat,
- BMF_TOPDOWN | BMF_NOZEROINIT, NULL);
- if (SourceStretchedBitmap == 0)
- {
- DPRINT1("EngCreateBitmap failed!\n");
- return FALSE;
- }
- SourceStretchedObj = EngLockSurface((HSURF)SourceStretchedBitmap);
- if (SourceStretchedObj == NULL)
- {
- DPRINT1("EngLockSurface failed!\n");
- EngDeleteSurface((HSURF)SourceStretchedBitmap);
- return FALSE;
- }
-
- SourceStretchedRect.left = 0;
- SourceStretchedRect.right = SourceStretchedSize.cx;
- SourceStretchedRect.top = 0;
- SourceStretchedRect.bottom = SourceStretchedSize.cy;
- /* FIXME: IntEngStretchBlt isn't used here atm because it results in a
- try to acquire an already acquired mutex (lock the already locked source surface) */
- /*if (!IntEngStretchBlt(SourceStretchedObj, psoSource, NULL, NULL,
- NULL, &SourceStretchedRect, SourceRect, NULL,
- NULL, NULL, COLORONCOLOR))*/
- if (!EngStretchBlt(SourceStretchedObj, psoSource, NULL, NULL, NULL,
- NULL, NULL, &SourceStretchedRect, &InputRect,
- NULL, COLORONCOLOR))
- {
- DPRINT1("EngStretchBlt failed!\n");
- EngFreeMem(SourceStretchedObj->pvBits);
- EngUnlockSurface(SourceStretchedObj);
- EngDeleteSurface((HSURF)SourceStretchedBitmap);
- return FALSE;
- }
- InputRect.top = SourceStretchedRect.top;
- InputRect.bottom = SourceStretchedRect.bottom;
- InputRect.left = SourceStretchedRect.left;
- InputRect.right = SourceStretchedRect.right;
- psoSource = SourceStretchedObj;
- }
-
/* Now call the DIB function */
if (!IntEngEnter(&EnterLeaveSource, psoSource, &InputRect, TRUE, &Translate, &InputObj))
{
- if (SourceStretchedObj != NULL)
- {
- EngFreeMem(SourceStretchedObj->pvBits);
- EngUnlockSurface(SourceStretchedObj);
- }
- if (SourceStretchedBitmap != 0)
- {
- EngDeleteSurface((HSURF)SourceStretchedBitmap);
- }
return FALSE;
}
InputRect.left += Translate.x;
if (!IntEngEnter(&EnterLeaveDest, psoDest, &OutputRect, FALSE, &Translate, &OutputObj))
{
- IntEngLeave(&EnterLeaveSource);
- if (SourceStretchedObj != NULL)
- {
- EngFreeMem(SourceStretchedObj->pvBits);
- EngUnlockSurface(SourceStretchedObj);
- }
- if (SourceStretchedBitmap != 0)
- {
- EngDeleteSurface((HSURF)SourceStretchedBitmap);
- }
return FALSE;
}
OutputRect.left += Translate.x;
IntEngLeave(&EnterLeaveDest);
IntEngLeave(&EnterLeaveSource);
- if (SourceStretchedObj != NULL)
- {
- EngFreeMem(SourceStretchedObj->pvBits);
- EngUnlockSurface(SourceStretchedObj);
- }
- if (SourceStretchedBitmap != 0)
- {
- EngDeleteSurface((HSURF)SourceStretchedBitmap);
- }
-
return Ret;
}
return TRUE;
}
- SURFACE_LockBitmapBits(psurfDest);
- MouseSafetyOnDrawStart(psoDest, DestRect->left, DestRect->top,
- DestRect->right, DestRect->bottom);
-
- if (psoSource != psoDest)
- SURFACE_LockBitmapBits(psurfSource);
- MouseSafetyOnDrawStart(psoSource, SourceRect->left, SourceRect->top,
- SourceRect->right, SourceRect->bottom);
-
/* Call the driver's DrvAlphaBlend if available */
- if (psurfDest->flHooks & HOOK_ALPHABLEND)
+ if (psurfDest->flags & HOOK_ALPHABLEND)
{
ret = GDIDEVFUNCS(psoDest).AlphaBlend(
psoDest, psoSource, ClipRegion, ColorTranslation,
DestRect, SourceRect, BlendObj);
}
- MouseSafetyOnDrawEnd(psoSource);
- if (psoSource != psoDest)
- SURFACE_UnlockBitmapBits(psurfSource);
- MouseSafetyOnDrawEnd(psoDest);
- SURFACE_UnlockBitmapBits(psurfDest);
-
return ret;
}
}
BOOL APIENTRY
- IntEngBitBltEx(
+ IntEngBitBlt(
SURFOBJ *psoTrg,
SURFOBJ *psoSrc,
SURFOBJ *psoMask,
POINTL *pptlMask,
BRUSHOBJ *pbo,
POINTL *pptlBrush,
- ROP4 rop4,
- BOOL bRemoveMouse)
+ ROP4 rop4)
{
SURFACE *psurfTrg;
SURFACE *psurfSrc = NULL;
psurfSrc = NULL;
}
- if (bRemoveMouse)
- {
- SURFACE_LockBitmapBits(psurfTrg);
-
- if (psoSrc)
- {
- if (psoSrc != psoTrg)
- {
- SURFACE_LockBitmapBits(psurfSrc);
- }
- MouseSafetyOnDrawStart(psoSrc, rclSrc.left, rclSrc.top,
- rclSrc.right, rclSrc.bottom);
- }
- MouseSafetyOnDrawStart(psoTrg, rclClipped.left, rclClipped.top,
- rclClipped.right, rclClipped.bottom);
- }
-
/* Is the target surface device managed? */
- if (psurfTrg->flHooks & HOOK_BITBLT)
+ if (psurfTrg->flags & HOOK_BITBLT)
{
/* Is the source a different device managed surface? */
- if (psoSrc && psoSrc->hdev != psoTrg->hdev && psurfSrc->flHooks & HOOK_BITBLT)
+ if (psoSrc && psoSrc->hdev != psoTrg->hdev && psurfSrc->flags & HOOK_BITBLT)
{
DPRINT1("Need to copy to standard bitmap format!\n");
ASSERT(FALSE);
}
/* Is the source surface device managed? */
- else if (psoSrc && psurfSrc->flHooks & HOOK_BITBLT)
+ else if (psoSrc && psurfSrc->flags & HOOK_BITBLT)
{
pfnBitBlt = GDIDEVFUNCS(psoSrc).BitBlt;
}
// FIXME: cleanup temp surface!
- if (bRemoveMouse)
- {
- MouseSafetyOnDrawEnd(psoTrg);
- if (psoSrc)
- {
- MouseSafetyOnDrawEnd(psoSrc);
- if (psoSrc != psoTrg)
- {
- SURFACE_UnlockBitmapBits(psurfSrc);
- }
- }
-
- SURFACE_UnlockBitmapBits(psurfTrg);
- }
-
return bResult;
}
ASSERT(psoDest);
psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);
- SURFACE_LockBitmapBits(psurfDest);
- MouseSafetyOnDrawStart(psoDest, OutputRect.left, OutputRect.top,
- OutputRect.right, OutputRect.bottom);
-
/* Dummy BitBlt to let driver know that it should flush its changes.
This should really be done using a call to DrvSynchronizeSurface,
but the VMware driver doesn't hook that call. */
- IntEngBitBltEx(psoDest, NULL, psoMask, ClipRegion, DestColorTranslation,
+ IntEngBitBlt(psoDest, NULL, psoMask, ClipRegion, DestColorTranslation,
DestRect, pptlMask, pptlMask, pbo, BrushOrigin,
- R4_NOOP, FALSE);
+ R4_NOOP);
ret = EngMaskBitBlt(psoDest, psoMask, ClipRegion, DestColorTranslation, SourceColorTranslation,
&OutputRect, &InputPoint, pbo, BrushOrigin);
/* Dummy BitBlt to let driver know that something has changed. */
- IntEngBitBltEx(psoDest, NULL, psoMask, ClipRegion, DestColorTranslation,
+ IntEngBitBlt(psoDest, NULL, psoMask, ClipRegion, DestColorTranslation,
DestRect, pptlMask, pptlMask, pbo, BrushOrigin,
- R4_NOOP, FALSE);
-
- MouseSafetyOnDrawEnd(psoDest);
- SURFACE_UnlockBitmapBits(psurfDest);
+ R4_NOOP);
return ret;
}
ASSERT(psoDest != NULL && psoSource != NULL && DestRect != NULL && SourcePoint != NULL);
psurfSource = CONTAINING_RECORD(psoSource, SURFACE, SurfObj);
- SURFACE_LockBitmapBits(psurfSource);
-
psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);
- if (psoDest != psoSource)
- {
- SURFACE_LockBitmapBits(psurfDest);
- }
// FIXME: Don't punt to the driver's DrvCopyBits immediately. Instead,
// mark the copy block function to be DrvCopyBits instead of the
if (psoDest->iType!=STYPE_BITMAP)
{
/* FIXME: Eng* functions shouldn't call Drv* functions. ? */
- if (psurfDest->flHooks & HOOK_COPYBITS)
+ if (psurfDest->flags & HOOK_COPYBITS)
{
ret = GDIDEVFUNCS(psoDest).CopyBits(
psoDest, psoSource, Clip, ColorTranslation, DestRect, SourcePoint);
if (psoSource->iType!=STYPE_BITMAP)
{
/* FIXME: Eng* functions shouldn't call Drv* functions. ? */
- if (psurfSource->flHooks & HOOK_COPYBITS)
+ if (psurfSource->flags & HOOK_COPYBITS)
{
ret = GDIDEVFUNCS(psoSource).CopyBits(
psoDest, psoSource, Clip, ColorTranslation, DestRect, SourcePoint);
}
cleanup:
- if (psoDest != psoSource)
- {
- SURFACE_UnlockBitmapBits(psurfDest);
- }
- SURFACE_UnlockBitmapBits(psurfSource);
-
return ret;
}
RECTL *prclDest,
POINTL *ptlSource)
{
- BOOL bResult;
-
- MouseSafetyOnDrawStart(psoSource, ptlSource->x, ptlSource->y,
- (ptlSource->x + abs(prclDest->right - prclDest->left)),
- (ptlSource->y + abs(prclDest->bottom - prclDest->top)));
-
- MouseSafetyOnDrawStart(psoDest, prclDest->left, prclDest->top, prclDest->right, prclDest->bottom);
-
- bResult = EngCopyBits(psoDest, psoSource, pco, pxlo, prclDest, ptlSource);
-
- MouseSafetyOnDrawEnd(psoDest);
- MouseSafetyOnDrawEnd(psoSource);
-
- return bResult;
+ return EngCopyBits(psoDest, psoSource, pco, pxlo, prclDest, ptlSource);
}
#define NDEBUG
#include <debug.h>
+ PGRAPHICS_DEVICE gpPrimaryGraphicsDevice;
+ PGRAPHICS_DEVICE gpVgaGraphicsDevice;
+
+ static PGRAPHICS_DEVICE gpGraphicsDeviceFirst = NULL;
+ static PGRAPHICS_DEVICE gpGraphicsDeviceLast = NULL;
+ static HSEMAPHORE ghsemGraphicsDeviceList;
+ static ULONG giDevNum = 1;
+
+ BOOL
+ NTAPI
+ InitDeviceImpl()
+ {
+ ghsemGraphicsDeviceList = EngCreateSemaphore();
+ if (!ghsemGraphicsDeviceList)
+ return FALSE;
+
+ return TRUE;
+ }
+
+
+ PGRAPHICS_DEVICE
+ NTAPI
+ EngpRegisterGraphicsDevice(
+ PUNICODE_STRING pustrDeviceName,
+ PUNICODE_STRING pustrDiplayDrivers,
+ PUNICODE_STRING pustrDescription,
+ PDEVMODEW pdmDefault)
+ {
+ PGRAPHICS_DEVICE pGraphicsDevice;
+ PDEVICE_OBJECT pDeviceObject;
+ PFILE_OBJECT pFileObject;
+ NTSTATUS Status;
+ PWSTR pwsz;
+ ULONG i, cj, cModes = 0;
+ BOOL bEnable = TRUE;
+ PDEVMODEINFO pdminfo;
+ PDEVMODEW pdm, pdmEnd;
+ PLDEVOBJ pldev;
+
+ DPRINT1("EngpRegisterGraphicsDevice(%S)\n", pustrDeviceName->Buffer);
+
+ /* Allocate a GRAPHICS_DEVICE structure */
+ pGraphicsDevice = ExAllocatePoolWithTag(PagedPool,
+ sizeof(GRAPHICS_DEVICE),
+ GDITAG_GDEVICE);
+ if (!pGraphicsDevice)
+ {
+ DPRINT1("ExAllocatePoolWithTag failed\n");
+ return NULL;
+ }
+
+ /* Try to open the driver */
+ Status = IoGetDeviceObjectPointer(pustrDeviceName,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ &pFileObject,
+ &pDeviceObject);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Could not open driver, 0x%lx\n", Status);
+ ExFreePoolWithTag(pGraphicsDevice, GDITAG_GDEVICE);
+ return NULL;
+ }
+
+ /* Enable the device */
+ EngFileWrite(pFileObject, &bEnable, sizeof(BOOL), &cj);
+
+ /* Copy the device and file object pointers */
+ pGraphicsDevice->DeviceObject = pDeviceObject;
+ pGraphicsDevice->FileObject = pFileObject;
+
+ /* Copy device name */
+ wcsncpy(pGraphicsDevice->szNtDeviceName,
+ pustrDeviceName->Buffer,
+ sizeof(pGraphicsDevice->szNtDeviceName) / sizeof(WCHAR));
+
+ /* Create a win device name (FIXME: virtual devices!) */
+ swprintf(pGraphicsDevice->szWinDeviceName, L"\\\\.\\VIDEO%d", (CHAR)giDevNum);
+
+ /* Allocate a buffer for the strings */
+ cj = pustrDiplayDrivers->Length + pustrDescription->Length + sizeof(WCHAR);
+ pwsz = ExAllocatePoolWithTag(PagedPool, cj, GDITAG_DRVSUP);
+ if (!pwsz)
+ {
+ DPRINT1("Could not allocate string buffer\n");
+ ASSERT(FALSE); // FIXME
+ }
+
+ /* Copy display driver names */
+ pGraphicsDevice->pDiplayDrivers = pwsz;
+ RtlCopyMemory(pGraphicsDevice->pDiplayDrivers,
+ pustrDiplayDrivers->Buffer,
+ pustrDiplayDrivers->Length);
+
+ /* Copy description */
+ pGraphicsDevice->pwszDescription = pwsz + pustrDiplayDrivers->Length / sizeof(WCHAR);
+ RtlCopyMemory(pGraphicsDevice->pwszDescription,
+ pustrDescription->Buffer,
+ pustrDescription->Length + sizeof(WCHAR));
+
+ /* Initialize the pdevmodeInfo list and default index */
+ pGraphicsDevice->pdevmodeInfo = NULL;
+ pGraphicsDevice->iDefaultMode = 0;
+ pGraphicsDevice->iCurrentMode = 0;
+
+ // FIXME: initialize state flags
+ pGraphicsDevice->StateFlags = 0;
+
+ /* Loop through the driver names
+ * This is a REG_MULTI_SZ string */
+ for (; *pwsz; pwsz += wcslen(pwsz) + 1)
+ {
+ DPRINT1("trying driver: %ls\n", pwsz);
+ /* Try to load the display driver */
+ pldev = EngLoadImageEx(pwsz, LDEV_DEVICE_DISPLAY);
+ if (!pldev)
+ {
+ DPRINT1("Could not load driver: '%ls'\n", pwsz);
+ continue;
+ }
+
+ /* Get the mode list from the driver */
+ pdminfo = LDEVOBJ_pdmiGetModes(pldev, pDeviceObject);
+ if (!pdminfo)
+ {
+ DPRINT1("Could not get mode list for '%ls'\n", pwsz);
+ continue;
+ }
+
+ /* Attach the mode info to the device */
+ pdminfo->pdmiNext = pGraphicsDevice->pdevmodeInfo;
+ pGraphicsDevice->pdevmodeInfo = pdminfo;
+
+ /* Count DEVMODEs */
+ pdmEnd = (DEVMODEW*)((PCHAR)pdminfo->adevmode + pdminfo->cbdevmode);
+ for (pdm = pdminfo->adevmode;
+ pdm + 1 <= pdmEnd;
+ pdm = (DEVMODEW*)((PCHAR)pdm + pdm->dmSize + pdm->dmDriverExtra))
+ {
+ cModes++;
+ }
+
+ // FIXME: release the driver again until it's used?
+ }
+
+ if (!pGraphicsDevice->pdevmodeInfo || cModes == 0)
+ {
+ DPRINT1("No devmodes\n");
+ ExFreePool(pGraphicsDevice);
+ return NULL;
+ }
+
+ /* Allocate an index buffer */
+ pGraphicsDevice->cDevModes = cModes;
+ pGraphicsDevice->pDevModeList = ExAllocatePoolWithTag(PagedPool,
+ cModes * sizeof(DEVMODEENTRY),
+ GDITAG_GDEVICE);
+ if (!pGraphicsDevice->pDevModeList)
+ {
+ DPRINT1("No devmode list\n");
+ ExFreePool(pGraphicsDevice);
+ return NULL;
+ }
+
+ /* Loop through all DEVMODEINFOs */
+ for (pdminfo = pGraphicsDevice->pdevmodeInfo, i = 0;
+ pdminfo;
+ pdminfo = pdminfo->pdmiNext)
+ {
+ /* Calculate End of the DEVMODEs */
+ pdmEnd = (DEVMODEW*)((PCHAR)pdminfo->adevmode + pdminfo->cbdevmode);
+
+ /* Loop through the DEVMODEs */
+ for (pdm = pdminfo->adevmode;
+ pdm + 1 <= pdmEnd;
+ pdm = (PDEVMODEW)((PCHAR)pdm + pdm->dmSize + pdm->dmDriverExtra))
+ {
+ /* Compare with the default entry */
+ if (pdm->dmBitsPerPel == pdmDefault->dmBitsPerPel &&
+ pdm->dmPelsWidth == pdmDefault->dmPelsWidth &&
+ pdm->dmPelsHeight == pdmDefault->dmPelsHeight &&
+ pdm->dmDisplayFrequency == pdmDefault->dmDisplayFrequency)
+ {
+ pGraphicsDevice->iDefaultMode = i;
+ pGraphicsDevice->iCurrentMode = i;
+ DPRINT1("Found default entry: %ld '%ls'\n", i, pdm->dmDeviceName);
+ }
+
+ /* Initialize the entry */
+ pGraphicsDevice->pDevModeList[i].dwFlags = 0;
+ pGraphicsDevice->pDevModeList[i].pdm = pdm;
+ i++;
+ }
+ }
+
+ /* Lock loader */
+ EngAcquireSemaphore(ghsemGraphicsDeviceList);
+
+ /* Insert the device into the global list */
+ pGraphicsDevice->pNextGraphicsDevice = gpGraphicsDeviceLast;
+ gpGraphicsDeviceLast = pGraphicsDevice;
+ if (!gpGraphicsDeviceFirst)
+ gpGraphicsDeviceFirst = pGraphicsDevice;
+
+ /* Increment device number */
+ giDevNum++;
+
+ /* Unlock loader */
+ EngReleaseSemaphore(ghsemGraphicsDeviceList);
+ DPRINT1("Prepared %ld modes for %ls\n", cModes, pGraphicsDevice->pwszDescription);
+
+ return pGraphicsDevice;
+ }
+
+
+ PGRAPHICS_DEVICE
+ NTAPI
+ EngpFindGraphicsDevice(
+ PUNICODE_STRING pustrDevice,
+ ULONG iDevNum,
+ DWORD dwFlags)
+ {
+ UNICODE_STRING ustrCurrent;
+ PGRAPHICS_DEVICE pGraphicsDevice;
+ ULONG i;
+
+ /* Lock list */
+ EngAcquireSemaphore(ghsemGraphicsDeviceList);
+
+ if (pustrDevice)
+ {
+ /* Loop through the list of devices */
+ for (pGraphicsDevice = gpGraphicsDeviceFirst;
+ pGraphicsDevice;
+ pGraphicsDevice = pGraphicsDevice->pNextGraphicsDevice)
+ {
+ /* Compare the device name */
+ RtlInitUnicodeString(&ustrCurrent, pGraphicsDevice->szWinDeviceName);
+ if (RtlEqualUnicodeString(&ustrCurrent, pustrDevice, FALSE))
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* Loop through the list of devices */
+ for (pGraphicsDevice = gpGraphicsDeviceFirst, i = 0;
+ pGraphicsDevice && i < iDevNum;
+ pGraphicsDevice = pGraphicsDevice->pNextGraphicsDevice, i++);
+ }
+
+ /* Unlock list */
+ EngReleaseSemaphore(ghsemGraphicsDeviceList);
+
+ return pGraphicsDevice;
+ }
+
+
static
NTSTATUS
EngpFileIoRequest(
/* Initialize an event */
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
- /* Build IPR */
+ /* Build IRP */
liStartOffset.QuadPart = ullStartOffset;
pIrp = IoBuildSynchronousFsdRequest(ulMajorFunction,
pDeviceObject,
/* Initialize an event */
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
- /* Build IO control IPR */
+ /* Build IO control IRP */
pIrp = IoBuildDeviceIoControlRequest(dwIoControlCode,
pDeviceObject,
lpInBuffer,
NTAPI
EBRUSHOBJ_vInit(EBRUSHOBJ *pebo, PBRUSH pbrush, PDC pdc)
{
- HPALETTE hpal = NULL;
-
ASSERT(pebo);
ASSERT(pbrush);
ASSERT(pdc);
pebo->crCurrentText = pdc->pdcattr->crForegroundClr;
pebo->psurfTrg = pdc->dclevel.pSurface;
- // ASSERT(pebo->psurfTrg); // FIXME: some dcs don't have a surface
+ ASSERT(pebo->psurfTrg);
+ ASSERT(pebo->psurfTrg->ppal);
- if (pebo->psurfTrg)
- hpal = pebo->psurfTrg->hDIBPalette;
- if (!hpal) hpal = pPrimarySurface->devinfo.hpalDefault;
- pebo->ppalSurf = PALETTE_ShareLockPalette(hpal);
- if (!pebo->ppalSurf)
- pebo->ppalSurf = &gpalRGB;
+ pebo->ppalSurf = pebo->psurfTrg->ppal;
+ GDIOBJ_IncrementShareCount(&pebo->ppalSurf->BaseObject);
if (pbrush->flAttrs & GDIBRUSH_IS_NULL)
{
pebo->ulRGBColor = crColor;
/* Initialize an XLATEOBJ RGB -> surface */
- EXLATEOBJ_vInitialize(&exlo, &gpalRGB, pebo->ppalSurf, 0, 0, 0);
+ EXLATEOBJ_vInitialize(&exlo,
+ &gpalRGB,
+ pebo->ppalSurf,
+ pebo->crCurrentBack,
+ 0,
+ 0);
/* Translate the brush color to the target format */
iSolidColor = XLATEOBJ_iXlate(&exlo.xlo, crColor);
pebo->BrushObject.pvRbrush = NULL;
}
- if (pebo->ppalSurf != &gpalRGB)
- PALETTE_ShareUnlockPalette(pebo->ppalSurf);
+ PALETTE_ShareUnlockPalette(pebo->ppalSurf);
}
VOID
ULONG lWidth;
/* Calculate width in bytes of the realized brush */
- lWidth = DIB_GetDIBWidthBytes(psoPattern->sizlBitmap.cx,
+ lWidth = WIDTH_BYTES_ALIGN32(psoPattern->sizlBitmap.cx,
BitsPerFormat(psoDst->iBitmapFormat));
/* Allocate a bitmap */
PPDEVOBJ ppdev = NULL;
EXLATEOBJ exlo;
- // FIXME: all EBRUSHOBJs need a surface, see EBRUSHOBJ_vInit
- if (!pebo->psurfTrg)
- {
- DPRINT1("Pattern brush has no target surface!\n");
- return FALSE;
- }
+ /* All EBRUSHOBJs have a surface, see EBRUSHOBJ_vInit */
+ ASSERT(pebo->psurfTrg);
ppdev = (PPDEVOBJ)pebo->psurfTrg->SurfObj.hdev;
psurfPattern = SURFACE_ShareLockSurface(pebo->pbrush->hbmPattern);
ASSERT(psurfPattern);
+ ASSERT(psurfPattern->ppal);
/* FIXME: implement mask */
psurfMask = NULL;
/* Initialize XLATEOBJ for the brush */
- EXLATEOBJ_vInitBrushXlate(&exlo,
- pebo->pbrush,
- pebo->psurfTrg,
- pebo->crCurrentText,
- pebo->crCurrentBack);
+ EXLATEOBJ_vInitialize(&exlo,
+ psurfPattern->ppal,
+ pebo->psurfTrg->ppal,
+ 0,
+ pebo->crCurrentBack,
+ pebo->crCurrentText);
/* Create the realization */
bResult = pfnRealzizeBrush(&pebo->BrushObject,
{
/* Driver needs to support DrvCopyBits, else we can't do anything */
SURFACE *psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);
- if (!(psurfDest->flHooks & HOOK_COPYBITS))
+ if (!(psurfDest->flags & HOOK_COPYBITS))
{
return FALSE;
}
/* Allocate a temporary bitmap */
BitmapSize.cx = DestRect->right - DestRect->left;
BitmapSize.cy = DestRect->bottom - DestRect->top;
- Width = DIB_GetDIBWidthBytes(BitmapSize.cx, BitsPerFormat(psoDest->iBitmapFormat));
+ Width = WIDTH_BYTES_ALIGN32(BitmapSize.cx, BitsPerFormat(psoDest->iBitmapFormat));
EnterLeave->OutputBitmap = EngCreateBitmap(BitmapSize, Width,
psoDest->iBitmapFormat,
BMF_TOPDOWN | BMF_NOZEROINIT, NULL);
&ClippedDestRect, &SrcPoint))
{
EngDeleteClip(EnterLeave->TrivialClipObj);
- EngFreeMem((*ppsoOutput)->pvBits);
EngUnlockSurface(*ppsoOutput);
EngDeleteSurface((HSURF)EnterLeave->OutputBitmap);
return FALSE;
if (NULL != *ppsoOutput)
{
SURFACE* psurfOutput = CONTAINING_RECORD(*ppsoOutput, SURFACE, SurfObj);
- if (0 != (psurfOutput->flHooks & HOOK_SYNCHRONIZE))
+ if (0 != (psurfOutput->flags & HOOK_SYNCHRONIZE))
{
if (NULL != GDIDEVFUNCS(*ppsoOutput).SynchronizeSurface)
{
Result = TRUE;
}
}
- EngFreeMem(EnterLeave->OutputObj->pvBits);
EngUnlockSurface(EnterLeave->OutputObj);
EngDeleteSurface((HSURF)EnterLeave->OutputBitmap);
EngDeleteClip(EnterLeave->TrivialClipObj);
psurf = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);
ASSERT(psurf);
- SURFACE_LockBitmapBits(psurf);
- MouseSafetyOnDrawStart(
- psoDest,
- pco->rclBounds.left,
- pco->rclBounds.top,
- pco->rclBounds.right,
- pco->rclBounds.bottom);
- if(psurf->flHooks & HOOK_GRADIENTFILL)
+ if(psurf->flags & HOOK_GRADIENTFILL)
{
Ret = GDIDEVFUNCS(psoDest).GradientFill(
psoDest, pco, pxlo, pVertex, nVertex, pMesh, nMesh,
Ret = EngGradientFill(psoDest, pco, pxlo, pVertex, nVertex, pMesh, nMesh, prclExtents,
pptlDitherOrg, ulMode);
}
- MouseSafetyOnDrawEnd(psoDest);
- SURFACE_UnlockBitmapBits(psurf);
return Ret;
}
--- /dev/null
+ /*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * PURPOSE: Support for logical devices
+ * FILE: subsystems/win32/win32k/eng/ldevobj.c
+ * PROGRAMER: Timo Kreuzer (timo.kreuzer@reactos.org)
+ */
+
+ #include <win32k.h>
+
+ #include <intrin.h>
+
+ #define NDEBUG
+ #include <debug.h>
+
+ #ifndef RVA_TO_ADDR
+ #define RVA_TO_ADDR(Base,Rva) ((PVOID)(((ULONG_PTR)(Base)) + (Rva)))
+ #endif
+
+ /** Globals *******************************************************************/
+
+ HSEMAPHORE ghsemLDEVList;
+ LDEVOBJ *gpldevHead = NULL;
+ LDEVOBJ *gpldevWin32k = NULL;
+
+
+ /** Private functions *********************************************************/
+
+ BOOL
+ NTAPI
+ InitLDEVImpl()
+ {
+ /* Initialize the loader lock */
+ ghsemLDEVList = EngCreateSemaphore();
+ if (!ghsemLDEVList)
+ {
+ return FALSE;
+ }
+
+ /* Allocate a LDEVOBJ for win32k */
+ gpldevWin32k = ExAllocatePoolWithTag(PagedPool,
+ sizeof(LDEVOBJ) +
+ sizeof(SYSTEM_GDI_DRIVER_INFORMATION),
+ GDITAG_LDEV);
+ if (!gpldevWin32k)
+ {
+ return FALSE;
+ }
+
+ /* Initialize the LDEVOBJ for win32k */
+ gpldevWin32k->pldevNext = NULL;
+ gpldevWin32k->pldevPrev = NULL;
+ gpldevWin32k->ldevtype = LDEV_DEVICE_DISPLAY;
+ gpldevWin32k->cRefs = 1;
+ gpldevWin32k->ulDriverVersion = GDI_ENGINE_VERSION;
+ gpldevWin32k->pGdiDriverInfo = (PVOID)(gpldevWin32k + 1);
+ RtlInitUnicodeString(&gpldevWin32k->pGdiDriverInfo->DriverName,
+ L"\\SystemRoot\\System32\\win32k.sys");
+ gpldevWin32k->pGdiDriverInfo->ImageAddress = &__ImageBase;
+ gpldevWin32k->pGdiDriverInfo->SectionPointer = NULL;
+ gpldevWin32k->pGdiDriverInfo->EntryPoint = (PVOID)DriverEntry;
+ gpldevWin32k->pGdiDriverInfo->ExportSectionPointer = NULL;
+ gpldevWin32k->pGdiDriverInfo->ImageLength = 0; // FIXME;
+
+ return TRUE;
+ }
+
+ PLDEVOBJ
+ NTAPI
+ LDEVOBJ_AllocLDEV(LDEVTYPE ldevtype)
+ {
+ PLDEVOBJ pldev;
+
+ /* Allocate the structure from paged pool */
+ pldev = ExAllocatePoolWithTag(PagedPool, sizeof(LDEVOBJ), GDITAG_LDEV);
+ if (!pldev)
+ {
+ DPRINT1("Failed to allocate LDEVOBJ.\n");
+ return NULL;
+ }
+
+ /* Zero out the structure */
+ RtlZeroMemory(pldev, sizeof(LDEVOBJ));
+
+ /* Set the ldevtype */
+ pldev->ldevtype = ldevtype;
+
+ return pldev;
+ }
+
+ VOID
+ NTAPI
+ LDEVOBJ_vFreeLDEV(PLDEVOBJ pldev)
+ {
+ /* Make sure we don't have a driver loaded */
+ ASSERT(pldev && pldev->pGdiDriverInfo == NULL);
+
+ /* Free the memory */
+ ExFreePoolWithTag(pldev, TAG_LDEV);
+ }
+
+ PDEVMODEINFO
+ NTAPI
+ LDEVOBJ_pdmiGetModes(
+ PLDEVOBJ pldev,
+ HANDLE hDriver)
+ {
+ ULONG cbSize, cbFull;
+ PDEVMODEINFO pdminfo;
+
+ DPRINT("LDEVOBJ_pdmiGetModes(%p, %p)\n", pldev, hDriver);
+
+ /* Call the driver to get the required size */
+ cbSize = pldev->pfn.GetModes(hDriver, 0, NULL);
+ if (!cbSize)
+ {
+ DPRINT1("DrvGetModes returned 0\n");
+ return NULL;
+ }
+
+ /* Add space for the header */
+ cbFull = cbSize + FIELD_OFFSET(DEVMODEINFO, adevmode);
+
+ /* Allocate a buffer for the DEVMODE array */
+ pdminfo = ExAllocatePoolWithTag(PagedPool, cbFull, GDITAG_DEVMODE);
+ if (!pdminfo)
+ {
+ DPRINT1("Could not allocate devmodeinfo\n");
+ return NULL;
+ }
+
+ pdminfo->pldev = pldev;
+ pdminfo->cbdevmode = cbSize;
+
+ /* Call the driver again to fill the buffer */
+ cbSize = pldev->pfn.GetModes(hDriver, cbSize, pdminfo->adevmode);
+ if (!cbSize)
+ {
+ /* Could not get modes */
+ DPRINT1("returned size %ld(%ld)\n", cbSize, pdminfo->cbdevmode);
+ ExFreePool(pdminfo);
+ pdminfo = NULL;
+ }
+
+ return pdminfo;
+ }
+
+
+ BOOL
+ NTAPI
+ LDEVOBJ_bLoadImage(
+ IN PLDEVOBJ pldev,
+ PUNICODE_STRING pstrPathName)
+ {
+ PSYSTEM_GDI_DRIVER_INFORMATION pDriverInfo;
+ NTSTATUS Status;
+ ULONG cbSize;
+
+ /* Make sure no image is loaded yet */
+ ASSERT(pldev && pldev->pGdiDriverInfo == NULL);
+
+ /* Allocate a SYSTEM_GDI_DRIVER_INFORMATION structure */
+ cbSize = sizeof(SYSTEM_GDI_DRIVER_INFORMATION) + pstrPathName->Length;
+ pDriverInfo = ExAllocatePoolWithTag(PagedPool, cbSize, GDITAG_LDEV);
+ if (!pDriverInfo)
+ {
+ DPRINT1("Failed to allocate SYSTEM_GDI_DRIVER_INFORMATION\n");
+ return FALSE;
+ }
+
+ /* Initialize the UNICODE_STRING and copy the driver name */
+ RtlInitEmptyUnicodeString(&pDriverInfo->DriverName,
+ (PWSTR)(pDriverInfo + 1),
+ pstrPathName->Length);
+ RtlCopyUnicodeString(&pDriverInfo->DriverName, pstrPathName);
+
+ /* Try to load the driver */
+ Status = ZwSetSystemInformation(SystemLoadGdiDriverInformation,
+ pDriverInfo,
+ sizeof(SYSTEM_GDI_DRIVER_INFORMATION));
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to load a GDI driver: '%S', Status = 0x%lx\n",
+ pstrPathName->Buffer, Status);
+
+ /* Free the allocated memory */
+ ExFreePoolWithTag(pDriverInfo, TAG_LDEV);
+ return FALSE;
+ }
+
+ /* Set the driver info */
+ pldev->pGdiDriverInfo = pDriverInfo;
+
+ /* Return success. */
+ return TRUE;
+ }
+
+ VOID
+ NTAPI
+ LDEVOBJ_vUnloadImage(
+ IN PLDEVOBJ pldev)
+ {
+ NTSTATUS Status;
+
+ /* Make sure we have a driver info */
+ ASSERT(pldev && pldev->pGdiDriverInfo != NULL);
+
+ /* Check if we have loaded a driver */
+ if (pldev->pfn.DisableDriver)
+ {
+ /* Call the unload function */
+ pldev->pfn.DisableDriver();
+ }
+
+ /* Unload the driver */
+ Status = ZwSetSystemInformation(SystemUnloadGdiDriverInformation,
+ &pldev->pGdiDriverInfo->ImageAddress,
+ sizeof(HANDLE));
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to unload the driver, this is bad.\n");
+ }
+
+ /* Free the driver info structure */
+ ExFreePoolWithTag(pldev->pGdiDriverInfo, GDITAG_LDEV);
+ pldev->pGdiDriverInfo = NULL;
+ }
+
+ BOOL
+ NTAPI
+ LDEVOBJ_bLoadDriver(
+ IN PLDEVOBJ pldev)
+ {
+ PFN_DrvEnableDriver pfnEnableDriver;
+ DRVENABLEDATA ded;
+ ULONG i;
+
+ /* Make sure we have a driver info */
+ ASSERT(pldev && pldev->pGdiDriverInfo != NULL);
+
+ /* Call the drivers DrvEnableDriver function */
+ RtlZeroMemory(&ded, sizeof(ded));
+ pfnEnableDriver = pldev->pGdiDriverInfo->EntryPoint;
+ if (!pfnEnableDriver(GDI_ENGINE_VERSION, sizeof(ded), &ded))
+ {
+ DPRINT1("DrvEnableDriver failed\n");
+
+ /* Unload the image. */
+ LDEVOBJ_vUnloadImage(pldev);
+ return FALSE;
+ }
+
+ /* Copy the returned driver version */
+ pldev->ulDriverVersion = ded.iDriverVersion;
+
+ /* Fill the driver function array */
+ for (i = 0; i < ded.c; i++)
+ {
+ pldev->apfn[ded.pdrvfn[i].iFunc] = ded.pdrvfn[i].pfn;
+ }
+
+ /* Return success. */
+ return TRUE;
+ }
+
+
+ PVOID
+ NTAPI
+ LDEVOBJ_pvFindImageProcAddress(
+ IN PLDEVOBJ pldev,
+ IN LPSTR pszProcName)
+ {
+ PVOID pvImageBase;
+ PIMAGE_EXPORT_DIRECTORY pExportDir;
+ PVOID pvProcAdress = NULL;
+ PUSHORT pOrdinals;
+ PULONG pNames, pAddresses;
+ ULONG i, cbSize;
+
+ /* Make sure we have a driver info */
+ ASSERT(pldev && pldev->pGdiDriverInfo != NULL);
+
+ /* Get the pointer to the export directory */
+ pvImageBase = pldev->pGdiDriverInfo->ImageAddress;
+ pExportDir = RtlImageDirectoryEntryToData(pvImageBase,
+ TRUE,
+ IMAGE_DIRECTORY_ENTRY_EXPORT,
+ &cbSize);
+ if (!pExportDir)
+ {
+ return NULL;
+ }
+
+ /* Get pointers to some tables */
+ pNames = RVA_TO_ADDR(pvImageBase, pExportDir->AddressOfNames);
+ pOrdinals = RVA_TO_ADDR(pvImageBase, pExportDir->AddressOfNameOrdinals);
+ pAddresses = RVA_TO_ADDR(pvImageBase, pExportDir->AddressOfFunctions);
+
+ /* Loop the export table */
+ for (i = 0; i < pExportDir->NumberOfNames; i++)
+ {
+ /* Compare the name */
+ if (_stricmp(pszProcName, RVA_TO_ADDR(pvImageBase, pNames[i])) == 0)
+ {
+ /* Found! Calculate the procedure address */
+ pvProcAdress = RVA_TO_ADDR(pvImageBase, pAddresses[pOrdinals[i]]);
+ break;
+ }
+ }
+
+ /* Return the address */
+ return pvProcAdress;
+ }
+
+ PLDEVOBJ
+ NTAPI
+ EngLoadImageEx(
+ LPWSTR pwszDriverName,
+ ULONG ldevtype)
+ {
+ WCHAR acwBuffer[MAX_PATH];
+ PLDEVOBJ pldev;
+ UNICODE_STRING strDriverName;
+ ULONG cwcLength;
+ LPWSTR pwsz;
+
+ DPRINT("EngLoadImageEx(%ls, %ld)\n", pwszDriverName, ldevtype);
+ ASSERT(pwszDriverName);
+
+ /* Initialize buffer for the the driver name */
+ RtlInitEmptyUnicodeString(&strDriverName, acwBuffer, sizeof(acwBuffer));
+
+ /* Start path with systemroot */
+ RtlAppendUnicodeToString(&strDriverName, L"\\SystemRoot\\System32\\");
+
+ /* Get Length of given string */
+ cwcLength = wcslen(pwszDriverName);
+
+ /* Check if we have a system32 path given */
+ pwsz = pwszDriverName + cwcLength;
+ while (pwsz > pwszDriverName)
+ {
+ if (_wcsnicmp(pwsz, L"\\system32\\", 10) == 0)
+ {
+ /* Driver name starts after system32 */
+ pwsz += 10;
+ break;
+ }
+ pwsz--;
+ }
+
+ /* Append the driver name */
+ RtlAppendUnicodeToString(&strDriverName, pwsz);
+
+ /* MSDN says "The driver must include this suffix in the pwszDriver string."
+ But in fact it's optional. */
+ if (_wcsnicmp(pwszDriverName + cwcLength - 4, L".dll", 4) != 0)
+ {
+ /* Append the .dll suffix */
+ RtlAppendUnicodeToString(&strDriverName, L".dll");
+ }
+
+ /* Lock loader */
+ EngAcquireSemaphore(ghsemLDEVList);
+
+ /* Search the List of LDEVS for the driver name */
+ for (pldev = gpldevHead; pldev != NULL; pldev = pldev->pldevNext)
+ {
+ /* Check if the ldev is associated with a file */
+ if (pldev->pGdiDriverInfo)
+ {
+ /* Check for match (case insensative) */
+ if (RtlEqualUnicodeString(&pldev->pGdiDriverInfo->DriverName, &strDriverName, 1))
+ {
+ /* Image found in LDEV list */
+ break;
+ }
+ }
+ }
+
+ /* Did we find one? */
+ if (!pldev)
+ {
+ /* No, allocate a new LDEVOBJ */
+ pldev = LDEVOBJ_AllocLDEV(ldevtype);
+ if (!pldev)
+ {
+ DPRINT1("Could not allocate LDEV\n");
+ goto leave;
+ }
+
+ /* Load the image */
+ if (!LDEVOBJ_bLoadImage(pldev, &strDriverName))
+ {
+ LDEVOBJ_vFreeLDEV(pldev);
+ pldev = NULL;
+ DPRINT1("LDEVOBJ_bLoadImage failed\n");
+ goto leave;
+ }
+
+ /* Shall we load a driver? */
+ if (ldevtype != LDEV_IMAGE)
+ {
+ /* Load the driver */
+ if (!LDEVOBJ_bLoadDriver(pldev))
+ {
+ DPRINT1("LDEVOBJ_bLoadDriver failed\n");
+ LDEVOBJ_vFreeLDEV(pldev);
+ pldev = NULL;
+ goto leave;
+ }
+ }
+
+ /* Insert the LDEV into the global list */
+ pldev->pldevPrev = NULL;
+ pldev->pldevNext = gpldevHead;
+ gpldevHead = pldev;
+ }
+
+ /* Increase ref count */
+ pldev->cRefs++;
+
+ leave:
+ /* Unlock loader */
+ EngReleaseSemaphore(ghsemLDEVList);
+
+ DPRINT("EngLoadImageEx returning %p\n", pldev);
+
+ return pldev;
+ }
+
+
+ /** Exported functions ********************************************************/
+
+ HANDLE
+ APIENTRY
+ EngLoadImage(
+ LPWSTR pwszDriverName)
+ {
+ return (HANDLE)EngLoadImageEx(pwszDriverName, LDEV_IMAGE);
+ }
+
+
+ VOID
+ APIENTRY
+ EngUnloadImage(
+ IN HANDLE hModule)
+ {
+ PLDEVOBJ pldev = (PLDEVOBJ)hModule;
+
+ /* Make sure the LDEV is in the list */
+ ASSERT(pldev->pldevPrev || pldev->pldevNext);
+
+ /* Lock loader */
+ EngAcquireSemaphore(ghsemLDEVList);
+
+ /* Decrement reference count */
+ pldev->cRefs--;
+
+ /* No more references left? */
+ if (pldev->cRefs == 0)
+ {
+ /* Remove ldev from the list */
+ if (pldev->pldevPrev)
+ pldev->pldevPrev->pldevNext = pldev->pldevNext;
+ if (pldev->pldevNext)
+ pldev->pldevNext->pldevPrev = pldev->pldevPrev;
+
+ /* Unload the image */
+ LDEVOBJ_vUnloadImage(pldev);
+ }
+
+ /* Unlock loader */
+ EngReleaseSemaphore(ghsemLDEVList);
+ }
+
+
+ PVOID
+ APIENTRY
+ EngFindImageProcAddress(
+ IN HANDLE hModule,
+ IN LPSTR lpProcName)
+ {
+ PLDEVOBJ pldev = (PLDEVOBJ)hModule;
+
+ ASSERT(gpldevWin32k != NULL);
+
+ /* Check if win32k is requested */
+ if (!pldev)
+ {
+ pldev = gpldevWin32k;
+ }
+
+ /* Check if the drivers entry point is requested */
+ if (_strnicmp(lpProcName, "DrvEnableDriver", 15) == 0)
+ {
+ return pldev->pGdiDriverInfo->EntryPoint;
+ }
+
+ /* Try to find the address */
+ return LDEVOBJ_pvFindImageProcAddress(pldev, lpProcName);
+ }
+
if (b.left == b.right) b.right++;
if (b.top == b.bottom) b.bottom++;
- SURFACE_LockBitmapBits(psurfDest);
- MouseSafetyOnDrawStart(psoDest, x1, y1, x2, y2);
-
- if (psurfDest->flHooks & HOOK_LINETO)
+ if (psurfDest->flags & HOOK_LINETO)
{
/* Call the driver's DrvLineTo */
ret = GDIDEVFUNCS(psoDest).LineTo(
}
#if 0
- if (! ret && (psurfDest->flHooks & HOOK_STROKEPATH))
+ if (! ret && (psurfDest->flags & HOOK_STROKEPATH))
{
/* FIXME: Emulate LineTo using drivers DrvStrokePath and set ret on success */
}
ret = EngLineTo(psoDest, ClipObj, pbo, x1, y1, x2, y2, RectBounds, Mix);
}
- MouseSafetyOnDrawEnd(psoDest);
- SURFACE_UnlockBitmapBits(psurfDest);
-
return ret;
}
* PROJECT: ReactOS kernel
* PURPOSE: Functions for mapping files and sections
* FILE: subsys/win32k/eng/device.c
- * PROGRAMER:
+ * PROGRAMER: Timo Kreuzer (timo.kreuzer@reactos.org)
*/
#include <win32k.h>
#define NDEBUG
#include <debug.h>
+ // HACK!!!
+ #define MmMapViewInSessionSpace MmMapViewInSystemSpace
+ #define MmUnmapViewInSessionSpace MmUnmapViewInSystemSpace
+
+ typedef struct _ENGSECTION
+ {
+ PVOID pvSectionObject;
+ PVOID pvMappedBase;
+ SIZE_T cjViewSize;
+ ULONG ulTag;
+ } ENGSECTION, *PENGSECTION;
+
+ typedef struct _FILEVIEW
+ {
+ LARGE_INTEGER LastWriteTime;
+ PVOID pvKView;
+ PVOID pvViewFD;
+ SIZE_T cjView;
+ PVOID pSection;
+ } FILEVIEW, *PFILEVIEW;
+
+ typedef struct _FONTFILEVIEW
+ {
+ FILEVIEW;
+ DWORD reserved[2];
+ PWSTR pwszPath;
+ SIZE_T ulRegionSize;
+ ULONG cKRefCount;
+ ULONG cRefCountFD;
+ PVOID pvSpoolerBase;
+ DWORD dwSpoolerPid;
+ } FONTFILEVIEW, *PFONTFILEVIEW;
+
+ enum
+ {
+ FVF_SYSTEMROOT = 1,
+ FVF_READONLY = 2,
+ FVF_FONTFILE = 4,
+ };
+
+ HANDLE ghSystem32Directory;
+ HANDLE ghRootDirectory;
+
+
+ PVOID
+ NTAPI
+ EngCreateSection(
+ IN ULONG fl,
+ IN SIZE_T cjSize,
+ IN ULONG ulTag)
+ {
+ NTSTATUS Status;
+ PENGSECTION pSection;
+ PVOID pvSectionObject;
+ LARGE_INTEGER liSize;
+
+ /* Allocate a section object */
+ pSection = EngAllocMem(0, sizeof(ENGSECTION), 'stsU');
+ if (!pSection) return NULL;
+
+ liSize.QuadPart = cjSize;
+ Status = MmCreateSection(&pvSectionObject,
+ SECTION_ALL_ACCESS,
+ NULL,
+ &liSize,
+ PAGE_READWRITE,
+ SEC_COMMIT,
+ NULL,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create a section Status=0x%x\n", Status);
+ EngFreeMem(pSection);
+ return NULL;
+ }
+
+ /* Set the fields of the section */
+ pSection->ulTag = ulTag;
+ pSection->pvSectionObject = pvSectionObject;
+ pSection->pvMappedBase = NULL;
+ pSection->cjViewSize = cjSize;
+
+ return pSection;
+ }
+
+
+ BOOL
+ APIENTRY
+ EngMapSection(
+ IN PVOID pvSection,
+ IN BOOL bMap,
+ IN HANDLE hProcess,
+ OUT PVOID* pvBaseAddress)
+ {
+ NTSTATUS Status;
+ PENGSECTION pSection = pvSection;
+ PEPROCESS pepProcess;
+
+ /* Get a pointer to the process */
+ Status = ObReferenceObjectByHandle(hProcess,
+ PROCESS_VM_OPERATION,
+ NULL,
+ KernelMode,
+ (PVOID*)&pepProcess,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Could not access process %p, Status=0x%lx\n", hProcess, Status);
+ return FALSE;
+ }
+
+ if (bMap)
+ {
+ /* Make sure the section isn't already mapped */
+ ASSERT(pSection->pvMappedBase == NULL);
+
+ /* Map the section into the process address space */
+ Status = MmMapViewOfSection(pSection->pvSectionObject,
+ pepProcess,
+ &pSection->pvMappedBase,
+ 0,
+ pSection->cjViewSize,
+ NULL,
+ &pSection->cjViewSize,
+ 0,
+ 0,
+ PAGE_READWRITE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to map a section Status=0x%x\n", Status);
+ }
+ }
+ else
+ {
+ /* Make sure the section is mapped */
+ ASSERT(pSection->pvMappedBase);
+
+ /* Unmap the section from the process address space */
+ Status = MmUnmapViewOfSection(pepProcess, pSection->pvMappedBase);
+ if (NT_SUCCESS(Status))
+ {
+ pSection->pvMappedBase = NULL;
+ }
+ else
+ {
+ DPRINT1("Failed to unmap a section @ &p Status=0x%x\n",
+ pSection->pvMappedBase, Status);
+ }
+ }
+
+ /* Dereference the process */
+ ObDereferenceObject(pepProcess);
+
+ /* Set the new mapping base and return bool status */
+ *pvBaseAddress = pSection->pvMappedBase;
+ return NT_SUCCESS(Status);
+ }
+
+ BOOL
+ APIENTRY
+ EngFreeSectionMem(
+ IN PVOID pvSection OPTIONAL,
+ IN PVOID pvMappedBase OPTIONAL)
+ {
+ NTSTATUS Status;
+ PENGSECTION pSection = pvSection;
+ BOOL bResult = TRUE;
+
+ /* Did the caller give us a mapping base? */
+ if (pvMappedBase)
+ {
+ Status = MmUnmapViewInSessionSpace(pvMappedBase);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("MmUnmapViewInSessionSpace failed: 0x%lx\n", Status);
+ bResult = FALSE;
+ }
+ }
+
+ /* Check if we should free the section as well */
+ if (pSection)
+ {
+ /* Dereference the kernel section */
+ ObDereferenceObject(pSection->pvSectionObject);
+
+ /* Finally free the section memory itself */
+ EngFreeMem(pSection);
+ }
+
+ return bResult;
+ }
+
+ PVOID
+ APIENTRY
+ EngAllocSectionMem(
+ OUT PVOID *ppvSection,
+ IN ULONG fl,
+ IN SIZE_T cjSize,
+ IN ULONG ulTag)
+ {
+ NTSTATUS Status;
+ PENGSECTION pSection;
+
+ /* Check parameter */
+ if (cjSize == 0) return NULL;
+
+ /* Allocate a section object */
+ pSection = EngCreateSection(fl, cjSize, ulTag);
+ if (!pSection)
+ {
+ *ppvSection = NULL;
+ return NULL;
+ }
+
+ /* Map the section in session space */
+ Status = MmMapViewInSessionSpace(pSection->pvSectionObject,
+ &pSection->pvMappedBase,
+ &pSection->cjViewSize);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to map a section Status=0x%x\n", Status);
+ *ppvSection = NULL;
+ EngFreeSectionMem(pSection, NULL);
+ return NULL;
+ }
+
+ if (fl & FL_ZERO_MEMORY)
+ {
+ RtlZeroMemory(pSection->pvMappedBase, cjSize);
+ }
+
+ /* Set section pointer and return base address */
+ *ppvSection = pSection;
+ return pSection->pvMappedBase;
+ }
+
+
+ PFILEVIEW
+ NTAPI
+ EngLoadModuleEx(
+ LPWSTR pwsz,
+ ULONG cjSizeOfModule,
+ FLONG fl)
+ {
+ PFILEVIEW pFileView = NULL;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE hRootDir;
+ UNICODE_STRING ustrFileName;
+ IO_STATUS_BLOCK IoStatusBlock;
+ FILE_BASIC_INFORMATION FileInformation;
+ HANDLE hFile;
+ NTSTATUS Status;
+ LARGE_INTEGER liSize;
+
+ if (fl & FVF_FONTFILE)
+ {
+ pFileView = EngAllocMem(0, sizeof(FONTFILEVIEW), 'vffG');
+ }
+ else
+ {
+ pFileView = EngAllocMem(0, sizeof(FILEVIEW), 'liFg');
+ }
+
+ /* Check for success */
+ if (!pFileView) return NULL;
+
+ /* Check if the file is relative to system32 */
+ if (fl & FVF_SYSTEMROOT)
+ {
+ hRootDir = ghSystem32Directory;
+ }
+ else
+ {
+ hRootDir = ghRootDirectory;
+ }
+
+ /* Initialize unicode string and object attributes */
+ RtlInitUnicodeString(&ustrFileName, pwsz);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &ustrFileName,
+ OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,
+ hRootDir,
+ NULL);
+
+ /* Now open the file */
+ Status = ZwCreateFile(&hFile,
+ FILE_READ_DATA,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_OPEN,
+ FILE_NON_DIRECTORY_FILE,
+ NULL,
+ 0);
+
+ Status = ZwQueryInformationFile(hFile,
+ &IoStatusBlock,
+ &FileInformation,
+ sizeof(FILE_BASIC_INFORMATION),
+ FileBasicInformation);
+ if (NT_SUCCESS(Status))
+ {
+ pFileView->LastWriteTime = FileInformation.LastWriteTime;
+ }
+
+ /* Create a section from the file */
+ liSize.QuadPart = cjSizeOfModule;
+ Status = MmCreateSection(&pFileView->pSection,
+ SECTION_ALL_ACCESS,
+ NULL,
+ cjSizeOfModule ? &liSize : NULL,
+ fl & FVF_READONLY ? PAGE_EXECUTE_READ : PAGE_EXECUTE_READWRITE,
+ SEC_COMMIT,
+ hFile,
+ NULL);
+
+ /* Close the file handle */
+ ZwClose(hFile);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create a section Status=0x%x\n", Status);
+ EngFreeMem(pFileView);
+ return NULL;
+ }
+
+
+ pFileView->pvKView = NULL;
+ pFileView->pvViewFD = NULL;
+ pFileView->cjView = 0;
+
+ return pFileView;
+ }
+
HANDLE
APIENTRY
EngLoadModule(LPWSTR pwsz)
{
- UNIMPLEMENTED;
- return NULL;
+ /* Forward to EngLoadModuleEx */
+ return (HANDLE)EngLoadModuleEx(pwsz, 0, FVF_READONLY | FVF_SYSTEMROOT);
}
HANDLE
IN LPWSTR pwsz,
IN ULONG cjSizeOfModule)
{
- // www.osr.com/ddk/graphics/gdifncs_98rr.htm
- UNIMPLEMENTED;
- return NULL;
+ /* Forward to EngLoadModuleEx */
+ return (HANDLE)EngLoadModuleEx(pwsz, cjSizeOfModule, FVF_SYSTEMROOT);
}
PVOID
IN HANDLE h,
OUT PULONG pulSize)
{
- // www.osr.com/ddk/graphics/gdifncs_9b1j.htm
- UNIMPLEMENTED;
- return NULL;
+ PFILEVIEW pFileView = (PFILEVIEW)h;
+ NTSTATUS Status;
+
+ pFileView->cjView = 0;
+
+ /* Map the section in session space */
+ Status = MmMapViewInSessionSpace(pFileView->pSection,
+ &pFileView->pvKView,
+ &pFileView->cjView);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to map a section Status=0x%x\n", Status);
+ *pulSize = 0;
+ return NULL;
+ }
+
+ *pulSize = pFileView->cjView;
+ return pFileView->pvKView;
}
VOID
APIENTRY
- EngFreeModule (IN HANDLE h)
+ EngFreeModule(IN HANDLE h)
{
- // www.osr.com/ddk/graphics/gdifncs_9fzb.htm
- UNIMPLEMENTED;
+ PFILEVIEW pFileView = (PFILEVIEW)h;
+ NTSTATUS Status;
+
+ /* Unmap the section */
+ Status = MmUnmapViewInSessionSpace(pFileView->pvKView);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("MmUnmapViewInSessionSpace failed: 0x%lx\n", Status);
+ ASSERT(FALSE);
+ }
+
+ /* Dereference the section */
+ ObDereferenceObject(pFileView->pSection);
+
+ /* Free the file view memory */
+ EngFreeMem(pFileView);
}
PVOID
IN ULONG cjSize,
OUT ULONG_PTR *piFile)
{
- UNIMPLEMENTED;
- return NULL;
+ HANDLE hModule;
+ PVOID pvBase;
+
+ /* Load the file */
+ hModule = EngLoadModuleEx(pwsz, 0, 0);
+ if (!hModule)
+ {
+ *piFile = 0;
+ return NULL;
+ }
+
+ /* Map the file */
+ pvBase = EngMapModule(hModule, &cjSize);
+ if (!pvBase)
+ {
+ EngFreeModule(hModule);
+ hModule = NULL;
+ }
+
+ /* Set iFile and return mapped base */
+ *piFile = (ULONG_PTR)hModule;
+ return pvBase;
}
BOOL
EngUnmapFile(
IN ULONG_PTR iFile)
{
- UNIMPLEMENTED;
- return FALSE;
+ HANDLE hModule = (HANDLE)iFile;
+
+ EngFreeModule(hModule);
+
+ return TRUE;
}
// www.osr.com/ddk/graphics/gdifncs_09wn.htm
EngUnmapFontFileFD(iFile);
}
-
-
- BOOLEAN
- APIENTRY
- EngMapSection(IN PVOID Section,
- IN BOOLEAN Map,
- IN HANDLE Process,
- IN PVOID* BaseAddress)
- {
- UNIMPLEMENTED;
- return FALSE;
- }
-
- PVOID
- APIENTRY
- EngAllocSectionMem(IN PVOID SectionObject,
- IN ULONG Flags,
- IN SIZE_T MemSize,
- IN ULONG Tag)
- {
- UNIMPLEMENTED;
- return NULL;
- }
-
-
- BOOLEAN
- APIENTRY
- EngFreeSectionMem(IN PVOID SectionObject OPTIONAL,
- IN PVOID MappedBase)
- {
- UNIMPLEMENTED;
- return FALSE;
- }
}
/* TODO: Add allocation info to AVL tree (stored inside W32PROCESS structure) */
+ //hSecure = EngSecureMem(NewMem, cj);
return NewMem;
}
HANDLE APIENTRY
EngSecureMem(PVOID Address, ULONG Length)
{
+ return (HANDLE)-1; // HACK!!!
return MmSecureVirtualMemory(Address, Length, PAGE_READWRITE);
}
VOID APIENTRY
EngUnsecureMem(HANDLE Mem)
{
+ if (Mem == (HANDLE)-1) return; // HACK!!!
MmUnsecureVirtualMemory((PVOID) Mem);
}
*/
INT INTERNAL_CALL
MouseSafetyOnDrawStart(
- SURFOBJ *pso,
+ PPDEVOBJ ppdev,
LONG HazardX1,
LONG HazardY1,
LONG HazardX2,
LONG HazardY2)
{
LONG tmp;
- PDEVOBJ *ppdev;
GDIPOINTER *pgp;
- ASSERT(pso != NULL);
-
- ppdev = GDIDEV(pso);
- if (ppdev == NULL)
- {
- return FALSE;
- }
+ ASSERT(ppdev != NULL);
+ ASSERT(ppdev->pSurface != NULL);
pgp = &ppdev->Pointer;
}
if (pgp->Exclude.right >= HazardX1
- && pgp->Exclude.left <= HazardX2
- && pgp->Exclude.bottom >= HazardY1
- && pgp->Exclude.top <= HazardY2)
+ && pgp->Exclude.left <= HazardX2
+ && pgp->Exclude.bottom >= HazardY1
+ && pgp->Exclude.top <= HazardY2)
{
ppdev->SafetyRemoveLevel = ppdev->SafetyRemoveCount;
- ppdev->pfnMovePointer(pso, -1, -1, NULL);
+ ppdev->pfnMovePointer(&ppdev->pSurface->SurfObj, -1, -1, NULL);
}
return(TRUE);
*/
INT INTERNAL_CALL
MouseSafetyOnDrawEnd(
- SURFOBJ *pso)
+ PPDEVOBJ ppdev)
{
- PDEVOBJ *ppdev;
GDIPOINTER *pgp;
- ASSERT(pso != NULL);
-
- ppdev = (PDEVOBJ*)pso->hdev;
-
- if (ppdev == NULL)
- {
- return(FALSE);
- }
+ ASSERT(ppdev != NULL);
+ ASSERT(ppdev->pSurface != NULL);
pgp = &ppdev->Pointer;
return FALSE;
}
- ppdev->pfnMovePointer(pso, gpsi->ptCursor.x, gpsi->ptCursor.y, &pgp->Exclude);
+ ppdev->pfnMovePointer(&ppdev->pSurface->SurfObj,
+ gpsi->ptCursor.x,
+ gpsi->ptCursor.y,
+ &pgp->Exclude);
ppdev->SafetyRemoveLevel = 0;
ptlSave.x = rclDest.left - pt.x;
ptlSave.y = rclDest.top - pt.y;
- IntEngBitBltEx(psoDest,
- &pgp->psurfSave->SurfObj,
- NULL,
- NULL,
- NULL,
- &rclDest,
- &ptlSave,
- &ptlSave,
- NULL,
- NULL,
- ROP3_TO_ROP4(SRCCOPY),
- FALSE);
+ IntEngBitBlt(psoDest,
+ &pgp->psurfSave->SurfObj,
+ NULL,
+ NULL,
+ NULL,
+ &rclDest,
+ &ptlSave,
+ &ptlSave,
+ NULL,
+ NULL,
+ ROP3_TO_ROP4(SRCCOPY));
}
VOID
rclPointer.bottom = min(pgp->Size.cy, psoDest->sizlBitmap.cy - pt.y);
/* Copy the pixels under the cursor to temporary surface. */
- IntEngBitBltEx(&pgp->psurfSave->SurfObj,
- psoDest,
- NULL,
- NULL,
- NULL,
- &rclPointer,
- (POINTL*)&rclSurf,
- NULL,
- NULL,
- NULL,
- ROP3_TO_ROP4(SRCCOPY),
- FALSE);
+ IntEngBitBlt(&pgp->psurfSave->SurfObj,
+ psoDest,
+ NULL,
+ NULL,
+ NULL,
+ &rclPointer,
+ (POINTL*)&rclSurf,
+ NULL,
+ NULL,
+ NULL,
+ ROP3_TO_ROP4(SRCCOPY));
/* Blt the pointer on the screen. */
if (pgp->psurfColor)
{
- IntEngBitBltEx(psoDest,
- &pgp->psurfMask->SurfObj,
- NULL,
- NULL,
- NULL,
- &rclSurf,
- (POINTL*)&rclPointer,
- NULL,
- NULL,
- NULL,
- ROP3_TO_ROP4(SRCAND),
- FALSE);
-
- IntEngBitBltEx(psoDest,
- &pgp->psurfColor->SurfObj,
- NULL,
- NULL,
- NULL,
- &rclSurf,
- (POINTL*)&rclPointer,
- NULL,
- NULL,
- NULL,
- ROP3_TO_ROP4(SRCINVERT),
- FALSE);
+ IntEngBitBlt(psoDest,
+ &pgp->psurfMask->SurfObj,
+ NULL,
+ NULL,
+ NULL,
+ &rclSurf,
+ (POINTL*)&rclPointer,
+ NULL,
+ NULL,
+ NULL,
+ ROP3_TO_ROP4(SRCAND));
+
+ IntEngBitBlt(psoDest,
+ &pgp->psurfColor->SurfObj,
+ NULL,
+ NULL,
+ NULL,
+ &rclSurf,
+ (POINTL*)&rclPointer,
+ NULL,
+ NULL,
+ NULL,
+ ROP3_TO_ROP4(SRCINVERT));
}
else
{
- IntEngBitBltEx(psoDest,
- &pgp->psurfMask->SurfObj,
- NULL,
- NULL,
- NULL,
- &rclSurf,
- (POINTL*)&rclPointer,
- NULL,
- NULL,
- NULL,
- ROP3_TO_ROP4(SRCAND),
- FALSE);
+ IntEngBitBlt(psoDest,
+ &pgp->psurfMask->SurfObj,
+ NULL,
+ NULL,
+ NULL,
+ &rclSurf,
+ (POINTL*)&rclPointer,
+ NULL,
+ NULL,
+ NULL,
+ ROP3_TO_ROP4(SRCAND));
rclPointer.top += pgp->Size.cy;
- IntEngBitBltEx(psoDest,
- &pgp->psurfMask->SurfObj,
- NULL,
- NULL,
- NULL,
- &rclSurf,
- (POINTL*)&rclPointer,
- NULL,
- NULL,
- NULL,
- ROP3_TO_ROP4(SRCINVERT),
- FALSE);
+ IntEngBitBlt(psoDest,
+ &pgp->psurfMask->SurfObj,
+ NULL,
+ NULL,
+ NULL,
+ &rclSurf,
+ (POINTL*)&rclPointer,
+ NULL,
+ NULL,
+ NULL,
+ ROP3_TO_ROP4(SRCINVERT));
}
}
rectl.bottom = sizel.cy;
/* Calculate lDelta for our surfaces. */
- lDelta = DIB_GetDIBWidthBytes(sizel.cx,
+ lDelta = WIDTH_BYTES_ALIGN32(sizel.cx,
BitsPerFormat(pso->iBitmapFormat));
/* Create a bitmap for saving the pixels under the cursor. */
/* Create a bitmap to copy the color bitmap to */
hbmColor = EngCreateBitmap(psoColor->sizlBitmap,
- lDelta,
- pso->iBitmapFormat,
- BMF_TOPDOWN | BMF_NOZEROINIT,
- NULL);
+ lDelta,
+ pso->iBitmapFormat,
+ BMF_TOPDOWN | BMF_NOZEROINIT,
+ NULL);
psurfColor = SURFACE_ShareLockSurface(hbmColor);
if (!psurfColor) goto failure;
prcl->right = prcl->left + pgp->Size.cx;
prcl->bottom = prcl->top + pgp->Size.cy;
}
- }
+ }
else if (prcl != NULL)
{
prcl->left = prcl->top = prcl->right = prcl->bottom = -1;
}
}
- VOID APIENTRY
- IntEngMovePointer(
- IN SURFOBJ *pso,
- IN LONG x,
- IN LONG y,
- IN RECTL *prcl)
- {
- SURFACE *psurf = CONTAINING_RECORD(pso, SURFACE, SurfObj);
- PPDEVOBJ ppdev = (PPDEVOBJ)pso->hdev;
-
- SURFACE_LockBitmapBits(psurf);
- ppdev->pfnMovePointer(pso, x, y, prcl);
- SURFACE_UnlockBitmapBits(psurf);
- }
-
ULONG APIENTRY
IntEngSetPointerShape(
IN SURFOBJ *pso,
IN FLONG fl)
{
ULONG ulResult = SPS_DECLINE;
- SURFACE *psurf = CONTAINING_RECORD(pso, SURFACE, SurfObj);
PFN_DrvSetPointerShape pfnSetPointerShape;
PPDEVOBJ ppdev = GDIDEV(pso);
pfnSetPointerShape = GDIDEVFUNCS(pso).SetPointerShape;
- SURFACE_LockBitmapBits(psurf);
if (pfnSetPointerShape)
{
ulResult = pfnSetPointerShape(pso,
ppdev->pfnMovePointer = EngMovePointer;
}
- SURFACE_UnlockBitmapBits(psurf);
-
return ulResult;
}
return 0;
}
- psurf = pdc->dclevel.pSurface;
+ ASSERT(pdc->dctype == DCTYPE_DIRECT);
+ EngAcquireSemaphore(pdc->ppdev->hsemDevLock);
+ /* We're not sure DC surface is the good one */
+ psurf = pdc->ppdev->pSurface;
if (!psurf)
{
DPRINT1("DC has no surface.\n");
+ EngReleaseSemaphore(pdc->ppdev->hsemDevLock);
DC_UnlockDc(pdc);
return 0;
}
{
/* We have one, lock it */
psurfColor = SURFACE_ShareLockSurface(hbmColor);
-
+
if (psurfColor)
{
/* Create an XLATEOBJ, no mono support */
if (psurfMask)
SURFACE_ShareUnlockSurface(psurfMask);
+ EngReleaseSemaphore(pdc->ppdev->hsemDevLock);
+
/* Unlock the DC */
DC_UnlockDc(pdc);
DPRINT1("Failed to lock the DC.\n");
return;
}
+ ASSERT(pdc->dctype == DCTYPE_DIRECT);
+
+ /* Acquire PDEV lock */
+ EngAcquireSemaphore(pdc->ppdev->hsemDevLock);
- /* Store the cursor exclude position in the PDEV */
- prcl = &pdc->ppdev->Pointer.Exclude;
+ /* Check if we need to move it */
+ if(pdc->ppdev->SafetyRemoveLevel == 0)
+ {
+ /* Store the cursor exclude position in the PDEV */
+ prcl = &pdc->ppdev->Pointer.Exclude;
+
+ /* Call Eng/Drv function */
+ pdc->ppdev->pfnMovePointer(&pdc->ppdev->pSurface->SurfObj, x, y, prcl);
+ }
- /* Call Eng/Drv function */
- IntEngMovePointer(&pdc->dclevel.pSurface->SurfObj, x, y, prcl);
+ /* Release PDEV lock */
+ EngReleaseSemaphore(pdc->ppdev->hsemDevLock);
/* Unlock the DC */
DC_UnlockDc(pdc);
#define NDEBUG
#include <debug.h>
- static BOOL APIENTRY FillSolidUnlocked(SURFOBJ *pso, PRECTL pRect, ULONG iColor)
+ BOOL APIENTRY FillSolid(SURFOBJ *pso, PRECTL pRect, ULONG iColor)
{
LONG y;
ULONG LineWidth;
ASSERT(pso);
ASSERT(pRect);
- MouseSafetyOnDrawStart(pso, pRect->left, pRect->top, pRect->right, pRect->bottom);
LineWidth = pRect->right - pRect->left;
DPRINT(" LineWidth: %d, top: %d, bottom: %d\n", LineWidth, pRect->top, pRect->bottom);
for (y = pRect->top; y < pRect->bottom; y++)
DibFunctionsForBitmapFormat[pso->iBitmapFormat].DIB_HLine(
pso, pRect->left, pRect->right, y, iColor);
}
- MouseSafetyOnDrawEnd(pso);
-
return TRUE;
}
- BOOL APIENTRY FillSolid(SURFOBJ *pso, PRECTL pRect, ULONG iColor)
- {
- SURFACE *psurf;
- BOOL Result;
- psurf = CONTAINING_RECORD(pso, SURFACE, SurfObj);
- SURFACE_LockBitmapBits(psurf);
- Result = FillSolidUnlocked(pso, pRect, iColor);
- SURFACE_UnlockBitmapBits(psurf);
- return Result;
- }
-
BOOL APIENTRY
EngPaintRgn(SURFOBJ *pso, CLIPOBJ *ClipRegion, ULONG iColor, MIX Mix,
BRUSHOBJ *BrushObj, POINTL *BrushPoint)
if (ClipRegion->iDComplexity == DC_RECT)
{
- FillSolidUnlocked(pso, &(ClipRegion->rclBounds), iColor);
+ FillSolid(pso, &(ClipRegion->rclBounds), iColor);
} else {
/* Enumerate all the rectangles and draw them */
do {
EnumMore = CLIPOBJ_bEnum(ClipRegion, sizeof(RectEnum), (PVOID) &RectEnum);
for (i = 0; i < RectEnum.c; i++) {
- FillSolidUnlocked(pso, RectEnum.arcl + i, iColor);
+ FillSolid(pso, RectEnum.arcl + i, iColor);
}
} while (EnumMore);
}
DPRINT("pso->iType == %d\n", pso->iType);
/* Is the surface's Paint function hooked? */
- if((pso->iType!=STYPE_BITMAP) && (psurf->flHooks & HOOK_PAINT))
+ if((pso->iType!=STYPE_BITMAP) && (psurf->flags & HOOK_PAINT))
{
// Call the driver's DrvPaint
- SURFACE_LockBitmapBits(psurf);
- MouseSafetyOnDrawStart(pso, ClipRegion->rclBounds.left,
- ClipRegion->rclBounds.top, ClipRegion->rclBounds.right,
- ClipRegion->rclBounds.bottom);
-
ret = GDIDEVFUNCS(pso).Paint(
pso, ClipRegion, Brush, BrushOrigin, Mix);
- MouseSafetyOnDrawEnd(pso);
- SURFACE_UnlockBitmapBits(psurf);
return ret;
}
return EngPaint(pso, ClipRegion, Brush, BrushOrigin, Mix );
--- /dev/null
+ /*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * PURPOSE: Support for physical devices
+ * FILE: subsystems/win32/win32k/eng/pdevobj.c
+ * PROGRAMER: Timo Kreuzer (timo.kreuzer@reactos.org)
+ */
+
+ #include <win32k.h>
+
+ #include <intrin.h>
+
+ #define NDEBUG
+ #include <debug.h>
+
+ PPDEVOBJ gppdevPrimary = NULL;
+
+ static PPDEVOBJ gppdevList = NULL;
+ static HSEMAPHORE ghsemPDEV;
+
+ BOOL
+ NTAPI
+ InitPDEVImpl()
+ {
+ ghsemPDEV = EngCreateSemaphore();
+ return TRUE;
+ }
+
+
+ PPDEVOBJ
+ PDEVOBJ_AllocPDEV()
+ {
+ PPDEVOBJ ppdev;
+
+ ppdev = ExAllocatePoolWithTag(PagedPool, sizeof(PDEVOBJ), GDITAG_PDEV);
+ if (!ppdev)
+ return NULL;
+
+ RtlZeroMemory(ppdev, sizeof(PDEVOBJ));
+
+ ppdev->cPdevRefs = 1;
+
+ return ppdev;
+ }
+
+ VOID
+ NTAPI
+ PDEVOBJ_vRelease(PPDEVOBJ ppdev)
+ {
+ /* Lock loader */
+ EngAcquireSemaphore(ghsemPDEV);
+
+ /* Decrease reference count */
+ --ppdev->cPdevRefs;
+
+ ASSERT(ppdev->cPdevRefs >= 0) ;
+
+ /* Check if references are left */
+ if (ppdev->cPdevRefs == 0)
+ {
+ /* Do we have a surface? */
+ if(ppdev->pSurface)
+ {
+ /* Release the surface and let the driver free it */
+ SURFACE_ShareUnlockSurface(ppdev->pSurface);
+ ppdev->pfn.DisableSurface(ppdev->dhpdev);
+ }
+
+ /* Do we have a palette? */
+ if(ppdev->ppalSurf)
+ {
+ PALETTE_ShareUnlockPalette(ppdev->ppalSurf);
+ }
+
+ /* Disable PDEV */
+ ppdev->pfn.DisablePDEV(ppdev->dhpdev);
+
+ /* Remove it from list */
+ if( ppdev == gppdevList )
+ gppdevList = ppdev->ppdevNext ;
+ else
+ {
+ PPDEVOBJ ppdevCurrent = gppdevList;
+ BOOL found = FALSE ;
+ while (!found && ppdevCurrent->ppdevNext)
+ {
+ if (ppdevCurrent->ppdevNext == ppdev)
+ found = TRUE;
+ else
+ ppdevCurrent = ppdevCurrent->ppdevNext ;
+ }
+ if(found)
+ ppdevCurrent->ppdevNext = ppdev->ppdevNext;
+ }
+
+ /* Is this the primary one ? */
+ if (ppdev == gppdevPrimary)
+ gppdevPrimary = NULL;
+
+ /* Free it */
+ ExFreePoolWithTag(ppdev, GDITAG_PDEV );
+ }
+
+ /* Unlock loader */
+ EngReleaseSemaphore(ghsemPDEV);
+
+ }
+
+ BOOL
+ NTAPI
+ PDEVOBJ_bEnablePDEV(
+ PPDEVOBJ ppdev,
+ PDEVMODEW pdevmode,
+ PWSTR pwszLogAddress)
+ {
+ PFN_DrvEnablePDEV pfnEnablePDEV;
+
+ DPRINT1("PDEVOBJ_bEnablePDEV()\n");
+
+ /* Get the DrvEnablePDEV function */
+ pfnEnablePDEV = ppdev->pldev->pfn.EnablePDEV;
+
+ /* Call the drivers DrvEnablePDEV function */
+ ppdev->dhpdev = pfnEnablePDEV(pdevmode,
+ pwszLogAddress,
+ HS_DDI_MAX,
+ ppdev->ahsurf,
+ sizeof(GDIINFO),
+ &ppdev->gdiinfo,
+ sizeof(DEVINFO),
+ &ppdev->devinfo,
+ (HDEV)ppdev,
+ ppdev->pGraphicsDevice->pwszDescription,
+ ppdev->pGraphicsDevice->DeviceObject);
+
+ /* Fix up some values */
+ if (ppdev->gdiinfo.ulLogPixelsX == 0)
+ ppdev->gdiinfo.ulLogPixelsX = 96;
+
+ if (ppdev->gdiinfo.ulLogPixelsY == 0)
+ ppdev->gdiinfo.ulLogPixelsY = 96;
+
+ /* Setup Palette */
+ GDIOBJ_SetOwnership(ppdev->devinfo.hpalDefault, NULL);
+ ppdev->ppalSurf = PALETTE_ShareLockPalette(ppdev->devinfo.hpalDefault);
+
+ DPRINT1("PDEVOBJ_bEnablePDEV - dhpdev = %p\n", ppdev->dhpdev);
+
+ return TRUE;
+ }
+
+ VOID
+ NTAPI
+ PDEVOBJ_vCompletePDEV(
+ PPDEVOBJ ppdev)
+ {
+ /* Call the drivers DrvCompletePDEV function */
+ ppdev->pldev->pfn.CompletePDEV(ppdev->dhpdev, (HDEV)ppdev);
+ }
+
+ PSURFACE
+ NTAPI
+ PDEVOBJ_pSurface(
+ PPDEVOBJ ppdev)
+ {
+ HSURF hsurf;
+
+ /* Check if we already have a surface */
+ if (ppdev->pSurface)
+ {
+ /* Increment reference count */
+ GDIOBJ_IncrementShareCount(&ppdev->pSurface->BaseObject);
+ }
+ else
+ {
+ /* Call the drivers DrvEnableSurface */
+ hsurf = ppdev->pldev->pfn.EnableSurface(ppdev->dhpdev);
+
+ /* Lock the surface */
+ ppdev->pSurface = SURFACE_ShareLockSurface(hsurf);
+ }
+
+ DPRINT("PDEVOBJ_pSurface() returning %p\n", ppdev->pSurface);
+ return ppdev->pSurface;
+ }
+
+ PDEVMODEW
+ NTAPI
+ PDEVOBJ_pdmMatchDevMode(
+ PPDEVOBJ ppdev,
+ PDEVMODEW pdm)
+ {
+ PGRAPHICS_DEVICE pGraphicsDevice;
+ PDEVMODEW pdmCurrent;
+ INT i;
+ DWORD dwFields;
+
+ pGraphicsDevice = ppdev->pGraphicsDevice;
+
+ for (i = 0; i < pGraphicsDevice->cDevModes; i++)
+ {
+ pdmCurrent = pGraphicsDevice->pDevModeList[i].pdm;
+
+ /* Compare asked DEVMODE fields
+ * Only compare those that are valid in both DEVMODE structs */
+ dwFields = pdmCurrent->dmFields & pdm->dmFields ;
+ /* For now, we only need those */
+ if ((dwFields & DM_BITSPERPEL) &&
+ (pdmCurrent->dmBitsPerPel != pdm->dmBitsPerPel))
+ continue;
+ if ((dwFields & DM_PELSWIDTH) &&
+ (pdmCurrent->dmPelsWidth != pdm->dmPelsWidth))
+ continue;
+ if ((dwFields & DM_PELSHEIGHT) &&
+ (pdmCurrent->dmPelsHeight != pdm->dmPelsHeight))
+ continue;
+ if ((dwFields & DM_DISPLAYFREQUENCY) &&
+ (pdmCurrent->dmDisplayFrequency != pdm->dmDisplayFrequency))
+ continue;
+
+ /* Match! Return the DEVMODE */
+ return pdmCurrent;
+ }
+
+ /* Nothing found */
+ return NULL;
+ }
+
+ static
+ PPDEVOBJ
+ EngpCreatePDEV(
+ PUNICODE_STRING pustrDeviceName,
+ PDEVMODEW pdm)
+ {
+ PGRAPHICS_DEVICE pGraphicsDevice;
+ PPDEVOBJ ppdev;
+
+ /* Try to find the GRAPHICS_DEVICE */
+ if (pustrDeviceName)
+ {
+ pGraphicsDevice = EngpFindGraphicsDevice(pustrDeviceName, 0, 0);
+ if (!pGraphicsDevice)
+ {
+ DPRINT1("No GRAPHICS_DEVICE found for %ls!\n",
+ pustrDeviceName ? pustrDeviceName->Buffer : 0);
+ return NULL;
+ }
+ }
+ else
+ {
+ pGraphicsDevice = gpPrimaryGraphicsDevice;
+ }
+
+ /* Allocate a new PDEVOBJ */
+ ppdev = PDEVOBJ_AllocPDEV();
+ if (!ppdev)
+ {
+ DPRINT1("failed to allocate a PDEV\n");
+ return NULL;
+ }
+
+ /* If no DEVMODEW is given, ... */
+ if (!pdm)
+ {
+ /* ... use the device's default one */
+ pdm = pGraphicsDevice->pDevModeList[pGraphicsDevice->iDefaultMode].pdm;
+ DPRINT1("Using iDefaultMode = %ld\n", pGraphicsDevice->iDefaultMode);
+ }
+
+ /* Try to get a diplay driver */
+ ppdev->pldev = EngLoadImageEx(pdm->dmDeviceName, LDEV_DEVICE_DISPLAY);
+ if (!ppdev->pldev)
+ {
+ DPRINT1("Could not load display driver '%ls'\n",
+ pGraphicsDevice->pDiplayDrivers);
+ ExFreePoolWithTag(ppdev, GDITAG_PDEV);
+ return NULL;
+ }
+
+ /* Copy the function table */
+ ppdev->pfn = ppdev->pldev->pfn;
+
+ /* Set MovePointer function */
+ ppdev->pfnMovePointer = ppdev->pfn.MovePointer;
+ if (!ppdev->pfnMovePointer)
+ ppdev->pfnMovePointer = EngMovePointer;
+
+ ppdev->pGraphicsDevice = pGraphicsDevice;
+ ppdev->hsemDevLock = EngCreateSemaphore();
+ // Should we change the ative mode of pGraphicsDevice ?
+ ppdev->pdmwDev = PDEVOBJ_pdmMatchDevMode(ppdev, pdm) ;
+
+ /* FIXME! */
+ ppdev->flFlags = PDEV_DISPLAY;
+
+ /* HACK: Don't use the pointer */
+ ppdev->Pointer.Exclude.right = -1;
+
+ /* Call the driver to enable the PDEV */
+ if (!PDEVOBJ_bEnablePDEV(ppdev, pdm, NULL))
+ {
+ DPRINT1("Failed to enable PDEV!\n");
+ ASSERT(FALSE);
+ }
+
+ /* FIXME: this must be done in a better way */
+ pGraphicsDevice->StateFlags |= DISPLAY_DEVICE_ATTACHED_TO_DESKTOP;
+
+ /* Tell the driver that the PDEV is ready */
+ PDEVOBJ_vCompletePDEV(ppdev);
+
+ /* Return the PDEV */
+ return ppdev;
+ }
+
+ VOID
+ NTAPI
+ PDEVOBJ_vSwitchPdev(
+ PPDEVOBJ ppdev,
+ PPDEVOBJ ppdev2)
+ {
+ PDEVOBJ pdevTmp;
+ DWORD tmpStateFlags;
+
+ /* Exchange data */
+ pdevTmp = *ppdev;
+
+ /* Exchange driver functions */
+ ppdev->pfn = ppdev2->pfn;
+ ppdev2->pfn = pdevTmp.pfn;
+
+ /* Exchange LDEVs */
+ ppdev->pldev = ppdev2->pldev;
+ ppdev2->pldev = pdevTmp.pldev;
+
+ /* Exchange DHPDEV */
+ ppdev->dhpdev = ppdev2->dhpdev;
+ ppdev2->dhpdev = pdevTmp.dhpdev;
+
+ /* Exchange surfaces and associate them with their new PDEV */
+ ppdev->pSurface = ppdev2->pSurface;
+ ppdev2->pSurface = pdevTmp.pSurface;
+ ppdev->pSurface->SurfObj.hdev = (HDEV)ppdev;
+ ppdev2->pSurface->SurfObj.hdev = (HDEV)ppdev2;
+
+ /* Exchange devinfo */
+ ppdev->devinfo = ppdev2->devinfo;
+ ppdev2->devinfo = pdevTmp.devinfo;
+
+ /* Exchange gdiinfo */
+ ppdev->gdiinfo = ppdev2->gdiinfo;
+ ppdev2->gdiinfo = pdevTmp.gdiinfo;
+
+ /* Exchange DEVMODE */
+ ppdev->pdmwDev = ppdev2->pdmwDev;
+ ppdev2->pdmwDev = pdevTmp.pdmwDev;
+
+ /* Exchange state flags */
+ tmpStateFlags = ppdev->pGraphicsDevice->StateFlags;
+ ppdev->pGraphicsDevice->StateFlags = ppdev2->pGraphicsDevice->StateFlags;
+ ppdev2->pGraphicsDevice->StateFlags = tmpStateFlags;
+
+ /* Notify each driver instance of its new HDEV association */
+ ppdev->pfn.CompletePDEV(ppdev->dhpdev, (HDEV)ppdev);
+ ppdev2->pfn.CompletePDEV(ppdev2->dhpdev, (HDEV)ppdev2);
+ }
+
+
+ BOOL
+ NTAPI
+ PDEVOBJ_bSwitchMode(
+ PPDEVOBJ ppdev,
+ PDEVMODEW pdm)
+ {
+ UNICODE_STRING ustrDevice;
+ PPDEVOBJ ppdevTmp;
+ PSURFACE pSurface;
+ BOOL retval = FALSE;
+
+ /* Lock the PDEV */
+ EngAcquireSemaphore(ppdev->hsemDevLock);
+ /* And everything else */
+ EngAcquireSemaphore(ghsemPDEV);
+
+ DPRINT1("PDEVOBJ_bSwitchMode, ppdev = %p, pSurface = %p\n", ppdev, ppdev->pSurface);
+
+ // Lookup the GraphicsDevice + select DEVMODE
+ // pdm = PDEVOBJ_pdmMatchDevMode(ppdev, pdm);
+
+ /* 1. Temporarily disable the current PDEV */
+ if (!ppdev->pfn.AssertMode(ppdev->dhpdev, FALSE))
+ {
+ DPRINT1("DrvAssertMode failed\n");
+ goto leave;
+ }
+
+ /* 2. Create new PDEV */
+ RtlInitUnicodeString(&ustrDevice, ppdev->pGraphicsDevice->szWinDeviceName);
+ ppdevTmp = EngpCreatePDEV(&ustrDevice, pdm);
+ if (!ppdevTmp)
+ {
+ DPRINT1("Failed to create a new PDEV\n");
+ goto leave;
+ }
+
+ /* 3. Create a new surface */
+ pSurface = PDEVOBJ_pSurface(ppdevTmp);
+ if (!pSurface)
+ {
+ DPRINT1("DrvEnableSurface failed\n");
+ goto leave;
+ }
+
+ /* 4. Get DirectDraw information */
+ /* 5. Enable DirectDraw Not traced */
+ /* 6. Copy old PDEV state to new PDEV instance */
+
+ /* 7. Switch the PDEVs */
+ PDEVOBJ_vSwitchPdev(ppdev, ppdevTmp);
+
+ /* 8. Disable DirectDraw */
+
+ PDEVOBJ_vRelease(ppdevTmp);
+
+ /* Update primary display capabilities */
+ if(ppdev == gppdevPrimary)
+ {
+ PDEVOBJ_vGetDeviceCaps(ppdev, &GdiHandleTable->DevCaps);
+ }
+
+ /* Success! */
+ retval = TRUE;
+ leave:
+ /* Unlock PDEV */
+ EngReleaseSemaphore(ppdev->hsemDevLock);
+ EngReleaseSemaphore(ghsemPDEV);
+
+ DPRINT1("leave, ppdev = %p, pSurface = %p\n", ppdev, ppdev->pSurface);
+
+ return retval;
+ }
+
+
+ PPDEVOBJ
+ NTAPI
+ EngpGetPDEV(
+ PUNICODE_STRING pustrDeviceName)
+ {
+ UNICODE_STRING ustrCurrent;
+ PPDEVOBJ ppdev;
+ PGRAPHICS_DEVICE pGraphicsDevice;
+
+ /* Acquire PDEV lock */
+ EngAcquireSemaphore(ghsemPDEV);
+
+ /* If no device name is given, ... */
+ if (!pustrDeviceName && gppdevPrimary)
+ {
+ /* ... use the primary PDEV */
+ ppdev = gppdevPrimary;
+
+ /* Reference the pdev */
+ InterlockedIncrement(&ppdev->cPdevRefs);
+ goto leave;
+ }
+
+ /* Loop all present PDEVs */
+ for (ppdev = gppdevList; ppdev; ppdev = ppdev->ppdevNext)
+ {
+ /* Get a pointer to the GRAPHICS_DEVICE */
+ pGraphicsDevice = ppdev->pGraphicsDevice;
+
+ /* Compare the name */
+ RtlInitUnicodeString(&ustrCurrent, pGraphicsDevice->szWinDeviceName);
+ if (RtlEqualUnicodeString(pustrDeviceName, &ustrCurrent, FALSE))
+ {
+ /* Found! Reference the PDEV */
+ InterlockedIncrement(&ppdev->cPdevRefs);
+ break;
+ }
+ }
+
+ /* Did we find one? */
+ if (!ppdev)
+ {
+ /* No, create a new PDEV */
+ ppdev = EngpCreatePDEV(pustrDeviceName, NULL);
+ if (ppdev)
+ {
+ /* Insert the PDEV into the list */
+ ppdev->ppdevNext = gppdevList;
+ gppdevList = ppdev;
+
+ /* Set as primary PDEV, if we don't have one yet */
+ if (!gppdevPrimary)
+ {
+ gppdevPrimary = ppdev;
+ ppdev->pGraphicsDevice->StateFlags |= DISPLAY_DEVICE_PRIMARY_DEVICE;
+ }
+ }
+ }
+
+ leave:
+ /* Release PDEV lock */
+ EngReleaseSemaphore(ghsemPDEV);
+
+ return ppdev;
+ }
+
+ INT
+ NTAPI
+ PDEVOBJ_iGetColorManagementCaps(PPDEVOBJ ppdev)
+ {
+ INT ret = CM_NONE;
+
+ if (ppdev->flFlags & PDEV_DISPLAY)
+ {
+ if (ppdev->devinfo.iDitherFormat == BMF_8BPP ||
+ ppdev->devinfo.flGraphicsCaps2 & GCAPS2_CHANGEGAMMARAMP)
+ ret = CM_GAMMA_RAMP;
+ }
+
+ if (ppdev->devinfo.flGraphicsCaps & GCAPS_CMYKCOLOR)
+ ret |= CM_CMYK_COLOR;
+ if (ppdev->devinfo.flGraphicsCaps & GCAPS_ICM)
+ ret |= CM_DEVICE_ICM;
+
+ return ret;
+ }
+
+ VOID
+ NTAPI
+ PDEVOBJ_vGetDeviceCaps(
+ IN PPDEVOBJ ppdev,
+ OUT PDEVCAPS pDevCaps)
+ {
+ PGDIINFO pGdiInfo = &ppdev->gdiinfo;
+
+ pDevCaps->ulVersion = pGdiInfo->ulVersion;
+ pDevCaps->ulTechnology = pGdiInfo->ulTechnology;
+ pDevCaps->ulHorzSizeM = (pGdiInfo->ulHorzSize + 500) / 1000;
+ pDevCaps->ulVertSizeM = (pGdiInfo->ulVertSize + 500) / 1000;
+ pDevCaps->ulHorzSize = pGdiInfo->ulHorzSize;
+ pDevCaps->ulVertSize = pGdiInfo->ulVertSize;
+ pDevCaps->ulHorzRes = pGdiInfo->ulHorzRes;
+ pDevCaps->ulVertRes = pGdiInfo->ulVertRes;
+ pDevCaps->ulBitsPixel = pGdiInfo->cBitsPixel;
+ if (pDevCaps->ulBitsPixel == 15) pDevCaps->ulBitsPixel = 16;
+ pDevCaps->ulPlanes = pGdiInfo->cPlanes;
+ pDevCaps->ulNumPens = pGdiInfo->ulNumColors;
+ if (pDevCaps->ulNumPens != -1) pDevCaps->ulNumPens *= 5;
+ pDevCaps->ulNumFonts = 0; // PDEVOBJ_cFonts(ppdev);
+ pDevCaps->ulNumColors = pGdiInfo->ulNumColors;
+ pDevCaps->ulRasterCaps = pGdiInfo->flRaster;
+ pDevCaps->ulAspectX = pGdiInfo->ulAspectX;
+ pDevCaps->ulAspectY = pGdiInfo->ulAspectY;
+ pDevCaps->ulAspectXY = pGdiInfo->ulAspectXY;
+ pDevCaps->ulLogPixelsX = pGdiInfo->ulLogPixelsX;
+ pDevCaps->ulLogPixelsY = pGdiInfo->ulLogPixelsY;
+ pDevCaps->ulSizePalette = pGdiInfo->ulNumPalReg;
+ pDevCaps->ulColorRes = pGdiInfo->ulDACRed +
+ pGdiInfo->ulDACGreen +
+ pGdiInfo->ulDACBlue;
+ pDevCaps->ulPhysicalWidth = pGdiInfo->szlPhysSize.cx;
+ pDevCaps->ulPhysicalHeight = pGdiInfo->szlPhysSize.cy;
+ pDevCaps->ulPhysicalOffsetX = pGdiInfo->ptlPhysOffset.x;
+ pDevCaps->ulPhysicalOffsetY = pGdiInfo->ptlPhysOffset.y;
+ pDevCaps->ulTextCaps = pGdiInfo->flTextCaps;
+ pDevCaps->ulTextCaps |= (TC_SO_ABLE|TC_UA_ABLE|TC_CP_STROKE|TC_OP_STROKE|TC_OP_CHARACTER);
+ if (pGdiInfo->ulTechnology != DT_PLOTTER)
+ pDevCaps->ulTextCaps |= TC_VA_ABLE;
+ pDevCaps->ulVRefresh = pGdiInfo->ulVRefresh;
+ pDevCaps->ulDesktopHorzRes = pGdiInfo->ulHorzRes;
+ pDevCaps->ulDesktopVertRes = pGdiInfo->ulVertRes;
+ pDevCaps->ulBltAlignment = pGdiInfo->ulBltAlignment;
+ pDevCaps->ulPanningHorzRes = pGdiInfo->ulPanningHorzRes;
+ pDevCaps->ulPanningVertRes = pGdiInfo->ulPanningVertRes;
+ pDevCaps->xPanningAlignment = pGdiInfo->xPanningAlignment;
+ pDevCaps->yPanningAlignment = pGdiInfo->yPanningAlignment;
+ pDevCaps->ulShadeBlend = pGdiInfo->flShadeBlend;
+ pDevCaps->ulColorMgmtCaps = PDEVOBJ_iGetColorManagementCaps(ppdev);
+ }
+
+
+ /** Exported functions ********************************************************/
+
+ LPWSTR
+ APIENTRY
+ EngGetDriverName(IN HDEV hdev)
+ {
+ PPDEVOBJ ppdev = (PPDEVOBJ)hdev;
+ PLDEVOBJ pldev;
+
+ if (!hdev)
+ return NULL;
+
+ pldev = ppdev->pldev;
+ ASSERT(pldev);
+
+ if (!pldev->pGdiDriverInfo)
+ return NULL;
+
+ return pldev->pGdiDriverInfo->DriverName.Buffer;
+ }
+
+
+ INT
+ APIENTRY
+ NtGdiGetDeviceCaps(
+ HDC hdc,
+ INT Index)
+ {
+ PDC pdc;
+ DEVCAPS devcaps;
+
+ /* Lock the given DC */
+ pdc = DC_LockDc(hdc);
+ if (!pdc)
+ {
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ return 0;
+ }
+
+ /* Get the data */
+ PDEVOBJ_vGetDeviceCaps(pdc->ppdev, &devcaps);
+
+ /* Unlock the DC */
+ DC_UnlockDc(pdc);
+
+ /* Return capability */
+ switch (Index)
+ {
+ case DRIVERVERSION:
+ return devcaps.ulVersion;
+
+ case TECHNOLOGY:
+ return devcaps.ulTechnology;
+
+ case HORZSIZE:
+ return devcaps.ulHorzSize;
+
+ case VERTSIZE:
+ return devcaps.ulVertSize;
+
+ case HORZRES:
+ return devcaps.ulHorzRes;
+
+ case VERTRES:
+ return devcaps.ulVertRes;
+
+ case LOGPIXELSX:
+ return devcaps.ulLogPixelsX;
+
+ case LOGPIXELSY:
+ return devcaps.ulLogPixelsY;
+
+ case BITSPIXEL:
+ return devcaps.ulBitsPixel;
+
+ case PLANES:
+ return devcaps.ulPlanes;
+
+ case NUMBRUSHES:
+ return -1;
+
+ case NUMPENS:
+ return devcaps.ulNumPens;
+
+ case NUMFONTS:
+ return devcaps.ulNumFonts;
+
+ case NUMCOLORS:
+ return devcaps.ulNumColors;
+
+ case ASPECTX:
+ return devcaps.ulAspectX;
+
+ case ASPECTY:
+ return devcaps.ulAspectY;
+
+ case ASPECTXY:
+ return devcaps.ulAspectXY;
+
+ case CLIPCAPS:
+ return CP_RECTANGLE;
+
+ case SIZEPALETTE:
+ return devcaps.ulSizePalette;
+
+ case NUMRESERVED:
+ return 20;
+
+ case COLORRES:
+ return devcaps.ulColorRes;
+
+ case DESKTOPVERTRES:
+ return devcaps.ulVertRes;
+
+ case DESKTOPHORZRES:
+ return devcaps.ulHorzRes;
+
+ case BLTALIGNMENT:
+ return devcaps.ulBltAlignment;
+
+ case SHADEBLENDCAPS:
+ return devcaps.ulShadeBlend;
+
+ case COLORMGMTCAPS:
+ return devcaps.ulColorMgmtCaps;
+
+ case PHYSICALWIDTH:
+ return devcaps.ulPhysicalWidth;
+
+ case PHYSICALHEIGHT:
+ return devcaps.ulPhysicalHeight;
+
+ case PHYSICALOFFSETX:
+ return devcaps.ulPhysicalOffsetX;
+
+ case PHYSICALOFFSETY:
+ return devcaps.ulPhysicalOffsetY;
+
+ case VREFRESH:
+ return devcaps.ulVRefresh;
+
+ case RASTERCAPS:
+ return devcaps.ulRasterCaps;
+
+ case CURVECAPS:
+ return (CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES | CC_WIDE |
+ CC_STYLED | CC_WIDESTYLED | CC_INTERIORS | CC_ROUNDRECT);
+
+ case LINECAPS:
+ return (LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE |
+ LC_STYLED | LC_WIDESTYLED | LC_INTERIORS);
+
+ case POLYGONALCAPS:
+ return (PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON | PC_SCANLINE |
+ PC_WIDE | PC_STYLED | PC_WIDESTYLED | PC_INTERIORS);
+
+ case TEXTCAPS:
+ return devcaps.ulTextCaps;
+
+ case CAPS1:
+ case PDEVICESIZE:
+ case SCALINGFACTORX:
+ case SCALINGFACTORY:
+ default:
+ return 0;
+ }
+
+ return 0;
+ }
+
+
+ BOOL
+ APIENTRY
+ NtGdiGetDeviceCapsAll(
+ IN HDC hDC,
+ OUT PDEVCAPS pDevCaps)
+ {
+ PDC pdc;
+ DEVCAPS devcaps;
+ BOOL bResult = TRUE;
+
+ /* Lock the given DC */
+ pdc = DC_LockDc(hDC);
+ if (!pdc)
+ {
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ /* Get the data */
+ PDEVOBJ_vGetDeviceCaps(pdc->ppdev, &devcaps);
+
+ /* Unlock the DC */
+ DC_UnlockDc(pdc);
+
+ /* Copy data to caller */
+ _SEH2_TRY
+ {
+ ProbeForWrite(pDevCaps, sizeof(DEVCAPS), 1);
+ RtlCopyMemory(pDevCaps, &devcaps, sizeof(DEVCAPS));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastNtError(_SEH2_GetExceptionCode());
+ bResult = FALSE;
+ }
+ _SEH2_END;
+
+ return bResult;
+ }
+
+ DHPDEV
+ APIENTRY
+ NtGdiGetDhpdev(
+ IN HDEV hdev)
+ {
+ PPDEVOBJ ppdev;
+ DHPDEV dhpdev = NULL;
+
+ /* Check parameter */
+ if (!hdev || (PCHAR)hdev < (PCHAR)MmSystemRangeStart)
+ return NULL;
+
+ /* Lock PDEV list */
+ EngAcquireSemaphore(ghsemPDEV);
+
+ /* Walk through the list of PDEVs */
+ for (ppdev = gppdevList; ppdev; ppdev = ppdev->ppdevNext)
+ {
+ /* Compare with the given HDEV */
+ if (ppdev == hdev)
+ {
+ /* Found the PDEV! Get it's dhpdev and break */
+ dhpdev = ppdev->dhpdev;
+ break;
+ }
+ }
+
+ /* Unlock PDEV list */
+ EngReleaseSemaphore(ghsemPDEV);
+
+ return dhpdev;
+ }
+
+ PSIZEL
+ FASTCALL
+ PDEVOBJ_sizl(PPDEVOBJ ppdev, PSIZEL psizl)
+ {
+ if (ppdev->flFlags & PDEV_META_DEVICE)
+ {
+ psizl->cx = ppdev->ulHorzRes;
+ psizl->cy = ppdev->ulVertRes;
+ }
+ else
+ {
+ psizl->cx = ppdev->gdiinfo.ulHorzRes;
+ psizl->cy = ppdev->gdiinfo.ulVertRes;
+ }
+ return psizl;
+ }
--- /dev/null
+ /*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * PURPOSE: RLE compression
+ * FILE: subsystems/win32k/eng/rlecomp.c
+ * PROGRAMER: Jason Filby
+ */
+
+ #include <win32k.h>
+
+ #define NDEBUG
+ #include <debug.h>
+
+ enum Rle_EscapeCodes
+ {
+ RLE_EOL = 0, /* End of line */
+ RLE_END = 1, /* End of bitmap */
+ RLE_DELTA = 2 /* Delta */
+ };
+
+ VOID DecompressBitmap(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta, ULONG Format)
+ {
+ INT x = 0;
+ INT y = Size.cy - 1;
+ INT c;
+ INT length;
+ INT width;
+ INT height = Size.cy - 1;
+ BYTE *begin = CompressedBits;
+ BYTE *bits = CompressedBits;
+ BYTE *temp;
+ INT shift = 0;
+
+ if (Format == BMF_4RLE)
+ shift = 1;
+ else if(Format != BMF_8RLE)
+ return;
+
+ width = ((Size.cx + shift) >> shift);
+
+ _SEH2_TRY
+ {
+ while (y >= 0)
+ {
+ length = (*bits++) >> shift;
+ if (length)
+ {
+ c = *bits++;
+ while (length--)
+ {
+ if (x >= width) break;
+ temp = UncompressedBits + (((height - y) * Delta) + x);
+ x++;
+ *temp = c;
+ }
+ }
+ else
+ {
+ length = *bits++;
+ switch (length)
+ {
+ case RLE_EOL:
+ x = 0;
+ y--;
+ break;
+ case RLE_END:
+ _SEH2_YIELD(return);
+ case RLE_DELTA:
+ x += (*bits++) >> shift;
+ y -= (*bits++) >> shift;
+ break;
+ default:
+ length = length >> shift;
+ while (length--)
+ {
+ c = *bits++;
+ if (x < width)
+ {
+ temp = UncompressedBits + (((height - y) * Delta) + x);
+ x++;
+ *temp = c;
+ }
+ }
+ if ((bits - begin) & 1)
+ {
+ bits++;
+ }
+ }
+ }
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ DPRINT1("Decoding error\n");
+ }
+ _SEH2_END;
+
+ return;
+ }
IntGdiReleaseSemaphore ( hsem );
}
+ VOID
+ NTAPI
+ EngAcquireSemaphoreShared(
+ IN HSEMAPHORE hsem)
+ {
+ PTHREADINFO pti;
+
+ ASSERT(hsem);
+ ExEnterCriticalRegionAndAcquireResourceShared((PERESOURCE)hsem);
+ pti = PsGetThreadWin32Thread(PsGetCurrentThread());
+ if (pti) ++pti->dwEngAcquireCount;
+ }
+
/*
* @implemented
*/
/* No success yet */
ret = FALSE;
- SURFACE_LockBitmapBits(psurfDest);
- MouseSafetyOnDrawStart(psoDest, OutputRect.left, OutputRect.top,
- OutputRect.right, OutputRect.bottom);
if (UsesSource)
{
psurfSource = CONTAINING_RECORD(psoSource, SURFACE, SurfObj);
- if (psoSource != psoDest)
- {
- SURFACE_LockBitmapBits(psurfSource);
- }
- MouseSafetyOnDrawStart(psoSource, InputRect.left, InputRect.top,
- InputRect.right, InputRect.bottom);
}
/* Prepare color adjustment */
/* Call the driver's DrvStretchBlt if available */
- if (psurfDest->flHooks & HOOK_STRETCHBLTROP)
+ if (psurfDest->flags & HOOK_STRETCHBLTROP)
{
/* Drv->StretchBltROP (look at http://www.osronline.com/ddkx/graphics/ddifncs_0z3b.htm ) */
ret = GDIDEVFUNCS(psoDest).StretchBltROP(psoDest,
ROP);
}
- if (UsesSource)
- {
- MouseSafetyOnDrawEnd(psoSource);
- if (psoSource != psoDest)
- {
- SURFACE_UnlockBitmapBits(psurfSource);
- }
- }
- MouseSafetyOnDrawEnd(psoDest);
- SURFACE_UnlockBitmapBits(psurfDest);
-
return ret;
}
* PROJECT: ReactOS kernel
* PURPOSE: GDI Driver Surace Functions
* FILE: subsys/win32k/eng/surface.c
- * PROGRAMER: Jason Filby
+ * PROGRAMERS: Jason Filby
+ * Timo Kreuzer
* REVISION HISTORY:
* 3/7/1999: Created
* 9/11/2000: Updated to handle real pixel packed bitmaps (UPDATE TO DATE COMPLETED)
#define NDEBUG
#include <debug.h>
- enum Rle_EscapeCodes
- {
- RLE_EOL = 0, /* End of line */
- RLE_END = 1, /* End of bitmap */
- RLE_DELTA = 2 /* Delta */
- };
+ ULONG giUniqueSurface = 0;
- INT FASTCALL BitsPerFormat(ULONG Format)
+ UCHAR
+ gajBitsPerFormat[11] =
{
- switch (Format)
- {
- case BMF_1BPP:
- return 1;
-
- case BMF_4BPP:
- /* Fall through */
- case BMF_4RLE:
- return 4;
-
- case BMF_8BPP:
- /* Fall through */
- case BMF_8RLE:
- return 8;
-
- case BMF_16BPP:
- return 16;
-
- case BMF_24BPP:
- return 24;
+ 0, /* 0: unused */
+ 1, /* 1: BMF_1BPP */
+ 4, /* 2: BMF_4BPP */
+ 8, /* 3: BMF_8BPP */
+ 16, /* 4: BMF_16BPP */
+ 24, /* 5: BMF_24BPP */
+ 32, /* 6: BMF_32BPP */
+ 4, /* 7: BMF_4RLE */
+ 8, /* 8: BMF_8RLE */
+ 0, /* 9: BMF_JPEG */
+ 0, /* 10: BMF_PNG */
+ };
- case BMF_32BPP:
- return 32;
-
- default:
- return 0;
- }
- }
ULONG FASTCALL BitmapFormat(WORD Bits, DWORD Compression)
{
}
}
- BOOL INTERNAL_CALL
+ BOOL
+ INTERNAL_CALL
SURFACE_Cleanup(PVOID ObjectBody)
{
PSURFACE psurf = (PSURFACE)ObjectBody;
PVOID pvBits = psurf->SurfObj.pvBits;
+ NTSTATUS Status;
- /* If this is an API bitmap, free the bits */
- if (pvBits != NULL &&
- (psurf->flFlags & BITMAPOBJ_IS_APIBITMAP))
+ /* Check if the surface has bits */
+ if (pvBits)
{
- /* Check if we have a DIB section */
- if (psurf->hSecure)
+ /* Only bitmaps can have bits */
+ ASSERT(psurf->SurfObj.iType == STYPE_BITMAP);
+
+ /* Check if it is a DIB section */
+ if (psurf->hDIBSection)
{
- // FIXME: IMPLEMENT ME!
- // MmUnsecureVirtualMemory(psurf->hSecure);
- if (psurf->hDIBSection)
+ /* Unsecure the memory */
+ EngUnsecureMem(psurf->hSecure);
+
+ /* Calculate the real start of the section */
+ pvBits = (PVOID)((ULONG_PTR)pvBits - psurf->dwOffset);
+
+ /* Unmap the section */
+ Status = MmUnmapViewOfSection(PsGetCurrentProcess(), pvBits);
+ if (!NT_SUCCESS(Status))
{
- /* DIB was created from a section */
- NTSTATUS Status;
-
- pvBits = (PVOID)((ULONG_PTR)pvBits - psurf->dwOffset);
- Status = ZwUnmapViewOfSection(NtCurrentProcess(), pvBits);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Could not unmap section view!\n");
- // Should we BugCheck here?
- }
+ DPRINT1("Could not unmap section view!\n");
+ // Should we BugCheck here?
+ ASSERT(FALSE);
}
- else
+ }
+ else if (psurf->SurfObj.fjBitmap & BMF_USERMEM)
+ {
+ /* Bitmap was allocated from usermode memory */
+ EngFreeUserMem(pvBits);
+ }
+ else if (psurf->SurfObj.fjBitmap & BMF_KMSECTION)
+ {
+ /* Bitmap was allocated from a kernel section */
+ if (!EngFreeSectionMem(NULL, pvBits))
{
- /* DIB was allocated */
- EngFreeUserMem(pvBits);
+ DPRINT1("EngFreeSectionMem failed for %p!\n", pvBits);
+ // Should we BugCheck here?
+ ASSERT(FALSE);
}
}
- else
+ else if (psurf->SurfObj.fjBitmap & BMF_RLE_HACK)
{
- // FIXME: use TAG
- ExFreePool(psurf->SurfObj.pvBits);
+ /* HACK: Free RLE decompressed bits */
+ EngFreeMem(pvBits);
}
-
- if (psurf->hDIBPalette != NULL)
+ else
{
- GreDeleteObject(psurf->hDIBPalette);
+ /* There should be nothing to free */
+ ASSERT(psurf->SurfObj.fjBitmap & BMF_DONT_FREE);
}
}
- if (NULL != psurf->BitsLock)
- {
- ExFreePoolWithTag(psurf->BitsLock, TAG_SURFACE);
- psurf->BitsLock = NULL;
- }
-
- return TRUE;
- }
-
- BOOL INTERNAL_CALL
- SURFACE_InitBitsLock(PSURFACE psurf)
- {
- psurf->BitsLock = ExAllocatePoolWithTag(NonPagedPool,
- sizeof(FAST_MUTEX),
- TAG_SURFACE);
- if (NULL == psurf->BitsLock)
+ /* Free palette */
+ if(psurf->ppal)
{
- return FALSE;
+ PALETTE_ShareUnlockPalette(psurf->ppal);
}
- ExInitializeFastMutex(psurf->BitsLock);
-
return TRUE;
}
- void INTERNAL_CALL
- SURFACE_CleanupBitsLock(PSURFACE psurf)
- {
- if (NULL != psurf->BitsLock)
- {
- ExFreePoolWithTag(psurf->BitsLock, TAG_SURFACE);
- psurf->BitsLock = NULL;
- }
- }
-
- /*
- * @implemented
- */
- HBITMAP APIENTRY
- EngCreateDeviceBitmap(IN DHSURF dhsurf,
- IN SIZEL Size,
- IN ULONG Format)
+ PSURFACE
+ NTAPI
+ SURFACE_AllocSurface(
+ IN ULONG iType,
+ IN ULONG cx,
+ IN ULONG cy,
+ IN ULONG iFormat)
{
- HBITMAP NewBitmap;
+ PSURFACE psurf;
SURFOBJ *pso;
- NewBitmap = EngCreateBitmap(Size, DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(Format)), Format, 0, NULL);
- if (!NewBitmap)
- {
- DPRINT1("EngCreateBitmap failed\n");
- return 0;
- }
-
- pso = EngLockSurface((HSURF)NewBitmap);
- if (!pso)
+ /* Verify format */
+ if (iFormat < BMF_1BPP || iFormat > BMF_PNG)
{
- DPRINT1("EngLockSurface failed on newly created bitmap!\n");
- GreDeleteObject(NewBitmap);
+ DPRINT1("Invalid bitmap format: %ld\n", iFormat);
return NULL;
}
- pso->dhsurf = dhsurf;
- EngUnlockSurface(pso);
-
- return NewBitmap;
- }
+ /* Allocate a SURFACE object */
+ psurf = (PSURFACE)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_BITMAP);
- BOOL DecompressBitmap(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta, ULONG Format)
- {
- INT x = 0;
- INT y = Size.cy - 1;
- INT c;
- INT length;
- INT width;
- INT height = Size.cy - 1;
- BYTE *begin = CompressedBits;
- BYTE *bits = CompressedBits;
- BYTE *temp;
- INT shift = 0;
-
- if (Format == BMF_4RLE)
- shift = 1;
- else if(Format != BMF_8RLE)
- return FALSE;
-
- width = ((Size.cx + shift) >> shift);
-
- _SEH2_TRY
- {
- while (y >= 0)
- {
- length = (*bits++) >> shift;
- if (length)
- {
- c = *bits++;
- while (length--)
- {
- if (x >= width) break;
- temp = UncompressedBits + (((height - y) * Delta) + x);
- x++;
- *temp = c;
- }
- }
- else
- {
- length = *bits++;
- switch (length)
- {
- case RLE_EOL:
- x = 0;
- y--;
- break;
- case RLE_END:
- _SEH2_YIELD(return TRUE);
- case RLE_DELTA:
- x += (*bits++) >> shift;
- y -= (*bits++) >> shift;
- break;
- default:
- length = length >> shift;
- while (length--)
- {
- c = *bits++;
- if (x < width)
- {
- temp = UncompressedBits + (((height - y) * Delta) + x);
- x++;
- *temp = c;
- }
- }
- if ((bits - begin) & 1)
- {
- bits++;
- }
- }
- }
- }
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ if (psurf)
{
- DPRINT1("Decoding error\n");
- _SEH2_YIELD(return FALSE);
+ /* Initialize the basic fields */
+ pso = &psurf->SurfObj;
+ pso->hsurf = psurf->BaseObject.hHmgr;
+ pso->sizlBitmap.cx = cx;
+ pso->sizlBitmap.cy = cy;
+ pso->iBitmapFormat = iFormat;
+ pso->iType = iType;
+ pso->iUniq = InterlockedIncrement((PLONG)&giUniqueSurface);
+
+ /* Assign a default palette and increment its reference count */
+ psurf->ppal = appalSurfaceDefault[iFormat];
+ GDIOBJ_IncrementShareCount(&psurf->ppal->BaseObject);
}
- _SEH2_END;
- return TRUE;
+ return psurf;
}
- HBITMAP FASTCALL
- IntCreateBitmap(IN SIZEL Size,
- IN LONG Width,
- IN ULONG Format,
- IN ULONG Flags,
- IN PVOID Bits)
+ BOOL
+ NTAPI
+ SURFACE_bSetBitmapBits(
+ IN PSURFACE psurf,
+ IN USHORT fjBitmap,
+ IN ULONG ulWidth,
+ IN PVOID pvBits OPTIONAL)
{
- HBITMAP hbmp;
- SURFOBJ *pso;
- PSURFACE psurf;
- PVOID UncompressedBits;
- ULONG UncompressedFormat;
+ SURFOBJ *pso = &psurf->SurfObj;
+ PVOID pvSection;
+ UCHAR cBitsPixel;
- if (Format == 0)
- return 0;
+ /* Only bitmaps can have bits */
+ ASSERT(psurf->SurfObj.iType == STYPE_BITMAP);
- psurf = SURFACE_AllocSurfaceWithHandle();
- if (psurf == NULL)
- {
- return 0;
- }
- hbmp = psurf->BaseObject.hHmgr;
+ /* Get bits per pixel from the format */
+ cBitsPixel = gajBitsPerFormat[pso->iBitmapFormat];
- if (! SURFACE_InitBitsLock(psurf))
+ /* Is a width in bytes given? */
+ if (ulWidth)
{
- SURFACE_UnlockSurface(psurf);
- SURFACE_FreeSurfaceByHandle(hbmp);
- return 0;
+ /* Align the width (Windows compatibility, drivers expect that) */
+ ulWidth = WIDTH_BYTES_ALIGN32((ulWidth << 3) / cBitsPixel, cBitsPixel);
}
- pso = &psurf->SurfObj;
+ else
+ {
+ /* Calculate width from the bitmap width in pixels */
+ ulWidth = WIDTH_BYTES_ALIGN32(pso->sizlBitmap.cx, cBitsPixel);
+ }
- if (Format == BMF_4RLE)
- {
- pso->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(BMF_4BPP));
- pso->cjBits = pso->lDelta * Size.cy;
- UncompressedFormat = BMF_4BPP;
- UncompressedBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB);
- DecompressBitmap(Size, (BYTE *)Bits, (BYTE *)UncompressedBits, pso->lDelta, Format);
- }
- else if (Format == BMF_8RLE)
- {
- pso->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(BMF_8BPP));
- pso->cjBits = pso->lDelta * Size.cy;
- UncompressedFormat = BMF_8BPP;
- UncompressedBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB);
- DecompressBitmap(Size, (BYTE *)Bits, (BYTE *)UncompressedBits, pso->lDelta, Format);
- }
- else
- {
- pso->lDelta = abs(Width);
- pso->cjBits = pso->lDelta * Size.cy;
- UncompressedBits = Bits;
- UncompressedFormat = Format;
- }
+ /* Calculate the bitmap size in bytes */
+ pso->cjBits = ulWidth * pso->sizlBitmap.cy;
- if (UncompressedBits != NULL)
+ /* Did the caller provide bits? */
+ if (pvBits)
{
- pso->pvBits = UncompressedBits;
+ /* Yes, so let him free it */
+ fjBitmap |= BMF_DONT_FREE;
}
- else
+ else if (pso->cjBits)
{
- if (pso->cjBits == 0)
+ /* We must allocate memory, check what kind */
+ if (fjBitmap & BMF_USERMEM)
{
- pso->pvBits = NULL;
+ /* User mode memory was requested */
+ pvBits = EngAllocUserMem(pso->cjBits, 0);
}
else
{
- if (0 != (Flags & BMF_USERMEM))
- {
- pso->pvBits = EngAllocUserMem(pso->cjBits, 0);
- }
- else
- {
- pso->pvBits = EngAllocMem(0 != (Flags & BMF_NOZEROINIT) ?
- 0 : FL_ZERO_MEMORY,
- pso->cjBits, TAG_DIB);
- }
- if (pso->pvBits == NULL)
- {
- SURFACE_UnlockSurface(psurf);
- SURFACE_FreeSurfaceByHandle(hbmp);
- SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
- return 0;
- }
+ /* Use a kernel mode section */
+ fjBitmap |= BMF_KMSECTION;
+ pvBits = EngAllocSectionMem(&pvSection,
+ (fjBitmap & BMF_NOZEROINIT) ?
+ 0 : FL_ZERO_MEMORY,
+ pso->cjBits, TAG_DIB);
+
+ /* Free the section already, but keep the mapping */
+ if (pvBits) EngFreeSectionMem(pvSection, NULL);
}
+
+ /* Check for failure */
+ if (!pvBits) return FALSE;
}
- if (0 == (Flags & BMF_TOPDOWN))
+ /* Set pvBits, pvScan0 and lDelta */
+ pso->pvBits = pvBits;
+ if (fjBitmap & BMF_TOPDOWN)
{
- pso->pvScan0 = (PVOID)((ULONG_PTR)pso->pvBits + pso->cjBits - pso->lDelta);
- pso->lDelta = - pso->lDelta;
+ /* Topdown is the normal way */
+ pso->pvScan0 = pso->pvBits;
+ pso->lDelta = ulWidth;
}
else
{
- pso->pvScan0 = pso->pvBits;
+ /* Inversed bitmap (bottom up) */
+ pso->pvScan0 = (PVOID)((ULONG_PTR)pso->pvBits + pso->cjBits - ulWidth);
+ pso->lDelta = -ulWidth;
}
- pso->dhsurf = 0; /* device managed surface */
- pso->hsurf = (HSURF)hbmp;
- pso->dhpdev = NULL;
- pso->hdev = NULL;
- pso->sizlBitmap = Size;
- pso->iBitmapFormat = UncompressedFormat;
- pso->iType = STYPE_BITMAP;
- pso->fjBitmap = Flags & (BMF_TOPDOWN | BMF_NOZEROINIT);
- pso->iUniq = 0;
-
- psurf->flHooks = 0;
- psurf->flFlags = 0;
- psurf->dimension.cx = 0;
- psurf->dimension.cy = 0;
-
- psurf->hSecure = NULL;
- psurf->hDIBSection = NULL;
-
- SURFACE_UnlockSurface(psurf);
+ pso->fjBitmap = fjBitmap;
- return hbmp;
+ /* Success */
+ return TRUE;
}
- /* Name gleaned from C++ symbol information for SURFMEM::bInitDIB */
- typedef struct _DEVBITMAPINFO
- {
- ULONG Format;
- ULONG Width;
- ULONG Height;
- ULONG Flags;
- ULONG Size;
- } DEVBITMAPINFO, *PDEVBITMAPINFO;
-
- SURFOBJ*
- FASTCALL
- SURFMEM_bCreateDib(IN PDEVBITMAPINFO BitmapInfo,
- IN PVOID Bits)
+ HBITMAP
+ APIENTRY
+ EngCreateBitmap(
+ IN SIZEL sizl,
+ IN LONG lWidth,
+ IN ULONG iFormat,
+ IN ULONG fl,
+ IN PVOID pvBits)
{
- BOOLEAN Compressed = FALSE;
- ULONG ScanLine = 0; // Compiler is dumb
- ULONG Size;
- SURFOBJ *pso;
PSURFACE psurf;
- SIZEL LocalSize;
- BOOLEAN AllocatedLocally = FALSE;
- PVOID DecompressedBits = NULL;
-
- /*
- * First, check the format so we can get the aligned scanline width.
- * RLE and the newer fancy-smanshy JPG/PNG support do NOT have scanlines
- * since they are compressed surfaces!
- */
- switch (BitmapInfo->Format)
- {
- case BMF_1BPP:
- ScanLine = ((BitmapInfo->Width + 31) & ~31) >> 3;
- break;
-
- case BMF_4BPP:
- ScanLine = ((BitmapInfo->Width + 7) & ~7) >> 1;
- break;
-
- case BMF_8BPP:
- ScanLine = (BitmapInfo->Width + 3) & ~3;
- break;
-
- case BMF_16BPP:
- ScanLine = ((BitmapInfo->Width + 1) & ~1) << 1;
- break;
-
- case BMF_24BPP:
- ScanLine = ((BitmapInfo->Width * 3) + 3) & ~3;
- break;
-
- case BMF_32BPP:
- ScanLine = BitmapInfo->Width << 2;
- break;
-
- case BMF_8RLE:
- ScanLine = (BitmapInfo->Width + 3) & ~3;
- Compressed = TRUE;
- break;
- case BMF_4RLE:
- ScanLine = ((BitmapInfo->Width + 7) & ~7) >> 1;
- Compressed = TRUE;
- break;
-
- case BMF_JPEG:
- case BMF_PNG:
- ASSERT(FALSE); // ENGDDI shouldn't be creating PNGs for drivers ;-)
- DPRINT1("No support for JPEG and PNG formats\n");
- return NULL;
-
- default:
- DPRINT1("Invalid bitmap format\n");
- return NULL;
- }
-
- /* Save local bitmap size */
- LocalSize.cy = BitmapInfo->Height;
- LocalSize.cx = BitmapInfo->Width;
-
- /* Does the device manage its own surface? */
- if (!Bits)
- {
- /* We need to allocate bits for the caller, figure out the size */
- if (Compressed)
- {
- /* Note: we should not be seeing this scenario from ENGDDI */
- ASSERT(FALSE);
- DPRINT1("RLE compressed bitmap requested with no valid bitmap bits\n");
- return NULL;
- }
- else
- {
- /* The height times the bytes for each scanline */
- Size = BitmapInfo->Height * ScanLine;
- }
-
- if (Size)
- {
- /* Check for allocation flag */
- if (BitmapInfo->Flags & BMF_USERMEM)
- {
- /* Get the bits from user-mode memory */
- Bits = EngAllocUserMem(Size, 'mbuG');
- }
- else
- {
- /* Get kernel bits (zeroed out if requested) */
- Bits = EngAllocMem((BitmapInfo->Flags & BMF_NOZEROINIT) ? 0 : FL_ZERO_MEMORY,
- Size,
- TAG_DIB);
- }
- AllocatedLocally = TRUE;
- /* Bail out if that failed */
- if (!Bits) return NULL;
- }
- }
- else
- {
- /* Should not have asked for user memory */
- ASSERT((BitmapInfo->Flags & BMF_USERMEM) == 0);
-
- if (Compressed)
- {
- DecompressedBits = EngAllocMem(FL_ZERO_MEMORY, BitmapInfo->Height * ScanLine, TAG_DIB);
-
- if(!DecompressedBits)
- return NULL;
-
- if(!DecompressBitmap(LocalSize, (BYTE *)Bits, (BYTE *)DecompressedBits, ScanLine, BitmapInfo->Format))
- {
- EngFreeMem(DecompressedBits);
- return NULL;
- }
-
- BitmapInfo->Format = (BitmapInfo->Format == BMF_4RLE) ? BMF_4BPP : BMF_8BPP;
- }
- }
+ HBITMAP hbmp;
- /* Allocate the actual surface object structure */
- psurf = SURFACE_AllocSurfaceWithHandle();
+ /* Allocate a surface */
+ psurf = SURFACE_AllocSurface(STYPE_BITMAP, sizl.cx, sizl.cy, iFormat);
if (!psurf)
{
- if(Bits && AllocatedLocally)
- {
- if(BitmapInfo->Flags & BMF_USERMEM)
- EngFreeUserMem(Bits);
- else
- EngFreeMem(Bits);
- }
- if (DecompressedBits)
- EngFreeMem(DecompressedBits);
+ DPRINT1("SURFACE_AllocSurface failed.\n");
return NULL;
}
- /* Lock down the surface */
- if (!SURFACE_InitBitsLock(psurf))
+ /* Get the handle for the bitmap */
+ hbmp = (HBITMAP)psurf->SurfObj.hsurf;
+
+ /* Set the bitmap bits */
+ if (!SURFACE_bSetBitmapBits(psurf, fl, lWidth, pvBits))
{
/* Bail out if that failed */
- SURFACE_UnlockSurface(psurf);
- SURFACE_FreeSurfaceByHandle(psurf->BaseObject.hHmgr);
+ DPRINT1("SURFACE_bSetBitmapBits failed.\n");
+ SURFACE_FreeSurfaceByHandle(hbmp);
return NULL;
}
- /* We should now have our surface object */
- pso = &psurf->SurfObj;
+ /* Set public ownership */
+ GDIOBJ_SetOwnership(hbmp, NULL);
- /* Save format and flags */
- pso->iBitmapFormat = BitmapInfo->Format;
- pso->fjBitmap = BitmapInfo->Flags & (BMF_TOPDOWN | BMF_UMPDMEM | BMF_USERMEM);
-
- /* Save size and type */
- pso->sizlBitmap = LocalSize;
- pso->iType = STYPE_BITMAP;
-
- /* Device-managed surface, no flags or dimension */
- pso->dhsurf = 0;
- pso->dhpdev = NULL;
- pso->hdev = NULL;
- psurf->flFlags = 0;
- psurf->dimension.cx = 0;
- psurf->dimension.cy = 0;
- psurf->hSecure = NULL;
- psurf->hDIBSection = NULL;
- psurf->flHooks = 0;
-
- /* Set bits */
- if(Compressed)
- pso->pvBits = DecompressedBits;
- else
- pso->pvBits = Bits;
-
- /* Number of bits is based on the height times the scanline */
- pso->cjBits = BitmapInfo->Height * ScanLine;
- if (BitmapInfo->Flags & BMF_TOPDOWN)
- {
- /* For topdown, the base address starts with the bits */
- pso->pvScan0 = pso->pvBits;
- pso->lDelta = ScanLine;
- }
- else
- {
- /* Otherwise we start with the end and go up */
- pso->pvScan0 = (PVOID)((ULONG_PTR)pso->pvBits + pso->cjBits - ScanLine);
- pso->lDelta = -ScanLine;
- }
-
- /* Finally set the handle and uniq */
- pso->hsurf = (HSURF)psurf->BaseObject.hHmgr;
- pso->iUniq = 0;
-
- /* Unlock and return the surface */
+ /* Unlock the surface and return */
SURFACE_UnlockSurface(psurf);
- return pso;
+ return hbmp;
}
/*
*/
HBITMAP
APIENTRY
- EngCreateBitmap(IN SIZEL Size,
- IN LONG Width,
- IN ULONG Format,
- IN ULONG Flags,
- IN PVOID Bits)
+ EngCreateDeviceBitmap(
+ IN DHSURF dhsurf,
+ IN SIZEL sizl,
+ IN ULONG iFormat)
{
- SURFOBJ* Surface;
- DEVBITMAPINFO BitmapInfo;
-
- /* Capture the parameters */
- BitmapInfo.Format = Format;
- BitmapInfo.Width = Size.cx;
- BitmapInfo.Height = Size.cy;
- BitmapInfo.Flags = Flags;
-
- /*
- * If the display driver supports framebuffer access, use the scanline width
- * to determine the actual width of the bitmap, and convert it to pels instead
- * of bytes.
- */
- if ((Bits) && (Width))
+ PSURFACE psurf;
+ HBITMAP hbmp;
+
+ /* Allocate a surface */
+ psurf = SURFACE_AllocSurface(STYPE_DEVBITMAP, sizl.cx, sizl.cy, iFormat);
+ if (!psurf)
{
- switch (BitmapInfo.Format)
- {
- /* Do the conversion for each bit depth we support */
- case BMF_1BPP:
- BitmapInfo.Width = Width * 8;
- break;
- case BMF_4BPP:
- BitmapInfo.Width = Width * 2;
- break;
- case BMF_8BPP:
- BitmapInfo.Width = Width;
- break;
- case BMF_16BPP:
- BitmapInfo.Width = Width / 2;
- break;
- case BMF_24BPP:
- BitmapInfo.Width = Width / 3;
- break;
- case BMF_32BPP:
- BitmapInfo.Width = Width / 4;
- break;
- }
+ return 0;
}
-
- /* Now create the surface */
- Surface = SURFMEM_bCreateDib(&BitmapInfo, Bits);
- if (!Surface) return 0;
-
- /* Set public ownership and reutrn the handle */
- GDIOBJ_SetOwnership(Surface->hsurf, NULL);
- return Surface->hsurf;
+
+ /* Set the device handle */
+ psurf->SurfObj.dhsurf = dhsurf;
+
+ /* Get the handle for the bitmap */
+ hbmp = (HBITMAP)psurf->SurfObj.hsurf;
+
+ /* Set public ownership */
+ GDIOBJ_SetOwnership(hbmp, NULL);
+
+ /* Unlock the surface and return */
+ SURFACE_UnlockSurface(psurf);
+ return hbmp;
}
- /*
- * @unimplemented
- */
- HSURF APIENTRY
- EngCreateDeviceSurface(IN DHSURF dhsurf,
- IN SIZEL Size,
- IN ULONG Format)
+ HSURF
+ APIENTRY
+ EngCreateDeviceSurface(
+ IN DHSURF dhsurf,
+ IN SIZEL sizl,
+ IN ULONG iFormat)
{
- HSURF hsurf;
- SURFOBJ *pso;
PSURFACE psurf;
+ HSURF hsurf;
- psurf = SURFACE_AllocSurfaceWithHandle();
+ /* Allocate a surface */
+ psurf = SURFACE_AllocSurface(STYPE_DEVICE, sizl.cx, sizl.cy, iFormat);
if (!psurf)
{
return 0;
}
- hsurf = psurf->BaseObject.hHmgr;
- GDIOBJ_SetOwnership(hsurf, NULL);
+ /* Set the device handle */
+ psurf->SurfObj.dhsurf = dhsurf;
- if (!SURFACE_InitBitsLock(psurf))
- {
- SURFACE_UnlockSurface(psurf);
- SURFACE_FreeSurfaceByHandle(hsurf);
- return 0;
- }
- pso = &psurf->SurfObj;
+ /* Get the handle for the surface */
+ hsurf = psurf->SurfObj.hsurf;
- pso->dhsurf = dhsurf;
- pso->hsurf = hsurf;
- pso->sizlBitmap = Size;
- pso->iBitmapFormat = Format;
- pso->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(Format));
- pso->iType = STYPE_DEVICE;
- pso->iUniq = 0;
-
- psurf->flHooks = 0;
+ /* Set public ownership */
+ GDIOBJ_SetOwnership(hsurf, NULL);
+ /* Unlock the surface and return */
SURFACE_UnlockSurface(psurf);
-
return hsurf;
}
- /*
- * @implemented
- */
BOOL
APIENTRY
EngAssociateSurface(
pso->dhpdev = ppdev->dhpdev;
/* Hook up specified functions */
- psurf->flHooks = flHooks;
+ psurf->flags &= ~HOOK_FLAGS;
+ psurf->flags |= (flHooks & HOOK_FLAGS);
+
+ /* Get palette */
+ psurf->ppal = PALETTE_ShareLockPalette(ppdev->devinfo.hpalDefault);
SURFACE_UnlockSurface(psurf);
return TRUE;
}
- /*
- * @implemented
- */
- BOOL APIENTRY
+ BOOL
+ APIENTRY
EngModifySurface(
IN HSURF hsurf,
IN HDEV hdev,
pso->dhpdev = ppdev->dhpdev;
/* Hook up specified functions */
- psurf->flHooks = flHooks;
+ psurf->flags &= ~HOOK_FLAGS;
+ psurf->flags |= (flHooks & HOOK_FLAGS);
+
+ /* Get palette */
+ psurf->ppal = PALETTE_ShareLockPalette(ppdev->devinfo.hpalDefault);
SURFACE_UnlockSurface(psurf);
return TRUE;
}
- /*
- * @implemented
- */
- BOOL APIENTRY
+
+ BOOL
+ APIENTRY
EngDeleteSurface(IN HSURF hsurf)
{
GDIOBJ_SetOwnership(hsurf, PsGetCurrentProcess());
return TRUE;
}
- /*
- * @implemented
- */
- BOOL APIENTRY
- EngEraseSurface(SURFOBJ *pso,
- RECTL *Rect,
- ULONG iColor)
+ BOOL
+ APIENTRY
+ EngEraseSurface(
+ SURFOBJ *pso,
+ RECTL *prcl,
+ ULONG iColor)
{
ASSERT(pso);
- ASSERT(Rect);
- return FillSolid(pso, Rect, iColor);
+ ASSERT(prcl);
+ return FillSolid(pso, prcl, iColor);
}
/*
}
- /*
- * @implemented
- */
- SURFOBJ * APIENTRY
+ SURFOBJ *
+ APIENTRY
EngLockSurface(IN HSURF hsurf)
{
SURFACE *psurf = GDIOBJ_ShareLockObj(hsurf, GDI_OBJECT_TYPE_BITMAP);
return NULL;
}
-
- /*
- * @implemented
- */
- VOID APIENTRY
+ VOID
+ APIENTRY
NtGdiEngUnlockSurface(IN SURFOBJ *pso)
{
EngUnlockSurface(pso);
}
- /*
- * @implemented
- */
- VOID APIENTRY
+ VOID
+ APIENTRY
EngUnlockSurface(IN SURFOBJ *pso)
{
if (pso != NULL)
}
}
-
/* EOF */
OutputRect.top = DestRect->bottom;
OutputRect.bottom = DestRect->top;
}
-
+
if(Clip)
{
if(OutputRect.left < Clip->rclBounds.left)
OutputRect = InputClippedRect;
}
- if(psoSource != psoDest)
- {
- SURFACE_LockBitmapBits(psurfSource);
- MouseSafetyOnDrawStart(psoSource, InputRect.left, InputRect.top,
- InputRect.right, InputRect.bottom);
- }
- SURFACE_LockBitmapBits(psurfDest);
- MouseSafetyOnDrawStart(psoDest, OutputRect.left, OutputRect.top,
- OutputRect.right, OutputRect.bottom);
-
- if(psurfDest->flHooks & HOOK_TRANSPARENTBLT)
+ if(psurfDest->flags & HOOK_TRANSPARENTBLT)
{
Ret = GDIDEVFUNCS(psoDest).TransparentBlt(
psoDest, psoSource, Clip, ColorTranslation, &OutputRect,
&OutputRect, &InputRect, iTransColor, Reserved);
}
- MouseSafetyOnDrawEnd(psoDest);
- SURFACE_UnlockBitmapBits(psurfDest);
- if(psoSource != psoDest)
- {
- MouseSafetyOnDrawEnd(psoSource);
- SURFACE_UnlockBitmapBits(psurfSource);
- }
-
return Ret;
}
{
ULONG iNewColor;
- /* Copy green and alpha */
+ /* Copy green */
iNewColor = iColor & 0xff00ff00;
/* Mask red and blue */
EXLATEOBJ_vInitTrivial(pexlo);
if (ppalDst == ppalSrc || !ppalSrc || !ppalDst ||
- ((ppalDst->Mode == PAL_RGB || ppalDst->Mode == PAL_BGR) &&
- ppalDst->Mode == ppalSrc->Mode))
+ ((ppalDst->flFlags == PAL_RGB || ppalDst->flFlags == PAL_BGR) &&
+ ppalDst->flFlags == ppalSrc->flFlags))
{
return;
}
pexlo->ppalSrc = ppalSrc;
pexlo->ppalDst = ppalDst;
- pexlo->xlo.iSrcType = ppalSrc->Mode;
- pexlo->xlo.iDstType = ppalDst->Mode;
+ pexlo->xlo.iSrcType = ppalSrc->flFlags;
+ pexlo->xlo.iDstType = ppalDst->flFlags;
/* Chack if both of the pallettes are indexed */
- if (!(ppalSrc->Mode & PAL_INDEXED) || !(ppalDst->Mode & PAL_INDEXED))
+ if (!(ppalSrc->flFlags & PAL_INDEXED) || !(ppalDst->flFlags & PAL_INDEXED))
{
/* At least one palette is not indexed, calculate shifts/masks */
ULONG aulMasksSrc[3], aulMasksDst[3];
pexlo->ulBlueShift = CalculateShift(aulMasksSrc[2], aulMasksDst[2]);
}
- if (ppalSrc->Mode & PAL_MONOCHROME)
+ if (ppalSrc->flFlags & PAL_MONOCHROME)
{
/* This is a monochrome palette */
- if (!(ppalDst->Mode & PAL_MONOCHROME))
+ if (!(ppalDst->flFlags & PAL_MONOCHROME))
{
/* Mono to color, use the dest DC's fore and back color */
pexlo->pfnXlate = EXLATEOBJ_iXlateTable;
PALETTE_ulGetNearestIndex(ppalDst, crDstBackColor);
}
}
- else if (ppalDst->Mode & PAL_MONOCHROME)
+ else if (ppalDst->flFlags & PAL_MONOCHROME)
{
pexlo->pfnXlate = EXLATEOBJ_iXlateToMono;
pexlo->xlo.flXlate |= XO_TO_MONO;
pexlo->xlo.cEntries = 1;
- if (ppalSrc->Mode & PAL_INDEXED)
+ if (ppalSrc->flFlags & PAL_INDEXED)
{
pexlo->aulXlate[0] =
PALETTE_ulGetNearestPaletteIndex(ppalSrc, crSrcBackColor);
}
- else if (ppalSrc->Mode & PAL_BGR)
+ else if (ppalSrc->flFlags & PAL_BGR)
{
pexlo->aulXlate[0] = crSrcBackColor;
}
- else if (ppalSrc->Mode & PAL_RGB)
+ else if (ppalSrc->flFlags & PAL_RGB)
{
pexlo->aulXlate[0] = RGB(GetBValue(crSrcBackColor),
GetGValue(crSrcBackColor),
GetRValue(crSrcBackColor));
}
- else if (ppalSrc->Mode & PAL_BITFIELDS)
+ else if (ppalSrc->flFlags & PAL_BITFIELDS)
{
PALETTE_vGetBitMasks(ppalSrc, &pexlo->ulRedMask);
pexlo->ulRedShift = CalculateShift(0xFF, pexlo->ulRedMask);
pexlo->aulXlate[0] = EXLATEOBJ_iXlateShiftAndMask(pexlo, crSrcBackColor);
}
}
- else if (ppalSrc->Mode & PAL_INDEXED)
+ else if (ppalSrc->flFlags & PAL_INDEXED)
{
cEntries = ppalSrc->NumColors;
pexlo->xlo.cEntries = cEntries;
pexlo->pfnXlate = EXLATEOBJ_iXlateTable;
- if (ppalDst->Mode & PAL_INDEXED)
+ if (ppalDst->flFlags & PAL_INDEXED)
{
pexlo->xlo.flXlate |= XO_TABLE;
}
}
}
- else if (ppalSrc->Mode & PAL_RGB)
+ else if (ppalSrc->flFlags & PAL_RGB)
{
- if (ppalDst->Mode & PAL_INDEXED)
+ if (ppalDst->flFlags & PAL_INDEXED)
pexlo->pfnXlate = EXLATEOBJ_iXlateRGBtoPal;
- else if (ppalDst->Mode & PAL_BGR)
+ else if (ppalDst->flFlags & PAL_BGR)
pexlo->pfnXlate = EXLATEOBJ_iXlateRGBtoBGR;
- else if (ppalDst->Mode & PAL_RGB16_555)
+ else if (ppalDst->flFlags & PAL_RGB16_555)
pexlo->pfnXlate = EXLATEOBJ_iXlateRGBto555;
- else if (ppalDst->Mode & PAL_RGB16_565)
+ else if (ppalDst->flFlags & PAL_RGB16_565)
pexlo->pfnXlate = EXLATEOBJ_iXlateRGBto565;
- else if (ppalDst->Mode & PAL_BITFIELDS)
+ else if (ppalDst->flFlags & PAL_BITFIELDS)
pexlo->pfnXlate = EXLATEOBJ_iXlateShiftAndMask;
}
- else if (ppalSrc->Mode & PAL_BGR)
+ else if (ppalSrc->flFlags & PAL_BGR)
{
- if (ppalDst->Mode & PAL_INDEXED)
+ if (ppalDst->flFlags & PAL_INDEXED)
pexlo->pfnXlate = EXLATEOBJ_iXlateBitfieldsToPal;
- else if (ppalDst->Mode & PAL_RGB)
+ else if (ppalDst->flFlags & PAL_RGB)
/* The inverse function works the same */
pexlo->pfnXlate = EXLATEOBJ_iXlateRGBtoBGR;
- else if (ppalDst->Mode & PAL_RGB16_555)
+ else if (ppalDst->flFlags & PAL_RGB16_555)
pexlo->pfnXlate = EXLATEOBJ_iXlateBGRto555;
- else if (ppalDst->Mode & PAL_RGB16_565)
+ else if (ppalDst->flFlags & PAL_RGB16_565)
pexlo->pfnXlate = EXLATEOBJ_iXlateBGRto565;
- else if (ppalDst->Mode & PAL_BITFIELDS)
+ else if (ppalDst->flFlags & PAL_BITFIELDS)
pexlo->pfnXlate = EXLATEOBJ_iXlateShiftAndMask;
}
- else if (ppalSrc->Mode & PAL_RGB16_555)
+ else if (ppalSrc->flFlags & PAL_RGB16_555)
{
- if (ppalDst->Mode & PAL_INDEXED)
+ if (ppalDst->flFlags & PAL_INDEXED)
pexlo->pfnXlate = EXLATEOBJ_iXlate555toPal;
- else if (ppalDst->Mode & PAL_RGB)
+ else if (ppalDst->flFlags & PAL_RGB)
pexlo->pfnXlate = EXLATEOBJ_iXlate555toRGB;
- else if (ppalDst->Mode & PAL_BGR)
+ else if (ppalDst->flFlags & PAL_BGR)
pexlo->pfnXlate = EXLATEOBJ_iXlate555toBGR;
- else if (ppalDst->Mode & PAL_RGB16_565)
+ else if (ppalDst->flFlags & PAL_RGB16_565)
pexlo->pfnXlate = EXLATEOBJ_iXlate555to565;
- else if (ppalDst->Mode & PAL_BITFIELDS)
+ else if (ppalDst->flFlags & PAL_BITFIELDS)
pexlo->pfnXlate = EXLATEOBJ_iXlateShiftAndMask;
}
- else if (ppalSrc->Mode & PAL_RGB16_565)
+ else if (ppalSrc->flFlags & PAL_RGB16_565)
{
- if (ppalDst->Mode & PAL_INDEXED)
+ if (ppalDst->flFlags & PAL_INDEXED)
pexlo->pfnXlate = EXLATEOBJ_iXlate565toPal;
- else if (ppalDst->Mode & PAL_RGB)
+ else if (ppalDst->flFlags & PAL_RGB)
pexlo->pfnXlate = EXLATEOBJ_iXlate565toRGB;
- else if (ppalDst->Mode & PAL_BGR)
+ else if (ppalDst->flFlags & PAL_BGR)
pexlo->pfnXlate = EXLATEOBJ_iXlate565toBGR;
- else if (ppalDst->Mode & PAL_RGB16_555)
+ else if (ppalDst->flFlags & PAL_RGB16_555)
pexlo->pfnXlate = EXLATEOBJ_iXlate565to555;
- else if (ppalDst->Mode & PAL_BITFIELDS)
+ else if (ppalDst->flFlags & PAL_BITFIELDS)
pexlo->pfnXlate = EXLATEOBJ_iXlateShiftAndMask;
}
- else if (ppalSrc->Mode & PAL_BITFIELDS)
+ else if (ppalSrc->flFlags & PAL_BITFIELDS)
{
- if (ppalDst->Mode & PAL_INDEXED)
+ if (ppalDst->flFlags & PAL_INDEXED)
pexlo->pfnXlate = EXLATEOBJ_iXlateBitfieldsToPal;
else
pexlo->pfnXlate = EXLATEOBJ_iXlateShiftAndMask;
PDC pdcDst)
{
PSURFACE psurfDst, psurfSrc;
- HPALETTE hpalSrc, hpalDst;
- PPALETTE ppalSrc, ppalDst, ppalDstDc;
-
- DPRINT("Enter EXLATEOBJ_vInitXlateFromDCs\n");
-
- /* Do basic init */
- EXLATEOBJ_vInitTrivial(pexlo);
psurfDst = pdcDst->dclevel.pSurface;
psurfSrc = pdcSrc->dclevel.pSurface;
+ /* Check for trivial color translation */
if (psurfDst == psurfSrc)
{
+ EXLATEOBJ_vInitTrivial(pexlo);
return;
}
- hpalSrc = psurfSrc->hDIBPalette;
- if (!hpalSrc)
- hpalSrc = pPrimarySurface->devinfo.hpalDefault;
-
- ppalSrc = PALETTE_ShareLockPalette(hpalSrc);
- if (!ppalSrc)
- return;
-
- hpalDst = psurfDst->hDIBPalette;
- if (!hpalDst) hpalDst = pPrimarySurface->devinfo.hpalDefault;
-
- ppalDst = PALETTE_ShareLockPalette(hpalDst);
- if (!ppalDst)
- {
- PALETTE_ShareUnlockPalette(ppalSrc);
- return;
- }
-
- ppalDstDc = pdcDst->dclevel.ppal;
- ASSERT(ppalDstDc);
-
- /* KB41464 details how to convert between mono and color */
- if (psurfDst->SurfObj.iBitmapFormat == BMF_1BPP)
- {
- if (psurfSrc->SurfObj.iBitmapFormat != BMF_1BPP)
- {
- // HACK!! FIXME: 1bpp DDBs should have gpalMono already!
- EXLATEOBJ_vInitialize(pexlo,
- ppalSrc,
- &gpalMono,
- pdcSrc->pdcattr->crBackgroundClr,
- pdcDst->pdcattr->crBackgroundClr,
- pdcDst->pdcattr->crForegroundClr);
- }
- }
- else if (psurfSrc->SurfObj.iBitmapFormat == BMF_1BPP && !psurfSrc->hSecure)
- {
- // HACK!! FIXME: 1bpp DDBs should have gpalMono already!
- EXLATEOBJ_vInitialize(pexlo,
- &gpalMono,
- ppalDst,
- 0,
- pdcDst->pdcattr->crBackgroundClr,
- pdcDst->pdcattr->crForegroundClr);
- }
- else
- {
- EXLATEOBJ_vInitialize(pexlo, ppalSrc, ppalDst, 0, 0, 0);
- }
-
- PALETTE_ShareUnlockPalette(ppalDst);
- PALETTE_ShareUnlockPalette(ppalSrc);
- }
-
-
- VOID
- NTAPI
- EXLATEOBJ_vInitBrushXlate(
- PEXLATEOBJ pexlo,
- BRUSH *pbrush,
- SURFACE *psurfDst,
- COLORREF crForegroundClr,
- COLORREF crBackgroundClr)
- {
- HPALETTE hpalDst = NULL;
- PPALETTE ppalDst, ppalPattern;
- SURFACE *psurfPattern;
-
- ASSERT(pexlo);
- ASSERT(pbrush);
- ASSERT(psurfDst);
- ASSERT(!(pbrush->flAttrs & (GDIBRUSH_IS_SOLID | GDIBRUSH_IS_NULL)));
-
- EXLATEOBJ_vInitTrivial(pexlo);
-
- hpalDst = psurfDst->hDIBPalette;
- if (!hpalDst) hpalDst = pPrimarySurface->devinfo.hpalDefault;
- ppalDst = PALETTE_ShareLockPalette(hpalDst);
- if (!ppalDst)
- {
- DPRINT1("No ppalDst!\n");
- return;
- }
-
- psurfPattern = SURFACE_ShareLockSurface(pbrush->hbmPattern);
- if (!psurfPattern)
- {
- PALETTE_ShareUnlockPalette(ppalDst);
- return;
- }
-
- #if 0
- if (psurfDst->SurfObj.iBitmapFormat == BMF_1BPP)
- {
- if (psurfSrc->SurfObj.iBitmapFormat != BMF_1BPP)
- {
- // HACK!! FIXME: 1bpp DDBs should have gpalMono already!
- EXLATEOBJ_vInitialize(pexlo,
- ppalSrc,
- &gpalMono,
- 0,
- crBackgroundClr,
- crForegroundClr);
- }
- }
- else
- #endif
- if (psurfPattern->SurfObj.iBitmapFormat == BMF_1BPP &&
- !(pbrush->flAttrs & GDIBRUSH_IS_DIB))
- {
- /* Special case: 1 bpp pattern, not a DIB brush. */
- if (psurfDst->SurfObj.iBitmapFormat != BMF_1BPP)
- {
- // HACK!! FIXME: 1bpp DDBs should have gpalMono already!
- EXLATEOBJ_vInitialize(pexlo,
- &gpalMono,
- ppalDst,
- 0,
- crBackgroundClr,
- crForegroundClr);
- }
- }
- else
- {
- /* Default: use the patterns' palette */
- ppalPattern = PALETTE_LockPalette(psurfPattern->hDIBPalette);
- if (ppalPattern)
- {
- EXLATEOBJ_vInitialize(pexlo, &gpalRGB, ppalDst, 0, 0, 0);
- PALETTE_UnlockPalette(ppalPattern);
- }
- }
-
- PALETTE_ShareUnlockPalette(ppalDst);
- SURFACE_ShareUnlockSurface(psurfPattern);
+ /* Normal initialisation. No surface means DEFAULT_BITMAP */
+ EXLATEOBJ_vInitialize(pexlo,
+ psurfSrc ? psurfSrc->ppal : &gpalMono,
+ psurfDst ? psurfDst->ppal : &gpalMono,
+ pdcSrc->pdcattr->crBackgroundClr,
+ pdcDst->pdcattr->crBackgroundClr,
+ pdcDst->pdcattr->crForegroundClr);
}
VOID
/* Verify palette type match */
if (!ppal ||
((iPal == XO_SRCPALETTE || iPal == XO_DESTPALETTE)
- && !(ppal->Mode & PAL_INDEXED)) ||
+ && !(ppal->flFlags & PAL_INDEXED)) ||
((iPal == XO_SRCBITFIELDS || iPal == XO_DESTBITFIELDS)
- && !(ppal->Mode & PAL_BITFIELDS)))
+ && !(ppal->flFlags & PAL_BITFIELDS)))
{
return 0;
}
}
/* Copy the values into the buffer */
- if (ppal->Mode & PAL_INDEXED)
+ if (ppal->flFlags & PAL_INDEXED)
{
cPal = min(cPal, ppal->NumColors);
for (i = 0; i < cPal; i++)
#include "surface.h"
- INT FASTCALL DIB_GetDIBWidthBytes (INT width, INT depth);
- int APIENTRY DIB_GetDIBImageBytes (INT width, INT height, INT depth);
- INT FASTCALL DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse);
+ typedef struct tagBITMAPV5INFO
+ {
+ BITMAPV5HEADER bmiHeader;
+ RGBQUAD bmiColors[256];
+ } BITMAPV5INFO, *PBITMAPV5INFO;
+
INT APIENTRY BITMAP_GetObject(SURFACE * bmp, INT count, LPVOID buffer);
HBITMAP FASTCALL IntCreateBitmap(IN SIZEL Size, IN LONG Width, IN ULONG Format, IN ULONG Flags, IN PVOID Bits);
HBITMAP FASTCALL BITMAP_CopyBitmap (HBITMAP hBitmap);
UINT FASTCALL BITMAP_GetRealBitsPixel(UINT nBitsPixel);
- INT FASTCALL BITMAP_GetWidthBytes (INT bmWidth, INT bpp);
+
+ HBITMAP
+ APIENTRY
+ GreCreateBitmap(
+ IN INT nWidth,
+ IN INT nHeight,
+ IN UINT cPlanes,
+ IN UINT cBitsPixel,
+ IN OPTIONAL PVOID pvBits);
+
+ HBITMAP
+ APIENTRY
+ GreCreateBitmapEx(
+ IN INT nWidth,
+ IN INT nHeight,
+ IN ULONG cjWidthBytes,
+ IN ULONG iFormat,
+ IN USHORT fjBitmap,
+ IN ULONG cjBits,
+ IN OPTIONAL PVOID pvBits,
+ IN FLONG flags);
+
+ HBITMAP
+ FASTCALL
+ GreCreateDIBitmapInternal(
+ IN HDC hDc,
+ IN INT cx,
+ IN INT cy,
+ IN DWORD fInit,
+ IN OPTIONAL LPBYTE pjInit,
+ IN OPTIONAL PBITMAPINFO pbmi,
+ IN DWORD iUsage,
+ IN FLONG fl,
+ IN HANDLE hcmXform);
- #pragma once
+ #ifndef __WIN32K_DC_H
+ #define __WIN32K_DC_H
typedef struct _DC *PDC;
/* fl */
#define DC_FL_PAL_BACK 1
+ #define DC_DISPLAY 1
+ #define DC_DIRECT 2
+ #define DC_CANCELED 4
+ #define DC_PERMANANT 0x08
+ #define DC_DIRTY_RAO 0x10
+ #define DC_ACCUM_WMGR 0x20
+ #define DC_ACCUM_APP 0x40
+ #define DC_RESET 0x80
+ #define DC_SYNCHRONIZEACCESS 0x100
+ #define DC_EPSPRINTINGESCAPE 0x200
+ #define DC_TEMPINFODC 0x400
+ #define DC_FULLSCREEN 0x800
+ #define DC_IN_CLONEPDEV 0x1000
+ #define DC_REDIRECTION 0x2000
+ #define DC_SHAREACCESS 0x4000
+
+ typedef enum
+ {
+ DCTYPE_DIRECT = 0,
+ DCTYPE_MEMORY = 1,
+ DCTYPE_INFO = 2,
+ } DCTYPE;
+
+
/* Type definitions ***********************************************************/
typedef struct _ROS_DC_INFO
HRGN hClipRgn; /* Clip region (may be 0) */
HRGN hGCClipRgn; /* GC clip region (ClipRgn AND VisRgn) */
- CLIPOBJ *CombinedClip; /* Use XCLIPOBJ in DC. */
+ CLIPOBJ *CombinedClip;
UNICODE_STRING DriverName;
NTSTATUS FASTCALL InitDcImpl(VOID);
PPDEVOBJ FASTCALL IntEnumHDev(VOID);
- HDC FASTCALL DC_AllocDC(PUNICODE_STRING Driver);
+ PDC NTAPI DC_AllocDcWithHandle();
VOID FASTCALL DC_InitDC(HDC DCToInit);
- HDC FASTCALL DC_FindOpenDC(PUNICODE_STRING Driver);
VOID FASTCALL DC_AllocateDcAttr(HDC);
VOID FASTCALL DC_FreeDcAttr(HDC);
BOOL INTERNAL_CALL DC_Cleanup(PVOID ObjectBody);
- BOOL FASTCALL DC_SetOwnership(HDC DC, PEPROCESS Owner);
+ BOOL FASTCALL DC_SetOwnership(HDC hDC, PEPROCESS Owner);
VOID FASTCALL DC_LockDisplay(HDC);
VOID FASTCALL DC_UnlockDisplay(HDC);
BOOL FASTCALL IntGdiDeleteDC(HDC, BOOL);
VOID FASTCALL DC_vUpdateLineBrush(PDC pdc);
VOID FASTCALL DC_vUpdateTextBrush(PDC pdc);
VOID FASTCALL DC_vUpdateBackgroundBrush(PDC pdc);
+ VOID FASTCALL DC_vFinishBlit(PDC pdc1, PDC pdc2);
+ VOID FASTCALL DC_vPrepareDCsForBlit(PDC pdc1, RECT rc1, PDC pdc2, RECT rc2);
+
+ VOID NTAPI DC_vRestoreDC(IN PDC pdc, INT iSaveLevel);
BOOL FASTCALL DCU_SyncDcAttrtoUser(PDC);
BOOL FASTCALL DCU_SynchDcAttrtoUser(HDC);
VOID FASTCALL DCU_SetDcUndeletable(HDC);
+ VOID NTAPI DC_vFreeDcAttr(PDC pdc);
+ VOID NTAPI DC_vInitDc(PDC pdc, DCTYPE dctype, PPDEVOBJ ppdev);
COLORREF FASTCALL IntGdiSetBkColor (HDC hDC, COLORREF Color);
INT FASTCALL IntGdiSetBkMode(HDC hDC, INT backgroundMode);
HDC FASTCALL IntGdiCreateDisplayDC(HDEV hDev, ULONG DcType, BOOL EmptyDC);
BOOL FASTCALL IntGdiCleanDC(HDC hDC);
VOID FASTCALL IntvGetDeviceCaps(PPDEVOBJ, PDEVCAPS);
- INT FASTCALL IntGdiGetDeviceCaps(PDC,INT);
BOOL FASTCALL MakeInfoDC(PDC,BOOL);
BOOL FASTCALL IntSetDefaultRegion(PDC);
- extern PPDEVOBJ pPrimarySurface;
-
VOID
FORCEINLINE
DC_vSelectSurface(PDC pdc, PSURFACE psurfNew)
pdc->dclevel.ppal = ppal;
}
- BOOL FASTCALL IntPrepareDriverIfNeeded(VOID);
- extern PDEVOBJ PrimarySurface;
+ extern PBRUSH pbrDefaultBrush ;
+
+ #endif /* not __WIN32K_DC_H */
--- /dev/null
+
+ //#define _PDEVOBJ _PDEVOBJ2
+ //#define PDEVOBJ PDEVOBJ2
+ //#define PPDEVOBJ PPDEVOBJ2
+
+ //typedef struct _PDEVOBJ *PPDEVOBJ;
+
+ #define TAG_GDEV 'gdev'
+
+ VOID
+ APIENTRY
+ EngFileWrite(
+ IN PFILE_OBJECT pFileObject,
+ IN PVOID lpBuffer,
+ IN SIZE_T nLength,
+ IN PSIZE_T lpBytesWritten);
+
+ PGRAPHICS_DEVICE
+ NTAPI
+ EngpFindGraphicsDevice(
+ PUNICODE_STRING pustrDevice,
+ DWORD iDevNum,
+ DWORD dwFlags);
+
+ PGRAPHICS_DEVICE
+ NTAPI
+ EngpRegisterGraphicsDevice(
+ PUNICODE_STRING pustrDeviceName,
+ PUNICODE_STRING pustrDiplayDrivers,
+ PUNICODE_STRING pustrDescription,
+ PDEVMODEW pdmDefault);
+
+ BOOL
+ NTAPI
+ InitDeviceImpl();
+
+ BOOL
+ FASTCALL
+ DC_AllocDcAttr(PDC pdc);
+
+ //#define KeRosDumpStackFrames(Frames, Count) KdSystemDebugControl(TAG('R', 'o', 's', 'D'), (PVOID)Frames, Count, NULL, 0, NULL, KernelMode)
+ NTSYSAPI ULONG APIENTRY RtlWalkFrameChain(OUT PVOID *Callers, IN ULONG Count, IN ULONG Flags);
+
+ BOOL
+ NTAPI
+ PDEVOBJ_bSwitchMode(
+ PPDEVOBJ ppdev,
+ PDEVMODEW pdm);
+
+ PDEVMODEW
+ NTAPI
+ PDEVOBJ_pdmMatchDevMode(
+ PPDEVOBJ ppdev,
+ PDEVMODEW pdm);
+
+ extern PGRAPHICS_DEVICE gpPrimaryGraphicsDevice;
+ extern PGRAPHICS_DEVICE gpVgaGraphicsDevice;
INT FASTCALL
DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse);
HBITMAP APIENTRY
- DIB_CreateDIBSection (PDC dc, PBITMAPINFO bmi, UINT usage, LPVOID *bits, HANDLE section, DWORD offset, DWORD ovr_pitch);
- INT APIENTRY
- DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, PLONG width, PLONG height, PWORD planes, PWORD bpp, PLONG compr, PLONG size );
+ DIB_CreateDIBSection (PDC dc, CONST BITMAPINFO *bmi, UINT usage, LPVOID *bits, HANDLE section, DWORD offset, DWORD ovr_pitch);
+ int FASTCALL
+ DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
+ LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size );
INT APIENTRY
DIB_GetDIBImageBytes (INT width, INT height, INT depth);
- INT FASTCALL
- DIB_GetDIBWidthBytes (INT width, INT depth);
- RGBQUAD * FASTCALL
- DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi);
+ HPALETTE FASTCALL
+ DIB_MapPaletteColors(PPALETTE ppal, CONST BITMAPINFO* lpbmi);
HPALETTE FASTCALL
- BuildDIBPalette (CONST BITMAPINFO *bmi, PINT paletteType);
+ BuildDIBPalette (CONST BITMAPINFO *bmi);
+
+ BITMAPINFO* FASTCALL DIB_ConvertBitmapInfo(CONST BITMAPINFO* bmi, DWORD Usage);
+ VOID FASTCALL DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig);
VOID FASTCALL IntGdiAcquireSemaphore ( HSEMAPHORE hsem );
VOID FASTCALL IntGdiReleaseSemaphore ( HSEMAPHORE hsem );
ULONGLONG APIENTRY EngGetTickCount(VOID);
+
+ BOOL
+ APIENTRY
+ EngFreeSectionMem(
+ IN PVOID pvSection OPTIONAL,
+ IN PVOID pvMappedBase OPTIONAL);
+
+ PVOID
+ APIENTRY
+ EngAllocSectionMem(
+ OUT PVOID *ppvSection,
+ IN ULONG fl,
+ IN SIZE_T cjSize,
+ IN ULONG ulTag);
+
+ VOID DecompressBitmap(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta, ULONG iFormat);
BOOL INTERNAL_CALL GDIOBJ_FreeObjByHandle (HGDIOBJ hObj, DWORD ObjectType);
PGDIOBJ INTERNAL_CALL GDIOBJ_LockObj (HGDIOBJ hObj, DWORD ObjectType);
PGDIOBJ INTERNAL_CALL GDIOBJ_ShareLockObj (HGDIOBJ hObj, DWORD ObjectType);
+ VOID INTERNAL_CALL GDIOBJ_LockMultipleObjs(ULONG ulCount, IN HGDIOBJ* ahObj, OUT PGDIOBJ* apObj);
PVOID INTERNAL_CALL GDI_MapHandleTable(PSECTION_OBJECT SectionObject, PEPROCESS Process);
#pragma once
#define HOOK_THREAD_REFERENCED (0x1)
- #define NB_HOOKS (WH_MAXHOOK-WH_MINHOOK+1)
#define HOOKID_TO_INDEX(HookId) (HookId - WH_MINHOOK)
#define HOOKID_TO_FLAG(HookId) (1 << ((HookId) + 1))
#define ISITHOOKED(HookId) (((PTHREADINFO)PsGetCurrentThreadWin32Thread())->fsHooks & HOOKID_TO_FLAG(HookId))
- typedef struct tagHOOKTABLE
- {
- LIST_ENTRY Hooks[NB_HOOKS]; /* array of hook chains */
- UINT Counts[NB_HOOKS]; /* use counts for each hook chain */
- } HOOKTABLE, *PHOOKTABLE;
-
typedef struct tagEVENTHOOK
{
THROBJHEAD head;
UINT Counts;
} EVENTTABLE, *PEVENTTABLE;
+ typedef struct _NOTIFYEVENT
+ {
+ DWORD event;
+ LONG idObject;
+ LONG idChild;
+ DWORD flags;
+ } NOTIFYEVENT, *PNOTIFYEVENT;
+
+ LRESULT FASTCALL co_CallHook(INT HookId, INT Code, WPARAM wParam, LPARAM lParam);
LRESULT FASTCALL co_HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam);
LRESULT FASTCALL co_EVENT_CallEvents(DWORD, HWND, UINT_PTR, LONG_PTR);
VOID FASTCALL HOOK_DestroyThreadHooks(PETHREAD Thread);
+ VOID FASTCALL EVENT_DestroyThreadEvents(PETHREAD Thread);
PHOOK FASTCALL IntGetHookObject(HHOOK);
PHOOK FASTCALL IntGetNextHook(PHOOK Hook);
LRESULT FASTCALL UserCallNextHookEx( PHOOK pHook, int Code, WPARAM wParam, LPARAM lParam, BOOL Ansi);
+ BOOL FASTCALL IntUnhookWindowsHook(int,HOOKPROC);
/* EOF */
MIX mix);
BOOL APIENTRY
- IntEngBitBltEx(SURFOBJ *DestObj,
+ IntEngBitBlt(SURFOBJ *DestObj,
SURFOBJ *SourceObj,
SURFOBJ *Mask,
CLIPOBJ *ClipRegion,
POINTL *MaskOrigin,
BRUSHOBJ *Brush,
POINTL *BrushOrigin,
- ROP4 Rop4,
- BOOL RemoveMouse);
- #define IntEngBitBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation, \
- DestRect, SourcePoint, MaskOrigin, Brush, BrushOrigin, \
- Rop4) \
- IntEngBitBltEx((DestObj), (SourceObj), (Mask), (ClipRegion), \
- (ColorTranslation), (DestRect), (SourcePoint), \
- (MaskOrigin), (Brush), (BrushOrigin), (Rop4), TRUE)
+ ROP4 Rop4);
BOOL APIENTRY
IntEngStretchBlt(SURFOBJ *DestObj,
/* Other Stuff */
- INT FASTCALL
- IntGdiGetDeviceCaps(PDC dc, INT Index);
-
INT
FASTCALL
IntGdiEscape(PDC dc,
IN OUT LPDEVMODEW pDevMode,
IN DWORD dwFlags);
- LONG
- FASTCALL
- IntChangeDisplaySettings(
- IN PUNICODE_STRING pDeviceName OPTIONAL,
- IN LPDEVMODEW pDevMode,
- IN DWORD dwflags,
- IN PVOID lParam OPTIONAL);
-
HBITMAP
FASTCALL
IntCreateCompatibleBitmap(PDC Dc,
--- /dev/null
+
+ #ifdef __GNUC__
+ /* Hack, for bug in ld. Will be removed soon. */
+ #define __ImageBase _image_base__
+ #endif
+ extern IMAGE_DOS_HEADER __ImageBase;
+
+
+ #define TAG_LDEV 'Gldv'
+
+ #define GDI_ENGINE_VERSION DDI_DRIVER_VERSION_NT5_01
+
+ typedef enum
+ {
+ LDEV_DEVICE_DISPLAY = 1,
+ LDEV_DEVICE_PRINTER = 2,
+ LDEV_DEVICE_META = 3,
+ LDEV_DEVICE_MIRROR = 4,
+ LDEV_IMAGE = 5,
+ LDEV_FONT = 6,
+ } LDEVTYPE;
+
+ typedef struct _LDEVOBJ
+ {
+ struct _LDEVOBJ *pldevNext;
+ struct _LDEVOBJ *pldevPrev;
+ SYSTEM_GDI_DRIVER_INFORMATION *pGdiDriverInfo;
+ LDEVTYPE ldevtype;
+ ULONG cRefs;
+ ULONG ulDriverVersion;
+
+ union
+ {
+ PVOID apfn[INDEX_LAST];
+ DRIVER_FUNCTIONS pfn;
+ };
+
+ } LDEVOBJ, *PLDEVOBJ;
+
+ extern PLDEVOBJ gpldevHead;
+ extern HSEMAPHORE ghsemDriverMgmt;
+
+ PLDEVOBJ
+ NTAPI
+ LDEVOBJ_pldevLoadImage(
+ PUNICODE_STRING pusPathName,
+ LDEVTYPE ldevtype);
+
+ BOOL
+ NTAPI
+ LDEVOBJ_bLoadDriver(
+ IN PLDEVOBJ pldev);
+
+ PVOID
+ NTAPI
+ LDEVOBJ_pvFindImageProcAddress(
+ IN PLDEVOBJ pldev,
+ IN LPSTR lpProcName);
+
+ PDEVMODEINFO
+ NTAPI
+ LDEVOBJ_pdmiGetModes(
+ PLDEVOBJ pldev,
+ HANDLE hDriver);
+
+ BOOL
+ NTAPI
+ InitLDEVImpl();
+
+ PLDEVOBJ
+ APIENTRY
+ EngLoadImageEx(
+ LPWSTR pwszDriverName,
+ ULONG ldevtype);
+
+ PLDEVOBJ
+ NTAPI
+ EngGetLDEV(
+ PDEVMODEW pdm);
+
+ NTSTATUS
+ APIENTRY
+ DriverEntry (
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath);
+
PVOID APIENTRY HackSecureVirtualMemory(IN PVOID,IN SIZE_T,IN ULONG,OUT PVOID *);
VOID APIENTRY HackUnsecureVirtualMemory(IN PVOID);
+ NTSTATUS
+ NTAPI
+ RegOpenKey(
+ LPCWSTR pwszKeyName,
+ PHKEY phkey);
+
+ NTSTATUS
+ NTAPI
+ RegQueryValue(
+ IN HKEY hkey,
+ IN PCWSTR pwszValueName,
+ IN ULONG ulType,
+ OUT PVOID pvData,
+ IN OUT PULONG pcbValue);
+
+ VOID
+ NTAPI
+ RegWriteSZ(HKEY hkey, PWSTR pwszValue, PWSTR pwszData);
+
+ VOID
+ NTAPI
+ RegWriteDWORD(HKEY hkey, PWSTR pwszValue, DWORD dwData);
+
+ BOOL
+ NTAPI
+ RegReadDWORD(HKEY hkey, PWSTR pwszValue, PDWORD pdwData);
+
BOOL
NTAPI
RegReadUserSetting(
#include <include/winsta.h>
- INT INTERNAL_CALL MouseSafetyOnDrawStart(SURFOBJ *SurfObj, LONG HazardX1, LONG HazardY1, LONG HazardX2, LONG HazardY2);
- INT INTERNAL_CALL MouseSafetyOnDrawEnd(SURFOBJ *SurfObj);
+ INT INTERNAL_CALL MouseSafetyOnDrawStart(PPDEVOBJ ppdev, LONG HazardX1, LONG HazardY1, LONG HazardX2, LONG HazardY2);
+ INT INTERNAL_CALL MouseSafetyOnDrawEnd(PPDEVOBJ ppdev);
#ifndef XBUTTON1
#define XBUTTON1 (0x01)
/* Caret information for this queue */
PTHRDCARETINFO CaretInfo;
- /* Window hooks */
- PHOOKTABLE Hooks;
-
/* queue state tracking */
WORD WakeMask;
WORD QueueBits;
BOOL APIENTRY IntUninitMessagePumpHook();
#define MAKE_LONG(x, y) ((((y) & 0xFFFF) << 16) | ((x) & 0xFFFF))
- PHOOKTABLE FASTCALL MsqGetHooks(PUSER_MESSAGE_QUEUE Queue);
- VOID FASTCALL MsqSetHooks(PUSER_MESSAGE_QUEUE Queue, PHOOKTABLE Hooks);
-
LPARAM FASTCALL MsqSetMessageExtraInfo(LPARAM lParam);
LPARAM FASTCALL MsqGetMessageExtraInfo(VOID);
VOID APIENTRY MsqRemoveWindowMessagesFromQueue(PVOID pWindow); /* F*(&$ headers, will be gone in the rewrite! */
PALOBJ PalObj;
XLATEOBJ *logicalToSystem;
HPALETTE Self;
- ULONG Mode; // PAL_INDEXED, PAL_BITFIELDS, PAL_RGB, PAL_BGR
+ FLONG flFlags; // PAL_INDEXED, PAL_BITFIELDS, PAL_RGB, PAL_BGR
ULONG NumColors;
PALETTEENTRY *IndexedColors;
ULONG RedMask;
HDEV hPDev;
} PALETTE, *PPALETTE;
- extern PALETTE gpalRGB, gpalBGR, gpalMono;
-
+ extern PALETTE gpalRGB, gpalBGR, gpalMono, gpalRGB555, gpalRGB565, *gppalDefault;
+ extern PPALETTE appalSurfaceDefault[];
HPALETTE FASTCALL PALETTE_AllocPalette(ULONG Mode,
ULONG NumColors,
- #pragma once
-
- #include <drivers/directx/directxint.h>
+ #ifndef __WIN32K_PDEVOBJ_H
+ #define __WIN32K_PDEVOBJ_H
/* PDEVOBJ flags */
#define PDEV_DISPLAY 0x00000001 /* Display device */
RECTL Exclude; /* required publicly for SPS_ACCEPT_EXCLUDE */
} GDIPOINTER, *PGDIPOINTER;
+ typedef struct _DEVMODEINFO
+ {
+ struct _DEVMODEINFO *pdmiNext;
+ struct _LDEVOBJ *pldev;
+ ULONG cbdevmode;
+ DEVMODEW adevmode[1];
+ } DEVMODEINFO, *PDEVMODEINFO;
+
+ typedef struct
+ {
+ DWORD dwFlags;
+ PDEVMODEW pdm;
+
+ } DEVMODEENTRY, *PDEVMODEENTRY;
+
typedef struct _GRAPHICS_DEVICE
{
WCHAR szNtDeviceName[CCHDEVICENAME/2];
DWORD hkClassDriverConfig;
DWORD StateFlags; /* See DISPLAY_DEVICE_* */
ULONG cbdevmodeInfo;
- PVOID devmodeInfo;
- DWORD cbdevmodeInfo1;
- PVOID devmodeInfo1;
- LPWSTR pwszDeviceNames;
+ PDEVMODEINFO pdevmodeInfo;
+ ULONG cDevModes;
+ PDEVMODEENTRY pDevModeList;
+ LPWSTR pDiplayDrivers;
LPWSTR pwszDescription;
DWORD dwUnknown;
PVOID pUnknown;
PFILE_OBJECT FileObject;
DWORD ProtocolType;
+ ULONG iDefaultMode;
+ ULONG iCurrentMode;
} GRAPHICS_DEVICE, *PGRAPHICS_DEVICE;
typedef struct _PDEVOBJ
BASEOBJECT BaseObject;
struct _PDEVOBJ * ppdevNext;
- INT cPdevRefs;
- INT cPdevOpenRefs;
+ LONG cPdevRefs;
+ LONG cPdevOpenRefs;
struct _PDEVOBJ * ppdevParent;
FLONG flFlags; // flags
// FLONG flAccelerated;
// PFN_DrvSetPalette pfnDrvSetPalette;
// PFN_DrvNotify pfnDrvNotify;
// ULONG TagSig;
- // PLDEVOBJ pldev;
+ struct _LDEVOBJ * pldev;
DHPDEV dhpdev; /* DHPDEV for device. */
- PVOID ppalSurf; /* PEPALOBJ/PPALETTE for this device. */
+ struct _PALETTE* ppalSurf; /* PEPALOBJ/PPALETTE for this device. */
DEVINFO devinfo;
GDIINFO gdiinfo;
- HSURF pSurface; /* SURFACE for this device., FIXME: PSURFACE */
+ PSURFACE pSurface; /* SURFACE for this device. */
// HANDLE hSpooler; /* Handle to spooler, if spooler dev driver. */
// PVOID pDesktopId;
PGRAPHICS_DEVICE pGraphicsDevice;
POINTL ptlOrigion;
- PVOID pdmwDev; /* Ptr->DEVMODEW.dmSize + dmDriverExtra == alloc size. */
+ PDEVMODEW pdmwDev; /* Ptr->DEVMODEW.dmSize + dmDriverExtra == alloc size. */
// DWORD Unknown3;
FLONG DxDd_Flags; /* DxDD active status flags. */
// LONG devAttr;
union
{
DRIVER_FUNCTIONS DriverFunctions;
+ DRIVER_FUNCTIONS pfn;
PVOID apfn[INDEX_LAST]; // B8C 0x0598
};
/* ros specific */
ULONG DxDd_nCount;
- ULONG DisplayNumber;
- DEVMODEW DMW;
- PFILE_OBJECT VideoFileObject;
- BOOLEAN PreparedDriver;
GDIPOINTER Pointer;
/* Stuff to keep track of software cursors; win32k gdi part */
UINT SafetyRemoveLevel; /* at what level was the cursor removed?
struct _EDD_DIRECTDRAW_GLOBAL * pEDDgpl;
} PDEVOBJ, *PPDEVOBJ;
- /* PDEV and EDDX extra data container.*/
- typedef struct _PDEVEDD
- {
- PDEVOBJ pdevobj;
- EDD_DIRECTDRAW_GLOBAL EDDgpl;
- } PDEVEDD, *PPDEVEDD;
+ /* Globals ********************************************************************/
+
+ extern PPDEVOBJ gppdevPrimary;
+ #define pPrimarySurface gppdevPrimary
+
+
+ /* Function prototypes ********************************************************/
+
+ PPDEVOBJ
+ NTAPI
+ EngpGetPDEV(PUNICODE_STRING pustrDevice);
+
+ VOID
+ NTAPI
+ PDEVOBJ_vRelease(PPDEVOBJ ppdev);
+
+ PSURFACE
+ NTAPI
+ PDEVOBJ_pSurface(
+ PPDEVOBJ ppdev);
+
+ VOID
+ NTAPI
+ PDEVOBJ_vGetDeviceCaps(
+ PPDEVOBJ ppdev,
+ PDEVCAPS pDevCaps);
+
+ BOOL
+ NTAPI
+ InitPDEVImpl();
+
+ BOOL
+ NTAPI
+ InitLDEVImpl();
+
+ BOOL
+ NTAPI
+ InitDeviceImpl();
- PSIZEL FASTCALL PDEV_sizl(PPDEVOBJ, PSIZEL);
+ PSIZEL
+ FASTCALL
+ PDEVOBJ_sizl(PPDEVOBJ, PSIZEL);
- extern ULONG gdwDirectDrawContext;
+ #endif /* !__WIN32K_PDEVOBJ_H */
RGNDATAHEADER rdh;
RECTL *Buffer;
- } ROSRGNDATA, *PROSRGNDATA, *LPROSRGNDATA;
+ } ROSRGNDATA, *PROSRGNDATA, *LPROSRGNDATA, REGION, *PREGION;
/* Functions ******************************************************************/
/* GDI surface object */
typedef struct _SURFACE
{
- BASEOBJECT BaseObject;
-
- SURFOBJ SurfObj;
- FLONG flHooks;
- FLONG flFlags;
- struct _PALETTE *ppal;
-
- union
- {
- HANDLE hSecureUMPD; // if UMPD_SURFACE set
- HANDLE hMirrorParent;// if MIRROR_SURFACE set
- HANDLE hDDSurface; // if DIRECTDRAW_SURFACE set
- };
-
- SIZEL dimension; /* For SetBitmapDimension(), do NOT use
+ BASEOBJECT BaseObject;
+
+ SURFOBJ SurfObj;
+ //XDCOBJ * pdcoAA;
+ FLONG flags;
+ struct _PALETTE *ppal;
+ //UINT unk_050;
+
+ union
+ {
+ HANDLE hSecureUMPD; // if UMPD_SURFACE set
+ HANDLE hMirrorParent;// if MIRROR_SURFACE set
+ HANDLE hDDSurface; // if DIRECTDRAW_SURFACE set
+ };
+
+ SIZEL sizlDim; /* For SetBitmapDimension(), do NOT use
to get width/height of bitmap, use
bitmap.bmWidth/bitmap.bmHeight for
that */
-
- HDC hDC; // Doc in "Undocumented Windows", page 546, seems to be supported with XP.
- ULONG cRef; // 0x064
- HPALETTE hpalHint;
- /* For device-independent bitmaps: */
- HANDLE hDIBSection;
- HANDLE hSecure;
- DWORD dwOffset;
+ HDC hdc; // Doc in "Undocumented Windows", page 546, seems to be supported with XP.
+ ULONG cRef;
+ HPALETTE hpalHint;
+
+ /* For device-independent bitmaps: */
+ HANDLE hDIBSection;
+ HANDLE hSecure;
+ DWORD dwOffset;
+ //UINT unk_078;
/* reactos specific */
- PFAST_MUTEX BitsLock; /* You need to hold this lock before you touch
- the actual bits in the bitmap */
- HPALETTE hDIBPalette;
- DWORD dsBitfields[3]; // hack, should probably use palette instead
- DWORD biClrUsed;
- DWORD biClrImportant;
+ DWORD biClrImportant;
} SURFACE, *PSURFACE;
- #define BITMAPOBJ_IS_APIBITMAP 0x1
+ // flags field:
+ //#define HOOK_BITBLT 0x00000001
+ //#define HOOK_STRETCHBLT 0x00000002
+ //#define HOOK_PLGBLT 0x00000004
+ //#define HOOK_TEXTOUT 0x00000008
+ //#define HOOK_PAINT 0x00000010
+ //#define HOOK_STROKEPATH 0x00000020
+ //#define HOOK_FILLPATH 0x00000040
+ //#define HOOK_STROKEANDFILLPATH 0x00000080
+ //#define HOOK_LINETO 0x00000100
+ //#define SHAREACCESS_SURFACE 0x00000200
+ //#define HOOK_COPYBITS 0x00000400
+ //#define REDIRECTION_SURFACE 0x00000800 // ?
+ //#define HOOK_MOVEPANNING 0x00000800
+ //#define HOOK_SYNCHRONIZE 0x00001000
+ //#define HOOK_STRETCHBLTROP 0x00002000
+ //#define HOOK_SYNCHRONIZEACCESS 0x00004000
+ //#define USE_DEVLOCK_SURFACE 0x00004000
+ //#define HOOK_TRANSPARENTBLT 0x00008000
+ //#define HOOK_ALPHABLEND 0x00010000
+ //#define HOOK_GRADIENTFILL 0x00020000
+ //#if (NTDDI_VERSION < 0x06000000)
+ // #define HOOK_FLAGS 0x0003B5FF
+ //#else
+ // #define HOOK_FLAGS 0x0003B5EF
+ //#endif
+ #define UMPD_SURFACE 0x00040000
+ #define MIRROR_SURFACE 0x00080000
+ #define DIRECTDRAW_SURFACE 0x00100000
+ #define DRIVER_CREATED_SURFACE 0x00200000
+ #define ENG_CREATE_DEVICE_SURFACE 0x00400000
+ #define DDB_SURFACE 0x00800000
+ #define LAZY_DELETE_SURFACE 0x01000000
+ #define BANDING_SURFACE 0x02000000
+ #define API_BITMAP 0x04000000
+ #define PALETTE_SELECT_SET 0x08000000
+ #define UNREADABLE_SURFACE 0x10000000
+ #define DYNAMIC_MODE_PALETTE 0x20000000
+ #define ABORT_SURFACE 0x40000000
+ #define PDEV_SURFACE 0x80000000
+
+
+ #define BMF_DONT_FREE 0x100
+ #define BMF_RLE_HACK 0x200
+
/* Internal interface */
- #define SURFACE_AllocSurface() ((PSURFACE) GDIOBJ_AllocObj(GDIObjType_SURF_TYPE))
#define SURFACE_AllocSurfaceWithHandle() ((PSURFACE) GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_BITMAP))
#define SURFACE_FreeSurface(pBMObj) GDIOBJ_FreeObj((POBJ) pBMObj, GDIObjType_SURF_TYPE)
#define SURFACE_FreeSurfaceByHandle(hBMObj) GDIOBJ_FreeObjByHandle((HGDIOBJ) hBMObj, GDI_OBJECT_TYPE_BITMAP)
#define SURFACE_ShareUnlockSurface(pBMObj) \
GDIOBJ_ShareUnlockObjByPtr ((POBJ)pBMObj)
- #define SURFACE_LockBitmapBits(pBMObj) ExEnterCriticalRegionAndAcquireFastMutexUnsafe((pBMObj)->BitsLock)
- #define SURFACE_UnlockBitmapBits(pBMObj) ExReleaseFastMutexUnsafeAndLeaveCriticalRegion((pBMObj)->BitsLock)
-
BOOL INTERNAL_CALL SURFACE_Cleanup(PVOID ObjectBody);
- BOOL INTERNAL_CALL SURFACE_InitBitsLock(SURFACE *pBMObj);
- void INTERNAL_CALL SURFACE_CleanupBitsLock(SURFACE *pBMObj);
+
+ PSURFACE
+ NTAPI
+ SURFACE_AllocSurface(
+ IN ULONG iType,
+ IN ULONG cx,
+ IN ULONG cy,
+ IN ULONG iFormat);
+
+ BOOL
+ NTAPI
+ SURFACE_bSetBitmapBits(
+ IN PSURFACE psurf,
+ IN USHORT fjBitmap,
+ IN ULONG ulWidth,
+ IN PVOID pvBits OPTIONAL);
#define GDIDEV(SurfObj) ((PDEVOBJ *)((SurfObj)->hdev))
#define GDIDEVFUNCS(SurfObj) ((PDEVOBJ *)((SurfObj)->hdev))->DriverFunctions
- INT FASTCALL BitsPerFormat (ULONG Format);
ULONG FASTCALL BitmapFormat (WORD Bits, DWORD Compression);
+ extern UCHAR gajBitsPerFormat[];
+ #define BitsPerFormat(Format) gajBitsPerFormat[Format]
+
+ #define WIDTH_BYTES_ALIGN32(cx, bpp) ((((cx) * (bpp) + 31) & ~31) >> 3)
+ #define WIDTH_BYTES_ALIGN16(cx, bpp) ((((cx) * (bpp) + 15) & ~15) >> 3)
+
LIST_ENTRY PtiLink;
POINT ptLast;
+ LIST_ENTRY aphkStart[NB_HOOKS];
CLIENTTHREADINFO cti; // Used only when no Desktop or pcti NULL.
/* ReactOS */
LIST_ENTRY WindowListHead;
LIST_ENTRY GDIBrushAttrFreeList;
} W32PROCESS, *PW32PROCESS;
+ #define CLIBS 32
+
typedef struct _PROCESSINFO
{
W32PROCESS;
struct _DESKTOP* rpdeskStartup;
PCLS pclsPrivateList;
PCLS pclsPublicList;
-
+ DWORD dwhmodLibLoadedMask;
+ HANDLE ahmodLibLoaded[CLIBS];
+ struct _WINSTATION_OBJECT *prpwinsta;
+ HWINSTA hwinsta;
+ ACCESS_MASK amwinsta;
+ DWORD dwHotkey;
HMONITOR hMonitor;
-
+ LUID luidSession;
USERSTARTUPINFO usi;
- ULONG Flags;
DWORD dwLayout;
DWORD dwRegisteredClasses;
/* ReactOS */
#include <include/gdifloat.h>
#include <include/engobjects.h>
#include <include/engevent.h>
+ #include <include/ldevobj.h>
+ #include <include/device.h>
#include <dib/dib.h>
LRESULT FASTCALL
IntDefWindowProc( PWND Window, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL Ansi);
- VOID FASTCALL IntNotifyWinEvent(DWORD, PWND, LONG, LONG);
+ VOID FASTCALL IntNotifyWinEvent(DWORD, PWND, LONG, LONG, DWORD);
PWND FASTCALL co_UserCreateWindowEx(CREATESTRUCTW*, PUNICODE_STRING, PLARGE_STRING);
WNDPROC FASTCALL IntGetWindowProc(PWND,BOOL);
VOID NTAPI EXLATEOBJ_vInitialize(PEXLATEOBJ pexlo, PALETTE *ppalSrc, PALETTE *ppalDst, ULONG, ULONG, ULONG);
VOID NTAPI EXLATEOBJ_vInitXlateFromDCs(PEXLATEOBJ pexlo, PDC pdcSrc, PDC pdcDst);
- VOID NTAPI EXLATEOBJ_vInitBrushXlate(PEXLATEOBJ pexlo, BRUSH *pbrush, SURFACE *psurf, COLORREF crForegroundClr, COLORREF crBackgroundClr);
VOID NTAPI EXLATEOBJ_vInitSrcMonoXlate(PEXLATEOBJ pexlo, PPALETTE ppalDst, ULONG Color0, ULONG Color1);
VOID NTAPI EXLATEOBJ_vCleanup(PEXLATEOBJ pexlo);
PGDI_HANDLE_TABLE GdiHandleTable = NULL;
PSECTION_OBJECT GdiTableSection = NULL;
- LIST_ENTRY GlobalDriverListHead;
-
HANDLE GlobalUserHeap = NULL;
PSECTION_OBJECT GlobalUserHeapSection = NULL;
{
struct _EPROCESS *Process;
PTHREADINFO Win32Thread;
+ int i;
DECLARE_RETURN(NTSTATUS);
DPRINT("Enter Win32kThreadCallback\n");
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
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);
return(STATUS_SUCCESS);
}
+ C_ASSERT(sizeof(SERVERINFO) <= PAGE_SIZE);
/*
* This definition doesn't work
return STATUS_UNSUCCESSFUL;
}
- /* Initialize a list of loaded drivers in Win32 subsystem */
- InitializeListHead(&GlobalDriverListHead);
+ 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();
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))
{
return(Status);
}
- Status = InitDcImpl();
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to initialize Device context implementation!\n");
- return STATUS_UNSUCCESSFUL;
- }
-
/* Initialize FreeType library */
if (! InitFontSupport())
{
return STATUS_UNSUCCESSFUL;
}
- InitXlateImpl();
-
- /* Create stock objects, ie. precreated objects commonly
- used by win32 applications */
- CreateStockObjects();
- CreateSysColorObjects();
-
gusLanguageID = IntGdiGetLanguageID();
return STATUS_SUCCESS;
_SEH2_TRY
{
- /* ProbeForRead(Source,Bytes,1); */
+ ProbeForRead(Source,Bytes,1);
RtlCopyMemory(Target,Source,Bytes);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- /*
- * ReactOS W32 Subsystem
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 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.
- */
- /* $Id$
- *
- * GDI Driver support routines
- * (mostly swiped from Wine)
- *
- */
- #include <win32k.h>
-
- #define NDEBUG
- #include <debug.h>
-
- /* #define TRACE_DRV_CALLS to get a log of all calls into the display driver. */
- #undef TRACE_DRV_CALLS
-
-
- typedef struct _GRAPHICS_DRIVER
- {
- PWSTR Name;
- PFN_DrvEnableDriver EnableDriver;
- int ReferenceCount;
- struct _GRAPHICS_DRIVER *Next;
- } GRAPHICS_DRIVER, *PGRAPHICS_DRIVER;
-
- static PGRAPHICS_DRIVER DriverList;
- static PGRAPHICS_DRIVER GenericDriver = NULL;
-
- BOOL DRIVER_RegisterDriver(LPCWSTR Name, PFN_DrvEnableDriver EnableDriver)
- {
- PGRAPHICS_DRIVER Driver;
-
- DPRINT( "DRIVER_RegisterDriver( Name: %S )\n", Name );
-
- if (GenericDriver != NULL)
- {
- return FALSE;
- }
- Driver = ExAllocatePoolWithTag(PagedPool, sizeof(*Driver), TAG_DRIVER);
- if (!Driver) return FALSE;
- Driver->ReferenceCount = 0;
- Driver->EnableDriver = EnableDriver;
- if (Name)
- {
- Driver->Name = ExAllocatePoolWithTag(PagedPool,
- (wcslen(Name) + 1) * sizeof(WCHAR),
- TAG_DRIVER);
- if (Driver->Name == NULL)
- {
- DPRINT1("Out of memory\n");
- ExFreePoolWithTag(Driver, TAG_DRIVER);
- return FALSE;
- }
-
- wcscpy(Driver->Name, Name);
- Driver->Next = DriverList;
- DriverList = Driver;
- return TRUE;
- }
-
- GenericDriver = Driver;
- return TRUE;
- }
-
- PFN_DrvEnableDriver DRIVER_FindExistingDDIDriver(LPCWSTR Name)
- {
- GRAPHICS_DRIVER *Driver = DriverList;
- while (Driver && Name)
- {
- if (!_wcsicmp(Driver->Name, Name))
- {
- return Driver->EnableDriver;
- }
- Driver = Driver->Next;
- }
-
- return NULL;
- }
-
- PFN_DrvEnableDriver DRIVER_FindDDIDriver(LPCWSTR Name)
- {
- static WCHAR DefaultPath[] = L"\\SystemRoot\\System32\\";
- static WCHAR DefaultExtension[] = L".DLL";
- PFN_DrvEnableDriver ExistingDriver;
- SYSTEM_GDI_DRIVER_INFORMATION GdiDriverInfo;
- NTSTATUS Status;
- LPWSTR FullName;
- LPCWSTR p;
- BOOL PathSeparatorFound;
- BOOL DotFound;
- UINT Size;
-
- DotFound = FALSE;
- PathSeparatorFound = FALSE;
- p = Name;
- while (L'\0' != *p)
- {
- if (L'\\' == *p || L'/' == *p)
- {
- PathSeparatorFound = TRUE;
- DotFound = FALSE;
- }
- else if (L'.' == *p)
- {
- DotFound = TRUE;
- }
- p++;
- }
-
- Size = (wcslen(Name) + 1) * sizeof(WCHAR);
- if (! PathSeparatorFound)
- {
- Size += sizeof(DefaultPath) - sizeof(WCHAR);
- }
- if (! DotFound)
- {
- Size += sizeof(DefaultExtension) - sizeof(WCHAR);
- }
- FullName = ExAllocatePoolWithTag(PagedPool, Size, TAG_DRIVER);
- if (NULL == FullName)
- {
- DPRINT1("Out of memory\n");
- return NULL;
- }
- if (PathSeparatorFound)
- {
- FullName[0] = L'\0';
- }
- else
- {
- wcscpy(FullName, DefaultPath);
- }
- wcscat(FullName, Name);
- if (! DotFound)
- {
- wcscat(FullName, DefaultExtension);
- }
-
- /* First see if the driver hasn't already been loaded */
- ExistingDriver = DRIVER_FindExistingDDIDriver(FullName);
- if (ExistingDriver)
- {
- ExFreePoolWithTag(FullName, TAG_DRIVER);
- return ExistingDriver;
- }
-
- /* If not, then load it */
- RtlInitUnicodeString (&GdiDriverInfo.DriverName, FullName);
- Status = ZwSetSystemInformation (SystemLoadGdiDriverInformation, &GdiDriverInfo, sizeof(SYSTEM_GDI_DRIVER_INFORMATION));
-
- if (!NT_SUCCESS(Status))
- {
- ExFreePoolWithTag(FullName, TAG_DRIVER);
- return NULL;
- }
-
- DRIVER_RegisterDriver( L"DISPLAY", GdiDriverInfo.EntryPoint);
- DRIVER_RegisterDriver( FullName, GdiDriverInfo.EntryPoint);
- ExFreePoolWithTag(FullName, TAG_DRIVER);
- return (PFN_DrvEnableDriver)GdiDriverInfo.EntryPoint;
- }
-
- #define BEGIN_FUNCTION_MAP() \
- ULONG i; \
- for (i = 0; i < DED->c; i++) \
- { \
- switch(DED->pdrvfn[i].iFunc) \
- {
-
- #define END_FUNCTION_MAP() \
- default: \
- DPRINT1("Unsupported DDI function 0x%x\n", DED->pdrvfn[i].iFunc); \
- break; \
- } \
- }
-
- #ifdef TRACE_DRV_CALLS
-
- typedef struct _TRACEDRVINFO
- {
- unsigned Index;
- char *Name;
- PVOID DrvRoutine;
- }
- TRACEDRVINFO, *PTRACEDRVINFO;
-
- __asm__(
- " .text\n"
- "TraceDrv:\n"
- " pushl %eax\n"
- " call _FindTraceInfo\n"
- " add $4,%esp\n"
- " pushl %eax\n"
- " pushl 4(%eax)\n"
- " call _DbgPrint\n"
- " addl $4,%esp\n"
- " popl %eax\n"
- " mov 8(%eax),%eax\n"
- " jmp *%eax\n"
- );
-
- #define TRACEDRV_ROUTINE(function) \
- unsigned TraceDrvIndex##function = INDEX_Drv##function; \
- __asm__ ( \
- " .text\n" \
- "_Trace" #function ":\n" \
- " movl _TraceDrvIndex" #function ",%eax\n" \
- " jmp TraceDrv\n" \
- ); \
- extern PVOID Trace##function;
-
- TRACEDRV_ROUTINE(EnablePDEV)
- TRACEDRV_ROUTINE(CompletePDEV)
- TRACEDRV_ROUTINE(DisablePDEV)
- TRACEDRV_ROUTINE(EnableSurface)
- TRACEDRV_ROUTINE(DisableSurface)
- TRACEDRV_ROUTINE(AssertMode)
- TRACEDRV_ROUTINE(Offset)
- TRACEDRV_ROUTINE(ResetPDEV)
- TRACEDRV_ROUTINE(DisableDriver)
- TRACEDRV_ROUTINE(CreateDeviceBitmap)
- TRACEDRV_ROUTINE(DeleteDeviceBitmap)
- TRACEDRV_ROUTINE(RealizeBrush)
- TRACEDRV_ROUTINE(DitherColor)
- TRACEDRV_ROUTINE(StrokePath)
- TRACEDRV_ROUTINE(FillPath)
- TRACEDRV_ROUTINE(StrokeAndFillPath)
- TRACEDRV_ROUTINE(Paint)
- TRACEDRV_ROUTINE(BitBlt)
- TRACEDRV_ROUTINE(TransparentBlt)
- TRACEDRV_ROUTINE(CopyBits)
- TRACEDRV_ROUTINE(StretchBlt)
- TRACEDRV_ROUTINE(StretchBltROP)
- TRACEDRV_ROUTINE(SetPalette)
- TRACEDRV_ROUTINE(TextOut)
- TRACEDRV_ROUTINE(Escape)
- TRACEDRV_ROUTINE(DrawEscape)
- TRACEDRV_ROUTINE(QueryFont)
- TRACEDRV_ROUTINE(QueryFontTree)
- TRACEDRV_ROUTINE(QueryFontData)
- TRACEDRV_ROUTINE(SetPointerShape)
- TRACEDRV_ROUTINE(MovePointer)
- TRACEDRV_ROUTINE(LineTo)
- TRACEDRV_ROUTINE(SendPage)
- TRACEDRV_ROUTINE(StartPage)
- TRACEDRV_ROUTINE(EndDoc)
- TRACEDRV_ROUTINE(StartDoc)
- TRACEDRV_ROUTINE(GetGlyphMode)
- TRACEDRV_ROUTINE(Synchronize)
- TRACEDRV_ROUTINE(SaveScreenBits)
- TRACEDRV_ROUTINE(GetModes)
- TRACEDRV_ROUTINE(Free)
- TRACEDRV_ROUTINE(DestroyFont)
- TRACEDRV_ROUTINE(QueryFontCaps)
- TRACEDRV_ROUTINE(LoadFontFile)
- TRACEDRV_ROUTINE(UnloadFontFile)
- TRACEDRV_ROUTINE(FontManagement)
- TRACEDRV_ROUTINE(QueryTrueTypeTable)
- TRACEDRV_ROUTINE(QueryTrueTypeOutline)
- TRACEDRV_ROUTINE(GetTrueTypeFile)
- TRACEDRV_ROUTINE(QueryFontFile)
- TRACEDRV_ROUTINE(QueryAdvanceWidths)
- TRACEDRV_ROUTINE(SetPixelFormat)
- TRACEDRV_ROUTINE(DescribePixelFormat)
- TRACEDRV_ROUTINE(SwapBuffers)
- TRACEDRV_ROUTINE(StartBanding)
- TRACEDRV_ROUTINE(NextBand)
- TRACEDRV_ROUTINE(GetDirectDrawInfo)
- TRACEDRV_ROUTINE(EnableDirectDraw)
- TRACEDRV_ROUTINE(DisableDirectDraw)
- TRACEDRV_ROUTINE(QuerySpoolType)
- TRACEDRV_ROUTINE(IcmSetDeviceGammaRamp)
- TRACEDRV_ROUTINE(GradientFill)
- TRACEDRV_ROUTINE(SynchronizeSurface)
- TRACEDRV_ROUTINE(AlphaBlend)
-
- #define TRACEDRVINFO_ENTRY(function) \
- { INDEX_Drv##function, "Drv" #function "\n", NULL }
- static TRACEDRVINFO TraceDrvInfo[] =
- {
- TRACEDRVINFO_ENTRY(EnablePDEV),
- TRACEDRVINFO_ENTRY(CompletePDEV),
- TRACEDRVINFO_ENTRY(DisablePDEV),
- TRACEDRVINFO_ENTRY(EnableSurface),
- TRACEDRVINFO_ENTRY(DisableSurface),
- TRACEDRVINFO_ENTRY(AssertMode),
- TRACEDRVINFO_ENTRY(Offset),
- TRACEDRVINFO_ENTRY(ResetPDEV),
- TRACEDRVINFO_ENTRY(DisableDriver),
- TRACEDRVINFO_ENTRY(CreateDeviceBitmap),
- TRACEDRVINFO_ENTRY(DeleteDeviceBitmap),
- TRACEDRVINFO_ENTRY(RealizeBrush),
- TRACEDRVINFO_ENTRY(DitherColor),
- TRACEDRVINFO_ENTRY(StrokePath),
- TRACEDRVINFO_ENTRY(FillPath),
- TRACEDRVINFO_ENTRY(StrokeAndFillPath),
- TRACEDRVINFO_ENTRY(Paint),
- TRACEDRVINFO_ENTRY(BitBlt),
- TRACEDRVINFO_ENTRY(TransparentBlt),
- TRACEDRVINFO_ENTRY(CopyBits),
- TRACEDRVINFO_ENTRY(StretchBlt),
- TRACEDRVINFO_ENTRY(StretchBltROP),
- TRACEDRVINFO_ENTRY(SetPalette),
- TRACEDRVINFO_ENTRY(TextOut),
- TRACEDRVINFO_ENTRY(Escape),
- TRACEDRVINFO_ENTRY(DrawEscape),
- TRACEDRVINFO_ENTRY(QueryFont),
- TRACEDRVINFO_ENTRY(QueryFontTree),
- TRACEDRVINFO_ENTRY(QueryFontData),
- TRACEDRVINFO_ENTRY(SetPointerShape),
- TRACEDRVINFO_ENTRY(MovePointer),
- TRACEDRVINFO_ENTRY(LineTo),
- TRACEDRVINFO_ENTRY(SendPage),
- TRACEDRVINFO_ENTRY(StartPage),
- TRACEDRVINFO_ENTRY(EndDoc),
- TRACEDRVINFO_ENTRY(StartDoc),
- TRACEDRVINFO_ENTRY(GetGlyphMode),
- TRACEDRVINFO_ENTRY(Synchronize),
- TRACEDRVINFO_ENTRY(SaveScreenBits),
- TRACEDRVINFO_ENTRY(GetModes),
- TRACEDRVINFO_ENTRY(Free),
- TRACEDRVINFO_ENTRY(DestroyFont),
- TRACEDRVINFO_ENTRY(QueryFontCaps),
- TRACEDRVINFO_ENTRY(LoadFontFile),
- TRACEDRVINFO_ENTRY(UnloadFontFile),
- TRACEDRVINFO_ENTRY(FontManagement),
- TRACEDRVINFO_ENTRY(QueryTrueTypeTable),
- TRACEDRVINFO_ENTRY(QueryTrueTypeOutline),
- TRACEDRVINFO_ENTRY(GetTrueTypeFile),
- TRACEDRVINFO_ENTRY(QueryFontFile),
- TRACEDRVINFO_ENTRY(QueryAdvanceWidths),
- TRACEDRVINFO_ENTRY(SetPixelFormat),
- TRACEDRVINFO_ENTRY(DescribePixelFormat),
- TRACEDRVINFO_ENTRY(SwapBuffers),
- TRACEDRVINFO_ENTRY(StartBanding),
- TRACEDRVINFO_ENTRY(NextBand),
- TRACEDRVINFO_ENTRY(GetDirectDrawInfo),
- TRACEDRVINFO_ENTRY(EnableDirectDraw),
- TRACEDRVINFO_ENTRY(DisableDirectDraw),
- TRACEDRVINFO_ENTRY(QuerySpoolType),
- TRACEDRVINFO_ENTRY(IcmSetDeviceGammaRamp),
- TRACEDRVINFO_ENTRY(GradientFill),
- TRACEDRVINFO_ENTRY(SynchronizeSurface),
- TRACEDRVINFO_ENTRY(AlphaBlend)
- };
-
- PTRACEDRVINFO
- FindTraceInfo(unsigned Index)
- {
- unsigned i;
-
- for (i = 0; i < sizeof(TraceDrvInfo) / sizeof(TRACEDRVINFO); i++)
- {
- if (TraceDrvInfo[i].Index == Index)
- {
- return TraceDrvInfo + i;
- }
- }
-
- return NULL;
- }
-
- #define DRIVER_FUNCTION(function) \
- case INDEX_Drv##function: \
- FindTraceInfo(INDEX_Drv##function)->DrvRoutine = DED->pdrvfn[i].pfn; \
- *(PVOID*)&DF->function = &Trace##function; \
- break
- #else
- #define DRIVER_FUNCTION(function) \
- case INDEX_Drv##function: \
- *(PVOID*)&DF->function = DED->pdrvfn[i].pfn; \
- break
- #endif
-
- BOOL DRIVER_BuildDDIFunctions(PDRVENABLEDATA DED,
- PDRIVER_FUNCTIONS DF)
- {
- BEGIN_FUNCTION_MAP();
- DRIVER_FUNCTION(EnablePDEV);
- DRIVER_FUNCTION(CompletePDEV);
- DRIVER_FUNCTION(DisablePDEV);
- DRIVER_FUNCTION(EnableSurface);
- DRIVER_FUNCTION(DisableSurface);
- DRIVER_FUNCTION(AssertMode);
- DRIVER_FUNCTION(Offset);
- DRIVER_FUNCTION(ResetPDEV);
- DRIVER_FUNCTION(DisableDriver);
- DRIVER_FUNCTION(Unknown1);
- DRIVER_FUNCTION(CreateDeviceBitmap);
- DRIVER_FUNCTION(DeleteDeviceBitmap);
- DRIVER_FUNCTION(RealizeBrush);
- DRIVER_FUNCTION(DitherColor);
- DRIVER_FUNCTION(StrokePath);
- DRIVER_FUNCTION(FillPath);
- DRIVER_FUNCTION(StrokeAndFillPath);
- DRIVER_FUNCTION(Paint);
- DRIVER_FUNCTION(BitBlt);
- DRIVER_FUNCTION(CopyBits);
- DRIVER_FUNCTION(StretchBlt);
- DRIVER_FUNCTION(Unknown2);
- DRIVER_FUNCTION(SetPalette);
- DRIVER_FUNCTION(TextOut);
- DRIVER_FUNCTION(Escape);
- DRIVER_FUNCTION(DrawEscape);
- DRIVER_FUNCTION(QueryFont);
- DRIVER_FUNCTION(QueryFontTree);
- DRIVER_FUNCTION(QueryFontData);
- DRIVER_FUNCTION(SetPointerShape);
- DRIVER_FUNCTION(MovePointer);
- DRIVER_FUNCTION(LineTo);
- DRIVER_FUNCTION(SendPage);
- DRIVER_FUNCTION(StartPage);
- DRIVER_FUNCTION(EndDoc);
- DRIVER_FUNCTION(StartDoc);
- DRIVER_FUNCTION(Unknown3);
- DRIVER_FUNCTION(GetGlyphMode);
- DRIVER_FUNCTION(Synchronize);
- DRIVER_FUNCTION(Unknown4);
- DRIVER_FUNCTION(SaveScreenBits);
- DRIVER_FUNCTION(GetModes);
- DRIVER_FUNCTION(Free);
- DRIVER_FUNCTION(DestroyFont);
- DRIVER_FUNCTION(QueryFontCaps);
- DRIVER_FUNCTION(LoadFontFile);
- DRIVER_FUNCTION(UnloadFontFile);
- DRIVER_FUNCTION(FontManagement);
- DRIVER_FUNCTION(QueryTrueTypeTable);
- DRIVER_FUNCTION(QueryTrueTypeOutline);
- DRIVER_FUNCTION(GetTrueTypeFile);
- DRIVER_FUNCTION(QueryFontFile);
- DRIVER_FUNCTION(QueryAdvanceWidths);
- DRIVER_FUNCTION(SetPixelFormat);
- DRIVER_FUNCTION(DescribePixelFormat);
- DRIVER_FUNCTION(SwapBuffers);
- DRIVER_FUNCTION(StartBanding);
- DRIVER_FUNCTION(NextBand);
- DRIVER_FUNCTION(GetDirectDrawInfo);
- DRIVER_FUNCTION(EnableDirectDraw);
- DRIVER_FUNCTION(DisableDirectDraw);
- DRIVER_FUNCTION(QuerySpoolType);
- DRIVER_FUNCTION(Unknown5);
- DRIVER_FUNCTION(IcmCreateColorTransform);
- DRIVER_FUNCTION(IcmDeleteColorTransform);
- DRIVER_FUNCTION(IcmCheckBitmapBits);
- DRIVER_FUNCTION(IcmSetDeviceGammaRamp);
- DRIVER_FUNCTION(GradientFill);
- DRIVER_FUNCTION(StretchBltROP);
- DRIVER_FUNCTION(PlgBlt);
- DRIVER_FUNCTION(AlphaBlend);
- DRIVER_FUNCTION(SynthesizeFont);
- DRIVER_FUNCTION(GetSynthesizedFontFiles);
- DRIVER_FUNCTION(TransparentBlt);
- DRIVER_FUNCTION(QueryPerBandInfo);
- DRIVER_FUNCTION(QueryDeviceSupport);
- DRIVER_FUNCTION(Reserved1);
- DRIVER_FUNCTION(Reserved2);
- DRIVER_FUNCTION(Reserved3);
- DRIVER_FUNCTION(Reserved4);
- DRIVER_FUNCTION(Reserved5);
- DRIVER_FUNCTION(Reserved6);
- DRIVER_FUNCTION(Reserved7);
- DRIVER_FUNCTION(Reserved8);
- DRIVER_FUNCTION(DeriveSurface);
- DRIVER_FUNCTION(QueryGlyphAttrs);
- DRIVER_FUNCTION(Notify);
- DRIVER_FUNCTION(SynchronizeSurface);
- DRIVER_FUNCTION(ResetDevice);
- DRIVER_FUNCTION(Reserved9);
- DRIVER_FUNCTION(Reserved10);
- DRIVER_FUNCTION(Reserved11);
- END_FUNCTION_MAP();
-
- return TRUE;
- }
-
- typedef LONG VP_STATUS;
- typedef VP_STATUS (APIENTRY *PMP_DRIVERENTRY)(PVOID, PVOID);
-
- PFILE_OBJECT DRIVER_FindMPDriver(ULONG DisplayNumber)
- {
- OBJECT_ATTRIBUTES ObjectAttributes;
- WCHAR DeviceNameBuffer[20];
- UNICODE_STRING DeviceName;
- IO_STATUS_BLOCK Iosb;
- HANDLE DisplayHandle;
- NTSTATUS Status;
- PFILE_OBJECT VideoFileObject;
-
- swprintf(DeviceNameBuffer, L"\\??\\DISPLAY%d", DisplayNumber + 1);
- RtlInitUnicodeString(&DeviceName, DeviceNameBuffer);
- InitializeObjectAttributes(&ObjectAttributes,
- &DeviceName,
- 0,
- NULL,
- NULL);
- Status = ZwOpenFile(&DisplayHandle,
- FILE_ALL_ACCESS,
- &ObjectAttributes,
- &Iosb,
- 0,
- FILE_SYNCHRONOUS_IO_ALERT);
- if (NT_SUCCESS(Status))
- {
- Status = ObReferenceObjectByHandle(DisplayHandle,
- FILE_READ_DATA | FILE_WRITE_DATA,
- IoFileObjectType,
- KernelMode,
- (PVOID *)&VideoFileObject,
- NULL);
- ZwClose(DisplayHandle);
- }
-
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Unable to connect to miniport (Status %lx)\n", Status);
- DPRINT1("Perhaps the miniport wasn't loaded?\n");
- return(NULL);
- }
-
- return VideoFileObject;
- }
-
-
- BOOL DRIVER_UnregisterDriver(LPCWSTR Name)
- {
- PGRAPHICS_DRIVER Driver = NULL;
-
- if (Name)
- {
- if (DriverList != NULL)
- {
- if (!_wcsicmp(DriverList->Name, Name))
- {
- Driver = DriverList;
- DriverList = DriverList->Next;
- }
- else
- {
- Driver = DriverList;
- while (Driver->Next && _wcsicmp(Driver->Name, Name))
- {
- Driver = Driver->Next;
- }
- }
- }
- }
- else
- {
- if (GenericDriver != NULL)
- {
- Driver = GenericDriver;
- GenericDriver = NULL;
- }
- }
-
- if (Driver != NULL)
- {
- ExFreePoolWithTag(Driver->Name, TAG_DRIVER);
- ExFreePoolWithTag(Driver, TAG_DRIVER);
-
- return TRUE;
- }
- else
- {
- return FALSE;
- }
- }
-
- INT DRIVER_ReferenceDriver (LPCWSTR Name)
- {
- GRAPHICS_DRIVER *Driver = DriverList;
-
- while (Driver && Name)
- {
- DPRINT( "Comparing %S to %S\n", Driver->Name, Name );
- if (!_wcsicmp( Driver->Name, Name))
- {
- return ++Driver->ReferenceCount;
- }
- Driver = Driver->Next;
- }
- DPRINT( "Driver %S not found to reference, generic count: %d\n", Name, GenericDriver->ReferenceCount );
- ASSERT( GenericDriver != 0 );
- return ++GenericDriver->ReferenceCount;
- }
-
- INT DRIVER_UnreferenceDriver (LPCWSTR Name)
- {
- GRAPHICS_DRIVER *Driver = DriverList;
-
- while (Driver && Name)
- {
- DPRINT( "Comparing %S to %S\n", Driver->Name, Name );
- if (!_wcsicmp( Driver->Name, Name))
- {
- return --Driver->ReferenceCount;
- }
- Driver = Driver->Next;
- }
- DPRINT( "Driver '%S' not found to dereference, generic count: %d\n", Name, GenericDriver->ReferenceCount );
- ASSERT( GenericDriver != 0 );
- return --GenericDriver->ReferenceCount;
- }
- /* EOF */
return pvBase;
}
- typedef struct tagBITMAPV5INFO
- {
- BITMAPV5HEADER bmiHeader;
- RGBQUAD bmiColors[256];
- } BITMAPV5INFO, *PBITMAPV5INFO;
-
- // FIXME: this should go to dibobj.c
- NTSTATUS
- ProbeAndConvertBitmapInfo(
- OUT BITMAPV5HEADER *pbmhDst,
- OUT RGBQUAD *pbmiColorsDst,
- ULONG cColors,
- IN PBITMAPINFO pbmiUnsafe)
- {
- DWORD dwSize;
- RGBQUAD *pbmiColors;
- ULONG ulWidthBytes;
-
- /* Get the size and probe */
- ProbeForRead(&pbmiUnsafe->bmiHeader.biSize, sizeof(DWORD), 1);
- dwSize = pbmiUnsafe->bmiHeader.biSize;
- ProbeForRead(pbmiUnsafe, dwSize, 1);
-
- /* Check the size */
- // FIXME: are intermediate sizes allowed? As what are they interpreted?
- // make sure we don't use a too big dwSize later
- if (dwSize != sizeof(BITMAPCOREHEADER) &&
- dwSize != sizeof(BITMAPINFOHEADER) &&
- dwSize != sizeof(BITMAPV4HEADER) &&
- dwSize != sizeof(BITMAPV5HEADER))
- {
- return STATUS_INVALID_PARAMETER;
- }
-
- pbmiColors = (RGBQUAD*)((PCHAR)pbmiUnsafe + dwSize);
-
- pbmhDst->bV5Size = sizeof(BITMAPV5HEADER);
-
- if (dwSize == sizeof(BITMAPCOREHEADER))
- {
- PBITMAPCOREHEADER pbch = (PBITMAPCOREHEADER)pbmiUnsafe;
-
- /* Manually copy the fields that are present */
- pbmhDst->bV5Width = pbch->bcWidth;
- pbmhDst->bV5Height = pbch->bcHeight;
- pbmhDst->bV5Planes = pbch->bcPlanes;
- pbmhDst->bV5BitCount = pbch->bcBitCount;
-
- /* Set some default values */
- pbmhDst->bV5Compression = BI_RGB;
- pbmhDst->bV5SizeImage = 0;
- pbmhDst->bV5XPelsPerMeter = 72;
- pbmhDst->bV5YPelsPerMeter = 72;
- pbmhDst->bV5ClrUsed = 0;
- pbmhDst->bV5ClrImportant = 0;
- }
- else
- {
- /* Copy valid fields */
- memcpy(pbmhDst, pbmiUnsafe, dwSize);
-
- /* Zero out the rest of the V5 header */
- memset((char*)pbmhDst + dwSize, 0, sizeof(BITMAPV5HEADER) - dwSize);
- }
-
-
- if (dwSize < sizeof(BITMAPV4HEADER))
- {
- if (pbmhDst->bV5Compression == BI_BITFIELDS)
- {
- DWORD *pMasks = (DWORD*)pbmiColors;
- pbmhDst->bV5RedMask = pMasks[0];
- pbmhDst->bV5GreenMask = pMasks[1];
- pbmhDst->bV5BlueMask = pMasks[2];
- pbmhDst->bV5AlphaMask = 0;
- pbmhDst->bV5ClrUsed = 0;
- }
-
- // pbmhDst->bV5CSType;
- // pbmhDst->bV5Endpoints;
- // pbmhDst->bV5GammaRed;
- // pbmhDst->bV5GammaGreen;
- // pbmhDst->bV5GammaBlue;
- }
-
- if (dwSize < sizeof(BITMAPV5HEADER))
- {
- // pbmhDst->bV5Intent;
- // pbmhDst->bV5ProfileData;
- // pbmhDst->bV5ProfileSize;
- // pbmhDst->bV5Reserved;
- }
-
- ulWidthBytes = ((pbmhDst->bV5Width * pbmhDst->bV5Planes *
- pbmhDst->bV5BitCount + 31) & ~31) / 8;
-
- if (pbmhDst->bV5SizeImage == 0)
- pbmhDst->bV5SizeImage = abs(ulWidthBytes * pbmhDst->bV5Height);
-
- if (pbmhDst->bV5ClrUsed == 0)
- pbmhDst->bV5ClrUsed = pbmhDst->bV5BitCount == 1 ? 2 :
- (pbmhDst->bV5BitCount == 4 ? 16 :
- (pbmhDst->bV5BitCount == 8 ? 256 : 0));
-
- if (pbmhDst->bV5Planes != 1)
- {
- return STATUS_INVALID_PARAMETER;
- }
-
- if (pbmhDst->bV5BitCount != 0 && pbmhDst->bV5BitCount != 1 &&
- pbmhDst->bV5BitCount != 4 && pbmhDst->bV5BitCount != 8 &&
- pbmhDst->bV5BitCount != 16 && pbmhDst->bV5BitCount != 24 &&
- pbmhDst->bV5BitCount != 32)
- {
- DPRINT("Invalid bit count: %d\n", pbmhDst->bV5BitCount);
- return STATUS_INVALID_PARAMETER;
- }
-
- if ((pbmhDst->bV5BitCount == 0 &&
- pbmhDst->bV5Compression != BI_JPEG && pbmhDst->bV5Compression != BI_PNG))
- {
- DPRINT("Bit count 0 is invalid for compression %d.\n", pbmhDst->bV5Compression);
- return STATUS_INVALID_PARAMETER;
- }
-
- if (pbmhDst->bV5Compression == BI_BITFIELDS &&
- pbmhDst->bV5BitCount != 16 && pbmhDst->bV5BitCount != 32)
- {
- DPRINT("Bit count %d is invalid for compression BI_BITFIELDS.\n", pbmhDst->bV5BitCount);
- return STATUS_INVALID_PARAMETER;
- }
-
- /* Copy Colors */
- cColors = min(cColors, pbmhDst->bV5ClrUsed);
- memcpy(pbmiColorsDst, pbmiColors, cColors * sizeof(RGBQUAD));
-
- return STATUS_SUCCESS;
- }
-
-
HBITMAP
NTAPI
UserLoadImage(PCWSTR pwszName)
{
- NTSTATUS Status;
+ NTSTATUS Status = STATUS_SUCCESS;
HANDLE hFile, hSection;
BITMAPFILEHEADER *pbmfh;
LPBITMAPINFO pbmi;
- ULONG cjInfoSize;
PVOID pvBits;
HBITMAP hbmp = 0;
- BITMAPV5INFO bmiLocal;
+
+ DPRINT("Enter UserLoadImage(%ls)\n", pwszName);
/* Open the file */
hFile = W32kOpenFile(pwszName, FILE_READ_DATA);
- if (hFile == INVALID_HANDLE_VALUE)
- return NULL;
+ if (!hFile)
+ {
+ return NULL;
+ }
/* Create a section */
hSection = W32kCreateFileSection(hFile, SEC_COMMIT, PAGE_READONLY, 0);
ZwClose(hFile);
if (!hSection)
- return NULL;
+ {
+ return NULL;
+ }
/* Map the section */
pbmfh = W32kMapViewOfSection(hSection, PAGE_READONLY, 0);
ZwClose(hSection);
if (!pbmfh)
- return NULL;
-
- /* Get a pointer to the BITMAPINFO */
- pbmi = (LPBITMAPINFO)(pbmfh + 1);
-
- /* Create a normalized local BITMAPINFO */
- _SEH2_TRY
{
- Status = ProbeAndConvertBitmapInfo(&bmiLocal.bmiHeader,
- bmiLocal.bmiColors,
- 256,
- pbmi);
+ return NULL;
}
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END
- if (NT_SUCCESS(Status))
- {
- cjInfoSize = bmiLocal.bmiHeader.bV5Size +
- bmiLocal.bmiHeader.bV5ClrUsed * sizeof(RGBQUAD);
- pvBits = (PVOID)((PCHAR)pbmi + cjInfoSize);
-
- // FIXME: use Gre... so that the BITMAPINFO doesn't get probed
- hbmp = NtGdiCreateDIBitmapInternal(NULL,
- bmiLocal.bmiHeader.bV5Width,
- bmiLocal.bmiHeader.bV5Height,
- CBM_INIT,
- pvBits,
- pbmi,
- DIB_RGB_COLORS,
- bmiLocal.bmiHeader.bV5Size,
- bmiLocal.bmiHeader.bV5SizeImage,
- 0,
- 0);
- }
+ /* Get a pointer to the BITMAPINFO */
+ pbmi = (LPBITMAPINFO)(pbmfh + 1);
+ _SEH2_TRY
+ {
+ ProbeForRead(&pbmfh->bfSize, sizeof(DWORD), 1);
+ ProbeForRead(pbmfh, pbmfh->bfSize, 1);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END
+
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("Bad File?\n");
+ goto leave;
+ }
+
+ if (pbmfh->bfType == 0x4D42 /* 'BM' */)
+ {
+ /* Could be BITMAPCOREINFO */
+ BITMAPINFO* pConvertedInfo;
+ HDC hdc;
+
+ pvBits = (PVOID)((PCHAR)pbmfh + pbmfh->bfOffBits);
+
+ pConvertedInfo = DIB_ConvertBitmapInfo(pbmi, DIB_RGB_COLORS);
+ if(!pConvertedInfo)
+ {
+ DPRINT1("Unable to convert the bitmap Info\n");
+ goto leave;
+ }
+
+ hdc = IntGdiCreateDC(NULL, NULL, NULL, NULL,FALSE);
+
+ hbmp = GreCreateDIBitmapInternal(hdc,
+ pConvertedInfo->bmiHeader.biWidth,
+ pConvertedInfo->bmiHeader.biHeight,
+ CBM_INIT,
+ pvBits,
+ pConvertedInfo,
+ DIB_RGB_COLORS,
+ 0,
+ 0);
+
+ NtGdiDeleteObjectApp(hdc);
+ DIB_FreeConvertedBitmapInfo(pConvertedInfo, pbmi);
+ }
+ else
+ {
+ DPRINT1("Unknown file type!\n");
+ }
+
+ leave:
/* Unmap our section, we don't need it anymore */
ZwUnmapViewOfSection(NtCurrentProcess(), pbmfh);
#define NDEBUG
#include <debug.h>
+ NTSTATUS
+ NTAPI
+ RegOpenKey(
+ LPCWSTR pwszKeyName,
+ PHKEY phkey)
+ {
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING ustrKeyName;
+ HKEY hkey;
+
+ /* Initialize the key name */
+ RtlInitUnicodeString(&ustrKeyName, pwszKeyName);
+
+ /* Initialize object attributes */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &ustrKeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ /* Open the key */
+ Status = ZwOpenKey(&hkey, KEY_READ, &ObjectAttributes);
+ if (NT_SUCCESS(Status))
+ {
+ *phkey = hkey;
+ }
+
+ return Status;
+ }
+
+ NTSTATUS
+ NTAPI
+ RegQueryValue(
+ IN HKEY hkey,
+ IN PCWSTR pwszValueName,
+ IN ULONG ulType,
+ OUT PVOID pvData,
+ IN OUT PULONG pcbValue)
+ {
+ NTSTATUS Status;
+ UNICODE_STRING ustrValueName;
+ BYTE ajBuffer[100];
+ PKEY_VALUE_PARTIAL_INFORMATION pInfo;
+ ULONG cbInfoSize, cbDataSize;
+
+ /* Check if the local buffer is sufficient */
+ cbInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + *pcbValue;
+ if (cbInfoSize <= sizeof(ajBuffer))
+ {
+ pInfo = (PVOID)ajBuffer;
+ }
+ else
+ {
+ /* It's not, allocate a sufficient buffer */
+ pInfo = ExAllocatePoolWithTag(PagedPool, cbInfoSize, TAG_TEMP);
+ if (!pInfo)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
+ /* Query the value */
+ RtlInitUnicodeString(&ustrValueName, pwszValueName);
+ Status = ZwQueryValueKey(hkey,
+ &ustrValueName,
+ KeyValuePartialInformation,
+ (PVOID)pInfo,
+ cbInfoSize,
+ &cbInfoSize);
+
+ cbDataSize = cbInfoSize - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
+
+ if (NT_SUCCESS(Status))
+ {
+ /* Did we get the right type */
+ if (pInfo->Type == ulType)
+ {
+ /* Copy the contents to the caller */
+ RtlCopyMemory(pvData, pInfo->Data, min(*pcbValue, cbDataSize));
+ }
+ else
+ Status = STATUS_OBJECT_TYPE_MISMATCH;
+ }
+
+ /* Return the data size to the caller */
+ *pcbValue = cbDataSize;
+
+ /* Cleanup */
+ if (pInfo != (PVOID)ajBuffer)
+ ExFreePoolWithTag(pInfo, TAG_TEMP);
+
+ return Status;
+
+ }
+
+ VOID
+ NTAPI
+ RegWriteSZ(HKEY hkey, PWSTR pwszValue, PWSTR pwszData)
+ {
+ UNICODE_STRING ustrValue;
+ UNICODE_STRING ustrData;
+
+ RtlInitUnicodeString(&ustrValue, pwszValue);
+ RtlInitUnicodeString(&ustrData, pwszData);
+ ZwSetValueKey(hkey, &ustrValue, 0, REG_SZ, &ustrData, ustrData.Length + sizeof(WCHAR));
+ }
+
+ VOID
+ NTAPI
+ RegWriteDWORD(HKEY hkey, PWSTR pwszValue, DWORD dwData)
+ {
+ UNICODE_STRING ustrValue;
+
+ RtlInitUnicodeString(&ustrValue, pwszValue);
+ ZwSetValueKey(hkey, &ustrValue, 0, REG_DWORD, &dwData, sizeof(DWORD));
+ }
+
+ BOOL
+ NTAPI
+ RegReadDWORD(HKEY hkey, PWSTR pwszValue, PDWORD pdwData)
+ {
+ NTSTATUS Status;
+ ULONG cbSize = sizeof(DWORD);
+ Status = RegQueryValue(hkey, pwszValue, REG_DWORD, pdwData, &cbSize);
+ return NT_SUCCESS(Status);
+ }
+
BOOL
NTAPI
RegReadUserSetting(
Status = RtlAppendUnicodeToString(&usKeyName, pwszKeyName);
if (!NT_SUCCESS(Status))
{
- DPRINT1("RtlAppendUnicodeToString failed with Status=%lx, buf:%d,%d\n", Status, usKeyName.Length, usKeyName.MaximumLength);
+ DPRINT1("RtlAppendUnicodeToString failed with Status=%lx, buf:%d,%d\n",
+ Status, usKeyName.Length, usKeyName.MaximumLength);
return FALSE;
}
- /*
+ /*
* PROJECT: ReactOS Win32 Subsystem
* LICENSE: GPL - See COPYING in the top level directory
* FILE: subsystems/win32/win32k/ntddraw/dxeng.c
break;
case DxEGShDevData_hSpooler:
DPRINT1("requested DXEGSHDEVDATA DxEGShDevData_hSpooler\n");
- // retVal = (DWORD_PTR) PDev->hSpooler; // If the device is a spooler driver.
- retVal = (DWORD_PTR) PDev->VideoFileObject->DeviceObject;
+ retVal = 0;//(DWORD_PTR) PDev->hSpooler; // If the device is a spooler driver.
break;
case DxEGShDevData_DitherFmt:
DPRINT1("requested DXEGSHDEVDATA DxEGShDevData_DitherFmt\n");
PUNICODE_STRING ModuleName)
{
ULONG ArgumentLength;
- PVOID Argument;
+ PVOID Argument = NULL;
LRESULT Result = 0;
NTSTATUS Status;
PVOID ResultPointer;
ULONG ResultLength;
PHOOKPROC_CALLBACK_ARGUMENTS Common;
- CBT_CREATEWNDW *CbtCreateWnd =NULL;
+ CBT_CREATEWNDW *CbtCreateWnd = NULL;
PCHAR Extra;
PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra = NULL;
- UNICODE_STRING WindowName;
- UNICODE_STRING ClassName;
- PANSI_STRING asWindowName;
- PANSI_STRING asClassName;
PTHREADINFO pti;
+ PWND pWnd;
+ BOOL Hit = FALSE;
ASSERT(Proc);
switch(Code)
{
case HCBT_CREATEWND:
- CbtCreateWnd = (CBT_CREATEWNDW *) lParam;
- ArgumentLength += sizeof(HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS);
-
- asWindowName = (PANSI_STRING)&WindowName;
- asClassName = (PANSI_STRING)&ClassName;
-
- if (Ansi)
- {
- RtlInitAnsiString(asWindowName, (PCSZ)CbtCreateWnd->lpcs->lpszName);
- ArgumentLength += WindowName.Length + sizeof(CHAR);
- }
- else
- {
- RtlInitUnicodeString(&WindowName, CbtCreateWnd->lpcs->lpszName);
- ArgumentLength += WindowName.Length + sizeof(WCHAR);
- }
-
- if (! IS_ATOM(CbtCreateWnd->lpcs->lpszClass))
+ pWnd = UserGetWindowObject((HWND) wParam);
+ if (!pWnd)
{
- if (Ansi)
- {
- RtlInitAnsiString(asClassName, (PCSZ)CbtCreateWnd->lpcs->lpszClass);
- ArgumentLength += ClassName.Length + sizeof(CHAR);
- }
- else
- {
- RtlInitUnicodeString(&ClassName, CbtCreateWnd->lpcs->lpszClass);
- ArgumentLength += ClassName.Length + sizeof(WCHAR);
- }
+ DPRINT1("WH_CBT HCBT_CREATEWND wParam bad hWnd!\n");
+ goto Fault_Exit;
}
+ // 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
+ CbtCreateWnd = (CBT_CREATEWNDW *) lParam;
+ ArgumentLength += sizeof(HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS);
break;
case HCBT_MOVESIZE:
break;
default:
DPRINT1("Trying to call unsupported CBT hook %d\n", Code);
- return 0;
+ goto Fault_Exit;
}
break;
case WH_KEYBOARD_LL:
break;
default:
DPRINT1("Trying to call unsupported window hook %d\n", HookId);
- return 0;
+ goto Fault_Exit;
}
Argument = IntCbAllocateMemory(ArgumentLength);
if (NULL == Argument)
{
DPRINT1("HookProc callback failed: out of memory\n");
- return 0;
+ goto Fault_Exit;
}
Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Argument;
Common->HookId = HookId;
Common->Proc = Proc;
Common->Ansi = Ansi;
Common->ModuleNameLength = ModuleName->Length;
- memcpy(Common->ModuleName, ModuleName->Buffer, ModuleName->Length);
+ if (ModuleName->Buffer)
+ RtlCopyMemory(Common->ModuleName, ModuleName->Buffer, ModuleName->Length);
Extra = (PCHAR) Common->ModuleName + Common->ModuleNameLength;
switch(HookId)
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.lpszName = CbtCreateWnd->lpcs->lpszName;
Extra = (PCHAR) (CbtCreatewndExtra + 1);
- RtlCopyMemory(Extra, WindowName.Buffer, WindowName.Length);
- CbtCreatewndExtra->Cs.lpszName = (LPCWSTR) (Extra - (PCHAR) CbtCreatewndExtra);
- CbtCreatewndExtra->Cs.lpszClass = ClassName.Buffer;
- Extra += WindowName.Length;
- if (Ansi)
- {
- *((CHAR *) Extra) = '\0';
- Extra += sizeof(CHAR);
- }
- else
- {
- *((WCHAR *) Extra) = L'\0';
- Extra += sizeof(WCHAR);
- }
-
- if (! IS_ATOM(ClassName.Buffer))
- {
- RtlCopyMemory(Extra, ClassName.Buffer, ClassName.Length);
- CbtCreatewndExtra->Cs.lpszClass =
- (LPCWSTR)(ULONG_PTR) MAKELONG(Extra - (PCHAR) CbtCreatewndExtra, 1);
- Extra += ClassName.Length;
-
- if (Ansi)
- *((CHAR *) Extra) = '\0';
- else
- *((WCHAR *) Extra) = L'\0';
- }
break;
case HCBT_CLICKSKIPPED:
RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MOUSEHOOKSTRUCT));
case WH_GETMESSAGE:
RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MSG));
Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
- // DPRINT1("KHOOK Memory: %x\n",Common);
break;
case WH_FOREGROUNDIDLE:
case WH_KEYBOARD:
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Result = 0;
+ Hit = TRUE;
}
_SEH2_END;
if (!NT_SUCCESS(Status))
{
- return 0;
+ goto Fault_Exit;
}
-
- if (HookId == WH_CBT && Code == HCBT_CREATEWND)
+ /* Support write backs... SEH is in UserCallNextHookEx. */
+ switch (HookId)
{
- if (CbtCreatewndExtra)
- {
- _SEH2_TRY
- { /*
- The parameters could have been changed, include the coordinates
- and dimensions of the window. We copy it back.
- */
- CbtCreateWnd->hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
- CbtCreateWnd->lpcs->x = CbtCreatewndExtra->Cs.x;
- CbtCreateWnd->lpcs->y = CbtCreatewndExtra->Cs.y;
- CbtCreateWnd->lpcs->cx = CbtCreatewndExtra->Cs.cx;
- CbtCreateWnd->lpcs->cy = CbtCreatewndExtra->Cs.cy;
+ case WH_CBT:
+ if (Code == HCBT_CREATEWND)
+ {
+ if (CbtCreatewndExtra)
+ {/*
+ The parameters could have been changed, include the coordinates
+ and dimensions of the window. We copy it back.
+ */
+ CbtCreateWnd->hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
+ CbtCreateWnd->lpcs->x = CbtCreatewndExtra->Cs.x;
+ CbtCreateWnd->lpcs->y = CbtCreatewndExtra->Cs.y;
+ CbtCreateWnd->lpcs->cx = CbtCreatewndExtra->Cs.cx;
+ CbtCreateWnd->lpcs->cy = CbtCreatewndExtra->Cs.cy;
+ }
}
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ break;
+ // "The GetMsgProc hook procedure can examine or modify the message."
+ case WH_GETMESSAGE:
+ if (lParam)
{
- Result = 0;
+ RtlCopyMemory((PVOID) lParam, Extra, sizeof(MSG));
}
- _SEH2_END;
- }
+ break;
}
+ Fault_Exit:
+ if (Hit)
+ {
+ DPRINT1("Exception CallHookProc HookId %d Code %d\n",HookId,Code);
+ }
if (Argument) IntCbFreeMemory(Argument);
return Result;
BOOL FASTCALL
co_IntHideCaret(PTHRDCARETINFO CaretInfo)
{
+ PWND pWnd;
if(CaretInfo->hWnd && CaretInfo->Visible && CaretInfo->Showing)
{
+ pWnd = UserGetWindowObject(CaretInfo->hWnd);
co_IntSendMessage(CaretInfo->hWnd, WM_SYSTIMER, IDCARETTIMER, 0);
CaretInfo->Showing = 0;
+ IntNotifyWinEvent(EVENT_OBJECT_HIDE, pWnd, OBJID_CARET, CHILDID_SELF, 0);
return TRUE;
}
return FALSE;
co_IntDestroyCaret(PTHREADINFO Win32Thread)
{
PUSER_MESSAGE_QUEUE ThreadQueue;
+ PWND pWnd;
ThreadQueue = (PUSER_MESSAGE_QUEUE)Win32Thread->MessageQueue;
if(!ThreadQueue || !ThreadQueue->CaretInfo)
return FALSE;
+ pWnd = UserGetWindowObject(ThreadQueue->CaretInfo->hWnd);
co_IntHideCaret(ThreadQueue->CaretInfo);
ThreadQueue->CaretInfo->Bitmap = (HBITMAP)0;
ThreadQueue->CaretInfo->hWnd = (HWND)0;
ThreadQueue->CaretInfo->Size.cx = ThreadQueue->CaretInfo->Size.cy = 0;
ThreadQueue->CaretInfo->Showing = 0;
ThreadQueue->CaretInfo->Visible = 0;
+ IntNotifyWinEvent(EVENT_OBJECT_DESTROY, pWnd, OBJID_CARET, CHILDID_SELF, 0);
return TRUE;
}
co_IntSetCaretPos(int X, int Y)
{
PTHREADINFO pti;
+ PWND pWnd;
PUSER_MESSAGE_QUEUE ThreadQueue;
pti = PsGetCurrentThreadWin32Thread();
if(ThreadQueue->CaretInfo->hWnd)
{
+ pWnd = UserGetWindowObject(ThreadQueue->CaretInfo->hWnd);
if(ThreadQueue->CaretInfo->Pos.x != X || ThreadQueue->CaretInfo->Pos.y != Y)
{
co_IntHideCaret(ThreadQueue->CaretInfo);
ThreadQueue->CaretInfo->Pos.y = Y;
co_IntSendMessage(ThreadQueue->CaretInfo->hWnd, WM_SYSTIMER, IDCARETTIMER, 0);
IntSetTimer(UserGetWindowObject(ThreadQueue->CaretInfo->hWnd), IDCARETTIMER, IntGetCaretBlinkTime(), NULL, TMRF_SYSTEM);
+ IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, pWnd, OBJID_CARET, CHILDID_SELF, 0);
}
return TRUE;
}
BOOL FASTCALL co_UserShowCaret(PWND Window OPTIONAL)
{
PTHREADINFO pti;
+ PWND pWnd;
PUSER_MESSAGE_QUEUE ThreadQueue;
if (Window) ASSERT_REFS_CO(Window);
ThreadQueue->CaretInfo->Visible = 1;
if(!ThreadQueue->CaretInfo->Showing)
{
+ pWnd = UserGetWindowObject(ThreadQueue->CaretInfo->hWnd);
co_IntSendMessage(ThreadQueue->CaretInfo->hWnd, WM_SYSTIMER, IDCARETTIMER, 0);
+ IntNotifyWinEvent(EVENT_OBJECT_SHOW, pWnd, OBJID_CARET, OBJID_CARET, 0);
}
IntSetTimer(UserGetWindowObject(ThreadQueue->CaretInfo->hWnd), IDCARETTIMER, IntGetCaretBlinkTime(), NULL, TMRF_SYSTEM);
}
-
return TRUE;
}
}
ThreadQueue->CaretInfo->Visible = 0;
ThreadQueue->CaretInfo->Showing = 0;
-
+ IntNotifyWinEvent(EVENT_OBJECT_CREATE, Window, OBJID_CARET, CHILDID_SELF, 0);
RETURN(TRUE);
CLEANUP:
/*==============================================================*/
HANDLE FASTCALL
- renderBITMAPfromDIB(LPBYTE hDIB)
+ renderBITMAPfromDIB(LPBYTE pDIB)
{
HDC hdc;
HBITMAP hbitmap;
- unsigned int offset;
- BITMAPINFOHEADER *ih;
+ PBITMAPINFO pBmi, pConvertedBmi = NULL;
+ NTSTATUS Status ;
+ UINT offset = 0; /* Stupid compiler */
+
+ pBmi = (BITMAPINFO*)pDIB;
//hdc = UserGetDCEx(NULL, NULL, DCX_USESTYLE);
hdc = UserGetDCEx(ClipboardWindow, NULL, DCX_USESTYLE);
- ih = (BITMAPINFOHEADER *)hDIB;
-
- offset = sizeof(BITMAPINFOHEADER) + ((ih->biBitCount <= 8) ? (sizeof(RGBQUAD) * (1 << ih->biBitCount)) : 0);
-
- hbitmap = NtGdiCreateDIBitmapInternal(hdc,
- ih->biWidth,
- ih->biHeight,
- CBM_INIT,
- (LPBYTE)ih+offset,
- (LPBITMAPINFO)ih,
- DIB_RGB_COLORS,
- ih->biBitCount,
- ih->biSizeImage,
- 0,
- 0);
+ /* Probe it */
+ _SEH2_TRY
+ {
+ ProbeForRead(&pBmi->bmiHeader.biSize, sizeof(DWORD), 1);
+ ProbeForRead(pBmi, pBmi->bmiHeader.biSize, 1);
+ ProbeForRead(pBmi, DIB_BitmapInfoSize(pBmi, DIB_RGB_COLORS), 1);
+ pConvertedBmi = DIB_ConvertBitmapInfo(pBmi, DIB_RGB_COLORS);
+ if(!pConvertedBmi)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ else
+ {
+ offset = DIB_BitmapInfoSize((BITMAPINFO*)pBmi, DIB_RGB_COLORS);
+ ProbeForRead(pDIB + offset, pConvertedBmi->bmiHeader.biSizeImage, 1);
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END
+
+ if(!NT_SUCCESS(Status))
+ {
+ UserReleaseDC(ClipboardWindow, hdc, FALSE);
+ return NULL;
+ }
+
+ hbitmap = GreCreateDIBitmapInternal(hdc,
+ pConvertedBmi->bmiHeader.biWidth,
+ pConvertedBmi->bmiHeader.biHeight,
+ CBM_INIT,
+ pDIB+offset,
+ pConvertedBmi,
+ DIB_RGB_COLORS,
+ 0,
+ 0);
//UserReleaseDC(NULL, hdc, FALSE);
UserReleaseDC(ClipboardWindow, hdc, FALSE);
+ DIB_FreeConvertedBitmapInfo(pConvertedBmi, pBmi);
+
return hbitmap;
}
PCURICON_OBJECT OldCursor;
HCURSOR hOldCursor = (HCURSOR)0;
HDC hdcScreen;
-
+
CurInfo = IntGetSysCursorInfo();
OldCursor = CurInfo->CurrentCursorObject;
}
+
/*
* @implemented
*/
END_CLEANUP;
}
-
- /*
- * @implemented
- */
BOOL
APIENTRY
- NtUserClipCursor(
- RECTL *UnsafeRect)
+ UserClipCursor(
+ RECTL *prcl)
{
/* FIXME - check if process has WINSTA_WRITEATTRIBUTES */
PSYSTEM_CURSORINFO CurInfo;
- RECTL Rect;
PWND DesktopWindow = NULL;
- DECLARE_RETURN(BOOL);
-
- DPRINT("Enter NtUserClipCursor\n");
- UserEnterExclusive();
-
- if (NULL != UnsafeRect && ! NT_SUCCESS(MmCopyFromCaller(&Rect, UnsafeRect, sizeof(RECT))))
- {
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- RETURN(FALSE);
- }
CurInfo = IntGetSysCursorInfo();
DesktopWindow = UserGetDesktopWindow();
- if ((Rect.right > Rect.left) && (Rect.bottom > Rect.top)
- && DesktopWindow && UnsafeRect != NULL)
+ if (prcl != NULL &&
+ (prcl->right > prcl->left) &&
+ (prcl->bottom > prcl->top) &&
+ DesktopWindow != NULL)
{
-
CurInfo->bClipped = TRUE;
- RECTL_bIntersectRect(&CurInfo->rcClip, &Rect, &DesktopWindow->rcWindow);
+ RECTL_bIntersectRect(&CurInfo->rcClip, prcl, &DesktopWindow->rcWindow);
UserSetCursorPos(gpsi->ptCursor.x, gpsi->ptCursor.y, FALSE);
+ }
+ else
+ {
+ CurInfo->bClipped = FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /*
+ * @implemented
+ */
+ BOOL
+ APIENTRY
+ NtUserClipCursor(
+ RECTL *prcl)
+ {
+ RECTL rclLocal;
+ BOOL bResult;
+
+ if (prcl)
+ {
+ _SEH2_TRY
+ {
+ /* Probe and copy rect */
+ ProbeForRead(prcl, sizeof(RECTL), 1);
+ rclLocal = *prcl;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ _SEH2_YIELD(return FALSE;)
+ }
+ _SEH2_END
- RETURN(TRUE);
+ prcl = &rclLocal;
}
+
+ UserEnterExclusive();
- CurInfo->bClipped = FALSE;
- RETURN(TRUE);
+ /* Call the internal function */
+ bResult = UserClipCursor(prcl);
- CLEANUP:
- DPRINT("Leave NtUserClipCursor, ret=%i\n",_ret_);
UserLeave();
- END_CLEANUP;
+
+ return bResult;
}
/* Delete old bitmaps */
if ((CurIcon->IconInfo.hbmColor)
- && (CurIcon->IconInfo.hbmColor != IconInfo.hbmColor))
+ && (CurIcon->IconInfo.hbmColor != IconInfo.hbmColor))
{
GreDeleteObject(CurIcon->IconInfo.hbmColor);
}
if ((CurIcon->IconInfo.hbmMask)
- && (CurIcon->IconInfo.hbmMask != IconInfo.hbmMask))
+ && CurIcon->IconInfo.hbmMask != IconInfo.hbmMask)
{
GreDeleteObject(CurIcon->IconInfo.hbmMask);
}
CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy / 2;
SURFACE_UnlockSurface(psurfBmp);
- GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmMask, NULL);
}
+ GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmMask, NULL);
Ret = TRUE;
if(bAlpha && (diFlags & DI_IMAGE))
{
BLENDFUNCTION pixelblend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
- DWORD Pixel;
- BYTE Red, Green, Blue, Alpha;
- DWORD Count = 0;
+ BYTE Alpha;
INT i, j;
PSURFACE psurf;
- PBYTE pBits ;
+ PBYTE ptr ;
HBITMAP hMemBmp = NULL;
- pBits = ExAllocatePoolWithTag(PagedPool,
- bmpColor.bmWidthBytes * abs(bmpColor.bmHeight),
- TAG_BITMAP);
- if (pBits == NULL)
- {
- Ret = FALSE;
- goto CleanupAlpha;
- }
-
hMemBmp = BITMAP_CopyBitmap(hbmColor);
if(!hMemBmp)
{
DPRINT1("SURFACE_LockSurface failed!\n");
goto CleanupAlpha;
}
- /* get color bits */
- IntGetBitmapBits(psurf,
- bmpColor.bmWidthBytes * abs(bmpColor.bmHeight),
- pBits);
/* premultiply with the alpha channel value */
- for (i = 0; i < abs(bmpColor.bmHeight); i++)
+ for (i = 0; i < psurf->SurfObj.sizlBitmap.cy; i++)
{
- Count = i*bmpColor.bmWidthBytes;
- for (j = 0; j < bmpColor.bmWidth; j++)
+ ptr = (PBYTE)psurf->SurfObj.pvScan0 + i*psurf->SurfObj.lDelta;
+ for (j = 0; j < psurf->SurfObj.sizlBitmap.cx; j++)
{
- Pixel = *(DWORD *)(pBits + Count);
-
- Alpha = ((BYTE)(Pixel >> 24) & 0xff);
+ Alpha = ptr[3];
+ ptr[0] = (ptr[0] * Alpha) / 0xff;
+ ptr[1] = (ptr[1] * Alpha) / 0xff;
+ ptr[2] = (ptr[2] * Alpha) / 0xff;
- Red = (((BYTE)(Pixel >> 0)) * Alpha) / 0xff;
- Green = (((BYTE)(Pixel >> 8)) * Alpha) / 0xff;
- Blue = (((BYTE)(Pixel >> 16)) * Alpha) / 0xff;
-
- *(DWORD *)(pBits + Count) = (DWORD)(Red | (Green << 8) | (Blue << 16) | (Alpha << 24));
-
- Count += sizeof(DWORD);
+ ptr += 4;
}
}
- /* set mem bits */
- IntSetBitmapBits(psurf,
- bmpColor.bmWidthBytes * abs(bmpColor.bmHeight),
- pBits);
SURFACE_UnlockSurface(psurf);
hTmpBmp = NtGdiSelectBitmap(hMemDC, hMemBmp);
NULL);
NtGdiSelectBitmap(hMemDC, hTmpBmp);
CleanupAlpha:
- if(pBits) ExFreePoolWithTag(pBits, TAG_BITMAP);
if(hMemBmp) NtGdiDeleteObjectApp(hMemBmp);
if(Ret) goto done;
}
-
if (diFlags & DI_MASK)
{
hTmpBmp = NtGdiSelectBitmap(hMemDC, hbmMask);
{
PWND Window = NULL;
- UserEnterExclusive();
-
Window = UserGetDesktopWindow();
IntInvalidateWindows( Window,
RDW_ERASE |
RDW_INVALIDATE |
RDW_ALLCHILDREN);
- UserLeave();
}
LARGE_STRING WindowName;
PWND pWnd = NULL;
CREATESTRUCTW Cs;
+ INT i;
DECLARE_RETURN(HDESK);
DPRINT("Enter NtUserCreateDesktop: %wZ\n", lpszDesktopName);
/* Initialize some local (to win32k) desktop state. */
InitializeListHead(&DesktopObject->PtiList);
DesktopObject->ActiveMessageQueue = NULL;
+ /* Setup Global Hooks. */
+ for (i = 0; i < NB_HOOKS; i++)
+ {
+ InitializeListHead(&DesktopObject->pDeskInfo->aphkStart[i]);
+ }
ExFreePoolWithTag(DesktopName.Buffer, TAG_STRING);
if (! NT_SUCCESS(Status))
/*
- * PROJECT: ReactOS Kernel
- * LICENSE: GPL - See COPYING in the top level directory
- * FILE: subsystems/win32/win32k/ntuser/display.c
- * PURPOSE: display settings
- * COPYRIGHT: Copyright 2007 ReactOS
- *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * PURPOSE: Video initialization and display settings
+ * FILE: subsystems/win32/win32k/ntuser/display.c
+ * PROGRAMER: Timo Kreuzer (timo.kreuzer@reactos.org)
*/
- /* INCLUDES ******************************************************************/
-
#include <win32k.h>
+ #include <intrin.h>
+
#define NDEBUG
#include <debug.h>
- #define SIZEOF_DEVMODEW_300 188
- #define SIZEOF_DEVMODEW_400 212
- #define SIZEOF_DEVMODEW_500 220
+ BOOL InitSysParams();
+
+ BOOL gbBaseVideo = 0;
+
+ static const PWCHAR KEY_ROOT = L"";
+ static const PWCHAR KEY_VIDEO = L"\\Registry\\Machine\\HARDWARE\\DEVICEMAP\\VIDEO";
+
+ VOID
+ RegWriteDisplaySettings(HKEY hkey, PDEVMODEW pdm)
+ {
+ RegWriteDWORD(hkey, L"DefaultSettings.BitsPerPel", pdm->dmBitsPerPel);
+ RegWriteDWORD(hkey, L"DefaultSettings.XResolution", pdm->dmPelsWidth);
+ RegWriteDWORD(hkey, L"DefaultSettings.YResolution", pdm->dmPelsHeight);
+ RegWriteDWORD(hkey, L"DefaultSettings.Flags", pdm->dmDisplayFlags);
+ RegWriteDWORD(hkey, L"DefaultSettings.VRefresh", pdm->dmDisplayFrequency);
+ RegWriteDWORD(hkey, L"DefaultSettings.XPanning", pdm->dmPanningWidth);
+ RegWriteDWORD(hkey, L"DefaultSettings.YPanning", pdm->dmPanningHeight);
+ RegWriteDWORD(hkey, L"DefaultSettings.Orientation", pdm->dmDisplayOrientation);
+ RegWriteDWORD(hkey, L"DefaultSettings.FixedOutput", pdm->dmDisplayFixedOutput);
+ RegWriteDWORD(hkey, L"Attach.RelativeX", pdm->dmPosition.x);
+ RegWriteDWORD(hkey, L"Attach.RelativeY", pdm->dmPosition.y);
+ // RegWriteDWORD(hkey, L"Attach.ToDesktop, pdm->dmBitsPerPel", pdm->);
+ }
+
+ VOID
+ RegReadDisplaySettings(HKEY hkey, PDEVMODEW pdm)
+ {
+ DWORD dwValue;
+
+ /* Zero out the structure */
+ RtlZeroMemory(pdm, sizeof(DEVMODEW));
+
+ /* Helper macro */
+ #define READ(field, str, flag) \
+ if (RegReadDWORD(hkey, L##str, &dwValue)) \
+ { \
+ pdm->field = dwValue; \
+ pdm->dmFields |= flag; \
+ }
+
+ /* Read all present settings */
+ READ(dmBitsPerPel, "DefaultSettings.BitsPerPel", DM_BITSPERPEL);
+ READ(dmPelsWidth, "DefaultSettings.XResolution", DM_PELSWIDTH);
+ READ(dmPelsHeight, "DefaultSettings.YResolution", DM_PELSHEIGHT);
+ READ(dmDisplayFlags, "DefaultSettings.Flags", DM_DISPLAYFLAGS);
+ READ(dmDisplayFrequency, "DefaultSettings.VRefresh", DM_DISPLAYFREQUENCY);
+ READ(dmPanningWidth, "DefaultSettings.XPanning", DM_PANNINGWIDTH);
+ READ(dmPanningHeight, "DefaultSettings.YPanning", DM_PANNINGHEIGHT);
+ READ(dmDisplayOrientation, "DefaultSettings.Orientation", DM_DISPLAYORIENTATION);
+ READ(dmDisplayFixedOutput, "DefaultSettings.FixedOutput", DM_DISPLAYFIXEDOUTPUT);
+ READ(dmPosition.x, "Attach.RelativeX", DM_POSITION);
+ READ(dmPosition.y, "Attach.RelativeY", DM_POSITION);
+ }
+
+ PGRAPHICS_DEVICE
+ NTAPI
+ InitDisplayDriver(
+ IN PWSTR pwszDeviceName,
+ IN PWSTR pwszRegKey)
+ {
+ PGRAPHICS_DEVICE pGraphicsDevice;
+ UNICODE_STRING ustrDeviceName, ustrDisplayDrivers, ustrDescription;
+ NTSTATUS Status;
+ WCHAR awcBuffer[128];
+ ULONG cbSize;
+ HKEY hkey;
+ DEVMODEW dmDefault;
+
+ DPRINT1("InitDisplayDriver(%S, %S);\n",
+ pwszDeviceName, pwszRegKey);
+
+ /* Open the driver's registry key */
+ Status = RegOpenKey(pwszRegKey, &hkey);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to open registry key: %ls\n", pwszRegKey);
+ return NULL;
+ }
+
+ /* Query the diplay drivers */
+ cbSize = sizeof(awcBuffer) - 10;
+ Status = RegQueryValue(hkey,
+ L"InstalledDisplayDrivers",
+ REG_MULTI_SZ,
+ awcBuffer,
+ &cbSize);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Didn't find 'InstalledDisplayDrivers', status = 0x%lx\n", Status);
+ ZwClose(hkey);
+ return NULL;
+ }
+
+ /* Initialize the UNICODE_STRING */
+ ustrDisplayDrivers.Buffer = awcBuffer;
+ ustrDisplayDrivers.MaximumLength = cbSize;
+ ustrDisplayDrivers.Length = cbSize;
+
+ /* Set Buffer for description and size of remaining buffer */
+ ustrDescription.Buffer = awcBuffer + (cbSize / sizeof(WCHAR));
+ cbSize = sizeof(awcBuffer) - cbSize;
+
+ /* Query the device string */
+ Status = RegQueryValue(hkey,
+ L"Device Description",
+ REG_SZ,
+ ustrDescription.Buffer,
+ &cbSize);
+ if (NT_SUCCESS(Status))
+ {
+ ustrDescription.MaximumLength = cbSize;
+ ustrDescription.Length = cbSize;
+ }
+ else
+ {
+ RtlInitUnicodeString(&ustrDescription, L"<unknown>");
+ }
+
+ /* Query the default settings */
+ RegReadDisplaySettings(hkey, &dmDefault);
+
+ /* Close the registry key */
+ ZwClose(hkey);
+
+ /* Register the device with GDI */
+ RtlInitUnicodeString(&ustrDeviceName, pwszDeviceName);
+ pGraphicsDevice = EngpRegisterGraphicsDevice(&ustrDeviceName,
+ &ustrDisplayDrivers,
+ &ustrDescription,
+ &dmDefault);
+
+ return pGraphicsDevice;
+ }
+
+ BOOL
+ InitVideo(
+ PUNICODE_STRING pustrRegPath,
+ FLONG flags)
+ {
+ ULONG iDevNum, iVGACompatible = -1, ulMaxObjectNumber = 0;
+ WCHAR awcDeviceName[20];
+ WCHAR awcBuffer[256];
+ NTSTATUS Status;
+ PGRAPHICS_DEVICE pGraphicsDevice;
+ ULONG cbValue;
+ HKEY hkey;
+
+ DPRINT1("----------------------------- InitVideo() -------------------------------\n");
+
+ Status = RegOpenKey(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control", &hkey);
+ if (NT_SUCCESS(Status))
+ {
+ cbValue = 256;
+ Status = RegQueryValue(hkey, L"SystemStartOptions", REG_SZ, awcBuffer, &cbValue);
+ if (NT_SUCCESS(Status))
+ {
+ /* Check if VGA mode is requested. */
+ if (wcsstr(awcBuffer, L"/BASEVIDEO") != 0)
+ {
+ DPRINT1("VGA mode requested.\n");
+ gbBaseVideo = TRUE;
+ }
+ }
+
+ ZwClose(hkey);
+ }
+
+ /* Open the key for the adapters */
+ Status = RegOpenKey(KEY_VIDEO, &hkey);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Could not open device registry key!\n");
+ ASSERT(FALSE);
+ }
+
+ /* Read the name of the VGA adapter */
+ cbValue = 20;
+ Status = RegQueryValue(hkey, L"VgaCompatible", REG_SZ, awcDeviceName, &cbValue);
+ if (NT_SUCCESS(Status))
+ {
+ iVGACompatible = _wtoi(&awcDeviceName[13]);
+ DPRINT1("VGA adapter = %ld\n", iVGACompatible);
+ }
+
+ /* Get the maximum mumber of adapters */
+ if (!RegReadDWORD(hkey, L"MaxObjectNumber", &ulMaxObjectNumber))
+ {
+ DPRINT1("Could not read MaxObjectNumber, defaulting to 0.\n");
+ }
+
+ 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 */
+ Status = RegQueryValue(hkey, awcDeviceName, REG_SZ, awcBuffer, &cbValue);
+
+ pGraphicsDevice = InitDisplayDriver(awcDeviceName, awcBuffer);
+
+ /* Check if this is the VGA adapter */
+ if (iDevNum == iVGACompatible)
+ {
+ /* Set the VGA device as primary */
+ gpVgaGraphicsDevice = pGraphicsDevice;
+ DPRINT1("gpVgaGraphicsDevice = %p\n", gpVgaGraphicsDevice);
+ }
+
+ /* Set the first one as primary device */
+ if (!gpPrimaryGraphicsDevice)
+ gpPrimaryGraphicsDevice = pGraphicsDevice;
+ }
+
+ ZwClose(hkey);
+
+ if (gbBaseVideo)
+ {
+ if (gpVgaGraphicsDevice)
+ {
+ /* Set the VgaAdapter as primary */
+ gpPrimaryGraphicsDevice = gpVgaGraphicsDevice;
+ // FIXME: DEVMODE
+ }
+ else
+ {
+ DPRINT1("Could not find VGA compatible driver. Trying normal.\n");
+ }
+ }
+
+ InitSysParams();
- /* PUBLIC FUNCTIONS ***********************************************************/
+ return 1;
+ }
NTSTATUS
- APIENTRY
- NtUserEnumDisplaySettings(
- PUNICODE_STRING pusDeviceName,
- DWORD iModeNum,
- LPDEVMODEW lpDevMode, /* FIXME is this correct? */
- DWORD dwFlags )
+ NTAPI
+ UserEnumDisplayDevices(
+ PUNICODE_STRING pustrDevice,
+ DWORD iDevNum,
+ PDISPLAY_DEVICEW pdispdev,
+ DWORD dwFlags)
{
+ PGRAPHICS_DEVICE pGraphicsDevice;
+ ULONG cbSize;
+ HKEY hkey;
NTSTATUS Status;
- LPDEVMODEW pSafeDevMode;
- PUNICODE_STRING pusSafeDeviceName = NULL;
- UNICODE_STRING usSafeDeviceName;
- USHORT Size = 0, ExtraSize = 0;
- /* Copy the devmode */
- _SEH2_TRY
+ /* Ask gdi for the GRAPHICS_DEVICE */
+ pGraphicsDevice = EngpFindGraphicsDevice(pustrDevice, iDevNum, 0);
+ if (!pGraphicsDevice)
{
- ProbeForRead(lpDevMode, sizeof(DEVMODEW), 1);
- Size = lpDevMode->dmSize;
- ExtraSize = lpDevMode->dmDriverExtra;
+ /* No device found */
+ DPRINT1("No GRAPHICS_DEVICE found\n");
+ return STATUS_UNSUCCESSFUL;
}
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+
+ /* Open thhe device map registry key */
+ Status = RegOpenKey(KEY_VIDEO, &hkey);
+ if (!NT_SUCCESS(Status))
{
- DPRINT("FIXME ? : Out of range of DEVMODEW size \n");
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ /* No device found */
+ DPRINT1("Could not open reg key\n");
+ return STATUS_UNSUCCESSFUL;
}
- _SEH2_END;
- if (Size != sizeof(DEVMODEW))
+ /* Query the registry path */
+ cbSize = sizeof(pdispdev->DeviceKey);
+ RegQueryValue(hkey,
+ pGraphicsDevice->szNtDeviceName,
+ REG_SZ,
+ pdispdev->DeviceKey,
+ &cbSize);
+
+ /* Close registry key */
+ ZwClose(hkey);
+
+ /* Copy device name, device string and StateFlags */
+ wcsncpy(pdispdev->DeviceName, pGraphicsDevice->szWinDeviceName, 32);
+ wcsncpy(pdispdev->DeviceString, pGraphicsDevice->pwszDescription, 128);
+ pdispdev->StateFlags = pGraphicsDevice->StateFlags;
+
+ // FIXME: fill in DEVICE ID
+
+ return STATUS_SUCCESS;
+ }
+
+ //NTSTATUS
+ BOOL
+ NTAPI
+ NtUserEnumDisplayDevices(
+ PUNICODE_STRING pustrDevice,
+ DWORD iDevNum,
+ PDISPLAY_DEVICEW pDisplayDevice,
+ DWORD dwFlags)
+ {
+ UNICODE_STRING ustrDevice;
+ WCHAR awcDevice[CCHDEVICENAME];
+ DISPLAY_DEVICEW dispdev;
+ NTSTATUS Status;
+
+ DPRINT("Enter NtUserEnumDisplayDevices(%wZ, %ld)\n",
+ pustrDevice, iDevNum);
+
+ // FIXME: HACK, desk.cpl passes broken crap
+ if (pustrDevice && iDevNum != 0)
+ return FALSE;
+
+ dispdev.cb = sizeof(DISPLAY_DEVICEW);
+
+ if (pustrDevice)
{
- return STATUS_BUFFER_TOO_SMALL;
+ /* Initialize destination string */
+ RtlInitEmptyUnicodeString(&ustrDevice, awcDevice, sizeof(awcDevice));
+
+ _SEH2_TRY
+ {
+ /* Probe the UNICODE_STRING and the buffer */
+ ProbeForRead(pustrDevice, sizeof(UNICODE_STRING), 1);
+ ProbeForRead(pustrDevice->Buffer, pustrDevice->Length, 1);
+
+ /* Copy the string */
+ RtlCopyUnicodeString(&ustrDevice, pustrDevice);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ // _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ _SEH2_YIELD(return NT_SUCCESS(_SEH2_GetExceptionCode()));
+ }
+ _SEH2_END
+
+ if (ustrDevice.Length > 0)
+ pustrDevice = &ustrDevice;
+ else
+ pustrDevice = NULL;
+ }
+
+ /* Acquire global USER lock */
+ UserEnterExclusive();
+
+ /* Call the internal function */
+ Status = UserEnumDisplayDevices(pustrDevice, iDevNum, &dispdev, dwFlags);
+
+ /* Release lock */
+ UserLeave();
+
+ /* On success copy data to caller */
+ if (NT_SUCCESS(Status))
+ {
+ /* Enter SEH */
+ _SEH2_TRY
+ {
+ /* First probe the cb field */
+ ProbeForWrite(&pDisplayDevice->cb, sizeof(DWORD), 1);
+
+ /* Check the buffer size */
+ if (pDisplayDevice->cb)
+ {
+ /* Probe the output buffer */
+ pDisplayDevice->cb = min(pDisplayDevice->cb, sizeof(dispdev));
+ ProbeForWrite(pDisplayDevice, pDisplayDevice->cb, 1);
+
+ /* Copy as much as the given buffer allows */
+ RtlCopyMemory(pDisplayDevice, &dispdev, pDisplayDevice->cb);
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END
}
- pSafeDevMode = ExAllocatePoolWithTag(PagedPool, Size + ExtraSize, GDITAG_DEVMODE);
- if (pSafeDevMode == NULL)
+ DPRINT1("Leave NtUserEnumDisplayDevices, Status = 0x%lx\n", Status);
+ /* Return the result */
+ // return Status;
+ return NT_SUCCESS(Status); // FIXME
+ }
+
+ NTSTATUS
+ NTAPI
+ UserEnumCurrentDisplaySettings(
+ PUNICODE_STRING pustrDevice,
+ PDEVMODEW *ppdm)
+ {
+ PPDEVOBJ ppdev;
+
+ /* Get the PDEV for the device */
+ ppdev = EngpGetPDEV(pustrDevice);
+ if (!ppdev)
{
- return STATUS_NO_MEMORY;
+ /* No device found */
+ DPRINT1("No PDEV found!\n");
+ return STATUS_UNSUCCESSFUL;
}
- pSafeDevMode->dmSize = Size;
- pSafeDevMode->dmDriverExtra = ExtraSize;
- /* Copy the device name */
- if (pusDeviceName != NULL)
+ *ppdm = ppdev->pdmwDev;
+ PDEVOBJ_vRelease(ppdev);
+
+ return STATUS_SUCCESS;
+ }
+
+ NTSTATUS
+ NTAPI
+ UserEnumDisplaySettings(
+ PUNICODE_STRING pustrDevice,
+ DWORD iModeNum,
+ LPDEVMODEW *ppdm,
+ DWORD dwFlags)
+ {
+ PGRAPHICS_DEVICE pGraphicsDevice;
+ PDEVMODEENTRY pdmentry;
+ ULONG i, iFoundMode;
+
+ DPRINT("Enter UserEnumDisplaySettings('%ls', %ld)\n",
+ pustrDevice ? pustrDevice->Buffer : NULL, iModeNum);
+
+ /* Ask gdi for the GRAPHICS_DEVICE */
+ pGraphicsDevice = EngpFindGraphicsDevice(pustrDevice, 0, 0);
+
+ if (!pGraphicsDevice)
{
- Status = IntSafeCopyUnicodeString(&usSafeDeviceName, pusDeviceName);
- if (!NT_SUCCESS(Status))
+ /* No device found */
+ DPRINT1("No device found!\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (iModeNum >= pGraphicsDevice->cDevModes)
+ return STATUS_NO_MORE_ENTRIES;
+
+ iFoundMode = 0;
+ for (i = 0; i < pGraphicsDevice->cDevModes; i++)
+ {
+ pdmentry = &pGraphicsDevice->pDevModeList[i];
+
+ /* FIXME: consider EDS_RAWMODE */
+ #if 0
+ if ((!(dwFlags & EDS_RAWMODE) && (pdmentry->dwFlags & 1)) ||!
+ (dwFlags & EDS_RAWMODE))
+ #endif
{
- ExFreePool(pSafeDevMode);
- return Status;
+ /* Is this the one we want? */
+ if (iFoundMode == iModeNum)
+ {
+ *ppdm = pdmentry->pdm;
+ return STATUS_SUCCESS;
+ }
+
+ /* Increment number of found modes */
+ iFoundMode++;
}
- pusSafeDeviceName = &usSafeDeviceName;
}
- /* Call internal function */
- Status = IntEnumDisplaySettings(pusSafeDeviceName, iModeNum, pSafeDevMode, dwFlags);
+ /* Nothing was found */
+ return STATUS_INVALID_PARAMETER;
+ }
- if (pusSafeDeviceName != NULL)
- RtlFreeUnicodeString(pusSafeDeviceName);
+ NTSTATUS
+ NTAPI
+ UserOpenDisplaySettingsKey(
+ OUT PHKEY phkey,
+ IN PUNICODE_STRING pustrDevice,
+ IN BOOL bGlobal)
+ {
+ HKEY hkey;
+ DISPLAY_DEVICEW dispdev;
+ NTSTATUS Status;
+ /* Get device info */
+ Status = UserEnumDisplayDevices(pustrDevice, 0, &dispdev, 0);
if (!NT_SUCCESS(Status))
+ return Status;
+
+ if (bGlobal)
{
- ExFreePool(pSafeDevMode);
+ // FIXME: need to fix the registry key somehow
+ }
+
+ /* Open the registry key */
+ Status = RegOpenKey(dispdev.DeviceKey, &hkey);
+ if (!NT_SUCCESS(Status))
return Status;
+
+ *phkey = hkey;
+
+ return Status;
+ }
+
+ NTSTATUS
+ NTAPI
+ UserEnumRegistryDisplaySettings(
+ IN PUNICODE_STRING pustrDevice,
+ OUT LPDEVMODEW pdm)
+ {
+ HKEY hkey;
+ NTSTATUS Status = UserOpenDisplaySettingsKey(&hkey, pustrDevice, 0);
+ if(NT_SUCCESS(Status))
+ {
+ RegReadDisplaySettings(hkey, pdm);
+ ZwClose(hkey);
+ return STATUS_SUCCESS;
}
+ return Status ;
+ }
+
+
+ NTSTATUS
+ APIENTRY
+ NtUserEnumDisplaySettings(
+ IN PUNICODE_STRING pustrDevice,
+ IN DWORD iModeNum,
+ OUT LPDEVMODEW lpDevMode,
+ IN DWORD dwFlags)
+ {
+ UNICODE_STRING ustrDevice;
+ WCHAR awcDevice[CCHDEVICENAME];
+ NTSTATUS Status;
+ ULONG cbSize, cbExtra;
+ DEVMODEW dmReg, *pdm;
- /* Copy some information back */
- _SEH2_TRY
+ DPRINT1("Enter NtUserEnumDisplaySettings(%ls, %ld)\n",
+ pustrDevice ? pustrDevice->Buffer : 0, iModeNum);
+
+ if (pustrDevice)
{
- ProbeForWrite(lpDevMode,Size + ExtraSize, 1);
- lpDevMode->dmPelsWidth = pSafeDevMode->dmPelsWidth;
- lpDevMode->dmPelsHeight = pSafeDevMode->dmPelsHeight;
- lpDevMode->dmBitsPerPel = pSafeDevMode->dmBitsPerPel;
- lpDevMode->dmDisplayFrequency = pSafeDevMode->dmDisplayFrequency;
- lpDevMode->dmDisplayFlags = pSafeDevMode->dmDisplayFlags;
+ /* Initialize destination string */
+ RtlInitEmptyUnicodeString(&ustrDevice, awcDevice, sizeof(awcDevice));
- /* output private/extra driver data */
- if (ExtraSize > 0)
+ _SEH2_TRY
{
- memcpy((PCHAR)lpDevMode + Size, (PCHAR)pSafeDevMode + Size, ExtraSize);
+ /* Probe the UNICODE_STRING and the buffer */
+ ProbeForRead(pustrDevice, sizeof(UNICODE_STRING), 1);
+ ProbeForRead(pustrDevice->Buffer, pustrDevice->Length, 1);
+
+ /* Copy the string */
+ RtlCopyUnicodeString(&ustrDevice, pustrDevice);
}
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END
+
+ pustrDevice = &ustrDevice;
+ }
+
+ /* Acquire global USER lock */
+ UserEnterExclusive();
+
+ if (iModeNum == ENUM_REGISTRY_SETTINGS)
+ {
+ /* Get the registry settings */
+ Status = UserEnumRegistryDisplaySettings(pustrDevice, &dmReg);
+ pdm = &dmReg;
}
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ else if (iModeNum == ENUM_CURRENT_SETTINGS)
{
- Status = _SEH2_GetExceptionCode();
+ /* Get the current settings */
+ Status = UserEnumCurrentDisplaySettings(pustrDevice, &pdm);
+ }
+ else
+ {
+ /* Get specified settings */
+ Status = UserEnumDisplaySettings(pustrDevice, iModeNum, &pdm, dwFlags);
+ }
+
+ /* Release lock */
+ UserLeave();
+
+ /* Did we succeed? */
+ if (NT_SUCCESS(Status))
+ {
+ /* Copy some information back */
+ _SEH2_TRY
+ {
+ ProbeForRead(lpDevMode, sizeof(DEVMODEW), 1);
+ cbSize = lpDevMode->dmSize;
+ cbExtra = lpDevMode->dmDriverExtra;
+
+ ProbeForWrite(lpDevMode, cbSize + cbExtra, 1);
+ /* Output what we got */
+ RtlCopyMemory(lpDevMode, pdm, min(cbSize, pdm->dmSize));
+
+ /* output private/extra driver data */
+ if (cbExtra > 0 && pdm->dmDriverExtra > 0)
+ {
+ RtlCopyMemory((PCHAR)lpDevMode + cbSize,
+ (PCHAR)pdm + pdm->dmSize,
+ min(cbExtra, pdm->dmDriverExtra));
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
}
- _SEH2_END;
- ExFreePool(pSafeDevMode);
return Status;
}
+ BOOL APIENTRY UserClipCursor(RECTL *prcl);
+ VOID APIENTRY UserRedrawDesktop();
+ HCURSOR FASTCALL UserSetCursor(PCURICON_OBJECT NewCursor, BOOL ForceChange);
LONG
APIENTRY
- NtUserChangeDisplaySettings(
- PUNICODE_STRING lpszDeviceName,
- LPDEVMODEW lpDevMode,
+ UserChangeDisplaySettings(
+ PUNICODE_STRING pustrDevice,
+ LPDEVMODEW pdm,
HWND hwnd,
- DWORD dwflags,
+ DWORD flags,
LPVOID lParam)
{
- NTSTATUS Status = STATUS_SUCCESS;
- LPDEVMODEW lpSafeDevMode = NULL;
- DEVMODEW DevMode;
- PUNICODE_STRING pSafeDeviceName = NULL;
- UNICODE_STRING SafeDeviceName;
- LONG Ret;
-
- /* Check arguments */
- #ifdef CDS_VIDEOPARAMETERS
- if (dwflags != CDS_VIDEOPARAMETERS && lParam != NULL)
- #else
- if (lParam != NULL)
- #endif
+ DEVMODEW dm;
+ LONG lResult = DISP_CHANGE_SUCCESSFUL;
+ HKEY hkey;
+ NTSTATUS Status;
+ PPDEVOBJ ppdev;
+ PDESKTOP pdesk;
+
+ /* If no DEVMODE is given, use registry settings */
+ if (!pdm)
{
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ /* Get the registry settings */
+ Status = UserEnumRegistryDisplaySettings(pustrDevice, &dm);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Could not load registry settings\n");
+ return DISP_CHANGE_BADPARAM;
+ }
+ }
+ else if (pdm->dmSize < FIELD_OFFSET(DEVMODEW, dmFields))
+ return DISP_CHANGE_BADMODE; /* This is what winXP SP3 returns */
+ else
+ dm = *pdm;
+
+ /* Check params */
+ if ((dm.dmFields & (DM_PELSWIDTH | DM_PELSHEIGHT)) != (DM_PELSWIDTH | DM_PELSHEIGHT))
+ {
+ DPRINT1("devmode doesn't specify the resolution.\n");
+ return DISP_CHANGE_BADMODE;
+ }
+
+ /* Get the PDEV */
+ ppdev = EngpGetPDEV(pustrDevice);
+ if (!ppdev)
+ {
+ DPRINT1("failed to get PDEV\n");
return DISP_CHANGE_BADPARAM;
}
- if (hwnd != NULL)
+ /* Fixup values */
+ if(dm.dmBitsPerPel == 0 || !(dm.dmFields & DM_BITSPERPEL))
+ {
+ dm.dmBitsPerPel = ppdev->pdmwDev->dmBitsPerPel;
+ dm.dmFields |= DM_BITSPERPEL;
+ }
+
+ if((dm.dmFields & DM_DISPLAYFREQUENCY) && (dm.dmDisplayFrequency == 0))
+ dm.dmDisplayFrequency = ppdev->pdmwDev->dmDisplayFrequency;
+
+ /* Look for the requested DEVMODE */
+ pdm = PDEVOBJ_pdmMatchDevMode(ppdev, &dm);
+ if (!pdm)
+ {
+ DPRINT1("Could not find a matching DEVMODE\n");
+ lResult = DISP_CHANGE_BADMODE;
+ goto leave;
+ }
+ else if (flags & CDS_TEST)
+ {
+ /* It's possible, go ahead! */
+ lResult = DISP_CHANGE_SUCCESSFUL;
+ goto leave;
+ }
+
+ /* Shall we update the registry? */
+ if (flags & CDS_UPDATEREGISTRY)
+ {
+ /* Open the local or global settings key */
+ Status = UserOpenDisplaySettingsKey(&hkey, pustrDevice, flags & CDS_GLOBAL);
+ if (NT_SUCCESS(Status))
+ {
+ /* Store the settings */
+ RegWriteDisplaySettings(hkey, pdm);
+
+ /* Close the registry key */
+ ZwClose(hkey);
+ }
+ else
+ {
+ DPRINT1("Could not open registry key\n");
+ lResult = DISP_CHANGE_NOTUPDATED;
+ }
+ }
+
+ /* Check if DEVMODE matches the current mode */
+ if (pdm == ppdev->pdmwDev && !(flags & CDS_RESET))
+ {
+ DPRINT1("DEVMODE matches, nothing to do\n");
+ goto leave;
+ }
+
+ /* Shall we apply the settings? */
+ if (!(flags & CDS_NORESET))
+ {
+ ULONG ulResult;
+
+ /* Remove mouse pointer */
+ UserSetCursor(NULL, TRUE);
+
+ /* Do the mode switch */
+ ulResult = PDEVOBJ_bSwitchMode(ppdev, pdm);
+
+ /* Restore mouse pointer, no hooks called */
+ UserSetCursorPos(gpsi->ptCursor.x, gpsi->ptCursor.y, FALSE);
+
+ /* Check for failure */
+ if (!ulResult)
+ {
+ DPRINT1("failed to set mode\n");
+ lResult = (lResult == DISP_CHANGE_NOTUPDATED) ?
+ DISP_CHANGE_FAILED : DISP_CHANGE_RESTART;
+
+ goto leave;
+ }
+
+ /* Update the system metrics */
+ InitMetrics();
+
+ //IntvGetDeviceCaps(&PrimarySurface, &GdiHandleTable->DevCaps);
+
+ /* Remove all cursor clipping */
+ UserClipCursor(NULL);
+
+ pdesk = IntGetActiveDesktop();
+ //IntHideDesktop(pdesk);
+
+ /* Send WM_DISPLAYCHANGE to all toplevel windows */
+ co_IntSendMessageTimeout(HWND_BROADCAST,
+ WM_DISPLAYCHANGE,
+ (WPARAM)ppdev->gdiinfo.cBitsPixel,
+ (LPARAM)(ppdev->gdiinfo.ulHorzRes + (ppdev->gdiinfo.ulVertRes << 16)),
+ SMTO_NORMAL,
+ 100,
+ &ulResult);
+
+ //co_IntShowDesktop(pdesk, ppdev->gdiinfo.ulHorzRes, ppdev->gdiinfo.ulVertRes);
+
+ UserRedrawDesktop();
+ }
+
+ leave:
+ /* Release the PDEV */
+ PDEVOBJ_vRelease(ppdev);
+
+ return lResult;
+ }
+
+ LONG
+ APIENTRY
+ NtUserChangeDisplaySettings(
+ PUNICODE_STRING pustrDevice,
+ LPDEVMODEW lpDevMode,
+ HWND hwnd,
+ DWORD dwflags,
+ LPVOID lParam)
+ {
+ WCHAR awcDevice[CCHDEVICENAME];
+ UNICODE_STRING ustrDevice;
+ DEVMODEW dmLocal;
+ LONG lRet;
+
+ /* Check arguments */
+ if ((dwflags != CDS_VIDEOPARAMETERS && lParam != NULL) ||
+ (hwnd != NULL))
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return DISP_CHANGE_BADPARAM;
}
- /* Copy devmode */
- if (lpDevMode != NULL)
+ /* Check flags */
+ if ((dwflags & (CDS_GLOBAL|CDS_NORESET)) && !(dwflags & CDS_UPDATEREGISTRY))
+ {
+ return DISP_CHANGE_BADFLAGS;
+ }
+
+ /* Copy the device name */
+ if (pustrDevice)
{
+ /* Initialize destination string */
+ RtlInitEmptyUnicodeString(&ustrDevice, awcDevice, sizeof(awcDevice));
+
_SEH2_TRY
{
- ProbeForRead(lpDevMode, sizeof(DevMode.dmSize), 1);
- DevMode.dmSize = lpDevMode->dmSize;
- DevMode.dmSize = min(sizeof(DevMode), DevMode.dmSize);
- ProbeForRead(lpDevMode, DevMode.dmSize, 1);
- RtlCopyMemory(&DevMode, lpDevMode, DevMode.dmSize);
+ /* Probe the UNICODE_STRING and the buffer */
+ ProbeForRead(pustrDevice, sizeof(UNICODE_STRING), 1);
+ ProbeForRead(pustrDevice->Buffer, pustrDevice->Length, 1);
+
+ /* Copy the string */
+ RtlCopyUnicodeString(&ustrDevice, pustrDevice);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- Status = _SEH2_GetExceptionCode();
+ /* Set and return error */
+ SetLastNtError(_SEH2_GetExceptionCode());
+ _SEH2_YIELD(return DISP_CHANGE_BADPARAM);
}
_SEH2_END
- if (!NT_SUCCESS(Status))
+ pustrDevice = &ustrDevice;
+ }
+
+ /* Copy devmode */
+ if (lpDevMode)
+ {
+ _SEH2_TRY
{
- SetLastNtError(Status);
- return DISP_CHANGE_BADPARAM;
- }
+ /* Probe the size field of the structure */
+ ProbeForRead(lpDevMode, sizeof(dmLocal.dmSize), 1);
- if (DevMode.dmDriverExtra > 0)
+ /* Calculate usable size */
+ dmLocal.dmSize = min(sizeof(dmLocal), lpDevMode->dmSize);
+
+ /* Probe and copy the full DEVMODE */
+ ProbeForRead(lpDevMode, dmLocal.dmSize, 1);
+ RtlCopyMemory(&dmLocal, lpDevMode, dmLocal.dmSize);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- DPRINT1("lpDevMode->dmDriverExtra is IGNORED!\n");
- DevMode.dmDriverExtra = 0;
+ /* Set and return error */
+ SetLastNtError(_SEH2_GetExceptionCode());
+ _SEH2_YIELD(return DISP_CHANGE_BADPARAM);
}
- lpSafeDevMode = &DevMode;
- }
+ _SEH2_END
- /* Copy the device name */
- if (lpszDeviceName != NULL)
- {
- Status = IntSafeCopyUnicodeString(&SafeDeviceName, lpszDeviceName);
- if (!NT_SUCCESS(Status))
+ /* Check for extra parameters */
+ if (dmLocal.dmDriverExtra > 0)
{
- SetLastNtError(Status);
- return DISP_CHANGE_BADPARAM;
+ /* FIXME: TODO */
+ DPRINT1("lpDevMode->dmDriverExtra is IGNORED!\n");
+ dmLocal.dmDriverExtra = 0;
}
- pSafeDeviceName = &SafeDeviceName;
+
+ /* Use the local structure */
+ lpDevMode = &dmLocal;
}
+ // FIXME: Copy videoparameters
+
+ /* Acquire global USER lock */
+ UserEnterExclusive();
+
/* Call internal function */
- Ret = IntChangeDisplaySettings(pSafeDeviceName, lpSafeDevMode, dwflags, lParam);
+ lRet = UserChangeDisplaySettings(pustrDevice, lpDevMode, hwnd, dwflags, NULL);
- if (pSafeDeviceName != NULL)
- RtlFreeUnicodeString(pSafeDeviceName);
+ /* Release lock */
+ UserLeave();
- return Ret;
+ return lRet;
}
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: Window event handlers
- * FILE: subsystem/win32/win32k/ntuser/event.c
+ * FILE: subsystems/win32/win32k/ntuser/event.c
* PROGRAMER: James Tabor (james.tabor@rectos.org)
*/
LONG idChild)
{
NTSTATUS Status;
- ULONG_PTR uResult;
- EVENTPACK EP;
+ PEVENTPACK pEP;
+ ULONG_PTR uResult = 0;
- EP.pEH = pEH;
- EP.idObject = idObject;
- EP.idChild = idChild;
+ pEP = ExAllocatePoolWithTag(NonPagedPool, sizeof(EVENTPACK), TAG_HOOK);
+ if (!pEP) return 0;
+
+ pEP->pEH = pEH;
+ pEP->idObject = idObject;
+ pEP->idChild = idChild;
/* FIXME should get timeout from
* HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */
hwnd,
event,
0,
- (LPARAM)&EP,
+ (LPARAM)pEP,
5000,
TRUE,
MSQ_ISEVENT,
&uResult);
-
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePoolWithTag(pEP, TAG_HOOK);
+ }
return NT_SUCCESS(Status) ? uResult : 0;
}
-
static
BOOL
FASTCALL
return FALSE;
}
+ VOID
+ FASTCALL
+ EVENT_DestroyThreadEvents(PETHREAD Thread)
+ {
+ PTHREADINFO pti;
+ PEVENTHOOK pEH;
+ PLIST_ENTRY pLE;
+
+ pti = Thread->Tcb.Win32Thread;
+ if (!pti) return;
+
+ if (!GlobalEvents || !GlobalEvents->Counts) return;
+
+ pLE = GlobalEvents->Events.Flink;
+ if (IsListEmpty(pLE)) return;
+
+ pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain);
+ do
+ {
+ if (IsListEmpty(pLE)) break;
+ if (!pEH) break;
+ pLE = pEH->Chain.Flink;
+ if (pEH->head.pti == pti)
+ {
+ IntRemoveEvent(pEH);
+ }
+ pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain);
+ } while (pLE != &GlobalEvents->Events);
+
+ return;
+ }
+
/* FUNCTIONS *****************************************************************/
+ //
+ // Dispatch MsgQueue Event Call processor!
+ //
LRESULT
FASTCALL
co_EVENT_CallEvents( DWORD event,
- HWND hwnd,
- UINT_PTR idObject,
- LONG_PTR idChild)
+ HWND hwnd,
+ UINT_PTR idObject,
+ LONG_PTR idChild)
{
PEVENTHOOK pEH;
LRESULT Result;
hwnd,
pEP->idObject,
pEP->idChild,
- (DWORD_PTR)(NtCurrentTeb()->ClientId).UniqueThread,
+ PtrToUint(NtCurrentTeb()->ClientId.UniqueThread),
(DWORD)EngGetTickCount(),
pEH->Proc);
+
+ ExFreePoolWithTag(pEP, TAG_HOOK);
return Result;
}
DWORD Event,
PWND pWnd,
LONG idObject,
- LONG idChild)
+ LONG idChild,
+ DWORD flags)
{
PEVENTHOOK pEH;
PLIST_ENTRY pLE;
+ PTHREADINFO pti, ptiCurrent;
DPRINT("IntNotifyWinEvent GlobalEvents = 0x%x pWnd 0x%x\n",GlobalEvents, pWnd);
- if (!pWnd) return;
+ if (!GlobalEvents || !GlobalEvents->Counts) return;
if (pWnd && pWnd->state & WNDS_DESTROYED) return;
- if (!GlobalEvents || !GlobalEvents->Counts) return;
+ ptiCurrent = PsGetCurrentThreadWin32Thread();
+
+ if (pWnd && flags & WEF_SETBYWNDPTI)
+ pti = pWnd->head.pti;
+ else
+ pti = ptiCurrent;
pLE = GlobalEvents->Events.Flink;
pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain);
do
- {
+ {
+ if (!pEH) break;
UserReferenceObject(pEH);
// Must be inside the event window.
if ( (pEH->eventMin <= Event) && (pEH->eventMax >= Event))
{
- if (pEH->head.pti->pEThread != PsGetCurrentThread())
- { // if all process || all thread || other thread same process
- if (!(pEH->idProcess) || !(pEH->idThread) ||
- (NtCurrentTeb()->ClientId.UniqueProcess == (PVOID)(DWORD_PTR)pEH->idProcess))
+ // if all process || all thread || other thread same process
+ // if ^skip own thread && ((Pid && CPid == Pid && ^skip own process) || all process)
+ if ( (!pEH->idProcess || pEH->idProcess == PtrToUint(pti->pEThread->Cid.UniqueProcess)) &&
+ (!(pEH->Flags & WINEVENT_SKIPOWNPROCESS) || pEH->head.pti->ppi != pti->ppi) &&
+ (!pEH->idThread || pEH->idThread == PtrToUint(pti->pEThread->Cid.UniqueThread)) &&
+ (!(pEH->Flags & WINEVENT_SKIPOWNTHREAD) || pEH->head.pti != pti) &&
+ pEH->head.pti->rpdesk == ptiCurrent->rpdesk ) // Same as hooks.
+ {
+ // Send message to the thread if pEH is not current.
+ if (pEH->head.pti != ptiCurrent)
{
+ DPRINT1("Global Event 0x%x, idObject %d\n", Event, idObject);
IntCallLowLevelEvent( pEH,
Event,
UserHMGetHandle(pWnd),
idObject,
idChild);
}
- }// if ^skip own thread && ((Pid && CPid == Pid && ^skip own process) || all process)
- else if ( !(pEH->Flags & WINEVENT_SKIPOWNTHREAD) &&
- ( ((pEH->idProcess &&
- NtCurrentTeb()->ClientId.UniqueProcess == (PVOID)(DWORD_PTR)pEH->idProcess) &&
- !(pEH->Flags & WINEVENT_SKIPOWNPROCESS)) ||
- !pEH->idProcess ) )
- {
- // What in the deuce is this right-aligned formatting?
- co_IntCallEventProc( UserHMGetHandle(pEH),
- Event,
- UserHMGetHandle(pWnd),
- idObject,
- idChild,
- PtrToUint(NtCurrentTeb()->ClientId.UniqueThread),
- (DWORD)EngGetTickCount(),
- pEH->Proc);
- }
+ else
+ {
+ DPRINT1("Local Event 0x%x, idObject %d\n", Event, idObject);
+ co_IntCallEventProc( UserHMGetHandle(pEH),
+ Event,
+ UserHMGetHandle(pWnd),
+ idObject,
+ idChild,
+ PtrToUint(NtCurrentTeb()->ClientId.UniqueThread),
+ (DWORD)EngGetTickCount(),
+ pEH->Proc);
+ }
+ }
}
UserDereferenceObject(pEH);
pLE = pEH->Chain.Flink;
UserEnterExclusive();
/* Validate input */
- if (hWnd && (hWnd != INVALID_HANDLE_VALUE) && !(Window = UserGetWindowObject(hWnd)))
+ if (hWnd && (hWnd != INVALID_HANDLE_VALUE))
{
- UserLeave();
- return;
+ Window = UserGetWindowObject(hWnd);
+ if (!Window)
+ {
+ UserLeave();
+ return;
+ }
}
if (gpsi->dwInstalledEventHooks & GetMaskFromEvent(Event))
{
- UserRefObjectCo(Window, &Ref);
- IntNotifyWinEvent( Event, Window, idObject, idChild);
- UserDerefObjectCo(Window);
+ if (Window) UserRefObjectCo(Window, &Ref);
+ IntNotifyWinEvent( Event, Window, idObject, idChild, WEF_SETBYWNDPTI);
+ if (Window) UserDerefObjectCo(Window);
}
UserLeave();
}
goto SetEventExit;
}
}
-
+ // Creator, pti is set here.
pEH = UserCreateObject(gHandleTable, NULL, &Handle, otEvent, sizeof(EVENTHOOK));
if (pEH)
{
GlobalEvents->Counts++;
UserHMGetHandle(pEH) = Handle;
- if (Thread)
- pEH->head.pti = Thread->Tcb.Win32Thread;
- else
- pEH->head.pti = GetW32ThreadInfo();
pEH->eventMin = eventMin;
pEH->eventMax = eventMax;
- pEH->idProcess = idProcess;
- pEH->idThread = idThread;
+ pEH->idProcess = idProcess; // These are cmp'ed
+ pEH->idThread = idThread; // "
pEH->Flags = dwflags;
-
+ /*
+ If WINEVENT_INCONTEXT, set offset from hmod and proc. Save ihmod from
+ the atom index table where the hmod data is saved to be recalled later
+ if fSync set by WINEVENT_INCONTEXT.
+ If WINEVENT_OUTOFCONTEXT just use proc..
+ Do this instead....
+ */
if (NULL != hmodWinEventProc)
{
pEH->offPfn = (ULONG_PTR)((char *)lpfnWinEventProc - (char *)hmodWinEventProc);
{
if (hWndPrev)
{
+ IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0);
co_IntPostOrSendMessage(hWndPrev, WM_KILLFOCUS, (WPARAM)hWnd, 0);
}
}
{
if (hWnd)
{
+ PWND pWnd = UserGetWindowObject(hWnd);
+ IntNotifyWinEvent(EVENT_OBJECT_FOCUS, pWnd, OBJID_CLIENT, CHILDID_SELF, 0);
co_IntPostOrSendMessage(hWnd, WM_SETFOCUS, (WPARAM)hWndPrev, 0);
}
}
cbt.fMouse = FALSE;
cbt.hWndActive = hWndPrev;
if (co_HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt))
+ {
+ DPRINT1("SetActiveWindow WH_CBT Call Hook return!\n");
return 0;
-
+ }
ThreadQueue->ActiveWindow = hWnd;
co_IntSendDeactivateMessages(hWndPrev, hWnd);
return hWndPrev;
}
- if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)Window->head.h, (LPARAM)hWndPrev))
- return 0;
-
+ if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)Window->head.h, (LPARAM)hWndPrev))
+ {
+ DPRINT1("SetFocusWindow 1 WH_CBT Call Hook return!\n");
+ return 0;
+ }
ThreadQueue->FocusWindow = Window->head.h;
co_IntSendKillFocusMessages(hWndPrev, Window->head.h);
else
{
ThreadQueue->FocusWindow = 0;
-
- if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)0, (LPARAM)hWndPrev))
- return 0;
+ if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)0, (LPARAM)hWndPrev))
+ {
+ DPRINT1("SetFocusWindow 2 WH_CBT Call Hook return!\n");
+ return 0;
+ }
co_IntSendKillFocusMessages(hWndPrev, 0);
}
{
PTHREADINFO pti;
PUSER_MESSAGE_QUEUE ThreadQueue;
- PWND Window;
+ PWND Window, pWnd;
HWND hWndPrev;
DECLARE_RETURN(HWND);
hWndPrev = MsqSetStateWindow(ThreadQueue, MSQ_STATE_CAPTURE, hWnd);
+ if (hWndPrev)
+ {
+ pWnd = UserGetWindowObject(hWndPrev);
+ if (pWnd)
+ IntNotifyWinEvent(EVENT_SYSTEM_CAPTUREEND, pWnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
+ }
+
/* also remove other windows if not capturing anymore */
- if(hWnd == NULL)
+ if (hWnd == NULL)
{
MsqSetStateWindow(ThreadQueue, MSQ_STATE_MENUOWNER, NULL);
MsqSetStateWindow(ThreadQueue, MSQ_STATE_MOVESIZE, NULL);
}
+ if (Window)
+ IntNotifyWinEvent(EVENT_SYSTEM_CAPTURESTART, Window, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
+
co_IntPostOrSendMessage(hWndPrev, WM_CAPTURECHANGED, 0, (LPARAM)hWnd);
ThreadQueue->CaptureWindow = hWnd;
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: Window hooks
- * FILE: subsystem/win32/win32k/ntuser/hook.c
+ * FILE: subsystems/win32/win32k/ntuser/hook.c
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * James Tabor (james.tabor@rectos.org)
+ *
* REVISION HISTORY:
* 06-06-2001 CSH Created
* NOTE: Most of this code was adapted from Wine,
#define NDEBUG
#include <debug.h>
- static PHOOKTABLE GlobalHooks;
-
-
- /* PRIVATE FUNCTIONS *********************************************************/
-
-
- /* create a new hook table */
- static
- PHOOKTABLE
- IntAllocHookTable(void)
- {
- PHOOKTABLE Table;
- UINT i;
-
- Table = ExAllocatePoolWithTag(PagedPool, sizeof(HOOKTABLE), TAG_HOOK);
- if (NULL != Table)
- {
- for (i = 0; i < NB_HOOKS; i++)
- {
- InitializeListHead(&Table->Hooks[i]);
- Table->Counts[i] = 0;
- }
- }
-
- return Table;
- }
-
-
- PHOOK
- FASTCALL
- IntGetHookObject(HHOOK hHook)
- {
- PHOOK Hook;
-
- if (!hHook)
- {
- SetLastWin32Error(ERROR_INVALID_HOOK_HANDLE);
- return NULL;
- }
-
- Hook = (PHOOK)UserGetObject(gHandleTable, hHook, otHook);
- if (!Hook)
- {
- SetLastWin32Error(ERROR_INVALID_HOOK_HANDLE);
- return NULL;
- }
-
- ASSERT(Hook->head.cLockObj >= 0);
-
- Hook->head.cLockObj++;
-
- return Hook;
- }
-
-
-
- /* create a new hook and add it to the specified table */
- static
- PHOOK
- IntAddHook(PETHREAD Thread, int HookId, BOOLEAN Global, PWINSTATION_OBJECT WinStaObj)
- {
- PTHREADINFO W32Thread;
- PHOOK Hook;
- PHOOKTABLE Table = Global ? GlobalHooks : MsqGetHooks(((PTHREADINFO)Thread->Tcb.Win32Thread)->MessageQueue);
- HANDLE Handle;
-
- if (NULL == Table)
- {
- Table = IntAllocHookTable();
- if (NULL == Table)
- {
- return NULL;
- }
- if (Global)
- {
- GlobalHooks = Table;
- }
- else
- {
- MsqSetHooks(((PTHREADINFO)Thread->Tcb.Win32Thread)->MessageQueue, Table);
- }
- }
-
- Hook = UserCreateObject(gHandleTable, NULL, &Handle, otHook, sizeof(HOOK));
- if (NULL == Hook)
- {
- return NULL;
- }
-
- Hook->Thread = Thread;
- Hook->HookId = HookId;
-
- if (Thread)
- {
- W32Thread = ((PTHREADINFO)Thread->Tcb.Win32Thread);
- ASSERT(W32Thread != NULL);
- W32Thread->fsHooks |= HOOKID_TO_FLAG(HookId);
-
- if (W32Thread->pClientInfo)
- W32Thread->pClientInfo->fsHooks = W32Thread->fsHooks;
-
- if (W32Thread->pDeskInfo) // Do this for now.
- W32Thread->pDeskInfo->fsHooks= W32Thread->fsHooks;
-
- Hook->head.pti = W32Thread;
- Hook->head.rpdesk = W32Thread->rpdesk;
- }
-
- RtlInitUnicodeString(&Hook->ModuleName, NULL);
-
- InsertHeadList(&Table->Hooks[HOOKID_TO_INDEX(HookId)], &Hook->Chain);
-
- return Hook;
- }
-
- /* get the hook table that a given hook belongs to */
- static
- PHOOKTABLE
- FASTCALL
- IntGetTable(PHOOK Hook)
- {
- if (NULL == Hook->Thread || WH_KEYBOARD_LL == Hook->HookId ||
- WH_MOUSE_LL == Hook->HookId)
- {
- return GlobalHooks;
- }
-
- return MsqGetHooks(((PTHREADINFO)Hook->Thread->Tcb.Win32Thread)->MessageQueue);
- }
-
- /* get the first hook in the chain */
- static
- PHOOK
- FASTCALL
- IntGetFirstHook(PHOOKTABLE Table, int HookId)
+ typedef struct _HOOKPACK
{
- PLIST_ENTRY Elem = Table->Hooks[HOOKID_TO_INDEX(HookId)].Flink;
+ PHOOK pHk;
+ LPARAM lParam;
+ } HOOKPACK, *PHOOKPACK;
- return Elem == &Table->Hooks[HOOKID_TO_INDEX(HookId)]
- ? NULL : CONTAINING_RECORD(Elem, HOOK, Chain);
- }
-
- /* find the first non-deleted hook in the chain */
- static
- PHOOK
- FASTCALL
- IntGetFirstValidHook(PHOOKTABLE Table, int HookId)
- {
- PHOOK Hook;
- PLIST_ENTRY Elem;
-
- Hook = IntGetFirstHook(Table, HookId);
-
- while (NULL != Hook && NULL == Hook->Proc)
- {
- Elem = Hook->Chain.Flink;
- Hook = (Elem == &Table->Hooks[HOOKID_TO_INDEX(HookId)]
- ? NULL : CONTAINING_RECORD(Elem, HOOK, Chain));
- }
-
- return Hook;
- }
-
- /* find the next hook in the chain, skipping the deleted ones */
- PHOOK
- FASTCALL
- IntGetNextHook(PHOOK Hook)
- {
- PHOOKTABLE Table = IntGetTable(Hook);
- int HookId = Hook->HookId;
- PLIST_ENTRY Elem;
-
- Elem = Hook->Chain.Flink;
- while (Elem != &Table->Hooks[HOOKID_TO_INDEX(HookId)])
- {
- Hook = CONTAINING_RECORD(Elem, HOOK, Chain);
- if (NULL != Hook->Proc)
- {
- return Hook;
- }
- }
-
- if (NULL != GlobalHooks && Table != GlobalHooks) /* now search through the global table */
- {
- return IntGetFirstValidHook(GlobalHooks, HookId);
- }
-
- return NULL;
- }
+ /* PRIVATE FUNCTIONS *********************************************************/
- /* free a hook, removing it from its chain */
static
- VOID
+ LRESULT
FASTCALL
- IntFreeHook(PHOOKTABLE Table, PHOOK Hook, PWINSTATION_OBJECT WinStaObj)
- {
- RemoveEntryList(&Hook->Chain);
- RtlFreeUnicodeString(&Hook->ModuleName);
-
- /* Dereference thread if required */
- if (Hook->Flags & HOOK_THREAD_REFERENCED)
- {
- ObDereferenceObject(Hook->Thread);
- }
-
- /* Close handle */
- UserDeleteObject(UserHMGetHandle(Hook), otHook);
- }
-
- /* remove a hook, freeing it if the chain is not in use */
- static
- VOID
- IntRemoveHook(PHOOK Hook, PWINSTATION_OBJECT WinStaObj, BOOL TableAlreadyLocked)
+ IntCallLowLevelHook( PHOOK Hook,
+ INT Code,
+ WPARAM wParam,
+ LPARAM lParam)
{
- PTHREADINFO W32Thread;
- PHOOKTABLE Table = IntGetTable(Hook);
-
- ASSERT(NULL != Table); // At this point this should not be null!
-
- W32Thread = ((PTHREADINFO)Hook->Thread->Tcb.Win32Thread);
- ASSERT(W32Thread != NULL);
- W32Thread->fsHooks &= ~HOOKID_TO_FLAG(Hook->HookId);
-
- GetWin32ClientInfo()->fsHooks = W32Thread->fsHooks;
-
- if (W32Thread->pDeskInfo) // Do this for now.
- W32Thread->pDeskInfo->fsHooks= W32Thread->fsHooks;
+ NTSTATUS Status;
+ PTHREADINFO pti;
+ PHOOKPACK pHP;
+ ULONG_PTR uResult = 0;
- if (0 != Table->Counts[HOOKID_TO_INDEX(Hook->HookId)])
- {
- Hook->Proc = NULL; /* chain is in use, just mark it and return */
- }
+ if (Hook->Thread)
+ pti = Hook->Thread->Tcb.Win32Thread;
else
- {
- IntFreeHook(Table, Hook, WinStaObj);
- }
- }
+ pti = Hook->head.pti;
- /* release a hook chain, removing deleted hooks if the use count drops to 0 */
- static
- VOID
- FASTCALL
- IntReleaseHookChain(PHOOKTABLE Table, int HookId, PWINSTATION_OBJECT WinStaObj)
- {
- PLIST_ENTRY Elem;
- PHOOK HookObj;
+ pHP = ExAllocatePoolWithTag(NonPagedPool, sizeof(HOOKPACK), TAG_HOOK);
+ if (!pHP) return 0;
- if (NULL == Table)
- {
- return;
- }
-
- /* use count shouldn't already be 0 */
- ASSERT(0 != Table->Counts[HOOKID_TO_INDEX(HookId)]);
-
- if (0 == Table->Counts[HOOKID_TO_INDEX(HookId)])
- {
- return;
- }
-
- if (0 == --Table->Counts[HOOKID_TO_INDEX(HookId)])
- {
- Elem = Table->Hooks[HOOKID_TO_INDEX(HookId)].Flink;
-
- while (Elem != &Table->Hooks[HOOKID_TO_INDEX(HookId)])
- {
- HookObj = CONTAINING_RECORD(Elem, HOOK, Chain);
- Elem = Elem->Flink;
-
- if (NULL == HookObj->Proc)
- {
- IntFreeHook(Table, HookObj, WinStaObj);
- }
- }
- }
- }
-
- static
- LRESULT
- FASTCALL
- IntCallLowLevelHook(PHOOK Hook, INT Code, WPARAM wParam, LPARAM lParam)
- {
- NTSTATUS Status;
- ULONG_PTR uResult;
+ pHP->pHk = Hook;
+ pHP->lParam = lParam;
/* FIXME should get timeout from
* HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */
- Status = co_MsqSendMessage(((PTHREADINFO)Hook->Thread->Tcb.Win32Thread)->MessageQueue,
- IntToPtr(Code),
- Hook->HookId,
+ Status = co_MsqSendMessage( pti->MessageQueue,
+ IntToPtr(Code), // hWnd
+ Hook->HookId, // Msg
wParam,
- lParam,
+ (LPARAM)pHP,
5000,
TRUE,
MSQ_ISHOOK,
- &uResult);
-
- return NT_SUCCESS(Status) ? uResult : 0;
- }
-
- /*
- Called from inside kernel space.
- */
- LRESULT
- FASTCALL
- co_HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam)
- {
- PHOOK Hook, SaveHook;
- PTHREADINFO pti;
- PCLIENTINFO ClientInfo;
- PHOOKTABLE Table;
- LRESULT Result;
- PWINSTATION_OBJECT WinStaObj;
- NTSTATUS Status;
-
- ASSERT(WH_MINHOOK <= HookId && HookId <= WH_MAXHOOK);
-
- #if 0
- /* FIXME! Check pDeskInfo->fsHooks for global hooks! */
- if (!ISITHOOKED(HookId))
- {
- return 0;
- }
- #endif
-
- pti = PsGetCurrentThreadWin32Thread();
- if (!pti)
- {
- Table = NULL;
- }
- else
- {
- Table = MsqGetHooks(pti->MessageQueue);
- }
-
- if (NULL == Table || ! (Hook = IntGetFirstValidHook(Table, HookId)))
- {
- /* try global table */
- Table = GlobalHooks;
- if (NULL == Table || ! (Hook = IntGetFirstValidHook(Table, HookId)))
- {
- return 0; /* no hook set */
- }
- }
-
- if ((Hook->Thread != PsGetCurrentThread()) && (Hook->Thread != NULL))
- {
- DPRINT1("\nHook found by Id and posted to Thread! %d\n",HookId );
- /* Post it in message queue. */
- return IntCallLowLevelHook(Hook, Code, wParam, lParam);
- }
-
- Table->Counts[HOOKID_TO_INDEX(HookId)]++;
- if (Table != GlobalHooks && GlobalHooks != NULL)
- {
- GlobalHooks->Counts[HOOKID_TO_INDEX(HookId)]++;
- }
-
- ClientInfo = GetWin32ClientInfo();
- SaveHook = ClientInfo->phkCurrent;
- ClientInfo->phkCurrent = Hook; /* Load the call. */
-
- Result = co_IntCallHookProc(HookId,
- Code,
- wParam,
- lParam,
- Hook->Proc,
- Hook->Ansi,
- &Hook->ModuleName);
-
- ClientInfo->phkCurrent = SaveHook;
-
- Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
- KernelMode,
- 0,
- &WinStaObj);
-
+ &uResult);
if (!NT_SUCCESS(Status))
{
- DPRINT1("Invalid window station????\n");
- }
- else
- {
- IntReleaseHookChain(MsqGetHooks(pti->MessageQueue), HookId, WinStaObj);
- IntReleaseHookChain(GlobalHooks, HookId, WinStaObj);
- ObDereferenceObject(WinStaObj);
- }
-
- return Result;
- }
-
- VOID
- FASTCALL
- HOOK_DestroyThreadHooks(PETHREAD Thread)
- {
- int HookId;
- PLIST_ENTRY Elem;
- PHOOK HookObj;
- PWINSTATION_OBJECT WinStaObj;
- NTSTATUS Status;
-
- if (NULL != GlobalHooks)
- {
- Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
- KernelMode,
- 0,
- &WinStaObj);
-
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Invalid window station????\n");
- return;
- }
-
- for (HookId = WH_MINHOOK; HookId <= WH_MAXHOOK; HookId++)
- {
- /* only low-level keyboard/mouse global hooks can be owned by a thread */
- switch(HookId)
- {
- case WH_KEYBOARD_LL:
- case WH_MOUSE_LL:
- Elem = GlobalHooks->Hooks[HOOKID_TO_INDEX(HookId)].Flink;
-
- while (Elem != &GlobalHooks->Hooks[HOOKID_TO_INDEX(HookId)])
- {
- HookObj = CONTAINING_RECORD(Elem, HOOK, Chain);
- Elem = Elem->Flink;
-
- if (HookObj->Thread == Thread)
- {
- IntRemoveHook(HookObj, WinStaObj, TRUE);
- }
- }
- break;
- }
- }
+ DPRINT1("Error Hook Call SendMsg. %d Status: 0x%x\n", Hook->HookId, Status);
+ ExFreePoolWithTag(pHP, TAG_HOOK);
}
+ return NT_SUCCESS(Status) ? uResult : 0;
}
static
LRESULT
FASTCALL
- co_HOOK_CallHookNext(PHOOK Hook, INT Code, WPARAM wParam, LPARAM lParam)
+ co_HOOK_CallHookNext( PHOOK Hook,
+ INT Code,
+ WPARAM wParam,
+ LPARAM lParam)
{
- if ((Hook->Thread != PsGetCurrentThread()) && (Hook->Thread != NULL))
+ if ( (Hook->Thread != PsGetCurrentThread()) && (Hook->Thread != NULL) )
{
- DPRINT1("CALLING HOOK from another Thread. %d\n", Hook->HookId);
+ DPRINT1("Calling Next HOOK from another Thread. %d\n", Hook->HookId);
return IntCallLowLevelHook(Hook, Code, wParam, lParam);
}
- DPRINT("CALLING HOOK %d\n", Hook->HookId);
+ DPRINT("Calling Next HOOK %d\n", Hook->HookId);
- return co_IntCallHookProc(Hook->HookId,
- Code,
- wParam,
- lParam,
- Hook->Proc,
- Hook->Ansi,
+ return co_IntCallHookProc( Hook->HookId,
+ Code,
+ wParam,
+ lParam,
+ Hook->Proc,
+ Hook->Ansi,
&Hook->ModuleName);
}
+ //
+ // Dispatch MsgQueue Hook Call processor!
+ //
+ LRESULT
+ FASTCALL
+ co_CallHook( INT HookId,
+ INT Code,
+ WPARAM wParam,
+ LPARAM lParam)
+ {
+ LRESULT Result;
+ PHOOK phk;
+ PHOOKPACK pHP = (PHOOKPACK)lParam;
+
+ phk = pHP->pHk;
+ /* The odds are high for this to be a Global call. */
+ Result = co_IntCallHookProc( HookId,
+ Code,
+ wParam,
+ pHP->lParam,
+ phk->Proc,
+ phk->Ansi,
+ &phk->ModuleName);
+
+ ExFreePoolWithTag(pHP, TAG_HOOK);
+ return Result;
+ }
LRESULT
FASTCALL
- IntCallDebugHook(PHOOK Hook,
- int Code,
- WPARAM wParam,
- LPARAM lParam)
+ IntCallDebugHook( PHOOK Hook,
+ int Code,
+ WPARAM wParam,
+ LPARAM lParam,
+ BOOL Ansi)
{
LRESULT lResult = 0;
ULONG Size;
return lResult;
}
- /*
- Called from user space via CallNextHook.
- */
LRESULT
FASTCALL
- UserCallNextHookEx(PHOOK Hook,
- int Code,
- WPARAM wParam,
- LPARAM lParam,
- BOOL Ansi)
+ UserCallNextHookEx( PHOOK Hook,
+ int Code,
+ WPARAM wParam,
+ LPARAM lParam,
+ BOOL Ansi)
{
LRESULT lResult = 0;
BOOL BadChk = FALSE;
break;
}
break;
-
+ /*
+ Note WH_JOURNALPLAYBACK,
+ "To have the system wait before processing the message, the return value
+ must be the amount of time, in clock ticks, that the system should wait."
+ */
case WH_JOURNALPLAYBACK:
case WH_JOURNALRECORD:
{
}
case WH_DEBUG:
- lResult = IntCallDebugHook(Hook, Code, wParam, lParam);
+ lResult = IntCallDebugHook(Hook, Code, wParam, lParam, Ansi);
break;
/*
DPRINT1("Unsupported HOOK Id -> %d\n",Hook->HookId);
break;
}
-
return lResult;
}
+ PHOOK
+ FASTCALL
+ IntGetHookObject(HHOOK hHook)
+ {
+ PHOOK Hook;
+
+ if (!hHook)
+ {
+ SetLastWin32Error(ERROR_INVALID_HOOK_HANDLE);
+ return NULL;
+ }
+
+ Hook = (PHOOK)UserGetObject(gHandleTable, hHook, otHook);
+ if (!Hook)
+ {
+ SetLastWin32Error(ERROR_INVALID_HOOK_HANDLE);
+ return NULL;
+ }
+
+ UserReferenceObject(Hook);
+
+ return Hook;
+ }
+
+ /* get the first hook in the chain */
+ static
+ PHOOK
+ FASTCALL
+ IntGetFirstHook(PLIST_ENTRY Table)
+ {
+ PLIST_ENTRY Elem = Table->Flink;
+
+ if (IsListEmpty(Table)) return NULL;
+
+ return Elem == Table ? NULL : CONTAINING_RECORD(Elem, HOOK, Chain);
+ }
+
+ /* find the next hook in the chain */
+ PHOOK
+ FASTCALL
+ IntGetNextHook(PHOOK Hook)
+ {
+ int HookId = Hook->HookId;
+ PLIST_ENTRY Elem;
+ PTHREADINFO pti;
+
+ if (Hook->Thread)
+ {
+ pti = ((PTHREADINFO)Hook->Thread->Tcb.Win32Thread);
+
+ Elem = Hook->Chain.Flink;
+ if (Elem != &pti->aphkStart[HOOKID_TO_INDEX(HookId)])
+ return CONTAINING_RECORD(Elem, HOOK, Chain);
+ }
+ else
+ {
+ pti = PsGetCurrentThreadWin32Thread();
+
+ Elem = Hook->Chain.Flink;
+ if (Elem != &pti->rpdesk->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)])
+ return CONTAINING_RECORD(Elem, HOOK, Chain);
+ }
+ return NULL;
+ }
+
+ /* free a hook, removing it from its chain */
+ static
+ VOID
+ FASTCALL
+ IntFreeHook(PHOOK Hook)
+ {
+ RemoveEntryList(&Hook->Chain);
+ if (Hook->ModuleName.Buffer)
+ {
+ ExFreePoolWithTag(Hook->ModuleName.Buffer, TAG_HOOK);
+ Hook->ModuleName.Buffer = NULL;
+ }
+ /* Close handle */
+ UserDeleteObject(UserHMGetHandle(Hook), otHook);
+ }
+
+ /* remove a hook, freeing it from the chain */
+ static
+ BOOL
+ FASTCALL
+ IntRemoveHook(PHOOK Hook)
+ {
+ INT HookId;
+ PTHREADINFO pti;
+
+ HookId = Hook->HookId;
+
+ if (Hook->Thread) // Local
+ {
+ pti = ((PTHREADINFO)Hook->Thread->Tcb.Win32Thread);
+
+ IntFreeHook( Hook);
+
+ if ( IsListEmpty(&pti->aphkStart[HOOKID_TO_INDEX(HookId)]) )
+ {
+ pti->fsHooks &= ~HOOKID_TO_FLAG(HookId);
+ _SEH2_TRY
+ {
+ GetWin32ClientInfo()->fsHooks = pti->fsHooks;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ }
+ _SEH2_END;
+ return TRUE;
+ }
+ }
+ else // Global
+ {
+ IntFreeHook( Hook);
+
+ pti = PsGetCurrentThreadWin32Thread();
+
+ if ( pti->rpdesk &&
+ pti->rpdesk->pDeskInfo &&
+ IsListEmpty(&pti->rpdesk->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]) )
+ {
+ pti->rpdesk->pDeskInfo->fsHooks &= ~HOOKID_TO_FLAG(HookId);
+ return TRUE;
+ }
+ }
+ return FALSE;
+ }
+
+ VOID
+ FASTCALL
+ HOOK_DestroyThreadHooks(PETHREAD Thread)
+ {
+ PTHREADINFO pti;
+ int HookId;
+ PHOOK HookObj;
+ PLIST_ENTRY pElem;
+
+ pti = Thread->Tcb.Win32Thread;
+ if (!pti || !pti->pDeskInfo) return;
+
+ // Local Thread cleanup.
+ if (pti->fsHooks)
+ {
+ for (HookId = WH_MINHOOK; HookId <= WH_MAXHOOK; HookId++)
+ {
+ PLIST_ENTRY pLLE = &pti->aphkStart[HOOKID_TO_INDEX(HookId)];
+
+ if (IsListEmpty(pLLE)) continue;
+
+ pElem = pLLE->Flink;
+ HookObj = CONTAINING_RECORD(pElem, HOOK, Chain);
+ do
+ {
+ if (!HookObj) break;
+ if (IntRemoveHook(HookObj)) break;
+ pElem = HookObj->Chain.Flink;
+ HookObj = CONTAINING_RECORD(pElem, HOOK, Chain);
+ }
+ while (pElem != pLLE);
+ }
+ pti->fsHooks = 0;
+ }
+ // Global search based on Thread and cleanup.
+ if (pti->rpdesk->pDeskInfo->fsHooks)
+ {
+ for (HookId = WH_MINHOOK; HookId <= WH_MAXHOOK; HookId++)
+ {
+ PLIST_ENTRY pGLE = &pti->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)];
+
+ if (IsListEmpty(pGLE)) continue;
+
+ pElem = pGLE->Flink;
+ HookObj = CONTAINING_RECORD(pElem, HOOK, Chain);
+ do
+ {
+ if (!HookObj) break;
+ if (HookObj->head.pti == pti)
+ {
+ if (IntRemoveHook(HookObj)) break;
+ }
+ pElem = HookObj->Chain.Flink;
+ HookObj = CONTAINING_RECORD(pElem, HOOK, Chain);
+ }
+ while (pElem != pGLE);
+ }
+ }
+ return;
+ }
+
+ /*
+ Win32k Kernel Space Hook Caller.
+ */
LRESULT
- APIENTRY
- NtUserCallNextHookEx(int Code,
- WPARAM wParam,
- LPARAM lParam,
- BOOL Ansi)
+ FASTCALL
+ co_HOOK_CallHooks( INT HookId,
+ INT Code,
+ WPARAM wParam,
+ LPARAM lParam)
{
- PHOOK HookObj, NextObj;
+ PHOOK Hook, SaveHook;
+ PTHREADINFO pti;
PCLIENTINFO ClientInfo;
- PWINSTATION_OBJECT WinStaObj;
- NTSTATUS Status;
- DECLARE_RETURN(LRESULT);
+ PLIST_ENTRY pLLE, pGLE;
+ BOOL Local = FALSE, Global = FALSE;
+ LRESULT Result = 0;
- DPRINT("Enter NtUserCallNextHookEx\n");
- UserEnterExclusive();
+ ASSERT(WH_MINHOOK <= HookId && HookId <= WH_MAXHOOK);
- Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
- KernelMode,
- 0,
- &WinStaObj);
- if (!NT_SUCCESS(Status))
+ pti = PsGetCurrentThreadWin32Thread();
+ if (!pti || !pti->rpdesk || !pti->rpdesk->pDeskInfo)
+ goto Exit; // Must have a desktop running for hooks.
+
+ if ( pti->TIF_flags & TIF_INCLEANUP)
+ goto Exit;
+
+ if ( ISITHOOKED(HookId) )
{
- SetLastNtError(Status);
- RETURN( 0);
+ DPRINT("Local Hooker %d\n", HookId);
+ Local = TRUE;
}
- ObDereferenceObject(WinStaObj);
+ if ( pti->rpdesk->pDeskInfo->fsHooks & HOOKID_TO_FLAG(HookId) )
+ {
+ DPRINT("Global Hooker %d\n", HookId);
+ Global = TRUE;
+ }
- ClientInfo = GetWin32ClientInfo();
+ if ( !Local && !Global ) goto Exit; // No work!
- if (!ClientInfo) RETURN( 0);
+ pLLE = &pti->aphkStart[HOOKID_TO_INDEX(HookId)];
+ pGLE = &pti->rpdesk->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)];
+ Hook = NULL;
- HookObj = ClientInfo->phkCurrent;
+ /* SetWindowHookEx sorts out the Thread issue by placing the Hook to
+ the correct Thread if not NULL.
+ */
+ if ( Local )
+ {
+ Hook = IntGetFirstHook(pLLE);
+ if (!Hook)
+ {
+ DPRINT1("No Local Hook Found!\n");
+ goto Exit;
+ }
+ ObReferenceObject(Hook->Thread);
+
+ ClientInfo = pti->pClientInfo;
+ SaveHook = pti->sphkCurrent;
+
+ /* Load it for the next call. */
+ pti->sphkCurrent = Hook;
+ Hook->phkNext = IntGetNextHook(Hook);
+ if (ClientInfo)
+ {
+ _SEH2_TRY
+ {
+ ClientInfo->phkCurrent = Hook;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ ClientInfo = NULL; // Don't bother next run.
+ }
+ _SEH2_END;
+ }
+ Result = co_IntCallHookProc( HookId,
+ Code,
+ wParam,
+ lParam,
+ Hook->Proc,
+ Hook->Ansi,
+ &Hook->ModuleName);
+ if (ClientInfo)
+ {
+ _SEH2_TRY
+ {
+ ClientInfo->phkCurrent = SaveHook;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ }
+ _SEH2_END;
+ }
+ pti->sphkCurrent = SaveHook;
+ Hook->phkNext = NULL;
+ ObDereferenceObject(Hook->Thread);
+ }
- if (!HookObj) RETURN( 0);
+ if ( Global )
+ {
+ PTHREADINFO ptiHook;
+
+ Hook = IntGetFirstHook(pGLE);
+ if (!Hook)
+ {
+ DPRINT1("No Global Hook Found!\n");
+ goto Exit;
+ }
+ /* Performance goes down the drain. If more hooks are associated to this
+ * hook ID, this will have to post to each of the thread message queues
+ * or make a direct call.
+ */
+ do
+ {
+ /* Hook->Thread is null, we hax around this with Hook->head.pti. */
+ ptiHook = Hook->head.pti;
+
+ /* "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)
+ {
+ Hook = IntGetNextHook(Hook);
+ 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);
+ }
+ else
+ { /* Make the direct call. */
+ DPRINT("\nLocal Hook calling to Thread! %d\n",HookId );
+ Result = co_IntCallHookProc( HookId,
+ Code,
+ wParam,
+ lParam,
+ Hook->Proc,
+ Hook->Ansi,
+ &Hook->ModuleName);
+ }
+ ObDereferenceObject(ptiHook->pEThread);
+ Hook = IntGetNextHook(Hook);
+ }
+ while ( Hook );
+ DPRINT("Ret: Global HookId %d Result 0x%x\n", HookId,Result);
+ }
+ Exit:
+ return Result;
+ }
- /* Check that the first hook in the chain is not this hook */
- NextObj = IntGetFirstHook(IntGetTable(HookObj), HookObj->HookId);
+ BOOL
+ FASTCALL
+ IntUnhookWindowsHook(int HookId, HOOKPROC pfnFilterProc)
+ {
+ PHOOK Hook;
+ PLIST_ENTRY pLLE, pLE;
+ PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
- /* Its the same so it has already been called */
- if (HookObj == NextObj) RETURN(0);
+ if (HookId < WH_MINHOOK || WH_MAXHOOK < HookId )
+ {
+ SetLastWin32Error(ERROR_INVALID_HOOK_FILTER);
+ return FALSE;
+ }
- UserReferenceObject(HookObj);
+ if (pti->fsHooks)
+ {
+ pLLE = &pti->aphkStart[HOOKID_TO_INDEX(HookId)];
+
+ if (IsListEmpty(pLLE)) return FALSE;
+
+ pLE = pLLE->Flink;
+ Hook = CONTAINING_RECORD(pLE, HOOK, Chain);
+ do
+ {
+ if (!Hook) break;
+ if (Hook->Proc == pfnFilterProc)
+ {
+ if (Hook->head.pti == pti)
+ {
+ IntRemoveHook(Hook);
+ UserDereferenceObject(Hook);
+ return TRUE;
+ }
+ else
+ {
+ SetLastWin32Error(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+ }
+ pLE = Hook->Chain.Flink;
+ Hook = CONTAINING_RECORD(pLE, HOOK, Chain);
+ }
+ while (pLE != pLLE);
+ }
+ return FALSE;
+ }
- Ansi = HookObj->Ansi;
+ /*
+ * Support for compatibility only? Global hooks are processed in kernel space.
+ * This is very thread specific! Never seeing applications with more than one
+ * hook per thread installed. Most of the applications are Global hookers and
+ * associated with just one hook Id. Maybe it's for diagnostic testing or a
+ * throw back to 3.11?
+ */
+ LRESULT
+ APIENTRY
+ NtUserCallNextHookEx( int Code,
+ WPARAM wParam,
+ LPARAM lParam,
+ BOOL Ansi)
+ {
+ PTHREADINFO pti;
+ PHOOK HookObj, NextObj;
+ PCLIENTINFO ClientInfo;
+ LRESULT lResult = 0;
+ DECLARE_RETURN(LRESULT);
+
+ DPRINT("Enter NtUserCallNextHookEx\n");
+ UserEnterExclusive();
- if (NULL != HookObj->Thread && (HookObj->Thread != PsGetCurrentThread()))
+ pti = GetW32ThreadInfo();
+
+ HookObj = pti->sphkCurrent;
+
+ if (!HookObj) RETURN( 0);
+
+ NextObj = HookObj->phkNext;
+
+ pti->sphkCurrent = NextObj;
+ ClientInfo = pti->pClientInfo;
+ _SEH2_TRY
{
- DPRINT1("Thread mismatch\n");
- UserDereferenceObject(HookObj);
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- RETURN( 0);
+ ClientInfo->phkCurrent = NextObj;
}
-
- NextObj = IntGetNextHook(HookObj);
- ClientInfo->phkCurrent = NextObj; /* Preset next hook from list. */
- UserCallNextHookEx( HookObj, Code, wParam, lParam, Ansi);
- UserDereferenceObject(HookObj);
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ ClientInfo = NULL;
+ }
+ _SEH2_END;
- RETURN( (LRESULT)NextObj);
+ /* Now in List run down. */
+ if (ClientInfo && NextObj)
+ {
+ NextObj->phkNext = IntGetNextHook(NextObj);
+ lResult = UserCallNextHookEx( NextObj, Code, wParam, lParam, NextObj->Ansi);
+ }
+ RETURN( lResult);
CLEANUP:
DPRINT("Leave NtUserCallNextHookEx, ret=%i\n",_ret_);
HHOOK
APIENTRY
- NtUserSetWindowsHookAW(int idHook,
- HOOKPROC lpfn,
- BOOL Ansi)
+ NtUserSetWindowsHookAW( int idHook,
+ HOOKPROC lpfn,
+ BOOL Ansi)
{
+ DWORD ThreadId;
UNICODE_STRING USModuleName;
RtlInitUnicodeString(&USModuleName, NULL);
-
- return NtUserSetWindowsHookEx(NULL, &USModuleName, 0, idHook, lpfn, Ansi);
+ ThreadId = PtrToUint(NtCurrentTeb()->ClientId.UniqueThread);
+
+ return NtUserSetWindowsHookEx( NULL,
+ &USModuleName,
+ ThreadId,
+ idHook,
+ lpfn,
+ Ansi);
}
HHOOK
APIENTRY
- NtUserSetWindowsHookEx(HINSTANCE Mod,
- PUNICODE_STRING UnsafeModuleName,
- DWORD ThreadId,
- int HookId,
- HOOKPROC HookProc,
- BOOL Ansi)
+ NtUserSetWindowsHookEx( HINSTANCE Mod,
+ PUNICODE_STRING UnsafeModuleName,
+ DWORD ThreadId,
+ int HookId,
+ HOOKPROC HookProc,
+ BOOL Ansi)
{
PWINSTATION_OBJECT WinStaObj;
- PCLIENTINFO ClientInfo;
- BOOLEAN Global;
- PETHREAD Thread;
PHOOK Hook;
UNICODE_STRING ModuleName;
NTSTATUS Status;
HHOOK Handle;
- BOOLEAN ThreadReferenced = FALSE;
+ PETHREAD Thread = NULL;
+ PTHREADINFO ptiCurrent, pti = NULL;
+ BOOL Hit = FALSE;
DECLARE_RETURN(HHOOK);
DPRINT("Enter NtUserSetWindowsHookEx\n");
UserEnterExclusive();
+ ptiCurrent = GetW32ThreadInfo();
+
if (HookId < WH_MINHOOK || WH_MAXHOOK < HookId )
{
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ SetLastWin32Error(ERROR_INVALID_HOOK_FILTER);
RETURN( NULL);
}
RETURN( NULL);
}
- ClientInfo = GetWin32ClientInfo();
-
if (ThreadId) /* thread-local hook */
{
- if (HookId == WH_JOURNALRECORD ||
+ if ( HookId == WH_JOURNALRECORD ||
HookId == WH_JOURNALPLAYBACK ||
HookId == WH_KEYBOARD_LL ||
HookId == WH_MOUSE_LL ||
HookId == WH_SYSMSGFILTER)
- {
- /* these can only be global */
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- RETURN( NULL);
- }
-
- Mod = NULL;
- Global = FALSE;
-
- if (!NT_SUCCESS(PsLookupThreadByThreadId((HANDLE)(DWORD_PTR) ThreadId, &Thread)))
- {
- DPRINT1("Invalid thread id 0x%x\n", ThreadId);
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- RETURN( NULL);
- }
-
- /* Thread was referenced */
- ThreadReferenced = TRUE;
- if (Thread->ThreadsProcess != PsGetCurrentProcess())
- {
- ObDereferenceObject(Thread);
- DPRINT1("Can't specify thread belonging to another process\n");
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- RETURN( NULL);
- }
+ {
+ DPRINT1("Local hook installing Global HookId: %d\n",HookId);
+ /* these can only be global */
+ SetLastWin32Error(ERROR_GLOBAL_ONLY_HOOK);
+ RETURN( NULL);
+ }
+
+ if (!NT_SUCCESS(PsLookupThreadByThreadId((HANDLE)(DWORD_PTR) ThreadId, &Thread)))
+ {
+ DPRINT1("Invalid thread id 0x%x\n", ThreadId);
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ RETURN( NULL);
+ }
+
+ pti = Thread->Tcb.Win32Thread;
+
+ ObDereferenceObject(Thread);
+
+ if ( pti->rpdesk != ptiCurrent->rpdesk) // gptiCurrent->rpdesk)
+ {
+ DPRINT1("Local hook wrong desktop HookId: %d\n",HookId);
+ SetLastWin32Error(ERROR_ACCESS_DENIED);
+ RETURN( NULL);
+ }
+
+ if (Thread->ThreadsProcess != PsGetCurrentProcess())
+ {
+ if ( !Mod &&
+ (HookId == WH_GETMESSAGE ||
+ HookId == WH_CALLWNDPROC ||
+ HookId == WH_CBT ||
+ HookId == WH_HARDWARE ||
+ HookId == WH_DEBUG ||
+ HookId == WH_SHELL ||
+ HookId == WH_FOREGROUNDIDLE ||
+ HookId == WH_CALLWNDPROCRET) )
+ {
+ DPRINT1("Local hook needs hMod HookId: %d\n",HookId);
+ SetLastWin32Error(ERROR_HOOK_NEEDS_HMOD);
+ RETURN( NULL);
+ }
+
+ if ( (pti->TIF_flags & (TIF_CSRSSTHREAD|TIF_SYSTEMTHREAD)) &&
+ (HookId == WH_GETMESSAGE ||
+ HookId == WH_CALLWNDPROC ||
+ HookId == WH_CBT ||
+ HookId == WH_HARDWARE ||
+ HookId == WH_DEBUG ||
+ HookId == WH_SHELL ||
+ HookId == WH_FOREGROUNDIDLE ||
+ HookId == WH_CALLWNDPROCRET) )
+ {
+ SetLastWin32Error(ERROR_HOOK_TYPE_NOT_ALLOWED);
+ RETURN( NULL);
+ }
+ }
}
else /* system-global hook */
{
- if (HookId == WH_KEYBOARD_LL || HookId == WH_MOUSE_LL)
- {
- Mod = NULL;
- Thread = PsGetCurrentThread();
-
- Status = ObReferenceObjectByPointer(Thread,
- THREAD_ALL_ACCESS,
- PsThreadType,
- KernelMode);
-
- if (!NT_SUCCESS(Status))
- {
- SetLastNtError(Status);
- RETURN( (HANDLE) NULL);
- }
-
- /* Thread was referenced */
- ThreadReferenced = TRUE;
- }
- else if (NULL == Mod)
- {
- SetLastWin32Error(ERROR_HOOK_NEEDS_HMOD);
- RETURN( NULL);
- }
- else
- {
- Thread = NULL;
- }
- Global = TRUE;
+ pti = ptiCurrent; // gptiCurrent;
+ if ( !Mod &&
+ (HookId == WH_GETMESSAGE ||
+ HookId == WH_CALLWNDPROC ||
+ HookId == WH_CBT ||
+ HookId == WH_SYSMSGFILTER ||
+ HookId == WH_HARDWARE ||
+ HookId == WH_DEBUG ||
+ HookId == WH_SHELL ||
+ HookId == WH_FOREGROUNDIDLE ||
+ HookId == WH_CALLWNDPROCRET) )
+ {
+ DPRINT1("Global hook needs hMod HookId: %d\n",HookId);
+ SetLastWin32Error(ERROR_HOOK_NEEDS_HMOD);
+ RETURN( NULL);
+ }
}
- if ((Global && (HookId != WH_KEYBOARD_LL && HookId != WH_MOUSE_LL)) ||
- WH_DEBUG == HookId ||
- WH_JOURNALPLAYBACK == HookId ||
- WH_JOURNALRECORD == HookId)
- {
- #if 0 /* Removed to get winEmbed working again */
- UNIMPLEMENTED
- #else
- DPRINT1("Not implemented: HookId %d Global %s\n", HookId, Global ? "TRUE" : "FALSE");
- #endif
-
- /* Dereference thread if needed */
- if (ThreadReferenced) ObDereferenceObject(Thread);
- SetLastWin32Error(ERROR_NOT_SUPPORTED);
- RETURN( NULL);
- }
-
- Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
- KernelMode,
- 0,
+ Status = IntValidateWindowStationHandle( PsGetCurrentProcess()->Win32WindowStation,
+ KernelMode,
+ 0,
&WinStaObj);
if (!NT_SUCCESS(Status))
{
- /* Dereference thread if needed */
- if (ThreadReferenced) ObDereferenceObject(Thread);
- SetLastNtError(Status);
- RETURN( (HANDLE) NULL);
+ SetLastNtError(Status);
+ RETURN( NULL);
}
+ ObDereferenceObject(WinStaObj);
- Hook = IntAddHook(Thread, HookId, Global, WinStaObj);
- if (NULL == Hook)
+ Hook = UserCreateObject(gHandleTable, NULL, &Handle, otHook, sizeof(HOOK));
+
+ if (!Hook)
{
- /* Dereference thread if needed */
- if (ThreadReferenced) ObDereferenceObject(Thread);
- ObDereferenceObject(WinStaObj);
- RETURN( NULL);
+ RETURN( NULL);
}
- /* Let IntFreeHook now that this thread needs a dereference */
- if (ThreadReferenced)
+ Hook->ihmod = (INT)Mod; // Module Index from atom table, Do this for now.
+ Hook->Thread = Thread; /* Set Thread, Null is Global. */
+ Hook->HookId = HookId;
+ Hook->rpdesk = pti->rpdesk;
+ Hook->phkNext = NULL; /* Dont use as a chain! Use link lists for chaining. */
+ Hook->Proc = HookProc;
+ Hook->Ansi = Ansi;
+
+ if (ThreadId) /* thread-local hook */
{
- Hook->Flags |= HOOK_THREAD_REFERENCED;
+ InsertHeadList(&pti->aphkStart[HOOKID_TO_INDEX(HookId)], &Hook->Chain);
+ pti->sphkCurrent = NULL;
+ Hook->ptiHooked = pti;
+ pti->fsHooks |= HOOKID_TO_FLAG(HookId);
+
+ if (pti->pClientInfo)
+ {
+ if ( pti->ppi == ptiCurrent->ppi) /* gptiCurrent->ppi) */
+ {
+ _SEH2_TRY
+ {
+ pti->pClientInfo->fsHooks = pti->fsHooks;
+ pti->pClientInfo->phkCurrent = 0;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Hit = TRUE;
+ }
+ _SEH2_END;
+ if (Hit)
+ {
+ DPRINT1("Problem writing to Local ClientInfo!\n");
+ }
+ }
+ else
+ {
+ KeAttachProcess(&pti->ppi->peProcess->Pcb);
+ _SEH2_TRY
+ {
+ pti->pClientInfo->fsHooks = pti->fsHooks;
+ pti->pClientInfo->phkCurrent = 0;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Hit = TRUE;
+ }
+ _SEH2_END;
+ KeDetachProcess();
+ if (Hit)
+ {
+ DPRINT1("Problem writing to Remote ClientInfo!\n");
+ }
+ }
+ }
}
-
- if (NULL != Mod)
+ else
{
- Status = MmCopyFromCaller(&ModuleName, UnsafeModuleName, sizeof(UNICODE_STRING));
- if (!NT_SUCCESS(Status))
- {
- UserDereferenceObject(Hook);
- IntRemoveHook(Hook, WinStaObj, FALSE);
- ObDereferenceObject(WinStaObj);
- SetLastNtError(Status);
- RETURN( NULL);
- }
+ InsertHeadList(&pti->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);
+ }
- Hook->ModuleName.Buffer = ExAllocatePoolWithTag(PagedPool,
+ RtlInitUnicodeString(&Hook->ModuleName, NULL);
+
+ if (Mod)
+ {
+ Status = MmCopyFromCaller(&ModuleName,
+ UnsafeModuleName,
+ sizeof(UNICODE_STRING));
+ if (!NT_SUCCESS(Status))
+ {
+ IntRemoveHook(Hook);
+ SetLastNtError(Status);
+ RETURN( NULL);
+ }
+
+ Hook->ModuleName.Buffer = ExAllocatePoolWithTag( PagedPool,
ModuleName.MaximumLength,
TAG_HOOK);
- if (NULL == Hook->ModuleName.Buffer)
- {
- UserDereferenceObject(Hook);
- IntRemoveHook(Hook, WinStaObj, FALSE);
- ObDereferenceObject(WinStaObj);
- SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
- RETURN( NULL);
- }
-
- Hook->ModuleName.MaximumLength = ModuleName.MaximumLength;
- Status = MmCopyFromCaller(Hook->ModuleName.Buffer,
+ if (NULL == Hook->ModuleName.Buffer)
+ {
+ IntRemoveHook(Hook);
+ SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ RETURN( NULL);
+ }
+
+ Hook->ModuleName.MaximumLength = ModuleName.MaximumLength;
+ Status = MmCopyFromCaller( Hook->ModuleName.Buffer,
ModuleName.Buffer,
ModuleName.MaximumLength);
- if (!NT_SUCCESS(Status))
- {
- ExFreePoolWithTag(Hook->ModuleName.Buffer, TAG_HOOK);
- UserDereferenceObject(Hook);
- IntRemoveHook(Hook, WinStaObj, FALSE);
- ObDereferenceObject(WinStaObj);
- SetLastNtError(Status);
- RETURN( NULL);
- }
-
- Hook->ModuleName.Length = ModuleName.Length;
- /* make proc relative to the module base */
- Hook->Proc = (void *)((char *)HookProc - (char *)Mod);
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePoolWithTag(Hook->ModuleName.Buffer, TAG_HOOK);
+ Hook->ModuleName.Buffer = NULL;
+ IntRemoveHook(Hook);
+ SetLastNtError(Status);
+ RETURN( NULL);
+ }
+
+ Hook->ModuleName.Length = ModuleName.Length;
+ /* make proc relative to the module base */
+ Hook->offPfn = (ULONG_PTR)((char *)HookProc - (char *)Mod);
}
else
- Hook->Proc = HookProc;
-
- Hook->Ansi = Ansi;
- Handle = UserHMGetHandle(Hook);
-
- /* Clear the client threads next hook. */
- ClientInfo->phkCurrent = 0;
-
- UserDereferenceObject(Hook);
-
- ObDereferenceObject(WinStaObj);
+ Hook->offPfn = 0;
+ DPRINT1("Installing: HookId %d Global %s\n", HookId, !ThreadId ? "TRUE" : "FALSE");
RETURN( Handle);
CLEANUP:
END_CLEANUP;
}
-
BOOL
APIENTRY
NtUserUnhookWindowsHookEx(HHOOK Hook)
{
- PWINSTATION_OBJECT WinStaObj;
PHOOK HookObj;
- NTSTATUS Status;
DECLARE_RETURN(BOOL);
DPRINT("Enter NtUserUnhookWindowsHookEx\n");
UserEnterExclusive();
- Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
- KernelMode,
- 0,
- &WinStaObj);
-
- if (!NT_SUCCESS(Status))
- {
- SetLastNtError(Status);
- RETURN( FALSE);
- }
-
- /* Status = UserReferenceObjectByHandle(gHandleTable, Hook,
- otHookProc, (PVOID *) &HookObj); */
if (!(HookObj = IntGetHookObject(Hook)))
{
DPRINT1("Invalid handle passed to NtUserUnhookWindowsHookEx\n");
- ObDereferenceObject(WinStaObj);
/* SetLastNtError(Status); */
RETURN( FALSE);
}
ASSERT(Hook == UserHMGetHandle(HookObj));
- IntRemoveHook(HookObj, WinStaObj, FALSE);
+ IntRemoveHook(HookObj);
UserDereferenceObject(HookObj);
- ObDereferenceObject(WinStaObj);
RETURN( TRUE);
KbdHookData.dwExtraInfo = ki->dwExtraInfo;
if (co_HOOK_CallHooks(WH_KEYBOARD_LL, HC_ACTION, Msg.message, (LPARAM) &KbdHookData))
{
- DPRINT("Kbd msg %d wParam %d lParam 0x%08x dropped by WH_KEYBOARD_LL hook\n",
+ DPRINT1("Kbd msg %d wParam %d lParam 0x%08x dropped by WH_KEYBOARD_LL hook\n",
Msg.message, vk_hook, Msg.lParam);
if (Entered) UserLeave();
return FALSE;
DPRINT("Loaded %wZ\n", &FullLayoutPath);
RtlInitAnsiString( &kbdProcedureName, "KbdLayerDescriptor" );
- LdrGetProcedureAddress((*(PDRIVERS*)phModule)->BaseAddress,
- &kbdProcedureName,
- 0,
- (PVOID*)&layerDescGetFn);
+ layerDescGetFn = EngFindImageProcAddress(*phModule, "KbdLayerDescriptor");
if(layerDescGetFn)
{
{
LARGE_INTEGER TickCount;
LONG Time;
- LRESULT retval;
+ LRESULT retval = 0;
PMSGMEMORY MsgMemoryEntry;
INT lParamBufferSize;
+ PTHREADINFO pti;
LPARAM lParamPacked;
PWND Window = NULL;
if (!Window) return 0;
}
+ pti = PsGetCurrentThreadWin32Thread();
+
if (((pMsg->message == WM_SYSTIMER) ||
(pMsg->message == WM_TIMER)) &&
(pMsg->lParam) )
{
if (pMsg->message == WM_TIMER)
{
- if (ValidateTimerCallback(PsGetCurrentThreadWin32Thread(),pMsg->lParam))
+ ObReferenceObject(pti->pEThread);
+ if (ValidateTimerCallback(pti,pMsg->lParam))
{
KeQueryTickCount(&TickCount);
Time = MsqCalculateMessageTime(&TickCount);
- return co_IntCallWindowProc((WNDPROC)pMsg->lParam,
+ retval = co_IntCallWindowProc((WNDPROC)pMsg->lParam,
TRUE,
pMsg->hwnd,
WM_TIMER,
(LPARAM)Time,
sizeof(LPARAM));
}
- return 0;
+ ObDereferenceObject(pti->pEThread);
+ return retval;
}
else
{
DPRINT1("Failed to pack message parameters\n");
return 0;
}
-
+ ObReferenceObject(pti->pEThread);
retval = co_IntCallWindowProc( Window->lpfnWndProc,
!Window->Unicode,
pMsg->hwnd,
co_UserGetUpdateRgn( Window, hrgn, TRUE );
REGION_FreeRgnByHandle( hrgn );
}
+ ObDereferenceObject(pti->pEThread);
return retval;
}
}
}
- if ( gspv.bMouseClickLock &&
+ if ( gspv.bMouseClickLock &&
( (Msg->message == WM_LBUTTONUP) ||
(Msg->message == WM_LBUTTONDOWN) ) )
{
HCBT_CLICKSKIPPED,
Msg->message,
(LPARAM)&MHook);
+ DPRINT1("MouseMessage WH_CBT Call Hook return!\n");
return FALSE;
}
HCBT_KEYSKIPPED,
LOWORD(Msg->wParam),
Msg->lParam );
+ DPRINT1("KeyboardMessage WH_CBT Call Hook return!\n");
return FALSE;
}
return TRUE;
do
{
- KeQueryTickCount(&LargeTickCount);
- ThreadQueue->LastMsgRead = LargeTickCount.u.LowPart;
-
- /* Dispatch sent messages here. */
- while (co_MsqDispatchOneSentMessage(ThreadQueue))
- ;
-
- /* Now look for a quit message. */
-
- if (ThreadQueue->QuitPosted)
- {
- /* 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;
- if (RemoveMessages)
- {
- ThreadQueue->QuitPosted = FALSE;
- }
+ KeQueryTickCount(&LargeTickCount);
+ ThreadQueue->LastMsgRead = LargeTickCount.u.LowPart;
+
+ /* Dispatch sent messages here. */
+ while (co_MsqDispatchOneSentMessage(ThreadQueue))
+ ;
+
+ /* Now look for a quit message. */
+
+ if (ThreadQueue->QuitPosted)
+ {
+ /* 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;
+ if (RemoveMessages)
+ {
+ ThreadQueue->QuitPosted = FALSE;
+ }
return TRUE;
- }
+ }
- /* Now check for normal messages. */
+ /* Now check for normal messages. */
if (co_MsqFindMessage( ThreadQueue,
- FALSE,
- RemoveMessages,
- Window,
- MsgFilterMin,
- MsgFilterMax,
+ FALSE,
+ RemoveMessages,
+ Window,
+ MsgFilterMin,
+ MsgFilterMax,
&Message ))
- {
- RtlCopyMemory(Msg, Message, sizeof(USER_MESSAGE));
- if (RemoveMessages)
- {
- MsqDestroyMessage(Message);
- }
+ {
+ RtlCopyMemory(Msg, Message, sizeof(USER_MESSAGE));
+ if (RemoveMessages)
+ {
+ MsqDestroyMessage(Message);
+ }
break;
- }
+ }
- /* Check for hardware events. */
+ /* Check for hardware events. */
if(co_MsqFindMessage( ThreadQueue,
- TRUE,
- RemoveMessages,
- Window,
- MsgFilterMin,
- MsgFilterMax,
+ TRUE,
+ RemoveMessages,
+ Window,
+ MsgFilterMin,
+ MsgFilterMax,
&Message ))
- {
- RtlCopyMemory(Msg, Message, sizeof(USER_MESSAGE));
- if (RemoveMessages)
- {
- MsqDestroyMessage(Message);
- }
+ {
+ RtlCopyMemory(Msg, Message, sizeof(USER_MESSAGE));
+ if (RemoveMessages)
+ {
+ MsqDestroyMessage(Message);
+ }
if(!ProcessHardwareMessage(&Msg->Msg, RemoveMessages))
continue;
break;
- }
+ }
- /* Check for sent messages again. */
- while (co_MsqDispatchOneSentMessage(ThreadQueue))
- ;
+ /* Check for sent messages again. */
+ while (co_MsqDispatchOneSentMessage(ThreadQueue))
+ ;
- /* Check for paint messages. */
+ /* Check for paint messages. */
if( IntGetPaintMessage( Window,
- MsgFilterMin,
- MsgFilterMax,
- pti,
- &Msg->Msg,
- RemoveMessages))
- {
+ MsgFilterMin,
+ MsgFilterMax,
+ pti,
+ &Msg->Msg,
+ RemoveMessages))
+ {
break;
- }
+ }
- if (PostTimerMessages(Window))
- {
+ if (PostTimerMessages(Window))
+ {
continue;
- }
+ }
- return FALSE;
- }
+ return FALSE;
+ }
while (TRUE);
- // The WH_GETMESSAGE hook enables an application to monitor messages about to
- // be returned by the GetMessage or PeekMessage function.
+ // 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;
+ co_HOOK_CallHooks( WH_GETMESSAGE, HC_ACTION, RemoveMsg & PM_REMOVE, (LPARAM)&Msg->Msg);
+ return TRUE;
}
static NTSTATUS FASTCALL
return FALSE;
}
- if (!Wnd)
+ if (!Wnd)
return UserPostThreadMessage( PtrToInt(PsGetCurrentThreadId()),
Msg,
wParam,
if (List != NULL)
{
+ UserPostMessage(DesktopWindow->head.h, Msg, wParam, lParam);
for (i = 0; List[i]; i++)
UserPostMessage(List[i], Msg, wParam, lParam);
ExFreePool(List);
UINT uTimeout,
ULONG_PTR *uResult )
{
- ULONG_PTR Result;
NTSTATUS Status;
PWND Window = NULL;
PMSGMEMORY MsgMemoryEntry;
INT lParamBufferSize;
LPARAM lParamPacked;
PTHREADINFO Win32Thread;
+ ULONG_PTR Result = 0;
DECLARE_RETURN(LRESULT);
USER_REFERENCE_ENTRY Ref;
RETURN( FALSE);
}
+ ObReferenceObject(Win32Thread->pEThread);
Result = (ULONG_PTR)co_IntCallWindowProc( Window->lpfnWndProc,
!Window->Unicode,
hWnd,
*uResult = Result;
}
+ ObDereferenceObject(Win32Thread->pEThread);
+
IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE)))
return 0;
}
+ /* Send message to the desktop window too! */
+ co_IntSendMessageTimeoutSingle(DesktopWindow->head.h, Msg, wParam, lParam, uFlags, uTimeout, uResult);
+
Children = IntWinListChildren(DesktopWindow);
if (NULL == Children)
{
/* If this is not a callback and it can be sent now, then send it. */
if ((Window->head.pti->MessageQueue == Win32Thread->MessageQueue) && (CompletionCallback == NULL))
{
-
+ ObReferenceObject(Win32Thread->pEThread);
Result = (ULONG_PTR)co_IntCallWindowProc( Window->lpfnWndProc,
!Window->Unicode,
hWnd,
{
*uResult = Result;
}
+ ObDereferenceObject(Win32Thread->pEThread);
}
IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
if (List != NULL)
{
+ UserSendNotifyMessage(DesktopWindow->head.h, Msg, wParam, lParam);
for (i = 0; List[i]; i++)
{
UserSendNotifyMessage(List[i], Msg, wParam, lParam);
BOOL Hit = FALSE;
MSG SafeMsg;
- UserEnterExclusive();
+ UserEnterExclusive();
_SEH2_TRY
{
ProbeForRead(UnsafeMsgInfo, sizeof(MSG), 1);
Hit = TRUE;
}
_SEH2_END;
-
+
if (!Hit) Res = IntDispatchMessage(&SafeMsg);
UserLeave();
2000,
&RetVal);
}
+ Ret = RetVal;
}
else if (parm.flags & BSF_POSTMESSAGE)
{
Ret = UserPostMessage(HWND_BROADCAST, Msg, wParam, lParam);
}
- else if ( parm.flags & BSF_SENDNOTIFYMESSAGE)
+ else //Everything else,,,, if ( parm.flags & BSF_SENDNOTIFYMESSAGE)
{
Ret = UserSendNotifyMessage(HWND_BROADCAST, Msg, wParam, lParam);
}
case FNID_CALLWNDPROC:
case FNID_CALLWNDPROCRET:
{
- PCLIENTINFO ClientInfo = GetWin32ClientInfo();
- PHOOK NextObj, Hook = ClientInfo->phkCurrent;
+ PTHREADINFO pti;
+ PCLIENTINFO ClientInfo;
+ PHOOK NextObj, Hook;
- if (!ClientInfo || !Hook) break;
+ pti = GetW32ThreadInfo();
- UserReferenceObject(Hook);
+ Hook = pti->sphkCurrent;
- if (Hook->Thread && (Hook->Thread != PsGetCurrentThread()))
+ if (!Hook) break;
+
+ NextObj = Hook->phkNext;
+ ClientInfo = pti->pClientInfo;
+ _SEH2_TRY
{
- UserDereferenceObject(Hook);
- break;
+ ClientInfo->phkCurrent = NextObj;
}
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ ClientInfo = NULL;
+ }
+ _SEH2_END;
+
+ if (!ClientInfo || !NextObj) break;
- NextObj = IntGetNextHook(Hook);
- ClientInfo->phkCurrent = NextObj;
+ NextObj->phkNext = IntGetNextHook(NextObj);
if ( Hook->HookId == WH_CALLWNDPROC)
{
Hook->Ansi,
&Hook->ModuleName);
}
- UserDereferenceObject(Hook);
- lResult = (LRESULT) NextObj;
}
break;
}
{
BadChk = TRUE;
}
- _SEH2_END;
+ _SEH2_END;
}
break;
default:
- break;
+ break;
}
UserLeave();
InitMetrics(VOID)
{
INT *piSysMet;
-
- ULONG Width = pPrimarySurface->gdiinfo.ulHorzRes;
- ULONG Height = pPrimarySurface->gdiinfo.ulVertRes;
+ ULONG Width, Height;
+
+ /* FIXME: HACK, due to missing PDEV on first init */
+ if (!pPrimarySurface)
+ {
+ Width = 640;
+ Height = 480;
+ }
+ else
+ {
+ Width = pPrimarySurface->gdiinfo.ulHorzRes;
+ Height = pPrimarySurface->gdiinfo.ulVertRes;
+ }
piSysMet = gpsi->aiSysMet;
KbdHookData.dwExtraInfo = 0;
if (co_HOOK_CallHooks(WH_KEYBOARD_LL, HC_ACTION, Msg.message, (LPARAM) &KbdHookData))
{
- DPRINT("Kbd msg %d wParam %d lParam 0x%08x dropped by WH_KEYBOARD_LL hook\n",
+ DPRINT1("Kbd msg %d wParam %d lParam 0x%08x dropped by WH_KEYBOARD_LL hook\n",
Msg.message, Msg.wParam, Msg.lParam);
if (Entered) UserLeave();
return;
&Message->ListEntry);
if (Message->HookMessage == MSQ_ISHOOK)
- {
- Result = co_HOOK_CallHooks(Message->Msg.message,
- (INT)(INT_PTR)Message->Msg.hwnd,
- Message->Msg.wParam,
- Message->Msg.lParam);
+ { // Direct Hook Call processor
+ Result = co_CallHook( Message->Msg.message, // HookId
+ (INT)(INT_PTR)Message->Msg.hwnd, // Code
+ Message->Msg.wParam,
+ Message->Msg.lParam);
}
else if (Message->HookMessage == MSQ_ISEVENT)
- {
+ { // Direct Event Call processor
Result = co_EVENT_CallEvents( Message->Msg.message,
Message->Msg.hwnd,
Message->Msg.wParam,
Message->Msg.lParam);
}
else
- {
- /* Call the window procedure. */
- Result = co_IntSendMessage(Message->Msg.hwnd,
- Message->Msg.message,
- Message->Msg.wParam,
- Message->Msg.lParam);
+ { /* Call the window procedure. */
+ Result = co_IntSendMessage( Message->Msg.hwnd,
+ Message->Msg.message,
+ Message->Msg.wParam,
+ Message->Msg.lParam);
}
/* remove the message from the local dispatching list, because it doesn't need
PUSER_SENT_MESSAGE Message;
KEVENT CompletionEvent;
NTSTATUS WaitStatus;
- LRESULT Result;
PUSER_MESSAGE_QUEUE ThreadQueue;
LARGE_INTEGER Timeout;
PLIST_ENTRY Entry;
+ LRESULT Result = 0; //// Result could be trashed. ////
if(!(Message = ExAllocatePoolWithTag(PagedPool, sizeof(USER_SENT_MESSAGE), TAG_USRMSG)))
{
/* FIXME - increase reference counter of sender's message queue here */
- Result = 0;
Message->Msg.hwnd = Wnd;
Message->Msg.message = Msg;
Message->Msg.wParam = wParam;
Message->SenderQueue = ThreadQueue;
IntReferenceMessageQueue(ThreadQueue);
Message->CompletionCallback = NULL;
+ Message->CompletionCallbackContext = 0;
Message->HookMessage = HookMessage;
Message->HasPackedLParam = FALSE;
IntDereferenceMessageQueue(MessageQueue);
}
- PHOOKTABLE FASTCALL
- MsqGetHooks(PUSER_MESSAGE_QUEUE Queue)
- {
- return Queue->Hooks;
- }
-
- VOID FASTCALL
- MsqSetHooks(PUSER_MESSAGE_QUEUE Queue, PHOOKTABLE Hooks)
- {
- Queue->Hooks = Hooks;
- }
-
LPARAM FASTCALL
MsqSetMessageExtraInfo(LPARAM lParam)
{
return 0;
}
- BOOL
- APIENTRY
- NtUserEnumDisplayDevices (
- PUNICODE_STRING lpDevice, /* device name */
- DWORD iDevNum, /* display device */
- PDISPLAY_DEVICEW lpDisplayDevice, /* device information */
- DWORD dwFlags ) /* reserved */
- {
- DPRINT1("NtUserEnumDisplayDevices() is UNIMPLEMENTED!\n");
- if (lpDevice->Length == 0 && iDevNum > 0)
- {
- /* Only one display device present */
- return FALSE;
- }
- else if (lpDevice->Length != 0)
- {
- /* Can't enumerate monitors :( */
- return FALSE;
- }
- if (lpDisplayDevice->cb < sizeof(DISPLAY_DEVICE))
- return FALSE;
-
- wcscpy(lpDisplayDevice->DeviceName, L"\\\\.\\DISPLAY1");
- wcscpy(lpDisplayDevice->DeviceString, L"<Unknown>");
- lpDisplayDevice->StateFlags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
- | DISPLAY_DEVICE_MODESPRUNED
- | DISPLAY_DEVICE_PRIMARY_DEVICE
- | DISPLAY_DEVICE_VGA_COMPATIBLE;
- lpDisplayDevice->DeviceID[0] = L'0';
- lpDisplayDevice->DeviceKey[0] = L'0';
- return TRUE;
- }
-
DWORD
APIENTRY
NtUserEvent(
return Status;
}
- if (!gpsi)
- {
- gpsi = UserHeapAlloc(sizeof(SERVERINFO));
- if (gpsi)
- {
- RtlZeroMemory(gpsi, sizeof(SERVERINFO));
- DPRINT("Global Server Data -> %x\n", gpsi);
- }
- }
-
InitUserAtoms();
InitSysParams();
return STATUS_SUCCESS;
}
+ BOOL
+ InitVideo(ULONG);
NTSTATUS
NTAPI
// 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.
// {
// DrvInitConsole.
{
NTSTATUS Status;
- DPRINT("Enter NtUserInitialize(%lx, %p, %p)\n",
- dwWinVersion, hPowerRequestEvent, hMediaRequestEvent);
+ DPRINT1("Enter NtUserInitialize(%lx, %p, %p)\n",
+ dwWinVersion, hPowerRequestEvent, hMediaRequestEvent);
/* Check the Windows version */
if (dwWinVersion != 0)
{
case otWindow:
// case otMenu:
- // case otHook:
- // case otCallProc:
+ case otHook:
+ case otCallProc:
case otInputContext:
Object = DesktopHeapAlloc(rpdesk, size);
dt = TRUE;
{
case otWindow:
// case otMenu:
- // case otHook:
- // case otCallProc:
+ case otHook:
+ case otCallProc:
case otInputContext:
return DesktopHeapFree(((PTHRDESKHEAD)object)->rpdesk, object);
RETURN (ret);
}
- case ONEPARAM_ROUTINE_ISWINDOWINDESTROY:
- {
- PWND Window;
- DWORD_PTR Result;
-
- if(!(Window = UserGetWindowObject((HWND)Param)))
- {
- RETURN( FALSE);
- }
-
- Result = (DWORD_PTR)IntIsWindowInDestroy(Window);
-
- RETURN( Result);
- }
-
case ONEPARAM_ROUTINE_ENABLEPROCWNDGHSTING:
{
BOOL Enable;
case TWOPARAM_ROUTINE_SETCURSORPOS:
RETURN( (DWORD_PTR)UserSetCursorPos((int)Param1, (int)Param2, FALSE));
+ case TWOPARAM_ROUTINE_UNHOOKWINDOWSHOOK:
+ RETURN( IntUnhookWindowsHook((int)Param1, (HOOKPROC)Param2));
}
DPRINT1("Calling invalid routine number 0x%x in NtUserCallTwoParam(), Param1=0x%x Parm2=0x%x\n",
Routine, Param1, Param2);
UserLeave();
return 0;
}
+
+ case HWNDPARAM_ROUTINE_ROS_NOTIFYWINEVENT:
+ {
+ PWND pWnd;
+ PNOTIFYEVENT pne;
+ UserEnterExclusive();
+ pne = (PNOTIFYEVENT)Param;
+ if (hWnd)
+ pWnd = UserGetWindowObject(hWnd);
+ else
+ pWnd = NULL;
+ IntNotifyWinEvent(pne->event, pWnd, pne->idObject, pne->idChild, pne->flags);
+ UserLeave();
+ return 0;
+ }
}
UNIMPLEMENTED;
UNICODE_STRING DriverName;
RtlInitUnicodeString(&DriverName, L"DISPLAY");
hDC = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, FALSE);
+
+ co_IntGraphicsCheck(TRUE);
+
//
// If NULL, first time through! Build the default window dc!
//
}
-
PWND FASTCALL
IntGetParent(PWND Wnd)
{
return NULL;
}
-
/*
* IntWinListChildren
*
Window->state2 |= WNDS2_INDESTROY;
Window->style &= ~WS_VISIBLE;
- IntNotifyWinEvent(EVENT_OBJECT_DESTROY, Window, OBJID_WINDOW, 0);
+ IntNotifyWinEvent(EVENT_OBJECT_DESTROY, Window, OBJID_WINDOW, CHILDID_SELF, 0);
/* remove the window already at this point from the thread window list so we
don't get into trouble when destroying the thread windows while we're still
if(BelongsToThreadData)
co_IntSendMessage(Window->head.h, WM_NCDESTROY, 0, 0);
}
+
DestroyTimersForWindow(ThreadData, Window);
+
HOOK_DestroyThreadHooks(ThreadData->pEThread); // This is needed here too!
/* flush the message queue */
}
+ IntNotifyWinEvent(EVENT_OBJECT_PARENTCHANGE, Wnd ,OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
/*
* SetParent additionally needs to make hwnd the top window
* in the z-order and send the expected WM_WINDOWPOSCHANGING and
Wnd->spwndPrev = Wnd->spwndNext = NULL;
}
- BOOL FASTCALL
- IntIsWindowInDestroy(PWND Window)
- {
- return ((Window->state2 & WNDS2_INDESTROY) == WNDS2_INDESTROY);
- }
-
-
BOOL
FASTCALL
IntGetWindowPlacement(PWND Wnd, WINDOWPLACEMENT *lpwndpl)
pti = PsGetCurrentThreadWin32Thread();
+ if (!(Cs->dwExStyle & WS_EX_LAYOUTRTL))
+ {
+ if (ParentWindow)
+ {
+ if ( (Cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD &&
+ ParentWindow->ExStyle & WS_EX_LAYOUTRTL &&
+ !(ParentWindow->ExStyle & WS_EX_NOINHERITLAYOUT) )
+ Cs->dwExStyle |= WS_EX_LAYOUTRTL;
+ }
+ else
+ {/*
+ Note from MSDN http://msdn.microsoft.com/en-us/library/aa913269.aspx :
+
+ Dialog boxes and message boxes do not inherit layout, so you must
+ set the layout explicitly.
+ */
+ if ( Class && Class->fnid != FNID_DIALOG)
+ {
+ PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
+ if (ppi->dwLayout & LAYOUT_RTL)
+ {
+ Cs->dwExStyle |= WS_EX_LAYOUTRTL;
+ }
+ }
+ }
+ }
+
/* Automatically add WS_EX_WINDOWEDGE */
if ((Cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
((!(Cs->dwExStyle & WS_EX_STATICEDGE)) &&
PLARGE_STRING WindowName)
{
PWND Window = NULL, ParentWindow = NULL, OwnerWindow;
- HWND hWnd, hWndParent, hWndOwner;
+ HWND hWnd, hWndParent, hWndOwner, hwndInsertAfter;
DWORD dwStyle;
PWINSTATION_OBJECT WinSta;
PCLS Class = NULL;
SIZE Size;
POINT MaxPos;
- CBT_CREATEWNDW CbtCreate;
+ CBT_CREATEWNDW * pCbtCreate;
LRESULT Result;
USER_REFERENCE_ENTRY ParentRef, Ref;
PTHREADINFO pti;
+ ANSI_STRING asClassName;
DWORD dwShowMode = SW_SHOW;
+ CREATESTRUCTW *pCsw;
DECLARE_RETURN(PWND);
/* Get the current window station and reference it */
WinSta = pti->rpdesk->rpwinstaParent;
ObReferenceObjectByPointer(WinSta, KernelMode, ExWindowStationObjectType, 0);
+ pCsw = NULL;
+ pCbtCreate = NULL;
+ RtlInitAnsiString(&asClassName, NULL);
+
/* Get the class and reference it*/
Class = IntGetAndReferenceClass(ClassName, Cs->hInstance);
if(!Class)
RETURN(0);
}
- hWnd = Window->head.h;
+ hWnd = UserHMGetHandle(Window);
UserRefObjectCo(Window, &Ref);
ObDereferenceObject(WinSta);
- /* Call the WH_CBT hook */
- dwStyle = Cs->style;
- Cs->style = Window->style; /* HCBT_CREATEWND needs the real window style */
- CbtCreate.lpcs = Cs;
- CbtCreate.hwndInsertAfter = HWND_TOP;
+ //// Call the WH_CBT hook ////
+
+ // Allocate the calling structures Justin Case this goes Global.
+ pCsw = ExAllocatePoolWithTag(NonPagedPool, sizeof(CREATESTRUCTW), TAG_HOOK);
+ pCbtCreate = ExAllocatePoolWithTag(NonPagedPool, sizeof(CBT_CREATEWNDW), TAG_HOOK);
+
+ /* Fill the new CREATESTRUCTW */
+ pCsw->lpCreateParams = Cs->lpCreateParams;
+ pCsw->hInstance = Cs->hInstance;
+ pCsw->hMenu = Cs->hMenu;
+ pCsw->hwndParent = Cs->hwndParent;
+ pCsw->cx = Cs->cx;
+ pCsw->cy = Cs->cy;
+ pCsw->x = Cs->x;
+ pCsw->y = Cs->y;
+ pCsw->dwExStyle = Cs->dwExStyle;
+ dwStyle = Cs->style; // Save it anyway.
+ pCsw->style = Window->style; /* HCBT_CREATEWND needs the real window style */
+
+ pCsw->lpszName = (LPCWSTR) WindowName->Buffer;
+ pCsw->lpszClass = (LPCWSTR) ClassName->Buffer;
+
+ if (Window->state & WNDS_ANSICREATOR)
+ {
+ if (!IS_ATOM(ClassName->Buffer))
+ {
+ RtlUnicodeStringToAnsiString(&asClassName, ClassName, TRUE);
+ pCsw->lpszClass = (LPCWSTR) asClassName.Buffer;
+ }
+ }
+
+ pCbtCreate->lpcs = pCsw;
+ pCbtCreate->hwndInsertAfter = HWND_TOP;
- if (co_HOOK_CallHooks(WH_CBT, HCBT_CREATEWND, (WPARAM) hWnd, (LPARAM) &CbtCreate))
+ Result = co_HOOK_CallHooks(WH_CBT, HCBT_CREATEWND, (WPARAM) hWnd, (LPARAM) pCbtCreate);
+ if (Result != 0)
{
- DPRINT1("HCBT_CREATEWND hook failed!\n");
+ DPRINT1("WH_CBT HCBT_CREATEWND hook failed! 0x%x\n", Result);
RETURN( (PWND) NULL);
}
+ // Write back changes.
+ Cs->cx = pCsw->cx;
+ Cs->cy = pCsw->cy;
+ Cs->x = pCsw->x;
+ Cs->y = pCsw->y;
+ hwndInsertAfter = pCbtCreate->hwndInsertAfter;
Cs->style = dwStyle; /* NCCREATE and WM_NCCALCSIZE need the original values*/
}
/* Send the NCCREATE message */
- Result = co_IntSendMessage(Window->head.h, WM_NCCREATE, 0, (LPARAM) Cs);
+ Result = co_IntSendMessage(UserHMGetHandle(Window), WM_NCCREATE, 0, (LPARAM) Cs);
if (!Result)
{
DPRINT1("co_UserCreateWindowEx(): NCCREATE message failed\n");
/* Send the WM_CREATE message. */
- Result = co_IntSendMessage(Window->head.h, WM_CREATE, 0, (LPARAM) Cs);
+ Result = co_IntSendMessage(UserHMGetHandle(Window), WM_CREATE, 0, (LPARAM) Cs);
if (Result == (LRESULT)-1)
{
DPRINT1("co_UserCreateWindowEx(): WM_CREATE message failed\n");
}
/* Send the EVENT_OBJECT_CREATE event*/
- IntNotifyWinEvent(EVENT_OBJECT_CREATE, Window, OBJID_WINDOW, 0);
+ IntNotifyWinEvent(EVENT_OBJECT_CREATE, Window, OBJID_WINDOW, CHILDID_SELF, 0);
/* By setting the flag below it can be examined to determine if the window
was created successfully and a valid pwnd was passed back to caller since
if (Window->ExStyle & WS_EX_MDICHILD)
{
- co_IntSendMessage(ParentWindow->head.h, WM_MDIREFRESHMENU, 0, 0);
+ co_IntSendMessage(UserHMGetHandle(ParentWindow), WM_MDIREFRESHMENU, 0, 0);
/* ShowWindow won't activate child windows */
co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
}
IntDereferenceClass(Class, pti->pDeskInfo, pti->ppi);
}
+ if (pCsw) ExFreePoolWithTag(pCsw, TAG_HOOK);
+ if (pCbtCreate) ExFreePoolWithTag(pCbtCreate, TAG_HOOK);
+ RtlFreeAnsiString(&asClassName);
+
if (Window)
{
UserDerefObjectCo(Window);
/* Call the internal function */
pwnd = co_UserCreateWindowEx(&Cs, &ustrClassName, plstrWindowName);
- if(!pwnd)
+ if(!pwnd)
{
DPRINT1("co_UserCreateWindowEx failed!\n");
}
/* If window was created successfully and it is hooked */
if ((Window->state2 & WNDS2_WMCREATEMSGPROCESSED))
{
- if (co_HOOK_CallHooks(WH_CBT, HCBT_DESTROYWND, (WPARAM) hWnd, 0)) return FALSE;
+ if (co_HOOK_CallHooks(WH_CBT, HCBT_DESTROYWND, (WPARAM) hWnd, 0))
+ {
+ DPRINT1("Destroy Window WH_CBT Call Hook return!\n");
+ return FALSE;
+ }
}
/* Inform the parent */
WinPosInitInternalPos(Wnd, &Size, &Wnd->rcWindow);
if (co_HOOK_CallHooks( WH_CBT, HCBT_MINMAX, (WPARAM)Wnd->head.h, ShowFlag))
+ {
+ DPRINT1("WinPosMinMaximize WH_CBT Call Hook return!\n");
return SWP_NOSIZE | SWP_NOMOVE;
-
+ }
if (Wnd->style & WS_MINIMIZE)
{
if (!co_IntSendMessageNoWait(Wnd->head.h, WM_QUERYOPEN, 0, 0))
}
}
}
-
return(SwpFlags);
}
co_IntSendMessageNoWait(WinPos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM) &WinPos);
}
+ if ( WinPos.flags & SWP_FRAMECHANGED || WinPos.flags & SWP_STATECHANGED ||
+ !(WinPos.flags & SWP_NOCLIENTSIZE) || !(WinPos.flags & SWP_NOCLIENTMOVE) )
+ {
+ PWND pWnd = UserGetWindowObject(WinPos.hwnd);
+ if (pWnd)
+ IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, pWnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
+ }
+
return TRUE;
}
static
BOOL
FASTCALL
- IntArc( DC *dc,
+ IntArc( DC *dc,
int Left,
int Top,
int Right,
}
if (!PenWidth) PenWidth = 1;
- pbrushPen->ptPenWidth.x = PenWidth;
+ pbrushPen->ptPenWidth.x = PenWidth;
RectBounds.left = Left;
RectBounds.right = Right;
IntLPtoDP(dc, (LPPOINT)&RectBounds, 2);
IntLPtoDP(dc, (LPPOINT)&RectSEpts, 2);
-
+
RectBounds.left += dc->ptlDCOrig.x;
RectBounds.right += dc->ptlDCOrig.x;
RectBounds.top += dc->ptlDCOrig.y;
}
if (arctype == GdiTypeChord)
PUTLINE(EfCx + CenterX, EfCy + CenterY, SfCx + CenterX, SfCy + CenterY, dc->eboLine);
-
+
pbrushPen->ptPenWidth.x = PenOrigWidth;
PEN_UnlockPen(pbrushPen);
DPRINT("IntArc Exit.\n");
pdcattr = dc->pdcattr;
- if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
- DC_vUpdateFillBrush(dc);
-
- if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
- DC_vUpdateLineBrush(dc);
-
if (arctype == GdiTypeArcTo)
{
if (dc->dclevel.flPath & DCPATH_CLOCKWISE)
}
worker.l = dwStartAngle;
worker1.l = dwSweepAngle;
+ DC_vPrepareDCsForBlit(pDC, pDC->rosdc.CombinedClip->rclBounds,
+ NULL, pDC->rosdc.CombinedClip->rclBounds);
+ if (pDC->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+ DC_vUpdateFillBrush(pDC);
+ if (pDC->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+ DC_vUpdateLineBrush(pDC);
Ret = IntGdiAngleArc( pDC, x, y, dwRadius, worker.f, worker1.f);
+ DC_vFinishBlit(pDC, NULL);
DC_UnlockDc( pDC );
return Ret;
}
return TRUE;
}
+ DC_vPrepareDCsForBlit(dc, dc->rosdc.CombinedClip->rclBounds,
+ NULL, dc->rosdc.CombinedClip->rclBounds);
+
+ if (dc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+ DC_vUpdateFillBrush(dc);
+
+ if (dc->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+ DC_vUpdateLineBrush(dc);
+
Ret = IntGdiArcInternal(
arctype,
dc,
XEndArc,
YEndArc);
+ DC_vFinishBlit(dc, NULL);
DC_UnlockDc( dc );
return Ret;
}
{
PDC DCDest;
PDC DCSrc;
+ HDC ahDC[2];
+ PGDIOBJ apObj[2];
SURFACE *BitmapDest, *BitmapSrc;
RECTL DestRect, SourceRect;
BOOL bResult;
return FALSE;
}
- DCDest = DC_LockDc(hDCDest);
- if (NULL == DCDest)
+ DPRINT("Locking DCs\n");
+ ahDC[0] = hDCDest;
+ ahDC[1] = hDCSrc ;
+ GDIOBJ_LockMultipleObjs(2, ahDC, apObj);
+ DCDest = apObj[0];
+ DCSrc = apObj[1];
+
+ if ((NULL == DCDest) || (NULL == DCSrc))
{
- DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiAlphaBlend\n", hDCDest);
+ DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hDCDest, hDCSrc);
SetLastWin32Error(ERROR_INVALID_HANDLE);
+ if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+ if(DCDest) GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
return FALSE;
}
- if (DCDest->dctype == DC_TYPE_INFO)
+ if (DCDest->dctype == DC_TYPE_INFO || DCDest->dctype == DCTYPE_INFO)
{
- DC_UnlockDc(DCDest);
+ GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+ GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
/* Yes, Windows really returns TRUE in this case */
return TRUE;
}
- if (hDCSrc != hDCDest)
- {
- DCSrc = DC_LockDc(hDCSrc);
- if (NULL == DCSrc)
- {
- DC_UnlockDc(DCDest);
- DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiAlphaBlend\n", hDCSrc);
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- return FALSE;
- }
-
- if (DCSrc->dctype == DC_TYPE_INFO)
- {
- DC_UnlockDc(DCSrc);
- DC_UnlockDc(DCDest);
- /* Yes, Windows really returns TRUE in this case */
- return TRUE;
- }
- }
- else
- {
- DCSrc = DCDest;
- }
-
DestRect.left = XOriginDest;
DestRect.top = YOriginDest;
DestRect.right = XOriginDest + WidthDest;
!SourceRect.right ||
!SourceRect.bottom)
{
- if (hDCSrc != hDCDest)
- DC_UnlockDc(DCSrc);
- DC_UnlockDc(DCDest);
+ GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+ GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
return TRUE;
}
+ /* Prepare DCs for blit */
+ DPRINT("Preparing DCs for blit\n");
+ DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect);
+
/* Determine surfaces to be used in the bitblt */
BitmapDest = DCDest->dclevel.pSurface;
if (!BitmapDest)
{
- if (hDCSrc != hDCDest)
- DC_UnlockDc(DCSrc);
- DC_UnlockDc(DCDest);
- return FALSE;
+ bResult = FALSE ;
+ goto leave ;
}
BitmapSrc = DCSrc->dclevel.pSurface;
if (!BitmapSrc)
{
- if (hDCSrc != hDCDest)
- DC_UnlockDc(DCSrc);
- DC_UnlockDc(DCDest);
- return FALSE;
+ bResult = FALSE;
+ goto leave;
}
/* Create the XLATEOBJ. */
EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
/* Perform the alpha blend operation */
+ DPRINT("Performing the alpha Blend\n");
bResult = IntEngAlphaBlend(&BitmapDest->SurfObj,
&BitmapSrc->SurfObj,
DCDest->rosdc.CombinedClip,
&BlendObj);
EXLATEOBJ_vCleanup(&exlo);
- DC_UnlockDc(DCDest);
- if (hDCSrc != hDCDest)
- DC_UnlockDc(DCSrc);
+ leave :
+ DPRINT("Finishing blit\n");
+ DC_vFinishBlit(DCDest, DCSrc);
+ GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+ GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
return bResult;
}
{
PDC DCDest;
PDC DCSrc = NULL;
+ HDC ahDC[2];
+ PGDIOBJ apObj[2];
PDC_ATTR pdcattr = NULL;
SURFACE *BitmapDest, *BitmapSrc = NULL;
- RECTL DestRect;
+ RECTL DestRect, SourceRect;
POINTL SourcePoint;
BOOL Status = FALSE;
EXLATEOBJ exlo;
XLATEOBJ *XlateObj = NULL;
BOOL UsesSource = ROP3_USES_SOURCE(ROP);
- DCDest = DC_LockDc(hDCDest);
+ DPRINT("Locking DCs\n");
+ ahDC[0] = hDCDest;
+ ahDC[1] = hDCSrc ;
+ GDIOBJ_LockMultipleObjs(2, ahDC, apObj);
+ DCDest = apObj[0];
+ DCSrc = apObj[1];
+
if (NULL == DCDest)
{
+ if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
DPRINT("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest);
return FALSE;
}
if (DCDest->dctype == DC_TYPE_INFO)
{
- DC_UnlockDc(DCDest);
+ if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+ GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
/* Yes, Windows really returns TRUE in this case */
return TRUE;
}
if (UsesSource)
{
- if (hDCSrc != hDCDest)
+ if (NULL == DCSrc)
{
- DCSrc = DC_LockDc(hDCSrc);
- if (NULL == DCSrc)
- {
- DC_UnlockDc(DCDest);
- DPRINT("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc);
- return FALSE;
- }
- if (DCSrc->dctype == DC_TYPE_INFO)
- {
- DC_UnlockDc(DCSrc);
- DC_UnlockDc(DCDest);
- /* Yes, Windows really returns TRUE in this case */
- return TRUE;
- }
+ GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
+ DPRINT("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc);
+ return FALSE;
}
- else
+ if (DCSrc->dctype == DC_TYPE_INFO)
{
- DCSrc = DCDest;
+ GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
+ GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+ /* Yes, Windows really returns TRUE in this case */
+ return TRUE;
}
}
+ else if(DCSrc)
+ {
+ DPRINT1("Getting a valid Source handle without using source!!!\n");
+ GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+ DCSrc = NULL ;
+ }
pdcattr = DCDest->pdcattr;
- if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
- DC_vUpdateFillBrush(DCDest);
-
DestRect.left = XDest;
DestRect.top = YDest;
DestRect.right = XDest+Width;
SourcePoint.x += DCSrc->ptlDCOrig.x;
SourcePoint.y += DCSrc->ptlDCOrig.y;
+ /* Calculate Source Rect */
+ SourceRect.left = SourcePoint.x;
+ SourceRect.top = SourcePoint.y;
+ SourceRect.right = SourcePoint.x + DestRect.right - DestRect.left;
+ SourceRect.bottom = SourcePoint.y + DestRect.bottom - DestRect.top ;
}
+ /* Prepare blit */
+ DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect);
+
+ if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+ DC_vUpdateFillBrush(DCDest);
+
/* Determine surfaces to be used in the bitblt */
BitmapDest = DCDest->dclevel.pSurface;
if (!BitmapDest)
&DCDest->dclevel.pbrFill->ptOrigin,
ROP3_TO_ROP4(ROP));
- if (UsesSource)
+ if (UsesSource)
EXLATEOBJ_vCleanup(&exlo);
cleanup:
- if (UsesSource && hDCSrc != hDCDest)
+ DC_vFinishBlit(DCDest, DCSrc);
+ if (UsesSource)
{
- DC_UnlockDc(DCSrc);
+ GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
}
- DC_UnlockDc(DCDest);
+ GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
return Status;
}
COLORREF TransColor)
{
PDC DCDest, DCSrc;
+ HDC ahDC[2];
+ PGDIOBJ apObj[2];
RECTL rcDest, rcSrc;
SURFACE *BitmapDest, *BitmapSrc = NULL;
- HPALETTE SourcePalette = 0, DestPalette = 0;
- PPALETTE PalDestGDI, PalSourceGDI;
ULONG TransparentColor = 0;
BOOL Ret = FALSE;
EXLATEOBJ exlo;
- if(!(DCDest = DC_LockDc(hdcDst)))
- {
- DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcDst);
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- return FALSE;
- }
- if (DCDest->dctype == DC_TYPE_INFO)
- {
- DC_UnlockDc(DCDest);
- /* Yes, Windows really returns TRUE in this case */
- return TRUE;
- }
+ DPRINT("Locking DCs\n");
+ ahDC[0] = hdcDst;
+ ahDC[1] = hdcSrc ;
+ GDIOBJ_LockMultipleObjs(2, ahDC, apObj);
+ DCDest = apObj[0];
+ DCSrc = apObj[1];
- if((hdcDst != hdcSrc) && !(DCSrc = DC_LockDc(hdcSrc)))
+ if ((NULL == DCDest) || (NULL == DCSrc))
{
- DC_UnlockDc(DCDest);
- DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcSrc);
+ DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hdcDst, hdcSrc);
SetLastWin32Error(ERROR_INVALID_HANDLE);
+ if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+ if(DCDest) GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
return FALSE;
}
- if(hdcDst == hdcSrc)
- {
- DCSrc = DCDest;
- }
-
- if (DCSrc->dctype == DC_TYPE_INFO)
+ if (DCDest->dctype == DC_TYPE_INFO || DCDest->dctype == DCTYPE_INFO)
{
- DC_UnlockDc(DCSrc);
- if(hdcDst != hdcSrc)
- {
- DC_UnlockDc(DCDest);
- }
+ GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+ GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
/* Yes, Windows really returns TRUE in this case */
return TRUE;
}
- BitmapDest = DCDest->dclevel.pSurface;
- if (!BitmapDest)
- {
- goto done;
- }
-
- BitmapSrc = DCSrc->dclevel.pSurface;
- if (!BitmapSrc)
- {
- goto done;
- }
-
- DestPalette = BitmapDest->hDIBPalette;
- if (!DestPalette) DestPalette = pPrimarySurface->devinfo.hpalDefault;
-
- SourcePalette = BitmapSrc->hDIBPalette;
- if (!SourcePalette) SourcePalette = pPrimarySurface->devinfo.hpalDefault;
-
- if(!(PalSourceGDI = PALETTE_LockPalette(SourcePalette)))
- {
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- goto done;
- }
- PALETTE_UnlockPalette(PalSourceGDI);
-
- if(DestPalette != SourcePalette)
- {
- if (!(PalDestGDI = PALETTE_LockPalette(DestPalette)))
- {
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- goto done;
- }
- PALETTE_UnlockPalette(PalDestGDI);
- }
- else
- {
- PalDestGDI = PalSourceGDI;
- }
-
- /* Translate Transparent (RGB) Color to the source palette */
- EXLATEOBJ_vInitialize(&exlo, &gpalRGB, PalSourceGDI, 0, 0, 0);
- TransparentColor = XLATEOBJ_iXlate(&exlo.xlo, (ULONG)TransColor);
- EXLATEOBJ_vCleanup(&exlo);
-
- EXLATEOBJ_vInitialize(&exlo, PalSourceGDI, PalDestGDI, 0, 0, 0);
-
rcDest.left = xDst;
rcDest.top = yDst;
rcDest.right = rcDest.left + cxDst;
rcSrc.right += DCSrc->ptlDCOrig.x;
rcSrc.bottom += DCSrc->ptlDCOrig.y;
+ /* Prepare for blit */
+ DC_vPrepareDCsForBlit(DCDest, rcDest, DCSrc, rcSrc);
+
+ BitmapDest = DCDest->dclevel.pSurface;
+ if (!BitmapDest)
+ {
+ goto done;
+ }
+
+ BitmapSrc = DCSrc->dclevel.pSurface;
+ if (!BitmapSrc)
+ {
+ goto done;
+ }
+
+ /* Translate Transparent (RGB) Color to the source palette */
+ EXLATEOBJ_vInitialize(&exlo, &gpalRGB, BitmapSrc->ppal, 0, 0, 0);
+ TransparentColor = XLATEOBJ_iXlate(&exlo.xlo, (ULONG)TransColor);
+ EXLATEOBJ_vCleanup(&exlo);
+
+ EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
+
Ret = IntEngTransparentBlt(&BitmapDest->SurfObj, &BitmapSrc->SurfObj,
DCDest->rosdc.CombinedClip, &exlo.xlo, &rcDest, &rcSrc,
TransparentColor, 0);
- done:
- DC_UnlockDc(DCSrc);
- if(hdcDst != hdcSrc)
- {
- DC_UnlockDc(DCDest);
- }
EXLATEOBJ_vCleanup(&exlo);
+
+ done:
+ DC_vFinishBlit(DCDest, DCSrc);
+ GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
+ GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+
return Ret;
}
PDC DCDest;
PDC DCSrc = NULL;
PDC DCMask = NULL;
+ HDC ahDC[3];
+ PGDIOBJ apObj[3];
PDC_ATTR pdcattr;
SURFACE *BitmapDest, *BitmapSrc = NULL;
SURFACE *BitmapMask = NULL;
return FALSE;
}
- DCDest = DC_LockDc(hDCDest);
+ DPRINT("Locking DCs\n");
+ ahDC[0] = hDCDest;
+ ahDC[1] = hDCSrc ;
+ ahDC[2] = hDCMask ;
+ GDIOBJ_LockMultipleObjs(3, ahDC, apObj);
+ DCDest = apObj[0];
+ DCSrc = apObj[1];
+ DCMask = apObj[2];
+
if (NULL == DCDest)
{
- DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCDest);
- SetLastWin32Error(ERROR_INVALID_HANDLE);
+ if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+ if(DCMask) GDIOBJ_UnlockObjByPtr(&DCMask->BaseObject);
+ DPRINT("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest);
return FALSE;
}
if (DCDest->dctype == DC_TYPE_INFO)
{
- DC_UnlockDc(DCDest);
+ if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+ if(DCMask) GDIOBJ_UnlockObjByPtr(&DCMask->BaseObject);
+ GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
/* Yes, Windows really returns TRUE in this case */
return TRUE;
}
if (UsesSource)
{
- if (hDCSrc != hDCDest)
+ if (NULL == DCSrc)
{
- DCSrc = DC_LockDc(hDCSrc);
- if (NULL == DCSrc)
- {
- DC_UnlockDc(DCDest);
- DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCSrc);
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- return FALSE;
- }
- if (DCSrc->dctype == DC_TYPE_INFO)
- {
- DC_UnlockDc(DCSrc);
- DC_UnlockDc(DCDest);
- /* Yes, Windows really returns TRUE in this case */
- return TRUE;
- }
+ GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
+ if(DCMask) GDIOBJ_UnlockObjByPtr(&DCMask->BaseObject);
+ DPRINT("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc);
+ return FALSE;
}
- else
+ if (DCSrc->dctype == DC_TYPE_INFO)
{
- DCSrc = DCDest;
+ GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
+ GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+ if(DCMask) GDIOBJ_UnlockObjByPtr(&DCMask->BaseObject);
+ /* Yes, Windows really returns TRUE in this case */
+ return TRUE;
}
}
+ else if(DCSrc)
+ {
+ DPRINT1("Getting a valid Source handle without using source!!!\n");
+ GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+ DCSrc = NULL ;
+ }
pdcattr = DCDest->pdcattr;
- if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
- DC_vUpdateFillBrush(DCDest);
-
DestRect.left = XOriginDest;
DestRect.top = YOriginDest;
DestRect.right = XOriginDest+WidthDest;
BrushOrigin.x = 0;
BrushOrigin.y = 0;
+ /* Only prepare Source and Dest, hdcMask represents a DIB */
+ DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect);
+
+ if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+ DC_vUpdateFillBrush(DCDest);
+
/* Determine surfaces to be used in the bitblt */
BitmapDest = DCDest->dclevel.pSurface;
if (BitmapDest == NULL)
BrushOrigin.y += DCDest->ptlDCOrig.y;
/* Make mask surface for source surface */
- if (BitmapSrc && hDCMask)
+ if (BitmapSrc && DCMask)
{
- DCMask = DC_LockDc(hDCMask);
- if (DCMask)
+ BitmapMask = DCMask->dclevel.pSurface;
+ if (BitmapMask &&
+ (BitmapMask->SurfObj.sizlBitmap.cx < WidthSrc ||
+ BitmapMask->SurfObj.sizlBitmap.cy < HeightSrc))
{
- BitmapMask = DCMask->dclevel.pSurface;
- if (BitmapMask &&
- (BitmapMask->SurfObj.sizlBitmap.cx < WidthSrc ||
- BitmapMask->SurfObj.sizlBitmap.cy < HeightSrc))
- {
- DPRINT1("%dx%d mask is smaller than %dx%d bitmap\n",
- BitmapMask->SurfObj.sizlBitmap.cx, BitmapMask->SurfObj.sizlBitmap.cy,
- WidthSrc, HeightSrc);
- goto failed;
- }
- /* Create mask offset point */
- MaskPoint.x = XOriginMask;
- MaskPoint.y = YOriginMask;
- IntLPtoDP(DCMask, &MaskPoint, 1);
- MaskPoint.x += DCMask->ptlDCOrig.x;
- MaskPoint.y += DCMask->ptlDCOrig.x;
+ DPRINT1("%dx%d mask is smaller than %dx%d bitmap\n",
+ BitmapMask->SurfObj.sizlBitmap.cx, BitmapMask->SurfObj.sizlBitmap.cy,
+ WidthSrc, HeightSrc);
+ EXLATEOBJ_vCleanup(&exlo);
+ goto failed;
}
+ /* Create mask offset point */
+ MaskPoint.x = XOriginMask;
+ MaskPoint.y = YOriginMask;
+ IntLPtoDP(DCMask, &MaskPoint, 1);
+ MaskPoint.x += DCMask->ptlDCOrig.x;
+ MaskPoint.y += DCMask->ptlDCOrig.x;
}
/* Perform the bitblt operation */
&DCDest->eboFill.BrushObject,
&BrushOrigin,
ROP3_TO_ROP4(ROP));
-
- failed:
if (UsesSource)
{
EXLATEOBJ_vCleanup(&exlo);
}
- if (UsesSource && hDCSrc != hDCDest)
+
+ failed:
+ DC_vFinishBlit(DCDest, DCSrc);
+ if (UsesSource)
{
DC_UnlockDc(DCSrc);
}
{
RECTL DestRect;
SURFACE *psurf;
- EBRUSHOBJ eboFill;
+ EBRUSHOBJ eboFill ;
POINTL BrushOrigin;
BOOL ret;
ASSERT(pbrush);
- psurf = pdc->dclevel.pSurface;
- if (psurf == NULL)
- {
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- return FALSE;
- }
-
if (pbrush->flAttrs & GDIBRUSH_IS_NULL)
{
return TRUE;
BrushOrigin.x = pbrush->ptOrigin.x + pdc->ptlDCOrig.x;
BrushOrigin.y = pbrush->ptOrigin.y + pdc->ptlDCOrig.y;
+ DC_vPrepareDCsForBlit(pdc, DestRect, NULL, DestRect);
+
+ psurf = pdc->dclevel.pSurface;
+
+ if (pdc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+ DC_vUpdateFillBrush(pdc);
+
EBRUSHOBJ_vInit(&eboFill, pbrush, pdc);
ret = IntEngBitBlt(
&DestRect,
NULL,
NULL,
- &eboFill.BrushObject, // use pDC->eboFill
+ &eboFill.BrushObject,
&BrushOrigin,
ROP3_TO_ROP4(dwRop));
+ DC_vFinishBlit(pdc, NULL);
+
EBRUSHOBJ_vCleanup(&eboFill);
return ret;
#define NDEBUG
#include <debug.h>
- HBITMAP APIENTRY
- IntGdiCreateBitmap(
- INT Width,
- INT Height,
- UINT Planes,
- UINT BitsPixel,
- IN OPTIONAL LPBYTE pBits)
+ LONG APIENTRY
+ IntSetBitmapBits(
+ PSURFACE psurf,
+ DWORD Bytes,
+ IN PBYTE Bits)
{
- HBITMAP hBitmap;
- SIZEL Size;
- LONG WidthBytes;
- PSURFACE psurfBmp;
+ /* Don't copy more bytes than the buffer has */
+ Bytes = min(Bytes, psurf->SurfObj.cjBits);
- /* NOTE: Windows also doesn't store nr. of planes separately! */
- BitsPixel = BITMAP_GetRealBitsPixel(BitsPixel * Planes);
+ RtlCopyMemory(psurf->SurfObj.pvBits, Bits, Bytes);
- /* Check parameters */
- if (BitsPixel == 0 || Width <= 0 || Width >= 0x8000000 || Height == 0)
- {
- DPRINT1("Width = %d, Height = %d BitsPixel = %d\n",
- Width, Height, BitsPixel);
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- return 0;
- }
+ return Bytes;
+ }
- WidthBytes = BITMAP_GetWidthBytes(Width, BitsPixel);
+ void
+ NTAPI
+ UnsafeSetBitmapBits(
+ PSURFACE psurf,
+ IN ULONG cjBits,
+ IN PVOID pvBits)
+ {
+ PUCHAR pjDst, pjSrc;
+ LONG lDeltaDst, lDeltaSrc;
+ ULONG nWidth, nHeight, cBitsPixel;
- Size.cx = Width;
- Size.cy = abs(Height);
+ nWidth = psurf->SurfObj.sizlBitmap.cx;
+ nHeight = psurf->SurfObj.sizlBitmap.cy;
+ cBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
- /* Make sure that cjBits will not overflow */
- if ((ULONGLONG)WidthBytes * Size.cy >= 0x100000000ULL)
- {
- DPRINT1("Width = %d, Height = %d BitsPixel = %d\n",
- Width, Height, BitsPixel);
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- return 0;
- }
+ /* Get pointers */
+ pjDst = psurf->SurfObj.pvScan0;
+ pjSrc = pvBits;
+ lDeltaDst = psurf->SurfObj.lDelta;
+ lDeltaSrc = WIDTH_BYTES_ALIGN16(nWidth, cBitsPixel);
- /* Create the bitmap object. */
- hBitmap = IntCreateBitmap(Size, WidthBytes,
- BitmapFormat(BitsPixel, BI_RGB),
- (Height < 0 ? BMF_TOPDOWN : 0) |
- (NULL == pBits ? 0 : BMF_NOZEROINIT), NULL);
- if (!hBitmap)
+ while (nHeight--)
{
- DPRINT("IntGdiCreateBitmap: returned 0\n");
- return 0;
+ /* Copy one line */
+ memcpy(pjDst, pjSrc, lDeltaSrc);
+ pjSrc += lDeltaSrc;
+ pjDst += lDeltaDst;
}
- psurfBmp = SURFACE_LockSurface(hBitmap);
- if (psurfBmp == NULL)
+ }
+
+ HBITMAP
+ APIENTRY
+ GreCreateBitmapEx(
+ IN INT nWidth,
+ IN INT nHeight,
+ IN ULONG cjWidthBytes,
+ IN ULONG iFormat,
+ IN USHORT fjBitmap,
+ IN ULONG cjSizeImage,
+ IN OPTIONAL PVOID pvBits,
+ IN FLONG flags)
+ {
+ PSURFACE psurf;
+ SURFOBJ *pso;
+ HBITMAP hbmp;
+ PVOID pvCompressedBits;
+ SIZEL sizl;
+
+ /* Verify format */
+ if (iFormat < BMF_1BPP || iFormat > BMF_PNG) return NULL;
+
+ /* Allocate a surface */
+ psurf = SURFACE_AllocSurface(STYPE_BITMAP, nWidth, nHeight, iFormat);
+ if (!psurf)
{
- GreDeleteObject(hBitmap);
+ DPRINT1("SURFACE_AllocSurface failed.\n");
return NULL;
}
- psurfBmp->flFlags = BITMAPOBJ_IS_APIBITMAP;
- psurfBmp->hDC = NULL; // Fixme
+ /* Get the handle for the bitmap and the surfobj */
+ hbmp = (HBITMAP)psurf->SurfObj.hsurf;
+ pso = &psurf->SurfObj;
- if (NULL != pBits)
+ /* The infamous RLE hack */
+ if (iFormat == BMF_4RLE || iFormat == BMF_8RLE)
{
- IntSetBitmapBits(psurfBmp, psurfBmp->SurfObj.cjBits, pBits);
+ sizl.cx = nWidth;
+ sizl.cy = nHeight;
+ pvCompressedBits = pvBits;
+ pvBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB);
+ DecompressBitmap(sizl, pvCompressedBits, pvBits, pso->lDelta, iFormat);
+ fjBitmap |= BMF_RLE_HACK;
}
- SURFACE_UnlockSurface(psurfBmp);
+ /* Mark as API bitmap */
+ psurf->flags |= (flags | API_BITMAP);
- DPRINT("IntGdiCreateBitmap : %dx%d, %d BPP colors, topdown %d, returning %08x\n",
- Size.cx, Size.cy, BitsPixel, (Height < 0 ? 1 : 0), hBitmap);
+ /* Set the bitmap bits */
+ if (!SURFACE_bSetBitmapBits(psurf, fjBitmap, cjWidthBytes, pvBits))
+ {
+ /* Bail out if that failed */
+ DPRINT1("SURFACE_bSetBitmapBits failed.\n");
+ SURFACE_FreeSurfaceByHandle(hbmp);
+ return NULL;
+ }
- return hBitmap;
+ /* Unlock the surface and return */
+ SURFACE_UnlockSurface(psurf);
+ return hbmp;
}
+ /* Creates a DDB surface,
+ * as in CreateCompatibleBitmap or CreateBitmap.
+ */
+ HBITMAP
+ APIENTRY
+ GreCreateBitmap(
+ IN INT nWidth,
+ IN INT nHeight,
+ IN UINT cPlanes,
+ IN UINT cBitsPixel,
+ IN OPTIONAL PVOID pvBits)
+ {
+ /* Call the extended function */
+ return GreCreateBitmapEx(nWidth,
+ nHeight,
+ 0, /* auto width */
+ BitmapFormat(cBitsPixel * cPlanes, BI_RGB),
+ 0, /* no bitmap flags */
+ 0, /* auto size */
+ pvBits,
+ DDB_SURFACE /* DDB */);
+ }
- HBITMAP APIENTRY
+ HBITMAP
+ APIENTRY
NtGdiCreateBitmap(
- INT Width,
- INT Height,
- UINT Planes,
- UINT BitsPixel,
+ IN INT nWidth,
+ IN INT nHeight,
+ IN UINT cPlanes,
+ IN UINT cBitsPixel,
IN OPTIONAL LPBYTE pUnsafeBits)
{
- if (pUnsafeBits)
+ HBITMAP hbmp;
+ ULONG cjWidthBytes, iFormat;
+
+ /* NOTE: Windows also doesn't store nr. of planes separately! */
+ cBitsPixel = BITMAP_GetRealBitsPixel(cBitsPixel * cPlanes);
+
+ /* Calculate bitmap format */
+ iFormat = BitmapFormat(cBitsPixel, BI_RGB);
+
+ /* Check parameters */
+ if (iFormat == 0 || nWidth <= 0 || nWidth >= 0x8000000 || nHeight <= 0)
{
- BOOL Hit = FALSE;
- UINT cjBits = BITMAP_GetWidthBytes(Width, BitsPixel) * abs(Height);
+ DPRINT1("Width = %d, Height = %d BitsPixel = %d\n",
+ nWidth, nHeight, cBitsPixel);
+ EngSetLastError(ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
- // FIXME: Use MmSecureVirtualMemory
+ /* Make sure that cjBits will not overflow */
+ cjWidthBytes = WIDTH_BYTES_ALIGN16(nWidth, cBitsPixel);
+ if ((ULONGLONG)cjWidthBytes * nHeight >= 0x100000000ULL)
+ {
+ DPRINT1("Width = %d, Height = %d BitsPixel = %d\n",
+ nWidth, nHeight, cBitsPixel);
+ EngSetLastError(ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ /* cBitsPixel = cBitsPixel * cPlanes now! */
+ hbmp = GreCreateBitmap(nWidth, nHeight, 1, cBitsPixel, NULL);
+
+ if (pUnsafeBits)
+ {
+ PSURFACE psurf = SURFACE_LockSurface(hbmp);
_SEH2_TRY
{
- ProbeForRead(pUnsafeBits, cjBits, 1);
+ ProbeForRead(pUnsafeBits, cjWidthBytes * nHeight, 1);
+ UnsafeSetBitmapBits(psurf, 0, pUnsafeBits);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- Hit = TRUE;
+ SURFACE_UnlockSurface(psurf);
+ SURFACE_FreeSurfaceByHandle(hbmp);
+ _SEH2_YIELD(return NULL;)
}
_SEH2_END
- if (Hit) return 0;
+ SURFACE_UnlockSurface(psurf);
}
- return IntGdiCreateBitmap(Width, Height, Planes, BitsPixel, pUnsafeBits);
+ return hbmp;
}
+
HBITMAP FASTCALL
IntCreateCompatibleBitmap(
PDC Dc,
{
if (Dc->dctype != DC_TYPE_MEMORY)
{
- Bmp = IntGdiCreateBitmap(abs(Width),
- abs(Height),
- IntGdiGetDeviceCaps(Dc,PLANES),
- IntGdiGetDeviceCaps(Dc,BITSPIXEL),
- NULL);
+ PSURFACE psurf;
+
+ Bmp = GreCreateBitmap(abs(Width),
+ abs(Height),
+ 1,
+ Dc->ppdev->gdiinfo.cBitsPixel,
+ NULL);
+ psurf = SURFACE_LockSurface(Bmp);
+ ASSERT(psurf);
+ /* Set palette */
+ psurf->ppal = PALETTE_ShareLockPalette(Dc->ppdev->devinfo.hpalDefault);
+ /* Set flags */
+ psurf->flags = API_BITMAP;
+ psurf->hdc = NULL; // Fixme
+ SURFACE_UnlockSurface(psurf);
}
else
{
{
if (Count == sizeof(BITMAP))
{
- /* We have a bitmap bug!!! W/O the HACK, we have white icons.
-
- MSDN Note: When a memory device context is created, it initially
- has a 1-by-1 monochrome bitmap selected into it. If this memory
- device context is used in CreateCompatibleBitmap, the bitmap that
- is created is a monochrome bitmap. To create a color bitmap, use
- the hDC that was used to create the memory device context, as
- shown in the following code:
-
- HDC memDC = CreateCompatibleDC(hDC);
- HBITMAP memBM = CreateCompatibleBitmap(hDC, nWidth, nHeight);
- SelectObject(memDC, memBM);
- */
- Bmp = IntGdiCreateBitmap(abs(Width),
- abs(Height),
- dibs.dsBm.bmPlanes,
- IntGdiGetDeviceCaps(Dc,BITSPIXEL),//<-- HACK! dibs.dsBm.bmBitsPixel, // <-- Correct!
- NULL);
+ PSURFACE psurfBmp;
+
+ Bmp = GreCreateBitmap(abs(Width),
+ abs(Height),
+ 1,
+ dibs.dsBm.bmBitsPixel,
+ NULL);
+ psurfBmp = SURFACE_LockSurface(Bmp);
+ ASSERT(psurfBmp);
+ /* Assign palette */
+ psurfBmp->ppal = psurf->ppal;
+ GDIOBJ_IncrementShareCount((POBJ)psurf->ppal);
+ /* Set flags */
+ psurfBmp->flags = API_BITMAP;
+ psurfBmp->hdc = NULL; // Fixme
+ SURFACE_UnlockSurface(psurfBmp);
}
else
{
/* A DIB section is selected in the DC */
- BITMAPINFO *bi;
+ BYTE buf[sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD)] = {0};
PVOID Bits;
-
- /* Allocate memory for a BITMAPINFOHEADER structure and a
- color table. The maximum number of colors in a color table
- is 256 which corresponds to a bitmap with depth 8.
- Bitmaps with higher depths don't have color tables. */
- bi = ExAllocatePoolWithTag(PagedPool,
- sizeof(BITMAPINFOHEADER) +
- 256 * sizeof(RGBQUAD),
- TAG_TEMP);
-
- if (bi)
+ BITMAPINFO* bi = (BITMAPINFO*)buf;
+
+ bi->bmiHeader.biSize = sizeof(bi->bmiHeader);
+ bi->bmiHeader.biWidth = Width;
+ bi->bmiHeader.biHeight = Height;
+ bi->bmiHeader.biPlanes = dibs.dsBmih.biPlanes;
+ bi->bmiHeader.biBitCount = dibs.dsBmih.biBitCount;
+ bi->bmiHeader.biCompression = dibs.dsBmih.biCompression;
+ bi->bmiHeader.biSizeImage = 0;
+ bi->bmiHeader.biXPelsPerMeter = dibs.dsBmih.biXPelsPerMeter;
+ bi->bmiHeader.biYPelsPerMeter = dibs.dsBmih.biYPelsPerMeter;
+ bi->bmiHeader.biClrUsed = dibs.dsBmih.biClrUsed;
+ bi->bmiHeader.biClrImportant = dibs.dsBmih.biClrImportant;
+
+ if (bi->bmiHeader.biCompression == BI_BITFIELDS)
+ {
+ /* Copy the color masks */
+ RtlCopyMemory(bi->bmiColors, dibs.dsBitfields, 3*sizeof(RGBQUAD));
+ }
+ else if (bi->bmiHeader.biBitCount <= 8)
{
- bi->bmiHeader.biSize = sizeof(bi->bmiHeader);
- bi->bmiHeader.biWidth = Width;
- bi->bmiHeader.biHeight = Height;
- bi->bmiHeader.biPlanes = dibs.dsBmih.biPlanes;
- bi->bmiHeader.biBitCount = dibs.dsBmih.biBitCount;
- bi->bmiHeader.biCompression = dibs.dsBmih.biCompression;
- bi->bmiHeader.biSizeImage = 0;
- bi->bmiHeader.biXPelsPerMeter = dibs.dsBmih.biXPelsPerMeter;
- bi->bmiHeader.biYPelsPerMeter = dibs.dsBmih.biYPelsPerMeter;
- bi->bmiHeader.biClrUsed = dibs.dsBmih.biClrUsed;
- bi->bmiHeader.biClrImportant = dibs.dsBmih.biClrImportant;
-
- if (bi->bmiHeader.biCompression == BI_BITFIELDS)
+ /* Copy the color table */
+ UINT Index;
+ PPALETTE PalGDI;
+
+ if (!psurf->ppal)
{
- /* Copy the color masks */
- RtlCopyMemory(bi->bmiColors, dibs.dsBitfields, 3 * sizeof(DWORD));
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ return 0;
}
- else if (bi->bmiHeader.biBitCount <= 8)
+
+ PalGDI = PALETTE_LockPalette(psurf->ppal->BaseObject.hHmgr);
+
+ for (Index = 0;
+ Index < 256 && Index < PalGDI->NumColors;
+ Index++)
{
- /* Copy the color table */
- UINT Index;
- PPALETTE PalGDI = PALETTE_LockPalette(psurf->hDIBPalette);
-
- if (!PalGDI)
- {
- ExFreePoolWithTag(bi, TAG_TEMP);
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- return 0;
- }
-
- for (Index = 0;
- Index < 256 && Index < PalGDI->NumColors;
- Index++)
- {
- bi->bmiColors[Index].rgbRed = PalGDI->IndexedColors[Index].peRed;
- bi->bmiColors[Index].rgbGreen = PalGDI->IndexedColors[Index].peGreen;
- bi->bmiColors[Index].rgbBlue = PalGDI->IndexedColors[Index].peBlue;
- bi->bmiColors[Index].rgbReserved = 0;
- }
- PALETTE_UnlockPalette(PalGDI);
+ bi->bmiColors[Index].rgbRed = PalGDI->IndexedColors[Index].peRed;
+ bi->bmiColors[Index].rgbGreen = PalGDI->IndexedColors[Index].peGreen;
+ bi->bmiColors[Index].rgbBlue = PalGDI->IndexedColors[Index].peBlue;
+ bi->bmiColors[Index].rgbReserved = 0;
}
+ PALETTE_UnlockPalette(PalGDI);
Bmp = DIB_CreateDIBSection(Dc,
bi,
NULL,
0,
0);
-
- ExFreePoolWithTag(bi, TAG_TEMP);
return Bmp;
}
}
}
if (!hDC)
- return IntGdiCreateBitmap(Width, Height, 1, 1, 0);
+ return GreCreateBitmap(Width, Height, 1, 1, 0);
Dc = DC_LockDc(hDC);
_SEH2_TRY
{
ProbeForWrite(Dimension, sizeof(SIZE), 1);
- *Dimension = psurfBmp->dimension;
+ *Dimension = psurfBmp->sizlDim;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
BOOL bInRect = FALSE;
SURFACE *psurf;
SURFOBJ *pso;
- HPALETTE hpal = 0;
- PPALETTE ppal;
EXLATEOBJ exlo;
HBITMAP hBmpTmp;
psurf = dc->dclevel.pSurface;
if (psurf)
{
- pso = &psurf->SurfObj;
- hpal = psurf->hDIBPalette;
- if (!hpal) hpal = pPrimarySurface->devinfo.hpalDefault;
- ppal = PALETTE_ShareLockPalette(hpal);
-
- if (psurf->SurfObj.iBitmapFormat == BMF_1BPP && !psurf->hSecure)
- {
- /* FIXME: palette should be gpalMono already ! */
- EXLATEOBJ_vInitialize(&exlo, &gpalMono, &gpalRGB, 0, 0xffffff, 0);
- }
- else
- {
- EXLATEOBJ_vInitialize(&exlo, ppal, &gpalRGB, 0, 0xffffff, 0);
- }
-
+ pso = &psurf->SurfObj;
+ EXLATEOBJ_vInitialize(&exlo, psurf->ppal, &gpalRGB, 0, 0xffffff, 0);
// check if this DC has a DIB behind it...
if (pso->pvScan0) // STYPE_BITMAP == pso->iType
{
}
EXLATEOBJ_vCleanup(&exlo);
- PALETTE_ShareUnlockPalette(ppal);
}
}
DC_UnlockDc(dc);
0,
0);
- //HBITMAP hBmpTmp = IntGdiCreateBitmap(1, 1, 1, 32, NULL);
+ //HBITMAP hBmpTmp = GreCreateBitmap(1, 1, 1, 32, NULL);
if (hBmpTmp)
{
HBITMAP hBmpOld = (HBITMAP)NtGdiSelectBitmap(hDCTmp, hBmpTmp);
return ret;
}
+ VOID
+ FASTCALL
+ UnsafeGetBitmapBits(
+ PSURFACE psurf,
+ DWORD Bytes,
+ OUT PBYTE pvBits)
+ {
+ PUCHAR pjDst, pjSrc;
+ LONG lDeltaDst, lDeltaSrc;
+ ULONG nWidth, nHeight, cBitsPixel;
+
+ nWidth = psurf->SurfObj.sizlBitmap.cx;
+ nHeight = psurf->SurfObj.sizlBitmap.cy;
+ cBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
+
+ /* Get pointers */
+ pjSrc = psurf->SurfObj.pvScan0;
+ pjDst = pvBits;
+ lDeltaSrc = psurf->SurfObj.lDelta;
+ lDeltaDst = WIDTH_BYTES_ALIGN16(nWidth, cBitsPixel);
+
+ while (nHeight--)
+ {
+ /* Copy one line */
+ RtlCopyMemory(pjDst, pjSrc, lDeltaDst);
+ pjSrc += lDeltaSrc;
+ pjDst += lDeltaDst;
+ }
+ }
+
LONG APIENTRY
NtGdiGetBitmapBits(
HBITMAP hBitmap,
return 0;
}
- bmSize = BITMAP_GetWidthBytes(psurf->SurfObj.sizlBitmap.cx,
+ bmSize = WIDTH_BYTES_ALIGN16(psurf->SurfObj.sizlBitmap.cx,
BitsPerFormat(psurf->SurfObj.iBitmapFormat)) *
abs(psurf->SurfObj.sizlBitmap.cy);
_SEH2_TRY
{
ProbeForWrite(pUnsafeBits, Bytes, 1);
- ret = IntGetBitmapBits(psurf, Bytes, pUnsafeBits);
+ UnsafeGetBitmapBits(psurf, Bytes, pUnsafeBits);
+ ret = Bytes;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
}
- LONG APIENTRY
- IntSetBitmapBits(
- PSURFACE psurf,
- DWORD Bytes,
- IN PBYTE Bits)
- {
- LONG ret;
-
- /* Don't copy more bytes than the buffer has */
- Bytes = min(Bytes, psurf->SurfObj.cjBits);
-
- #if 0
- /* FIXME: call DDI specific function here if available */
- if (psurf->DDBitmap)
- {
- DPRINT("Calling device specific BitmapBits\n");
- if (psurf->DDBitmap->funcs->pBitmapBits)
- {
- ret = psurf->DDBitmap->funcs->pBitmapBits(hBitmap,
- (void *)Bits,
- Bytes,
- DDB_SET);
- }
- else
- {
- DPRINT("BitmapBits == NULL??\n");
- ret = 0;
- }
- }
- else
- #endif
- {
- RtlCopyMemory(psurf->SurfObj.pvBits, Bits, Bytes);
- ret = Bytes;
- }
-
- return ret;
- }
-
-
LONG APIENTRY
NtGdiSetBitmapBits(
HBITMAP hBitmap,
_SEH2_TRY
{
ProbeForRead(pUnsafeBits, Bytes, 1);
- ret = IntSetBitmapBits(psurf, Bytes, pUnsafeBits);
+ UnsafeSetBitmapBits(psurf, Bytes, pUnsafeBits);
+ ret = 1;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
_SEH2_TRY
{
ProbeForWrite(Size, sizeof(SIZE), 1);
- *Size = psurf->dimension;
+ *Size = psurf->sizlDim;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
}
/* The dimension is changed even if writing the old value failed */
- psurf->dimension.cx = Width;
- psurf->dimension.cy = Height;
+ psurf->sizlDim.cx = Width;
+ psurf->sizlDim.cy = Height;
SURFACE_UnlockSurface(psurf);
switch (*Color >> 24)
{
case 0x10: /* DIBINDEX */
- if (IntGetDIBColorTable(hDC, LOWORD(*Color), 1, &quad) == 1)
+ if (IntGetDIBColorTable(hDC, LOWORD(*Color), 1, &quad) == 1)
{
*Color = RGB(quad.rgbRed, quad.rgbGreen, quad.rgbBlue);
}
default:
DPRINT("Unsupported color type %d passed\n", *Color >> 24);
break;
- }
+ }
}
BOOL APIENTRY
return 0;
}
- INT FASTCALL
- BITMAP_GetWidthBytes(INT bmWidth, INT bpp)
- {
- #if 0
- switch (bpp)
- {
- case 1:
- return 2 * ((bmWidth+15) >> 4);
-
- case 24:
- bmWidth *= 3; /* fall through */
- case 8:
- return bmWidth + (bmWidth & 1);
-
- case 32:
- return bmWidth * 4;
-
- case 16:
- case 15:
- return bmWidth * 2;
-
- case 4:
- return 2 * ((bmWidth+3) >> 2);
-
- default:
- DPRINT ("stub");
- }
-
- return -1;
- #endif
-
- return ((bmWidth * bpp + 15) & ~15) >> 3;
- }
-
HBITMAP FASTCALL
BITMAP_CopyBitmap(HBITMAP hBitmap)
{
return 0;
}
- Bitmap = GDIOBJ_LockObj(hBitmap, GDI_OBJECT_TYPE_BITMAP);
+ Bitmap = SURFACE_LockSurface(hBitmap);
if (Bitmap == NULL)
{
return 0;
Size.cx = abs(bm.bmWidth);
Size.cy = abs(bm.bmHeight);
- res = IntCreateBitmap(Size,
- bm.bmWidthBytes,
- BitmapFormat(bm.bmBitsPixel * bm.bmPlanes, BI_RGB),
- (bm.bmHeight < 0 ? BMF_TOPDOWN : 0) | BMF_NOZEROINIT,
- NULL);
+ res = GreCreateBitmapEx(Size.cx,
+ Size.cy,
+ bm.bmWidthBytes,
+ Bitmap->SurfObj.iBitmapFormat,
+ Bitmap->SurfObj.fjBitmap,
+ Bitmap->SurfObj.cjBits,
+ NULL,
+ Bitmap->flags);
+
if (res)
{
- PBYTE buf;
-
- resBitmap = GDIOBJ_LockObj(res, GDI_OBJECT_TYPE_BITMAP);
+ resBitmap = SURFACE_LockSurface(res);
if (resBitmap)
{
- buf = ExAllocatePoolWithTag(PagedPool,
- bm.bmWidthBytes * abs(bm.bmHeight),
- TAG_BITMAP);
- if (buf == NULL)
- {
- GDIOBJ_UnlockObjByPtr((POBJ)resBitmap);
- GDIOBJ_UnlockObjByPtr((POBJ)Bitmap);
- GreDeleteObject(res);
- return 0;
- }
- IntGetBitmapBits(Bitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
- IntSetBitmapBits(resBitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
- ExFreePoolWithTag(buf,TAG_BITMAP);
- resBitmap->flFlags = Bitmap->flFlags;
- GDIOBJ_UnlockObjByPtr((POBJ)resBitmap);
+ IntSetBitmapBits(resBitmap, Bitmap->SurfObj.cjBits, Bitmap->SurfObj.pvBits);
+ SURFACE_UnlockSurface(resBitmap);
}
else
{
}
}
- GDIOBJ_UnlockObjByPtr((POBJ)Bitmap);
+ SURFACE_UnlockSurface(Bitmap);
return res;
}
pBitmap->bmType = 0;
pBitmap->bmWidth = psurf->SurfObj.sizlBitmap.cx;
pBitmap->bmHeight = psurf->SurfObj.sizlBitmap.cy;
- pBitmap->bmWidthBytes = abs(psurf->SurfObj.lDelta);
pBitmap->bmPlanes = 1;
pBitmap->bmBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
+ pBitmap->bmWidthBytes = WIDTH_BYTES_ALIGN16(pBitmap->bmWidth, pBitmap->bmBitsPixel);
/* Check for DIB section */
if (psurf->hSecure)
{
/* Set bmBits in this case */
pBitmap->bmBits = psurf->SurfObj.pvBits;
+ /* DIBs data are 32 bits aligned */
+ pBitmap->bmWidthBytes = WIDTH_BYTES_ALIGN32(pBitmap->bmWidth, pBitmap->bmBitsPixel);
if (Count >= sizeof(DIBSECTION))
{
pds->dsBmih.biHeight = pds->dsBm.bmHeight;
pds->dsBmih.biPlanes = pds->dsBm.bmPlanes;
pds->dsBmih.biBitCount = pds->dsBm.bmBitsPixel;
- switch (psurf->SurfObj.iBitmapFormat)
- {
- /* FIXME: What about BI_BITFIELDS? */
- case BMF_1BPP:
- case BMF_4BPP:
- case BMF_8BPP:
- case BMF_16BPP:
- case BMF_24BPP:
- case BMF_32BPP:
- pds->dsBmih.biCompression = BI_RGB;
- break;
- case BMF_4RLE:
- pds->dsBmih.biCompression = BI_RLE4;
- break;
- case BMF_8RLE:
- pds->dsBmih.biCompression = BI_RLE8;
- break;
- case BMF_JPEG:
- pds->dsBmih.biCompression = BI_JPEG;
- break;
- case BMF_PNG:
- pds->dsBmih.biCompression = BI_PNG;
- break;
- }
+ if(psurf->ppal->flFlags & PAL_BITFIELDS)
+ {
+ pds->dsBmih.biCompression = BI_BITFIELDS;
+ }
+ else
+ {
+ switch (psurf->SurfObj.iBitmapFormat)
+ {
+ case BMF_1BPP:
+ case BMF_4BPP:
+ case BMF_8BPP:
+ case BMF_16BPP:
+ case BMF_24BPP:
+ case BMF_32BPP:
+ pds->dsBmih.biCompression = BI_RGB;
+ break;
+ case BMF_4RLE:
+ pds->dsBmih.biCompression = BI_RLE4;
+ break;
+ case BMF_8RLE:
+ pds->dsBmih.biCompression = BI_RLE8;
+ break;
+ case BMF_JPEG:
+ pds->dsBmih.biCompression = BI_JPEG;
+ break;
+ case BMF_PNG:
+ pds->dsBmih.biCompression = BI_PNG;
+ break;
+ }
+ }
pds->dsBmih.biSizeImage = psurf->SurfObj.cjBits;
pds->dsBmih.biXPelsPerMeter = 0;
pds->dsBmih.biYPelsPerMeter = 0;
- pds->dsBmih.biClrUsed = psurf->biClrUsed;
+ pds->dsBmih.biClrUsed = psurf->ppal->NumColors;
pds->dsBmih.biClrImportant = psurf->biClrImportant;
- pds->dsBitfields[0] = psurf->dsBitfields[0];
- pds->dsBitfields[1] = psurf->dsBitfields[1];
- pds->dsBitfields[2] = psurf->dsBitfields[2];
+ pds->dsBitfields[0] = psurf->ppal->RedMask;
+ pds->dsBitfields[1] = psurf->ppal->GreenMask;
+ pds->dsBitfields[2] = psurf->ppal->BlueMask;
pds->dshSection = psurf->hDIBSection;
pds->dsOffset = psurf->dwOffset;
NtGdiGetDCforBitmap(
IN HBITMAP hsurf)
{
- HDC hDC = NULL;
+ HDC hdc = NULL;
PSURFACE psurf = SURFACE_LockSurface(hsurf);
if (psurf)
{
- hDC = psurf->hDC;
+ hdc = psurf->hdc;
SURFACE_UnlockSurface(psurf);
}
- return hDC;
+ return hdc;
}
+
/* EOF */
- /*
+ /*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS win32 subsystem
* PURPOSE: Functions for brushes
* FILE: subsystem/win32/win32k/objects/brush.c
- * PROGRAMER:
+ * PROGRAMER:
*/
#include <win32k.h>
DWORD nEntries;
PVOID AttrList[GDIOBJATTRFREE];
} GDI_OBJ_ATTR_FREELIST, *PGDI_OBJ_ATTR_FREELIST;
-
+
typedef struct _GDI_OBJ_ATTR_ENTRY
{
RGN_ATTR Attr[GDIOBJATTRFREE];
} GDI_OBJ_ATTR_ENTRY, *PGDI_OBJ_ATTR_ENTRY;
- static const USHORT HatchBrushes[NB_HATCH_STYLES][8] =
+ static const ULONG HatchBrushes[NB_HATCH_STYLES][8] =
{
{0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF}, /* HS_HORIZONTAL */
{0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7}, /* HS_VERTICAL */
PGDI_OBJ_ATTR_FREELIST pGdiObjAttrFreeList;
PGDI_OBJ_ATTR_ENTRY pGdiObjAttrEntry;
int i;
-
+
pti = PsGetCurrentThreadWin32Thread();
if (pti->pgdiBrushAttr)
{
PGDI_OBJ_ATTR_FREELIST pGdiObjAttrFreeList;
pti = PsGetCurrentThreadWin32Thread();
-
+
if (!pti) return;
-
+
if (!pti->pgdiBrushAttr)
{ // If it is null, just cache it for the next time.
pti->pgdiBrushAttr = pAttr;
return sizeof(LOGBRUSH);
}
- /**
- * @name CalculateColorTableSize
- *
- * Internal routine to calculate the number of color table entries.
- *
- * @param BitmapInfoHeader
- * Input bitmap information header, can be any version of
- * BITMAPINFOHEADER or BITMAPCOREHEADER.
- *
- * @param ColorSpec
- * Pointer to variable which specifiing the color mode (DIB_RGB_COLORS
- * or DIB_RGB_COLORS). On successful return this value is normalized
- * according to the bitmap info.
- *
- * @param ColorTableSize
- * On successful return this variable is filled with number of
- * entries in color table for the image with specified parameters.
- *
- * @return
- * TRUE if the input values together form a valid image, FALSE otherwise.
- */
- BOOL
- APIENTRY
- CalculateColorTableSize(
- CONST BITMAPINFOHEADER *BitmapInfoHeader,
- UINT *ColorSpec,
- UINT *ColorTableSize)
- {
- WORD BitCount;
- DWORD ClrUsed;
- DWORD Compression;
-
- /*
- * At first get some basic parameters from the passed BitmapInfoHeader
- * structure. It can have one of the following formats:
- * - BITMAPCOREHEADER (the oldest one with totally different layout
- * from the others)
- * - BITMAPINFOHEADER (the standard and most common header)
- * - BITMAPV4HEADER (extension of BITMAPINFOHEADER)
- * - BITMAPV5HEADER (extension of BITMAPV4HEADER)
- */
- if (BitmapInfoHeader->biSize == sizeof(BITMAPCOREHEADER))
- {
- BitCount = ((LPBITMAPCOREHEADER)BitmapInfoHeader)->bcBitCount;
- ClrUsed = 0;
- Compression = BI_RGB;
- }
- else
- {
- BitCount = BitmapInfoHeader->biBitCount;
- ClrUsed = BitmapInfoHeader->biClrUsed;
- Compression = BitmapInfoHeader->biCompression;
- }
-
- switch (Compression)
- {
- case BI_BITFIELDS:
- if (*ColorSpec == DIB_PAL_COLORS)
- *ColorSpec = DIB_RGB_COLORS;
-
- if (BitCount != 16 && BitCount != 32)
- return FALSE;
-
- /* For BITMAPV4HEADER/BITMAPV5HEADER the masks are included in
- * the structure itself (bV4RedMask, bV4GreenMask, and bV4BlueMask).
- * For BITMAPINFOHEADER the color masks are stored in the palette. */
- if (BitmapInfoHeader->biSize > sizeof(BITMAPINFOHEADER))
- *ColorTableSize = 0;
- else
- *ColorTableSize = 3;
-
- return TRUE;
-
- case BI_RGB:
- switch (BitCount)
- {
- case 1:
- *ColorTableSize = ClrUsed ? min(ClrUsed, 2) : 2;
- return TRUE;
-
- case 4:
- *ColorTableSize = ClrUsed ? min(ClrUsed, 16) : 16;
- return TRUE;
-
- case 8:
- *ColorTableSize = ClrUsed ? min(ClrUsed, 256) : 256;
- return TRUE;
-
- default:
- if (*ColorSpec == DIB_PAL_COLORS)
- *ColorSpec = DIB_RGB_COLORS;
- if (BitCount != 16 && BitCount != 24 && BitCount != 32)
- return FALSE;
- *ColorTableSize = ClrUsed;
- return TRUE;
- }
-
- case BI_RLE4:
- if (BitCount == 4)
- {
- *ColorTableSize = ClrUsed ? min(ClrUsed, 16) : 16;
- return TRUE;
- }
- return FALSE;
-
- case BI_RLE8:
- if (BitCount == 8)
- {
- *ColorTableSize = ClrUsed ? min(ClrUsed, 256) : 256;
- return TRUE;
- }
- return FALSE;
-
- case BI_JPEG:
- case BI_PNG:
- *ColorTableSize = ClrUsed;
- return TRUE;
-
- default:
- return FALSE;
- }
- }
-
HBRUSH
APIENTRY
IntGdiCreateDIBBrush(
PBRUSH pbrush;
HBITMAP hPattern;
ULONG_PTR DataPtr;
- UINT PaletteEntryCount;
- PSURFACE psurfPattern;
- INT PaletteType;
+ PVOID pvDIBits;
if (BitmapInfo->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
{
return NULL;
}
- if (!CalculateColorTableSize(&BitmapInfo->bmiHeader,
- &ColorSpec,
- &PaletteEntryCount))
- {
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- return NULL;
- }
-
- // FIXME: What about BI_BITFIELDS
- DataPtr = (ULONG_PTR)BitmapInfo + BitmapInfo->bmiHeader.biSize;
- if (ColorSpec == DIB_RGB_COLORS)
- DataPtr += PaletteEntryCount * sizeof(RGBQUAD);
- else
- DataPtr += PaletteEntryCount * sizeof(USHORT);
+ DataPtr = (ULONG_PTR)BitmapInfo + DIB_BitmapInfoSize(BitmapInfo, ColorSpec);
- hPattern = IntGdiCreateBitmap(BitmapInfo->bmiHeader.biWidth,
- BitmapInfo->bmiHeader.biHeight,
- BitmapInfo->bmiHeader.biPlanes,
- BitmapInfo->bmiHeader.biBitCount,
- (PVOID)DataPtr);
+ hPattern = DIB_CreateDIBSection(NULL, BitmapInfo, ColorSpec, &pvDIBits, NULL, 0, 0);
if (hPattern == NULL)
{
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
-
- psurfPattern = SURFACE_LockSurface(hPattern);
- ASSERT(psurfPattern != NULL);
- psurfPattern->hDIBPalette = BuildDIBPalette(BitmapInfo, &PaletteType);
- SURFACE_UnlockSurface(psurfPattern);
+ RtlCopyMemory(pvDIBits,
+ (PVOID)DataPtr,
+ DIB_GetDIBImageBytes(BitmapInfo->bmiHeader.biWidth,
+ BitmapInfo->bmiHeader.biHeight,
+ BitmapInfo->bmiHeader.biBitCount * BitmapInfo->bmiHeader.biPlanes));
pbrush = BRUSH_AllocBrushWithHandle();
if (pbrush == NULL)
return 0;
}
- hPattern = IntGdiCreateBitmap(8, 8, 1, 1, (LPBYTE)HatchBrushes[Style]);
+ hPattern = GreCreateBitmap(8, 8, 1, 1, (LPBYTE)HatchBrushes[Style]);
if (hPattern == NULL)
{
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
PROSRGNDATA CombinedRegion;
HRGN hRgnVis = Dc->prgnVis->BaseObject.hHmgr;
- /* Experiment with API region based on wine.. */
- if (Dc->rosdc.hClipRgn && Dc->dclevel.prgnMeta)
+ // would prefer this, but the rest of the code sucks
+ // ASSERT(Dc->rosdc.hGCClipRgn);
+ // ASSERT(Dc->rosdc.hClipRgn);
+ if (!Dc->prgnVis)
{
- PROSRGNDATA pClipRgn;
-
- if ((pClipRgn = RGNOBJAPI_Lock(Dc->rosdc.hClipRgn, NULL)))
- {
- if (!Dc->prgnAPI) Dc->prgnAPI = IntSysCreateRectpRgn( 0, 0, 0, 0 );
-
- IntGdiCombineRgn( Dc->prgnAPI,
- pClipRgn,
- Dc->dclevel.prgnMeta,
- RGN_AND );
- RGNOBJAPI_Unlock(pClipRgn);
- }
+ DPRINT1("Warning, prgnVis is NULL!\n");
}
else
{
- if (Dc->prgnAPI)
- GreDeleteObject(((PROSRGNDATA)Dc->prgnAPI)->BaseObject.hHmgr);
- Dc->prgnAPI = NULL;
+ hRgnVis = Dc->prgnVis->BaseObject.hHmgr ;
}
NtGdiOffsetRgn(Dc->rosdc.hGCClipRgn, Dc->ptlDCOrig.x, Dc->ptlDCOrig.y);
- if((CombinedRegion = RGNOBJAPI_Lock(Dc->rosdc.hGCClipRgn, NULL)))
- {
- CLIPOBJ *CombinedClip;
-
- CombinedClip = IntEngCreateClipRegion(CombinedRegion->rdh.nCount,
- CombinedRegion->Buffer,
- &CombinedRegion->rdh.rcBound);
+ if((CombinedRegion = RGNOBJAPI_Lock(Dc->rosdc.hGCClipRgn, NULL)))
+ {
+ CLIPOBJ *CombinedClip;
- RGNOBJAPI_Unlock(CombinedRegion);
+ CombinedClip = IntEngCreateClipRegion(CombinedRegion->rdh.nCount,
+ CombinedRegion->Buffer,
+ &CombinedRegion->rdh.rcBound);
- if (!CombinedClip)
- {
- DPRINT1("IntEngCreateClipRegion() failed\n");
- return ERROR;
- }
+ RGNOBJAPI_Unlock(CombinedRegion);
- if (Dc->rosdc.CombinedClip != NULL)
- IntEngDeleteClipRegion(Dc->rosdc.CombinedClip);
+ if ( !CombinedClip )
+ {
+ DPRINT1("IntEngCreateClipRegion() failed\n");
+ return ERROR;
+ }
- Dc->rosdc.CombinedClip = CombinedClip;
- }
+ if(Dc->rosdc.CombinedClip != NULL)
+ IntEngDeleteClipRegion(Dc->rosdc.CombinedClip);
+ Dc->rosdc.CombinedClip = CombinedClip ;
+ }
return NtGdiOffsetRgn(Dc->rosdc.hGCClipRgn, -Dc->ptlDCOrig.x, -Dc->ptlDCOrig.y);
}
NtGdiOffsetRgn(dc->prgnVis->BaseObject.hHmgr, -dc->ptlDCOrig.x, -dc->ptlDCOrig.y);
CLIPPING_UpdateGCRegion(dc);
}
-
DC_UnlockDc(dc);
return retval;
else
NtGdiCombineRgn(dc->rosdc.hClipRgn, dc->rosdc.hClipRgn, hrgn, fnMode);
}
+
return CLIPPING_UpdateGCRegion(dc);
}
retval = REGION_GetRgnBox(pRgnNew, rc);
REGION_FreeRgnByHandle(pRgnNew->BaseObject.hHmgr);
+
DC_UnlockDc(dc);
if(Unlock) REGION_UnlockRgn(pRgn);
return retval;
return Ret;
}
+
int APIENTRY NtGdiSetMetaRgn(HDC hDC)
{
INT Ret;
IntGdiCombineRgn( pDC->prgnAPI,
pDC->dclevel.prgnClip,
pDC->dclevel.prgnMeta,
- RGN_AND );
+ RGN_AND);
}
else
{
IntGdiCombineRgn( pDC->prgnAPI,
pDC->dclevel.prgnClip,
NULL,
- RGN_COPY );
+ RGN_COPY);
}
else if (pDC->dclevel.prgnMeta)
{
IntGdiCombineRgn( pDC->prgnAPI,
pDC->dclevel.prgnMeta,
NULL,
- RGN_COPY );
+ RGN_COPY);
}
}
IntGdiCombineRgn( pDC->prgnRao,
pDC->prgnVis,
pDC->prgnAPI,
- RGN_AND );
+ RGN_AND);
- RtlCopyMemory( &pDC->erclClip,
- &((PROSRGNDATA)pDC->prgnRao)->rdh.rcBound,
- sizeof(RECTL));
+ RtlCopyMemory(&pDC->erclClip,
+ &((PROSRGNDATA)pDC->prgnRao)->rdh.rcBound,
+ sizeof(RECTL));
pDC->fs &= ~DC_FLAG_DIRTY_RAO;
IntGdiOffsetRgn(pDC->prgnRao, pDC->ptlDCOrig.x, pDC->ptlDCOrig.y);
// pDC->co should be used. Example, CLIPOBJ_cEnumStart uses XCLIPOBJ to build
- // the rects from region objects rects in pClipRgn->Buffer.
+ // the rects from region objects rects in pClipRgn->Buffer.
// With pDC->co.pClipRgn->Buffer,
// pDC->co.pClipRgn = pDC->prgnRao ? pDC->prgnRao : pDC->prgnVis;
co = IntEngCreateClipRegion( ((PROSRGNDATA)pDC->prgnRao)->rdh.nCount,
((PROSRGNDATA)pDC->prgnRao)->Buffer,
- &pDC->erclClip);
-
+ &pDC->erclClip);
if (co)
{
if (pDC->rosdc.CombinedClip != NULL)
- IntEngDeleteClipRegion(pDC->rosdc.CombinedClip);
+ IntEngDeleteClipRegion(pDC->rosdc.CombinedClip);
pDC->rosdc.CombinedClip = co;
}
return;
}
+ BOOL
+ FASTCALL
+ DC_AllocDcAttr(PDC pdc)
+ {
+ DC_AllocateDcAttr(pdc->BaseObject.hHmgr);
+ *pdc->pdcattr = pdc->dcattr;
+ return TRUE;
+ }
+
+ // CHECK against current head
VOID
FASTCALL
DC_AllocateDcAttr(HDC hDC)
{
PVOID NewMem = NULL;
PDC pDC;
-
+ HANDLE Pid = NtCurrentProcess();
+ ULONG MemSize = sizeof(DC_ATTR); //PAGE_SIZE it will allocate that size
+
+ NTSTATUS Status = ZwAllocateVirtualMemory(Pid,
+ &NewMem,
+ 0,
+ &MemSize,
+ MEM_COMMIT|MEM_RESERVE,
+ PAGE_READWRITE);
{
INT Index = GDI_HANDLE_GET_INDEX((HGDIOBJ)hDC);
PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index];
-
- NewMem = AllocateDcAttr();
-
// FIXME: dc could have been deleted!!! use GDIOBJ_InsertUserData
-
- if (NewMem)
+ if (NT_SUCCESS(Status))
{
- RtlZeroMemory(NewMem, sizeof(DC_ATTR));
- Entry->UserData = NewMem;
- DPRINT("DC_ATTR allocated! 0x%x\n",NewMem);
+ RtlZeroMemory(NewMem, MemSize);
+ Entry->UserData = NewMem;
+ DPRINT("DC_ATTR allocated! 0x%x\n",NewMem);
}
else
{
- DPRINT1("DC_ATTR not allocated!\n");
+ DPRINT("DC_ATTR not allocated!\n");
}
}
pDC = DC_LockDc(hDC);
ASSERT(pDC->pdcattr == &pDC->dcattr);
- if (NewMem)
+ if(NewMem)
{
pDC->pdcattr = NewMem; // Store pointer
}
}
VOID
- FASTCALL
- DC_FreeDcAttr(HDC DCToFree )
+ NTAPI
+ DC_vFreeDcAttr(PDC pdc)
{
- PDC pDC = DC_LockDc(DCToFree);
- if (pDC->pdcattr == &pDC->dcattr) return; // Internal DC object!
- pDC->pdcattr = &pDC->dcattr;
- DC_UnlockDc(pDC);
+ HANDLE Pid = NtCurrentProcess();
+ INT Index;
+ PGDI_TABLE_ENTRY pent;
- {
- INT Index = GDI_HANDLE_GET_INDEX((HGDIOBJ)DCToFree);
- PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index];
- if (Entry->UserData)
+ if (pdc->pdcattr == &pdc->dcattr)
{
- FreeDcAttr(Entry->UserData);
- Entry->UserData = NULL;
+ // Internal DC object!
+ return;
+ }
+
+ pdc->pdcattr = &pdc->dcattr;
+
+ Index = GDI_HANDLE_GET_INDEX(pdc->BaseObject.hHmgr);
+ pent = &GdiHandleTable->Entries[Index];
+ if(pent->UserData)
+ {
+ ULONG MemSize = sizeof(DC_ATTR);
+ NTSTATUS Status = ZwFreeVirtualMemory(Pid,
+ &pent->UserData,
+ &MemSize,
+ MEM_RELEASE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("DC_FreeDC failed to free DC_ATTR 0x%p\n", pent->UserData);
+ ASSERT(FALSE);
+ }
+ pent->UserData = NULL;
}
- }
}
_SEH2_TRY
{
- ProbeForWrite( pdcattr,
- sizeof(DC_ATTR),
- 1);
- RtlCopyMemory( pdcattr,
- &dc->dcattr,
- sizeof(DC_ATTR));
+ ProbeForWrite(pdcattr, sizeof(DC_ATTR), 1);
+ RtlCopyMemory(pdcattr, &dc->dcattr, sizeof(DC_ATTR));
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
#define NDEBUG
#include <debug.h>
- /** Internal functions ********************************************************/
+ //FIXME: windows uses 0x0012009f
+ #define DIRTY_DEFAULT DIRTY_CHARSET|DIRTY_BACKGROUND|DIRTY_TEXT|DIRTY_LINE|DIRTY_FILL
- HDC FASTCALL
- DC_AllocDC(PUNICODE_STRING Driver)
- {
- PDC NewDC;
- PDC_ATTR pdcattr;
- HDC hDC;
- PWSTR Buf = NULL;
- XFORM xformTemplate;
- PBRUSH pbrush;
- HSURF hsurf;
-
- if (Driver != NULL)
- {
- Buf = ExAllocatePoolWithTag(PagedPool, Driver->MaximumLength, TAG_DC);
- if (!Buf)
- {
- DPRINT1("ExAllocatePoolWithTag failed\n");
- return NULL;
- }
- RtlCopyMemory(Buf, Driver->Buffer, Driver->MaximumLength);
- }
+ PSURFACE psurfDefaultBitmap = NULL;
+ PBRUSH pbrDefaultBrush = NULL;
- NewDC = (PDC)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_DC);
- if (!NewDC)
- {
- if (Buf)
- {
- ExFreePoolWithTag(Buf, TAG_DC);
- }
- DPRINT1("GDIOBJ_AllocObjWithHandle failed\n");
- return NULL;
- }
+ // FIXME: these should go to floatobj.h or something
+ #define FLOATOBJ_0 {0x00000000, 0x00000000}
+ #define FLOATOBJ_1 {0x40000000, 0x00000002}
+ #define FLOATOBJ_16 {0x40000000, 0x00000006}
+ #define FLOATOBJ_1_16 {0x40000000, 0xfffffffe}
- hDC = NewDC->BaseObject.hHmgr;
+ static const FLOATOBJ gef0 = FLOATOBJ_0;
+ static const FLOATOBJ gef1 = FLOATOBJ_1;
+ static const FLOATOBJ gef16 = FLOATOBJ_16;
- NewDC->pdcattr = &NewDC->dcattr;
- DC_AllocateDcAttr(hDC);
+ static const MATRIX gmxWorldToDeviceDefault =
+ {
+ FLOATOBJ_16, FLOATOBJ_0,
+ FLOATOBJ_0, FLOATOBJ_16,
+ FLOATOBJ_0, FLOATOBJ_0,
+ 0, 0, 0x4b
+ };
- if (Driver != NULL)
- {
- RtlCopyMemory(&NewDC->rosdc.DriverName, Driver, sizeof(UNICODE_STRING));
- NewDC->rosdc.DriverName.Buffer = Buf;
- }
- pdcattr = NewDC->pdcattr;
+ static const MATRIX gmxDeviceToWorldDefault =
+ {
+ FLOATOBJ_1_16, FLOATOBJ_0,
+ FLOATOBJ_0, FLOATOBJ_1_16,
+ FLOATOBJ_0, FLOATOBJ_0,
+ 0, 0, 0x53
+ };
- // FIXME: no floating point in the kernel!
- xformTemplate.eM11 = 1.0f;
- xformTemplate.eM12 = 0.0f;
- xformTemplate.eM21 = 0.0f;
- xformTemplate.eM22 = 1.0f;
- xformTemplate.eDx = 0.0f;
- xformTemplate.eDy = 0.0f;
- XForm2MatrixS(&NewDC->dclevel.mxWorldToDevice, &xformTemplate);
- XForm2MatrixS(&NewDC->dclevel.mxDeviceToWorld, &xformTemplate);
- XForm2MatrixS(&NewDC->dclevel.mxWorldToPage, &xformTemplate);
+ static const MATRIX gmxWorldToPageDefault =
+ {
+ FLOATOBJ_1, FLOATOBJ_0,
+ FLOATOBJ_0, FLOATOBJ_1,
+ FLOATOBJ_0, FLOATOBJ_0,
+ 0, 0, 0x63
+ };
- // Setup syncing bits for the dcattr data packets.
- pdcattr->flXform = DEVICE_TO_PAGE_INVALID;
+ // HACK!! Fix XFORMOBJ then use 1:16 / 16:1
+ #define gmxWorldToDeviceDefault gmxWorldToPageDefault
+ #define gmxDeviceToWorldDefault gmxWorldToPageDefault
- pdcattr->ulDirty_ = 0; // Server side
+ /** Internal functions ********************************************************/
- pdcattr->iMapMode = MM_TEXT;
- pdcattr->iGraphicsMode = GM_COMPATIBLE;
- pdcattr->jFillMode = ALTERNATE;
+ NTSTATUS
+ InitDcImpl()
+ {
+ psurfDefaultBitmap = SURFACE_ShareLockSurface(StockObjects[DEFAULT_BITMAP]);
+ if (!psurfDefaultBitmap)
+ return STATUS_UNSUCCESSFUL;
- pdcattr->szlWindowExt.cx = 1; // Float to Int,,, WRONG!
- pdcattr->szlWindowExt.cy = 1;
- pdcattr->szlViewportExt.cx = 1;
- pdcattr->szlViewportExt.cy = 1;
+ pbrDefaultBrush = BRUSH_ShareLockBrush(StockObjects[BLACK_BRUSH]);
+ if (!pbrDefaultBrush)
+ return STATUS_UNSUCCESSFUL;
- pdcattr->crForegroundClr = 0;
- pdcattr->ulForegroundClr = 0;
+ return STATUS_SUCCESS;
+ }
- pdcattr->ulBackgroundClr = 0xffffff;
- pdcattr->crBackgroundClr = 0xffffff;
- pdcattr->ulPenClr = RGB(0, 0, 0);
- pdcattr->crPenClr = RGB(0, 0, 0);
+ PDC
+ NTAPI
+ DC_AllocDcWithHandle()
+ {
+ PDC pdc;
+ pdc = (PDC)GDIOBJ_AllocObjWithHandle(GDILoObjType_LO_DC_TYPE);
- pdcattr->ulBrushClr = RGB(255, 255, 255); // Do this way too.
- pdcattr->crBrushClr = RGB(255, 255, 255);
+ pdc->pdcattr = &pdc->dcattr;
- //// This fixes the default brush and pen settings. See DC_InitDC.
+ return pdc;
+ }
- /* Create the default fill brush */
- pdcattr->hbrush = NtGdiGetStockObject(WHITE_BRUSH);
- NewDC->dclevel.pbrFill = BRUSH_ShareLockBrush(pdcattr->hbrush);
- EBRUSHOBJ_vInit(&NewDC->eboFill, NewDC->dclevel.pbrFill, NewDC);
- /* Create the default pen / line brush */
- pdcattr->hpen = NtGdiGetStockObject(BLACK_PEN);
- NewDC->dclevel.pbrLine = PEN_ShareLockPen(pdcattr->hpen);
- EBRUSHOBJ_vInit(&NewDC->eboLine, NewDC->dclevel.pbrLine, NewDC);
+ void
+ DC_InitHack(PDC pdc)
+ {
+ TextIntRealizeFont(pdc->pdcattr->hlfntNew,NULL);
+ pdc->pdcattr->iCS_CP = ftGdiGetTextCharsetInfo(pdc,NULL,0);
- /* Create the default text brush */
- pbrush = BRUSH_ShareLockBrush(NtGdiGetStockObject(BLACK_BRUSH));
- EBRUSHOBJ_vInit(&NewDC->eboText, pbrush, NewDC);
- pdcattr->ulDirty_ |= DIRTY_TEXT;
+ /* This should never fail */
+ ASSERT(pdc->dclevel.ppal);
- /* Create the default background brush */
- pbrush = BRUSH_ShareLockBrush(NtGdiGetStockObject(WHITE_BRUSH));
- EBRUSHOBJ_vInit(&NewDC->eboBackground, pbrush, NewDC);
+ /* Select regions */
+ pdc->rosdc.hClipRgn = NULL;
+ pdc->rosdc.hGCClipRgn = NULL;
+ }
- pdcattr->hlfntNew = NtGdiGetStockObject(SYSTEM_FONT);
- TextIntRealizeFont(pdcattr->hlfntNew,NULL);
- NewDC->hlfntCur = pdcattr->hlfntNew;
- NewDC->dclevel.plfnt = GDIOBJ_GetKernelObj(pdcattr->hlfntNew);
+ VOID
+ NTAPI
+ DC_vInitDc(
+ PDC pdc,
+ DCTYPE dctype,
+ PPDEVOBJ ppdev)
+ {
+ /* Setup some basic fields */
+ pdc->dctype = dctype;
+ pdc->ppdev = ppdev;
+ pdc->dhpdev = ppdev->dhpdev;
+ pdc->hsem = ppdev->hsemDevLock;
+ pdc->flGraphicsCaps = ppdev->devinfo.flGraphicsCaps;
+ pdc->flGraphicsCaps2 = ppdev->devinfo.flGraphicsCaps2;
+ pdc->fs = DC_DIRTY_RAO;
+
+ /* Setup dc attribute */
+ pdc->pdcattr = &pdc->dcattr;
+ pdc->dcattr.pvLDC = NULL;
+ pdc->dcattr.ulDirty_ = DIRTY_DEFAULT;
+ if (ppdev == gppdevPrimary)
+ pdc->dcattr.ulDirty_ |= DC_PRIMARY_DISPLAY;
+
+ /* Setup the DC size */
+ if (dctype == DCTYPE_MEMORY)
+ {
+ /* Memory DCs have a 1 x 1 bitmap by default */
+ pdc->dclevel.sizl.cx = 1;
+ pdc->dclevel.sizl.cy = 1;
+ }
+ else
+ {
+ /* Other DC's are as big as the related PDEV */
+ pdc->dclevel.sizl.cx = ppdev->gdiinfo.ulHorzRes;
+ pdc->dclevel.sizl.cy = ppdev->gdiinfo.ulVertRes;
+ }
- NewDC->dclevel.hpal = NtGdiGetStockObject(DEFAULT_PALETTE);
- NewDC->dclevel.ppal = PALETTE_ShareLockPalette(NewDC->dclevel.hpal);
- /* This should never fail */
- ASSERT(NewDC->dclevel.ppal);
+ /* Setup Window rect based on DC size */
+ pdc->erclWindow.left = 0;
+ pdc->erclWindow.top = 0;
+ pdc->erclWindow.right = pdc->dclevel.sizl.cx;
+ pdc->erclWindow.bottom = pdc->dclevel.sizl.cy;
- NewDC->dclevel.laPath.eMiterLimit = 10.0; // FIXME: use FLOATL or FLOATOBJ!
+ if (dctype == DCTYPE_DIRECT)
+ {
+ /* Direct DCs get the surface from the PDEV */
+ pdc->dclevel.pSurface = PDEVOBJ_pSurface(ppdev);
+
+ pdc->erclBounds.left = 0x7fffffff;
+ pdc->erclBounds.top = 0x7fffffff;
+ pdc->erclBounds.right = 0x80000000;
+ pdc->erclBounds.bottom = 0x80000000;
+ pdc->erclBoundsApp.left = 0xffffffff;
+ pdc->erclBoundsApp.top = 0xfffffffc;
+ pdc->erclBoundsApp.right = 0x00007ffc; // FIXME
+ pdc->erclBoundsApp.bottom = 0x00000333; // FIXME
+ pdc->erclClip = pdc->erclBounds;
+ // pdc->co
+
+ pdc->fs |= DC_SYNCHRONIZEACCESS | DC_ACCUM_APP | DC_PERMANANT | DC_DISPLAY;
+ }
+ else
+ {
+ /* Non-direct DCs don't have a surface by default */
+ pdc->dclevel.pSurface = NULL;
- NewDC->dclevel.lSaveDepth = 1;
+ // FIXME: HACK, because our code expects a surface
+ pdc->dclevel.pSurface = SURFACE_ShareLockSurface(StockObjects[DEFAULT_BITMAP]);
- hsurf = (HBITMAP)PrimarySurface.pSurface; // <- what kind of haxx0ry is that?
- NewDC->dclevel.pSurface = SURFACE_ShareLockSurface(hsurf);
+ pdc->erclBounds.left = 0;
+ pdc->erclBounds.top = 0;
+ pdc->erclBounds.right = 0;
+ pdc->erclBounds.bottom = 0;
+ pdc->erclBoundsApp = pdc->erclBounds;
+ pdc->erclClip = pdc->erclWindow;
+ // pdc->co = NULL
+ }
+ // pdc->dcattr.VisRectRegion:
+
+ /* Setup coordinate transformation data */
+ pdc->dclevel.mxWorldToDevice = gmxWorldToDeviceDefault;
+ pdc->dclevel.mxDeviceToWorld = gmxDeviceToWorldDefault;
+ pdc->dclevel.mxWorldToPage = gmxWorldToPageDefault;
+ pdc->dclevel.efM11PtoD = gef16;
+ pdc->dclevel.efM22PtoD = gef16;
+ pdc->dclevel.efDxPtoD = gef0;
+ pdc->dclevel.efDyPtoD = gef0;
+ pdc->dclevel.efM11_TWIPS = gef0;
+ pdc->dclevel.efM22_TWIPS = gef0;
+ pdc->dclevel.efPr11 = gef0;
+ pdc->dclevel.efPr22 = gef0;
+ pdc->dcattr.mxWorldToDevice = pdc->dclevel.mxWorldToDevice;
+ pdc->dcattr.mxDeviceToWorld = pdc->dclevel.mxDeviceToWorld;
+ pdc->dcattr.mxWorldToPage = pdc->dclevel.mxWorldToPage;
+ pdc->dcattr.efM11PtoD = pdc->dclevel.efM11PtoD;
+ pdc->dcattr.efM22PtoD = pdc->dclevel.efM22PtoD;
+ pdc->dcattr.efDxPtoD = pdc->dclevel.efDxPtoD;
+ pdc->dcattr.efDyPtoD = pdc->dclevel.efDyPtoD;
+ pdc->dcattr.iMapMode = MM_TEXT;
+ pdc->dcattr.dwLayout = 0;
+ pdc->dcattr.flXform = PAGE_TO_DEVICE_SCALE_IDENTITY |
+ PAGE_TO_DEVICE_IDENTITY |
+ WORLD_TO_PAGE_IDENTITY;
+
+ /* Setup more coordinates */
+ pdc->ptlDCOrig.x = 0;
+ pdc->ptlDCOrig.y = 0;
+ pdc->dcattr.lWindowOrgx = 0;
+ pdc->dcattr.ptlWindowOrg.x = 0;
+ pdc->dcattr.ptlWindowOrg.y = 0;
+ pdc->dcattr.szlWindowExt.cx = 1;
+ pdc->dcattr.szlWindowExt.cy = 1;
+ pdc->dcattr.ptlViewportOrg.x = 0;
+ pdc->dcattr.ptlViewportOrg.y = 0;
+ pdc->dcattr.szlViewportExt.cx = 1;
+ pdc->dcattr.szlViewportExt.cy = 1;
+ pdc->dcattr.szlVirtualDevicePixel.cx = ppdev->gdiinfo.ulHorzRes;
+ pdc->dcattr.szlVirtualDevicePixel.cy = ppdev->gdiinfo.ulVertRes;
+ pdc->dcattr.szlVirtualDeviceMm.cx = ppdev->gdiinfo.ulHorzSize;
+ pdc->dcattr.szlVirtualDeviceMm.cy = ppdev->gdiinfo.ulVertSize;
+ pdc->dcattr.szlVirtualDeviceSize.cx = 0;
+ pdc->dcattr.szlVirtualDeviceSize.cy = 0;
+
+ /* Setup regions */
+ pdc->prgnAPI = NULL;
+ pdc->prgnRao = NULL;
/* Allocate a Vis region */
- NewDC->prgnVis = IntSysCreateRectpRgn(0, 0, 1, 1);
- if (!NewDC->prgnVis)
- {
- DPRINT1("IntSysCreateRectpRgn failed\n");
- if (!GDIOBJ_FreeObjByHandle(hDC, GDI_OBJECT_TYPE_DC))
- {
- ASSERT(FALSE);
- }
- return NULL;
- }
+ pdc->prgnVis = IntSysCreateRectpRgn(0, 0, pdc->dclevel.sizl.cx, pdc->dclevel.sizl.cy);
+ ASSERT(pdc->prgnVis);
+ GDIOBJ_CopyOwnership(pdc->BaseObject.hHmgr, pdc->prgnVis->BaseObject.hHmgr);
+
+ /* Setup palette */
+ pdc->dclevel.hpal = StockObjects[DEFAULT_PALETTE];
+ pdc->dclevel.ppal = PALETTE_ShareLockPalette(pdc->dclevel.hpal);
+
+ /* Setup path */
+ pdc->dclevel.hPath = NULL;
+ pdc->dclevel.flPath = 0;
+ // pdc->dclevel.lapath:
+
+ /* Setup colors */
+ pdc->dcattr.crBackgroundClr = RGB(0xff, 0xff, 0xff);
+ pdc->dcattr.ulBackgroundClr = RGB(0xff, 0xff, 0xff);
+ pdc->dcattr.crForegroundClr = RGB(0, 0, 0);
+ pdc->dcattr.ulForegroundClr = RGB(0, 0, 0);
+ pdc->dcattr.crBrushClr = RGB(0xff, 0xff, 0xff);
+ pdc->dcattr.ulBrushClr = RGB(0xff, 0xff, 0xff);
+ pdc->dcattr.crPenClr = RGB(0, 0, 0);
+ pdc->dcattr.ulPenClr = RGB(0, 0, 0);
+
+ /* Select the default fill and line brush */
+ pdc->dcattr.hbrush = StockObjects[WHITE_BRUSH];
+ pdc->dcattr.hpen = StockObjects[BLACK_PEN];
+ pdc->dclevel.pbrFill = BRUSH_ShareLockBrush(pdc->pdcattr->hbrush);
+ pdc->dclevel.pbrLine = PEN_ShareLockPen(pdc->pdcattr->hpen);
+ pdc->dclevel.ptlBrushOrigin.x = 0;
+ pdc->dclevel.ptlBrushOrigin.y = 0;
+ pdc->dcattr.ptlBrushOrigin = pdc->dclevel.ptlBrushOrigin;
+
+ /* Initialize EBRUSHOBJs */
+ EBRUSHOBJ_vInit(&pdc->eboFill, pdc->dclevel.pbrFill, pdc);
+ EBRUSHOBJ_vInit(&pdc->eboLine, pdc->dclevel.pbrLine, pdc);
+ EBRUSHOBJ_vInit(&pdc->eboText, pbrDefaultBrush, pdc);
+ EBRUSHOBJ_vInit(&pdc->eboBackground, pbrDefaultBrush, pdc);
+
+ /* Setup fill data */
+ pdc->dcattr.jROP2 = R2_COPYPEN;
+ pdc->dcattr.jBkMode = 2;
+ pdc->dcattr.lBkMode = 2;
+ pdc->dcattr.jFillMode = ALTERNATE;
+ pdc->dcattr.lFillMode = 1;
+ pdc->dcattr.jStretchBltMode = 1;
+ pdc->dcattr.lStretchBltMode = 1;
+ pdc->ptlFillOrigin.x = 0;
+ pdc->ptlFillOrigin.y = 0;
+
+ /* Setup drawing position */
+ pdc->dcattr.ptlCurrent.x = 0;
+ pdc->dcattr.ptlCurrent.y = 0;
+ pdc->dcattr.ptfxCurrent.x = 0;
+ pdc->dcattr.ptfxCurrent.y = 0;
+
+ /* Setup ICM data */
+ pdc->dclevel.lIcmMode = 0;
+ pdc->dcattr.lIcmMode = 0;
+ pdc->dcattr.hcmXform = NULL;
+ pdc->dcattr.flIcmFlags = 0;
+ pdc->dcattr.IcmBrushColor = CLR_INVALID;
+ pdc->dcattr.IcmPenColor = CLR_INVALID;
+ pdc->dcattr.pvLIcm = NULL;
+ pdc->dcattr.hColorSpace = NULL; // FIXME: 0189001f
+ pdc->dclevel.pColorSpace = NULL; // FIXME
+ pdc->pClrxFormLnk = NULL;
+ // pdc->dclevel.ca =
+
+ /* Setup font data */
+ pdc->hlfntCur = NULL; // FIXME: 2f0a0cf8
+ pdc->pPFFList = NULL;
+ pdc->flSimulationFlags = 0;
+ pdc->lEscapement = 0;
+ pdc->prfnt = NULL;
+ pdc->dcattr.flFontMapper = 0;
+ pdc->dcattr.flTextAlign = 0;
+ pdc->dcattr.lTextAlign = 0;
+ pdc->dcattr.lTextExtra = 0;
+ pdc->dcattr.lRelAbs = 1;
+ pdc->dcattr.lBreakExtra = 0;
+ pdc->dcattr.cBreak = 0;
+ pdc->dcattr.hlfntNew = StockObjects[SYSTEM_FONT];
+ // pdc->dclevel.pFont = LFONT_ShareLockFont(pdc->dcattr.hlfntNew);
+
+ /* Other stuff */
+ pdc->hdcNext = NULL;
+ pdc->hdcPrev = NULL;
+ pdc->ipfdDevMax = 0x0000ffff;
+ pdc->ulCopyCount = -1;
+ pdc->ptlDoBanding.x = 0;
+ pdc->ptlDoBanding.y = 0;
+ pdc->dclevel.lSaveDepth = 1;
+ pdc->dclevel.hdcSave = NULL;
+ pdc->dcattr.iGraphicsMode = GM_COMPATIBLE;
+ pdc->dcattr.iCS_CP = 0;
+ pdc->pSurfInfo = NULL;
- return NewDC;
}
- BOOL INTERNAL_CALL
+ BOOL
+ INTERNAL_CALL
DC_Cleanup(PVOID ObjectBody)
{
- PDC pDC = (PDC)ObjectBody;
+ PDC pdc = (PDC)ObjectBody;
- /* Free driver name (HACK) */
- if (pDC->rosdc.DriverName.Buffer)
- ExFreePoolWithTag(pDC->rosdc.DriverName.Buffer, TAG_DC);
+ /* Free DC_ATTR */
+ DC_vFreeDcAttr(pdc);
- /* Deselect dc objects */
- DC_vSelectSurface(pDC, NULL);
- DC_vSelectFillBrush(pDC, NULL);
- DC_vSelectLineBrush(pDC, NULL);
- DC_vSelectPalette(pDC, NULL);
+ /* Delete saved DCs */
+ DC_vRestoreDC(pdc, 1);
- /* Dereference default brushes */
- if (pDC->eboText.pbrush)
- BRUSH_ShareUnlockBrush(pDC->eboText.pbrush);
- if (pDC->eboBackground.pbrush)
- BRUSH_ShareUnlockBrush(pDC->eboBackground.pbrush);
+ /* Deselect dc objects */
+ DC_vSelectSurface(pdc, NULL);
+ DC_vSelectFillBrush(pdc, NULL);
+ DC_vSelectLineBrush(pdc, NULL);
+ DC_vSelectPalette(pdc, NULL);
/* Cleanup the dc brushes */
- EBRUSHOBJ_vCleanup(&pDC->eboFill);
- EBRUSHOBJ_vCleanup(&pDC->eboLine);
- EBRUSHOBJ_vCleanup(&pDC->eboText);
- EBRUSHOBJ_vCleanup(&pDC->eboBackground);
+ EBRUSHOBJ_vCleanup(&pdc->eboFill);
+ EBRUSHOBJ_vCleanup(&pdc->eboLine);
+ EBRUSHOBJ_vCleanup(&pdc->eboText);
+ EBRUSHOBJ_vCleanup(&pdc->eboBackground);
+
+ /* Free regions */
+ if (pdc->rosdc.hClipRgn)
+ GreDeleteObject(pdc->rosdc.hClipRgn);
+ if (pdc->prgnVis)
+ REGION_FreeRgnByHandle(pdc->prgnVis->BaseObject.hHmgr);
+ if (pdc->rosdc.hGCClipRgn)
+ GreDeleteObject(pdc->rosdc.hGCClipRgn);
+ if (NULL != pdc->rosdc.CombinedClip)
+ IntEngDeleteClipRegion(pdc->rosdc.CombinedClip);
+
+ PATH_Delete(pdc->dclevel.hPath);
+
+ if(pdc->dclevel.pSurface)
+ SURFACE_ShareUnlockSurface(pdc->dclevel.pSurface);
+
+ PDEVOBJ_vRelease(pdc->ppdev) ;
return TRUE;
}
INT Index;
PGDI_TABLE_ENTRY Entry;
PDC pDC;
+ BOOL ret = FALSE;
+
+ if (!GDIOBJ_SetOwnership(hDC, Owner))
+ {
+ DPRINT1("GDIOBJ_SetOwnership failed\n");
+ return FALSE;
+ }
- if (!GDIOBJ_SetOwnership(hDC, Owner)) return FALSE;
pDC = DC_LockDc(hDC);
- if (pDC)
+ if (!pDC)
{
+ DPRINT1("Could not lock DC\n");
+ return FALSE;
+ }
+
/*
System Regions:
These regions do not use attribute sections and when allocated, use
gdiobj level functions.
*/
- if (pDC->rosdc.hClipRgn)
- { // FIXME! HAX!!!
- Index = GDI_HANDLE_GET_INDEX(pDC->rosdc.hClipRgn);
- Entry = &GdiHandleTable->Entries[Index];
- if (Entry->UserData) FreeObjectAttr(Entry->UserData);
- Entry->UserData = NULL;
- //
- if (!GDIOBJ_SetOwnership(pDC->rosdc.hClipRgn, Owner)) return FALSE;
- }
- if (pDC->prgnVis)
- { // FIXME! HAX!!!
- Index = GDI_HANDLE_GET_INDEX(pDC->prgnVis->BaseObject.hHmgr);
- Entry = &GdiHandleTable->Entries[Index];
- if (Entry->UserData) FreeObjectAttr(Entry->UserData);
- Entry->UserData = NULL;
- //
- if (!GDIOBJ_SetOwnership(pDC->prgnVis->BaseObject.hHmgr, Owner)) return FALSE;
- }
- if (pDC->rosdc.hGCClipRgn)
- { // FIXME! HAX!!!
- Index = GDI_HANDLE_GET_INDEX(pDC->rosdc.hGCClipRgn);
- Entry = &GdiHandleTable->Entries[Index];
- if (Entry->UserData) FreeObjectAttr(Entry->UserData);
- Entry->UserData = NULL;
- //
- if (!GDIOBJ_SetOwnership(pDC->rosdc.hGCClipRgn, Owner)) return FALSE;
- }
- if (pDC->dclevel.hPath)
- {
- if (!GDIOBJ_SetOwnership(pDC->dclevel.hPath, Owner)) return FALSE;
- }
- DC_UnlockDc(pDC);
+ if (pDC->rosdc.hClipRgn)
+ { // FIXME! HAX!!!
+ Index = GDI_HANDLE_GET_INDEX(pDC->rosdc.hClipRgn);
+ Entry = &GdiHandleTable->Entries[Index];
+ if (Entry->UserData) FreeObjectAttr(Entry->UserData);
+ Entry->UserData = NULL;
+ //
+ if (!GDIOBJ_SetOwnership(pDC->rosdc.hClipRgn, Owner)) goto leave;
+ }
+ if (pDC->prgnVis)
+ { // FIXME! HAX!!!
+ Index = GDI_HANDLE_GET_INDEX(pDC->prgnVis->BaseObject.hHmgr);
+ Entry = &GdiHandleTable->Entries[Index];
+ if (Entry->UserData) FreeObjectAttr(Entry->UserData);
+ Entry->UserData = NULL;
+ //
+ if (!GDIOBJ_SetOwnership(pDC->prgnVis->BaseObject.hHmgr, Owner)) goto leave;
+ }
+ if (pDC->rosdc.hGCClipRgn)
+ { // FIXME! HAX!!!
+ Index = GDI_HANDLE_GET_INDEX(pDC->rosdc.hGCClipRgn);
+ Entry = &GdiHandleTable->Entries[Index];
+ if (Entry->UserData) FreeObjectAttr(Entry->UserData);
+ Entry->UserData = NULL;
+ //
+ if (!GDIOBJ_SetOwnership(pDC->rosdc.hGCClipRgn, Owner)) goto leave;
+ }
+ if (pDC->dclevel.hPath)
+ {
+ if (!GDIOBJ_SetOwnership(pDC->dclevel.hPath, Owner)) goto leave;
}
+ ret = TRUE;
- return TRUE;
+ leave:
+ DC_UnlockDc(pDC);
+
+ return ret;
}
- HDC FASTCALL
- IntGdiCreateDC(
- PUNICODE_STRING Driver,
- PUNICODE_STRING Device,
- PVOID pUMdhpdev,
- CONST PDEVMODEW InitData,
- BOOL CreateAsIC)
+ int FASTCALL
+ CLIPPING_UpdateGCRegion(DC* Dc);
+
+ static
+ void
+ DC_vUpdateDC(PDC pdc)
{
- HDC hdc;
- PDC pdc;
- PDC_ATTR pdcattr;
- HRGN hVisRgn;
- UNICODE_STRING StdDriver;
- BOOL calledFromUser;
+ HRGN hVisRgn ;
+ PPDEVOBJ ppdev = pdc->ppdev ;
+
+ pdc->dhpdev = ppdev->dhpdev;
- RtlInitUnicodeString(&StdDriver, L"DISPLAY");
+ SURFACE_ShareUnlockSurface(pdc->dclevel.pSurface);
+ pdc->dclevel.pSurface = PDEVOBJ_pSurface(ppdev);
- DPRINT("DriverName: %wZ, DeviceName: %wZ\n", Driver, Device);
+ PDEVOBJ_sizl(pdc->ppdev, &pdc->dclevel.sizl);
+ hVisRgn = NtGdiCreateRectRgn(0, 0, pdc->dclevel.sizl.cx, pdc->dclevel.sizl.cy);
+ ASSERT(hVisRgn);
+ GdiSelectVisRgn(pdc->BaseObject.hHmgr, hVisRgn);
+ GreDeleteObject(hVisRgn);
- if (NULL == Driver || 0 == RtlCompareUnicodeString(Driver, &StdDriver, TRUE))
+ pdc->flGraphicsCaps = ppdev->devinfo.flGraphicsCaps;
+ pdc->flGraphicsCaps2 = ppdev->devinfo.flGraphicsCaps2;
+
+ /* Mark EBRUSHOBJs as dirty */
+ pdc->pdcattr->ulDirty_ |= DIRTY_DEFAULT ;
+ }
+
+ /* Prepare a blit for up to 2 DCs */
+ /* rc1 and rc2 are the rectangles where we want to draw or
+ * from where we take pixels. */
+ VOID
+ FASTCALL
+ DC_vPrepareDCsForBlit(PDC pdc1,
+ RECT rc1,
+ PDC pdc2,
+ RECT rc2)
+ {
+ PDC pdcFirst, pdcSecond;
+ PRECT prcFirst, prcSecond;
+ /* Lock them in good order */
+ if(pdc2)
{
- if (CreateAsIC)
+ if((ULONG_PTR)pdc1->ppdev->hsemDevLock >= (ULONG_PTR)pdc2->ppdev->hsemDevLock)
{
- if (! IntPrepareDriverIfNeeded())
- {
- /* Here, we have two possibilities:
- * a) return NULL, and hope that the caller
- * won't call us in a loop
- * b) bugcheck, but caller is unable to
- * react on the problem
- */
- /*DPRINT1("Unable to prepare graphics driver, returning NULL ic\n");
- return NULL;*/
- KeBugCheck(VIDEO_DRIVER_INIT_FAILURE);
- }
+ pdcFirst = pdc1;
+ prcFirst = &rc1;
+ pdcSecond = pdc2;
+ prcSecond = &rc2;
}
else
{
- calledFromUser = UserIsEntered();
- if (!calledFromUser)
- {
- UserEnterExclusive();
- }
-
- if (! co_IntGraphicsCheck(TRUE))
- {
- if (!calledFromUser)
- {
- UserLeave();
- }
- DPRINT1("Unable to initialize graphics, returning NULL dc\n");
- return NULL;
- }
-
- if (!calledFromUser)
- {
- UserLeave();
- }
-
+ pdcFirst = pdc2;
+ prcFirst = &rc2;
+ pdcSecond = pdc1;
+ prcSecond = &rc1;
}
}
-
- /* Check for existing DC object */
- if ((hdc = DC_FindOpenDC(Driver)) != NULL)
+ else
{
- hdc = NtGdiCreateCompatibleDC(hdc);
- if (!hdc)
- DPRINT1("NtGdiCreateCompatibleDC() failed\n");
- return hdc;
+ pdcFirst = pdc1 ;
+ prcFirst = &rc1;
+ pdcSecond = NULL ;
}
- /* Allocate a DC object */
- pdc = DC_AllocDC(Driver);
- if (pdc == NULL)
+ if(pdcFirst && pdcFirst->dctype == DCTYPE_DIRECT)
{
- DPRINT1("DC_AllocDC() failed\n");
- return NULL;
+ EngAcquireSemaphore(pdcFirst->ppdev->hsemDevLock);
+ MouseSafetyOnDrawStart(pdcFirst->ppdev,
+ prcFirst->left,
+ prcFirst->top,
+ prcFirst->right,
+ prcFirst->bottom) ;
+ /* Update surface if needed */
+ if(pdcFirst->ppdev->pSurface != pdcFirst->dclevel.pSurface)
+ {
+ DC_vUpdateDC(pdcFirst);
+ }
}
- hdc = pdc->BaseObject.hHmgr;
- pdcattr = pdc->pdcattr;
-
- pdc->dctype = DC_TYPE_DIRECT;
-
- pdc->dhpdev = PrimarySurface.dhpdev;
- if (pUMdhpdev) pUMdhpdev = pdc->dhpdev; // set DHPDEV for device.
- pdc->ppdev = (PVOID)&PrimarySurface;
-
- // ATM we only have one display.
- pdcattr->ulDirty_ |= DC_PRIMARY_DISPLAY;
-
- pdc->flGraphicsCaps = PrimarySurface.devinfo.flGraphicsCaps;
- pdc->flGraphicsCaps2 = PrimarySurface.devinfo.flGraphicsCaps2;
-
- pdc->dclevel.hpal = NtGdiGetStockObject(DEFAULT_PALETTE);
-
- pdcattr->jROP2 = R2_COPYPEN;
+ if(pdcSecond && pdcSecond->dctype == DCTYPE_DIRECT)
+ {
+ EngAcquireSemaphore(pdcSecond->ppdev->hsemDevLock);
+ MouseSafetyOnDrawStart(pdcSecond->ppdev,
+ prcSecond->left,
+ prcSecond->top,
+ prcSecond->right,
+ prcSecond->bottom) ;
+ /* Update surface if needed */
+ if(pdcSecond->ppdev->pSurface != pdcSecond->dclevel.pSurface)
+ {
+ DC_vUpdateDC(pdcSecond);
+ }
+ }
+ }
- pdc->erclWindow.top = pdc->erclWindow.left = 0;
- pdc->erclWindow.right = pdc->ppdev->gdiinfo.ulHorzRes;
- pdc->erclWindow.bottom = pdc->ppdev->gdiinfo.ulVertRes;
- pdc->dclevel.flPath &= ~DCPATH_CLOCKWISE; // Default is CCW.
+ /* Finishes a blit for one or two DCs */
+ VOID
+ FASTCALL
+ DC_vFinishBlit(PDC pdc1, PDC pdc2)
+ {
+ if(pdc1->dctype == DCTYPE_DIRECT)
+ {
+ MouseSafetyOnDrawEnd(pdc1->ppdev);
+ EngReleaseSemaphore(pdc1->ppdev->hsemDevLock);
+ }
- pdcattr->iCS_CP = ftGdiGetTextCharsetInfo(pdc,NULL,0);
+ if(pdc2)
+ {
+ if(pdc2->dctype == DCTYPE_DIRECT)
+ {
+ MouseSafetyOnDrawEnd(pdc2->ppdev);
+ EngReleaseSemaphore(pdc2->ppdev->hsemDevLock);
+ }
+ }
+ }
- hVisRgn = IntSysCreateRectRgn(0, 0, pdc->ppdev->gdiinfo.ulHorzRes,
- pdc->ppdev->gdiinfo.ulVertRes);
+ HDC
+ NTAPI
+ GreOpenDCW(
+ PUNICODE_STRING pustrDevice,
+ DEVMODEW *pdmInit,
+ PUNICODE_STRING pustrLogAddr,
+ ULONG iType,
+ BOOL bDisplay,
+ HANDLE hspool,
+ VOID *pDriverInfo2,
+ VOID *pUMdhpdev)
+ {
+ PPDEVOBJ ppdev;
+ PDC pdc;
+ HDC hdc;
- if (!CreateAsIC)
- {
- pdc->pSurfInfo = NULL;
- // pdc->dclevel.pSurface =
- DC_UnlockDc(pdc);
+ DPRINT("GreOpenDCW(%S, iType=%ld)\n",
+ pustrDevice ? pustrDevice->Buffer : NULL, iType);
- /* Initialize the DC state */
- IntGdiSetTextColor(hdc, RGB(0, 0, 0));
- IntGdiSetBkColor(hdc, RGB(255, 255, 255));
- }
- else
+ /* Get a PDEVOBJ for the device */
+ ppdev = EngpGetPDEV(pustrDevice);
+ if (!ppdev)
{
- /* From MSDN2:
- The CreateIC function creates an information context for the specified device.
- The information context provides a fast way to get information about the
- device without creating a device context (DC). However, GDI drawing functions
- cannot accept a handle to an information context.
- */
- pdc->dctype = DC_TYPE_INFO;
- // pdc->pSurfInfo =
- // DC_vSelectSurface(pdc, NULL);
- pdcattr->crBackgroundClr = pdcattr->ulBackgroundClr = RGB(255, 255, 255);
- pdcattr->crForegroundClr = RGB(0, 0, 0);
- DC_UnlockDc(pdc);
+ DPRINT1("Didn't find a suitable PDEV\n");
+ return NULL;
}
- DC_InitDC(hdc);
- if (hVisRgn)
+ DPRINT("GreOpenDCW - ppdev = %p\n", ppdev);
+
+ pdc = DC_AllocDcWithHandle();
+ if (!pdc)
{
- GdiSelectVisRgn(hdc, hVisRgn);
- REGION_FreeRgnByHandle(hVisRgn);
+ DPRINT1("Could not Allocate a DC\n");
+ PDEVOBJ_vRelease(ppdev);
+ return NULL;
}
+ hdc = pdc->BaseObject.hHmgr;
+
+ /* Lock ppdev and initialize the new DC */
+ DC_vInitDc(pdc, iType, ppdev);
+ /* FIXME: HACK! */
+ DC_InitHack(pdc);
+
+ DC_AllocDcAttr(pdc);
+
+ DC_UnlockDc(pdc);
- IntGdiSetTextAlign(hdc, TA_TOP);
- IntGdiSetBkMode(hdc, OPAQUE);
+ DPRINT("returning hdc = %p\n", hdc);
return hdc;
}
-
- HDC APIENTRY
+ HDC
+ APIENTRY
NtGdiOpenDCW(
- PUNICODE_STRING Device,
- DEVMODEW *InitData,
+ PUNICODE_STRING pustrDevice,
+ DEVMODEW *pdmInit,
PUNICODE_STRING pustrLogAddr,
ULONG iType,
BOOL bDisplay,
VOID *pDriverInfo2,
VOID *pUMdhpdev)
{
- UNICODE_STRING SafeDevice;
- DEVMODEW SafeInitData;
- PVOID Dhpdev;
- HDC Ret;
- NTSTATUS Status = STATUS_SUCCESS;
-
- if (!Device) return UserGetDesktopDC(iType,FALSE,TRUE);
-
- if (InitData)
+ UNICODE_STRING ustrDevice;
+ WCHAR awcDevice[CCHDEVICENAME];
+ DEVMODEW dmInit;
+ PVOID dhpdev;
+ HDC hdc;
+
+ /* Only if a devicename is given, we need any data */
+ if (pustrDevice)
{
+ /* Initialize destination string */
+ RtlInitEmptyUnicodeString(&ustrDevice, awcDevice, sizeof(awcDevice));
+
_SEH2_TRY
{
+ /* Probe the UNICODE_STRING and the buffer */
+ ProbeForRead(pustrDevice, sizeof(UNICODE_STRING), 1);
+ ProbeForRead(pustrDevice->Buffer, pustrDevice->Length, 1);
+
+ /* Copy the string */
+ RtlCopyUnicodeString(&ustrDevice, pustrDevice);
+
+ if (pdmInit)
+ {
+ /* FIXME: could be larger */
+ ProbeForRead(pdmInit, sizeof(DEVMODEW), 1);
+ RtlCopyMemory(&dmInit, pdmInit, sizeof(DEVMODEW));
+ }
+
if (pUMdhpdev)
{
- ProbeForWrite(pUMdhpdev, sizeof(PVOID), 1);
+ ProbeForWrite(pUMdhpdev, sizeof(HANDLE), 1);
}
- ProbeForRead(InitData, sizeof(DEVMODEW), 1);
- RtlCopyMemory(&SafeInitData, InitData, sizeof(DEVMODEW));
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- Status = _SEH2_GetExceptionCode();
+ SetLastNtError(_SEH2_GetExceptionCode());
+ _SEH2_YIELD(return NULL);
}
- _SEH2_END;
+ _SEH2_END
+ }
+ else
+ {
+ pdmInit = NULL;
+ pUMdhpdev = NULL;
+ }
- if (!NT_SUCCESS(Status))
+ /* FIXME: HACK! */
+ if (pustrDevice)
+ {
+ UNICODE_STRING ustrDISPLAY = RTL_CONSTANT_STRING(L"DISPLAY");
+ if (RtlEqualUnicodeString(&ustrDevice, &ustrDISPLAY, TRUE))
{
- SetLastNtError(Status);
- return NULL;
+ pustrDevice = NULL;
}
- /* FIXME - InitData can have some more bytes! */
}
- if (Device)
+ /* Call the internal function */
+ hdc = GreOpenDCW(pustrDevice ? &ustrDevice : NULL,
+ pdmInit ? &dmInit : NULL,
+ NULL, // fixme pwszLogAddress
+ iType,
+ bDisplay,
+ hspool,
+ NULL, //FIXME: pDriverInfo2
+ pUMdhpdev ? &dhpdev : NULL);
+
+ /* If we got a HDC and a UM dhpdev is requested,... */
+ if (hdc && pUMdhpdev)
{
- Status = IntSafeCopyUnicodeString(&SafeDevice, Device);
- if (!NT_SUCCESS(Status))
+ /* Copy dhpdev to caller (FIXME: use dhpdev?? */
+ _SEH2_TRY
{
- SetLastNtError(Status);
- return NULL;
+ /* Pointer was already probed */
+ *(HANDLE*)pUMdhpdev = dhpdev;
}
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Ignore error */
+ }
+ _SEH2_END
}
- Ret = IntGdiCreateDC(Device ? &SafeDevice : NULL,
- NULL,
- pUMdhpdev ? &Dhpdev : NULL,
- InitData ? &SafeInitData : NULL,
- (BOOL) iType); // FALSE 0 DCW, TRUE 1 ICW
-
- // FIXME!!!!
- if (pUMdhpdev) pUMdhpdev = Dhpdev;
-
- return Ret;
+ return hdc;
}
- HDC FASTCALL
- IntGdiCreateDisplayDC(HDEV hDev, ULONG DcType, BOOL EmptyDC)
+
+ HDC
+ APIENTRY
+ NtGdiCreateCompatibleDC(HDC hdc)
{
- HDC hDC;
- UNICODE_STRING DriverName;
- RtlInitUnicodeString(&DriverName, L"DISPLAY");
+ HDC hdcNew;
+ PPDEVOBJ ppdev;
+ PDC pdc, pdcNew;
- if (DcType != DC_TYPE_MEMORY)
- hDC = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, (DcType == DC_TYPE_INFO));
- else
- hDC = NtGdiCreateCompatibleDC(NULL); // OH~ Yuck! I think I taste vomit in my mouth!
- //
- // There is room to grow here~
- //
-
- //
- // If NULL, first time through! Build the default (was window) dc!
- // Setup clean DC state for the system.
- //
- if (hDC && !defaultDCstate) // Ultra HAX! Dedicated to GvG!
- { // This is a cheesy way to do this.
- PDC dc = DC_LockDc(hDC);
- HSURF hsurf;
- defaultDCstate = ExAllocatePoolWithTag(PagedPool, sizeof(DC), TAG_DC);
- if (!defaultDCstate)
+ DPRINT("NtGdiCreateCompatibleDC(0x%p)\n", hdc);
+
+ /* Did the caller provide a DC? */
+ if (hdc)
+ {
+ /* Yes, try to lock it */
+ pdc = DC_LockDc(hdc);
+ if (!pdc)
{
- DC_UnlockDc(dc);
+ DPRINT1("Could not lock source DC %p\n", hdc);
return NULL;
}
- RtlZeroMemory(defaultDCstate, sizeof(DC));
- defaultDCstate->pdcattr = &defaultDCstate->dcattr;
- hsurf = (HSURF)PrimarySurface.pSurface; // HAX²
- defaultDCstate->dclevel.pSurface = SURFACE_ShareLockSurface(hsurf);
- DC_vCopyState(dc, defaultDCstate, TRUE);
- DC_UnlockDc(dc);
+
+ /* Get the pdev from the DC */
+ ppdev = pdc->ppdev;
+ InterlockedIncrement(&ppdev->cPdevRefs);
+
+ /* Unlock the source DC */
+ DC_UnlockDc(pdc);
}
- return hDC;
+ else
+ {
+ /* No DC given, get default device */
+ ppdev = EngpGetPDEV(NULL);
+ }
+
+ if (!ppdev)
+ {
+ DPRINT1("Didn't find a suitable PDEV\n");
+ return NULL;
+ }
+
+ /* Allocate a new DC */
+ pdcNew = DC_AllocDcWithHandle();
+ if (!pdcNew)
+ {
+ DPRINT1("Could not allocate a new DC\n");
+ PDEVOBJ_vRelease(ppdev);
+ return NULL;
+ }
+ hdcNew = pdcNew->BaseObject.hHmgr;
+
+ /* Lock ppdev and initialize the new DC */
+ DC_vInitDc(pdcNew, DCTYPE_MEMORY, ppdev);
+ /* FIXME: HACK! */
+ DC_InitHack(pdcNew);
+
+ /* Allocate a dc attribute */
+ DC_AllocDcAttr(pdcNew);
+
+ // HACK!
+ DC_vSelectSurface(pdcNew, psurfDefaultBitmap);
+
+ DC_UnlockDc(pdcNew);
+
+ DPRINT("Leave NtGdiCreateCompatibleDC hdcNew = %p\n", hdcNew);
+
+ return hdcNew;
}
BOOL
if (!Force)
{
+ /* Windows permits NtGdiDeleteObjectApp to delete a permanent DC
+ * For some reason, it's still a valid handle, pointing to some kernel data.
+ * Not sure if this is a bug, a feature, some cache stuff... Who knows?
+ * See NtGdiDeleteObjectApp test for details */
if (DCToDelete->fs & DC_FLAG_PERMANENT)
{
- DPRINT1("No! You Naughty Application!\n");
DC_UnlockDc(DCToDelete);
- return UserReleaseDC(NULL, hDC, FALSE);
+ if(UserReleaseDC(NULL, hDC, FALSE))
+ {
+ /* ReactOs feature : call UserReleaseDC
+ * I don't think windows does it.
+ * Still, complain, no one should ever call DeleteDC
+ * on a window DC */
+ DPRINT1("No, you naughty application!\n");
+ return TRUE;
+ }
+ else
+ {
+ /* This is not a window owned DC.
+ * Force its deletion */
+ return IntGdiDeleteDC(hDC, TRUE);
+ }
}
}
- /* First delete all saved DCs */
- while (DCToDelete->dclevel.lSaveDepth > 1)
- {
- PDC savedDC;
- HDC savedHDC;
+ DC_UnlockDc(DCToDelete);
- savedHDC = DCToDelete->hdcNext;
- savedDC = DC_LockDc(savedHDC);
- if (savedDC == NULL)
+ if (!IsObjectDead(hDC))
+ {
+ if (!GDIOBJ_FreeObjByHandle(hDC, GDI_OBJECT_TYPE_DC))
{
- break;
+ DPRINT1("DC_FreeDC failed\n");
}
- DCToDelete->hdcNext = savedDC->hdcNext;
- DCToDelete->dclevel.lSaveDepth--;
- DC_UnlockDc(savedDC);
- IntGdiDeleteDC(savedHDC, Force);
- }
-
- /* Free GDI resources allocated to this DC */
- if (!(DCToDelete->dclevel.flPath & DCPATH_SAVESTATE))
- {
- /*
- NtGdiSelectPen (DCHandle, STOCK_BLACK_PEN);
- NtGdiSelectBrush (DCHandle, STOCK_WHITE_BRUSH);
- NtGdiSelectFont (DCHandle, STOCK_SYSTEM_FONT);
- DC_LockDC (DCHandle); NtGdiSelectXxx does not recognize stock objects yet */
- }
- if (DCToDelete->rosdc.hClipRgn)
- {
- GreDeleteObject(DCToDelete->rosdc.hClipRgn);
- }
- if (DCToDelete->prgnVis)
- {
- GreDeleteObject(DCToDelete->prgnVis->BaseObject.hHmgr);
- }
- if (NULL != DCToDelete->rosdc.CombinedClip)
- {
- IntEngDeleteClipRegion(DCToDelete->rosdc.CombinedClip);
- }
- if (DCToDelete->rosdc.hGCClipRgn)
- {
- GreDeleteObject(DCToDelete->rosdc.hGCClipRgn);
- }
- if (DCToDelete->dclevel.prgnMeta)
- {
- GreDeleteObject(((PROSRGNDATA)DCToDelete->dclevel.prgnMeta)->BaseObject.hHmgr);
}
- if (DCToDelete->prgnAPI)
+ else
{
- GreDeleteObject(((PROSRGNDATA)DCToDelete->prgnAPI)->BaseObject.hHmgr);
+ DPRINT1("Attempted to Delete 0x%x currently being destroyed!!!\n", hDC);
}
- PATH_Delete(DCToDelete->dclevel.hPath);
-
- DC_UnlockDc(DCToDelete);
- GreDeleteObject(hDC);
+
return TRUE;
}
- HDC FASTCALL
- DC_FindOpenDC(PUNICODE_STRING Driver)
+ BOOL
+ APIENTRY
+ NtGdiDeleteObjectApp(HANDLE DCHandle)
{
- return NULL;
- }
+ /* Complete all pending operations */
+ NtGdiFlushUserBatch();
- /*!
- * Initialize some common fields in the Device Context structure.
- */
- VOID FASTCALL
- DC_InitDC(HDC DCHandle)
- {
- // NtGdiRealizeDefaultPalette(DCHandle);
+ if (GDI_HANDLE_IS_STOCKOBJ(DCHandle)) return TRUE;
- //// Removed for now.. See above brush and pen.
- // NtGdiSelectBrush(DCHandle, NtGdiGetStockObject( WHITE_BRUSH ));
- // NtGdiSelectPen(DCHandle, NtGdiGetStockObject( BLACK_PEN ));
- ////
- //NtGdiSelectFont(DCHandle, hFont);
+ if (GDI_HANDLE_GET_TYPE(DCHandle) != GDI_OBJECT_TYPE_DC)
+ return GreDeleteObject((HGDIOBJ) DCHandle);
- /*
- {
- int res;
- res = CLIPPING_UpdateGCRegion(DCToInit);
- ASSERT ( res != ERROR );
- }
- */
+ if (IsObjectDead((HGDIOBJ)DCHandle)) return TRUE;
+
+ if (!GDIOBJ_OwnedByCurrentProcess(DCHandle))
+ {
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
- /* Set virtual resolution */
- NtGdiSetVirtualResolution(DCHandle, 0, 0, 0, 0);
+ return IntGdiDeleteDC(DCHandle, FALSE);
}
BOOL
pdc->dctype = DC_TYPE_INFO;
pdc->dclevel.pSurface = NULL;
- PDEV_sizl(pdc->ppdev, &sizl);
+ PDEVOBJ_sizl(pdc->ppdev, &sizl);
if ( sizl.cx == pdc->dclevel.sizl.cx &&
sizl.cy == pdc->dclevel.sizl.cy )
return FALSE;
}
- HDC APIENTRY
- NtGdiCreateCompatibleDC(HDC hDC)
- {
- PDC pdcNew, pdcOld;
- PDC_ATTR pdcattrNew, pdcattrOld;
- HDC hdcNew, DisplayDC = NULL;
- UNICODE_STRING DriverName;
- DWORD Layout = 0;
- HSURF hsurf;
-
- if (hDC == NULL)
- {
- RtlInitUnicodeString(&DriverName, L"DISPLAY");
- DisplayDC = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, TRUE);
- if (NULL == DisplayDC)
- {
- DPRINT1("Failed to create DisplayDC\n");
- return NULL;
- }
- hDC = DisplayDC;
- }
-
- /* Allocate a new DC based on the original DC's device */
- pdcOld = DC_LockDc(hDC);
- if (NULL == pdcOld)
- {
- if (NULL != DisplayDC)
- {
- NtGdiDeleteObjectApp(DisplayDC);
- }
- DPRINT1("Failed to lock hDC\n");
- return NULL;
- }
- pdcNew = DC_AllocDC(&pdcOld->rosdc.DriverName);
- if (!pdcNew)
- {
- DPRINT1("Failed to create pdcNew\n");
- DC_UnlockDc(pdcOld);
- if (DisplayDC)
- {
- NtGdiDeleteObjectApp(DisplayDC);
- }
- return NULL;
- }
- hdcNew = pdcNew->BaseObject.hHmgr;
-
- pdcattrOld = pdcOld->pdcattr;
- pdcattrNew = pdcNew->pdcattr;
-
- /* Copy information from original DC to new DC */
- pdcNew->dclevel.hdcSave = hdcNew;
-
- pdcNew->dhpdev = pdcOld->dhpdev;
-
- /* DriverName is copied in the AllocDC routine */
- pdcattrNew->ptlWindowOrg = pdcattrOld->ptlWindowOrg;
- pdcattrNew->szlWindowExt = pdcattrOld->szlWindowExt;
- pdcattrNew->ptlViewportOrg = pdcattrOld->ptlViewportOrg;
- pdcattrNew->szlViewportExt = pdcattrOld->szlViewportExt;
-
- pdcNew->dctype = DC_TYPE_MEMORY; // Always!
- hsurf = NtGdiGetStockObject(DEFAULT_BITMAP);
- pdcNew->dclevel.pSurface = SURFACE_ShareLockSurface(hsurf);
- pdcNew->ppdev = pdcOld->ppdev;
- pdcNew->dclevel.hpal = pdcOld->dclevel.hpal;
-
- pdcattrNew->lTextAlign = pdcattrOld->lTextAlign;
- pdcattrNew->lBkMode = pdcattrOld->lBkMode;
- pdcattrNew->jBkMode = pdcattrOld->jBkMode;
- pdcattrNew->jROP2 = pdcattrOld->jROP2;
- pdcattrNew->dwLayout = pdcattrOld->dwLayout;
- if (pdcattrOld->dwLayout & LAYOUT_ORIENTATIONMASK) Layout = pdcattrOld->dwLayout;
- pdcNew->dclevel.flPath = pdcOld->dclevel.flPath;
- pdcattrNew->ulDirty_ = pdcattrOld->ulDirty_;
- pdcattrNew->iCS_CP = pdcattrOld->iCS_CP;
-
- pdcNew->erclWindow.left = pdcNew->erclWindow.top = 0;
- pdcNew->erclWindow.right = pdcNew->erclWindow.bottom = 1;
- DC_UnlockDc(pdcNew);
- DC_UnlockDc(pdcOld);
- if (NULL != DisplayDC)
- {
- NtGdiDeleteObjectApp(DisplayDC);
- }
-
- if (Layout) NtGdiSetLayout(hdcNew, -1, Layout);
+ HDC FASTCALL
+ IntGdiCreateDC(
+ PUNICODE_STRING Driver,
+ PUNICODE_STRING pustrDevice,
+ PVOID pUMdhpdev,
+ CONST PDEVMODEW pdmInit,
+ BOOL CreateAsIC)
+ {
+ HDC hdc;
+
+ hdc = GreOpenDCW(pustrDevice,
+ pdmInit,
+ NULL,
+ CreateAsIC ? DCTYPE_INFO :
+ (Driver ? DC_TYPE_DIRECT : DC_TYPE_DIRECT),
+ TRUE,
+ NULL,
+ NULL,
+ pUMdhpdev);
- DC_InitDC(hdcNew);
- return hdcNew;
+ return hdc;
}
-
- BOOL
- APIENTRY
- NtGdiDeleteObjectApp(HANDLE DCHandle)
+ HDC FASTCALL
+ IntGdiCreateDisplayDC(HDEV hDev, ULONG DcType, BOOL EmptyDC)
{
- GDIOBJTYPE ObjType;
-
- /* Complete all pending operations */
- NtGdiFlushUserBatch();
-
- if (GDI_HANDLE_IS_STOCKOBJ(DCHandle)) return TRUE;
-
- if (IsObjectDead((HGDIOBJ)DCHandle)) return TRUE;
-
- ObjType = GDI_OBJECT_GET_TYPE_INDEX((ULONG_PTR)DCHandle);
-
- if (GreGetObjectOwner( DCHandle, ObjType))
- {
- switch(ObjType)
- {
- case GDIObjType_DC_TYPE:
- return IntGdiDeleteDC(DCHandle, FALSE);
+ HDC hDC;
+ UNIMPLEMENTED;
+ ASSERT(FALSE);
- case GDIObjType_RGN_TYPE:
- case GDIObjType_SURF_TYPE:
- case GDIObjType_PAL_TYPE:
- case GDIObjType_LFONT_TYPE:
- case GDIObjType_BRUSH_TYPE:
- return GreDeleteObject((HGDIOBJ) DCHandle);
+ if (DcType == DC_TYPE_MEMORY)
+ hDC = NtGdiCreateCompatibleDC(NULL); // OH~ Yuck! I think I taste vomit in my mouth!
+ else
+ hDC = IntGdiCreateDC(NULL, NULL, NULL, NULL, (DcType == DC_TYPE_INFO));
- default:
- return FALSE;
- }
- }
- return (DCHandle != NULL);
+ return hDC;
}
{
PDC_ATTR pdcattr = pdc->pdcattr;
+ /* Timo : The text brush should never be changed.
+ * Jérôme : Yeah, but its palette must be updated anyway! */
if(pdcattr->ulDirty_ & DIRTY_TEXT)
- EBRUSHOBJ_vUpdate(&pdc->eboText, pdc->eboText.pbrush, pdc);
+ EBRUSHOBJ_vUpdate(&pdc->eboText, pbrDefaultBrush, pdc);
/* Update the eboText's solid color */
EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboText, pdcattr->crForegroundClr);
PDC_ATTR pdcattr = pdc->pdcattr;
if(pdcattr->ulDirty_ & DIRTY_BACKGROUND)
- EBRUSHOBJ_vUpdate(&pdc->eboBackground, pdc->eboBackground.pbrush, pdc);
+ EBRUSHOBJ_vUpdate(&pdc->eboBackground, pbrDefaultBrush, pdc);
/* Update the eboBackground's solid color */
EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboBackground, pdcattr->crBackgroundClr);
/* Is this a valid palette for this depth? */
if ((BitsPerFormat(pdc->dclevel.pSurface->SurfObj.iBitmapFormat) <= 8
- && ppal->Mode == PAL_INDEXED) ||
+ && (ppal->flFlags & PAL_INDEXED)) ||
(BitsPerFormat(pdc->dclevel.pSurface->SurfObj.iBitmapFormat) > 8))
{
/* Get old palette, set new one */
}
/* Get the handle for the old bitmap */
- psurfOld = pDC->dclevel.pSurface;
- hOrgBmp = psurfOld ? psurfOld->BaseObject.hHmgr : NULL;
+ ASSERT(pDC->dclevel.pSurface);
+ hOrgBmp = pDC->dclevel.pSurface->BaseObject.hHmgr;
+
+ /* Lock it, to be sure while we mess with it*/
+ psurfOld = SURFACE_LockSurface(hOrgBmp);
+
+ /* Reset hdc, this surface isn't selected anymore */
+ psurfOld->hdc = NULL;
/* Release the old bitmap, reference the new */
DC_vSelectSurface(pDC, psurfBmp);
+ /* And unlock it, now we're done */
+ SURFACE_UnlockSurface(psurfOld);
+
// If Info DC this is zero and pSurface is moved to DC->pSurfInfo.
- psurfBmp->hDC = hDC;
+ psurfBmp->hdc = hDC;
+
/* FIXME; improve by using a region without a handle and selecting it */
hVisRgn = IntSysCreateRectRgn( 0,
if (pPath->state != PATH_Closed)
{
SetLastWin32Error(ERROR_CAN_NOT_COMPLETE);
+ DC_UnlockDc(pdc);
return FALSE;
}
FASTCALL
DC_vCopyState(PDC pdcSrc, PDC pdcDst, BOOL To)
{
+ DPRINT("DC_vCopyState(%p, %p)\n", pdcSrc->BaseObject.hHmgr, pdcDst->BaseObject.hHmgr);
+
/* Copy full DC attribute */
*pdcDst->pdcattr = *pdcSrc->pdcattr;
-
+
+ /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
+ /* The VisRectRegion field needs to be set to a valid state */
+
/* Mark some fields as dirty */
pdcDst->pdcattr->ulDirty_ |= 0x0012001f; // Note: Use if, To is FALSE....
pdcDst->dclevel.hpal = pdcSrc->dclevel.hpal;
/* Handle references here correctly */
- DC_vSelectSurface(pdcDst, pdcSrc->dclevel.pSurface);
DC_vSelectFillBrush(pdcDst, pdcSrc->dclevel.pbrFill);
DC_vSelectLineBrush(pdcDst, pdcSrc->dclevel.pbrLine);
DC_vSelectPalette(pdcDst, pdcSrc->dclevel.ppal);
}
- BOOL
- APIENTRY
- NtGdiRestoreDC(
- HDC hdc,
+ VOID
+ NTAPI
+ DC_vRestoreDC(
+ IN PDC pdc,
INT iSaveLevel)
{
- PDC pdc, pdcSave;
+ PEPROCESS pepCurrentProcess;
HDC hdcSave;
+ PDC pdcSave;
- DPRINT("NtGdiRestoreDC(%lx, %d)\n", hdc, iSaveLevel);
+ ASSERT(iSaveLevel > 0);
+ DPRINT("DC_vRestoreDC(%p, %ld)\n", pdc->BaseObject.hHmgr, iSaveLevel);
- /* Lock the original DC */
- pdc = DC_LockDc(hdc);
- if (!pdc)
- {
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- return FALSE;
- }
-
- ASSERT(pdc->dclevel.lSaveDepth > 0);
-
- /* Negative values are relative to the stack top */
- if (iSaveLevel < 0)
- iSaveLevel = pdc->dclevel.lSaveDepth + iSaveLevel;
-
- /* Check if we have a valid instance */
- if (iSaveLevel <= 0 || iSaveLevel >= pdc->dclevel.lSaveDepth)
- {
- DPRINT("Illegal save level, requested: %ld, current: %ld\n",
- iSaveLevel, pdc->dclevel.lSaveDepth);
- DC_UnlockDc(pdc);
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
+ /* Get current process */
+ pepCurrentProcess = PsGetCurrentProcess();
/* Loop the save levels */
while (pdc->dclevel.lSaveDepth > iSaveLevel)
{
hdcSave = pdc->dclevel.hdcSave;
+ DPRINT("RestoreDC = %p\n", hdcSave);
/* Set us as the owner */
- if (!IntGdiSetDCOwnerEx(hdcSave, GDI_OBJ_HMGR_POWNED, FALSE ))
+ if (!GDIOBJ_SetOwnership(hdcSave, pepCurrentProcess))
{
/* Could not get ownership. That's bad! */
- DPRINT1("Could not get ownership of saved DC (%p) for dc %p!\n",
- hdcSave, hdc);
- return FALSE;
+ DPRINT1("Could not get ownership of saved DC (%p) for hdc %p!\n",
+ hdcSave, pdc->BaseObject.hHmgr);
+ return;// FALSE;
}
/* Lock the saved dc */
{
/* WTF? Internal error! */
DPRINT1("Could not lock the saved DC (%p) for dc %p!\n",
- hdcSave, hdc);
- DC_UnlockDc(pdc);
- return FALSE;
+ hdcSave, pdc->BaseObject.hHmgr);
+ return;// FALSE;
}
/* Remove the saved dc from the queue */
/* Copy the state back */
DC_vCopyState(pdcSave, pdc, FALSE);
+ /* Only memory DC's change their surface */
+ if (pdc->dctype == DCTYPE_MEMORY)
+ DC_vSelectSurface(pdc, pdcSave->dclevel.pSurface);
+
// Restore Path by removing it, if the Save flag is set.
// BeginPath will takecare of the rest.
if (pdc->dclevel.hPath && pdc->dclevel.flPath & DCPATH_SAVE)
pdc->dclevel.hPath = 0;
pdc->dclevel.flPath &= ~DCPATH_SAVE;
}
- // Attempt to plug the leak!
- if (pdcSave->rosdc.hClipRgn)
- {
- DPRINT("Have hClipRgn!\n");
- REGION_FreeRgnByHandle(pdcSave->rosdc.hClipRgn);
- }
- // FIXME! Handle prgnMeta!
}
+ /* Prevent save dc from being restored */
+ pdcSave->dclevel.lSaveDepth = 1;
+
+ /* Unlock it */
+ DC_UnlockDc(pdcSave);
/* Delete the saved dc */
GreDeleteObject(hdcSave);
}
+ DPRINT("Leave DC_vRestoreDC()\n");
+ }
+
+
+
+ BOOL
+ APIENTRY
+ NtGdiRestoreDC(
+ HDC hdc,
+ INT iSaveLevel)
+ {
+ PDC pdc;
+
+ DPRINT("NtGdiRestoreDC(%p, %d)\n", hdc, iSaveLevel);
+
+ /* Lock the original DC */
+ pdc = DC_LockDc(hdc);
+ if (!pdc)
+ {
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ ASSERT(pdc->dclevel.lSaveDepth > 0);
+
+ /* Negative values are relative to the stack top */
+ if (iSaveLevel < 0)
+ iSaveLevel = pdc->dclevel.lSaveDepth + iSaveLevel;
+
+ /* Check if we have a valid instance */
+ if (iSaveLevel <= 0 || iSaveLevel >= pdc->dclevel.lSaveDepth)
+ {
+ DPRINT("Illegal save level, requested: %ld, current: %ld\n",
+ iSaveLevel, pdc->dclevel.lSaveDepth);
+ DC_UnlockDc(pdc);
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ /* Call the internal function */
+ DC_vRestoreDC(pdc, iSaveLevel);
+
DC_UnlockDc(pdc);
- DPRINT("Leaving NtGdiRestoreDC\n");
+ DPRINT("Leave NtGdiRestoreDC\n");
return TRUE;
}
PDC pdc, pdcSave;
INT lSaveDepth;
- DPRINT("NtGdiSaveDC(%lx)\n", hDC);
+ DPRINT("NtGdiSaveDC(%p)\n", hDC);
/* Lock the original dc */
pdc = DC_LockDc(hDC);
}
/* Allocate a new dc */
- pdcSave = DC_AllocDC(NULL);
+ pdcSave = DC_AllocDcWithHandle();
if (pdcSave == NULL)
{
DPRINT("Could not allocate a new DC\n");
}
hdcSave = pdcSave->BaseObject.hHmgr;
- /* Copy the current state */
- DC_vCopyState(pdc, pdcSave, TRUE);
+ InterlockedIncrement(&pdc->ppdev->cPdevRefs);
+ DC_vInitDc(pdcSave, DCTYPE_MEMORY, pdc->ppdev);
+
+ /* Handle references here correctly */
+ // pdcSrc->dclevel.pSurface = NULL;
+ // pdcSrc->dclevel.pbrFill = NULL;
+ // pdcSrc->dclevel.pbrLine = NULL;
+ // pdcSrc->dclevel.ppal = NULL;
/* Make it a kernel handle
(FIXME: windows handles this different, see wiki)*/
- IntGdiSetDCOwnerEx(hdcSave, GDI_OBJ_HMGR_NONE, FALSE);
+ GDIOBJ_SetOwnership(hdcSave, NULL);
+
+ /* Copy the current state */
+ DC_vCopyState(pdc, pdcSave, TRUE);
+
+ /* Only memory DC's change their surface */
+ if (pdc->dctype == DCTYPE_MEMORY)
+ DC_vSelectSurface(pdcSave, pdc->dclevel.pSurface);
/* Copy path. FIXME: why this way? */
pdcSave->dclevel.hPath = pdc->dclevel.hPath;
DC_UnlockDc(pdcSave);
DC_UnlockDc(pdc);
- DPRINT("Leave NtGdiSaveDC: %ld\n", lSaveDepth);
+ DPRINT("Leave NtGdiSaveDC: %ld, hdcSave = %p\n", lSaveDepth, hdcSave);
return lSaveDepth;
}
if (pdc->ppdev->flFlags & PDEV_META_DEVICE)
{
pSurface = pdc->dclevel.pSurface;
- if (pSurface && pSurface->flFlags & PDEV_SURFACE)
+ if (pSurface && pSurface->flags & PDEV_SURFACE)
{
rclClip.left += pdc->ppdev->ptlOrigion.x;
rclClip.top += pdc->ppdev->ptlOrigion.y;
#define NDEBUG
#include <debug.h>
- // TODO: proper implementation of LDEVOBJ and PDEVOBJ interface
-
- /*static*/ PDEVOBJ PrimarySurface;
- PPDEVOBJ pPrimarySurface = &PrimarySurface;
- static KEVENT VideoDriverNeedsPreparation;
- static KEVENT VideoDriverPrepared;
PDC defaultDCstate = NULL;
- PSIZEL
- FASTCALL
- PDEV_sizl(PPDEVOBJ ppdev, PSIZEL psizl)
- {
- if (ppdev->flFlags & PDEV_META_DEVICE)
- {
- psizl->cx = ppdev->ulHorzRes;
- psizl->cy = ppdev->ulVertRes;
- }
- else
- {
- psizl->cx = ppdev->gdiinfo.ulHorzRes;
- psizl->cy = ppdev->gdiinfo.ulVertRes;
- }
- return psizl;
- }
-
- NTSTATUS FASTCALL
- InitDcImpl(VOID)
- {
- KeInitializeEvent(&VideoDriverNeedsPreparation, SynchronizationEvent, TRUE);
- KeInitializeEvent(&VideoDriverPrepared, NotificationEvent, FALSE);
- return STATUS_SUCCESS;
- }
-
-
- static BOOLEAN FASTCALL
- GetRegistryPath(PUNICODE_STRING RegistryPath, ULONG DisplayNumber)
- {
- RTL_QUERY_REGISTRY_TABLE QueryTable[2];
- WCHAR DeviceNameBuffer[20];
- NTSTATUS Status;
-
- swprintf(DeviceNameBuffer, L"\\Device\\Video%lu", DisplayNumber);
- RtlInitUnicodeString(RegistryPath, NULL);
- RtlZeroMemory(QueryTable, sizeof(QueryTable));
- QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
- QueryTable[0].Name = DeviceNameBuffer;
- QueryTable[0].EntryContext = RegistryPath;
-
- Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP,
- L"VIDEO",
- QueryTable,
- NULL,
- NULL);
- if (! NT_SUCCESS(Status))
- {
- DPRINT1("No \\Device\\Video%lu value in DEVICEMAP\\VIDEO found\n", DisplayNumber);
- return FALSE;
- }
-
- DPRINT("RegistryPath %wZ\n", RegistryPath);
-
- return TRUE;
- }
-
-
- NTSTATUS
- NTAPI
- EnumDisplayQueryRoutine(IN PWSTR ValueName,
- IN ULONG ValueType,
- IN PVOID ValueData,
- IN ULONG ValueLength,
- IN PVOID Context,
- IN PVOID EntryContext)
- {
- if ((Context == NULL) && ((ValueType == REG_SZ) || (ValueType == REG_MULTI_SZ)))
- {
- *(PULONG)EntryContext = ValueLength;
- }
- else
- {
- DPRINT1("Value data: %S %d\n", ValueData, ValueLength);
- RtlCopyMemory(Context, ValueData, ValueLength);
- }
-
- return STATUS_SUCCESS;
- }
-
- static BOOL FASTCALL
- FindDriverFileNames(PUNICODE_STRING DriverFileNames, ULONG DisplayNumber)
- {
- RTL_QUERY_REGISTRY_TABLE QueryTable[2];
- UNICODE_STRING RegistryPath;
- NTSTATUS Status;
- PWCHAR DriverNames = NULL;
- ULONG Length = 0;
-
- if (! GetRegistryPath(&RegistryPath, DisplayNumber))
- {
- DPRINT("GetRegistryPath failed\n");
- return FALSE;
- }
-
- RtlZeroMemory(QueryTable, sizeof(QueryTable));
- QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND;
- QueryTable[0].Name = L"InstalledDisplayDrivers";
- QueryTable[0].EntryContext = &Length;
- QueryTable[0].QueryRoutine = EnumDisplayQueryRoutine;
-
- Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
- RegistryPath.Buffer,
- QueryTable,
- NULL,
- NULL);
- // DPRINT1("Status: %lx\n", Status);
- if (Length)
- {
- DriverNames = ExAllocatePoolWithTag(PagedPool, Length, TAG_DRIVER);
- // DPRINT1("Length allocated: %d\n", Length);
- Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
- RegistryPath.Buffer,
- QueryTable,
- DriverNames,
- NULL);
- if (!NT_SUCCESS(Status)) DriverNames = NULL;
- }
-
- ExFreePoolWithTag(RegistryPath.Buffer, TAG_RTLREGISTRY);
- if (! NT_SUCCESS(Status))
- {
- DPRINT1("No InstalledDisplayDrivers value in service entry found\n");
- return FALSE;
- }
-
- RtlInitUnicodeString(DriverFileNames, DriverNames);
- DriverFileNames->Length = Length;
- DriverFileNames->MaximumLength = Length;
- //DPRINT1("DriverFileNames %wZ\n", DriverFileNames);
-
- return TRUE;
- }
-
-
- static NTSTATUS APIENTRY
- DevModeCallback(IN PWSTR ValueName,
- IN ULONG ValueType,
- IN PVOID ValueData,
- IN ULONG ValueLength,
- IN PVOID Context,
- IN PVOID EntryContext)
- {
- PDEVMODEW DevMode = (PDEVMODEW) Context;
-
- DPRINT("Found registry value for name %S: type %d, length %d\n",
- ValueName, ValueType, ValueLength);
-
- if (REG_DWORD == ValueType && sizeof(DWORD) == ValueLength)
- {
- if (0 == _wcsicmp(ValueName, L"DefaultSettings.BitsPerPel"))
- {
- DevMode->dmBitsPerPel = *((DWORD *) ValueData);
- }
- else if (0 == _wcsicmp(ValueName, L"DefaultSettings.Flags"))
- {
- DevMode->dmDisplayFlags = *((DWORD *) ValueData);
- }
- else if (0 == _wcsicmp(ValueName, L"DefaultSettings.VRefresh"))
- {
- DevMode->dmDisplayFrequency = *((DWORD *) ValueData);
- }
- else if (0 == _wcsicmp(ValueName, L"DefaultSettings.XPanning"))
- {
- DevMode->dmPanningWidth = *((DWORD *) ValueData);
- }
- else if (0 == _wcsicmp(ValueName, L"DefaultSettings.XResolution"))
- {
- DevMode->dmPelsWidth = *((DWORD *) ValueData);
- }
- else if (0 == _wcsicmp(ValueName, L"DefaultSettings.YPanning"))
- {
- DevMode->dmPanningHeight = *((DWORD *) ValueData);
- }
- else if (0 == _wcsicmp(ValueName, L"DefaultSettings.YResolution"))
- {
- DevMode->dmPelsHeight = *((DWORD *) ValueData);
- }
- }
-
- return STATUS_SUCCESS;
- }
-
-
- static BOOL FASTCALL
- SetupDevMode(PDEVMODEW DevMode, ULONG DisplayNumber)
- {
- UNICODE_STRING RegistryPath;
- RTL_QUERY_REGISTRY_TABLE QueryTable[2];
- NTSTATUS Status;
- BOOLEAN Valid = TRUE;
-
- if (!GetRegistryPath(&RegistryPath, DisplayNumber))
- {
- DPRINT("GetRegistryPath failed\n");
- return FALSE;
- }
-
- RtlZeroMemory(QueryTable, sizeof(QueryTable));
- QueryTable[0].QueryRoutine = DevModeCallback;
- QueryTable[0].Flags = 0;
- QueryTable[0].Name = NULL;
- QueryTable[0].EntryContext = NULL;
- QueryTable[0].DefaultType = REG_NONE;
- QueryTable[0].DefaultData = NULL;
- QueryTable[0].DefaultLength = 0;
-
- Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
- RegistryPath.Buffer,
- QueryTable,
- DevMode,
- NULL);
- if (! NT_SUCCESS(Status))
- {
- DPRINT("RtlQueryRegistryValues for %wZ failed with status 0x%08x\n",
- &RegistryPath, Status);
- Valid = FALSE;
- }
- else
- {
- DPRINT("dmBitsPerPel %d dmDisplayFrequency %d dmPelsWidth %d dmPelsHeight %d\n",
- DevMode->dmBitsPerPel, DevMode->dmDisplayFrequency,
- DevMode->dmPelsWidth, DevMode->dmPelsHeight);
- if (0 == DevMode->dmBitsPerPel || 0 == DevMode->dmDisplayFrequency
- || 0 == DevMode->dmPelsWidth || 0 == DevMode->dmPelsHeight)
- {
- DPRINT("Not all required devmode members are set\n");
- Valid = FALSE;
- }
- }
-
- ExFreePoolWithTag(RegistryPath.Buffer, TAG_RTLREGISTRY);
-
- if (! Valid)
- {
- RtlZeroMemory(DevMode, sizeof(DEVMODEW));
- }
-
- return Valid;
- }
-
- static BOOL FASTCALL
- IntPrepareDriver(VOID)
- {
- PFN_DrvEnableDriver GDEnableDriver;
- DRVENABLEDATA DED;
- UNICODE_STRING DriverFileNames;
- PWSTR CurrentName;
- BOOL GotDriver;
- BOOL DoDefault;
- ULONG DisplayNumber;
- LARGE_INTEGER Zero;
- BOOLEAN ret = FALSE;
-
- Zero.QuadPart = 0;
- if (STATUS_SUCCESS != KeWaitForSingleObject(&VideoDriverNeedsPreparation, Executive, KernelMode, TRUE, &Zero))
- {
- /* Concurrent access. Wait for VideoDriverPrepared event */
- if (STATUS_SUCCESS == KeWaitForSingleObject(&VideoDriverPrepared, Executive, KernelMode, TRUE, NULL))
- ret = PrimarySurface.PreparedDriver;
- goto cleanup;
- }
- // HAX! Fixme so I can support more than one! So how many?
- for (DisplayNumber = 0; ; DisplayNumber++)
- {
- DPRINT("Trying to load display driver no. %d\n", DisplayNumber);
-
- RtlZeroMemory(&PrimarySurface, sizeof(PrimarySurface));
-
- // if (!pPrimarySurface) pPrimarySurface = ExAllocatePoolWithTag(PagedPool, gdwDirectDrawContext + sizeof(PDEVOBJ), TAG_GDIPDEV);
-
- PrimarySurface.VideoFileObject = DRIVER_FindMPDriver(DisplayNumber);
-
- /* Open the miniport driver */
- if (PrimarySurface.VideoFileObject == NULL)
- {
- DPRINT1("FindMPDriver failed\n");
- goto cleanup;
- }
-
- /* Retrieve DDI driver names from registry */
- RtlInitUnicodeString(&DriverFileNames, NULL);
- if (!FindDriverFileNames(&DriverFileNames, DisplayNumber))
- {
- DPRINT1("FindDriverFileNames failed\n");
- continue;
- }
-
- /*
- * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
- * scan all of them until a good one found.
- */
- CurrentName = DriverFileNames.Buffer;
- GotDriver = FALSE;
- while (!GotDriver &&
- CurrentName < DriverFileNames.Buffer + (DriverFileNames.Length / sizeof (WCHAR)))
- {
- /* Get the DDI driver's entry point */
- GDEnableDriver = DRIVER_FindDDIDriver(CurrentName);
- if (NULL == GDEnableDriver)
- {
- DPRINT("FindDDIDriver failed for %S\n", CurrentName);
- }
- else
- {
- /* Call DDI driver's EnableDriver function */
- RtlZeroMemory(&DED, sizeof(DED));
-
- if (! GDEnableDriver(DDI_DRIVER_VERSION_NT5_01, sizeof(DED), &DED))
- {
- DPRINT("DrvEnableDriver failed for %S\n", CurrentName);
- }
- else
- {
- GotDriver = TRUE;
- }
- }
-
- if (! GotDriver)
- {
- /* Skip to the next name but never get past the Unicode string */
- while (L'\0' != *CurrentName &&
- CurrentName < DriverFileNames.Buffer + (DriverFileNames.Length / sizeof (WCHAR)))
- {
- CurrentName++;
- }
- if (CurrentName < DriverFileNames.Buffer + (DriverFileNames.Length / sizeof (WCHAR)))
- {
- CurrentName++;
- }
- }
- }
-
- if (!GotDriver)
- {
- ObDereferenceObject(PrimarySurface.VideoFileObject);
- ExFreePoolWithTag(DriverFileNames.Buffer, TAG_RTLREGISTRY);
- DPRINT1("No suitable DDI driver found\n");
- continue;
- }
-
- DPRINT1("Display driver %S loaded\n", CurrentName);
-
- ExFreePoolWithTag(DriverFileNames.Buffer, TAG_RTLREGISTRY);
-
- DPRINT("Building DDI Functions\n");
-
- /* Construct DDI driver function dispatch table */
- if (!DRIVER_BuildDDIFunctions(&DED, &PrimarySurface.DriverFunctions))
- {
- ObDereferenceObject(PrimarySurface.VideoFileObject);
- DPRINT1("BuildDDIFunctions failed\n");
- goto cleanup;
- }
-
- /* Allocate a phyical device handle from the driver */
- // Support DMW.dmSize + DMW.dmDriverExtra & Alloc DMW then set prt pdmwDev.
- PrimarySurface.DMW.dmSize = sizeof (PrimarySurface.DMW);
- if (SetupDevMode(&PrimarySurface.DMW, DisplayNumber))
- {
- PrimarySurface.dhpdev = PrimarySurface.DriverFunctions.EnablePDEV(
- &PrimarySurface.DMW,
- L"",
- HS_DDI_MAX,
- PrimarySurface.ahsurf,
- sizeof(PrimarySurface.gdiinfo),
- &PrimarySurface.gdiinfo,
- sizeof(PrimarySurface.devinfo),
- &PrimarySurface.devinfo,
- NULL,
- L"",
- (HANDLE) (PrimarySurface.VideoFileObject->DeviceObject));
- DoDefault = (NULL == PrimarySurface.dhpdev);
- if (DoDefault)
- {
- DPRINT1("DrvEnablePDev with registry parameters failed\n");
- }
- }
- else
- {
- DoDefault = TRUE;
- }
-
- if (DoDefault)
- {
- RtlZeroMemory(&(PrimarySurface.DMW), sizeof(DEVMODEW));
- PrimarySurface.DMW.dmSize = sizeof (PrimarySurface.DMW);
- PrimarySurface.dhpdev = PrimarySurface.DriverFunctions.EnablePDEV(
- &PrimarySurface.DMW,
- L"",
- HS_DDI_MAX,
- PrimarySurface.ahsurf,
- sizeof(PrimarySurface.gdiinfo),
- &PrimarySurface.gdiinfo,
- sizeof(PrimarySurface.devinfo),
- &PrimarySurface.devinfo,
- NULL,
- L"",
- (HANDLE) (PrimarySurface.VideoFileObject->DeviceObject));
-
- if (NULL == PrimarySurface.dhpdev)
- {
- ObDereferenceObject(PrimarySurface.VideoFileObject);
- DPRINT1("DrvEnablePDEV with default parameters failed\n");
- DPRINT1("Perhaps DDI driver doesn't match miniport driver?\n");
- continue;
- }
-
- // Update the primary surface with what we really got
- PrimarySurface.DMW.dmPelsWidth = PrimarySurface.gdiinfo.ulHorzRes;
- PrimarySurface.DMW.dmPelsHeight = PrimarySurface.gdiinfo.ulVertRes;
- PrimarySurface.DMW.dmBitsPerPel = PrimarySurface.gdiinfo.cBitsPixel;
- PrimarySurface.DMW.dmDisplayFrequency = PrimarySurface.gdiinfo.ulVRefresh;
- }
-
- if (!PrimarySurface.DMW.dmDriverExtra)
- {
- PrimarySurface.pdmwDev = &PrimarySurface.DMW; // HAX!
- }
- else
- {
- DPRINT1("WARNING!!! Need to Alloc DMW !!!!!!\n");
- }
- // Dont remove until we finish testing other drivers.
- if (PrimarySurface.DMW.dmDriverExtra != 0)
- {
- DPRINT1("**** DMW extra = %u bytes. Please report to ros-dev@reactos.org ****\n", PrimarySurface.DMW.dmDriverExtra);
- }
-
- if (0 == PrimarySurface.gdiinfo.ulLogPixelsX)
- {
- DPRINT("Adjusting gdiinfo.ulLogPixelsX\n");
- PrimarySurface.gdiinfo.ulLogPixelsX = 96;
- }
- if (0 == PrimarySurface.gdiinfo.ulLogPixelsY)
- {
- DPRINT("Adjusting gdiinfo.ulLogPixelsY\n");
- PrimarySurface.gdiinfo.ulLogPixelsY = 96;
- }
-
- PrimarySurface.Pointer.Exclude.right = -1;
-
- DPRINT("calling completePDev\n");
-
- /* Complete initialization of the physical device */
- PrimarySurface.DriverFunctions.CompletePDEV(
- PrimarySurface.dhpdev,
- (HDEV)&PrimarySurface);
-
- DPRINT("calling DRIVER_ReferenceDriver\n");
-
- DRIVER_ReferenceDriver(L"DISPLAY");
-
- PrimarySurface.PreparedDriver = TRUE;
- PrimarySurface.DisplayNumber = DisplayNumber;
- PrimarySurface.flFlags = PDEV_DISPLAY; // Hard set,, add more flags.
- PrimarySurface.hsemDevLock = (PERESOURCE)EngCreateSemaphore();
- // Should be null,, but make sure for now.
- PrimarySurface.pvGammaRamp = NULL;
- PrimarySurface.ppdevNext = NULL; // Fixme! We need to support more than display drvs.
- PrimarySurface.ppdevParent = NULL; // Always NULL if primary.
- PrimarySurface.pGraphicsDevice = NULL; // Fixme!
- PrimarySurface.pEDDgpl = ExAllocatePoolWithTag(PagedPool, sizeof(EDD_DIRECTDRAW_GLOBAL), TAG_EDDGBL);
- if (PrimarySurface.pEDDgpl)
- {
- RtlZeroMemory( PrimarySurface.pEDDgpl ,sizeof(EDD_DIRECTDRAW_GLOBAL));
- ret = TRUE;
- }
- goto cleanup;
- }
-
- cleanup:
- KeSetEvent(&VideoDriverPrepared, 1, FALSE);
- return ret;
- }
-
- BOOL FASTCALL
- IntPrepareDriverIfNeeded(VOID)
+ VOID FASTCALL
+ IntGdiReferencePdev(PPDEVOBJ ppdev)
{
- return (PrimarySurface.PreparedDriver ? TRUE : IntPrepareDriver());
+ UNIMPLEMENTED;
}
- static BOOL FASTCALL
- PrepareVideoPrt(VOID)
+ VOID FASTCALL
+ IntGdiUnreferencePdev(PPDEVOBJ ppdev, DWORD CleanUpType)
{
- PIRP Irp;
- NTSTATUS Status;
- IO_STATUS_BLOCK Iosb;
- BOOL Prepare = TRUE;
- ULONG Length = sizeof(BOOL);
- PIO_STACK_LOCATION StackPtr;
- LARGE_INTEGER StartOffset;
- PFILE_OBJECT FileObject = PrimarySurface.VideoFileObject;
- PDEVICE_OBJECT DeviceObject = FileObject->DeviceObject;
-
- DPRINT("PrepareVideoPrt() called\n");
-
- KeClearEvent(&PrimarySurface.VideoFileObject->Event);
-
- ObReferenceObjectByPointer(FileObject, 0, IoFileObjectType, KernelMode);
-
- StartOffset.QuadPart = 0;
- Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
- DeviceObject,
- (PVOID) &Prepare,
- Length,
- &StartOffset,
- NULL,
- &Iosb);
- if (NULL == Irp)
- {
- return FALSE;
- }
-
- /* Set up IRP Data */
- Irp->Tail.Overlay.OriginalFileObject = FileObject;
- Irp->RequestorMode = KernelMode;
- Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
- Irp->Overlay.AsynchronousParameters.UserApcContext = NULL;
- Irp->Flags |= IRP_WRITE_OPERATION;
-
- /* Setup Stack Data */
- StackPtr = IoGetNextIrpStackLocation(Irp);
- StackPtr->FileObject = PrimarySurface.VideoFileObject;
- StackPtr->Parameters.Write.Key = 0;
-
- Status = IoCallDriver(DeviceObject, Irp);
-
- if (STATUS_PENDING == Status)
- {
- KeWaitForSingleObject(&FileObject->Event, Executive, KernelMode, TRUE, 0);
- Status = Iosb.Status;
- }
-
- return NT_SUCCESS(Status);
+ UNIMPLEMENTED;
}
-
BOOL FASTCALL
- IntCreatePrimarySurface(VOID)
+ IntCreatePrimarySurface()
{
SIZEL SurfSize;
- RECTL SurfaceRect;
- SURFOBJ *SurfObj;
+ SURFOBJ *pso;
BOOL calledFromUser;
- if (! IntPrepareDriverIfNeeded())
- {
- return FALSE;
- }
-
- if (! PrepareVideoPrt())
- {
- return FALSE;
- }
-
- DPRINT("calling EnableSurface\n");
- /* Enable the drawing surface */
- PrimarySurface.pSurface =
- PrimarySurface.DriverFunctions.EnableSurface(PrimarySurface.dhpdev);
- if (NULL == PrimarySurface.pSurface)
- {
- /* PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.dhpdev, FALSE);*/
- PrimarySurface.DriverFunctions.DisablePDEV(PrimarySurface.dhpdev);
- ObDereferenceObject(PrimarySurface.VideoFileObject);
- DPRINT1("DrvEnableSurface failed\n");
- return FALSE;
- }
-
- PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.dhpdev, TRUE);
-
calledFromUser = UserIsEntered(); //fixme: possibly upgrade a shared lock
if (!calledFromUser)
{
}
/* attach monitor */
- IntAttachMonitor(&PrimarySurface, PrimarySurface.DisplayNumber);
+ IntAttachMonitor(gppdevPrimary, 0);
- SurfObj = EngLockSurface(PrimarySurface.pSurface);
- SurfObj->dhpdev = PrimarySurface.dhpdev;
- SurfSize = SurfObj->sizlBitmap;
- SurfaceRect.left = SurfaceRect.top = 0;
- SurfaceRect.right = SurfObj->sizlBitmap.cx;
- SurfaceRect.bottom = SurfObj->sizlBitmap.cy;
- /* FIXME - why does EngEraseSurface() sometimes crash?
- EngEraseSurface(SurfObj, &SurfaceRect, 0); */
+ DPRINT1("IntCreatePrimarySurface, pPrimarySurface=%p, pPrimarySurface->pSurface = %p\n",
+ pPrimarySurface, pPrimarySurface->pSurface);
- /* Put the pointer in the center of the screen */
- gpsi->ptCursor.x = (SurfaceRect.right - SurfaceRect.left) / 2;
- gpsi->ptCursor.y = (SurfaceRect.bottom - SurfaceRect.top) / 2;
+ /* Create surface */
+ pso = &PDEVOBJ_pSurface(pPrimarySurface)->SurfObj;
+ SurfSize = pso->sizlBitmap;
- /* Give the PDEV a MovePointer function */
- PrimarySurface.pfnMovePointer = PrimarySurface.DriverFunctions.MovePointer;
- if (!PrimarySurface.pfnMovePointer)
- PrimarySurface.pfnMovePointer = EngMovePointer;
+ /* Put the pointer in the center of the screen */
+ gpsi->ptCursor.x = pso->sizlBitmap.cx / 2;
+ gpsi->ptCursor.y = pso->sizlBitmap.cy / 2;
- EngUnlockSurface(SurfObj);
co_IntShowDesktop(IntGetActiveDesktop(), SurfSize.cx, SurfSize.cy);
// Init Primary Displays Device Capabilities.
- IntvGetDeviceCaps(&PrimarySurface, &GdiHandleTable->DevCaps);
+ PDEVOBJ_vGetDeviceCaps(pPrimarySurface, &GdiHandleTable->DevCaps);
if (!calledFromUser)
{
}
VOID FASTCALL
- IntDestroyPrimarySurface(VOID)
+ IntDestroyPrimarySurface()
{
- BOOL calledFromUser;
-
- DRIVER_UnreferenceDriver(L"DISPLAY");
-
- calledFromUser = UserIsEntered();
- if (!calledFromUser)
- {
- UserEnterExclusive();
- }
-
- /* detach monitor */
- IntDetachMonitor(&PrimarySurface);
-
- if (!calledFromUser)
- {
- UserLeave();
- }
-
- /*
- * FIXME: Hide a mouse pointer there. Also because we have to prevent
- * memory leaks with the Eng* mouse routines.
- */
-
- DPRINT("Reseting display\n" );
- PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.dhpdev, FALSE);
- PrimarySurface.DriverFunctions.DisableSurface(PrimarySurface.dhpdev);
- PrimarySurface.DriverFunctions.DisablePDEV(PrimarySurface.dhpdev);
- PrimarySurface.PreparedDriver = FALSE;
- KeSetEvent(&VideoDriverNeedsPreparation, 1, FALSE);
- KeResetEvent(&VideoDriverPrepared);
-
- DceEmptyCache();
-
- ObDereferenceObject(PrimarySurface.VideoFileObject);
- }
-
- INT
- FASTCALL
- IntcFonts(PPDEVOBJ pDevObj)
- {
- ULONG_PTR Junk;
- // Msdn DrvQueryFont:
- // If the number of fonts in DEVINFO is -1 and iFace is zero, the driver
- // should return the number of fonts it supports.
- if ( pDevObj->devinfo.cFonts == -1)
- {
- if (pDevObj->DriverFunctions.QueryFont)
- pDevObj->devinfo.cFonts =
- (ULONG)pDevObj->DriverFunctions.QueryFont(pDevObj->dhpdev, 0, 0, &Junk);
- else
- pDevObj->devinfo.cFonts = 0;
- }
- return pDevObj->devinfo.cFonts;
- }
-
- //
- // Support multi display/device locks.
- //
- VOID
- FASTCALL
- DC_LockDisplay(HDC hDC)
- {
- PERESOURCE Resource;
- PDC dc = DC_LockDc(hDC);
- if (!dc) return;
- Resource = dc->ppdev->hsemDevLock;
- DC_UnlockDc(dc);
- if (!Resource) return;
- KeEnterCriticalRegion();
- ExAcquireResourceExclusiveLite( Resource , TRUE);
- }
-
- VOID
- FASTCALL
- DC_UnlockDisplay(HDC hDC)
- {
- PERESOURCE Resource;
- PDC dc = DC_LockDc(hDC);
- if (!dc) return;
- Resource = dc->ppdev->hsemDevLock;
- DC_UnlockDc(dc);
- if (!Resource) return;
- ExReleaseResourceLite( Resource );
- KeLeaveCriticalRegion();
+ UNIMPLEMENTED;
}
- //
- // Enumerate HDev
- //
PPDEVOBJ FASTCALL
IntEnumHDev(VOID)
{
// I guess we will soon have more than one primary surface.
// This will do for now.
- return &PrimarySurface;
+ return pPrimarySurface;
}
- VOID FASTCALL
- IntGdiReferencePdev(PPDEVOBJ ppdev)
- {
- if (!hsemDriverMgmt) hsemDriverMgmt = EngCreateSemaphore(); // Hax, should be in dllmain.c
- IntGdiAcquireSemaphore(hsemDriverMgmt);
- ppdev->cPdevRefs++;
- IntGdiReleaseSemaphore(hsemDriverMgmt);
- }
-
- VOID FASTCALL
- IntGdiUnreferencePdev(PPDEVOBJ ppdev, DWORD CleanUpType)
- {
- IntGdiAcquireSemaphore(hsemDriverMgmt);
- ppdev->cPdevRefs--;
- if (!ppdev->cPdevRefs)
- {
- // Handle the destruction of ppdev or PDEVOBJ or PDEVOBJ or PDEV etc.
- }
- IntGdiReleaseSemaphore(hsemDriverMgmt);
- }
-
-
-
- INT
- FASTCALL
- IntGetColorManagementCaps(PPDEVOBJ pDevObj)
- {
- INT ret = CM_NONE;
-
- if ( pDevObj->flFlags & PDEV_DISPLAY)
- {
- if (pDevObj->devinfo.iDitherFormat == BMF_8BPP ||
- pDevObj->devinfo.flGraphicsCaps2 & GCAPS2_CHANGEGAMMARAMP)
- ret = CM_GAMMA_RAMP;
- }
- if (pDevObj->devinfo.flGraphicsCaps & GCAPS_CMYKCOLOR)
- ret |= CM_CMYK_COLOR;
- if (pDevObj->devinfo.flGraphicsCaps & GCAPS_ICM)
- ret |= CM_DEVICE_ICM;
- return ret;
- }
-
- INT FASTCALL
- IntGdiGetDeviceCaps(PDC dc, INT Index)
- {
- INT ret = 0;
- PPDEVOBJ ppdev = dc->ppdev;
- /* Retrieve capability */
- switch (Index)
- {
- case DRIVERVERSION:
- ret = ppdev->gdiinfo.ulVersion;
- break;
-
- case TECHNOLOGY:
- ret = ppdev->gdiinfo.ulTechnology;
- break;
-
- case HORZSIZE:
- ret = ppdev->gdiinfo.ulHorzSize;
- break;
-
- case VERTSIZE:
- ret = ppdev->gdiinfo.ulVertSize;
- break;
-
- case HORZRES:
- ret = ppdev->gdiinfo.ulHorzRes;
- break;
-
- case VERTRES:
- ret = ppdev->gdiinfo.ulVertRes;
- break;
-
- case LOGPIXELSX:
- ret = ppdev->gdiinfo.ulLogPixelsX;
- break;
-
- case LOGPIXELSY:
- ret = ppdev->gdiinfo.ulLogPixelsY;
- break;
-
- case CAPS1:
- if ( ppdev->pGraphicsDevice &&
- (((PGRAPHICS_DEVICE)ppdev->pGraphicsDevice)->StateFlags &
- DISPLAY_DEVICE_MIRRORING_DRIVER))
- ret = C1_MIRRORING;
- break;
-
- case BITSPIXEL:
- ret = ppdev->gdiinfo.cBitsPixel;
- break;
-
- case PLANES:
- ret = ppdev->gdiinfo.cPlanes;
- break;
-
- case NUMBRUSHES:
- ret = -1;
- break;
-
- case NUMPENS:
- ret = ppdev->gdiinfo.ulNumColors;
- if ( ret != -1 ) ret *= 5;
- break;
-
- case NUMFONTS:
- ret = IntcFonts(ppdev);
- break;
-
- case NUMCOLORS:
- ret = ppdev->gdiinfo.ulNumColors;
- break;
-
- case ASPECTX:
- ret = ppdev->gdiinfo.ulAspectX;
- break;
-
- case ASPECTY:
- ret = ppdev->gdiinfo.ulAspectY;
- break;
-
- case ASPECTXY:
- ret = ppdev->gdiinfo.ulAspectXY;
- break;
-
- case CLIPCAPS:
- ret = CP_RECTANGLE;
- break;
-
- case SIZEPALETTE:
- ret = ppdev->gdiinfo.ulNumPalReg;
- break;
-
- case NUMRESERVED:
- ret = 20;
- break;
-
- case COLORRES:
- ret = ppdev->gdiinfo.ulDACRed +
- ppdev->gdiinfo.ulDACGreen +
- ppdev->gdiinfo.ulDACBlue;
- break;
-
- case DESKTOPVERTRES:
- ret = ppdev->gdiinfo.ulVertRes;
- break;
-
- case DESKTOPHORZRES:
- ret = ppdev->gdiinfo.ulHorzRes;
- break;
-
- case BLTALIGNMENT:
- ret = ppdev->gdiinfo.ulBltAlignment;
- break;
-
- case SHADEBLENDCAPS:
- ret = ppdev->gdiinfo.flShadeBlend;
- break;
-
- case COLORMGMTCAPS:
- ret = IntGetColorManagementCaps(ppdev);
- break;
-
- case PHYSICALWIDTH:
- ret = ppdev->gdiinfo.szlPhysSize.cx;
- break;
-
- case PHYSICALHEIGHT:
- ret = ppdev->gdiinfo.szlPhysSize.cy;
- break;
-
- case PHYSICALOFFSETX:
- ret = ppdev->gdiinfo.ptlPhysOffset.x;
- break;
-
- case PHYSICALOFFSETY:
- ret = ppdev->gdiinfo.ptlPhysOffset.y;
- break;
-
- case VREFRESH:
- ret = ppdev->gdiinfo.ulVRefresh;
- break;
-
- case RASTERCAPS:
- ret = ppdev->gdiinfo.flRaster;
- break;
-
- case CURVECAPS:
- ret = (CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES | CC_WIDE |
- CC_STYLED | CC_WIDESTYLED | CC_INTERIORS | CC_ROUNDRECT);
- break;
-
- case LINECAPS:
- ret = (LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE |
- LC_STYLED | LC_WIDESTYLED | LC_INTERIORS);
- break;
-
- case POLYGONALCAPS:
- ret = (PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON | PC_SCANLINE |
- PC_WIDE | PC_STYLED | PC_WIDESTYLED | PC_INTERIORS);
- break;
-
- case TEXTCAPS:
- ret = ppdev->gdiinfo.flTextCaps;
- if (ppdev->gdiinfo.ulTechnology) ret |= TC_VA_ABLE;
- ret |= (TC_SO_ABLE|TC_UA_ABLE);
- break;
-
- case PDEVICESIZE:
- case SCALINGFACTORX:
- case SCALINGFACTORY:
- default:
- ret = 0;
- break;
- }
-
- return ret;
- }
-
- INT APIENTRY
- NtGdiGetDeviceCaps(HDC hDC,
- INT Index)
- {
- PDC dc;
- INT ret;
-
- dc = DC_LockDc(hDC);
- if (dc == NULL)
- {
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- return 0;
- }
-
- ret = IntGdiGetDeviceCaps(dc, Index);
-
- DPRINT("(%04x,%d): returning %d\n", hDC, Index, ret);
-
- DC_UnlockDc( dc );
- return ret;
- }
-
- VOID
- FASTCALL
- IntvGetDeviceCaps(
- PPDEVOBJ pDevObj,
- PDEVCAPS pDevCaps)
- {
- ULONG Tmp = 0;
- PGDIINFO pGdiInfo = &pDevObj->gdiinfo;
-
- pDevCaps->ulVersion = pGdiInfo->ulVersion;
- pDevCaps->ulTechnology = pGdiInfo->ulTechnology;
- pDevCaps->ulHorzSizeM = (pGdiInfo->ulHorzSize + 500) / 1000;
- pDevCaps->ulVertSizeM = (pGdiInfo->ulVertSize + 500) / 1000;
- pDevCaps->ulHorzSize = pGdiInfo->ulHorzSize;
- pDevCaps->ulVertSize = pGdiInfo->ulVertSize;
- pDevCaps->ulHorzRes = pGdiInfo->ulHorzRes;
- pDevCaps->ulVertRes = pGdiInfo->ulVertRes;
- pDevCaps->ulVRefresh = pGdiInfo->ulVRefresh;
- pDevCaps->ulDesktopHorzRes = pGdiInfo->ulHorzRes;
- pDevCaps->ulDesktopVertRes = pGdiInfo->ulVertRes;
- pDevCaps->ulBltAlignment = pGdiInfo->ulBltAlignment;
- pDevCaps->ulPlanes = pGdiInfo->cPlanes;
-
- pDevCaps->ulBitsPixel = pGdiInfo->cBitsPixel;
- if (pGdiInfo->cBitsPixel == 15) pDevCaps->ulBitsPixel = 16;
-
- Tmp = pGdiInfo->ulNumColors;
- if ( Tmp != -1 ) Tmp *= 5;
- pDevCaps->ulNumPens = Tmp;
- pDevCaps->ulNumColors = pGdiInfo->ulNumColors;
-
- pDevCaps->ulNumFonts = IntcFonts(pDevObj);
-
- pDevCaps->ulRasterCaps = pGdiInfo->flRaster;
- pDevCaps->ulShadeBlend = pGdiInfo->flShadeBlend;
- pDevCaps->ulAspectX = pGdiInfo->ulAspectX;
- pDevCaps->ulAspectY = pGdiInfo->ulAspectY;
- pDevCaps->ulAspectXY = pGdiInfo->ulAspectXY;
- pDevCaps->ulLogPixelsX = pGdiInfo->ulLogPixelsX;
- pDevCaps->ulLogPixelsY = pGdiInfo->ulLogPixelsY;
- pDevCaps->ulSizePalette = pGdiInfo->ulNumPalReg;
- pDevCaps->ulColorRes = pGdiInfo->ulDACRed + pGdiInfo->ulDACGreen + pGdiInfo->ulDACBlue;
- pDevCaps->ulPhysicalWidth = pGdiInfo->szlPhysSize.cx;
- pDevCaps->ulPhysicalHeight = pGdiInfo->szlPhysSize.cy;
- pDevCaps->ulPhysicalOffsetX = pGdiInfo->ptlPhysOffset.x;
- pDevCaps->ulPhysicalOffsetY = pGdiInfo->ptlPhysOffset.y;
- pDevCaps->ulPanningHorzRes = pGdiInfo->ulPanningHorzRes;
- pDevCaps->ulPanningVertRes = pGdiInfo->ulPanningVertRes;
- pDevCaps->xPanningAlignment = pGdiInfo->xPanningAlignment;
- pDevCaps->yPanningAlignment = pGdiInfo->yPanningAlignment;
-
- Tmp = 0;
- Tmp = pGdiInfo->flTextCaps | (TC_SO_ABLE|TC_UA_ABLE|TC_CP_STROKE|TC_OP_STROKE|TC_OP_CHARACTER);
-
- pDevCaps->ulTextCaps = pGdiInfo->flTextCaps | (TC_SO_ABLE|TC_UA_ABLE|TC_CP_STROKE|TC_OP_STROKE|TC_OP_CHARACTER);
-
- if (pGdiInfo->ulTechnology)
- pDevCaps->ulTextCaps = Tmp | TC_VA_ABLE;
-
- pDevCaps->ulColorMgmtCaps = IntGetColorManagementCaps(pDevObj);
-
- return;
- }
-
- /*
- * @implemented
- */
- BOOL
- APIENTRY
- NtGdiGetDeviceCapsAll (
- IN HDC hDC,
- OUT PDEVCAPS pDevCaps)
- {
- PDC dc;
- PDEVCAPS pSafeDevCaps;
- NTSTATUS Status = STATUS_SUCCESS;
-
- dc = DC_LockDc(hDC);
- if (!dc)
- {
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- return FALSE;
- }
-
- pSafeDevCaps = ExAllocatePoolWithTag(PagedPool, sizeof(DEVCAPS), TAG_TEMP);
-
- if (!pSafeDevCaps)
- {
- DC_UnlockDc(dc);
- return FALSE;
- }
-
- IntvGetDeviceCaps(dc->ppdev, pSafeDevCaps);
-
- _SEH2_TRY
- {
- ProbeForWrite(pDevCaps,
- sizeof(DEVCAPS),
- 1);
- RtlCopyMemory(pDevCaps, pSafeDevCaps, sizeof(DEVCAPS));
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
-
- ExFreePoolWithTag(pSafeDevCaps, TAG_TEMP);
- DC_UnlockDc(dc);
-
- if (!NT_SUCCESS(Status))
- {
- SetLastNtError(Status);
- return FALSE;
- }
- return TRUE;
- }
-
-
- /*
- * @implemented
- */
- DHPDEV
- APIENTRY
- NtGdiGetDhpdev(
- IN HDEV hdev)
- {
- PPDEVOBJ ppdev, pGdiDevice = (PPDEVOBJ) hdev;
- if (!pGdiDevice) return NULL;
- if ( pGdiDevice < (PPDEVOBJ)MmSystemRangeStart) return NULL;
- ppdev = pPrimarySurface;
- IntGdiAcquireSemaphore(hsemDriverMgmt);
- do
- {
- if (pGdiDevice == ppdev) break;
- else
- ppdev = ppdev->ppdevNext;
- }
- while (ppdev != NULL);
- IntGdiReleaseSemaphore(hsemDriverMgmt);
- if (!ppdev) return NULL;
- return pGdiDevice->dhpdev;
- }
-
- static NTSTATUS FASTCALL
- GetVideoRegistryKey(
- OUT PUNICODE_STRING RegistryPath,
- IN PCUNICODE_STRING DeviceName) /* ex: "\Device\Video0" */
- {
- RTL_QUERY_REGISTRY_TABLE QueryTable[2];
- NTSTATUS Status;
-
- RtlInitUnicodeString(RegistryPath, NULL);
- RtlZeroMemory(QueryTable, sizeof(QueryTable));
- QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
- QueryTable[0].Name = DeviceName->Buffer;
- QueryTable[0].EntryContext = RegistryPath;
-
- Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP,
- L"VIDEO",
- QueryTable,
- NULL,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("No %wZ value in DEVICEMAP\\VIDEO found (Status 0x%08lx)\n", DeviceName, Status);
- return STATUS_NO_SUCH_DEVICE;
- }
-
- DPRINT("RegistryPath %wZ\n", RegistryPath);
- return STATUS_SUCCESS;
- }
-
-
- static NTSTATUS FASTCALL
- GetVideoDeviceName(
- OUT PUNICODE_STRING VideoDeviceName,
- IN PCUNICODE_STRING DisplayDevice) /* ex: "\.\DISPLAY1" or "\??\DISPLAY1" */
- {
- UNICODE_STRING Prefix = RTL_CONSTANT_STRING(L"\\??\\");
- UNICODE_STRING ObjectName;
- UNICODE_STRING KernelModeName = { 0, };
- OBJECT_ATTRIBUTES ObjectAttributes;
- USHORT LastSlash;
- ULONG Length;
- HANDLE LinkHandle = NULL;
- NTSTATUS Status;
-
- RtlInitUnicodeString(VideoDeviceName, NULL);
-
- /* Get device name (DisplayDevice is "\.\xxx") */
- for (LastSlash = DisplayDevice->Length / sizeof(WCHAR); LastSlash > 0; LastSlash--)
- {
- if (DisplayDevice->Buffer[LastSlash - 1] == L'\\')
- break;
- }
-
- if (LastSlash == 0)
- {
- DPRINT1("Invalid device name '%wZ'\n", DisplayDevice);
- Status = STATUS_OBJECT_NAME_INVALID;
- goto cleanup;
- }
- ObjectName = *DisplayDevice;
- ObjectName.Length -= LastSlash * sizeof(WCHAR);
- ObjectName.MaximumLength -= LastSlash * sizeof(WCHAR);
- ObjectName.Buffer += LastSlash;
-
- /* Create "\??\xxx" (ex: "\??\DISPLAY1") */
- KernelModeName.MaximumLength = Prefix.Length + ObjectName.Length + sizeof(UNICODE_NULL);
- KernelModeName.Buffer = ExAllocatePoolWithTag(PagedPool,
- KernelModeName.MaximumLength,
- TAG_DC);
- if (!KernelModeName.Buffer)
- {
- Status = STATUS_NO_MEMORY;
- goto cleanup;
- }
- RtlCopyUnicodeString(&KernelModeName, &Prefix);
- Status = RtlAppendUnicodeStringToString(&KernelModeName, &ObjectName);
- if (!NT_SUCCESS(Status))
- goto cleanup;
-
- /* Open \??\xxx (ex: "\??\DISPLAY1") */
- InitializeObjectAttributes(&ObjectAttributes,
- &KernelModeName,
- OBJ_KERNEL_HANDLE,
- NULL,
- NULL);
- Status = ZwOpenSymbolicLinkObject(&LinkHandle,
- GENERIC_READ,
- &ObjectAttributes);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Unable to open symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName, Status);
- Status = STATUS_NO_SUCH_DEVICE;
- goto cleanup;
- }
-
- Status = ZwQuerySymbolicLinkObject(LinkHandle, VideoDeviceName, &Length);
- if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL)
- {
- DPRINT1("Unable to query symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName, Status);
- Status = STATUS_NO_SUCH_DEVICE;
- goto cleanup;
- }
- VideoDeviceName->MaximumLength = Length;
- VideoDeviceName->Buffer = ExAllocatePoolWithTag(PagedPool,
- VideoDeviceName->MaximumLength + sizeof(UNICODE_NULL),
- TAG_DC);
- if (!VideoDeviceName->Buffer)
- {
- Status = STATUS_NO_MEMORY;
- goto cleanup;
- }
- Status = ZwQuerySymbolicLinkObject(LinkHandle, VideoDeviceName, NULL);
- VideoDeviceName->Buffer[VideoDeviceName->MaximumLength / sizeof(WCHAR) - 1] = UNICODE_NULL;
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Unable to query symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName, Status);
- Status = STATUS_NO_SUCH_DEVICE;
- goto cleanup;
- }
- Status = STATUS_SUCCESS;
-
- cleanup:
- if (!NT_SUCCESS(Status) && VideoDeviceName->Buffer)
- ExFreePoolWithTag(VideoDeviceName->Buffer, TAG_DC);
- if (KernelModeName.Buffer)
- ExFreePoolWithTag(KernelModeName.Buffer, TAG_DC);
- if (LinkHandle)
- ZwClose(LinkHandle);
- return Status;
- }
-
- LONG
- FASTCALL
- IntChangeDisplaySettings(
- IN PUNICODE_STRING pDeviceName OPTIONAL,
- IN LPDEVMODEW DevMode,
- IN DWORD dwflags,
- IN PVOID lParam OPTIONAL)
- {
- BOOLEAN NoReset = FALSE;
- BOOLEAN Reset = FALSE;
- LONG Ret = DISP_CHANGE_SUCCESSFUL;
- NTSTATUS Status ;
-
- DPRINT1("display flags : %x\n",dwflags);
-
- if ((dwflags & CDS_UPDATEREGISTRY) == CDS_UPDATEREGISTRY)
- {
- /* Check global, reset and noreset flags */
- if ((dwflags & CDS_GLOBAL) == CDS_GLOBAL)
- DPRINT1("CDS_GLOBAL unhandled");
- if ((dwflags & CDS_NORESET) == CDS_NORESET)
- NoReset = TRUE;
- dwflags &= ~(CDS_GLOBAL | CDS_NORESET);
- }
- if ((dwflags & CDS_RESET) == CDS_RESET)
- Reset = TRUE;
- if ((dwflags & CDS_SET_PRIMARY) == CDS_SET_PRIMARY)
- DPRINT1("CDS_SET_PRIMARY unhandled");
- dwflags &= ~(CDS_RESET | CDS_SET_PRIMARY);
-
- if (Reset && NoReset)
- return DISP_CHANGE_BADFLAGS;
-
- if (dwflags == 0)
- {
- /* Dynamically change graphics mode */
- DPRINT1("flag 0 UNIMPLEMENTED\n");
- SetLastWin32Error(ERROR_CALL_NOT_IMPLEMENTED);
- return DISP_CHANGE_FAILED;
- }
-
- if ((dwflags & CDS_TEST) == CDS_TEST)
- {
- /* Test resolution */
- dwflags &= ~CDS_TEST;
- Status = IntEnumDisplaySettings(pDeviceName, ENUM_REGISTRY_SETTINGS, DevMode, 0);
- if (!NT_SUCCESS(Status))
- Ret = DISP_CHANGE_BADMODE;
- return Ret;
- }
-
- if ((dwflags & CDS_FULLSCREEN) == CDS_FULLSCREEN)
- {
- DEVMODEW lpDevMode;
- /* Full Screen */
- dwflags &= ~CDS_FULLSCREEN;
- DPRINT1("flag CDS_FULLSCREEN partially implemented\n");
- Ret = DISP_CHANGE_FAILED;
-
- RtlZeroMemory(&lpDevMode, sizeof(DEVMODEW));
- lpDevMode.dmSize = sizeof(DEVMODEW);
-
- Status = IntEnumDisplaySettings(pDeviceName, ENUM_CURRENT_SETTINGS, &lpDevMode, 0);
- if (!NT_SUCCESS(Status))
- return DISP_CHANGE_FAILED;
-
- DPRINT1("Req Mode : %d x %d x %d\n", DevMode->dmPelsWidth,DevMode->dmPelsHeight,DevMode->dmBitsPerPel);
- DPRINT1("Current Mode : %d x %d x %d\n", lpDevMode.dmPelsWidth,lpDevMode.dmPelsHeight, lpDevMode.dmBitsPerPel);
-
-
- if ((lpDevMode.dmBitsPerPel == DevMode->dmBitsPerPel) &&
- (lpDevMode.dmPelsWidth == DevMode->dmPelsWidth) &&
- (lpDevMode.dmPelsHeight == DevMode->dmPelsHeight))
- Ret = DISP_CHANGE_SUCCESSFUL;
- }
-
- if ((dwflags & CDS_VIDEOPARAMETERS) == CDS_VIDEOPARAMETERS)
- {
- dwflags &= ~CDS_VIDEOPARAMETERS;
- if (lParam == NULL)
- Ret=DISP_CHANGE_BADPARAM;
- else
- {
- DPRINT1("flag CDS_VIDEOPARAMETERS UNIMPLEMENTED\n");
- Ret = DISP_CHANGE_FAILED;
- SetLastWin32Error(ERROR_CALL_NOT_IMPLEMENTED);
- }
-
- }
-
- if ((dwflags & CDS_UPDATEREGISTRY) == CDS_UPDATEREGISTRY)
- {
-
- UNICODE_STRING DeviceName;
- UNICODE_STRING RegistryKey;
- UNICODE_STRING InDeviceName;
- OBJECT_ATTRIBUTES ObjectAttributes;
- HANDLE DevInstRegKey;
- ULONG NewValue;
-
- DPRINT1("set CDS_UPDATEREGISTRY\n");
-
- dwflags &= ~CDS_UPDATEREGISTRY;
-
- /* Check if pDeviceName is NULL, we need to retrieve it */
- if (pDeviceName == NULL)
- {
- WCHAR szBuffer[MAX_DRIVER_NAME];
- PDC DC;
- PWND Wnd=NULL;
- HWND hWnd;
- HDC hDC;
-
- hWnd = IntGetDesktopWindow();
- if (!(Wnd = UserGetWindowObject(hWnd)))
- {
- return FALSE;
- }
-
- hDC = UserGetWindowDC(Wnd);
-
- DC = DC_LockDc(hDC);
- if (NULL == DC)
- {
- return FALSE;
- }
- swprintf (szBuffer, L"\\\\.\\DISPLAY%lu", DC->ppdev->DisplayNumber);
- DC_UnlockDc(DC);
-
- RtlInitUnicodeString(&InDeviceName, szBuffer);
- pDeviceName = &InDeviceName;
- }
-
- Status = GetVideoDeviceName(&DeviceName, pDeviceName);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Unable to get destination of '%wZ' (Status 0x%08lx)\n", pDeviceName, Status);
- return DISP_CHANGE_FAILED;
- }
- Status = GetVideoRegistryKey(&RegistryKey, &DeviceName);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Unable to get registry key for '%wZ' (Status 0x%08lx)\n", &DeviceName, Status);
- ExFreePoolWithTag(DeviceName.Buffer, TAG_DC);
- return DISP_CHANGE_FAILED;
- }
- ExFreePoolWithTag(DeviceName.Buffer, TAG_DC);
-
- InitializeObjectAttributes(&ObjectAttributes, &RegistryKey,
- OBJ_CASE_INSENSITIVE, NULL, NULL);
- Status = ZwOpenKey(&DevInstRegKey, KEY_SET_VALUE, &ObjectAttributes);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Unable to open registry key %wZ (Status 0x%08lx)\n", &RegistryKey, Status);
- ExFreePoolWithTag(RegistryKey.Buffer, TAG_RTLREGISTRY);
- return DISP_CHANGE_FAILED;
- }
- ExFreePoolWithTag(RegistryKey.Buffer, TAG_RTLREGISTRY);
-
- /* Update needed fields */
- if (NT_SUCCESS(Status) && DevMode->dmFields & DM_BITSPERPEL)
- {
- RtlInitUnicodeString(&RegistryKey, L"DefaultSettings.BitsPerPel");
- NewValue = DevMode->dmBitsPerPel;
- Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue));
- }
-
- if (NT_SUCCESS(Status) && DevMode->dmFields & DM_PELSWIDTH)
- {
- RtlInitUnicodeString(&RegistryKey, L"DefaultSettings.XResolution");
- NewValue = DevMode->dmPelsWidth;
- Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue));
- }
-
- if (NT_SUCCESS(Status) && DevMode->dmFields & DM_PELSHEIGHT)
- {
- RtlInitUnicodeString(&RegistryKey, L"DefaultSettings.YResolution");
- NewValue = DevMode->dmPelsHeight;
- Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue));
- }
-
- if (NT_SUCCESS(Status) && DevMode->dmFields & DM_DISPLAYFREQUENCY)
- {
- RtlInitUnicodeString(&RegistryKey, L"DefaultSettings.VRefresh");
- NewValue = DevMode->dmDisplayFrequency;
- Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue));
- }
-
- ZwClose(DevInstRegKey);
- if (NT_SUCCESS(Status))
- Ret = DISP_CHANGE_RESTART;
- else
- /* return DISP_CHANGE_NOTUPDATED when we can save to reg only valid for NT */
- Ret = DISP_CHANGE_NOTUPDATED;
- }
-
- if (dwflags != 0)
- Ret = DISP_CHANGE_BADFLAGS;
-
- DPRINT("IntChangeDisplaySettings returning %x\n", Ret);
- return Ret;
- }
-
-
-
- #define SIZEOF_DEVMODEW_300 188
- #define SIZEOF_DEVMODEW_400 212
- #define SIZEOF_DEVMODEW_500 220
-
- static NTSTATUS FASTCALL
- GetDisplayNumberFromDeviceName(
- IN PUNICODE_STRING pDeviceName OPTIONAL,
- OUT ULONG *DisplayNumber)
- {
- UNICODE_STRING DisplayString = RTL_CONSTANT_STRING(L"\\\\.\\DISPLAY");
- NTSTATUS Status = STATUS_SUCCESS;
- ULONG Length;
- ULONG Number;
- ULONG i;
-
- if (DisplayNumber == NULL)
- return STATUS_INVALID_PARAMETER_2;
-
- /* Check if DeviceName is valid */
- if (pDeviceName &&
- pDeviceName->Length > 0 && pDeviceName->Length <= DisplayString.Length)
- return STATUS_OBJECT_NAME_INVALID;
-
- if (pDeviceName == NULL || pDeviceName->Length == 0)
- {
- PWND DesktopObject;
- HDC DesktopHDC;
- PDC pDC;
-
- DesktopObject = UserGetDesktopWindow();
- DesktopHDC = UserGetWindowDC(DesktopObject);
- pDC = DC_LockDc(DesktopHDC);
-
- *DisplayNumber = pDC->ppdev->DisplayNumber;
-
- DC_UnlockDc(pDC);
- UserReleaseDC(DesktopObject, DesktopHDC, FALSE);
-
- return STATUS_SUCCESS;
- }
-
- /* Hack to check if the first parts are equal, by faking the device name length */
- Length = pDeviceName->Length;
- pDeviceName->Length = DisplayString.Length;
- if (RtlEqualUnicodeString(&DisplayString, pDeviceName, FALSE) == FALSE)
- Status = STATUS_OBJECT_NAME_INVALID;
- pDeviceName->Length = Length;
-
- if (NT_SUCCESS(Status))
- {
- /* Convert the last part of pDeviceName to a number */
- Number = 0;
- Length = pDeviceName->Length / sizeof(WCHAR);
- for (i = DisplayString.Length / sizeof(WCHAR); i < Length; i++)
- {
- WCHAR Char = pDeviceName->Buffer[i];
- if (Char >= L'0' && Char <= L'9')
- Number = Number * 10 + Char - L'0';
- else if (Char != L'\0')
- return STATUS_OBJECT_NAME_INVALID;
- }
-
- *DisplayNumber = Number - 1;
- }
-
- return Status;
- }
-
- /*! \brief Enumerate possible display settings for the given display...
- *
- * \todo Make thread safe!?
- * \todo Don't ignore pDeviceName
- * \todo Implement non-raw mode (only return settings valid for driver and monitor)
- */
- NTSTATUS
- FASTCALL
- IntEnumDisplaySettings(
- IN PUNICODE_STRING pDeviceName OPTIONAL,
- IN DWORD iModeNum,
- IN OUT LPDEVMODEW pDevMode,
- IN DWORD dwFlags)
- {
- static DEVMODEW *CachedDevModes = NULL, *CachedDevModesEnd = NULL;
- static DWORD SizeOfCachedDevModes = 0;
- static UNICODE_STRING CachedDeviceName;
- PDEVMODEW CachedMode = NULL;
- DEVMODEW DevMode;
- ULONG DisplayNumber;
- NTSTATUS Status;
-
- Status = GetDisplayNumberFromDeviceName(pDeviceName, &DisplayNumber);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- if (pDevMode != NULL)
- {
- DPRINT("DevMode->dmSize = %d\n", pDevMode->dmSize);
- DPRINT("DevMode->dmExtraSize = %d\n", pDevMode->dmDriverExtra);
- if (pDevMode->dmSize != SIZEOF_DEVMODEW_300 &&
- pDevMode->dmSize != SIZEOF_DEVMODEW_400 &&
- pDevMode->dmSize != SIZEOF_DEVMODEW_500)
- {
- return STATUS_BUFFER_TOO_SMALL;
- }
- }
-
- if (iModeNum == ENUM_CURRENT_SETTINGS)
- {
- CachedMode = &PrimarySurface.DMW;
- ASSERT(CachedMode->dmSize > 0);
- }
- else if (iModeNum == ENUM_REGISTRY_SETTINGS)
- {
- RtlZeroMemory(&DevMode, sizeof (DevMode));
- DevMode.dmSize = sizeof (DevMode);
- DevMode.dmDriverExtra = 0;
- if (SetupDevMode(&DevMode, DisplayNumber))
- CachedMode = &DevMode;
- else
- {
- return STATUS_UNSUCCESSFUL; // FIXME: what status?
- }
- /* FIXME: Maybe look for the matching devmode supplied by the
- * driver so we can provide driver private/extra data?
- */
- }
- else
- {
- BOOL IsCachedDevice = (CachedDevModes != NULL);
-
- if (CachedDevModes &&
- ((pDeviceName == NULL && CachedDeviceName.Length > 0) ||
- (pDeviceName != NULL && pDeviceName->Buffer != NULL && CachedDeviceName.Length == 0) ||
- (pDeviceName != NULL && pDeviceName->Buffer != NULL && CachedDeviceName.Length > 0 && RtlEqualUnicodeString(pDeviceName, &CachedDeviceName, TRUE) == FALSE)))
- {
- IsCachedDevice = FALSE;
- }
-
- if (iModeNum == 0 || IsCachedDevice == FALSE) /* query modes from drivers */
- {
- UNICODE_STRING DriverFileNames;
- LPWSTR CurrentName;
- DRVENABLEDATA DrvEnableData;
-
- /* Free resources from last driver cache */
- if (IsCachedDevice == FALSE && CachedDeviceName.Buffer != NULL)
- {
- RtlFreeUnicodeString(&CachedDeviceName);
- }
-
- /* Retrieve DDI driver names from registry */
- RtlInitUnicodeString(&DriverFileNames, NULL);
- if (!FindDriverFileNames(&DriverFileNames, DisplayNumber))
- {
- DPRINT1("FindDriverFileNames failed\n");
- return STATUS_UNSUCCESSFUL;
- }
-
- if (!IntPrepareDriverIfNeeded())
- {
- DPRINT1("IntPrepareDriverIfNeeded failed\n");
- return STATUS_UNSUCCESSFUL;
- }
-
- /*
- * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
- * scan all of them until a good one found.
- */
- CurrentName = DriverFileNames.Buffer;
- for (;CurrentName < DriverFileNames.Buffer + (DriverFileNames.Length / sizeof (WCHAR));
- CurrentName += wcslen(CurrentName) + 1)
- {
- INT i;
- PFN_DrvEnableDriver GDEnableDriver;
- PFN_DrvGetModes GetModes = NULL;
- INT SizeNeeded, SizeUsed;
-
- /* Get the DDI driver's entry point */
- //GDEnableDriver = DRIVER_FindDDIDriver(CurrentName);
- GDEnableDriver = DRIVER_FindExistingDDIDriver(L"DISPLAY");
- if (NULL == GDEnableDriver)
- {
- DPRINT("FindDDIDriver failed for %S\n", CurrentName);
- continue;
- }
-
- /* Call DDI driver's EnableDriver function */
- RtlZeroMemory(&DrvEnableData, sizeof(DrvEnableData));
-
- if (!GDEnableDriver(DDI_DRIVER_VERSION_NT5_01, sizeof (DrvEnableData), &DrvEnableData))
- {
- DPRINT("DrvEnableDriver failed for %S\n", CurrentName);
- continue;
- }
-
- CachedDevModesEnd = CachedDevModes;
-
- /* find DrvGetModes function */
- for (i = 0; i < DrvEnableData.c; i++)
- {
- PDRVFN DrvFn = DrvEnableData.pdrvfn + i;
-
- if (DrvFn->iFunc == INDEX_DrvGetModes)
- {
- GetModes = (PFN_DrvGetModes)DrvFn->pfn;
- break;
- }
- }
-
- if (GetModes == NULL)
- {
- DPRINT("DrvGetModes doesn't exist for %S\n", CurrentName);
- continue;
- }
-
- /* make sure we have enough memory to hold the modes */
- SizeNeeded = GetModes((HANDLE)(PrimarySurface.VideoFileObject->DeviceObject), 0, NULL);
- if (SizeNeeded <= 0)
- {
- DPRINT("DrvGetModes failed for %S\n", CurrentName);
- break;
- }
-
- SizeUsed = (PCHAR)CachedDevModesEnd - (PCHAR)CachedDevModes;
- if (SizeOfCachedDevModes < SizeUsed + SizeNeeded)
- {
- PVOID NewBuffer;
-
- SizeOfCachedDevModes += SizeNeeded;
- NewBuffer = ExAllocatePoolWithTag(PagedPool, SizeOfCachedDevModes, GDITAG_DEVMODE);
- if (NewBuffer == NULL)
- {
- /* clean up */
- ExFreePool(CachedDevModes);
- CachedDevModes = NULL;
- CachedDevModesEnd = NULL;
- SizeOfCachedDevModes = 0;
-
- if (CachedDeviceName.Buffer != NULL)
- RtlFreeUnicodeString(&CachedDeviceName);
-
- return STATUS_NO_MEMORY;
- }
- if (CachedDevModes != NULL)
- {
- RtlCopyMemory(NewBuffer, CachedDevModes, SizeUsed);
- ExFreePool(CachedDevModes);
- }
- CachedDevModes = NewBuffer;
- CachedDevModesEnd = (DEVMODEW *)((PCHAR)NewBuffer + SizeUsed);
- }
-
- if (!IsCachedDevice)
- {
- if (CachedDeviceName.Buffer != NULL)
- RtlFreeUnicodeString(&CachedDeviceName);
-
- if (pDeviceName)
- IntSafeCopyUnicodeString(&CachedDeviceName, pDeviceName);
-
- IsCachedDevice = TRUE;
- }
-
- /* query modes */
- SizeNeeded = GetModes((HANDLE)(PrimarySurface.VideoFileObject->DeviceObject),
- SizeNeeded,
- CachedDevModesEnd);
- if (SizeNeeded <= 0)
- {
- DPRINT("DrvGetModes failed for %S\n", CurrentName);
- }
- else
- {
- CachedDevModesEnd = (DEVMODEW *)((PCHAR)CachedDevModesEnd + SizeNeeded);
- }
- }
-
- ExFreePoolWithTag(DriverFileNames.Buffer, TAG_RTLREGISTRY);
- }
-
- /* return cached info */
- CachedMode = CachedDevModes;
- if (CachedMode >= CachedDevModesEnd)
- {
- return STATUS_NO_MORE_ENTRIES;
- }
- while (iModeNum-- > 0 && CachedMode < CachedDevModesEnd)
- {
- ASSERT(CachedMode->dmSize > 0);
- CachedMode = (DEVMODEW *)((PCHAR)CachedMode + CachedMode->dmSize + CachedMode->dmDriverExtra);
- }
- if (CachedMode >= CachedDevModesEnd)
- {
- return STATUS_NO_MORE_ENTRIES;
- }
- }
-
- ASSERT(CachedMode != NULL);
-
- if (pDevMode != NULL)
- {
- RtlCopyMemory(pDevMode, CachedMode, min(pDevMode->dmSize, CachedMode->dmSize));
- RtlZeroMemory(pDevMode + pDevMode->dmSize, pDevMode->dmDriverExtra);
- RtlCopyMemory(pDevMode + min(pDevMode->dmSize, CachedMode->dmSize), CachedMode + CachedMode->dmSize, min(pDevMode->dmDriverExtra, CachedMode->dmDriverExtra));
- }
-
- return STATUS_SUCCESS;
- }
-
INT
APIENTRY
NtGdiDrawEscape(
return 0;
}
+
{ 0xff, 0xff, 0xff, 0x00 }
};
+ static const RGBTRIPLE EGAColorsTriples[16] = {
+ /* rgbBlue, rgbGreen, rgbRed */
+ { 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x80 },
+ { 0x00, 0x80, 0x00 },
+ { 0x00, 0x80, 0x80 },
+ { 0x80, 0x00, 0x00 },
+ { 0x80, 0x00, 0x80 },
+ { 0x80, 0x80, 0x00 },
+ { 0x80, 0x80, 0x80 },
+ { 0xc0, 0xc0, 0xc0 },
+ { 0x00, 0x00, 0xff },
+ { 0x00, 0xff, 0x00 },
+ { 0x00, 0xff, 0xff },
+ { 0xff, 0x00, 0x00 },
+ { 0xff, 0x00, 0xff },
+ { 0xff, 0xff, 0x00 },
+ { 0xff, 0xff, 0xff }
+ };
+
static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
/* rgbBlue, rgbGreen, rgbRed, rgbReserved */
{ 0x00, 0x00, 0x00, 0x00 },
{ 0xff, 0xff, 0xff, 0x00 }
};
+ static const RGBQUAD DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
+ /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
+ { 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x80 },
+ { 0x00, 0x80, 0x00 },
+ { 0x00, 0x80, 0x80 },
+ { 0x80, 0x00, 0x00 },
+ { 0x80, 0x00, 0x80 },
+ { 0x80, 0x80, 0x00 },
+ { 0xc0, 0xc0, 0xc0 },
+ { 0xc0, 0xdc, 0xc0 },
+ { 0xf0, 0xca, 0xa6 },
+ { 0xf0, 0xfb, 0xff },
+ { 0xa4, 0xa0, 0xa0 },
+ { 0x80, 0x80, 0x80 },
+ { 0x00, 0x00, 0xf0 },
+ { 0x00, 0xff, 0x00 },
+ { 0x00, 0xff, 0xff },
+ { 0xff, 0x00, 0x00 },
+ { 0xff, 0x00, 0xff },
+ { 0xff, 0xff, 0x00 },
+ { 0xff, 0xff, 0xff }
+ };
+
UINT
APIENTRY
if (StartIndex + Entries > (1 << biBitCount))
Entries = (1 << biBitCount) - StartIndex;
- PalGDI = PALETTE_LockPalette(psurf->hDIBPalette);
- if (PalGDI == NULL)
+ if (psurf->ppal == NULL)
{
DC_UnlockDc(dc);
SetLastWin32Error(ERROR_INVALID_HANDLE);
return 0;
}
+ PalGDI = PALETTE_LockPalette(psurf->ppal->BaseObject.hHmgr);
+
for (Index = StartIndex;
Index < StartIndex + Entries && Index < PalGDI->NumColors;
Index++)
if (StartIndex + Entries > (1 << biBitCount))
Entries = (1 << biBitCount) - StartIndex;
- PalGDI = PALETTE_LockPalette(psurf->hDIBPalette);
- if (PalGDI == NULL)
+ if (psurf->ppal == NULL)
{
DC_UnlockDc(dc);
SetLastWin32Error(ERROR_INVALID_HANDLE);
return 0;
}
+ PalGDI = PALETTE_LockPalette(psurf->ppal->BaseObject.hHmgr);
+
for (Index = StartIndex;
Index < StartIndex + Entries && Index < PalGDI->NumColors;
Index++)
CONST BITMAPINFO *bmi,
UINT ColorUse)
{
- SURFACE *bitmap;
HBITMAP SourceBitmap;
+ PSURFACE psurfDst, psurfSrc;
INT result = 0;
- BOOL copyBitsResult;
- SURFOBJ *DestSurf, *SourceSurf;
- SIZEL SourceSize;
- POINTL ZeroPoint;
- RECTL DestRect;
- EXLATEOBJ exlo;
- PPALETTE ppalDDB, ppalDIB;
- //RGBQUAD *lpRGB;
- HPALETTE DDB_Palette, DIB_Palette;
- ULONG DIB_Palette_Type;
- INT DIBWidth;
-
- // Check parameters
- if (!(bitmap = SURFACE_LockSurface(hBitmap)))
- {
- return 0;
- }
-
- // Get RGB values
- //if (ColorUse == DIB_PAL_COLORS)
- // lpRGB = DIB_MapPaletteColors(hDC, bmi);
- //else
- // lpRGB = &bmi->bmiColors;
-
- DestSurf = &bitmap->SurfObj;
+ RECT rcDst;
+ POINTL ptSrc;
+ PVOID pvBits;
+ EXLATEOBJ exlo;
- // Create source surface
- SourceSize.cx = bmi->bmiHeader.biWidth;
- SourceSize.cy = ScanLines;
-
- // Determine width of DIB
- DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount);
-
- SourceBitmap = EngCreateBitmap(SourceSize,
- DIBWidth,
- BitmapFormat(bmi->bmiHeader.biBitCount, bmi->bmiHeader.biCompression),
- bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
- (PVOID) Bits);
- if (0 == SourceBitmap)
+ SourceBitmap = DIB_CreateDIBSection(DC, bmi, ColorUse, &pvBits, NULL, 0, 0);
+ if (0 == SourceBitmap)
{
- SURFACE_UnlockSurface(bitmap);
+ DPRINT1("Error : Could not create a DIBSection.\n");
SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
return 0;
}
- SourceSurf = EngLockSurface((HSURF)SourceBitmap);
- if (NULL == SourceSurf)
- {
- EngDeleteSurface((HSURF)SourceBitmap);
- SURFACE_UnlockSurface(bitmap);
- SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
- return 0;
- }
+ RtlCopyMemory(pvBits, Bits, DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
+ bmi->bmiHeader.biHeight,
+ bmi->bmiHeader.biBitCount));
- // Use hDIBPalette if it exists
- if (bitmap->hDIBPalette)
- {
- DDB_Palette = bitmap->hDIBPalette;
- }
- else
- {
- // Destination palette obtained from the hDC
- DDB_Palette = DC->ppdev->devinfo.hpalDefault;
- }
-
- ppalDDB = PALETTE_LockPalette(DDB_Palette);
- if (NULL == ppalDDB)
- {
- EngUnlockSurface(SourceSurf);
- EngDeleteSurface((HSURF)SourceBitmap);
- SURFACE_UnlockSurface(bitmap);
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- return 0;
- }
-
- // Source palette obtained from the BITMAPINFO
- DIB_Palette = BuildDIBPalette((PBITMAPINFO)bmi, (PINT)&DIB_Palette_Type);
- if (NULL == DIB_Palette)
- {
- EngUnlockSurface(SourceSurf);
- EngDeleteSurface((HSURF)SourceBitmap);
- SURFACE_UnlockSurface(bitmap);
- SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
- return 0;
- }
-
- ppalDIB = PALETTE_LockPalette(DIB_Palette);
-
- /* Initialize XLATEOBJ for color translation */
- EXLATEOBJ_vInitialize(&exlo, ppalDIB, ppalDDB, 0, 0, 0);
+ psurfDst = SURFACE_LockSurface(hBitmap);
+ psurfSrc = SURFACE_LockSurface(SourceBitmap);
- // Zero point
- ZeroPoint.x = 0;
- ZeroPoint.y = 0;
+ if(!(psurfSrc && psurfDst))
+ {
+ DPRINT1("Error, could not lock surfaces\n");
+ goto cleanup;
+ }
- // Determine destination rectangle
- DestRect.left = 0;
- DestRect.top = abs(bmi->bmiHeader.biHeight) - StartScan - ScanLines;
- DestRect.right = SourceSize.cx;
- DestRect.bottom = DestRect.top + ScanLines;
+ rcDst.top = bmi->bmiHeader.biHeight < 0 ?
+ abs(bmi->bmiHeader.biHeight) - (ScanLines + StartScan) : StartScan;
+ rcDst.left = 0;
+ rcDst.bottom = rcDst.top + ScanLines;
+ rcDst.right = psurfDst->SurfObj.sizlBitmap.cx;
- copyBitsResult = IntEngCopyBits(DestSurf, SourceSurf, NULL, &exlo.xlo, &DestRect, &ZeroPoint);
+ ptSrc.x = 0;
+ ptSrc.y = 0;
- // If it succeeded, return number of scanlines copies
- if (copyBitsResult == TRUE)
- {
- result = SourceSize.cy;
- // or
- // result = abs(bmi->bmiHeader.biHeight) - StartScan;
- }
+ EXLATEOBJ_vInitialize(&exlo, psurfSrc->ppal, psurfDst->ppal, 0, 0, 0);
- // Clean up
- EXLATEOBJ_vCleanup(&exlo);
- PALETTE_UnlockPalette(ppalDIB);
- PALETTE_UnlockPalette(ppalDDB);
- PALETTE_FreePaletteByHandle(DIB_Palette);
- EngUnlockSurface(SourceSurf);
- EngDeleteSurface((HSURF)SourceBitmap);
+ result = IntEngCopyBits(&psurfDst->SurfObj,
+ &psurfSrc->SurfObj,
+ NULL,
+ &exlo.xlo,
+ &rcDst,
+ &ptSrc);
+ if(result)
+ result = ScanLines;
- // if (ColorUse == DIB_PAL_COLORS)
- // WinFree((LPSTR)lpRGB);
+ EXLATEOBJ_vCleanup(&exlo);
- SURFACE_UnlockSurface(bitmap);
+ cleanup:
+ if(psurfSrc)
+ {
+ SURFACE_UnlockSurface(psurfSrc);
+ }
+ if(psurfDst)
+ {
+ SURFACE_UnlockSurface(psurfDst);
+ }
+ GreDeleteObject(SourceBitmap);
return result;
}
PDC Dc;
INT Ret;
NTSTATUS Status = STATUS_SUCCESS;
- UINT cjBits;
if (!Bits) return 0;
_SEH2_TRY
- { // FYI: We converted from CORE in gdi.
- ProbeForRead(bmi, sizeof(BITMAPINFO), 1);
- cjBits = bmi->bmiHeader.biBitCount * bmi->bmiHeader.biPlanes * bmi->bmiHeader.biWidth;
- cjBits = ((cjBits + 31) & ~31) / 8;
- cjBits *= ScanLines;
- ProbeForRead(Bits, cjBits, 1);
+ {
+ ProbeForRead(&bmi->bmiHeader.biSize, sizeof(DWORD), 1);
+ ProbeForRead(bmi, bmi->bmiHeader.biSize, 1);
+ ProbeForRead(bmi, DIB_BitmapInfoSize(bmi, ColorUse), 1);
+ ProbeForRead(Bits,
+ DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
+ ScanLines,
+ bmi->bmiHeader.biBitCount),
+ 1);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
INT DIBWidth;
SIZEL SourceSize;
EXLATEOBJ exlo;
- PPALETTE ppalDDB = NULL, ppalDIB = NULL;
- HPALETTE hpalDDB, hpalDIB = NULL;
- ULONG DIBPaletteType;
+ PPALETTE ppalDIB = NULL;
+ HPALETTE hpalDIB = NULL;
if (!Bits) return 0;
_SEH2_TRY
{
- ProbeForRead(bmi, cjMaxInfo , 1);
+ ProbeForRead(bmi, cjMaxInfo, 1);
ProbeForRead(Bits, cjMaxBits, 1);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
return 0;
}
- /* Use destination palette obtained from the DC by default */
- hpalDDB = pDC->ppdev->devinfo.hpalDefault;
-
- /* Try to use hDIBPalette if it exists */
pSurf = pDC->dclevel.pSurface;
- if (pSurf && pSurf->hDIBPalette)
- {
- hpalDDB = pSurf->hDIBPalette;
- }
pDestSurf = pSurf ? &pSurf->SurfObj : NULL;
SourceSize.cx = bmi->bmiHeader.biWidth;
SourceSize.cy = ScanLines;
- DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount);
+ DIBWidth = WIDTH_BYTES_ALIGN32(SourceSize.cx, bmi->bmiHeader.biBitCount);
hSourceBitmap = EngCreateBitmap(SourceSize,
DIBWidth,
- BitmapFormat(bmi->bmiHeader.biBitCount, bmi->bmiHeader.biCompression),
+ BitmapFormat(bmi->bmiHeader.biBitCount,
+ bmi->bmiHeader.biCompression),
bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
(PVOID) Bits);
if (!hSourceBitmap)
goto Exit;
}
- /* Obtain destination palette */
- ppalDDB = PALETTE_LockPalette(hpalDDB);
- if (!ppalDDB)
- {
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- Status = STATUS_UNSUCCESSFUL;
- goto Exit;
- }
+ ASSERT(pSurf->ppal);
/* Create a palette for the DIB */
- hpalDIB = BuildDIBPalette(bmi, (PINT)&DIBPaletteType);
+ hpalDIB = BuildDIBPalette(bmi);
if (!hpalDIB)
{
SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
/* Lock the DIB palette */
ppalDIB = PALETTE_LockPalette(hpalDIB);
- if (!ppalDDB)
+ if (!ppalDIB)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
Status = STATUS_UNSUCCESSFUL;
}
/* Initialize EXLATEOBJ */
- EXLATEOBJ_vInitialize(&exlo, ppalDIB, ppalDDB, 0, 0, 0);
+ EXLATEOBJ_vInitialize(&exlo, ppalDIB, pSurf->ppal, 0, 0, 0);
/* Copy the bits */
DPRINT("BitsToDev with dstsurf=(%d|%d) (%d|%d), src=(%d|%d) w=%d h=%d\n",
}
if (ppalDIB) PALETTE_UnlockPalette(ppalDIB);
- if (ppalDDB) PALETTE_UnlockPalette(ppalDDB);
if (pSourceSurf) EngUnlockSurface(pSourceSurf);
if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
UINT MaxBits,
UINT MaxInfo)
{
- PDC Dc;
- SURFACE *psurf = NULL;
- HBITMAP hDestBitmap = NULL;
- HPALETTE hSourcePalette = NULL;
- HPALETTE hDestPalette = NULL;
- PPALETTE ppalSrc = NULL;
- PPALETTE ppalDst = NULL;
- NTSTATUS Status = STATUS_SUCCESS;
- ULONG Result = 0;
- BOOL bPaletteMatch = FALSE;
- PBYTE ChkBits = Bits;
- PVOID ColorPtr;
- RGBQUAD *rgbQuads;
- ULONG DestPaletteType;
- ULONG Index;
+ BITMAPCOREINFO* pbmci = NULL;
+ PSURFACE psurf = NULL;
+ PDC pDC;
+ LONG width, height;
+ WORD planes, bpp;
+ DWORD compr, size ;
+ int i, bitmap_type;
+ RGBTRIPLE* rgbTriples;
+ RGBQUAD* rgbQuads;
+ VOID* colorPtr;
+ NTSTATUS Status = STATUS_SUCCESS;
DPRINT("Entered NtGdiGetDIBitsInternal()\n");
if ((Usage && Usage != DIB_PAL_COLORS) || !Info || !hBitmap)
return 0;
- // if ScanLines == 0, no need to copy Bits.
- if (!ScanLines)
- ChkBits = NULL;
-
_SEH2_TRY
{
- ProbeForRead(&Info->bmiHeader.biSize, sizeof(DWORD), 1);
-
- ProbeForWrite(Info, Info->bmiHeader.biSize, 1); // Comp for Core.
- if (ChkBits) ProbeForWrite(ChkBits, MaxBits, 1);
+ /* Probe for read and write */
+ ProbeForRead(Info, MaxInfo, 1);
+ ProbeForWrite(Info, MaxInfo, 1);
+ if (Bits) ProbeForWrite(Bits, MaxBits, 1);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
return 0;
}
- Dc = DC_LockDc(hDC);
- if (Dc == NULL) return 0;
- if (Dc->dctype == DC_TYPE_INFO)
+ colorPtr = (LPBYTE)Info + Info->bmiHeader.biSize;
+ rgbTriples = colorPtr;
+ rgbQuads = colorPtr;
+
+ bitmap_type = DIB_GetBitmapInfo(&Info->bmiHeader,
+ &width,
+ &height,
+ &planes,
+ &bpp,
+ &compr,
+ &size);
+ if(bitmap_type == -1)
+ {
+ DPRINT("Wrong bitmap format\n");
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+ else if(bitmap_type == 0)
+ {
+ /* We need a BITMAPINFO to create a DIB, but we have to fill
+ * the BITMAPCOREINFO we're provided */
+ pbmci = (BITMAPCOREINFO*)Info;
+ Info = DIB_ConvertBitmapInfo((BITMAPINFO*)pbmci, Usage);
+ if(Info == NULL)
+ {
+ DPRINT1("Error, could not convert the BITMAPCOREINFO!\n");
+ return 0;
+ }
+ rgbQuads = Info->bmiColors;
+ }
+
+ pDC = DC_LockDc(hDC);
+ if (pDC == NULL || pDC->dctype == DC_TYPE_INFO)
{
- DC_UnlockDc(Dc);
- return 0;
+ ScanLines = 0;
+ goto done;
}
- DC_UnlockDc(Dc);
/* Get a pointer to the source bitmap object */
psurf = SURFACE_LockSurface(hBitmap);
if (psurf == NULL)
- return 0;
-
- hSourcePalette = psurf->hDIBPalette;
- if (!hSourcePalette)
- {
- hSourcePalette = pPrimarySurface->devinfo.hpalDefault;
- }
-
- ColorPtr = ((PBYTE)Info + Info->bmiHeader.biSize);
- rgbQuads = (RGBQUAD *)ColorPtr;
-
- /* Copy palette information
- * Always create a palette for 15 & 16 bit. */
- if ((Info->bmiHeader.biBitCount == BitsPerFormat(psurf->SurfObj.iBitmapFormat) &&
- Info->bmiHeader.biBitCount != 15 && Info->bmiHeader.biBitCount != 16) ||
- !ChkBits)
{
- hDestPalette = hSourcePalette;
- bPaletteMatch = TRUE;
- }
- else
- hDestPalette = BuildDIBPalette(Info, (PINT)&DestPaletteType); //hDestPalette = Dc->DevInfo->hpalDefault;
-
- ppalSrc = PALETTE_LockPalette(hSourcePalette);
- /* FIXME - ppalSrc can be NULL!!! Don't assert here! */
- ASSERT(ppalSrc);
-
- if (!bPaletteMatch)
- {
- ppalDst = PALETTE_LockPalette(hDestPalette);
- /* FIXME - ppalDst can be NULL!!!! Don't assert here!!! */
- DPRINT("ppalDst : %p\n", ppalDst);
- ASSERT(ppalDst);
- }
- else
- {
- ppalDst = ppalSrc;
- }
-
- /* Copy palette. */
- /* FIXME: This is largely incomplete. ATM no Core!*/
- switch (Info->bmiHeader.biBitCount)
- {
- case 1:
- case 4:
- case 8:
- Info->bmiHeader.biClrUsed = 0;
- if (psurf->hSecure &&
- BitsPerFormat(psurf->SurfObj.iBitmapFormat) == Info->bmiHeader.biBitCount)
- {
- if (Usage == DIB_RGB_COLORS)
- {
- if (ppalDst->NumColors != 1 << Info->bmiHeader.biBitCount)
- Info->bmiHeader.biClrUsed = ppalDst->NumColors;
- for (Index = 0;
- Index < (1 << Info->bmiHeader.biBitCount) && Index < ppalDst->NumColors;
- Index++)
- {
- rgbQuads[Index].rgbRed = ppalDst->IndexedColors[Index].peRed;
- rgbQuads[Index].rgbGreen = ppalDst->IndexedColors[Index].peGreen;
- rgbQuads[Index].rgbBlue = ppalDst->IndexedColors[Index].peBlue;
- rgbQuads[Index].rgbReserved = 0;
- }
- }
- else
- {
- PWORD Ptr = ColorPtr;
- for (Index = 0;
- Index < (1 << Info->bmiHeader.biBitCount);
- Index++)
+ ScanLines = 0;
+ goto done;
+ }
+
+ /* Fill in the structure */
+ switch(bpp)
+ {
+ case 0: /* Only info */
+ if(pbmci)
+ {
+ pbmci->bmciHeader.bcWidth = psurf->SurfObj.sizlBitmap.cx;
+ pbmci->bmciHeader.bcHeight = (psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ?
+ -psurf->SurfObj.sizlBitmap.cy :
+ psurf->SurfObj.sizlBitmap.cy;
+ pbmci->bmciHeader.bcPlanes = 1;
+ pbmci->bmciHeader.bcBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
+ }
+ Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
+ Info->bmiHeader.biHeight = (psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ?
+ -psurf->SurfObj.sizlBitmap.cy :
+ psurf->SurfObj.sizlBitmap.cy;;
+ Info->bmiHeader.biPlanes = 1;
+ Info->bmiHeader.biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
+ Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( Info->bmiHeader.biWidth,
+ Info->bmiHeader.biHeight,
+ Info->bmiHeader.biBitCount);
+ if(psurf->hSecure)
+ {
+ switch(Info->bmiHeader.biBitCount)
+ {
+ case 16:
+ case 32:
+ Info->bmiHeader.biCompression = BI_BITFIELDS;
+ break;
+ default:
+ Info->bmiHeader.biCompression = BI_RGB;
+ break;
+ }
+ }
+ else if(Info->bmiHeader.biBitCount > 8)
+ {
+ Info->bmiHeader.biCompression = BI_BITFIELDS;
+ }
+ else
+ {
+ Info->bmiHeader.biCompression = BI_RGB;
+ }
+ Info->bmiHeader.biXPelsPerMeter = 0;
+ Info->bmiHeader.biYPelsPerMeter = 0;
+ Info->bmiHeader.biClrUsed = 0;
+ Info->bmiHeader.biClrImportant = 0;
+ ScanLines = abs(Info->bmiHeader.biHeight);
+ goto done;
+
+ case 1:
+ case 4:
+ case 8:
+ Info->bmiHeader.biClrUsed = 0;
+
+ /* If the bitmap if a DIB section and has the same format than what
+ * we're asked, go ahead! */
+ if((psurf->hSecure) &&
+ (BitsPerFormat(psurf->SurfObj.iBitmapFormat) == bpp))
+ {
+ if(Usage == DIB_RGB_COLORS)
+ {
+ unsigned int colors = min(psurf->ppal->NumColors, 1 << bpp);
+
+ if(pbmci)
+ {
+ for(i=0; i < colors; i++)
+ {
+ rgbTriples[i].rgbtRed = psurf->ppal->IndexedColors[i].peRed;
+ rgbTriples[i].rgbtGreen = psurf->ppal->IndexedColors[i].peGreen;
+ rgbTriples[i].rgbtBlue = psurf->ppal->IndexedColors[i].peBlue;
+ }
+ }
+ if(colors != 1 << bpp) Info->bmiHeader.biClrUsed = colors;
+ for(i=0; i < colors; i++)
+ {
+ rgbQuads[i].rgbRed = psurf->ppal->IndexedColors[i].peRed;
+ rgbQuads[i].rgbGreen = psurf->ppal->IndexedColors[i].peGreen;
+ rgbQuads[i].rgbBlue = psurf->ppal->IndexedColors[i].peBlue;
+ }
+ }
+ else
+ {
+ for(i=0; i < 1 << bpp; i++)
+ {
+ if(pbmci) ((WORD*)rgbTriples)[i] = i;
+ ((WORD*)rgbQuads)[i] = i;
+ }
+ }
+ }
+ else
+ {
+ if(Usage == DIB_PAL_COLORS)
+ {
+ for(i=0; i < 1 << bpp; i++)
+ {
+ if(pbmci) ((WORD*)rgbTriples)[i] = i;
+ ((WORD*)rgbQuads)[i] = i;
+ }
+ }
+ else if(bpp > 1 && bpp == BitsPerFormat(psurf->SurfObj.iBitmapFormat)) {
+ /* For color DDBs in native depth (mono DDBs always have
+ a black/white palette):
+ Generate the color map from the selected palette */
+ PPALETTE pDcPal = PALETTE_LockPalette(pDC->dclevel.hpal);
+ if(!pDcPal)
+ {
+ ScanLines = 0 ;
+ goto done ;
+ }
+ for (i = 0; i < pDcPal->NumColors; i++) {
+ if (pbmci)
{
- Ptr[Index] = (WORD)Index;
+ rgbTriples[i].rgbtRed = pDcPal->IndexedColors[i].peRed;
+ rgbTriples[i].rgbtGreen = pDcPal->IndexedColors[i].peGreen;
+ rgbTriples[i].rgbtBlue = pDcPal->IndexedColors[i].peBlue;
}
- }
- }
- else
- {
- if (Usage == DIB_PAL_COLORS)
- {
- PWORD Ptr = ColorPtr;
- for (Index = 0;
- Index < (1 << Info->bmiHeader.biBitCount);
- Index++)
- {
- Ptr[Index] = (WORD)Index;
- }
- }
- else if (Info->bmiHeader.biBitCount > 1 && bPaletteMatch)
- {
- for (Index = 0;
- Index < (1 << Info->bmiHeader.biBitCount) && Index < ppalDst->NumColors;
- Index++)
+
+ rgbQuads[i].rgbRed = pDcPal->IndexedColors[i].peRed;
+ rgbQuads[i].rgbGreen = pDcPal->IndexedColors[i].peGreen;
+ rgbQuads[i].rgbBlue = pDcPal->IndexedColors[i].peBlue;
+ rgbQuads[i].rgbReserved = 0;
+ }
+ PALETTE_UnlockPalette(pDcPal);
+ } else {
+ switch (bpp) {
+ case 1:
+ if (pbmci)
{
- Info->bmiColors[Index].rgbRed = ppalDst->IndexedColors[Index].peRed;
- Info->bmiColors[Index].rgbGreen = ppalDst->IndexedColors[Index].peGreen;
- Info->bmiColors[Index].rgbBlue = ppalDst->IndexedColors[Index].peBlue;
- Info->bmiColors[Index].rgbReserved = 0;
+ rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
+ rgbTriples[0].rgbtBlue = 0;
+ rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
+ rgbTriples[1].rgbtBlue = 0xff;
}
- }
- else
- {
- switch (Info->bmiHeader.biBitCount)
+ rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
+ rgbQuads[0].rgbBlue = 0;
+ rgbQuads[0].rgbReserved = 0;
+ rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
+ rgbQuads[1].rgbBlue = 0xff;
+ rgbQuads[1].rgbReserved = 0;
+ break;
+
+ case 4:
+ if (pbmci)
+ RtlCopyMemory(rgbTriples, EGAColorsTriples, sizeof(EGAColorsTriples));
+ RtlCopyMemory(rgbQuads, EGAColorsQuads, sizeof(EGAColorsQuads));
+
+ break;
+
+ case 8:
{
- case 1:
- rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen = rgbQuads[0].rgbBlue = 0;
- rgbQuads[0].rgbReserved = 0;
- rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen = rgbQuads[1].rgbBlue = 0xff;
- rgbQuads[1].rgbReserved = 0;
- break;
- case 4:
- RtlCopyMemory(ColorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
- break;
- case 8:
+ INT r, g, b;
+ RGBQUAD *color;
+ if (pbmci)
{
- INT r, g, b;
- RGBQUAD *color;
-
- RtlCopyMemory(rgbQuads, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
- RtlCopyMemory(rgbQuads + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
- color = rgbQuads + 10;
- for (r = 0; r <= 5; r++) /* FIXME */
- for (g = 0; g <= 5; g++)
- for (b = 0; b <= 5; b++)
- {
- color->rgbRed = (r * 0xff) / 5;
- color->rgbGreen = (g * 0xff) / 5;
- color->rgbBlue = (b * 0xff) / 5;
- color->rgbReserved = 0;
+ RGBTRIPLE *colorTriple;
+
+ RtlCopyMemory(rgbTriples, DefLogPaletteTriples,
+ 10 * sizeof(RGBTRIPLE));
+ RtlCopyMemory(rgbTriples + 246, DefLogPaletteTriples + 10,
+ 10 * sizeof(RGBTRIPLE));
+ colorTriple = rgbTriples + 10;
+ for(r = 0; r <= 5; r++) /* FIXME */
+ {
+ for(g = 0; g <= 5; g++)
+ {
+ for(b = 0; b <= 5; b++)
+ {
+ colorTriple->rgbtRed = (r * 0xff) / 5;
+ colorTriple->rgbtGreen = (g * 0xff) / 5;
+ colorTriple->rgbtBlue = (b * 0xff) / 5;
color++;
}
+ }
+ }
}
- break;
+ memcpy(rgbQuads, DefLogPaletteQuads,
+ 10 * sizeof(RGBQUAD));
+ memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
+ 10 * sizeof(RGBQUAD));
+ color = rgbQuads + 10;
+ for(r = 0; r <= 5; r++) /* FIXME */
+ {
+ for(g = 0; g <= 5; g++)
+ {
+ for(b = 0; b <= 5; b++)
+ {
+ color->rgbRed = (r * 0xff) / 5;
+ color->rgbGreen = (g * 0xff) / 5;
+ color->rgbBlue = (b * 0xff) / 5;
+ color->rgbReserved = 0;
+ color++;
+ }
+ }
+ }
}
}
}
+ }
+ break;
- case 15:
- if (Info->bmiHeader.biCompression == BI_BITFIELDS)
- {
- ((PDWORD)Info->bmiColors)[0] = 0x7c00;
- ((PDWORD)Info->bmiColors)[1] = 0x03e0;
- ((PDWORD)Info->bmiColors)[2] = 0x001f;
- }
- break;
+ case 15:
+ if (Info->bmiHeader.biCompression == BI_BITFIELDS)
+ {
+ ((PDWORD)Info->bmiColors)[0] = 0x7c00;
+ ((PDWORD)Info->bmiColors)[1] = 0x03e0;
+ ((PDWORD)Info->bmiColors)[2] = 0x001f;
+ }
+ break;
- case 16:
- if (Info->bmiHeader.biCompression == BI_BITFIELDS)
+ case 16:
+ if (Info->bmiHeader.biCompression == BI_BITFIELDS)
+ {
+ if (psurf->hSecure)
+ {
+ ((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask;
+ ((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask;
+ ((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask;
+ }
+ else
{
((PDWORD)Info->bmiColors)[0] = 0xf800;
((PDWORD)Info->bmiColors)[1] = 0x07e0;
((PDWORD)Info->bmiColors)[2] = 0x001f;
}
- break;
+ }
+ break;
- case 24:
- case 32:
- if (Info->bmiHeader.biCompression == BI_BITFIELDS)
+ case 24:
+ case 32:
+ if (Info->bmiHeader.biCompression == BI_BITFIELDS)
+ {
+ if (psurf->hSecure)
+ {
+ ((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask;
+ ((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask;
+ ((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask;
+ }
+ else
{
((PDWORD)Info->bmiColors)[0] = 0xff0000;
((PDWORD)Info->bmiColors)[1] = 0x00ff00;
((PDWORD)Info->bmiColors)[2] = 0x0000ff;
}
- break;
- }
-
- if (!bPaletteMatch)
- PALETTE_UnlockPalette(ppalDst);
-
- /* fill out the BITMAPINFO struct */
- if (!ChkBits)
- { // Core or not to Core? We have converted from Core in Gdi~ so?
- if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
- {
- BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) Info;
- coreheader->bcWidth = psurf->SurfObj.sizlBitmap.cx;
- coreheader->bcPlanes = 1;
- coreheader->bcBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
- coreheader->bcHeight = psurf->SurfObj.sizlBitmap.cy;
- if (psurf->SurfObj.lDelta > 0)
- coreheader->bcHeight = -coreheader->bcHeight;
- }
-
- if (Info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER))
- {
- Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
- Info->bmiHeader.biHeight = psurf->SurfObj.sizlBitmap.cy;
- Info->bmiHeader.biPlanes = 1;
- Info->bmiHeader.biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
- switch (psurf->SurfObj.iBitmapFormat)
- {
- /* FIXME: What about BI_BITFIELDS? */
- case BMF_1BPP:
- case BMF_4BPP:
- case BMF_8BPP:
- case BMF_16BPP:
- case BMF_24BPP:
- case BMF_32BPP:
- Info->bmiHeader.biCompression = BI_RGB;
- break;
- case BMF_4RLE:
- Info->bmiHeader.biCompression = BI_RLE4;
- break;
- case BMF_8RLE:
- Info->bmiHeader.biCompression = BI_RLE8;
- break;
- case BMF_JPEG:
- Info->bmiHeader.biCompression = BI_JPEG;
- break;
- case BMF_PNG:
- Info->bmiHeader.biCompression = BI_PNG;
- break;
- }
- /* Image size has to be calculated */
- Info->bmiHeader.biSizeImage = DIB_GetDIBWidthBytes(Info->bmiHeader.biWidth,
- Info->bmiHeader.biBitCount) * Info->bmiHeader.biHeight;
- Info->bmiHeader.biXPelsPerMeter = 0; /* FIXME */
- Info->bmiHeader.biYPelsPerMeter = 0; /* FIXME */
- Info->bmiHeader.biClrUsed = 0;
- Info->bmiHeader.biClrImportant = 1 << Info->bmiHeader.biBitCount; /* FIXME */
- /* Report negtive height for top-down bitmaps. */
- if (psurf->SurfObj.lDelta > 0)
- Info->bmiHeader.biHeight = -Info->bmiHeader.biHeight;
}
- Result = psurf->SurfObj.sizlBitmap.cy;
- }
- else
- {
- SIZEL DestSize;
- POINTL SourcePoint;
-
- //
- // If we have a good dib pointer, why not just copy bits from there w/o XLATE'ing them.
- //
- /* Create the destination bitmap too for the copy operation */
- if (StartScan > psurf->SurfObj.sizlBitmap.cy)
+ break;
+ }
+ Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(width, height, bpp);
+
+ if(Bits && ScanLines)
+ {
+ /* Create a DIBSECTION, blt it, profit */
+ PVOID pDIBits ;
+ HBITMAP hBmpDest;
+ PSURFACE psurfDest;
+ EXLATEOBJ exlo;
+ RECT rcDest;
+ POINTL srcPoint;
+ BOOL ret ;
+
+ if (StartScan > psurf->SurfObj.sizlBitmap.cy)
{
- goto cleanup;
+ ScanLines = 0;
+ goto done;
}
else
{
ScanLines = min(ScanLines, psurf->SurfObj.sizlBitmap.cy - StartScan);
- DestSize.cx = psurf->SurfObj.sizlBitmap.cx;
- DestSize.cy = ScanLines;
-
- hDestBitmap = NULL;
-
- if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
- {
- BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) Info;
- hDestBitmap = EngCreateBitmap(DestSize,
- DIB_GetDIBWidthBytes(DestSize.cx, coreheader->bcBitCount),
- BitmapFormat(coreheader->bcBitCount, BI_RGB),
- 0 < coreheader->bcHeight ? 0 : BMF_TOPDOWN,
- Bits);
- }
-
- if (Info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER))
- {
- Info->bmiHeader.biSizeImage = DIB_GetDIBWidthBytes(DestSize.cx,
- Info->bmiHeader.biBitCount) * DestSize.cy;
-
- hDestBitmap = EngCreateBitmap(DestSize,
- DIB_GetDIBWidthBytes(DestSize.cx, Info->bmiHeader.biBitCount),
- BitmapFormat(Info->bmiHeader.biBitCount, Info->bmiHeader.biCompression),
- 0 < Info->bmiHeader.biHeight ? 0 : BMF_TOPDOWN,
- Bits);
- }
-
- if (hDestBitmap == NULL)
- goto cleanup;
- }
-
- if (NT_SUCCESS(Status))
- {
- EXLATEOBJ exlo;
- SURFOBJ *DestSurfObj;
- RECTL DestRect;
-
- EXLATEOBJ_vInitialize(&exlo, ppalSrc, ppalDst, 0, 0, 0);
-
- SourcePoint.x = 0;
- SourcePoint.y = psurf->SurfObj.sizlBitmap.cy - (StartScan + ScanLines);
-
- /* Determine destination rectangle */
- DestRect.top = 0;
- DestRect.left = 0;
- DestRect.right = DestSize.cx;
- DestRect.bottom = DestSize.cy;
-
- DestSurfObj = EngLockSurface((HSURF)hDestBitmap);
-
- if (IntEngCopyBits(DestSurfObj,
- &psurf->SurfObj,
- NULL,
- &exlo.xlo,
- &DestRect,
- &SourcePoint))
- {
- DPRINT("GetDIBits %d \n",abs(Info->bmiHeader.biHeight) - StartScan);
- Result = ScanLines;
- }
-
- EXLATEOBJ_vCleanup(&exlo);
- EngUnlockSurface(DestSurfObj);
- }
- }
- cleanup:
- PALETTE_UnlockPalette(ppalSrc);
-
- if (hDestBitmap != NULL)
- EngDeleteSurface((HSURF)hDestBitmap);
-
- if (hDestPalette != NULL && bPaletteMatch == FALSE)
- PALETTE_FreePaletteByHandle(hDestPalette);
-
- SURFACE_UnlockSurface(psurf);
-
- DPRINT("leaving NtGdiGetDIBitsInternal\n");
-
- return Result;
+ }
+
+ /* Fixup values */
+ Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
+ Info->bmiHeader.biHeight = height < 0 ?
+ -ScanLines : ScanLines;
+ /* Create the DIB */
+ hBmpDest = DIB_CreateDIBSection(pDC, Info, Usage, &pDIBits, NULL, 0, 0);
+ /* Restore them */
+ Info->bmiHeader.biWidth = width;
+ Info->bmiHeader.biHeight = height;
+
+ if(!hBmpDest)
+ {
+ DPRINT1("Unable to create a DIB Section!\n");
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ ScanLines = 0;
+ goto done ;
+ }
+
+ psurfDest = SURFACE_LockSurface(hBmpDest);
+
+ rcDest.left = 0;
+ rcDest.top = 0;
+ rcDest.bottom = ScanLines;
+ rcDest.right = psurf->SurfObj.sizlBitmap.cx;
+
+ srcPoint.x = 0;
+ srcPoint.y = height < 0 ?
+ psurf->SurfObj.sizlBitmap.cy - (StartScan + ScanLines) : StartScan;
+
+ EXLATEOBJ_vInitialize(&exlo, psurf->ppal, psurfDest->ppal, 0, 0, 0);
+
+ ret = IntEngCopyBits(&psurfDest->SurfObj,
+ &psurf->SurfObj,
+ NULL,
+ &exlo.xlo,
+ &rcDest,
+ &srcPoint);
+
+ if(!ret)
+ ScanLines = 0;
+ else
+ {
+ Status = STATUS_SUCCESS;
+ _SEH2_TRY
+ {
+ RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, height, bpp));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END
+
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("Unable to copy bits to the user provided pointer\n");
+ ScanLines = 0;
+ }
+ }
+
+ GreDeleteObject(hBmpDest);
+ EXLATEOBJ_vCleanup(&exlo);
+ }
+ else ScanLines = abs(height);
+
+ done:
+
+ if(pDC) DC_UnlockDc(pDC);
+ if(psurf) SURFACE_UnlockSurface(psurf);
+ if(pbmci) DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci);
+
+ return ScanLines;
}
+
INT
APIENTRY
NtGdiStretchDIBitsInternal(
UINT cjMaxBits,
HANDLE hcmXform)
{
- HBITMAP hBitmap, hOldBitmap = NULL;
- HDC hdcMem;
- HPALETTE hPal = NULL;
- PDC pDC;
- BOOL Hit = FALSE;
+ PDC pdc;
+ INT ret = 0;
+ LONG height;
+ LONG width;
+ WORD planes, bpp;
+ DWORD compr, size;
+ HBITMAP hBitmap;
+ BOOL fastpath = FALSE;
+ NTSTATUS Status = STATUS_SUCCESS;
+ PBYTE safeBits ;
if (!Bits || !BitsInfo)
- {
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
return 0;
- }
+
+ safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
+ if(!safeBits)
+ {
+ SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ return 0;
+ }
+
+ if (!(pdc = DC_LockDc(hDC)))
+ {
+ ExFreePoolWithTag(safeBits, TAG_DIB);
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ return 0;
+ }
_SEH2_TRY
{
ProbeForRead(BitsInfo, cjMaxInfo, 1);
ProbeForRead(Bits, cjMaxBits, 1);
+ if (DIB_GetBitmapInfo( &BitsInfo->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
+ {
+ DPRINT1("Invalid bitmap\n");
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ RtlCopyMemory(safeBits, Bits, cjMaxBits);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- Hit = TRUE;
+ Status = _SEH2_GetExceptionCode();
}
_SEH2_END
- if (Hit)
- {
- DPRINT1("NtGdiStretchDIBitsInternal fail to read BitMapInfo: %x or Bits: %x\n",BitsInfo,Bits);
- return 0;
- }
-
- hdcMem = NtGdiCreateCompatibleDC(hDC);
- if (hdcMem == NULL)
+ if(!NT_SUCCESS(Status))
{
- DPRINT1("NtGdiCreateCompatibleDC fail create hdc\n");
- return 0;
+ DPRINT1("Error, failed to read the DIB bits\n");
+ goto cleanup;
}
- hBitmap = NtGdiCreateCompatibleBitmap(hDC,
- abs(BitsInfo->bmiHeader.biWidth),
- abs(BitsInfo->bmiHeader.biHeight));
- if (hBitmap == NULL)
+ if (width < 0)
{
- DPRINT1("NtGdiCreateCompatibleBitmap fail create bitmap\n");
- DPRINT1("hDC : 0x%08x \n", hDC);
- DPRINT1("BitsInfo->bmiHeader.biWidth : 0x%08x \n", BitsInfo->bmiHeader.biWidth);
- DPRINT1("BitsInfo->bmiHeader.biHeight : 0x%08x \n", BitsInfo->bmiHeader.biHeight);
+ DPRINT1("Bitmap has a negative width\n");
return 0;
}
- /* Select the bitmap into hdcMem, and save a handle to the old bitmap */
- hOldBitmap = NtGdiSelectBitmap(hdcMem, hBitmap);
+ hBitmap = NtGdiGetDCObject(hDC, OBJ_BITMAP);
- if (Usage == DIB_PAL_COLORS)
+ if (XDest == 0 && YDest == 0 && XSrc == 0 && XSrc == 0 &&
+ DestWidth == SrcWidth && DestHeight == SrcHeight &&
+ compr == BI_RGB &&
+ ROP == SRCCOPY)
{
- hPal = NtGdiGetDCObject(hDC, GDI_OBJECT_TYPE_PALETTE);
- hPal = GdiSelectPalette(hdcMem, hPal, FALSE);
+ BITMAP bmp;
+ if (IntGdiGetObject(hBitmap, sizeof(bmp), &bmp) == sizeof(bmp))
+ {
+ if (bmp.bmBitsPixel == bpp &&
+ bmp.bmWidth == SrcWidth &&
+ bmp.bmHeight == SrcHeight &&
+ bmp.bmPlanes == planes)
+ fastpath = TRUE;
+ }
}
- if (BitsInfo->bmiHeader.biCompression == BI_RLE4 ||
- BitsInfo->bmiHeader.biCompression == BI_RLE8)
+ if (fastpath)
{
- /* copy existing bitmap from destination dc */
- if (SrcWidth == DestWidth && SrcHeight == DestHeight)
- NtGdiBitBlt(hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
- SrcWidth, SrcHeight, hDC, XDest, YDest, ROP, 0, 0);
- else
- NtGdiStretchBlt(hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
- SrcWidth, SrcHeight, hDC, XDest, YDest, DestWidth, DestHeight,
- ROP, 0);
+ /* fast path */
+ DPRINT1("using fast path\n");
+ ret = IntSetDIBits( pdc, hBitmap, 0, height, safeBits, BitsInfo, Usage);
}
-
- pDC = DC_LockDc(hdcMem);
- if (pDC != NULL)
+ else
{
- /* Note BitsInfo->bmiHeader.biHeight is the number of scanline,
- * if it negitve we getting to many scanline for scanline is UINT not
- * a INT, so we need make the negtive value to positve and that make the
- * count correct for negtive bitmap, TODO : we need testcase for this api */
- IntSetDIBits(pDC, hBitmap, 0, abs(BitsInfo->bmiHeader.biHeight), Bits,
- BitsInfo, Usage);
-
- DC_UnlockDc(pDC);
+ /* slow path - need to use StretchBlt */
+ HBITMAP hOldBitmap;
+ HDC hdcMem;
+ PVOID pvBits;
+
+ hdcMem = NtGdiCreateCompatibleDC( hDC );
+ hBitmap = DIB_CreateDIBSection(pdc, BitsInfo, Usage, &pvBits, NULL, 0, 0);
+ if(!hBitmap)
+ {
+ DPRINT1("Error, failed to create a DIB section\n");
+ NtGdiDeleteObjectApp(hdcMem);
+ goto cleanup;
+ }
+ RtlCopyMemory(pvBits, safeBits, cjMaxBits);
+ hOldBitmap = NtGdiSelectBitmap( hdcMem, hBitmap );
+
+ /* Origin for DIBitmap may be bottom left (positive biHeight) or top
+ left (negative biHeight) */
+ ret = NtGdiStretchBlt( hDC, XDest, YDest, DestWidth, DestHeight,
+ hdcMem, XSrc, abs(height) - SrcHeight - YSrc,
+ SrcWidth, SrcHeight, ROP, 0 );
+
+ if(ret)
+ ret = SrcHeight;
+ NtGdiSelectBitmap( hdcMem, hOldBitmap );
+ NtGdiDeleteObjectApp( hdcMem );
+ GreDeleteObject( hBitmap );
}
-
-
- /* Origin for DIBitmap may be bottom left (positive biHeight) or top
- left (negative biHeight) */
- if (SrcWidth == DestWidth && SrcHeight == DestHeight)
- NtGdiBitBlt(hDC, XDest, YDest, DestWidth, DestHeight,
- hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
- ROP, 0, 0);
- else
- NtGdiStretchBlt(hDC, XDest, YDest, DestWidth, DestHeight,
- hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
- SrcWidth, SrcHeight, ROP, 0);
-
- /* cleanup */
- if (hPal)
- GdiSelectPalette(hdcMem, hPal, FALSE);
-
- if (hOldBitmap)
- NtGdiSelectBitmap(hdcMem, hOldBitmap);
-
- NtGdiDeleteObjectApp(hdcMem);
-
- GreDeleteObject(hBitmap);
-
- return SrcHeight;
+ cleanup:
+ ExFreePoolWithTag(safeBits, TAG_DIB);
+ DC_UnlockDc(pdc);
+ return ret;
}
else if ((coloruse != DIB_RGB_COLORS) || (init != CBM_INIT) || !data) fColor = FALSE;
else
{
- if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
- {
- const RGBQUAD *rgb = data->bmiColors;
- DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
-
- // Check if the first color of the colormap is black
- if ((col == RGB(0, 0, 0)))
- {
- rgb++;
- col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
+ const RGBQUAD *rgb = (RGBQUAD*)((PBYTE)data + data->bmiHeader.biSize);
+ DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
- // If the second color is white, create a monochrome bitmap
- fColor = (col != RGB(0xff,0xff,0xff));
- }
- else fColor = TRUE;
- }
- else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
+ // Check if the first color of the colormap is black
+ if ((col == RGB(0, 0, 0)))
{
- RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
- DWORD col = RGB(rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue);
+ rgb++;
+ col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
- if ((col == RGB(0,0,0)))
- {
- rgb++;
- col = RGB(rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue);
- fColor = (col != RGB(0xff,0xff,0xff));
- }
- else fColor = TRUE;
- }
- else
- {
- DPRINT("(%ld): wrong size for data\n", data->bmiHeader.biSize);
- return 0;
+ // If the second color is white, create a monochrome bitmap
+ fColor = (col != RGB(0xff,0xff,0xff));
}
+ else fColor = TRUE;
}
// Now create the bitmap
}
else
{
- handle = IntGdiCreateBitmap(width,
- height,
- 1,
- 1,
- NULL);
+ handle = GreCreateBitmap(width,
+ height,
+ 1,
+ 1,
+ NULL);
}
if (height < 0)
IN UINT cjMaxBits,
IN FLONG fl,
IN HANDLE hcmXform)
+ {
+ NTSTATUS Status = STATUS_SUCCESS;
+ PBYTE safeBits = NULL;
+ HBITMAP hbmResult = NULL;
+
+ if(pjInit && (fInit == CBM_INIT))
+ {
+ safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
+ if(!safeBits)
+ {
+ SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ return NULL;
+ }
+ }
+
+ _SEH2_TRY
+ {
+ if(pbmi) ProbeForRead(pbmi, cjMaxInitInfo, 1);
+ if(pjInit && (fInit == CBM_INIT))
+ {
+ ProbeForRead(pjInit, cjMaxBits, 1);
+ RtlCopyMemory(safeBits, pjInit, cjMaxBits);
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END
+
+ if(!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ goto cleanup;
+ }
+
+ hbmResult = GreCreateDIBitmapInternal(hDc,
+ cx,
+ cy,
+ fInit,
+ safeBits,
+ pbmi,
+ iUsage,
+ fl,
+ hcmXform);
+
+ cleanup:
+ if (safeBits) ExFreePoolWithTag(safeBits, TAG_DIB);
+ return hbmResult;
+ }
+
+ HBITMAP
+ FASTCALL
+ GreCreateDIBitmapInternal(
+ IN HDC hDc,
+ IN INT cx,
+ IN INT cy,
+ IN DWORD fInit,
+ IN OPTIONAL LPBYTE pjInit,
+ IN OPTIONAL PBITMAPINFO pbmi,
+ IN DWORD iUsage,
+ IN FLONG fl,
+ IN HANDLE hcmXform)
{
PDC Dc;
HBITMAP Bmp;
- UINT bpp;
+ WORD bpp;
+ HDC hdcDest;
- if (!hDc) // CreateBitmap
+ if (!hDc) /* 1bpp monochrome bitmap */
{ // Should use System Bitmap DC hSystemBM, with CreateCompatibleDC for this.
- hDc = IntGdiCreateDC(NULL, NULL, NULL, NULL,FALSE);
- if (!hDc)
+ hdcDest = NtGdiCreateCompatibleDC(0);
+ if(!hdcDest)
{
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- return NULL;
- }
-
- Dc = DC_LockDc(hDc);
- if (!Dc)
- {
- NtGdiDeleteObjectApp(hDc);
- SetLastWin32Error(ERROR_INVALID_HANDLE);
return NULL;
}
- bpp = 1;
- Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
+ }
+ else
+ {
+ hdcDest = hDc;
+ }
- DC_UnlockDc(Dc);
- NtGdiDeleteObjectApp(hDc);
+ Dc = DC_LockDc(hdcDest);
+ if (!Dc)
+ {
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ return NULL;
}
- else // CreateCompatibleBitmap
+ /* It's OK to set bpp=0 here, as IntCreateDIBitmap will create a compatible Bitmap
+ * if bpp != 1 and ignore the real value that was passed */
+ if (pbmi)
+ bpp = pbmi->bmiHeader.biBitCount;
+ else
+ bpp = 0;
+ Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
+ DC_UnlockDc(Dc);
+
+ if(!hDc)
{
- Dc = DC_LockDc(hDc);
- if (!Dc)
- {
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- return NULL;
- }
- /* pbmi == null
- First create an un-initialised bitmap. The depth of the bitmap
- should match that of the hdc and not that supplied in bmih.
- */
- if (pbmi)
- bpp = pbmi->bmiHeader.biBitCount;
- else
- {
- if (Dc->dctype != DC_TYPE_MEMORY)
- bpp = IntGdiGetDeviceCaps(Dc, BITSPIXEL);
- else
- {
- DIBSECTION dibs;
- INT Count;
- SURFACE *psurf = Dc->dclevel.pSurface;
- Count = BITMAP_GetObject(psurf, sizeof(dibs), &dibs);
- if (!Count)
- bpp = 1;
- else
- {
- if (Count == sizeof(BITMAP))
- /* A device-dependent bitmap is selected in the DC */
- bpp = dibs.dsBm.bmBitsPixel;
- else
- /* A DIB section is selected in the DC */
- bpp = dibs.dsBmih.biBitCount;
- }
- }
- }
- Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
- DC_UnlockDc(Dc);
+ NtGdiDeleteObjectApp(hdcDest);
}
return Bmp;
}
IN HDC hDC,
IN OPTIONAL HANDLE hSection,
IN DWORD dwOffset,
- IN LPBITMAPINFO bmi,
+ IN BITMAPINFO* bmi,
IN DWORD Usage,
IN UINT cjHeader,
IN FLONG fl,
HBITMAP hbitmap = 0;
DC *dc;
BOOL bDesktopDC = FALSE;
+ NTSTATUS Status = STATUS_SUCCESS;
if (!bmi) return hbitmap; // Make sure.
+ _SEH2_TRY
+ {
+ ProbeForRead(&bmi->bmiHeader.biSize, sizeof(DWORD), 1);
+ ProbeForRead(bmi, bmi->bmiHeader.biSize, 1);
+ ProbeForRead(bmi, DIB_BitmapInfoSize(bmi, Usage), 1);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END
+
+ if(!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ return NULL;
+ }
+
// If the reference hdc is null, take the desktop dc
if (hDC == 0)
{
if ((dc = DC_LockDc(hDC)))
{
hbitmap = DIB_CreateDIBSection(dc,
- (BITMAPINFO*)bmi,
+ bmi,
Usage,
Bits,
hSection,
APIENTRY
DIB_CreateDIBSection(
PDC dc,
- BITMAPINFO *bmi,
+ CONST BITMAPINFO *bmi,
UINT usage,
LPVOID *bits,
HANDLE section,
HBITMAP res = 0;
SURFACE *bmp = NULL;
void *mapBits = NULL;
+ HPALETTE hpal ;
// Fill BITMAP32 structure with DIB data
- BITMAPINFOHEADER *bi = &bmi->bmiHeader;
+ CONST BITMAPINFOHEADER *bi = &bmi->bmiHeader;
INT effHeight;
ULONG totalSize;
BITMAP bm;
SIZEL Size;
- RGBQUAD *lpRGB;
HANDLE hSecure;
- DWORD dsBitfields[3] = {0};
- ULONG ColorCount;
DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
bm.bmType = 0;
bm.bmWidth = bi->biWidth;
bm.bmHeight = effHeight;
- bm.bmWidthBytes = ovr_pitch ? ovr_pitch : (ULONG) DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
+ bm.bmWidthBytes = ovr_pitch ? ovr_pitch : WIDTH_BYTES_ALIGN32(bm.bmWidth, bi->biBitCount);
bm.bmPlanes = bi->biPlanes;
bm.bmBitsPixel = bi->biBitCount;
{
offset = 0;
bm.bmBits = EngAllocUserMem(totalSize, 0);
+ if(!bm.bmBits) goto cleanup;
}
// hSecure = MmSecureVirtualMemory(bm.bmBits, totalSize, PAGE_READWRITE);
if (usage == DIB_PAL_COLORS)
{
- lpRGB = DIB_MapPaletteColors(dc, bmi);
- ColorCount = bi->biClrUsed;
- if (ColorCount == 0)
- {
- ColorCount = 1 << bi->biBitCount;
- }
+ if(dc)
+ {
+ PPALETTE pdcPal ;
+ pdcPal = PALETTE_LockPalette(dc->dclevel.hpal);
+ hpal = DIB_MapPaletteColors(pdcPal, bmi);
+ PALETTE_UnlockPalette(pdcPal);
+ }
+ else
+ {
+ /* For DIB Brushes */
+ DPRINT1("FIXME : Unsupported DIB_PAL_COLORS without a DC to map colors.\n");
+ /* HACK */
+ hpal = (HPALETTE) 0xFFFFFFFF;
+ }
}
else
- {
- lpRGB = bmi->bmiColors;
- ColorCount = 1 << bi->biBitCount;
- }
-
- /* Set dsBitfields values */
- if (usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
- {
- dsBitfields[0] = dsBitfields[1] = dsBitfields[2] = 0;
- }
- else if (bi->biCompression == BI_RGB)
- {
- switch (bi->biBitCount)
- {
- case 15:
- case 16:
- dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)lpRGB : 0x7c00;
- dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 1) : 0x03e0;
- dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 2) : 0x001f;
- break;
+ {
+ hpal = BuildDIBPalette(bmi);
+ }
- case 24:
- case 32:
- dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)lpRGB : 0xff0000;
- dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 1) : 0x00ff00;
- dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 2) : 0x0000ff;
- break;
- }
- }
- else
- {
- dsBitfields[0] = ((DWORD*)bmi->bmiColors)[0];
- dsBitfields[1] = ((DWORD*)bmi->bmiColors)[1];
- dsBitfields[2] = ((DWORD*)bmi->bmiColors)[2];
- }
+ if(!hpal)
+ {
+ DPRINT1("Error : Could not create a palette for the DIB.\n");
+ goto cleanup;
+ }
// Create Device Dependent Bitmap and add DIB pointer
Size.cx = bm.bmWidth;
Size.cy = abs(bm.bmHeight);
- res = IntCreateBitmap(Size,
- bm.bmWidthBytes,
- BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
- BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
- (bi->biHeight < 0 ? BMF_TOPDOWN : 0),
- bm.bmBits);
+ res = GreCreateBitmapEx(bm.bmWidth,
+ abs(bm.bmHeight),
+ bm.bmWidthBytes,
+ BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
+ BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
+ (bi->biHeight < 0 ? BMF_TOPDOWN : 0),
+ bi->biSizeImage,
+ bm.bmBits,
+ 0);
if (!res)
{
- if (lpRGB != bmi->bmiColors)
- {
- ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
- }
SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
- return NULL;
+ goto cleanup;
}
bmp = SURFACE_LockSurface(res);
if (NULL == bmp)
{
- if (lpRGB != bmi->bmiColors)
- {
- ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
- }
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- GreDeleteObject(bmp);
- return NULL;
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ goto cleanup;
}
/* WINE NOTE: WINE makes use of a colormap, which is a color translation
table between the DIB and the X physical device. Obviously,
this is left out of the ReactOS implementation. Instead,
we call NtGdiSetDIBColorTable. */
- if (bi->biBitCount <= 8)
- {
- bi->biClrUsed = 1 << bi->biBitCount;
- }
- else
- {
- bi->biClrUsed = 0;
- }
-
bmp->hDIBSection = section;
bmp->hSecure = hSecure;
bmp->dwOffset = offset;
- bmp->flFlags = BITMAPOBJ_IS_APIBITMAP;
- bmp->dsBitfields[0] = dsBitfields[0];
- bmp->dsBitfields[1] = dsBitfields[1];
- bmp->dsBitfields[2] = dsBitfields[2];
- bmp->biClrUsed = bi->biClrUsed;
+ bmp->flags = API_BITMAP;
bmp->biClrImportant = bi->biClrImportant;
- if (bi->biClrUsed != 0)
- {
- bmp->hDIBPalette = PALETTE_AllocPaletteIndexedRGB(ColorCount, lpRGB);
- }
- else
- {
- bmp->hDIBPalette = PALETTE_AllocPalette(PAL_BITFIELDS, 0, NULL,
- dsBitfields[0],
- dsBitfields[1],
- dsBitfields[2]);
- }
+ /* HACK */
+ if(hpal != (HPALETTE)0xFFFFFFFF)
+ {
+ bmp->ppal = PALETTE_ShareLockPalette(hpal);
+ /* Lazy delete hpal, it will be freed at surface release */
+ GreDeleteObject(hpal);
+ }
// Clean up in case of errors
+ cleanup:
if (!res || !bmp || !bm.bmBits)
{
DPRINT("got an error res=%08x, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
}
}
- if (lpRGB != bmi->bmiColors)
- {
- ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
- }
-
if (bmp)
{
SURFACE_UnlockSurface(bmp);
}
/***********************************************************************
- * DIB_GetDIBWidthBytes
+ * DIB_GetBitmapInfo
*
- * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
- * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
- * 11/16/1999 (RJJ) lifted from wine
+ * Get the info from a bitmap header.
+ * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
*/
- INT FASTCALL DIB_GetDIBWidthBytes(INT width, INT depth)
+ int
+ FASTCALL
+ DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
+ LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
{
- return ((width * depth + 31) & ~31) >> 3;
+ if (header->biSize == sizeof(BITMAPCOREHEADER))
+ {
+ const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
+ *width = core->bcWidth;
+ *height = core->bcHeight;
+ *planes = core->bcPlanes;
+ *bpp = core->bcBitCount;
+ *compr = BI_RGB;
+ *size = 0;
+ return 0;
+ }
+ if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
+ {
+ *width = header->biWidth;
+ *height = header->biHeight;
+ *planes = header->biPlanes;
+ *bpp = header->biBitCount;
+ *compr = header->biCompression;
+ *size = header->biSizeImage;
+ return 1;
+ }
+ DPRINT1("(%d): unknown/wrong size for header\n", header->biSize );
+ return -1;
}
/***********************************************************************
INT APIENTRY DIB_GetDIBImageBytes(INT width, INT height, INT depth)
{
- return DIB_GetDIBWidthBytes(width, depth) * (height < 0 ? -height : height);
+ return WIDTH_BYTES_ALIGN32(width, depth) * (height < 0 ? -height : height);
}
/***********************************************************************
INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
{
- int colors;
+ unsigned int colors, size, masks = 0;
if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{
- BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
+ const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
- return sizeof(BITMAPCOREHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
+ return sizeof(BITMAPCOREHEADER) + colors *
+ ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
}
else /* assume BITMAPINFOHEADER */
{
colors = info->bmiHeader.biClrUsed;
- if (!colors && (info->bmiHeader.biBitCount <= 8)) colors = 1 << info->bmiHeader.biBitCount;
- return sizeof(BITMAPINFOHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
+ if (colors > 256) colors = 256;
+ if (!colors && (info->bmiHeader.biBitCount <= 8))
+ colors = 1 << info->bmiHeader.biBitCount;
+ if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
+ size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
+ return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
}
}
- RGBQUAD *
+ HPALETTE
FASTCALL
- DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi)
+ DIB_MapPaletteColors(PPALETTE ppal, CONST BITMAPINFO* lpbmi)
{
- RGBQUAD *lpRGB;
+ PALETTEENTRY* ppalEntries;
ULONG nNumColors,i;
USHORT *lpIndex;
- PPALETTE palGDI;
-
- palGDI = PALETTE_LockPalette(dc->dclevel.hpal);
-
- if (NULL == palGDI)
- {
- return NULL;
- }
+ HPALETTE hpal;
- if (palGDI->Mode != PAL_INDEXED)
+ if (!(ppal->flFlags & PAL_INDEXED))
{
- PALETTE_UnlockPalette(palGDI);
return NULL;
}
nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
}
- lpRGB = (RGBQUAD *)ExAllocatePoolWithTag(PagedPool, sizeof(RGBQUAD) * nNumColors, TAG_COLORMAP);
- if (lpRGB == NULL)
+ /* Don't have more colors than we need */
+ nNumColors = min(ppal->NumColors, nNumColors);
+
+ ppalEntries = ExAllocatePoolWithTag(PagedPool, sizeof(PALETTEENTRY) * nNumColors, TAG_COLORMAP);
+ if (ppalEntries == NULL)
{
- PALETTE_UnlockPalette(palGDI);
+ DPRINT1("Could not allocate palette entries\n");
return NULL;
}
- lpIndex = (USHORT *)&lpbmi->bmiColors[0];
+ lpIndex = (USHORT *)((PBYTE)lpbmi + lpbmi->bmiHeader.biSize);
for (i = 0; i < nNumColors; i++)
{
- if (*lpIndex < palGDI->NumColors)
+ if (*lpIndex < ppal->NumColors)
{
- lpRGB[i].rgbRed = palGDI->IndexedColors[*lpIndex].peRed;
- lpRGB[i].rgbGreen = palGDI->IndexedColors[*lpIndex].peGreen;
- lpRGB[i].rgbBlue = palGDI->IndexedColors[*lpIndex].peBlue;
+ ppalEntries[i] = ppal->IndexedColors[*lpIndex];
}
else
{
- lpRGB[i].rgbRed = 0;
- lpRGB[i].rgbGreen = 0;
- lpRGB[i].rgbBlue = 0;
+ ppalEntries[i].peRed = 0;
+ ppalEntries[i].peGreen = 0;
+ ppalEntries[i].peBlue = 0;
+ ppalEntries[i].peFlags = 0;
}
- lpRGB[i].rgbReserved = 0;
+
lpIndex++;
}
- PALETTE_UnlockPalette(palGDI);
- return lpRGB;
+ hpal = PALETTE_AllocPalette(PAL_INDEXED, nNumColors, (ULONG*)ppalEntries, 0, 0, 0);
+
+ ExFreePoolWithTag(ppalEntries, TAG_COLORMAP);
+
+ return hpal;
}
HPALETTE
FASTCALL
- BuildDIBPalette(CONST BITMAPINFO *bmi, PINT paletteType)
+ BuildDIBPalette(CONST BITMAPINFO *bmi)
{
BYTE bits;
ULONG ColorCount;
- PALETTEENTRY *palEntries = NULL;
HPALETTE hPal;
- ULONG RedMask, GreenMask, BlueMask;
+ ULONG RedMask = 0, GreenMask = 0, BlueMask = 0;
+ PDWORD pdwColors = (PDWORD)((PBYTE)bmi + bmi->bmiHeader.biSize);
+ INT paletteType;
// Determine Bits Per Pixel
bits = bmi->bmiHeader.biBitCount;
// Determine paletteType from Bits Per Pixel
if (bits <= 8)
{
- *paletteType = PAL_INDEXED;
+ paletteType = PAL_INDEXED;
RedMask = GreenMask = BlueMask = 0;
}
else if (bmi->bmiHeader.biCompression == BI_BITFIELDS)
{
- *paletteType = PAL_BITFIELDS;
- RedMask = ((ULONG *)bmi->bmiColors)[0];
- GreenMask = ((ULONG *)bmi->bmiColors)[1];
- BlueMask = ((ULONG *)bmi->bmiColors)[2];
- }
- else if (bits < 24)
- {
- *paletteType = PAL_BITFIELDS;
- RedMask = 0x7c00;
- GreenMask = 0x03e0;
- BlueMask = 0x001f;
+ paletteType = PAL_BITFIELDS;
+ RedMask = pdwColors[0];
+ GreenMask = pdwColors[1];
+ BlueMask = pdwColors[2];
}
else
{
- *paletteType = PAL_BGR;
- RedMask = 0xff0000;
- GreenMask = 0x00ff00;
- BlueMask = 0x0000ff;
+ paletteType = PAL_BITFIELDS;
+ switch (bits)
+ {
+ case 15:
+ paletteType |= PAL_RGB16_555;
+ RedMask = 0x7C00;
+ GreenMask = 0x03E0;
+ BlueMask = 0x001F;
+ break;
+
+ case 16:
+ paletteType |= PAL_RGB16_565;
+ RedMask = 0xF800;
+ GreenMask = 0x07E0;
+ BlueMask = 0x001F;
+ break;
+
+ case 24:
+ case 32:
+ paletteType |= PAL_BGR;
+ RedMask = 0xFF0000;
+ GreenMask = 0x00FF00;
+ BlueMask = 0x0000FF;
+ break;
+ }
}
if (bmi->bmiHeader.biClrUsed == 0)
ColorCount = bmi->bmiHeader.biClrUsed;
}
- if (PAL_INDEXED == *paletteType)
+ if (PAL_INDEXED == paletteType)
{
- hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)bmi->bmiColors);
+ hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)pdwColors);
}
else
{
- hPal = PALETTE_AllocPalette(*paletteType, ColorCount,
- (ULONG*) palEntries,
+ hPal = PALETTE_AllocPalette(paletteType, 0,
+ NULL,
RedMask, GreenMask, BlueMask);
}
return hPal;
}
+ /* Converts a BITMAPCOREINFO to a BITMAPINFO structure,
+ * or does nothing if it's already a BITMAPINFO (or V4 or V5) */
+ BITMAPINFO*
+ FASTCALL
+ DIB_ConvertBitmapInfo (CONST BITMAPINFO* pbmi, DWORD Usage)
+ {
+ CONST BITMAPCOREINFO* pbmci = (BITMAPCOREINFO*)pbmi;
+ BITMAPINFO* pNewBmi ;
+ UINT numColors = 0, ColorsSize = 0;
+
+ if(pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) return (BITMAPINFO*)pbmi;
+ if(pbmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) return NULL;
+
+ if(pbmci->bmciHeader.bcBitCount <= 8)
+ {
+ numColors = 1 << pbmci->bmciHeader.bcBitCount;
+ if(Usage == DIB_PAL_COLORS)
+ {
+ ColorsSize = numColors * sizeof(WORD);
+ }
+ else
+ {
+ ColorsSize = numColors * sizeof(RGBQUAD);
+ }
+ }
+ else if (Usage == DIB_PAL_COLORS)
+ {
+ /* Invalid at high Res */
+ return NULL;
+ }
+
+ pNewBmi = ExAllocatePoolWithTag(PagedPool, sizeof(BITMAPINFOHEADER) + ColorsSize, TAG_DIB);
+ if(!pNewBmi) return NULL;
+
+ RtlZeroMemory(pNewBmi, sizeof(BITMAPINFOHEADER) + ColorsSize);
+
+ pNewBmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ pNewBmi->bmiHeader.biBitCount = pbmci->bmciHeader.bcBitCount;
+ pNewBmi->bmiHeader.biWidth = pbmci->bmciHeader.bcWidth;
+ pNewBmi->bmiHeader.biHeight = pbmci->bmciHeader.bcHeight;
+ pNewBmi->bmiHeader.biPlanes = pbmci->bmciHeader.bcPlanes;
+ pNewBmi->bmiHeader.biCompression = BI_RGB ;
+ pNewBmi->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(pNewBmi->bmiHeader.biWidth,
+ pNewBmi->bmiHeader.biHeight,
+ pNewBmi->bmiHeader.biBitCount);
+
+ if(Usage == DIB_PAL_COLORS)
+ {
+ RtlCopyMemory(pNewBmi->bmiColors, pbmci->bmciColors, ColorsSize);
+ }
+ else
+ {
+ UINT i;
+ for(i=0; i<numColors; i++)
+ {
+ pNewBmi->bmiColors[i].rgbRed = pbmci->bmciColors[i].rgbtRed;
+ pNewBmi->bmiColors[i].rgbGreen = pbmci->bmciColors[i].rgbtGreen;
+ pNewBmi->bmiColors[i].rgbBlue = pbmci->bmciColors[i].rgbtBlue;
+ }
+ }
+
+ return pNewBmi ;
+ }
+
+ /* Frees a BITMAPINFO created with DIB_ConvertBitmapInfo */
+ VOID
+ FASTCALL
+ DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig)
+ {
+ if(converted != orig)
+ ExFreePoolWithTag(converted, TAG_DIB);
+ }
+
+
+
+
+
+
/* EOF */
} Rect, *PRect;
int FASTCALL IntFillRect(DC *dc, INT XLeft, INT YLeft, INT Width, INT Height, PBRUSH pbrush, BOOL Pen);
- int FASTCALL app_fill_rect(DC *dc, Rect r, PBRUSH pbrush, BOOL Pen);
+ //int FASTCALL app_fill_rect(DC *dc, Rect r, PBRUSH pbrush, BOOL Pen);
static
POINT
INTERNAL_CALL
app_new_point(int x, int y)
{
- POINT p;
+ POINT p;
p.x = x;
p.y = y;
return p;
*
* The draw_arc algorithm is based on draw_ellipse, but unlike
* that algorithm is not symmetric in the general case, since
- * an angular portion is clipped from the shape.
+ * an angular portion is clipped from the shape.
* This clipping is performed by keeping track of two hypothetical
* lines joining the centre point to the enclosing rectangle,
* at the angles start_angle and end_angle, using a line-intersection
rise2 = p2.y - p0.y;
run2 = p2.x - p0.x;
- if (r.y <= p0.y) //
+ if (r.y <= p0.y) //
{
/* in top half of arc ellipse */
* between an outer and inner ellipse, and also the draw_arc and
* fill_arc operations which additionally clip drawing between
* a start_angle and an end_angle.
- *
+ *
*/
static
int
r1.height = r1.y+r1.height-r2.y;
r1.y = r2.y;
while (r1.height > 0) {
- result &= app_fill_arc_rect(g,
+ result &= app_fill_arc_rect(g,
rect(r1.x, r1.y, r1.width, 1),
p0, p1, p2, start_angle, end_angle, pbrush, FALSE);
r1.y += 1;
pdcattr = dc->pdcattr;
pbrush = BRUSH_LockBrush(pdcattr->hbrush);
- if (!pbrush)
+ if (!pbrush)
{
DPRINT1("FillArc Fail\n");
SetLastWin32Error(ERROR_INTERNAL_ERROR);
(dc->dclevel.flPath & DCPATH_CLOCKWISE) ? -Start : -End,
pbrush, Chord);
- BRUSH_UnlockBrush(pbrush);
+ BRUSH_UnlockBrush(pbrush);
return ret;
}
INT XLeft,
INT YLeft,
INT Width,
- INT Height,
+ INT Height,
PBRUSH pbrush)
{
return (BOOL)app_fill_ellipse(dc, rect( XLeft, YLeft, Width, Height), pbrush);
INT Right,
INT Bottom,
INT Wellipse,
- INT Hellipse,
+ INT Hellipse,
PBRUSH pbrush)
{
Rect r;
270, 360, pbrush,FALSE);
app_fill_arc(dc, rect(r.x+r.width-rx-rx, r.y, rx+rx, ry+ry),
- 0, 90, pbrush,FALSE);
+ 0, 90, pbrush,FALSE);
}
if (Wellipse < r.width)
{
r = rect( Left, Top, abs(Right-Left), abs(Bottom-Top));
rx = Wellipse/2;
ry = Hellipse/2;
-
+
if (Wellipse > r.width)
{
if (Hellipse > r.height) // > W > H
app_draw_arc(dc, rect(r.x, r.y, Wellipse - 1, r.height - 1),
90, 270, pbrushPen, FALSE);
app_draw_arc(dc, rect(Right - Wellipse, r.y, Wellipse - 1, r.height - 1),
- 270, 90, pbrushPen, FALSE);
+ 270, 90, pbrushPen, FALSE);
}
else // < W < H
{
psurf,
&dc->eboFill.BrushObject,
Points,
- Count,
+ Count,
DestRect,
&BrushOrigin);
}
}
if (!PenWidth) PenWidth = 1;
- pbrush->ptPenWidth.x = PenWidth;
+ pbrush->ptPenWidth.x = PenWidth;
RectBounds.left = Left;
RectBounds.right = Right;
RectBounds.top = Top;
RectBounds.bottom = Bottom;
-
+
IntLPtoDP(dc, (LPPOINT)&RectBounds, 2);
-
+
RectBounds.left += dc->ptlDCOrig.x;
RectBounds.right += dc->ptlDCOrig.x;
RectBounds.top += dc->ptlDCOrig.y;
CenterX - RadiusX, CenterY + RadiusY, RadiusX*2, RadiusY*2);
pFillBrushObj = BRUSH_LockBrush(pdcattr->hbrush);
- if (NULL == pFillBrushObj)
+ if (NULL == pFillBrushObj)
{
DPRINT1("FillEllipse Fail\n");
SetLastWin32Error(ERROR_INTERNAL_ERROR);
return TRUE;
}
+ DC_vPrepareDCsForBlit(dc, dc->rosdc.CombinedClip->rclBounds,
+ NULL, dc->rosdc.CombinedClip->rclBounds);
+
+ if (dc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+ DC_vUpdateFillBrush(dc);
+
+ if (dc->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+ DC_vUpdateLineBrush(dc);
+
/* Perform the actual work */
switch (iFunc)
{
}
/* Cleanup and return */
+ DC_vFinishBlit(dc, NULL);
DC_UnlockDc(dc);
ExFreePool(pTemp);
pdcattr = dc->pdcattr;
- /* Do we rotate or shear? */
- if (!(dc->dclevel.mxWorldToDevice.flAccel & MX_SCALE))
- {
-
- POINTL DestCoords[4];
- ULONG PolyCounts = 4;
- DestCoords[0].x = DestCoords[3].x = LeftRect;
- DestCoords[0].y = DestCoords[1].y = TopRect;
- DestCoords[1].x = DestCoords[2].x = RightRect;
- DestCoords[2].y = DestCoords[3].y = BottomRect;
- // Use IntGdiPolyPolygon so to support PATH.
- return IntGdiPolyPolygon(dc, DestCoords, &PolyCounts, 1);
- }
// Rectangle Path only.
if ( PATH_IsPathOpen(dc->dclevel) )
{
DestRect.bottom--;
}
+ DC_vPrepareDCsForBlit(dc, DestRect, NULL, DestRect);
+
if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
DC_vUpdateFillBrush(dc);
ret = FALSE;
goto cleanup;
}
+
psurf = dc->dclevel.pSurface;
if (!psurf)
{
}
cleanup:
+ DC_vFinishBlit(dc, NULL);
+
/* Move current position in DC?
MSDN: The current position is neither used nor updated by Rectangle. */
return TRUE;
}
- ret = IntRectangle ( dc, LeftRect, TopRect, RightRect, BottomRect );
- DC_UnlockDc ( dc );
+ /* Do we rotate or shear? */
+ if (!(dc->dclevel.mxWorldToDevice.flAccel & MX_SCALE))
+ {
+ POINTL DestCoords[4];
+ ULONG PolyCounts = 4;
+
+ DestCoords[0].x = DestCoords[3].x = LeftRect;
+ DestCoords[0].y = DestCoords[1].y = TopRect;
+ DestCoords[1].x = DestCoords[2].x = RightRect;
+ DestCoords[2].y = DestCoords[3].y = BottomRect;
+ // Use IntGdiPolyPolygon so to support PATH.
+ ret = IntGdiPolyPolygon(dc, DestCoords, &PolyCounts, 1);
+ }
+ else
+ {
+ ret = IntRectangle(dc, LeftRect, TopRect, RightRect, BottomRect );
+ }
+
+ DC_UnlockDc(dc);
return ret;
}
}
if (!PenWidth) PenWidth = 1;
- pbrushLine->ptPenWidth.x = PenWidth;
+ pbrushLine->ptPenWidth.x = PenWidth;
RectBounds.left = Left;
RectBounds.top = Top;
RectBounds.bottom += dc->ptlDCOrig.y;
pbrushFill = BRUSH_LockBrush(pdcattr->hbrush);
- if (NULL == pbrushFill)
+ if (NULL == pbrushFill)
{
DPRINT1("FillRound Fail\n");
SetLastWin32Error(ERROR_INTERNAL_ERROR);
ret = FALSE;
- }
+ }
else
{
RtlCopyMemory(&brushTemp, pbrushFill, sizeof(brushTemp));
{
PDC pdc;
SURFACE *psurf;
- PPALETTE ppal;
EXLATEOBJ exlo;
RECTL rclExtent;
POINTL ptlDitherOrg;
ULONG i;
BOOL bRet;
- HPALETTE hDestPalette;
- /* Check parameters */
- if (ulMode == GRADIENT_FILL_TRIANGLE)
+ /* check parameters */
+ if (ulMode & GRADIENT_FILL_TRIANGLE)
{
PGRADIENT_TRIANGLE pTriangle = (PGRADIENT_TRIANGLE)pMesh;
/* Lock the output DC */
pdc = DC_LockDc(hdc);
- if (!pdc)
+ if(!pdc)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
- if (pdc->dctype == DC_TYPE_INFO)
+ if(pdc->dctype == DC_TYPE_INFO)
{
DC_UnlockDc(pdc);
/* Yes, Windows really returns TRUE in this case */
}
psurf = pdc->dclevel.pSurface;
- if (!psurf)
+ if(!psurf)
{
/* Memory DC with no surface selected */
DC_UnlockDc(pdc);
- return TRUE; // CHECKME
+ return TRUE; //CHECKME
}
/* calculate extent */
rclExtent.top = min(rclExtent.top, (pVertex + i)->y);
rclExtent.bottom = max(rclExtent.bottom, (pVertex + i)->y);
}
-
IntLPtoDP(pdc, (LPPOINT)&rclExtent, 2);
+
rclExtent.left += pdc->ptlDCOrig.x;
rclExtent.right += pdc->ptlDCOrig.x;
rclExtent.top += pdc->ptlDCOrig.y;
ptlDitherOrg.x = ptlDitherOrg.y = 0;
IntLPtoDP(pdc, (LPPOINT)&ptlDitherOrg, 1);
+
ptlDitherOrg.x += pdc->ptlDCOrig.x;
ptlDitherOrg.y += pdc->ptlDCOrig.y;
- hDestPalette = psurf->hDIBPalette;
- if (!hDestPalette) hDestPalette = pPrimarySurface->devinfo.hpalDefault;
-
- ppal = PALETTE_LockPalette(hDestPalette);
- EXLATEOBJ_vInitialize(&exlo, &gpalRGB, ppal, 0, 0, 0);
+ EXLATEOBJ_vInitialize(&exlo, &gpalRGB, psurf->ppal, 0, 0, 0);
ASSERT(pdc->rosdc.CombinedClip);
+ DC_vPrepareDCsForBlit(pdc, rclExtent, NULL, rclExtent);
+
bRet = IntEngGradientFill(&psurf->SurfObj,
- pdc->rosdc.CombinedClip,
- &exlo.xlo,
- pVertex,
- nVertex,
- pMesh,
- nMesh,
- &rclExtent,
- &ptlDitherOrg,
- ulMode);
+ pdc->rosdc.CombinedClip,
+ &exlo.xlo,
+ pVertex,
+ nVertex,
+ pMesh,
+ nMesh,
+ &rclExtent,
+ &ptlDitherOrg,
+ ulMode);
EXLATEOBJ_vCleanup(&exlo);
-
- if (ppal)
- PALETTE_UnlockPalette(ppal);
-
+ DC_vFinishBlit(pdc, NULL);
DC_UnlockDc(pdc);
return bRet;
return FALSE;
}
- cbVertex = nVertex * sizeof(TRIVERTEX);
- if (cbVertex + cbMesh <= cbVertex)
+ cbVertex = nVertex * sizeof(TRIVERTEX) ;
+ if(cbVertex + cbMesh <= cbVertex)
{
/* Overflow */
- return FALSE;
+ return FALSE ;
}
/* Allocate a kernel mode buffer */
SafeVertex = ExAllocatePoolWithTag(PagedPool, cbVertex + cbMesh, TAG_SHAPE);
- if (!SafeVertex)
+ if(!SafeVertex)
{
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
PDC dc;
PDC_ATTR pdcattr;
SURFACE *psurf = NULL;
- HPALETTE hpal;
- PPALETTE ppal;
EXLATEOBJ exlo;
BOOL Ret = FALSE;
RECTL DestRect;
goto cleanup;
}
- hpal = dc->dclevel.pSurface->hDIBPalette;
- if (!hpal) hpal = pPrimarySurface->devinfo.hpalDefault;
- ppal = PALETTE_ShareLockPalette(hpal);
-
- EXLATEOBJ_vInitialize(&exlo, &gpalRGB, ppal, 0, 0xffffff, 0);
+ EXLATEOBJ_vInitialize(&exlo, &gpalRGB, psurf->ppal, 0, 0xffffff, 0);
/* Only solid fills supported for now
* How to support pattern brushes and non standard surfaces (not offering dib functions):
Ret = DIB_XXBPP_FloodFillSolid(&psurf->SurfObj, &dc->eboFill.BrushObject, &DestRect, &Pt, ConvColor, FillType);
EXLATEOBJ_vCleanup(&exlo);
- PALETTE_ShareUnlockPalette(ppal);
cleanup:
DC_UnlockDc(dc);
Size->cx = (TotalWidth + 32) >> 6;
Size->cy = (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight < 0 ? - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight);
- Size->cy = EngMulDiv(Size->cy, IntGdiGetDeviceCaps(dc, LOGPIXELSY), 72);
+ Size->cy = EngMulDiv(Size->cy, dc->ppdev->gdiinfo.ulLogPixelsY, 72);
return TRUE;
}
LONGLONG TextLeft, RealXStart;
ULONG TextTop, previous, BackgroundLeft;
FT_Bool use_kerning;
- RECTL DestRect, MaskRect;
+ RECTL DestRect, MaskRect, DummyRect = {0, 0, 0, 0};
POINTL SourcePoint, BrushOrigin;
HBITMAP HSourceGlyph;
SURFOBJ *SourceGlyphSurf;
BOOLEAN Render;
POINT Start;
BOOL DoBreak = FALSE;
- HPALETTE hDestPalette;
- PPALETTE ppalDst;
USHORT DxShift;
// TODO: Write test-cases to exactly match real Windows in different
pdcattr = dc->pdcattr;
- if (pdcattr->ulDirty_ & DIRTY_TEXT)
- DC_vUpdateTextBrush(dc);
-
if ((fuOptions & ETO_OPAQUE) || pdcattr->jBkMode == OPAQUE)
{
if (pdcattr->ulDirty_ & DIRTY_BACKGROUND)
IntLPtoDP(dc, (POINT *)lprc, 2);
}
- psurf = dc->dclevel.pSurface;
- if (!psurf)
- {
- goto fail;
- }
- SurfObj = &psurf->SurfObj;
-
Start.x = XStart;
Start.y = YStart;
IntLPtoDP(dc, &Start, 1);
DestRect.right += dc->ptlDCOrig.x;
DestRect.bottom += dc->ptlDCOrig.y;
+ DC_vPrepareDCsForBlit(dc, DestRect, NULL, DestRect);
+
+ if (pdcattr->ulDirty_ & DIRTY_BACKGROUND)
+ DC_vUpdateBackgroundBrush(dc);
+
IntEngBitBlt(
- &psurf->SurfObj,
+ &dc->dclevel.pSurface->SurfObj,
NULL,
NULL,
dc->rosdc.CombinedClip,
&BrushOrigin,
ROP3_TO_ROP4(PATCOPY));
fuOptions &= ~ETO_OPAQUE;
+ DC_vFinishBlit(dc, NULL);
}
else
{
TextTop = YStart;
BackgroundLeft = (RealXStart + 32) >> 6;
- /* Create the xlateobj */
- hDestPalette = psurf->hDIBPalette;
- if (!hDestPalette) hDestPalette = pPrimarySurface->devinfo.hpalDefault;
- ppalDst = PALETTE_LockPalette(hDestPalette);
- EXLATEOBJ_vInitialize(&exloRGB2Dst, &gpalRGB, ppalDst, 0, 0, 0);
- EXLATEOBJ_vInitialize(&exloDst2RGB, ppalDst, &gpalRGB, 0, 0, 0);
- PALETTE_UnlockPalette(ppalDst);
+ /* Lock blit with a dummy rect */
+ DC_vPrepareDCsForBlit(dc, DummyRect, NULL, DummyRect);
+ psurf = dc->dclevel.pSurface ;
+ SurfObj = &psurf->SurfObj ;
+
+ EXLATEOBJ_vInitialize(&exloRGB2Dst, &gpalRGB, psurf->ppal, 0, 0, 0);
+ EXLATEOBJ_vInitialize(&exloDst2RGB, psurf->ppal, &gpalRGB, 0, 0, 0);
+
+ if ((fuOptions & ETO_OPAQUE) && (dc->pdcattr->ulDirty_ & DIRTY_BACKGROUND))
+ DC_vUpdateBackgroundBrush(dc) ;
+
+ if(dc->pdcattr->ulDirty_ & DIRTY_TEXT)
+ DC_vUpdateTextBrush(dc) ;
/*
* The main rendering loop.
*/
-
for (i = 0; i < Count; i++)
{
if (fuOptions & ETO_GLYPH_INDEX)
DestRect.right = (TextLeft + (realglyph->root.advance.x >> 10) + 32) >> 6;
DestRect.top = TextTop + yoff - ((face->size->metrics.ascender + 32) >> 6);
DestRect.bottom = TextTop + yoff + ((32 - face->size->metrics.descender) >> 6);
+ MouseSafetyOnDrawStart(dc->ppdev, DestRect.left, DestRect.top, DestRect.right, DestRect.bottom);
IntEngBitBlt(
&psurf->SurfObj,
NULL,
&dc->eboBackground.BrushObject,
&BrushOrigin,
ROP3_TO_ROP4(PATCOPY));
+ MouseSafetyOnDrawEnd(dc->ppdev);
BackgroundLeft = DestRect.right;
+
}
DestRect.left = ((TextLeft + 32) >> 6) + realglyph->left;
DestRect.right = lprc->right + dc->ptlDCOrig.x;
DoBreak = TRUE;
}
-
+ MouseSafetyOnDrawStart(dc->ppdev, DestRect.left, DestRect.top, DestRect.right, DestRect.bottom);
IntEngMaskBlt(
SurfObj,
SourceGlyphSurf,
(PPOINTL)&MaskRect,
&dc->eboText.BrushObject,
&BrushOrigin);
+ MouseSafetyOnDrawEnd(dc->ppdev) ;
EngUnlockSurface(SourceGlyphSurf);
EngDeleteSurface((HSURF)HSourceGlyph);
String++;
}
-
IntUnLockFreeType;
+ DC_vFinishBlit(dc, NULL) ;
EXLATEOBJ_vCleanup(&exloRGB2Dst);
EXLATEOBJ_vCleanup(&exloDst2RGB);
if (TextObj != NULL)
fail:
if (TextObj != NULL)
TEXTOBJ_UnlockText(TextObj);
+
DC_UnlockDc(dc);
return FALSE;
Flags = DSS_TIMER_EVENT;
Device = IntEnumHDev();
-
- SurfObj = EngLockSurface( Device->pSurface );
+ // UNIMPLEMENTED;
+ //ASSERT(FALSE);
+ SurfObj = 0;// EngLockSurface( Device->pSurface );
if(!SurfObj) return;
DoDeviceSync( SurfObj, NULL, Flags);
EngUnlockSurface(SurfObj);
/** INCLUDES ******************************************************************/
- //#define GDI_DEBUG
+ #define GDI_DEBUG
#include <win32k.h>
#define NDEBUG
PEPROCESS OldProcess;
Object->BaseFlags |= BASEFLAG_READY_TO_DIE;
DPRINT("Object %p, ulShareCount = %d\n", Object->hHmgr, Object->ulShareCount);
- //GDIDBG_TRACECALLER();
- //GDIDBG_TRACESHARELOCKER(GDI_HANDLE_GET_INDEX(hObj));
- /* Set NULL owner. This will permit an other process to kill the object
- * Do the work here to avoid race conditions */
+ /* Set NULL owner. Do the work here to avoid race conditions */
Status = PsLookupProcessByProcessId((HANDLE)((ULONG_PTR)PrevProcId & ~0x1), &OldProcess);
if (NT_SUCCESS(Status))
{
}
ObDereferenceObject(OldProcess);
}
- (void)InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
+ (void)InterlockedExchangePointer((PVOID*)&Entry->ProcessId, NULL);
/* Don't wait on shared locks */
return FALSE;
}
*/
DPRINT1("Object->cExclusiveLock = %d\n", Object->cExclusiveLock);
GDIDBG_TRACECALLER();
- GDIDBG_TRACELOCKER(GDI_HANDLE_GET_INDEX(hObj));
+ GDIDBG_TRACELOCKER(hObj);
(void)InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
/* do not assert here for it will call again from dxg.sys it being call twice */
}
DPRINT1("Type = 0x%lx, KernelData = 0x%p, ProcessId = 0x%p\n", Entry->Type, Entry->KernelData, Entry->ProcessId);
GDIDBG_TRACECALLER();
- GDIDBG_TRACEALLOCATOR(GDI_HANDLE_GET_INDEX(hObj));
+ GDIDBG_TRACEALLOCATOR(hObj);
}
}
break;
case GDI_OBJECT_TYPE_DC:
- DC_FreeDcAttr(hObject);
+ // DC_FreeDcAttr(hObject);
break;
}
if(hObj == NULL)
return NULL ;
+ GDIDBG_INITLOOPTRACE();
+
HandleIndex = GDI_HANDLE_GET_INDEX(hObj);
HandleType = GDI_HANDLE_GET_TYPE(hObj);
HandleUpper = GDI_HANDLE_GET_UPPER(hObj);
/* Check that the handle index is valid. */
- if (HandleIndex >= GDI_HANDLE_COUNT)
+ if (HandleIndex >= GDI_HANDLE_COUNT )
return NULL;
Entry = &GdiHandleTable->Entries[HandleIndex];
{
DPRINT1("Tried to lock object (0x%p) of wrong owner! ProcessId = %p, HandleProcessId = %p\n", hObj, ProcessId, HandleProcessId);
GDIDBG_TRACECALLER();
- GDIDBG_TRACEALLOCATOR(GDI_HANDLE_GET_INDEX(hObj));
+ GDIDBG_TRACEALLOCATOR(hObj);
return NULL;
}
/*
* The handle is currently locked, wait some time and try again.
*/
+ GDIDBG_TRACELOOP(hObj, PrevProcId, NULL);
DelayExecution();
continue;
return MappedView;
}
+ /* Locks 2 or 3 objects at a time */
+ VOID
+ INTERNAL_CALL
+ GDIOBJ_LockMultipleObjs(ULONG ulCount,
+ IN HGDIOBJ* ahObj,
+ OUT PGDIOBJ* apObj)
+ {
+ UINT auiIndices[3] = {0,1,2};
+ UINT i, tmp ;
+ BOOL bUnsorted = TRUE;
+
+ /* First is greatest */
+ while(bUnsorted)
+ {
+ bUnsorted = FALSE;
+ for(i=1; i<ulCount; i++)
+ {
+ if((ULONG_PTR)ahObj[auiIndices[i-1]] < (ULONG_PTR)ahObj[auiIndices[i]])
+ {
+ tmp = auiIndices[i-1];
+ auiIndices[i-1] = auiIndices[i];
+ auiIndices[i] = tmp;
+ bUnsorted = TRUE;
+ }
+ }
+ }
+
+ for(i=0;i<ulCount;i++)
+ apObj[auiIndices[i]] = GDIOBJ_LockObj(ahObj[auiIndices[i]], GDI_OBJECT_TYPE_DONTCARE);
+ }
+
+
/** PUBLIC FUNCTIONS **********************************************************/
BOOL
{
pDC = DC_LockDc ( hDC );
MmCopyFromCaller(&pDC->dcattr, pDC->pdcattr, sizeof(DC_ATTR));
+ DC_vFreeDcAttr(pDC);
DC_UnlockDc( pDC );
- DC_FreeDcAttr( hDC ); // Free the dcattr!
-
if (!DC_SetOwnership( hDC, NULL )) // This hDC is inaccessible!
return Ret;
}
palPtr = (PALOBJ*) palGDI;
if (pGDev->flFlags & PDEV_GAMMARAMP_TABLE)
- palGDI->Mode |= PAL_GAMMACORRECTION;
+ palGDI->flFlags |= PAL_GAMMACORRECTION;
else
- palGDI->Mode &= ~PAL_GAMMACORRECTION;
+ palGDI->flFlags &= ~PAL_GAMMACORRECTION;
if (!(pGDev->flFlags & PDEV_DRIVER_PUNTED_CALL)) // No punting, we hook
{
}
else
{
- if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
- DC_vUpdateLineBrush(dc);
-
psurf = dc->dclevel.pSurface;
if (NULL == psurf)
{
if (PATH_IsPathOpen(dc->dclevel))
return PATH_Polyline(dc, pt, Count);
+ DC_vPrepareDCsForBlit(dc, dc->rosdc.CombinedClip->rclBounds,
+ NULL, dc->rosdc.CombinedClip->rclBounds);
+
if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
DC_vUpdateFillBrush(dc);
}
}
+ DC_vFinishBlit(dc, NULL);
+
return Ret;
}
{
DC *dc;
BOOL Ret;
+ RECT rcLockRect ;
dc = DC_LockDc(hDC);
if (!dc)
return TRUE;
}
+ rcLockRect.left = dc->pdcattr->ptlCurrent.x;
+ rcLockRect.top = dc->pdcattr->ptlCurrent.y;
+ rcLockRect.right = XEnd;
+ rcLockRect.bottom = YEnd;
+
+ IntLPtoDP(dc, &rcLockRect, 2);
+
+ /* The DCOrg is in device coordinates */
+ rcLockRect.left += dc->ptlDCOrig.x;
+ rcLockRect.top += dc->ptlDCOrig.y;
+ rcLockRect.right += dc->ptlDCOrig.x;
+ rcLockRect.bottom += dc->ptlDCOrig.y;
+
+ DC_vPrepareDCsForBlit(dc, rcLockRect, NULL, rcLockRect);
+
+ if (dc->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+ DC_vUpdateLineBrush(dc);
+
Ret = IntGdiLineTo(dc, XEnd, YEnd);
+ DC_vFinishBlit(dc, NULL);
+
DC_UnlockDc(dc);
return Ret;
}
static UINT SystemPaletteUse = SYSPAL_NOSTATIC; /* the program need save the pallete and restore it */
- PALETTE gpalRGB, gpalBGR, gpalMono;
+ PALETTE gpalRGB, gpalBGR, gpalMono, gpalRGB555, gpalRGB565, *gppalDefault;
+ PPALETTE appalSurfaceDefault[11];
const PALETTEENTRY g_sysPalTemplate[NB_RESERVED_COLORS] =
{
/* palette_size = visual->map_entries; */
- gpalRGB.Mode = PAL_RGB;
+ gpalRGB.flFlags = PAL_RGB;
gpalRGB.RedMask = RGB(0xFF, 0x00, 0x00);
gpalRGB.GreenMask = RGB(0x00, 0xFF, 0x00);
gpalRGB.BlueMask = RGB(0x00, 0x00, 0xFF);
+ gpalRGB.BaseObject.ulShareCount = 0;
+ gpalRGB.BaseObject.BaseFlags = 0 ;
- gpalBGR.Mode = PAL_BGR;
+ gpalBGR.flFlags = PAL_BGR;
gpalBGR.RedMask = RGB(0x00, 0x00, 0xFF);
gpalBGR.GreenMask = RGB(0x00, 0xFF, 0x00);
gpalBGR.BlueMask = RGB(0xFF, 0x00, 0x00);
+ gpalBGR.BaseObject.ulShareCount = 0;
+ gpalBGR.BaseObject.BaseFlags = 0 ;
+
+ gpalRGB555.flFlags = PAL_RGB16_555 | PAL_BITFIELDS;
+ gpalRGB555.RedMask = 0x7C00;
+ gpalRGB555.GreenMask = 0x3E0;
+ gpalRGB555.BlueMask = 0x1F;
+ gpalRGB555.BaseObject.ulShareCount = 0;
+ gpalRGB555.BaseObject.BaseFlags = 0 ;
+
+ gpalRGB565.flFlags = PAL_RGB16_565 | PAL_BITFIELDS;
+ gpalRGB565.RedMask = 0xF800;
+ gpalRGB565.GreenMask = 0x7E0;
+ gpalRGB565.BlueMask = 0x1F;
+ gpalRGB565.BaseObject.ulShareCount = 0;
+ gpalRGB565.BaseObject.BaseFlags = 0 ;
memset(&gpalMono, 0, sizeof(PALETTE));
- gpalMono.Mode = PAL_MONOCHROME;
+ gpalMono.flFlags = PAL_MONOCHROME;
+ gpalMono.BaseObject.ulShareCount = 0;
+ gpalMono.BaseObject.BaseFlags = 0 ;
+
+ /* Initialize default surface palettes */
+ gppalDefault = PALETTE_ShareLockPalette(hpalette);
+ appalSurfaceDefault[BMF_1BPP] = &gpalMono;
+ appalSurfaceDefault[BMF_4BPP] = gppalDefault;
+ appalSurfaceDefault[BMF_8BPP] = gppalDefault;
+ appalSurfaceDefault[BMF_16BPP] = &gpalRGB565;
+ appalSurfaceDefault[BMF_24BPP] = &gpalBGR;
+ appalSurfaceDefault[BMF_32BPP] = &gpalBGR;
+ appalSurfaceDefault[BMF_4RLE] = gppalDefault;
+ appalSurfaceDefault[BMF_8RLE] = gppalDefault;
+ appalSurfaceDefault[BMF_JPEG] = &gpalRGB;
+ appalSurfaceDefault[BMF_PNG] = &gpalRGB;
return hpalette;
}
NewPalette = PalGDI->BaseObject.hHmgr;
PalGDI->Self = NewPalette;
- PalGDI->Mode = Mode;
+ PalGDI->flFlags = Mode;
if (NULL != Colors)
{
RtlCopyMemory(PalGDI->IndexedColors, Colors, sizeof(PALETTEENTRY) * NumColors);
}
- if (PAL_INDEXED == Mode)
+ if (Mode & PAL_INDEXED)
{
PalGDI->NumColors = NumColors;
}
- else if (PAL_BITFIELDS == Mode)
+ else if (Mode & PAL_BITFIELDS)
{
PalGDI->RedMask = Red;
PalGDI->GreenMask = Green;
PalGDI->BlueMask = Blue;
-
+
if (Red == 0x7c00 && Green == 0x3E0 && Blue == 0x1F)
- PalGDI->Mode |= PAL_RGB16_555;
+ PalGDI->flFlags |= PAL_RGB16_555;
else if (Red == 0xF800 && Green == 0x7E0 && Blue == 0x1F)
- PalGDI->Mode |= PAL_RGB16_565;
+ PalGDI->flFlags |= PAL_RGB16_565;
+ else if (Red == 0xFF0000 && Green == 0xFF00 && Blue == 0xFF)
+ PalGDI->flFlags |= PAL_BGR;
}
PALETTE_UnlockPalette(PalGDI);
NewPalette = PalGDI->BaseObject.hHmgr;
PalGDI->Self = NewPalette;
- PalGDI->Mode = PAL_INDEXED;
+ PalGDI->flFlags = PAL_INDEXED;
PalGDI->IndexedColors = ExAllocatePoolWithTag(PagedPool,
sizeof(PALETTEENTRY) * NumColors,
NTAPI
PALETTE_ulGetNearestIndex(PALETTE* ppal, ULONG ulColor)
{
- if (ppal->Mode & PAL_INDEXED) // use fl & PALINDEXED
+ if (ppal->flFlags & PAL_INDEXED) // use fl & PALINDEXED
return PALETTE_ulGetNearestPaletteIndex(ppal, ulColor);
else
return PALETTE_ulGetNearestBitFieldsIndex(ppal, ulColor);
{
ASSERT(pulColors);
- if (ppal->Mode & PAL_INDEXED || ppal->Mode & PAL_RGB)
+ if (ppal->flFlags & PAL_INDEXED || ppal->flFlags & PAL_RGB)
{
pulColors[0] = RGB(0xFF, 0x00, 0x00);
pulColors[1] = RGB(0x00, 0xFF, 0x00);
pulColors[2] = RGB(0x00, 0x00, 0xFF);
}
- else if (ppal->Mode & PAL_BGR)
+ else if (ppal->flFlags & PAL_BGR)
{
pulColors[0] = RGB(0x00, 0x00, 0xFF);
pulColors[1] = RGB(0x00, 0xFF, 0x00);
pulColors[2] = RGB(0xFF, 0x00, 0x00);
}
- else if (ppal->Mode & PAL_BITFIELDS)
+ else if (ppal->flFlags & PAL_BITFIELDS)
{
pulColors[0] = ppal->RedMask;
pulColors[1] = ppal->GreenMask;
{
HPALETTE Palette;
- Palette = PALETTE_AllocPalette(Mode, NumColors, Colors, Red, Green, Blue);
+ Palette = PALETTE_AllocPalette(Mode, NumColors, Colors, Red, Green, Blue);
if (Palette != NULL)
{
GDIOBJ_SetOwnership(Palette, NULL);
/* NOTE: PaletteEntry ULONGs are in the same order as PALETTEENTRY. */
RtlCopyMemory(PaletteEntry, PalGDI->IndexedColors + Start, sizeof(ULONG) * Colors);
- if (PalGDI->Mode & PAL_GAMMACORRECTION)
+ if (PalGDI->flFlags & PAL_GAMMACORRECTION)
ColorCorrection(PalGDI, (PPALETTEENTRY)PaletteEntry, Colors);
return Colors;
return nearest;
}
- if (palGDI->Mode & PAL_INDEXED)
+ if (palGDI->flFlags & PAL_INDEXED)
{
ULONG index;
index = PALETTE_ulGetNearestPaletteIndex(palGDI, Color);
nearest = PALETTE_ulGetRGBColorFromIndex(palGDI, index);
}
- else if (palGDI->Mode & PAL_RGB || palGDI->Mode & PAL_BGR)
+ else if (palGDI->flFlags & PAL_RGB || palGDI->flFlags & PAL_BGR)
{
nearest = Color;
}
- else if (palGDI->Mode & PAL_BITFIELDS)
+ else if (palGDI->flFlags & PAL_BITFIELDS)
{
RBits = 8 - GetNumberOfBits(palGDI->RedMask);
GBits = 8 - GetNumberOfBits(palGDI->GreenMask);
if (ppal)
{
- if (ppal->Mode & PAL_INDEXED)
+ if (ppal->flFlags & PAL_INDEXED)
{
/* Return closest match for the given RGB color */
index = PALETTE_ulGetNearestPaletteIndex(ppal, crColor);
FLOAT_POINT ellCorners[2];
pPath = PATH_LockPath( dc->dclevel.hPath );
- if (!pPath) return FALSE;
+ if (!pPath) return FALSE;
/* Check that path is open */
if(pPath->state!=PATH_Open)
if ( pPath->state != PATH_Open )
{
Ret = FALSE;
- goto ArcExit;
+ goto ArcExit;
}
/* Check for zero height / width */
pPath = PATH_LockPath( dc->dclevel.hPath );
if (!pPath) return FALSE;
-
+
/* Check that path is open */
if ( pPath->state != PATH_Open )
{
pPath = PATH_LockPath( dc->dclevel.hPath );
if (!pPath) return FALSE;
-
+
/* Check that path is open */
if ( pPath->state != PATH_Open )
{
numStrokes++;
j = 0;
if (numStrokes == 1)
- pStrokes = ExAllocatePoolWithTag(PagedPool, numStrokes * sizeof(PPATH), TAG_PATH);
+ pStrokes = ExAllocatePoolWithTag(PagedPool, numStrokes * sizeof(PPATH), TAG_PATH);
else
{
pOldStrokes = pStrokes; // Save old pointer.
}
}
- pNewPath = ExAllocatePoolWithTag(PagedPool, sizeof(PATH), TAG_PATH);
+ pNewPath = ExAllocatePoolWithTag(PagedPool, sizeof(PATH), TAG_PATH);
PATH_InitGdiPath(pNewPath);
pNewPath->state = PATH_Open;
}
IntGdiCloseFigure( pPath );
- PATH_UnlockPath( pPath );
+ PATH_UnlockPath( pPath );
return TRUE;
}
* PATH_ExtTextOut
*/
BOOL
- FASTCALL
+ FASTCALL
PATH_ExtTextOut(PDC dc, INT x, INT y, UINT flags, const RECTL *lprc,
LPCWSTR str, UINT count, const INT *dx)
{
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE;
- }
+ }
pPath = PATH_LockPath( pDc->dclevel.hPath );
if (!pPath)
{
PPATH pPath;
PDC_ATTR pdcattr;
PDC dc = DC_LockDc ( hDC );
-
+
if ( !dc )
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE;
}
+ DC_vPrepareDCsForBlit(dc, dc->rosdc.CombinedClip->rclBounds,
+ NULL, dc->rosdc.CombinedClip->rclBounds);
+
pdcattr = dc->pdcattr;
if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
}
PATH_UnlockPath( pPath );
+ DC_vFinishBlit(dc, NULL);
DC_UnlockDc ( dc );
return ret;
}
pDc = DC_LockDc(hDC);
if (!pDc)
{
- SetLastWin32Error(ERROR_INVALID_HANDLE);
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
return FALSE;
}
+ DC_vPrepareDCsForBlit(pDc, pDc->rosdc.CombinedClip->rclBounds,
+ NULL, pDc->rosdc.CombinedClip->rclBounds);
+
pdcattr = pDc->pdcattr;
if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
if (bRet) PATH_EmptyPath(pPath);
PATH_UnlockPath( pPath );
+ DC_vFinishBlit(pDc, NULL);
DC_UnlockDc(pDc);
return bRet;
}
return FALSE;
}
+ DC_vPrepareDCsForBlit(pDc, pDc->rosdc.CombinedClip->rclBounds,
+ NULL, pDc->rosdc.CombinedClip->rclBounds);
+
pdcattr = pDc->pdcattr;
if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
DC_vUpdateLineBrush(pDc);
bRet = PATH_StrokePath(pDc, pPath);
+
+ DC_vFinishBlit(pDc, NULL);
PATH_EmptyPath(pPath);
PATH_UnlockPath( pPath );
NtGdiWidenPath(HDC hDC)
{
BOOL Ret;
- PDC pdc = DC_LockDc ( hDC );
+ PDC pdc = DC_LockDc ( hDC );
if ( !pdc )
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
{
HPEN hPen;
PBRUSH pbrushPen;
- static const BYTE PatternAlternate[] = {0x55, 0x55, 0x55};
- static const BYTE PatternDash[] = {0xFF, 0xFF, 0xC0};
- static const BYTE PatternDot[] = {0xE3, 0x8E, 0x38};
- static const BYTE PatternDashDot[] = {0xFF, 0x81, 0xC0};
- static const BYTE PatternDashDotDot[] = {0xFF, 0x8E, 0x38};
+ static const BYTE PatternAlternate[] = {0x55, 0x55, 0x55, 0};
+ static const BYTE PatternDash[] = {0xFF, 0xFF, 0xC0, 0};
+ static const BYTE PatternDot[] = {0xE3, 0x8E, 0x38, 0};
+ static const BYTE PatternDashDot[] = {0xFF, 0x81, 0xC0, 0};
+ static const BYTE PatternDashDotDot[] = {0xFF, 0x8E, 0x38, 0};
dwWidth = abs(dwWidth);
case PS_ALTERNATE:
pbrushPen->flAttrs |= GDIBRUSH_IS_BITMAP;
- pbrushPen->hbmPattern = IntGdiCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternAlternate);
+ pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternAlternate);
break;
case PS_DOT:
pbrushPen->flAttrs |= GDIBRUSH_IS_BITMAP;
- pbrushPen->hbmPattern = IntGdiCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDot);
+ pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDot);
break;
case PS_DASH:
pbrushPen->flAttrs |= GDIBRUSH_IS_BITMAP;
- pbrushPen->hbmPattern = IntGdiCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDash);
+ pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDash);
break;
case PS_DASHDOT:
pbrushPen->flAttrs |= GDIBRUSH_IS_BITMAP;
- pbrushPen->hbmPattern = IntGdiCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDashDot);
+ pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDashDot);
break;
case PS_DASHDOTDOT:
pbrushPen->flAttrs |= GDIBRUSH_IS_BITMAP;
- pbrushPen->hbmPattern = IntGdiCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDashDotDot);
+ pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDashDotDot);
break;
case PS_INSIDEFRAME:
else if (pDC->dclevel.prgnMeta) hSrc = ((PROSRGNDATA)pDC->dclevel.prgnMeta)->BaseObject.hHmgr;
break;
case SYSRGN:
- if (pDC->prgnVis) hSrc = ((PROSRGNDATA)pDC->prgnVis)->BaseObject.hHmgr;
+ if (pDC->prgnVis) hSrc = pDC->prgnVis->BaseObject.hHmgr;
break;
default:
hSrc = 0;
StockObjects[NULL_PEN] = IntCreateStockPen(NullPen.lopnStyle, NullPen.lopnWidth.x, BS_SOLID, NullPen.lopnColor);
StockObjects[20] = NULL; /* TODO: Unknown internal stock object */
- StockObjects[DEFAULT_BITMAP] = IntGdiCreateBitmap(1, 1, 1, 1, NULL);
+ StockObjects[DEFAULT_BITMAP] = GreCreateBitmap(1, 1, 1, 1, NULL);
(void) TextIntCreateFontIndirect(&OEMFixedFont, (HFONT*)&StockObjects[OEM_FIXED_FONT]);
(void) TextIntCreateFontIndirect(&AnsiFixedFont, (HFONT*)&StockObjects[ANSI_FIXED_FONT]);
(void) TextIntCreateFontIndirect(&SystemFixedFont, (HFONT*)&StockObjects[SYSTEM_FIXED_FONT]);
(void) TextIntCreateFontIndirect(&DefaultGuiFont, (HFONT*)&StockObjects[DEFAULT_GUI_FONT]);
- StockObjects[DEFAULT_PALETTE] = (HGDIOBJ)PALETTE_Init();
+ StockObjects[DEFAULT_PALETTE] = (HGDIOBJ)gppalDefault->BaseObject.hHmgr;
for (Object = 0; Object < NB_STOCK_OBJECTS; Object++)
{
return NULL;
}
- /*
- * @unimplemented
- */
- LPWSTR
- APIENTRY
- EngGetDriverName ( IN HDEV hdev )
- {
- // www.osr.com/ddk/graphics/gdifncs_2gx3.htm
- UNIMPLEMENTED;
- return NULL;
- }
-
/*
* @unimplemented
*/