Wine-devel
Threads by month
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
September 2021
- 83 participants
- 748 discussions
Unless explicitly turned off decoding of gzip, deflate is supported.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47505
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/wininet/internet.c | 1 +
dlls/wininet/internet.h | 2 +-
dlls/wininet/tests/http.c | 62 +++++++++++++++++++++++++++++++++++++++
3 files changed, 64 insertions(+), 1 deletion(-)
diff --git a/dlls/wininet/internet.c b/dlls/wininet/internet.c
index cef151c7bf2..4ac66660aa3 100644
--- a/dlls/wininet/internet.c
+++ b/dlls/wininet/internet.c
@@ -107,6 +107,7 @@ void *alloc_object(object_header_t *parent, const object_vtbl_t *vtbl, size_t si
if(!ret)
return NULL;
+ ret->decoding = -1;
list_init(&ret->children);
EnterCriticalSection( &WININET_cs );
diff --git a/dlls/wininet/internet.h b/dlls/wininet/internet.h
index e9d68e2c2d9..462c7a47635 100644
--- a/dlls/wininet/internet.h
+++ b/dlls/wininet/internet.h
@@ -283,7 +283,7 @@ struct _object_header_t
ULONG ErrorMask;
DWORD dwInternalFlags;
LONG refs;
- BOOL decoding;
+ INT decoding;
INTERNET_STATUS_CALLBACK lpfnStatusCB;
struct list entry;
struct list children;
diff --git a/dlls/wininet/tests/http.c b/dlls/wininet/tests/http.c
index d32f01be2c5..ed35025d5f4 100644
--- a/dlls/wininet/tests/http.c
+++ b/dlls/wininet/tests/http.c
@@ -3523,6 +3523,67 @@ static void test_not_modified(int port)
InternetCloseHandle(ses);
}
+static void test_deflate(int port)
+{
+ DWORD len;
+ char buf[256];
+ HINTERNET ses, con, req;
+ BOOL ret;
+ BOOL b;
+ char binary[] = "\x1f\x8b\x08";
+ char text[] = "<!DOCTYPE HTML PUBLIC";
+
+ ses = InternetOpenA("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
+ ok(ses != NULL, "InternetOpen failed\n");
+
+ con = InternetConnectA(ses, "test.winehq.org", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
+ ok(con != NULL, "InternetConnect failed\n");
+
+ /* Default Decoding */
+ req = HttpOpenRequestA(con, NULL, "/tests/gzip.php", NULL, NULL, NULL, 0, 0);
+ ok(req != NULL, "HttpOpenRequest failed\n");
+
+ SetLastError(0xdeadbeef);
+ ret = HttpSendRequestW(req, L"Accept-Encoding: gzip, deflate", ~0u, NULL, 0);
+ ok(ret, "HttpSendRequest failed: %u\n", GetLastError());
+ test_status_code(req, 200);
+
+ len = sizeof(buf)-1;
+ ret = HttpQueryInfoA(req, HTTP_QUERY_CONTENT_LENGTH, buf, &len, 0);
+ ok(!ret, "HttpQueryInfo should have failed\n");
+ ok(GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND , "got %u\n", GetLastError());
+
+ ret = InternetReadFile(req, buf, 256, &len);
+ ok(ret, "InternetReadFile failed %d\n", GetLastError());
+ ok(!strncmp(buf, text, strlen(text)), "got %s\n", debugstr_a(buf));
+
+ InternetCloseHandle(req);
+ InternetCloseHandle(con);
+
+ /* Disabled Decoding */
+ b = FALSE;
+ InternetSetOptionA(ses, INTERNET_OPTION_HTTP_DECODING, &b, sizeof(b));
+
+ con = InternetConnectA(ses, "test.winehq.org", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
+ ok(con != NULL, "InternetConnect failed\n");
+
+ req = HttpOpenRequestA(con, NULL, "/tests/gzip.php", NULL, NULL, NULL, 0, 0);
+ ok(req != NULL, "HttpOpenRequest failed\n");
+
+ SetLastError(0xdeadbeef);
+ ret = HttpSendRequestW(req, L"Accept-Encoding: gzip, deflate", ~0u, NULL, 0);
+ ok(ret, "HttpSendRequest failed: %u\n", GetLastError());
+ test_status_code(req, 200);
+
+ ret = InternetReadFile(req, buf, 256, &len);
+ ok(ret, "InternetReadFile failed %d\n", GetLastError());
+ ok(!strncmp(buf, binary, strlen(binary)), "got %s\n", debugstr_a(buf));
+
+ InternetCloseHandle(req);
+ InternetCloseHandle(con);
+ InternetCloseHandle(ses);
+}
+
static void test_conn_close(int port)
{
HINTERNET session, connection, req;
@@ -6097,6 +6158,7 @@ static void test_http_connection(void)
test_options(si.port);
test_no_content(si.port);
test_not_modified(si.port);
+ test_deflate(si.port);
test_conn_close(si.port);
test_no_cache(si.port);
test_cache_read_gzipped(si.port);
--
2.33.0
2
1
04 Sep '21
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/wininet/http.c | 4 +++-
dlls/wininet/tests/http.c | 37 +++++++++++++++++++++++++++++++++++++
2 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c
index e9363208471..4bfd93aa3be 100644
--- a/dlls/wininet/http.c
+++ b/dlls/wininet/http.c
@@ -2918,7 +2918,9 @@ static DWORD set_content_length(http_request_t *request)
WCHAR encoding[20];
DWORD size;
- if(request->status_code == HTTP_STATUS_NO_CONTENT || !wcscmp(request->verb, L"HEAD")) {
+ if(request->status_code == HTTP_STATUS_NO_CONTENT || request->status_code == HTTP_STATUS_NOT_MODIFIED ||
+ !wcscmp(request->verb, L"HEAD"))
+ {
request->contentLength = request->netconn_stream.content_length = 0;
return ERROR_SUCCESS;
}
diff --git a/dlls/wininet/tests/http.c b/dlls/wininet/tests/http.c
index bf4dce80bef..d32f01be2c5 100644
--- a/dlls/wininet/tests/http.c
+++ b/dlls/wininet/tests/http.c
@@ -2381,6 +2381,11 @@ static DWORD CALLBACK server_thread(LPVOID param)
static const char nocontentmsg[] = "HTTP/1.1 204 No Content\r\nConnection: close\r\n\r\n";
send(c, nocontentmsg, sizeof(nocontentmsg)-1, 0);
}
+ if (strstr(buffer, "GET /test_not_modified"))
+ {
+ static const char notmodifiedmsg[] = "HTTP/1.1 304 Not Modified\r\nConnection: close\r\n\r\n";
+ send(c, notmodifiedmsg, sizeof(notmodifiedmsg)-1, 0);
+ }
if (strstr(buffer, "GET /test_conn_close"))
{
static const char conn_close_response[] = "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\nsome content";
@@ -3487,6 +3492,37 @@ static void test_no_content(int port)
CHECK_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
}
+static void test_not_modified(int port)
+{
+ DWORD len;
+ char buf[256];
+ HINTERNET ses, con, req;
+ BOOL ret;
+
+ ses = InternetOpenA("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
+ ok(ses != NULL, "InternetOpen failed\n");
+
+ con = InternetConnectA(ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
+ ok(con != NULL, "InternetConnect failed\n");
+
+ req = HttpOpenRequestA(con, NULL, "/test_not_modified", NULL, NULL, NULL, 0, 0);
+ ok(req != NULL, "HttpOpenRequest failed\n");
+
+ SetLastError(0xdeadbeef);
+ ret = HttpSendRequestW(req, NULL, 0, NULL, 0);
+ ok(ret, "HttpSendRequest failed: %u\n", GetLastError());
+ test_status_code(req, 304);
+
+ len = sizeof(buf)-1;
+ ret = HttpQueryInfoA(req, HTTP_QUERY_CONTENT_LENGTH, buf, &len, 0);
+ ok(!ret, "HttpQueryInfo should have failed\n");
+ ok(GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND , "got %u\n", GetLastError());
+
+ InternetCloseHandle(req);
+ InternetCloseHandle(con);
+ InternetCloseHandle(ses);
+}
+
static void test_conn_close(int port)
{
HINTERNET session, connection, req;
@@ -6060,6 +6096,7 @@ static void test_http_connection(void)
test_HttpSendRequestW(si.port);
test_options(si.port);
test_no_content(si.port);
+ test_not_modified(si.port);
test_conn_close(si.port);
test_no_cache(si.port);
test_cache_read_gzipped(si.port);
--
2.33.0
2
1
03 Sep '21
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
server/fd.c | 61 ++++++++++++++++++++++++++++-------------------------
1 file changed, 32 insertions(+), 29 deletions(-)
diff --git a/server/fd.c b/server/fd.c
index a09fc9edfcf..79ddd0a96a9 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -385,41 +385,44 @@ timeout_t monotonic_time;
struct _KUSER_SHARED_DATA *user_shared_data = NULL;
static const int user_shared_data_timeout = 16;
+static void atomic_store_ulong(volatile ULONG *ptr, ULONG value)
+{
+ /* on x86 there should be total store order guarantees, so volatile is
+ * enough to ensure the stores aren't reordered by the compiler, and then
+ * they will always be seen in-order from other CPUs. On other archs, we
+ * need atomic intrinsics to guarantee that. */
+#if defined(__i386__) || defined(__x86_64__)
+ *ptr = value;
+#else
+ __atomic_store_n(ptr, value, __ATOMIC_SEQ_CST);
+#endif
+}
+
+static void atomic_store_long(volatile LONG *ptr, LONG value)
+{
+#if defined(__i386__) || defined(__x86_64__)
+ *ptr = value;
+#else
+ __atomic_store_n(ptr, value, __ATOMIC_SEQ_CST);
+#endif
+}
+
static void set_user_shared_data_time(void)
{
timeout_t tick_count = monotonic_time / 10000;
- /* on X86 there should be total store order guarantees, so volatile is enough
- * to ensure the stores aren't reordered by the compiler, and then they will
- * always be seen in-order from other CPUs. On other archs, we need atomic
- * intrinsics to guarantee that. */
-#if defined(__i386__) || defined(__x86_64__)
- user_shared_data->SystemTime.High2Time = current_time >> 32;
- user_shared_data->SystemTime.LowPart = current_time;
- user_shared_data->SystemTime.High1Time = current_time >> 32;
+ atomic_store_long(&user_shared_data->SystemTime.High2Time, current_time >> 32);
+ atomic_store_ulong(&user_shared_data->SystemTime.LowPart, current_time);
+ atomic_store_long(&user_shared_data->SystemTime.High1Time, current_time >> 32);
- user_shared_data->InterruptTime.High2Time = monotonic_time >> 32;
- user_shared_data->InterruptTime.LowPart = monotonic_time;
- user_shared_data->InterruptTime.High1Time = monotonic_time >> 32;
+ atomic_store_long(&user_shared_data->InterruptTime.High2Time, monotonic_time >> 32);
+ atomic_store_ulong(&user_shared_data->InterruptTime.LowPart, monotonic_time);
+ atomic_store_long(&user_shared_data->InterruptTime.High1Time, monotonic_time >> 32);
- user_shared_data->TickCount.High2Time = tick_count >> 32;
- user_shared_data->TickCount.LowPart = tick_count;
- user_shared_data->TickCount.High1Time = tick_count >> 32;
- *(volatile ULONG *)&user_shared_data->TickCountLowDeprecated = tick_count;
-#else
- __atomic_store_n(&user_shared_data->SystemTime.High2Time, current_time >> 32, __ATOMIC_SEQ_CST);
- __atomic_store_n(&user_shared_data->SystemTime.LowPart, current_time, __ATOMIC_SEQ_CST);
- __atomic_store_n(&user_shared_data->SystemTime.High1Time, current_time >> 32, __ATOMIC_SEQ_CST);
-
- __atomic_store_n(&user_shared_data->InterruptTime.High2Time, monotonic_time >> 32, __ATOMIC_SEQ_CST);
- __atomic_store_n(&user_shared_data->InterruptTime.LowPart, monotonic_time, __ATOMIC_SEQ_CST);
- __atomic_store_n(&user_shared_data->InterruptTime.High1Time, monotonic_time >> 32, __ATOMIC_SEQ_CST);
-
- __atomic_store_n(&user_shared_data->TickCount.High2Time, tick_count >> 32, __ATOMIC_SEQ_CST);
- __atomic_store_n(&user_shared_data->TickCount.LowPart, tick_count, __ATOMIC_SEQ_CST);
- __atomic_store_n(&user_shared_data->TickCount.High1Time, tick_count >> 32, __ATOMIC_SEQ_CST);
- __atomic_store_n(&user_shared_data->TickCountLowDeprecated, tick_count, __ATOMIC_SEQ_CST);
-#endif
+ atomic_store_long(&user_shared_data->TickCount.High2Time, tick_count >> 32);
+ atomic_store_ulong(&user_shared_data->TickCount.LowPart, tick_count);
+ atomic_store_long(&user_shared_data->TickCount.High1Time, tick_count >> 32);
+ atomic_store_ulong(&user_shared_data->TickCountLowDeprecated, tick_count);
}
void set_current_time(void)
--
2.33.0
1
1
03 Sep '21
Signed-off-by: Francois Gouget <fgouget(a)free.fr>
---
dlls/windowscodecs/libjpeg.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/dlls/windowscodecs/libjpeg.c b/dlls/windowscodecs/libjpeg.c
index 96a9b79f358..dff13c90db2 100644
--- a/dlls/windowscodecs/libjpeg.c
+++ b/dlls/windowscodecs/libjpeg.c
@@ -535,7 +535,7 @@ static void dest_mgr_term_destination(j_compress_ptr cinfo)
}
}
-HRESULT CDECL jpeg_encoder_initialize(struct encoder* iface, IStream *stream)
+static HRESULT CDECL jpeg_encoder_initialize(struct encoder* iface, IStream *stream)
{
struct jpeg_encoder *This = impl_from_encoder(iface);
jmp_buf jmpbuf;
@@ -570,7 +570,7 @@ HRESULT CDECL jpeg_encoder_initialize(struct encoder* iface, IStream *stream)
return S_OK;
}
-HRESULT CDECL jpeg_encoder_get_supported_format(struct encoder* iface, GUID *pixel_format,
+static HRESULT CDECL jpeg_encoder_get_supported_format(struct encoder* iface, GUID *pixel_format,
DWORD *bpp, BOOL *indexed)
{
int i;
@@ -590,7 +590,7 @@ HRESULT CDECL jpeg_encoder_get_supported_format(struct encoder* iface, GUID *pix
return S_OK;
}
-HRESULT CDECL jpeg_encoder_create_frame(struct encoder* iface, const struct encoder_frame *frame)
+static HRESULT CDECL jpeg_encoder_create_frame(struct encoder* iface, const struct encoder_frame *frame)
{
struct jpeg_encoder *This = impl_from_encoder(iface);
jmp_buf jmpbuf;
@@ -629,7 +629,7 @@ HRESULT CDECL jpeg_encoder_create_frame(struct encoder* iface, const struct enco
return S_OK;
}
-HRESULT CDECL jpeg_encoder_write_lines(struct encoder* iface, BYTE *data,
+static HRESULT CDECL jpeg_encoder_write_lines(struct encoder* iface, BYTE *data,
DWORD line_count, DWORD stride)
{
struct jpeg_encoder *This = impl_from_encoder(iface);
@@ -690,7 +690,7 @@ HRESULT CDECL jpeg_encoder_write_lines(struct encoder* iface, BYTE *data,
return S_OK;
}
-HRESULT CDECL jpeg_encoder_commit_frame(struct encoder* iface)
+static HRESULT CDECL jpeg_encoder_commit_frame(struct encoder* iface)
{
struct jpeg_encoder *This = impl_from_encoder(iface);
jmp_buf jmpbuf;
@@ -705,12 +705,12 @@ HRESULT CDECL jpeg_encoder_commit_frame(struct encoder* iface)
return S_OK;
}
-HRESULT CDECL jpeg_encoder_commit_file(struct encoder* iface)
+static HRESULT CDECL jpeg_encoder_commit_file(struct encoder* iface)
{
return S_OK;
}
-void CDECL jpeg_encoder_destroy(struct encoder* iface)
+static void CDECL jpeg_encoder_destroy(struct encoder* iface)
{
struct jpeg_encoder *This = impl_from_encoder(iface);
if (This->cinfo_initialized)
--
2.30.2
2
1
[PATCH v3 1/3] ntoskrnl.exe/tests: Move driver testing helpers to a separate file.
by Rémi Bernon 03 Sep '21
by Rémi Bernon 03 Sep '21
03 Sep '21
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
v3: Add a check that the service is started as it should be, or consider
that the machine doesn't support test signed drivers.
According to https://testbot.winehq.org/JobDetails.pl?Key=96764 it
should be fine now.
dlls/ntoskrnl.exe/tests/driver_tests.h | 577 ++++++++++++++++++++++
dlls/ntoskrnl.exe/tests/ntoskrnl.c | 632 +------------------------
2 files changed, 595 insertions(+), 614 deletions(-)
create mode 100644 dlls/ntoskrnl.exe/tests/driver_tests.h
diff --git a/dlls/ntoskrnl.exe/tests/driver_tests.h b/dlls/ntoskrnl.exe/tests/driver_tests.h
new file mode 100644
index 00000000000..b3a25e4d563
--- /dev/null
+++ b/dlls/ntoskrnl.exe/tests/driver_tests.h
@@ -0,0 +1,577 @@
+/*
+ * ntoskrnl.exe testing framework
+ *
+ * Copyright 2015 Sebastian Lackner
+ * Copyright 2015 Michael Müller
+ * Copyright 2015 Christian Costa
+ * Copyright 2020-2021 Zebediah Figura for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <time.h>
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winbase.h"
+#include "winioctl.h"
+#include "winternl.h"
+#include "winuser.h"
+#include "winnls.h"
+#include "winsvc.h"
+#include "winreg.h"
+#include "wincrypt.h"
+
+#include "mscat.h"
+#include "newdev.h"
+#include "ntsecapi.h"
+#include "objbase.h"
+#include "setupapi.h"
+
+#include "wine/mssign.h"
+#include "wine/test.h"
+
+#include "driver.h"
+
+static HANDLE test_data_mapping;
+static struct test_data *test_data;
+
+static HRESULT (WINAPI *pSignerSign)(SIGNER_SUBJECT_INFO *subject, SIGNER_CERT *cert,
+ SIGNER_SIGNATURE_INFO *signature, SIGNER_PROVIDER_INFO *provider,
+ const WCHAR *timestamp, CRYPT_ATTRIBUTES *attr, void *sip_data);
+
+#define load_resource (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : load_resource_
+static void load_resource_(const WCHAR *name, WCHAR *filename)
+{
+ static WCHAR path[MAX_PATH];
+ DWORD written;
+ HANDLE file;
+ HRSRC res;
+ void *ptr;
+
+ GetTempPathW(ARRAY_SIZE(path), path);
+ GetTempFileNameW(path, name, 0, filename);
+
+ file = CreateFileW(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
+ winetest_ok(file != INVALID_HANDLE_VALUE, "failed to create %s, error %u\n", debugstr_w(filename), GetLastError());
+
+ res = FindResourceW(NULL, name, L"TESTDLL");
+ winetest_ok( res != 0, "couldn't find resource\n" );
+ ptr = LockResource( LoadResource( GetModuleHandleA(NULL), res ));
+ WriteFile( file, ptr, SizeofResource( GetModuleHandleA(NULL), res ), &written, NULL );
+ winetest_ok( written == SizeofResource( GetModuleHandleA(NULL), res ), "couldn't write resource\n" );
+ CloseHandle( file );
+}
+
+struct testsign_context
+{
+ HCRYPTPROV provider;
+ const CERT_CONTEXT *cert, *root_cert, *publisher_cert;
+ HCERTSTORE root_store, publisher_store;
+};
+
+static BOOL testsign_create_cert(struct testsign_context *ctx)
+{
+ BYTE encoded_name[100], encoded_key_id[200], public_key_info_buffer[1000];
+ WCHAR container_name[26];
+ BYTE hash_buffer[16], cert_buffer[1000], provider_nameA[100], serial[16];
+ CERT_PUBLIC_KEY_INFO *public_key_info = (CERT_PUBLIC_KEY_INFO *)public_key_info_buffer;
+ CRYPT_KEY_PROV_INFO provider_info = {0};
+ CRYPT_ALGORITHM_IDENTIFIER algid = {0};
+ CERT_AUTHORITY_KEY_ID_INFO key_info;
+ CERT_INFO cert_info = {0};
+ WCHAR provider_nameW[100];
+ CERT_EXTENSION extension;
+ HCRYPTKEY key;
+ DWORD size;
+ BOOL ret;
+
+ memset(ctx, 0, sizeof(*ctx));
+
+ srand(time(NULL));
+ swprintf(container_name, ARRAY_SIZE(container_name), L"wine_testsign%u", rand());
+
+ ret = CryptAcquireContextW(&ctx->provider, container_name, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET);
+ winetest_ok(ret, "Failed to create container, error %#x\n", GetLastError());
+
+ ret = CryptGenKey(ctx->provider, AT_SIGNATURE, CRYPT_EXPORTABLE, &key);
+ winetest_ok(ret, "Failed to create key, error %#x\n", GetLastError());
+ ret = CryptDestroyKey(key);
+ winetest_ok(ret, "Failed to destroy key, error %#x\n", GetLastError());
+ ret = CryptGetUserKey(ctx->provider, AT_SIGNATURE, &key);
+ winetest_ok(ret, "Failed to get user key, error %#x\n", GetLastError());
+ ret = CryptDestroyKey(key);
+ winetest_ok(ret, "Failed to destroy key, error %#x\n", GetLastError());
+
+ size = sizeof(encoded_name);
+ ret = CertStrToNameA(X509_ASN_ENCODING, "CN=winetest_cert", CERT_X500_NAME_STR, NULL, encoded_name, &size, NULL);
+ winetest_ok(ret, "Failed to convert name, error %#x\n", GetLastError());
+ key_info.CertIssuer.cbData = size;
+ key_info.CertIssuer.pbData = encoded_name;
+
+ size = sizeof(public_key_info_buffer);
+ ret = CryptExportPublicKeyInfo(ctx->provider, AT_SIGNATURE, X509_ASN_ENCODING, public_key_info, &size);
+ winetest_ok(ret, "Failed to export public key, error %#x\n", GetLastError());
+ cert_info.SubjectPublicKeyInfo = *public_key_info;
+
+ size = sizeof(hash_buffer);
+ ret = CryptHashPublicKeyInfo(ctx->provider, CALG_MD5, 0, X509_ASN_ENCODING, public_key_info, hash_buffer, &size);
+ winetest_ok(ret, "Failed to hash public key, error %#x\n", GetLastError());
+
+ key_info.KeyId.cbData = size;
+ key_info.KeyId.pbData = hash_buffer;
+
+ RtlGenRandom(serial, sizeof(serial));
+ key_info.CertSerialNumber.cbData = sizeof(serial);
+ key_info.CertSerialNumber.pbData = serial;
+
+ size = sizeof(encoded_key_id);
+ ret = CryptEncodeObject(X509_ASN_ENCODING, X509_AUTHORITY_KEY_ID, &key_info, encoded_key_id, &size);
+ winetest_ok(ret, "Failed to convert name, error %#x\n", GetLastError());
+
+ extension.pszObjId = (char *)szOID_AUTHORITY_KEY_IDENTIFIER;
+ extension.fCritical = TRUE;
+ extension.Value.cbData = size;
+ extension.Value.pbData = encoded_key_id;
+
+ cert_info.dwVersion = CERT_V3;
+ cert_info.SerialNumber = key_info.CertSerialNumber;
+ cert_info.SignatureAlgorithm.pszObjId = (char *)szOID_RSA_SHA1RSA;
+ cert_info.Issuer = key_info.CertIssuer;
+ GetSystemTimeAsFileTime(&cert_info.NotBefore);
+ GetSystemTimeAsFileTime(&cert_info.NotAfter);
+ cert_info.NotAfter.dwHighDateTime += 1;
+ cert_info.Subject = key_info.CertIssuer;
+ cert_info.cExtension = 1;
+ cert_info.rgExtension = &extension;
+ algid.pszObjId = (char *)szOID_RSA_SHA1RSA;
+ size = sizeof(cert_buffer);
+ ret = CryptSignAndEncodeCertificate(ctx->provider, AT_SIGNATURE, X509_ASN_ENCODING,
+ X509_CERT_TO_BE_SIGNED, &cert_info, &algid, NULL, cert_buffer, &size);
+ winetest_ok(ret, "Failed to create certificate, error %#x\n", GetLastError());
+
+ ctx->cert = CertCreateCertificateContext(X509_ASN_ENCODING, cert_buffer, size);
+ winetest_ok(!!ctx->cert, "Failed to create context, error %#x\n", GetLastError());
+
+ size = sizeof(provider_nameA);
+ ret = CryptGetProvParam(ctx->provider, PP_NAME, provider_nameA, &size, 0);
+ winetest_ok(ret, "Failed to get prov param, error %#x\n", GetLastError());
+ MultiByteToWideChar(CP_ACP, 0, (char *)provider_nameA, -1, provider_nameW, ARRAY_SIZE(provider_nameW));
+
+ provider_info.pwszContainerName = (WCHAR *)container_name;
+ provider_info.pwszProvName = provider_nameW;
+ provider_info.dwProvType = PROV_RSA_FULL;
+ provider_info.dwKeySpec = AT_SIGNATURE;
+ ret = CertSetCertificateContextProperty(ctx->cert, CERT_KEY_PROV_INFO_PROP_ID, 0, &provider_info);
+ winetest_ok(ret, "Failed to set provider info, error %#x\n", GetLastError());
+
+ ctx->root_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_A, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, "root");
+ if (!ctx->root_store && GetLastError() == ERROR_ACCESS_DENIED)
+ {
+ winetest_skip("Failed to open root store.\n");
+
+ ret = CertFreeCertificateContext(ctx->cert);
+ winetest_ok(ret, "Failed to free certificate, error %u\n", GetLastError());
+ ret = CryptReleaseContext(ctx->provider, 0);
+ winetest_ok(ret, "failed to release context, error %u\n", GetLastError());
+
+ return FALSE;
+ }
+ winetest_ok(!!ctx->root_store, "Failed to open store, error %u\n", GetLastError());
+ ret = CertAddCertificateContextToStore(ctx->root_store, ctx->cert, CERT_STORE_ADD_ALWAYS, &ctx->root_cert);
+ if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
+ {
+ winetest_skip("Failed to add self-signed certificate to store.\n");
+
+ ret = CertFreeCertificateContext(ctx->cert);
+ winetest_ok(ret, "Failed to free certificate, error %u\n", GetLastError());
+ ret = CertCloseStore(ctx->root_store, CERT_CLOSE_STORE_CHECK_FLAG);
+ winetest_ok(ret, "Failed to close store, error %u\n", GetLastError());
+ ret = CryptReleaseContext(ctx->provider, 0);
+ winetest_ok(ret, "failed to release context, error %u\n", GetLastError());
+
+ return FALSE;
+ }
+ winetest_ok(ret, "Failed to add certificate, error %u\n", GetLastError());
+
+ ctx->publisher_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_A, 0, 0,
+ CERT_SYSTEM_STORE_LOCAL_MACHINE, "trustedpublisher");
+ winetest_ok(!!ctx->publisher_store, "Failed to open store, error %u\n", GetLastError());
+ ret = CertAddCertificateContextToStore(ctx->publisher_store, ctx->cert,
+ CERT_STORE_ADD_ALWAYS, &ctx->publisher_cert);
+ winetest_ok(ret, "Failed to add certificate, error %u\n", GetLastError());
+
+ return TRUE;
+}
+
+static void testsign_cleanup(struct testsign_context *ctx)
+{
+ BOOL ret;
+
+ ret = CertFreeCertificateContext(ctx->cert);
+ winetest_ok(ret, "Failed to free certificate, error %u\n", GetLastError());
+
+ ret = CertDeleteCertificateFromStore(ctx->root_cert);
+ winetest_ok(ret, "Failed to remove certificate, error %u\n", GetLastError());
+ ret = CertCloseStore(ctx->root_store, CERT_CLOSE_STORE_CHECK_FLAG);
+ winetest_ok(ret, "Failed to close store, error %u\n", GetLastError());
+
+ ret = CertDeleteCertificateFromStore(ctx->publisher_cert);
+ winetest_ok(ret, "Failed to remove certificate, error %u\n", GetLastError());
+ ret = CertCloseStore(ctx->publisher_store, CERT_CLOSE_STORE_CHECK_FLAG);
+ winetest_ok(ret, "Failed to close store, error %u\n", GetLastError());
+
+ ret = CryptReleaseContext(ctx->provider, 0);
+ winetest_ok(ret, "failed to release context, error %u\n", GetLastError());
+}
+
+#define testsign_sign (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : testsign_sign_
+static void testsign_sign_(struct testsign_context *ctx, const WCHAR *filename)
+{
+ SIGNER_ATTR_AUTHCODE authcode = {sizeof(authcode)};
+ SIGNER_SIGNATURE_INFO signature = {sizeof(signature)};
+ SIGNER_SUBJECT_INFO subject = {sizeof(subject)};
+ SIGNER_CERT_STORE_INFO store = {sizeof(store)};
+ SIGNER_CERT cert_info = {sizeof(cert_info)};
+ SIGNER_FILE_INFO file = {sizeof(file)};
+ DWORD index = 0;
+ HRESULT hr;
+
+ subject.dwSubjectChoice = 1;
+ subject.pdwIndex = &index;
+ subject.pSignerFileInfo = &file;
+ file.pwszFileName = (WCHAR *)filename;
+ cert_info.dwCertChoice = 2;
+ cert_info.pCertStoreInfo = &store;
+ store.pSigningCert = ctx->cert;
+ store.dwCertPolicy = 0;
+ signature.algidHash = CALG_SHA_256;
+ signature.dwAttrChoice = SIGNER_AUTHCODE_ATTR;
+ signature.pAttrAuthcode = &authcode;
+ authcode.pwszName = L"";
+ authcode.pwszInfo = L"";
+ hr = pSignerSign(&subject, &cert_info, &signature, NULL, NULL, NULL, NULL);
+ todo_wine winetest_ok(hr == S_OK || broken(hr == NTE_BAD_ALGID) /* < 7 */, "Failed to sign, hr %#x\n", hr);
+}
+
+#define unload_driver (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : unload_driver_
+static void unload_driver_(SC_HANDLE service)
+{
+ SERVICE_STATUS status;
+
+ ControlService(service, SERVICE_CONTROL_STOP, &status);
+ while (status.dwCurrentState == SERVICE_STOP_PENDING)
+ {
+ BOOL ret;
+ Sleep(100);
+ ret = QueryServiceStatus(service, &status);
+ winetest_ok(ret, "QueryServiceStatus failed: %u\n", GetLastError());
+ }
+ winetest_ok(status.dwCurrentState == SERVICE_STOPPED,
+ "expected SERVICE_STOPPED, got %d\n", status.dwCurrentState);
+
+ DeleteService(service);
+ CloseServiceHandle(service);
+}
+
+static HANDLE okfile;
+
+static void cat_okfile(void)
+{
+ char buffer[512];
+ DWORD size;
+
+ SetFilePointer(okfile, 0, NULL, FILE_BEGIN);
+
+ do
+ {
+ ReadFile(okfile, buffer, sizeof(buffer), &size, NULL);
+ printf("%.*s", size, buffer);
+ } while (size == sizeof(buffer));
+
+ SetFilePointer(okfile, 0, NULL, FILE_BEGIN);
+ SetEndOfFile(okfile);
+
+ winetest_add_failures(InterlockedExchange(&test_data->failures, 0));
+ winetest_add_failures(InterlockedExchange(&test_data->todo_failures, 0));
+}
+
+#ifdef __i386__
+#define EXT "x86"
+#elif defined(__x86_64__)
+#define EXT "amd64"
+#elif defined(__arm__)
+#define EXT "arm"
+#elif defined(__aarch64__)
+#define EXT "arm64"
+#else
+#define EXT
+#endif
+
+static const char inf_text[] =
+ "[Version]\n"
+ "Signature=$Chicago$\n"
+ "ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318}\n"
+ "CatalogFile=winetest.cat\n"
+ "DriverVer=09/21/2006,6.0.5736.1\n"
+
+ "[Manufacturer]\n"
+ "Wine=mfg_section,NT" EXT "\n"
+
+ "[mfg_section.NT" EXT "]\n"
+ "Wine test root driver=device_section,test_hardware_id\n"
+
+ "[device_section.NT" EXT "]\n"
+ "CopyFiles=file_section\n"
+
+ "[device_section.NT" EXT ".Services]\n"
+ "AddService=winetest,0x2,svc_section\n"
+
+ "[file_section]\n"
+ "winetest.sys\n"
+
+ "[SourceDisksFiles]\n"
+ "winetest.sys=1\n"
+
+ "[SourceDisksNames]\n"
+ "1=,winetest.sys\n"
+
+ "[DestinationDirs]\n"
+ "DefaultDestDir=12\n"
+
+ "[svc_section]\n"
+ "ServiceBinary=%12%\\winetest.sys\n"
+ "ServiceType=1\n"
+ "StartType=3\n"
+ "ErrorControl=1\n"
+ "LoadOrderGroup=Extended Base\n"
+ "DisplayName=\"winetest bus driver\"\n"
+ "; they don't sleep anymore, on the beach\n";
+
+static void add_file_to_catalog(HANDLE catalog, const WCHAR *file)
+{
+ SIP_SUBJECTINFO subject_info = {sizeof(SIP_SUBJECTINFO)};
+ SIP_INDIRECT_DATA *indirect_data;
+ const WCHAR *filepart = file;
+ CRYPTCATMEMBER *member;
+ WCHAR hash_buffer[100];
+ GUID subject_guid;
+ unsigned int i;
+ DWORD size;
+ BOOL ret;
+
+ ret = CryptSIPRetrieveSubjectGuidForCatalogFile(file, NULL, &subject_guid);
+ todo_wine winetest_ok(ret, "Failed to get subject guid, error %u\n", GetLastError());
+
+ size = 0;
+ subject_info.pgSubjectType = &subject_guid;
+ subject_info.pwsFileName = file;
+ subject_info.DigestAlgorithm.pszObjId = (char *)szOID_OIWSEC_sha1;
+ subject_info.dwFlags = SPC_INC_PE_RESOURCES_FLAG | SPC_INC_PE_IMPORT_ADDR_TABLE_FLAG | SPC_EXC_PE_PAGE_HASHES_FLAG | 0x10000;
+ ret = CryptSIPCreateIndirectData(&subject_info, &size, NULL);
+ todo_wine winetest_ok(ret, "Failed to get indirect data size, error %u\n", GetLastError());
+
+ indirect_data = malloc(size);
+ ret = CryptSIPCreateIndirectData(&subject_info, &size, indirect_data);
+ todo_wine winetest_ok(ret, "Failed to get indirect data, error %u\n", GetLastError());
+ if (ret)
+ {
+ memset(hash_buffer, 0, sizeof(hash_buffer));
+ for (i = 0; i < indirect_data->Digest.cbData; ++i)
+ swprintf(&hash_buffer[i * 2], 2, L"%02X", indirect_data->Digest.pbData[i]);
+
+ member = CryptCATPutMemberInfo(catalog, (WCHAR *)file,
+ hash_buffer, &subject_guid, 0, size, (BYTE *)indirect_data);
+ winetest_ok(!!member, "Failed to write member, error %u\n", GetLastError());
+
+ if (wcsrchr(file, '\\'))
+ filepart = wcsrchr(file, '\\') + 1;
+
+ ret = !!CryptCATPutAttrInfo(catalog, member, (WCHAR *)L"File",
+ CRYPTCAT_ATTR_NAMEASCII | CRYPTCAT_ATTR_DATAASCII | CRYPTCAT_ATTR_AUTHENTICATED,
+ (wcslen(filepart) + 1) * 2, (BYTE *)filepart);
+ winetest_ok(ret, "Failed to write attr, error %u\n", GetLastError());
+
+ ret = !!CryptCATPutAttrInfo(catalog, member, (WCHAR *)L"OSAttr",
+ CRYPTCAT_ATTR_NAMEASCII | CRYPTCAT_ATTR_DATAASCII | CRYPTCAT_ATTR_AUTHENTICATED,
+ sizeof(L"2:6.0"), (BYTE *)L"2:6.0");
+ winetest_ok(ret, "Failed to write attr, error %u\n", GetLastError());
+ }
+}
+
+typedef void (*driver_test_callback)(void *);
+
+#define run_driver_test (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : run_driver_test_
+static void run_driver_test_(struct testsign_context *ctx, const WCHAR *name,
+ driver_test_callback callback, void *args)
+{
+ static const char hardware_id[] = "test_hardware_id\0";
+ char path[MAX_PATH], dest[MAX_PATH], *filepart;
+ SP_DEVINFO_DATA device = {sizeof(device)};
+ char cwd[MAX_PATH], tempdir[MAX_PATH];
+ WCHAR driver_filename[MAX_PATH];
+ SC_HANDLE manager, service;
+ BOOL ret, need_reboot;
+ HANDLE catalog, file;
+ HDEVINFO set;
+ FILE *f;
+
+ GetCurrentDirectoryA(ARRAY_SIZE(cwd), cwd);
+ GetTempPathA(ARRAY_SIZE(tempdir), tempdir);
+ SetCurrentDirectoryA(tempdir);
+
+ load_resource_(name, driver_filename);
+ ret = MoveFileExW(driver_filename, L"winetest.sys", MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING);
+ winetest_ok(ret, "failed to move file, error %u\n", GetLastError());
+
+ f = fopen("winetest.inf", "w");
+ winetest_ok(!!f, "failed to open winetest.inf: %s\n", strerror(errno));
+ fputs(inf_text, f);
+ fclose(f);
+
+ /* Create the catalog file. */
+
+ catalog = CryptCATOpen((WCHAR *)L"winetest.cat", CRYPTCAT_OPEN_CREATENEW, 0, CRYPTCAT_VERSION_1, 0);
+ winetest_ok(catalog != INVALID_HANDLE_VALUE, "Failed to create catalog, error %#x\n", GetLastError());
+
+ add_file_to_catalog(catalog, L"winetest.sys");
+ add_file_to_catalog(catalog, L"winetest.inf");
+
+ ret = CryptCATPersistStore(catalog);
+ todo_wine winetest_ok(ret, "Failed to write catalog, error %u\n", GetLastError());
+
+ ret = CryptCATClose(catalog);
+ winetest_ok(ret, "Failed to close catalog, error %u\n", GetLastError());
+
+ testsign_sign_(ctx, L"winetest.cat");
+
+ /* Install the driver. */
+
+ set = SetupDiCreateDeviceInfoList(NULL, NULL);
+ winetest_ok(set != INVALID_HANDLE_VALUE, "failed to create device list, error %#x\n", GetLastError());
+
+ ret = SetupDiCreateDeviceInfoA(set, "root\\winetest\\0", &GUID_NULL, NULL, NULL, 0, &device);
+ winetest_ok(ret, "failed to create device, error %#x\n", GetLastError());
+
+ ret = SetupDiSetDeviceRegistryPropertyA( set, &device, SPDRP_HARDWAREID,
+ (const BYTE *)hardware_id, sizeof(hardware_id) );
+ winetest_ok(ret, "failed to create set hardware ID, error %#x\n", GetLastError());
+
+ ret = SetupDiCallClassInstaller(DIF_REGISTERDEVICE, set, &device);
+ winetest_ok(ret, "failed to register device, error %#x\n", GetLastError());
+
+ GetFullPathNameA("winetest.inf", sizeof(path), path, NULL);
+ ret = UpdateDriverForPlugAndPlayDevicesA(NULL, hardware_id, path, INSTALLFLAG_FORCE, &need_reboot);
+ winetest_ok(ret, "failed to install device, error %#x\n", GetLastError());
+ winetest_ok(!need_reboot, "expected no reboot necessary\n");
+
+ /* Check that the service is created and started. */
+ manager = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
+ winetest_ok(!!manager, "failed to open service manager, error %u\n", GetLastError());
+ service = OpenServiceA(manager, "winetest", SERVICE_START | SERVICE_STOP | DELETE);
+ winetest_ok(!!service, "failed to open service, error %u\n", GetLastError());
+
+ ret = StartServiceA(service, 0, NULL);
+ winetest_ok(!ret, "service didn't start automatically\n");
+ if (ret || GetLastError() == ERROR_SERVICE_ALREADY_RUNNING)
+ callback(args);
+ else
+ {
+ /* If Secure Boot is enabled or the machine is 64-bit, it will reject an unsigned driver. */
+ winetest_ok(GetLastError() == ERROR_DRIVER_BLOCKED || GetLastError() == ERROR_INVALID_IMAGE_HASH,
+ "unexpected error %u\n", GetLastError());
+ winetest_skip("Failed to start service; probably your machine doesn't accept unsigned drivers.\n");
+ }
+
+ ret = SetupDiCallClassInstaller(DIF_REMOVE, set, &device);
+ winetest_ok(ret, "failed to remove device, error %#x\n", GetLastError());
+
+ file = CreateFileA("\\\\?\\root#winetest#0#{deadbeef-29ef-4538-a5fd-b69573a362c0}", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
+ winetest_ok(file == INVALID_HANDLE_VALUE, "expected failure\n");
+ winetest_ok(GetLastError() == ERROR_FILE_NOT_FOUND, "got error %u\n", GetLastError());
+
+ ret = SetupDiDestroyDeviceInfoList(set);
+ winetest_ok(ret, "failed to destroy set, error %#x\n", GetLastError());
+
+ /* Windows stops the service but does not delete it. */
+ unload_driver_(service);
+ CloseServiceHandle(manager);
+
+ cat_okfile();
+
+ GetFullPathNameA("winetest.inf", sizeof(path), path, NULL);
+ ret = SetupCopyOEMInfA(path, NULL, 0, 0, dest, sizeof(dest), NULL, &filepart);
+ winetest_ok(ret, "Failed to copy INF, error %#x\n", GetLastError());
+ ret = SetupUninstallOEMInfA(filepart, 0, NULL);
+ winetest_ok(ret, "Failed to uninstall INF, error %u\n", GetLastError());
+
+ ret = DeleteFileA("winetest.cat");
+ winetest_ok(ret, "Failed to delete file, error %u\n", GetLastError());
+ ret = DeleteFileA("winetest.inf");
+ winetest_ok(ret, "Failed to delete file, error %u\n", GetLastError());
+ ret = DeleteFileA("winetest.sys");
+ winetest_ok(ret, "Failed to delete file, error %u\n", GetLastError());
+ /* Windows 10 apparently deletes the image in SetupUninstallOEMInf(). */
+ ret = DeleteFileA("C:/windows/system32/drivers/winetest.sys");
+ winetest_ok(ret || GetLastError() == ERROR_FILE_NOT_FOUND, "Failed to delete file, error %u\n", GetLastError());
+
+ SetCurrentDirectoryA(cwd);
+}
+
+#define driver_test_init(a) driver_test_init_(__FILE__, __LINE__, a)
+static BOOL driver_test_init_(char const *file, int line, struct testsign_context *ctx)
+{
+ BOOL is_wow64;
+
+ winetest_set_location(file, line);
+
+ pSignerSign = (void *)GetProcAddress(LoadLibraryA("mssign32"), "SignerSign");
+
+ if (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)
+ {
+ winetest_skip("Running in WoW64.\n");
+ return FALSE;
+ }
+
+ if (!testsign_create_cert(ctx))
+ return FALSE;
+
+ test_data_mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
+ 0, sizeof(*test_data), "Global\\winetest_ntoskrnl_section");
+ winetest_ok(!!test_data_mapping, "got error %u\n", GetLastError());
+ test_data = MapViewOfFile(test_data_mapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 1024);
+ test_data->running_under_wine = !strcmp(winetest_platform, "wine");
+ test_data->winetest_report_success = winetest_report_success;
+ test_data->winetest_debug = winetest_debug;
+
+ okfile = CreateFileA("C:\\windows\\winetest_ntoskrnl_okfile", GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);
+ winetest_ok(okfile != INVALID_HANDLE_VALUE, "failed to create file, error %u\n", GetLastError());
+
+ return TRUE;
+}
+
+#define driver_test_cleanup (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : driver_test_cleanup_
+static void driver_test_cleanup_(struct testsign_context *ctx)
+{
+ testsign_cleanup(ctx);
+ UnmapViewOfFile(test_data);
+ CloseHandle(test_data_mapping);
+ CloseHandle(okfile);
+ DeleteFileA("C:\\windows\\winetest_ntoskrnl_okfile");
+}
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c
index dc10497caee..b98c551ad4c 100644
--- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c
@@ -44,15 +44,12 @@
#include "ddk/hidpi.h"
#include "wine/test.h"
#include "wine/heap.h"
-#include "wine/mssign.h"
-
-#include "driver.h"
static const GUID GUID_NULL;
-static HANDLE device;
+#include "driver_tests.h"
-static struct test_data *test_data;
+static HANDLE device;
static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)(const WCHAR *, UNICODE_STRING *, WCHAR **, CURDIR *);
static BOOL (WINAPI *pRtlFreeUnicodeString)(UNICODE_STRING *);
@@ -63,237 +60,6 @@ static HRESULT (WINAPI *pSignerSign)(SIGNER_SUBJECT_INFO *subject, SIGNER_CERT *
SIGNER_SIGNATURE_INFO *signature, SIGNER_PROVIDER_INFO *provider,
const WCHAR *timestamp, CRYPT_ATTRIBUTES *attr, void *sip_data);
-static void load_resource(const WCHAR *name, WCHAR *filename)
-{
- static WCHAR path[MAX_PATH];
- DWORD written;
- HANDLE file;
- HRSRC res;
- void *ptr;
-
- GetTempPathW(ARRAY_SIZE(path), path);
- GetTempFileNameW(path, name, 0, filename);
-
- file = CreateFileW(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
- ok(file != INVALID_HANDLE_VALUE, "failed to create %s, error %u\n", debugstr_w(filename), GetLastError());
-
- res = FindResourceW(NULL, name, L"TESTDLL");
- ok( res != 0, "couldn't find resource\n" );
- ptr = LockResource( LoadResource( GetModuleHandleA(NULL), res ));
- WriteFile( file, ptr, SizeofResource( GetModuleHandleA(NULL), res ), &written, NULL );
- ok( written == SizeofResource( GetModuleHandleA(NULL), res ), "couldn't write resource\n" );
- CloseHandle( file );
-}
-
-struct testsign_context
-{
- HCRYPTPROV provider;
- const CERT_CONTEXT *cert, *root_cert, *publisher_cert;
- HCERTSTORE root_store, publisher_store;
-};
-
-static BOOL testsign_create_cert(struct testsign_context *ctx)
-{
- BYTE encoded_name[100], encoded_key_id[200], public_key_info_buffer[1000];
- WCHAR container_name[26];
- BYTE hash_buffer[16], cert_buffer[1000], provider_nameA[100], serial[16];
- CERT_PUBLIC_KEY_INFO *public_key_info = (CERT_PUBLIC_KEY_INFO *)public_key_info_buffer;
- CRYPT_KEY_PROV_INFO provider_info = {0};
- CRYPT_ALGORITHM_IDENTIFIER algid = {0};
- CERT_AUTHORITY_KEY_ID_INFO key_info;
- CERT_INFO cert_info = {0};
- WCHAR provider_nameW[100];
- CERT_EXTENSION extension;
- HCRYPTKEY key;
- DWORD size;
- BOOL ret;
-
- memset(ctx, 0, sizeof(*ctx));
-
- srand(time(NULL));
- swprintf(container_name, ARRAY_SIZE(container_name), L"wine_testsign%u", rand());
-
- ret = CryptAcquireContextW(&ctx->provider, container_name, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET);
- ok(ret, "Failed to create container, error %#x\n", GetLastError());
-
- ret = CryptGenKey(ctx->provider, AT_SIGNATURE, CRYPT_EXPORTABLE, &key);
- ok(ret, "Failed to create key, error %#x\n", GetLastError());
- ret = CryptDestroyKey(key);
- ok(ret, "Failed to destroy key, error %#x\n", GetLastError());
- ret = CryptGetUserKey(ctx->provider, AT_SIGNATURE, &key);
- ok(ret, "Failed to get user key, error %#x\n", GetLastError());
- ret = CryptDestroyKey(key);
- ok(ret, "Failed to destroy key, error %#x\n", GetLastError());
-
- size = sizeof(encoded_name);
- ret = CertStrToNameA(X509_ASN_ENCODING, "CN=winetest_cert", CERT_X500_NAME_STR, NULL, encoded_name, &size, NULL);
- ok(ret, "Failed to convert name, error %#x\n", GetLastError());
- key_info.CertIssuer.cbData = size;
- key_info.CertIssuer.pbData = encoded_name;
-
- size = sizeof(public_key_info_buffer);
- ret = CryptExportPublicKeyInfo(ctx->provider, AT_SIGNATURE, X509_ASN_ENCODING, public_key_info, &size);
- ok(ret, "Failed to export public key, error %#x\n", GetLastError());
- cert_info.SubjectPublicKeyInfo = *public_key_info;
-
- size = sizeof(hash_buffer);
- ret = CryptHashPublicKeyInfo(ctx->provider, CALG_MD5, 0, X509_ASN_ENCODING, public_key_info, hash_buffer, &size);
- ok(ret, "Failed to hash public key, error %#x\n", GetLastError());
-
- key_info.KeyId.cbData = size;
- key_info.KeyId.pbData = hash_buffer;
-
- RtlGenRandom(serial, sizeof(serial));
- key_info.CertSerialNumber.cbData = sizeof(serial);
- key_info.CertSerialNumber.pbData = serial;
-
- size = sizeof(encoded_key_id);
- ret = CryptEncodeObject(X509_ASN_ENCODING, X509_AUTHORITY_KEY_ID, &key_info, encoded_key_id, &size);
- ok(ret, "Failed to convert name, error %#x\n", GetLastError());
-
- extension.pszObjId = (char *)szOID_AUTHORITY_KEY_IDENTIFIER;
- extension.fCritical = TRUE;
- extension.Value.cbData = size;
- extension.Value.pbData = encoded_key_id;
-
- cert_info.dwVersion = CERT_V3;
- cert_info.SerialNumber = key_info.CertSerialNumber;
- cert_info.SignatureAlgorithm.pszObjId = (char *)szOID_RSA_SHA1RSA;
- cert_info.Issuer = key_info.CertIssuer;
- GetSystemTimeAsFileTime(&cert_info.NotBefore);
- GetSystemTimeAsFileTime(&cert_info.NotAfter);
- cert_info.NotAfter.dwHighDateTime += 1;
- cert_info.Subject = key_info.CertIssuer;
- cert_info.cExtension = 1;
- cert_info.rgExtension = &extension;
- algid.pszObjId = (char *)szOID_RSA_SHA1RSA;
- size = sizeof(cert_buffer);
- ret = CryptSignAndEncodeCertificate(ctx->provider, AT_SIGNATURE, X509_ASN_ENCODING,
- X509_CERT_TO_BE_SIGNED, &cert_info, &algid, NULL, cert_buffer, &size);
- ok(ret, "Failed to create certificate, error %#x\n", GetLastError());
-
- ctx->cert = CertCreateCertificateContext(X509_ASN_ENCODING, cert_buffer, size);
- ok(!!ctx->cert, "Failed to create context, error %#x\n", GetLastError());
-
- size = sizeof(provider_nameA);
- ret = CryptGetProvParam(ctx->provider, PP_NAME, provider_nameA, &size, 0);
- ok(ret, "Failed to get prov param, error %#x\n", GetLastError());
- MultiByteToWideChar(CP_ACP, 0, (char *)provider_nameA, -1, provider_nameW, ARRAY_SIZE(provider_nameW));
-
- provider_info.pwszContainerName = (WCHAR *)container_name;
- provider_info.pwszProvName = provider_nameW;
- provider_info.dwProvType = PROV_RSA_FULL;
- provider_info.dwKeySpec = AT_SIGNATURE;
- ret = CertSetCertificateContextProperty(ctx->cert, CERT_KEY_PROV_INFO_PROP_ID, 0, &provider_info);
- ok(ret, "Failed to set provider info, error %#x\n", GetLastError());
-
- ctx->root_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_A, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, "root");
- if (!ctx->root_store && GetLastError() == ERROR_ACCESS_DENIED)
- {
- skip("Failed to open root store.\n");
-
- ret = CertFreeCertificateContext(ctx->cert);
- ok(ret, "Failed to free certificate, error %u\n", GetLastError());
- ret = CryptReleaseContext(ctx->provider, 0);
- ok(ret, "failed to release context, error %u\n", GetLastError());
-
- return FALSE;
- }
- ok(!!ctx->root_store, "Failed to open store, error %u\n", GetLastError());
- ret = CertAddCertificateContextToStore(ctx->root_store, ctx->cert, CERT_STORE_ADD_ALWAYS, &ctx->root_cert);
- if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
- {
- skip("Failed to add self-signed certificate to store.\n");
-
- ret = CertFreeCertificateContext(ctx->cert);
- ok(ret, "Failed to free certificate, error %u\n", GetLastError());
- ret = CertCloseStore(ctx->root_store, CERT_CLOSE_STORE_CHECK_FLAG);
- ok(ret, "Failed to close store, error %u\n", GetLastError());
- ret = CryptReleaseContext(ctx->provider, 0);
- ok(ret, "failed to release context, error %u\n", GetLastError());
-
- return FALSE;
- }
- ok(ret, "Failed to add certificate, error %u\n", GetLastError());
-
- ctx->publisher_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_A, 0, 0,
- CERT_SYSTEM_STORE_LOCAL_MACHINE, "trustedpublisher");
- ok(!!ctx->publisher_store, "Failed to open store, error %u\n", GetLastError());
- ret = CertAddCertificateContextToStore(ctx->publisher_store, ctx->cert,
- CERT_STORE_ADD_ALWAYS, &ctx->publisher_cert);
- ok(ret, "Failed to add certificate, error %u\n", GetLastError());
-
- return TRUE;
-}
-
-static void testsign_cleanup(struct testsign_context *ctx)
-{
- BOOL ret;
-
- ret = CertFreeCertificateContext(ctx->cert);
- ok(ret, "Failed to free certificate, error %u\n", GetLastError());
-
- ret = CertDeleteCertificateFromStore(ctx->root_cert);
- ok(ret, "Failed to remove certificate, error %u\n", GetLastError());
- ret = CertCloseStore(ctx->root_store, CERT_CLOSE_STORE_CHECK_FLAG);
- ok(ret, "Failed to close store, error %u\n", GetLastError());
-
- ret = CertDeleteCertificateFromStore(ctx->publisher_cert);
- ok(ret, "Failed to remove certificate, error %u\n", GetLastError());
- ret = CertCloseStore(ctx->publisher_store, CERT_CLOSE_STORE_CHECK_FLAG);
- ok(ret, "Failed to close store, error %u\n", GetLastError());
-
- ret = CryptReleaseContext(ctx->provider, 0);
- ok(ret, "failed to release context, error %u\n", GetLastError());
-}
-
-static void testsign_sign(struct testsign_context *ctx, const WCHAR *filename)
-{
- SIGNER_ATTR_AUTHCODE authcode = {sizeof(authcode)};
- SIGNER_SIGNATURE_INFO signature = {sizeof(signature)};
- SIGNER_SUBJECT_INFO subject = {sizeof(subject)};
- SIGNER_CERT_STORE_INFO store = {sizeof(store)};
- SIGNER_CERT cert_info = {sizeof(cert_info)};
- SIGNER_FILE_INFO file = {sizeof(file)};
- DWORD index = 0;
- HRESULT hr;
-
- subject.dwSubjectChoice = 1;
- subject.pdwIndex = &index;
- subject.pSignerFileInfo = &file;
- file.pwszFileName = (WCHAR *)filename;
- cert_info.dwCertChoice = 2;
- cert_info.pCertStoreInfo = &store;
- store.pSigningCert = ctx->cert;
- store.dwCertPolicy = 0;
- signature.algidHash = CALG_SHA_256;
- signature.dwAttrChoice = SIGNER_AUTHCODE_ATTR;
- signature.pAttrAuthcode = &authcode;
- authcode.pwszName = L"";
- authcode.pwszInfo = L"";
- hr = pSignerSign(&subject, &cert_info, &signature, NULL, NULL, NULL, NULL);
- todo_wine ok(hr == S_OK || broken(hr == NTE_BAD_ALGID) /* < 7 */, "Failed to sign, hr %#x\n", hr);
-}
-
-static void unload_driver(SC_HANDLE service)
-{
- SERVICE_STATUS status;
-
- ControlService(service, SERVICE_CONTROL_STOP, &status);
- while (status.dwCurrentState == SERVICE_STOP_PENDING)
- {
- BOOL ret;
- Sleep(100);
- ret = QueryServiceStatus(service, &status);
- ok(ret, "QueryServiceStatus failed: %u\n", GetLastError());
- }
- ok(status.dwCurrentState == SERVICE_STOPPED,
- "expected SERVICE_STOPPED, got %d\n", status.dwCurrentState);
-
- DeleteService(service);
- CloseServiceHandle(service);
-}
-
static SC_HANDLE load_driver(struct testsign_context *ctx, WCHAR *filename,
const WCHAR *resname, const WCHAR *driver_name)
{
@@ -367,28 +133,6 @@ static BOOL start_driver(HANDLE service, BOOL vista_plus)
return TRUE;
}
-static HANDLE okfile;
-
-static void cat_okfile(void)
-{
- char buffer[512];
- DWORD size;
-
- SetFilePointer(okfile, 0, NULL, FILE_BEGIN);
-
- do
- {
- ReadFile(okfile, buffer, sizeof(buffer), &size, NULL);
- printf("%.*s", size, buffer);
- } while (size == sizeof(buffer));
-
- SetFilePointer(okfile, 0, NULL, FILE_BEGIN);
- SetEndOfFile(okfile);
-
- winetest_add_failures(InterlockedExchange(&test_data->failures, 0));
- winetest_add_failures(InterlockedExchange(&test_data->todo_failures, 0));
-}
-
static ULONG64 modified_value;
static void main_test(void)
@@ -1239,109 +983,6 @@ static void test_driver_netio(struct testsign_context *ctx)
cat_okfile();
}
-#ifdef __i386__
-#define EXT "x86"
-#elif defined(__x86_64__)
-#define EXT "amd64"
-#elif defined(__arm__)
-#define EXT "arm"
-#elif defined(__aarch64__)
-#define EXT "arm64"
-#else
-#define EXT
-#endif
-
-static const char inf_text[] =
- "[Version]\n"
- "Signature=$Chicago$\n"
- "ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318}\n"
- "CatalogFile=winetest.cat\n"
- "DriverVer=09/21/2006,6.0.5736.1\n"
-
- "[Manufacturer]\n"
- "Wine=mfg_section,NT" EXT "\n"
-
- "[mfg_section.NT" EXT "]\n"
- "Wine test root driver=device_section,test_hardware_id\n"
-
- "[device_section.NT" EXT "]\n"
- "CopyFiles=file_section\n"
-
- "[device_section.NT" EXT ".Services]\n"
- "AddService=winetest,0x2,svc_section\n"
-
- "[file_section]\n"
- "winetest.sys\n"
-
- "[SourceDisksFiles]\n"
- "winetest.sys=1\n"
-
- "[SourceDisksNames]\n"
- "1=,winetest.sys\n"
-
- "[DestinationDirs]\n"
- "DefaultDestDir=12\n"
-
- "[svc_section]\n"
- "ServiceBinary=%12%\\winetest.sys\n"
- "ServiceType=1\n"
- "StartType=3\n"
- "ErrorControl=1\n"
- "LoadOrderGroup=Extended Base\n"
- "DisplayName=\"winetest bus driver\"\n"
- "; they don't sleep anymore, on the beach\n";
-
-static void add_file_to_catalog(HANDLE catalog, const WCHAR *file)
-{
- SIP_SUBJECTINFO subject_info = {sizeof(SIP_SUBJECTINFO)};
- SIP_INDIRECT_DATA *indirect_data;
- const WCHAR *filepart = file;
- CRYPTCATMEMBER *member;
- WCHAR hash_buffer[100];
- GUID subject_guid;
- unsigned int i;
- DWORD size;
- BOOL ret;
-
- ret = CryptSIPRetrieveSubjectGuidForCatalogFile(file, NULL, &subject_guid);
- todo_wine ok(ret, "Failed to get subject guid, error %u\n", GetLastError());
-
- size = 0;
- subject_info.pgSubjectType = &subject_guid;
- subject_info.pwsFileName = file;
- subject_info.DigestAlgorithm.pszObjId = (char *)szOID_OIWSEC_sha1;
- subject_info.dwFlags = SPC_INC_PE_RESOURCES_FLAG | SPC_INC_PE_IMPORT_ADDR_TABLE_FLAG | SPC_EXC_PE_PAGE_HASHES_FLAG | 0x10000;
- ret = CryptSIPCreateIndirectData(&subject_info, &size, NULL);
- todo_wine ok(ret, "Failed to get indirect data size, error %u\n", GetLastError());
-
- indirect_data = malloc(size);
- ret = CryptSIPCreateIndirectData(&subject_info, &size, indirect_data);
- todo_wine ok(ret, "Failed to get indirect data, error %u\n", GetLastError());
- if (ret)
- {
- memset(hash_buffer, 0, sizeof(hash_buffer));
- for (i = 0; i < indirect_data->Digest.cbData; ++i)
- swprintf(&hash_buffer[i * 2], 2, L"%02X", indirect_data->Digest.pbData[i]);
-
- member = CryptCATPutMemberInfo(catalog, (WCHAR *)file,
- hash_buffer, &subject_guid, 0, size, (BYTE *)indirect_data);
- ok(!!member, "Failed to write member, error %u\n", GetLastError());
-
- if (wcsrchr(file, '\\'))
- filepart = wcsrchr(file, '\\') + 1;
-
- ret = !!CryptCATPutAttrInfo(catalog, member, (WCHAR *)L"File",
- CRYPTCAT_ATTR_NAMEASCII | CRYPTCAT_ATTR_DATAASCII | CRYPTCAT_ATTR_AUTHENTICATED,
- (wcslen(filepart) + 1) * 2, (BYTE *)filepart);
- ok(ret, "Failed to write attr, error %u\n", GetLastError());
-
- ret = !!CryptCATPutAttrInfo(catalog, member, (WCHAR *)L"OSAttr",
- CRYPTCAT_ATTR_NAMEASCII | CRYPTCAT_ATTR_DATAASCII | CRYPTCAT_ATTR_AUTHENTICATED,
- sizeof(L"2:6.0"), (BYTE *)L"2:6.0");
- ok(ret, "Failed to write attr, error %u\n", GetLastError());
- }
-}
-
static const GUID bus_class = {0xdeadbeef, 0x29ef, 0x4538, {0xa5, 0xfd, 0xb6, 0x95, 0x73, 0xa3, 0x62, 0xc1}};
static const GUID child_class = {0xdeadbeef, 0x29ef, 0x4538, {0xa5, 0xfd, 0xb6, 0x95, 0x73, 0xa3, 0x62, 0xc2}};
@@ -1434,7 +1075,7 @@ static void pump_messages(void)
}
}
-static void test_pnp_devices(void)
+static void test_pnp_devices(void *args)
{
static const char expect_hardware_id[] = "winetest_hardware\0winetest_hardware_1\0";
static const char expect_compat_id[] = "winetest_compat\0winetest_compat_1\0";
@@ -1698,133 +1339,6 @@ static void test_pnp_devices(void)
UnregisterClassA("ntoskrnl_test_wc", GetModuleHandleA(NULL));
}
-static void test_pnp_driver(struct testsign_context *ctx)
-{
- static const char hardware_id[] = "test_hardware_id\0";
- char path[MAX_PATH], dest[MAX_PATH], *filepart;
- SP_DEVINFO_DATA device = {sizeof(device)};
- char cwd[MAX_PATH], tempdir[MAX_PATH];
- WCHAR driver_filename[MAX_PATH];
- SC_HANDLE manager, service;
- BOOL ret, need_reboot;
- HANDLE catalog, file;
- unsigned int i;
- HDEVINFO set;
- FILE *f;
-
- GetCurrentDirectoryA(ARRAY_SIZE(cwd), cwd);
- GetTempPathA(ARRAY_SIZE(tempdir), tempdir);
- SetCurrentDirectoryA(tempdir);
-
- load_resource(L"driver_pnp.dll", driver_filename);
- ret = MoveFileExW(driver_filename, L"winetest.sys", MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING);
- ok(ret, "failed to move file, error %u\n", GetLastError());
-
- f = fopen("winetest.inf", "w");
- ok(!!f, "failed to open winetest.inf: %s\n", strerror(errno));
- fputs(inf_text, f);
- fclose(f);
-
- /* Create the catalog file. */
-
- catalog = CryptCATOpen((WCHAR *)L"winetest.cat", CRYPTCAT_OPEN_CREATENEW, 0, CRYPTCAT_VERSION_1, 0);
- ok(catalog != INVALID_HANDLE_VALUE, "Failed to create catalog, error %#x\n", GetLastError());
-
- ret = !!CryptCATPutCatAttrInfo(catalog, (WCHAR *)L"HWID1",
- CRYPTCAT_ATTR_NAMEASCII | CRYPTCAT_ATTR_DATAASCII | CRYPTCAT_ATTR_AUTHENTICATED,
- sizeof(L"test_hardware_id"), (BYTE *)L"test_hardware_id");
- todo_wine ok(ret, "failed to add attribute, error %#x\n", GetLastError());
-
- ret = !!CryptCATPutCatAttrInfo(catalog, (WCHAR *)L"OS",
- CRYPTCAT_ATTR_NAMEASCII | CRYPTCAT_ATTR_DATAASCII | CRYPTCAT_ATTR_AUTHENTICATED,
- sizeof(L"VistaX64"), (BYTE *)L"VistaX64");
- todo_wine ok(ret, "failed to add attribute, error %#x\n", GetLastError());
-
- add_file_to_catalog(catalog, L"winetest.sys");
- add_file_to_catalog(catalog, L"winetest.inf");
-
- ret = CryptCATPersistStore(catalog);
- todo_wine ok(ret, "Failed to write catalog, error %u\n", GetLastError());
-
- ret = CryptCATClose(catalog);
- ok(ret, "Failed to close catalog, error %u\n", GetLastError());
-
- testsign_sign(ctx, L"winetest.cat");
-
- /* Install the driver. */
-
- set = SetupDiCreateDeviceInfoList(NULL, NULL);
- ok(set != INVALID_HANDLE_VALUE, "failed to create device list, error %#x\n", GetLastError());
-
- ret = SetupDiCreateDeviceInfoA(set, "root\\winetest\\0", &GUID_NULL, NULL, NULL, 0, &device);
- ok(ret, "failed to create device, error %#x\n", GetLastError());
-
- ret = SetupDiSetDeviceRegistryPropertyA( set, &device, SPDRP_HARDWAREID,
- (const BYTE *)hardware_id, sizeof(hardware_id) );
- ok(ret, "failed to create set hardware ID, error %#x\n", GetLastError());
-
- ret = SetupDiCallClassInstaller(DIF_REGISTERDEVICE, set, &device);
- ok(ret, "failed to register device, error %#x\n", GetLastError());
-
- GetFullPathNameA("winetest.inf", sizeof(path), path, NULL);
- ret = UpdateDriverForPlugAndPlayDevicesA(NULL, hardware_id, path, INSTALLFLAG_FORCE, &need_reboot);
- ok(ret, "failed to install device, error %#x\n", GetLastError());
- ok(!need_reboot, "expected no reboot necessary\n");
-
- /* Tests. */
-
- test_pnp_devices();
-
- /* Clean up. */
-
- ret = SetupDiCallClassInstaller(DIF_REMOVE, set, &device);
- ok(ret, "failed to remove device, error %#x\n", GetLastError());
-
- file = CreateFileA("\\\\?\\root#winetest#0#{deadbeef-29ef-4538-a5fd-b69573a362c0}", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
- ok(file == INVALID_HANDLE_VALUE, "expected failure\n");
- ok(GetLastError() == ERROR_FILE_NOT_FOUND, "got error %u\n", GetLastError());
-
- ret = SetupDiDestroyDeviceInfoList(set);
- ok(ret, "failed to destroy set, error %#x\n", GetLastError());
-
- set = SetupDiGetClassDevsA(NULL, "wine", NULL, DIGCF_ALLCLASSES);
- ok(set != INVALID_HANDLE_VALUE, "failed to get device list, error %#x\n", GetLastError());
-
- for (i = 0; SetupDiEnumDeviceInfo(set, i, &device); ++i)
- {
- ret = SetupDiCallClassInstaller(DIF_REMOVE, set, &device);
- ok(ret, "failed to remove device, error %#x\n", GetLastError());
- }
-
- /* Windows stops the service but does not delete it. */
- manager = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
- ok(!!manager, "failed to open service manager, error %u\n", GetLastError());
- service = OpenServiceA(manager, "winetest", SERVICE_STOP | DELETE);
- ok(!!service, "failed to open service, error %u\n", GetLastError());
- unload_driver(service);
- CloseServiceHandle(manager);
-
- cat_okfile();
-
- GetFullPathNameA("winetest.inf", sizeof(path), path, NULL);
- ret = SetupCopyOEMInfA(path, NULL, 0, 0, dest, sizeof(dest), NULL, &filepart);
- ok(ret, "Failed to copy INF, error %#x\n", GetLastError());
- ret = SetupUninstallOEMInfA(filepart, 0, NULL);
- ok(ret, "Failed to uninstall INF, error %u\n", GetLastError());
-
- ret = DeleteFileA("winetest.cat");
- ok(ret, "Failed to delete file, error %u\n", GetLastError());
- ret = DeleteFileA("winetest.inf");
- ok(ret, "Failed to delete file, error %u\n", GetLastError());
- ret = DeleteFileA("winetest.sys");
- ok(ret, "Failed to delete file, error %u\n", GetLastError());
- /* Windows 10 apparently deletes the image in SetupUninstallOEMInf(). */
- ret = DeleteFileA("C:/windows/system32/drivers/winetest.sys");
- ok(ret || GetLastError() == ERROR_FILE_NOT_FOUND, "Failed to delete file, error %u\n", GetLastError());
-
- SetCurrentDirectoryA(cwd);
-}
-
#define check_member_(file, line, val, exp, fmt, member) \
ok_(file, line)((val).member == (exp).member, \
"got " #member " " fmt ", expected " fmt "\n", \
@@ -3131,8 +2645,16 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
HidD_FreePreparsedData(preparsed_data);
}
-static void test_hid_device(DWORD report_id, DWORD polled)
+struct test_hid_params
{
+ BOOL report_id;
+ BOOL polled;
+};
+
+static void test_hid_device(void *args)
+{
+ struct test_hid_params *params = args;
+ BOOL report_id = params->report_id, polled = params->polled;
char buffer[200];
SP_DEVICE_INTERFACE_DETAIL_DATA_A *iface_detail = (void *)buffer;
SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)};
@@ -3297,18 +2819,11 @@ static void test_hid_device(DWORD report_id, DWORD polled)
static void test_hid_driver(struct testsign_context *ctx, DWORD report_id, DWORD polled)
{
- static const char hardware_id[] = "test_hardware_id\0";
- char path[MAX_PATH], dest[MAX_PATH], *filepart;
+ struct test_hid_params params = {.report_id = report_id, .polled = polled};
SP_DEVINFO_DATA device = {sizeof(device)};
char cwd[MAX_PATH], tempdir[MAX_PATH];
- WCHAR driver_filename[MAX_PATH];
- SC_HANDLE manager, service;
- BOOL ret, need_reboot;
- HANDLE catalog, file;
LSTATUS status;
- HDEVINFO set;
HKEY hkey;
- FILE *f;
GetCurrentDirectoryA(ARRAY_SIZE(cwd), cwd);
GetTempPathA(ARRAY_SIZE(tempdir), tempdir);
@@ -3323,94 +2838,7 @@ static void test_hid_driver(struct testsign_context *ctx, DWORD report_id, DWORD
status = RegSetValueExW(hkey, L"PolledMode", 0, REG_DWORD, (void *)&polled, sizeof(polled));
ok(!status, "RegSetValueExW returned %#x\n", status);
- load_resource(L"driver_hid.dll", driver_filename);
- ret = MoveFileExW(driver_filename, L"winetest.sys", MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING);
- ok(ret, "failed to move file, error %u\n", GetLastError());
-
- f = fopen("winetest.inf", "w");
- ok(!!f, "failed to open winetest.inf: %s\n", strerror(errno));
- fputs(inf_text, f);
- fclose(f);
-
- /* Create the catalog file. */
-
- catalog = CryptCATOpen((WCHAR *)L"winetest.cat", CRYPTCAT_OPEN_CREATENEW, 0, CRYPTCAT_VERSION_1, 0);
- ok(catalog != INVALID_HANDLE_VALUE, "Failed to create catalog, error %#x\n", GetLastError());
-
- add_file_to_catalog(catalog, L"winetest.sys");
- add_file_to_catalog(catalog, L"winetest.inf");
-
- ret = CryptCATPersistStore(catalog);
- todo_wine ok(ret, "Failed to write catalog, error %u\n", GetLastError());
-
- ret = CryptCATClose(catalog);
- ok(ret, "Failed to close catalog, error %u\n", GetLastError());
-
- testsign_sign(ctx, L"winetest.cat");
-
- /* Install the driver. */
-
- set = SetupDiCreateDeviceInfoList(NULL, NULL);
- ok(set != INVALID_HANDLE_VALUE, "failed to create device list, error %#x\n", GetLastError());
-
- ret = SetupDiCreateDeviceInfoA(set, "root\\winetest\\0", &GUID_NULL, NULL, NULL, 0, &device);
- ok(ret, "failed to create device, error %#x\n", GetLastError());
-
- ret = SetupDiSetDeviceRegistryPropertyA( set, &device, SPDRP_HARDWAREID,
- (const BYTE *)hardware_id, sizeof(hardware_id) );
- ok(ret, "failed to create set hardware ID, error %#x\n", GetLastError());
-
- ret = SetupDiCallClassInstaller(DIF_REGISTERDEVICE, set, &device);
- ok(ret, "failed to register device, error %#x\n", GetLastError());
-
- GetFullPathNameA("winetest.inf", sizeof(path), path, NULL);
- ret = UpdateDriverForPlugAndPlayDevicesA(NULL, hardware_id, path, INSTALLFLAG_FORCE, &need_reboot);
- ok(ret, "failed to install device, error %#x\n", GetLastError());
- ok(!need_reboot, "expected no reboot necessary\n");
-
- /* Tests. */
-
- test_hid_device(report_id, polled);
-
- /* Clean up. */
-
- ret = SetupDiCallClassInstaller(DIF_REMOVE, set, &device);
- ok(ret, "failed to remove device, error %#x\n", GetLastError());
-
- file = CreateFileA("\\\\?\\root#winetest#0#{deadbeef-29ef-4538-a5fd-b69573a362c0}", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
- ok(file == INVALID_HANDLE_VALUE, "expected failure\n");
- ok(GetLastError() == ERROR_FILE_NOT_FOUND, "got error %u\n", GetLastError());
-
- ret = SetupDiDestroyDeviceInfoList(set);
- ok(ret, "failed to destroy set, error %#x\n", GetLastError());
-
- /* Windows stops the service but does not delete it. */
- manager = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
- ok(!!manager, "failed to open service manager, error %u\n", GetLastError());
- service = OpenServiceA(manager, "winetest", SERVICE_STOP | DELETE);
- ok(!!service, "failed to open service, error %u\n", GetLastError());
- unload_driver(service);
- CloseServiceHandle(manager);
-
- cat_okfile();
-
- GetFullPathNameA("winetest.inf", sizeof(path), path, NULL);
- ret = SetupCopyOEMInfA(path, NULL, 0, 0, dest, sizeof(dest), NULL, &filepart);
- ok(ret, "Failed to copy INF, error %#x\n", GetLastError());
- ret = SetupUninstallOEMInfA(filepart, 0, NULL);
- ok(ret, "Failed to uninstall INF, error %u\n", GetLastError());
-
- ret = DeleteFileA("winetest.cat");
- ok(ret, "Failed to delete file, error %u\n", GetLastError());
- ret = DeleteFileA("winetest.inf");
- ok(ret, "Failed to delete file, error %u\n", GetLastError());
- ret = DeleteFileA("winetest.sys");
- ok(ret, "Failed to delete file, error %u\n", GetLastError());
- /* Windows 10 apparently deletes the image in SetupUninstallOEMInf(). */
- ret = DeleteFileA("C:/windows/system32/drivers/winetest.sys");
- ok(ret || GetLastError() == ERROR_FILE_NOT_FOUND, "Failed to delete file, error %u\n", GetLastError());
-
- SetCurrentDirectoryA(cwd);
+ run_driver_test(ctx, L"driver_hid.dll", test_hid_device, ¶ms);
}
START_TEST(ntoskrnl)
@@ -3418,9 +2846,8 @@ START_TEST(ntoskrnl)
WCHAR filename[MAX_PATH], filename2[MAX_PATH];
struct testsign_context ctx;
SC_HANDLE service, service2;
- BOOL ret, is_wow64;
- HANDLE mapping;
DWORD written;
+ BOOL ret;
pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(GetModuleHandleA("ntdll"), "RtlDosPathNameToNtPathName_U");
pRtlFreeUnicodeString = (void *)GetProcAddress(GetModuleHandleA("ntdll"), "RtlFreeUnicodeString");
@@ -3428,29 +2855,10 @@ START_TEST(ntoskrnl)
pIsWow64Process = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "IsWow64Process");
pSetFileCompletionNotificationModes = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"),
"SetFileCompletionNotificationModes");
- pSignerSign = (void *)GetProcAddress(LoadLibraryA("mssign32"), "SignerSign");
-
- if (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)
- {
- skip("Running in WoW64.\n");
- return;
- }
- if (!testsign_create_cert(&ctx))
+ if (!driver_test_init(&ctx))
return;
- mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
- 0, sizeof(*test_data), "Global\\winetest_ntoskrnl_section");
- ok(!!mapping, "got error %u\n", GetLastError());
- test_data = MapViewOfFile(mapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 1024);
- test_data->running_under_wine = !strcmp(winetest_platform, "wine");
- test_data->winetest_report_success = winetest_report_success;
- test_data->winetest_debug = winetest_debug;
-
- okfile = CreateFileA("C:\\windows\\winetest_ntoskrnl_okfile", GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);
- ok(okfile != INVALID_HANDLE_VALUE, "failed to create file, error %u\n", GetLastError());
-
subtest("driver");
if (!(service = load_driver(&ctx, filename, L"driver.dll", L"WineTestDriver")))
goto out;
@@ -3497,7 +2905,7 @@ START_TEST(ntoskrnl)
test_driver_netio(&ctx);
subtest("driver_pnp");
- test_pnp_driver(&ctx);
+ run_driver_test(&ctx, L"driver_pnp.dll", test_pnp_devices, NULL);
subtest("driver_hid");
test_hid_driver(&ctx, 0, FALSE);
@@ -3506,9 +2914,5 @@ START_TEST(ntoskrnl)
test_hid_driver(&ctx, 1, TRUE);
out:
- testsign_cleanup(&ctx);
- UnmapViewOfFile(test_data);
- CloseHandle(mapping);
- CloseHandle(okfile);
- DeleteFileA("C:\\windows\\winetest_ntoskrnl_okfile");
+ driver_test_cleanup(&ctx);
}
--
2.33.0
3
6
[PATCH 4/6] gdi32: Get stock objects directly from GDI_SHARED_MEMORY in GetStockObject.
by Jacek Caban 03 Sep '21
by Jacek Caban 03 Sep '21
03 Sep '21
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/gdi32/gdiobj.c | 131 ++++++++++++++++++-------------------------
dlls/gdi32/objects.c | 52 +++++++++++++++++
2 files changed, 107 insertions(+), 76 deletions(-)
2
1
[PATCH v2 6/6] gdi32: Use NtGdiDeleteObjectApp instead of DeleteObject in ntgdi functions.
by Huw Davies 03 Sep '21
by Huw Davies 03 Sep '21
03 Sep '21
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/gdi32/bitblt.c | 12 ++++++------
dlls/gdi32/bitmap.c | 4 ++--
dlls/gdi32/clipping.c | 14 ++++++-------
dlls/gdi32/dc.c | 12 ++++++------
dlls/gdi32/dib.c | 14 ++++++-------
dlls/gdi32/dibdrv/bitblt.c | 2 +-
dlls/gdi32/dibdrv/graphics.c | 38 ++++++++++++++++++------------------
dlls/gdi32/dibdrv/objects.c | 8 ++++----
dlls/gdi32/font.c | 6 +++---
dlls/gdi32/gdiobj.c | 2 +-
dlls/gdi32/painting.c | 2 +-
dlls/gdi32/path.c | 2 +-
dlls/gdi32/region.c | 2 +-
13 files changed, 59 insertions(+), 59 deletions(-)
diff --git a/dlls/gdi32/bitblt.c b/dlls/gdi32/bitblt.c
index ec117199a86..aa1ba0dda1e 100644
--- a/dlls/gdi32/bitblt.c
+++ b/dlls/gdi32/bitblt.c
@@ -488,7 +488,7 @@ BOOL CDECL nulldrv_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert
ret = !dev->funcs->pPutImage( dev, rgn, info, &bits, &src, &dst, SRCCOPY );
if (bits.free) bits.free( &bits );
- DeleteObject( rgn );
+ NtGdiDeleteObjectApp( rgn );
done:
HeapFree( GetProcessHeap(), 0, pts );
@@ -823,9 +823,9 @@ BOOL WINAPI MaskBlt(HDC hdcDest, INT nXDest, INT nYDest,
NtGdiSelectBitmap(hDC2, hOldBitmap2);
/* delete all temp objects */
- DeleteObject(hBitmap1);
- DeleteObject(hBitmap2);
- DeleteObject(hbrMask);
+ NtGdiDeleteObjectApp( hBitmap1 );
+ NtGdiDeleteObjectApp( hBitmap2 );
+ NtGdiDeleteObjectApp( hbrMask );
NtGdiDeleteObjectApp( hDC1 );
NtGdiDeleteObjectApp( hDC2 );
@@ -926,12 +926,12 @@ error:
NtGdiSelectBitmap(hdcWork, oldWork);
NtGdiDeleteObjectApp( hdcWork );
}
- if(bmpWork) DeleteObject(bmpWork);
+ if(bmpWork) NtGdiDeleteObjectApp( bmpWork );
if(hdcMask) {
NtGdiSelectBitmap(hdcMask, oldMask);
NtGdiDeleteObjectApp( hdcMask );
}
- if(bmpMask) DeleteObject(bmpMask);
+ if(bmpMask) NtGdiDeleteObjectApp( bmpMask );
return ret;
}
diff --git a/dlls/gdi32/bitmap.c b/dlls/gdi32/bitmap.c
index cc9b106de0b..ad04603bf69 100644
--- a/dlls/gdi32/bitmap.c
+++ b/dlls/gdi32/bitmap.c
@@ -303,7 +303,7 @@ LONG WINAPI NtGdiSetBitmapBits(
last_row = NtGdiCreateRectRgn( src.visrect.left, src.visrect.bottom - 1,
src.visrect.left + extra_pixels, src.visrect.bottom );
NtGdiCombineRgn( clip, clip, last_row, RGN_OR );
- DeleteObject( last_row );
+ NtGdiDeleteObjectApp( last_row );
}
TRACE("(%p, %d, %p) %dx%d %d bpp fetched height: %d\n",
@@ -354,7 +354,7 @@ LONG WINAPI NtGdiSetBitmapBits(
}
if (err) count = 0;
- if (clip) DeleteObject( clip );
+ if (clip) NtGdiDeleteObjectApp( clip );
if (src_bits.free) src_bits.free( &src_bits );
GDI_ReleaseObj( hbitmap );
return count;
diff --git a/dlls/gdi32/clipping.c b/dlls/gdi32/clipping.c
index 02247f03620..e051b1c012c 100644
--- a/dlls/gdi32/clipping.c
+++ b/dlls/gdi32/clipping.c
@@ -111,7 +111,7 @@ void update_dc_clipping( DC * dc )
}
else /* only one region, we don't need the total region */
{
- if (dc->region) DeleteObject( dc->region );
+ if (dc->region) NtGdiDeleteObjectApp( dc->region );
dc->region = 0;
}
physdev->funcs->pSetDeviceClipping( physdev, get_dc_region( dc ));
@@ -153,7 +153,7 @@ INT WINAPI NtGdiExtSelectClipRgn( HDC hdc, HRGN rgn, INT mode )
switch (mode)
{
case RGN_COPY:
- if (dc->hClipRgn) DeleteObject( dc->hClipRgn );
+ if (dc->hClipRgn) NtGdiDeleteObjectApp( dc->hClipRgn );
dc->hClipRgn = 0;
ret = SIMPLEREGION;
break;
@@ -189,7 +189,7 @@ INT WINAPI NtGdiExtSelectClipRgn( HDC hdc, HRGN rgn, INT mode )
else
ret = NtGdiCombineRgn( dc->hClipRgn, dc->hClipRgn, rgn, mode );
- if (mirrored) DeleteObject( mirrored );
+ if (mirrored) NtGdiDeleteObjectApp( mirrored );
}
if (ret != ERROR) update_dc_clipping( dc );
release_dc_ptr( dc );
@@ -212,7 +212,7 @@ void CDECL __wine_set_visible_region( HDC hdc, HRGN hrgn, const RECT *vis_rect,
/* map region to DC coordinates */
NtGdiOffsetRgn( hrgn, -vis_rect->left, -vis_rect->top );
- if (dc->hVisRgn) DeleteObject( dc->hVisRgn );
+ if (dc->hVisRgn) NtGdiDeleteObjectApp( dc->hVisRgn );
dc->dirty = 0;
dc->attr->vis_rect = *vis_rect;
dc->device_rect = *device_rect;
@@ -269,7 +269,7 @@ INT WINAPI NtGdiExcludeClipRect( HDC hdc, INT left, INT top, INT right, INT bott
{
if (!dc->hClipRgn) create_default_clip_region( dc );
ret = NtGdiCombineRgn( dc->hClipRgn, dc->hClipRgn, rgn, RGN_DIFF );
- DeleteObject( rgn );
+ NtGdiDeleteObjectApp( rgn );
if (ret != ERROR) update_dc_clipping( dc );
}
release_dc_ptr( dc );
@@ -299,7 +299,7 @@ INT WINAPI NtGdiIntersectClipRect( HDC hdc, INT left, INT top, INT right, INT bo
else if ((rgn = CreateRectRgnIndirect( &rect )))
{
ret = NtGdiCombineRgn( dc->hClipRgn, dc->hClipRgn, rgn, RGN_AND );
- DeleteObject( rgn );
+ NtGdiDeleteObjectApp( rgn );
}
if (ret != ERROR) update_dc_clipping( dc );
release_dc_ptr( dc );
@@ -476,7 +476,7 @@ INT WINAPI NtGdiSetMetaRgn( HDC hdc )
{
/* the intersection becomes the new meta region */
NtGdiCombineRgn( dc->hMetaRgn, dc->hMetaRgn, dc->hClipRgn, RGN_AND );
- DeleteObject( dc->hClipRgn );
+ NtGdiDeleteObjectApp( dc->hClipRgn );
dc->hClipRgn = 0;
}
else
diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c
index 42217681b17..d8eaa1093f3 100644
--- a/dlls/gdi32/dc.c
+++ b/dlls/gdi32/dc.c
@@ -164,10 +164,10 @@ DC *alloc_dc_ptr( DWORD magic )
*/
static void free_dc_state( DC *dc )
{
- if (dc->hClipRgn) DeleteObject( dc->hClipRgn );
- if (dc->hMetaRgn) DeleteObject( dc->hMetaRgn );
- if (dc->hVisRgn) DeleteObject( dc->hVisRgn );
- if (dc->region) DeleteObject( dc->region );
+ if (dc->hClipRgn) NtGdiDeleteObjectApp( dc->hClipRgn );
+ if (dc->hMetaRgn) NtGdiDeleteObjectApp( dc->hMetaRgn );
+ if (dc->hVisRgn) NtGdiDeleteObjectApp( dc->hVisRgn );
+ if (dc->region) NtGdiDeleteObjectApp( dc->region );
if (dc->path) free_gdi_path( dc->path );
HeapFree( GetProcessHeap(), 0, dc->attr );
HeapFree( GetProcessHeap(), 0, dc );
@@ -403,8 +403,8 @@ static BOOL reset_dc_state( HDC hdc )
NtGdiSetBoundsRect( hdc, NULL, DCB_DISABLE );
NtGdiAbortPath( hdc );
- if (dc->hClipRgn) DeleteObject( dc->hClipRgn );
- if (dc->hMetaRgn) DeleteObject( dc->hMetaRgn );
+ if (dc->hClipRgn) NtGdiDeleteObjectApp( dc->hClipRgn );
+ if (dc->hMetaRgn) NtGdiDeleteObjectApp( dc->hMetaRgn );
dc->hClipRgn = 0;
dc->hMetaRgn = 0;
update_dc_clipping( dc );
diff --git a/dlls/gdi32/dib.c b/dlls/gdi32/dib.c
index f00d5cf13e2..b504e8c1a01 100644
--- a/dlls/gdi32/dib.c
+++ b/dlls/gdi32/dib.c
@@ -439,7 +439,7 @@ static BOOL build_rle_bitmap( BITMAPINFO *info, struct gdi_image_bits *bits, HRG
}
done:
- if (run) DeleteObject( run );
+ if (run) NtGdiDeleteObjectApp( run );
if (bits->free) bits->free( bits );
bits->ptr = out_bits;
@@ -450,8 +450,8 @@ done:
return TRUE;
fail:
- if (run) DeleteObject( run );
- if (clip && *clip) DeleteObject( *clip );
+ if (run) NtGdiDeleteObjectApp( run );
+ if (clip && *clip) NtGdiDeleteObjectApp( *clip );
HeapFree( GetProcessHeap(), 0, out_bits );
return FALSE;
}
@@ -600,7 +600,7 @@ INT CDECL nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst,
done:
if (src_bits.free) src_bits.free( &src_bits );
- if (clip) DeleteObject( clip );
+ if (clip) NtGdiDeleteObjectApp( clip );
return ret;
}
@@ -756,7 +756,7 @@ INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
done:
if (src_bits.free) src_bits.free( &src_bits );
- if (clip) DeleteObject( clip );
+ if (clip) NtGdiDeleteObjectApp( clip );
GDI_ReleaseObj( hbitmap );
return result;
}
@@ -874,7 +874,7 @@ INT CDECL nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD cx
done:
if (src_bits.free) src_bits.free( &src_bits );
- if (clip) DeleteObject( clip );
+ if (clip) NtGdiDeleteObjectApp( clip );
return lines;
}
@@ -1691,7 +1691,7 @@ NTSTATUS WINAPI NtGdiDdDDIDestroyDCFromMemory( const D3DKMT_DESTROYDCFROMMEMORY
if (GetObjectType( desc->hDc ) != OBJ_MEMDC ||
GetObjectType( desc->hBitmap ) != OBJ_BITMAP) return STATUS_INVALID_PARAMETER;
- DeleteObject( desc->hBitmap );
+ NtGdiDeleteObjectApp( desc->hBitmap );
NtGdiDeleteObjectApp( desc->hDc );
return STATUS_SUCCESS;
diff --git a/dlls/gdi32/dibdrv/bitblt.c b/dlls/gdi32/dibdrv/bitblt.c
index dabdf01a591..86390663f29 100644
--- a/dlls/gdi32/dibdrv/bitblt.c
+++ b/dlls/gdi32/dibdrv/bitblt.c
@@ -1034,7 +1034,7 @@ DWORD CDECL dibdrv_PutImage( PHYSDEV dev, HRGN clip, BITMAPINFO *info,
free_clipped_rects( &clipped_rects );
}
free_dib_info( &src_dib );
- if (tmp_rgn) DeleteObject( tmp_rgn );
+ if (tmp_rgn) NtGdiDeleteObjectApp( tmp_rgn );
return ret;
update_format:
diff --git a/dlls/gdi32/dibdrv/graphics.c b/dlls/gdi32/dibdrv/graphics.c
index c6f11ae6a69..9bd6dc557a5 100644
--- a/dlls/gdi32/dibdrv/graphics.c
+++ b/dlls/gdi32/dibdrv/graphics.c
@@ -375,7 +375,7 @@ static BOOL draw_arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
!(interior = create_polypolygon_region( points, &count, 1, WINDING, &rc )))
{
HeapFree( GetProcessHeap(), 0, points );
- if (outline) DeleteObject( outline );
+ if (outline) NtGdiDeleteObjectApp( outline );
return FALSE;
}
@@ -383,7 +383,7 @@ static BOOL draw_arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
if (interior && !outline)
{
ret = brush_region( pdev, interior );
- DeleteObject( interior );
+ NtGdiDeleteObjectApp( interior );
interior = 0;
}
@@ -395,12 +395,12 @@ static BOOL draw_arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
{
NtGdiCombineRgn( interior, interior, outline, RGN_DIFF );
ret = brush_region( pdev, interior );
- DeleteObject( interior );
+ NtGdiDeleteObjectApp( interior );
}
if (outline)
{
if (ret) ret = pen_region( pdev, outline );
- DeleteObject( outline );
+ NtGdiDeleteObjectApp( outline );
}
HeapFree( GetProcessHeap(), 0, points );
return ret;
@@ -428,7 +428,7 @@ static BOOL stroke_and_fill_path( dibdrv_physdev *dev, BOOL stroke, BOOL fill )
if (interior && !outline)
{
ret = brush_region( dev, interior );
- DeleteObject( interior );
+ NtGdiDeleteObjectApp( interior );
interior = 0;
}
@@ -460,12 +460,12 @@ static BOOL stroke_and_fill_path( dibdrv_physdev *dev, BOOL stroke, BOOL fill )
{
NtGdiCombineRgn( interior, interior, outline, RGN_DIFF );
ret = brush_region( dev, interior );
- DeleteObject( interior );
+ NtGdiDeleteObjectApp( interior );
}
if (outline)
{
if (ret) ret = pen_region( dev, outline );
- DeleteObject( outline );
+ NtGdiDeleteObjectApp( outline );
}
done:
@@ -1074,7 +1074,7 @@ BOOL CDECL dibdrv_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT
add_clipped_bounds( pdev, NULL, rgn );
brush_region( pdev, rgn );
- DeleteObject( rgn );
+ NtGdiDeleteObjectApp( rgn );
return TRUE;
}
@@ -1156,7 +1156,7 @@ BOOL CDECL dibdrv_LineTo( PHYSDEV dev, INT x, INT y )
if (region)
{
ret = pen_region( pdev, region );
- DeleteObject( region );
+ NtGdiDeleteObjectApp( region );
}
return ret;
}
@@ -1284,7 +1284,7 @@ BOOL CDECL dibdrv_PolyPolygon( PHYSDEV dev, const POINT *pt, const INT *counts,
if (interior && !outline)
{
ret = brush_region( pdev, interior );
- DeleteObject( interior );
+ NtGdiDeleteObjectApp( interior );
interior = 0;
}
@@ -1300,12 +1300,12 @@ BOOL CDECL dibdrv_PolyPolygon( PHYSDEV dev, const POINT *pt, const INT *counts,
{
NtGdiCombineRgn( interior, interior, outline, RGN_DIFF );
ret = brush_region( pdev, interior );
- DeleteObject( interior );
+ NtGdiDeleteObjectApp( interior );
}
if (outline)
{
if (ret) ret = pen_region( pdev, outline );
- DeleteObject( outline );
+ NtGdiDeleteObjectApp( outline );
}
done:
@@ -1357,7 +1357,7 @@ BOOL CDECL dibdrv_PolyPolyline( PHYSDEV dev, const POINT* pt, const DWORD* count
if (outline)
{
ret = pen_region( pdev, outline );
- DeleteObject( outline );
+ NtGdiDeleteObjectApp( outline );
}
done:
@@ -1425,10 +1425,10 @@ BOOL CDECL dibdrv_Rectangle( PHYSDEV dev, INT left, INT top, INT right, INT bott
NtGdiCombineRgn( interior, interior, outline, RGN_DIFF );
brush_region( pdev, interior );
- DeleteObject( interior );
+ NtGdiDeleteObjectApp( interior );
}
ret = pen_region( pdev, outline );
- DeleteObject( outline );
+ NtGdiDeleteObjectApp( outline );
}
else
{
@@ -1480,7 +1480,7 @@ BOOL CDECL dibdrv_RoundRect( PHYSDEV dev, INT left, INT top, INT right, INT bott
ellipse_width, ellipse_height )))
{
HeapFree( GetProcessHeap(), 0, points );
- if (outline) DeleteObject( outline );
+ if (outline) NtGdiDeleteObjectApp( outline );
return FALSE;
}
@@ -1488,7 +1488,7 @@ BOOL CDECL dibdrv_RoundRect( PHYSDEV dev, INT left, INT top, INT right, INT bott
if (interior && !outline)
{
ret = brush_region( pdev, interior );
- DeleteObject( interior );
+ NtGdiDeleteObjectApp( interior );
interior = 0;
}
@@ -1543,12 +1543,12 @@ BOOL CDECL dibdrv_RoundRect( PHYSDEV dev, INT left, INT top, INT right, INT bott
{
NtGdiCombineRgn( interior, interior, outline, RGN_DIFF );
ret = brush_region( pdev, interior );
- DeleteObject( interior );
+ NtGdiDeleteObjectApp( interior );
}
if (outline)
{
if (ret) ret = pen_region( pdev, outline );
- DeleteObject( outline );
+ NtGdiDeleteObjectApp( outline );
}
HeapFree( GetProcessHeap(), 0, points );
return ret;
diff --git a/dlls/gdi32/dibdrv/objects.c b/dlls/gdi32/dibdrv/objects.c
index 452b2705e51..e7eff6fdd03 100644
--- a/dlls/gdi32/dibdrv/objects.c
+++ b/dlls/gdi32/dibdrv/objects.c
@@ -1367,7 +1367,7 @@ static void add_join( dibdrv_physdev *pdev, HRGN region, HRGN round_cap, const P
NtGdiGetRgnBox( join, &rect );
if (clip_rect_to_dib( &pdev->dib, &rect ))
NtGdiCombineRgn( region, region, join, RGN_OR );
- DeleteObject( join );
+ NtGdiDeleteObjectApp( join );
return;
}
@@ -1499,7 +1499,7 @@ static BOOL wide_line_segment( dibdrv_physdev *pdev, HRGN total,
{
segment = CreatePolygonRgn( seg_pts, 4, ALTERNATE );
NtGdiCombineRgn( total, total, segment, RGN_OR );
- DeleteObject( segment );
+ NtGdiDeleteObjectApp( segment );
}
face_1->start = seg_pts[0];
@@ -1583,7 +1583,7 @@ static BOOL wide_pen_lines(dibdrv_physdev *pdev, int num, POINT *pts, BOOL close
else
wide_line_segments( pdev, num, pts, FALSE, 0, num - 1, &pts[0], &pts[num - 1], round_cap, total );
- if (round_cap) DeleteObject( round_cap );
+ if (round_cap) NtGdiDeleteObjectApp( round_cap );
return TRUE;
}
@@ -1702,7 +1702,7 @@ static BOOL dashed_wide_pen_lines(dibdrv_physdev *pdev, int num, POINT *pts, BOO
&pts[0], &initial_point, round_cap, total );
}
- if (round_cap) DeleteObject( round_cap );
+ if (round_cap) NtGdiDeleteObjectApp( round_cap );
return TRUE;
}
diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
index 792ba803257..6c5bc9ced94 100644
--- a/dlls/gdi32/font.c
+++ b/dlls/gdi32/font.c
@@ -4839,7 +4839,7 @@ BOOL CDECL nulldrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT
dp_to_lp( dc, (POINT *)&rc, 2 );
NtGdiPatBlt( dev->hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY );
NtGdiSelectBrush( dev->hdc, orig );
- DeleteObject( brush );
+ NtGdiDeleteObjectApp( brush );
}
}
@@ -4954,7 +4954,7 @@ BOOL CDECL nulldrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT
}
NtGdiSelectPen( dev->hdc, orig );
- DeleteObject( pen );
+ NtGdiDeleteObjectApp( pen );
return TRUE;
}
@@ -5351,7 +5351,7 @@ done:
NtGdiSelectPen(hdc, hpen);
hbrush = NtGdiSelectBrush(hdc, hbrush);
- DeleteObject(hbrush);
+ NtGdiDeleteObjectApp( hbrush );
}
release_dc_ptr( dc );
diff --git a/dlls/gdi32/gdiobj.c b/dlls/gdi32/gdiobj.c
index c12ff98c058..70148cdcb77 100644
--- a/dlls/gdi32/gdiobj.c
+++ b/dlls/gdi32/gdiobj.c
@@ -504,7 +504,7 @@ BOOL GDI_dec_ref_count( HGDIOBJ handle )
entry_obj( entry )->deleted = 0;
LeaveCriticalSection( &gdi_section );
TRACE( "executing delayed DeleteObject for %p\n", handle );
- DeleteObject( handle );
+ NtGdiDeleteObjectApp( handle );
return TRUE;
}
}
diff --git a/dlls/gdi32/painting.c b/dlls/gdi32/painting.c
index acb3a95f30f..a7f06ea7df3 100644
--- a/dlls/gdi32/painting.c
+++ b/dlls/gdi32/painting.c
@@ -92,7 +92,7 @@ BOOL CDECL nulldrv_FrameRgn( PHYSDEV dev, HRGN rgn, HBRUSH brush, INT width, INT
{
if (REGION_FrameRgn( tmp, rgn, width, height ))
ret = NtGdiFillRgn( dev->hdc, tmp, brush );
- DeleteObject( tmp );
+ NtGdiDeleteObjectApp( tmp );
}
return ret;
}
diff --git a/dlls/gdi32/path.c b/dlls/gdi32/path.c
index b3735f60b0b..74c972df1dd 100644
--- a/dlls/gdi32/path.c
+++ b/dlls/gdi32/path.c
@@ -721,7 +721,7 @@ BOOL WINAPI NtGdiSelectClipPath( HDC hdc, INT mode )
if ((rgn = NtGdiPathToRegion( hdc )))
{
ret = NtGdiExtSelectClipRgn( hdc, rgn, mode ) != ERROR;
- DeleteObject( rgn );
+ NtGdiDeleteObjectApp( rgn );
}
return ret;
}
diff --git a/dlls/gdi32/region.c b/dlls/gdi32/region.c
index 4df48209de5..757efc0ac1a 100644
--- a/dlls/gdi32/region.c
+++ b/dlls/gdi32/region.c
@@ -929,7 +929,7 @@ HRGN WINAPI NtGdiExtCreateRegion( const XFORM *xform, DWORD count, const RGNDATA
translate( pt, 4, xform );
poly_hrgn = CreatePolyPolygonRgn( pt, &count, 1, WINDING );
NtGdiCombineRgn( hrgn, hrgn, poly_hrgn, RGN_OR );
- DeleteObject( poly_hrgn );
+ NtGdiDeleteObjectApp( poly_hrgn );
}
return hrgn;
}
--
2.23.0
1
0
03 Sep '21
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/gdi32/bitblt.c | 2 +-
dlls/gdi32/bitmap.c | 2 +-
dlls/gdi32/dc.c | 20 ++++++++++----------
dlls/gdi32/dibdrv/objects.c | 8 ++++----
dlls/gdi32/font.c | 2 +-
dlls/gdi32/gdiobj.c | 23 +++++++++++++++++++++++
dlls/gdi32/ntgdi_private.h | 1 +
dlls/gdi32/painting.c | 2 +-
dlls/gdi32/palette.c | 8 ++++----
dlls/gdi32/pen.c | 2 +-
10 files changed, 47 insertions(+), 23 deletions(-)
diff --git a/dlls/gdi32/bitblt.c b/dlls/gdi32/bitblt.c
index e6a846c3d74..ec117199a86 100644
--- a/dlls/gdi32/bitblt.c
+++ b/dlls/gdi32/bitblt.c
@@ -785,7 +785,7 @@ BOOL WINAPI MaskBlt(HDC hdcDest, INT nXDest, INT nYDest,
return BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
hbrMask = CreatePatternBrush(hbmMask);
- hbrDst = NtGdiSelectBrush(hdcDest, GetStockObject(NULL_BRUSH));
+ hbrDst = NtGdiSelectBrush( hdcDest, get_stock_object(NULL_BRUSH) );
/* make bitmap */
hDC1 = NtGdiCreateCompatibleDC( hdcDest );
diff --git a/dlls/gdi32/bitmap.c b/dlls/gdi32/bitmap.c
index 1ce0e940235..cc9b106de0b 100644
--- a/dlls/gdi32/bitmap.c
+++ b/dlls/gdi32/bitmap.c
@@ -387,7 +387,7 @@ HGDIOBJ WINAPI NtGdiSelectBitmap( HDC hdc, HGDIOBJ handle )
goto done;
}
- if (handle != GetStockObject(DEFAULT_BITMAP) && GDI_get_ref_count( handle ))
+ if (handle != get_stock_object( DEFAULT_BITMAP ) && GDI_get_ref_count( handle ))
{
WARN( "Bitmap already selected in another DC\n" );
GDI_ReleaseObj( handle );
diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c
index 739dc53d31d..42217681b17 100644
--- a/dlls/gdi32/dc.c
+++ b/dlls/gdi32/dc.c
@@ -133,10 +133,10 @@ DC *alloc_dc_ptr( DWORD magic )
dc->physDev = &dc->nulldrv;
dc->thread = GetCurrentThreadId();
dc->refcount = 1;
- dc->hPen = GDI_inc_ref_count( GetStockObject( BLACK_PEN ));
- dc->hBrush = GDI_inc_ref_count( GetStockObject( WHITE_BRUSH ));
- dc->hFont = GDI_inc_ref_count( GetStockObject( SYSTEM_FONT ));
- dc->hPalette = GetStockObject( DEFAULT_PALETTE );
+ dc->hPen = GDI_inc_ref_count( get_stock_object( BLACK_PEN ));
+ dc->hBrush = GDI_inc_ref_count( get_stock_object( WHITE_BRUSH ));
+ dc->hFont = GDI_inc_ref_count( get_stock_object( SYSTEM_FONT ));
+ dc->hPalette = get_stock_object( DEFAULT_PALETTE );
set_initial_dc_state( dc );
@@ -395,11 +395,11 @@ static BOOL reset_dc_state( HDC hdc )
set_initial_dc_state( dc );
set_bk_color( dc, RGB( 255, 255, 255 ));
set_text_color( dc, RGB( 0, 0, 0 ));
- NtGdiSelectBrush( hdc, GetStockObject( WHITE_BRUSH ));
- NtGdiSelectFont( hdc, GetStockObject( SYSTEM_FONT ));
- NtGdiSelectPen( hdc, GetStockObject( BLACK_PEN ));
+ NtGdiSelectBrush( hdc, get_stock_object( WHITE_BRUSH ));
+ NtGdiSelectFont( hdc, get_stock_object( SYSTEM_FONT ));
+ NtGdiSelectPen( hdc, get_stock_object( BLACK_PEN ));
NtGdiSetVirtualResolution( hdc, 0, 0, 0, 0 );
- GDISelectPalette( hdc, GetStockObject( DEFAULT_PALETTE ), FALSE );
+ GDISelectPalette( hdc, get_stock_object( DEFAULT_PALETTE ), FALSE );
NtGdiSetBoundsRect( hdc, NULL, DCB_DISABLE );
NtGdiAbortPath( hdc );
@@ -659,7 +659,7 @@ HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output,
if (!(dc = alloc_dc_ptr( NTGDI_OBJ_DC ))) return 0;
hdc = dc->hSelf;
- dc->hBitmap = GDI_inc_ref_count( GetStockObject( DEFAULT_BITMAP ));
+ dc->hBitmap = GDI_inc_ref_count( get_stock_object( DEFAULT_BITMAP ));
TRACE("(driver=%s, device=%s, output=%s): returning %p\n",
debugstr_w(driver), debugstr_w(device), debugstr_w(output), dc->hSelf );
@@ -727,7 +727,7 @@ HDC WINAPI NtGdiCreateCompatibleDC( HDC hdc )
TRACE("(%p): returning %p\n", hdc, dc->hSelf );
- dc->hBitmap = GDI_inc_ref_count( GetStockObject( DEFAULT_BITMAP ));
+ dc->hBitmap = GDI_inc_ref_count( get_stock_object( DEFAULT_BITMAP ));
dc->attr->vis_rect.left = 0;
dc->attr->vis_rect.top = 0;
dc->attr->vis_rect.right = 1;
diff --git a/dlls/gdi32/dibdrv/objects.c b/dlls/gdi32/dibdrv/objects.c
index 4e24de0b3aa..452b2705e51 100644
--- a/dlls/gdi32/dibdrv/objects.c
+++ b/dlls/gdi32/dibdrv/objects.c
@@ -1770,7 +1770,7 @@ COLORREF CDECL dibdrv_SetDCPenColor( PHYSDEV dev, COLORREF color )
dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
DC *dc = get_physdev_dc( dev );
- if (dc->hPen == GetStockObject( DC_PEN ))
+ if (dc->hPen == get_stock_object( DC_PEN ))
pdev->pen_brush.colorref = color;
return color;
@@ -2136,7 +2136,7 @@ HBRUSH CDECL dibdrv_SelectBrush( PHYSDEV dev, HBRUSH hbrush, const struct brush_
GetObjectW( hbrush, sizeof(logbrush), &logbrush );
- if (hbrush == GetStockObject( DC_BRUSH ))
+ if (hbrush == get_stock_object( DC_BRUSH ))
logbrush.lbColor = dc->attr->brush_color;
select_brush( pdev, &pdev->brush, &logbrush, pattern, TRUE );
@@ -2188,7 +2188,7 @@ HPEN CDECL dibdrv_SelectPen( PHYSDEV dev, HPEN hpen, const struct brush_pattern
pdev->pen_endcap = logpen.lopnStyle & PS_ENDCAP_MASK;
pdev->pen_width = get_pen_device_width( dc, logpen.lopnWidth.x );
- if (hpen == GetStockObject( DC_PEN ))
+ if (hpen == get_stock_object( DC_PEN ))
logbrush.lbColor = dc->attr->pen_color;
set_dash_pattern( &pdev->pen_pattern, 0, NULL );
@@ -2256,7 +2256,7 @@ COLORREF CDECL dibdrv_SetDCBrushColor( PHYSDEV dev, COLORREF color )
dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
DC *dc = get_physdev_dc( dev );
- if (dc->hBrush == GetStockObject( DC_BRUSH ))
+ if (dc->hBrush == get_stock_object( DC_BRUSH ))
{
LOGBRUSH logbrush = { BS_SOLID, color, 0 };
select_brush( pdev, &pdev->brush, &logbrush, NULL, TRUE );
diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
index 1bbab661c95..792ba803257 100644
--- a/dlls/gdi32/font.c
+++ b/dlls/gdi32/font.c
@@ -5289,7 +5289,7 @@ done:
UINT size = NtGdiGetOutlineTextMetricsInternalW( hdc, 0, NULL, 0 );
OUTLINETEXTMETRICW* otm = NULL;
POINT pts[5];
- HPEN hpen = NtGdiSelectPen(hdc, GetStockObject(NULL_PEN));
+ HPEN hpen = NtGdiSelectPen( hdc, get_stock_object(NULL_PEN) );
HBRUSH hbrush = CreateSolidBrush( dc->attr->text_color );
hbrush = NtGdiSelectBrush(hdc, hbrush);
diff --git a/dlls/gdi32/gdiobj.c b/dlls/gdi32/gdiobj.c
index 50c337cd6c4..c12ff98c058 100644
--- a/dlls/gdi32/gdiobj.c
+++ b/dlls/gdi32/gdiobj.c
@@ -610,6 +610,29 @@ static void set_gdi_shared(void)
NtCurrentTeb()->Peb->GdiSharedHandleTable = &gdi_shared;
}
+HGDIOBJ get_stock_object( INT obj )
+{
+ assert( obj >= 0 && obj <= STOCK_LAST + 1 && obj != 9 );
+
+ switch (obj)
+ {
+ case OEM_FIXED_FONT:
+ if (get_system_dpi() != 96) obj = 9;
+ break;
+ case SYSTEM_FONT:
+ if (get_system_dpi() != 96) obj = STOCK_LAST + 2;
+ break;
+ case SYSTEM_FIXED_FONT:
+ if (get_system_dpi() != 96) obj = STOCK_LAST + 3;
+ break;
+ case DEFAULT_GUI_FONT:
+ if (get_system_dpi() != 96) obj = STOCK_LAST + 4;
+ break;
+ }
+
+ return entry_to_handle( handle_entry( ULongToHandle( obj + FIRST_GDI_HANDLE )));
+}
+
static void init_stock_objects(void)
{
const struct DefaultFontInfo *deffonts;
diff --git a/dlls/gdi32/ntgdi_private.h b/dlls/gdi32/ntgdi_private.h
index 73870fcd2f8..ec3db21a2bd 100644
--- a/dlls/gdi32/ntgdi_private.h
+++ b/dlls/gdi32/ntgdi_private.h
@@ -403,6 +403,7 @@ extern HGDIOBJ GDI_inc_ref_count( HGDIOBJ handle ) DECLSPEC_HIDDEN;
extern BOOL GDI_dec_ref_count( HGDIOBJ handle ) DECLSPEC_HIDDEN;
extern DWORD get_dpi(void) DECLSPEC_HIDDEN;
extern DWORD get_system_dpi(void) DECLSPEC_HIDDEN;
+extern HGDIOBJ get_stock_object( INT obj ) DECLSPEC_HIDDEN;
/* mapping.c */
extern BOOL dp_to_lp( DC *dc, POINT *points, INT count ) DECLSPEC_HIDDEN;
diff --git a/dlls/gdi32/painting.c b/dlls/gdi32/painting.c
index 1ab977595f8..acb3a95f30f 100644
--- a/dlls/gdi32/painting.c
+++ b/dlls/gdi32/painting.c
@@ -100,7 +100,7 @@ BOOL CDECL nulldrv_FrameRgn( PHYSDEV dev, HRGN rgn, HBRUSH brush, INT width, INT
BOOL CDECL nulldrv_InvertRgn( PHYSDEV dev, HRGN rgn )
{
INT prev_rop = SetROP2( dev->hdc, R2_NOT );
- BOOL ret = NtGdiFillRgn( dev->hdc, rgn, GetStockObject(BLACK_BRUSH) );
+ BOOL ret = NtGdiFillRgn( dev->hdc, rgn, get_stock_object(BLACK_BRUSH) );
SetROP2( dev->hdc, prev_rop );
return ret;
}
diff --git a/dlls/gdi32/palette.c b/dlls/gdi32/palette.c
index 0451adbdf80..a14ba9aeb08 100644
--- a/dlls/gdi32/palette.c
+++ b/dlls/gdi32/palette.c
@@ -202,7 +202,7 @@ static UINT set_palette_entries( HPALETTE hpalette, UINT start, UINT count,
TRACE("hpal=%p,start=%i,count=%i\n",hpalette,start,count );
hpalette = get_full_gdi_handle( hpalette );
- if (hpalette == GetStockObject(DEFAULT_PALETTE)) return 0;
+ if (hpalette == get_stock_object(DEFAULT_PALETTE)) return 0;
palPtr = GDI_GetObjPtr( hpalette, NTGDI_OBJ_PAL );
if (!palPtr) return 0;
@@ -255,7 +255,7 @@ static BOOL animate_palette( HPALETTE hPal, UINT StartIndex, UINT NumEntries,
TRACE("%p (%i - %i)\n", hPal, StartIndex,StartIndex+NumEntries);
hPal = get_full_gdi_handle( hPal );
- if( hPal != GetStockObject(DEFAULT_PALETTE) )
+ if( hPal != get_stock_object(DEFAULT_PALETTE) )
{
PALETTEOBJ * palPtr;
UINT pal_entries;
@@ -412,7 +412,7 @@ COLORREF CDECL nulldrv_GetNearestColor( PHYSDEV dev, COLORREF color )
PALETTEENTRY entry;
HPALETTE hpal = dc->hPalette;
- if (!hpal) hpal = GetStockObject( DEFAULT_PALETTE );
+ if (!hpal) hpal = get_stock_object( DEFAULT_PALETTE );
if (spec_type == 2) /* PALETTERGB */
index = NtGdiGetNearestPaletteIndex( hpal, color );
else /* PALETTEINDEX */
@@ -549,7 +549,7 @@ UINT WINAPI GDIRealizePalette( HDC hdc )
TRACE("%p...\n", hdc );
- if( dc->hPalette == GetStockObject( DEFAULT_PALETTE ))
+ if( dc->hPalette == get_stock_object( DEFAULT_PALETTE ))
{
PHYSDEV physdev = GET_DC_PHYSDEV( dc, pRealizeDefaultPalette );
realized = physdev->funcs->pRealizeDefaultPalette( physdev );
diff --git a/dlls/gdi32/pen.c b/dlls/gdi32/pen.c
index f79eaca4185..fa8b138229e 100644
--- a/dlls/gdi32/pen.c
+++ b/dlls/gdi32/pen.c
@@ -92,7 +92,7 @@ HPEN create_pen( INT style, INT width, COLORREF color )
HPEN WINAPI NtGdiCreatePen( INT style, INT width, COLORREF color, HBRUSH brush )
{
if (brush) FIXME( "brush not supported\n" );
- if (style == PS_NULL) return GetStockObject( NULL_PEN );
+ if (style == PS_NULL) return get_stock_object( NULL_PEN );
return create_pen( style, width, color );
}
--
2.23.0
1
0
[PATCH v2 4/6] gdi32: Get stock objects directly from GDI_SHARED_MEMORY in GetStockObject.
by Huw Davies 03 Sep '21
by Huw Davies 03 Sep '21
03 Sep '21
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/gdi32/gdiobj.c | 131 ++++++++++++++++++-------------------------
dlls/gdi32/objects.c | 52 +++++++++++++++++
2 files changed, 107 insertions(+), 76 deletions(-)
diff --git a/dlls/gdi32/gdiobj.c b/dlls/gdi32/gdiobj.c
index ffb42ab88e2..50c337cd6c4 100644
--- a/dlls/gdi32/gdiobj.c
+++ b/dlls/gdi32/gdiobj.c
@@ -82,13 +82,6 @@ static const LOGBRUSH DkGrayBrush = { BS_SOLID, RGB(64,64,64), 0 };
static const LOGBRUSH DCBrush = { BS_SOLID, RGB(255,255,255), 0 };
-/* reserve one extra entry for the stock default bitmap */
-/* this is what Windows does too */
-#define NB_STOCK_OBJECTS (STOCK_LAST+2)
-
-static HGDIOBJ stock_objects[NB_STOCK_OBJECTS];
-static HGDIOBJ scaled_stock_objects[NB_STOCK_OBJECTS];
-
static CRITICAL_SECTION gdi_section;
static CRITICAL_SECTION_DEBUG critsect_debug =
{
@@ -617,14 +610,62 @@ static void set_gdi_shared(void)
NtCurrentTeb()->Peb->GdiSharedHandleTable = &gdi_shared;
}
-static HGDIOBJ make_stock_object( HGDIOBJ obj )
+static void init_stock_objects(void)
{
- GDI_HANDLE_ENTRY *entry;
+ const struct DefaultFontInfo *deffonts;
+ unsigned int i;
+ HGDIOBJ obj;
+
+ /* Create stock objects in order matching stock object macros,
+ * so that they use predictable handle slots. Our GetStockObject
+ * depends on it. */
+ create_brush( &WhiteBrush );
+ create_brush( &LtGrayBrush );
+ create_brush( &GrayBrush );
+ create_brush( &DkGrayBrush );
+ create_brush( &BlackBrush );
+ create_brush( &NullBrush );
+
+ create_pen( PS_SOLID, 0, RGB(255,255,255) );
+ create_pen( PS_SOLID, 0, RGB(0,0,0) );
+ create_pen( PS_NULL, 0, RGB(0,0,0) );
+
+ /* slot 9 is not used for non-scaled stock objects */
+ create_scaled_font( &OEMFixedFont );
+
+ /* language-independent stock fonts */
+ create_font( &OEMFixedFont );
+ create_font( &AnsiFixedFont );
+ create_font( &AnsiVarFont );
+
+ /* language-dependent stock fonts */
+ deffonts = get_default_fonts(get_default_charset());
+ create_font( &deffonts->SystemFont );
+ create_font( &deffonts->DeviceDefaultFont );
+
+ PALETTE_Init();
+
+ create_font( &deffonts->SystemFixedFont );
+ create_font( &deffonts->DefaultGuiFont );
- if (!(entry = handle_entry( obj ))) return 0;
- entry_obj( entry )->system = TRUE;
- entry->StockFlag = 1;
- return entry_to_handle( entry );
+ create_brush( &DCBrush );
+ NtGdiCreatePen( PS_SOLID, 0, RGB(0,0,0), NULL );
+
+ obj = NtGdiCreateBitmap( 1, 1, 1, 1, NULL );
+
+ assert( (HandleToULong( obj ) & 0xffff) == FIRST_GDI_HANDLE + DEFAULT_BITMAP );
+
+ create_scaled_font( &deffonts->SystemFont );
+ create_scaled_font( &deffonts->SystemFixedFont );
+ create_scaled_font( &deffonts->DefaultGuiFont );
+
+ /* clear the NOSYSTEM bit on all stock objects*/
+ for (i = 0; i < STOCK_LAST + 5; i++)
+ {
+ GDI_HANDLE_ENTRY *entry = &gdi_shared.Handles[FIRST_GDI_HANDLE + i];
+ entry_obj( entry )->system = TRUE;
+ entry->StockFlag = 1;
+ }
}
/***********************************************************************
@@ -634,57 +675,13 @@ static HGDIOBJ make_stock_object( HGDIOBJ obj )
*/
BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
{
- const struct DefaultFontInfo* deffonts;
- int i;
-
if (reason != DLL_PROCESS_ATTACH) return TRUE;
gdi32_module = inst;
DisableThreadLibraryCalls( inst );
set_gdi_shared();
font_init();
-
- /* create stock objects */
- stock_objects[WHITE_BRUSH] = create_brush( &WhiteBrush );
- stock_objects[LTGRAY_BRUSH] = create_brush( &LtGrayBrush );
- stock_objects[GRAY_BRUSH] = create_brush( &GrayBrush );
- stock_objects[DKGRAY_BRUSH] = create_brush( &DkGrayBrush );
- stock_objects[BLACK_BRUSH] = create_brush( &BlackBrush );
- stock_objects[NULL_BRUSH] = create_brush( &NullBrush );
-
- stock_objects[WHITE_PEN] = create_pen( PS_SOLID, 0, RGB(255,255,255) );
- stock_objects[BLACK_PEN] = create_pen( PS_SOLID, 0, RGB(0,0,0) );
- stock_objects[NULL_PEN] = create_pen( PS_NULL, 0, RGB(0,0,0) );
-
- stock_objects[DEFAULT_PALETTE] = PALETTE_Init();
- stock_objects[DEFAULT_BITMAP] = NtGdiCreateBitmap( 1, 1, 1, 1, NULL );
-
- /* language-independent stock fonts */
- stock_objects[OEM_FIXED_FONT] = create_font( &OEMFixedFont );
- stock_objects[ANSI_FIXED_FONT] = create_font( &AnsiFixedFont );
- stock_objects[ANSI_VAR_FONT] = create_font( &AnsiVarFont );
-
- /* language-dependent stock fonts */
- deffonts = get_default_fonts(get_default_charset());
- stock_objects[SYSTEM_FONT] = create_font( &deffonts->SystemFont );
- stock_objects[DEVICE_DEFAULT_FONT] = create_font( &deffonts->DeviceDefaultFont );
- stock_objects[SYSTEM_FIXED_FONT] = create_font( &deffonts->SystemFixedFont );
- stock_objects[DEFAULT_GUI_FONT] = create_font( &deffonts->DefaultGuiFont );
-
- scaled_stock_objects[OEM_FIXED_FONT] = create_scaled_font( &OEMFixedFont );
- scaled_stock_objects[SYSTEM_FONT] = create_scaled_font( &deffonts->SystemFont );
- scaled_stock_objects[SYSTEM_FIXED_FONT] = create_scaled_font( &deffonts->SystemFixedFont );
- scaled_stock_objects[DEFAULT_GUI_FONT] = create_scaled_font( &deffonts->DefaultGuiFont );
-
- stock_objects[DC_BRUSH] = create_brush( &DCBrush );
- stock_objects[DC_PEN] = create_pen( PS_SOLID, 0, RGB(0,0,0) );
-
- /* clear the NOSYSTEM bit on all stock objects*/
- for (i = 0; i < NB_STOCK_OBJECTS; i++)
- {
- stock_objects[i] = make_stock_object( stock_objects[i] );
- scaled_stock_objects[i] = make_stock_object( scaled_stock_objects[i] );
- }
+ init_stock_objects();
return TRUE;
}
@@ -960,24 +957,6 @@ BOOL WINAPI NtGdiDeleteClientObj( HGDIOBJ handle )
return TRUE;
}
-/***********************************************************************
- * GetStockObject (GDI32.@)
- */
-HGDIOBJ WINAPI GetStockObject( INT obj )
-{
- if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
- switch (obj)
- {
- case OEM_FIXED_FONT:
- case SYSTEM_FONT:
- case SYSTEM_FIXED_FONT:
- case DEFAULT_GUI_FONT:
- if (get_system_dpi() != 96) return scaled_stock_objects[obj];
- break;
- }
- return stock_objects[obj];
-}
-
/***********************************************************************
* NtGdiExtGetObjectW (win32u.@)
diff --git a/dlls/gdi32/objects.c b/dlls/gdi32/objects.c
index b656c2a3f1e..5b1145c52a2 100644
--- a/dlls/gdi32/objects.c
+++ b/dlls/gdi32/objects.c
@@ -39,6 +39,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(gdi);
DEFINE_DEVPROPKEY(DEVPROPKEY_GPU_LUID, 0x60b193cb, 0x5276, 0x4d0f, 0x96, 0xfc, 0xf1, 0x73, 0xab, 0xad, 0x3e, 0xc6, 2);
+#define FIRST_GDI_HANDLE 32
+
struct hdc_list
{
HDC hdc;
@@ -95,6 +97,12 @@ static inline GDI_HANDLE_ENTRY *handle_entry( HGDIOBJ handle )
return NULL;
}
+static HGDIOBJ entry_to_handle( GDI_HANDLE_ENTRY *entry )
+{
+ unsigned int idx = entry - get_gdi_shared()->Handles;
+ return LongToHandle( idx | (entry->Unique << NTGDI_HANDLE_TYPE_SHIFT) );
+}
+
static DWORD get_object_type( HGDIOBJ obj )
{
GDI_HANDLE_ENTRY *entry = handle_entry( obj );
@@ -379,6 +387,50 @@ HGDIOBJ WINAPI GetCurrentObject( HDC hdc, UINT type )
return NtGdiGetDCObject( hdc, obj_type );
}
+/******************************************************************************
+ * get_system_dpi
+ *
+ * Get the system DPI, based on the DPI awareness mode.
+ */
+static DWORD get_system_dpi(void)
+{
+ static UINT (WINAPI *pGetDpiForSystem)(void);
+
+ if (!pGetDpiForSystem)
+ {
+ HMODULE user = GetModuleHandleW( L"user32.dll" );
+ if (user) pGetDpiForSystem = (void *)GetProcAddress( user, "GetDpiForSystem" );
+ }
+ return pGetDpiForSystem ? pGetDpiForSystem() : 96;
+}
+
+/***********************************************************************
+ * GetStockObject (GDI32.@)
+ */
+HGDIOBJ WINAPI GetStockObject( INT obj )
+{
+ if (obj < 0 || obj > STOCK_LAST + 1 || obj == 9) return 0;
+
+ /* Wine stores stock objects in predictable order, see init_stock_objects */
+ switch (obj)
+ {
+ case OEM_FIXED_FONT:
+ if (get_system_dpi() != 96) obj = 9;
+ break;
+ case SYSTEM_FONT:
+ if (get_system_dpi() != 96) obj = STOCK_LAST + 2;
+ break;
+ case SYSTEM_FIXED_FONT:
+ if (get_system_dpi() != 96) obj = STOCK_LAST + 3;
+ break;
+ case DEFAULT_GUI_FONT:
+ if (get_system_dpi() != 96) obj = STOCK_LAST + 4;
+ break;
+ }
+
+ return entry_to_handle( handle_entry( ULongToHandle( obj + FIRST_GDI_HANDLE )));
+}
+
/***********************************************************************
* GetObjectA (GDI32.@)
*/
--
2.23.0
1
0
03 Sep '21
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/gdi32/gdiobj.c | 40 +++++++++++++++++++++-----------------
dlls/gdi32/ntgdi_private.h | 3 +++
dlls/gdi32/palette.c | 2 +-
dlls/gdi32/pen.c | 18 ++++++++++-------
4 files changed, 37 insertions(+), 26 deletions(-)
diff --git a/dlls/gdi32/gdiobj.c b/dlls/gdi32/gdiobj.c
index 14b65429d4a..ffb42ab88e2 100644
--- a/dlls/gdi32/gdiobj.c
+++ b/dlls/gdi32/gdiobj.c
@@ -80,12 +80,7 @@ static const LOGBRUSH LtGrayBrush = { BS_SOLID, RGB(192,192,192), 0 };
static const LOGBRUSH GrayBrush = { BS_SOLID, RGB(128,128,128), 0 };
static const LOGBRUSH DkGrayBrush = { BS_SOLID, RGB(64,64,64), 0 };
-static const LOGPEN WhitePen = { PS_SOLID, { 0, 0 }, RGB(255,255,255) };
-static const LOGPEN BlackPen = { PS_SOLID, { 0, 0 }, RGB(0,0,0) };
-static const LOGPEN NullPen = { PS_NULL, { 0, 0 }, 0 };
-
static const LOGBRUSH DCBrush = { BS_SOLID, RGB(255,255,255), 0 };
-static const LOGPEN DCPen = { PS_SOLID, { 0, 0 }, RGB(0,0,0) };
/* reserve one extra entry for the stock default bitmap */
/* this is what Windows does too */
@@ -582,6 +577,15 @@ DWORD get_system_dpi(void)
return pGetDpiForSystem ? pGetDpiForSystem() : 96;
}
+static HFONT create_font( const LOGFONTW *deffont )
+{
+ ENUMLOGFONTEXDVW lf;
+
+ memset( &lf, 0, sizeof(lf) );
+ lf.elfEnumLogfontEx.elfLogFont = *deffont;
+ return NtGdiHfontCreate( &lf, sizeof(lf), 0, 0, NULL );
+}
+
static HFONT create_scaled_font( const LOGFONTW *deffont )
{
LOGFONTW lf;
@@ -595,7 +599,7 @@ static HFONT create_scaled_font( const LOGFONTW *deffont )
lf = *deffont;
lf.lfHeight = MulDiv( lf.lfHeight, dpi, 96 );
- return CreateFontIndirectW( &lf );
+ return create_font( &lf );
}
static void set_gdi_shared(void)
@@ -648,24 +652,24 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
stock_objects[BLACK_BRUSH] = create_brush( &BlackBrush );
stock_objects[NULL_BRUSH] = create_brush( &NullBrush );
- stock_objects[WHITE_PEN] = CreatePenIndirect( &WhitePen );
- stock_objects[BLACK_PEN] = CreatePenIndirect( &BlackPen );
- stock_objects[NULL_PEN] = CreatePenIndirect( &NullPen );
+ stock_objects[WHITE_PEN] = create_pen( PS_SOLID, 0, RGB(255,255,255) );
+ stock_objects[BLACK_PEN] = create_pen( PS_SOLID, 0, RGB(0,0,0) );
+ stock_objects[NULL_PEN] = create_pen( PS_NULL, 0, RGB(0,0,0) );
stock_objects[DEFAULT_PALETTE] = PALETTE_Init();
- stock_objects[DEFAULT_BITMAP] = CreateBitmap( 1, 1, 1, 1, NULL );
+ stock_objects[DEFAULT_BITMAP] = NtGdiCreateBitmap( 1, 1, 1, 1, NULL );
/* language-independent stock fonts */
- stock_objects[OEM_FIXED_FONT] = CreateFontIndirectW( &OEMFixedFont );
- stock_objects[ANSI_FIXED_FONT] = CreateFontIndirectW( &AnsiFixedFont );
- stock_objects[ANSI_VAR_FONT] = CreateFontIndirectW( &AnsiVarFont );
+ stock_objects[OEM_FIXED_FONT] = create_font( &OEMFixedFont );
+ stock_objects[ANSI_FIXED_FONT] = create_font( &AnsiFixedFont );
+ stock_objects[ANSI_VAR_FONT] = create_font( &AnsiVarFont );
/* language-dependent stock fonts */
deffonts = get_default_fonts(get_default_charset());
- stock_objects[SYSTEM_FONT] = CreateFontIndirectW( &deffonts->SystemFont );
- stock_objects[DEVICE_DEFAULT_FONT] = CreateFontIndirectW( &deffonts->DeviceDefaultFont );
- stock_objects[SYSTEM_FIXED_FONT] = CreateFontIndirectW( &deffonts->SystemFixedFont );
- stock_objects[DEFAULT_GUI_FONT] = CreateFontIndirectW( &deffonts->DefaultGuiFont );
+ stock_objects[SYSTEM_FONT] = create_font( &deffonts->SystemFont );
+ stock_objects[DEVICE_DEFAULT_FONT] = create_font( &deffonts->DeviceDefaultFont );
+ stock_objects[SYSTEM_FIXED_FONT] = create_font( &deffonts->SystemFixedFont );
+ stock_objects[DEFAULT_GUI_FONT] = create_font( &deffonts->DefaultGuiFont );
scaled_stock_objects[OEM_FIXED_FONT] = create_scaled_font( &OEMFixedFont );
scaled_stock_objects[SYSTEM_FONT] = create_scaled_font( &deffonts->SystemFont );
@@ -673,7 +677,7 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
scaled_stock_objects[DEFAULT_GUI_FONT] = create_scaled_font( &deffonts->DefaultGuiFont );
stock_objects[DC_BRUSH] = create_brush( &DCBrush );
- stock_objects[DC_PEN] = CreatePenIndirect( &DCPen );
+ stock_objects[DC_PEN] = create_pen( PS_SOLID, 0, RGB(0,0,0) );
/* clear the NOSYSTEM bit on all stock objects*/
for (i = 0; i < NB_STOCK_OBJECTS; i++)
diff --git a/dlls/gdi32/ntgdi_private.h b/dlls/gdi32/ntgdi_private.h
index a438a3f93ae..73870fcd2f8 100644
--- a/dlls/gdi32/ntgdi_private.h
+++ b/dlls/gdi32/ntgdi_private.h
@@ -453,6 +453,9 @@ extern HPALETTE PALETTE_Init(void) DECLSPEC_HIDDEN;
extern UINT get_palette_entries( HPALETTE hpalette, UINT start, UINT count,
PALETTEENTRY *entries ) DECLSPEC_HIDDEN;
+/* pen.c */
+extern HPEN create_pen( INT style, INT width, COLORREF color ) DECLSPEC_HIDDEN;
+
/* region.c */
extern BOOL add_rect_to_region( HRGN rgn, const RECT *rect ) DECLSPEC_HIDDEN;
extern INT mirror_region( HRGN dst, HRGN src, INT width ) DECLSPEC_HIDDEN;
diff --git a/dlls/gdi32/palette.c b/dlls/gdi32/palette.c
index aa7745dc65f..0451adbdf80 100644
--- a/dlls/gdi32/palette.c
+++ b/dlls/gdi32/palette.c
@@ -89,7 +89,7 @@ HPALETTE PALETTE_Init(void)
palPtr->palPalEntry[i].peBlue = entries[i < 10 ? i : 236 + i].rgbBlue;
palPtr->palPalEntry[i].peFlags = 0;
}
- return CreatePalette( palPtr );
+ return NtGdiCreatePaletteInternal( palPtr, palPtr->palNumEntries );
}
diff --git a/dlls/gdi32/pen.c b/dlls/gdi32/pen.c
index ff2a766d40c..f79eaca4185 100644
--- a/dlls/gdi32/pen.c
+++ b/dlls/gdi32/pen.c
@@ -50,17 +50,12 @@ static const struct gdi_obj_funcs pen_funcs =
PEN_DeleteObject /* pDeleteObject */
};
-
-/***********************************************************************
- * NtGdiCreatePen (win32u.@)
- */
-HPEN WINAPI NtGdiCreatePen( INT style, INT width, COLORREF color, HBRUSH brush )
+HPEN create_pen( INT style, INT width, COLORREF color )
{
PENOBJ *penPtr;
HPEN hpen;
TRACE( "%d %d %06x\n", style, width, color );
- if (brush) FIXME( "brush not supported\n" );
switch (style)
{
@@ -72,7 +67,6 @@ HPEN WINAPI NtGdiCreatePen( INT style, INT width, COLORREF color, HBRUSH brush )
case PS_INSIDEFRAME:
break;
case PS_NULL:
- if ((hpen = GetStockObject( NULL_PEN ))) return hpen;
width = 1;
color = 0;
break;
@@ -92,6 +86,16 @@ HPEN WINAPI NtGdiCreatePen( INT style, INT width, COLORREF color, HBRUSH brush )
return hpen;
}
+/***********************************************************************
+ * NtGdiCreatePen (win32u.@)
+ */
+HPEN WINAPI NtGdiCreatePen( INT style, INT width, COLORREF color, HBRUSH brush )
+{
+ if (brush) FIXME( "brush not supported\n" );
+ if (style == PS_NULL) return GetStockObject( NULL_PEN );
+ return create_pen( style, width, color );
+}
+
/***********************************************************************
* NtGdiExtCreatePen (win32u.@)
*/
--
2.23.0
1
0