You've already forked wine-staging
mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-09-12 18:50:20 -07:00
Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
b09545bc48 | ||
|
8c98aa0c22 | ||
|
31cab243e7 | ||
|
caa47e6c73 | ||
|
d102a32693 | ||
|
784382204b |
@@ -1,4 +1,4 @@
|
||||
From 8aa6fb73e3142d86ba354c204313b8a74a5fa43d Mon Sep 17 00:00:00 2001
|
||||
From fb422ad56e3549e81d3b60afc77b0a0c6a56f672 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Thu, 2 Oct 2014 19:53:46 +0200
|
||||
Subject: [PATCH] winelib: Append '(Staging)' at the end of the version string.
|
||||
@@ -8,10 +8,10 @@ Subject: [PATCH] winelib: Append '(Staging)' at the end of the version string.
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index f86a5decb07..3d7f9cc96e6 100644
|
||||
index b4ede761391..ea6bd2fae3c 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -3910,7 +3910,7 @@ dnl Rules for generated source files
|
||||
@@ -3728,7 +3728,7 @@ dnl Rules for generated source files
|
||||
|
||||
WINE_APPEND_RULE(
|
||||
[dlls/ntdll/unix/version.c: dummy
|
||||
@@ -19,7 +19,7 @@ index f86a5decb07..3d7f9cc96e6 100644
|
||||
+ @version=\`(GIT_DIR=${wine_srcdir}.git git describe HEAD 2>/dev/null || echo \"wine-\$(PACKAGE_VERSION)\") | sed -n -e '\$\$s/\(.*\)/const char wine_build[[]] = \"\\1 (Staging)\";/p'\` && (echo \$\$version | cmp -s - \$[@]) || echo \$\$version >\$[@] || (rm -f \$[@] && exit 1)
|
||||
programs/winetest/build.rc: dummy
|
||||
@build=\"STRINGTABLE { 1 \\\"\`GIT_DIR=${wine_srcdir}.git git rev-parse HEAD 2>/dev/null\`\\\" }\" && (echo \$\$build | cmp -s - \$[@]) || echo \$\$build >\$[@] || (rm -f \$[@] && exit 1)
|
||||
programs/winetest/build.nfo:
|
||||
dlls/wineandroid.drv/wine-debug.apk: dlls/wineandroid.drv/build.gradle ${wine_srcdir}dlls/wineandroid.drv/AndroidManifest.xml ${wine_srcdir}dlls/wineandroid.drv/WineActivity.java ${wine_srcdir}dlls/wineandroid.drv/wine.svg
|
||||
--
|
||||
2.33.0
|
||||
2.47.2
|
||||
|
||||
|
@@ -0,0 +1,24 @@
|
||||
From 8a9c55d23750ca2650eba518e46549d8b5d94b43 Mon Sep 17 00:00:00 2001
|
||||
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
|
||||
Date: Fri, 11 Jul 2025 14:11:36 +1000
|
||||
Subject: [PATCH] comctl32: Animate support AVI msvc codex
|
||||
|
||||
---
|
||||
dlls/comctl32/animate.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/dlls/comctl32/animate.c b/dlls/comctl32/animate.c
|
||||
index 46e1e37b72d..717422c784f 100644
|
||||
--- a/dlls/comctl32/animate.c
|
||||
+++ b/dlls/comctl32/animate.c
|
||||
@@ -644,6 +644,7 @@ static BOOL ANIMATE_GetAviCodec(ANIMATE_INFO *infoPtr)
|
||||
/* check uncompressed AVI */
|
||||
if ((infoPtr->ash.fccHandler == mmioFOURCC('D', 'I', 'B', ' ')) ||
|
||||
(infoPtr->ash.fccHandler == mmioFOURCC('R', 'L', 'E', ' ')) ||
|
||||
+ (infoPtr->ash.fccHandler == mmioFOURCC('m', 's', 'v', 'c')) ||
|
||||
(infoPtr->ash.fccHandler == mmioFOURCC(0, 0, 0, 0)))
|
||||
{
|
||||
infoPtr->hic = 0;
|
||||
--
|
||||
2.47.2
|
||||
|
@@ -0,0 +1,24 @@
|
||||
From b8cce6663a956f8fb8f07700672e378b44b1af1c Mon Sep 17 00:00:00 2001
|
||||
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
|
||||
Date: Fri, 11 Jul 2025 15:21:07 +1000
|
||||
Subject: [PATCH] comctl32: Animate to support RLE8 codex
|
||||
|
||||
---
|
||||
dlls/comctl32/animate.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/dlls/comctl32/animate.c b/dlls/comctl32/animate.c
|
||||
index 717422c784f..ca4fae85a11 100644
|
||||
--- a/dlls/comctl32/animate.c
|
||||
+++ b/dlls/comctl32/animate.c
|
||||
@@ -645,6 +645,7 @@ static BOOL ANIMATE_GetAviCodec(ANIMATE_INFO *infoPtr)
|
||||
if ((infoPtr->ash.fccHandler == mmioFOURCC('D', 'I', 'B', ' ')) ||
|
||||
(infoPtr->ash.fccHandler == mmioFOURCC('R', 'L', 'E', ' ')) ||
|
||||
(infoPtr->ash.fccHandler == mmioFOURCC('m', 's', 'v', 'c')) ||
|
||||
+ (infoPtr->ash.fccHandler == mmioFOURCC('m', 'r', 'l', 'e')) ||
|
||||
(infoPtr->ash.fccHandler == mmioFOURCC(0, 0, 0, 0)))
|
||||
{
|
||||
infoPtr->hic = 0;
|
||||
--
|
||||
2.47.2
|
||||
|
@@ -0,0 +1,119 @@
|
||||
From 2ef9715ae9fffa0a6d7cdf0dc04e8de7eb245ce4 Mon Sep 17 00:00:00 2001
|
||||
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
|
||||
Date: Fri, 11 Jul 2025 18:07:39 +1000
|
||||
Subject: [PATCH] comctl32: Animate control doesn't support compressed AVI
|
||||
|
||||
The Animate control only supporst uncompress AVI with the excpetion of RLE8.
|
||||
---
|
||||
dlls/comctl32/animate.c | 64 ++---------------------------------------
|
||||
1 file changed, 3 insertions(+), 61 deletions(-)
|
||||
|
||||
diff --git a/dlls/comctl32/animate.c b/dlls/comctl32/animate.c
|
||||
index ca4fae85a11..74516db81f5 100644
|
||||
--- a/dlls/comctl32/animate.c
|
||||
+++ b/dlls/comctl32/animate.c
|
||||
@@ -39,14 +39,6 @@
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(animate);
|
||||
|
||||
-static struct {
|
||||
- HMODULE hModule;
|
||||
- HIC (WINAPI *fnICOpen)(DWORD, DWORD, UINT);
|
||||
- LRESULT (WINAPI *fnICClose)(HIC);
|
||||
- LRESULT (WINAPI *fnICSendMessage)(HIC, UINT, DWORD_PTR, DWORD_PTR);
|
||||
- DWORD (WINAPIV *fnICDecompress)(HIC,DWORD,LPBITMAPINFOHEADER,LPVOID,LPBITMAPINFOHEADER,LPVOID);
|
||||
-} fnIC;
|
||||
-
|
||||
typedef struct
|
||||
{
|
||||
/* reference to input stream (file or resource) */
|
||||
@@ -189,11 +181,6 @@ static void ANIMATE_Free(ANIMATE_INFO *infoPtr)
|
||||
}
|
||||
Free (infoPtr->lpIndex);
|
||||
infoPtr->lpIndex = NULL;
|
||||
- if (infoPtr->hic)
|
||||
- {
|
||||
- fnIC.fnICClose(infoPtr->hic);
|
||||
- infoPtr->hic = 0;
|
||||
- }
|
||||
Free (infoPtr->inbih);
|
||||
infoPtr->inbih = NULL;
|
||||
Free (infoPtr->outbih);
|
||||
@@ -342,13 +329,6 @@ static BOOL ANIMATE_DrawFrame(ANIMATE_INFO *infoPtr, HDC hDC)
|
||||
mmioSeek(infoPtr->hMMio, infoPtr->lpIndex[infoPtr->currFrame], SEEK_SET);
|
||||
mmioRead(infoPtr->hMMio, infoPtr->indata, infoPtr->ash.dwSuggestedBufferSize);
|
||||
|
||||
- if (infoPtr->hic &&
|
||||
- fnIC.fnICDecompress(infoPtr->hic, 0, infoPtr->inbih, infoPtr->indata,
|
||||
- infoPtr->outbih, infoPtr->outdata) != ICERR_OK) {
|
||||
- WARN("Decompression error\n");
|
||||
- return FALSE;
|
||||
- }
|
||||
-
|
||||
ANIMATE_PaintFrame(infoPtr, hDC);
|
||||
|
||||
if (infoPtr->currFrame++ >= infoPtr->nToFrame) {
|
||||
@@ -649,39 +629,12 @@ static BOOL ANIMATE_GetAviCodec(ANIMATE_INFO *infoPtr)
|
||||
(infoPtr->ash.fccHandler == mmioFOURCC(0, 0, 0, 0)))
|
||||
{
|
||||
infoPtr->hic = 0;
|
||||
- return TRUE;
|
||||
- }
|
||||
-
|
||||
- /* try to get a decompressor for that type */
|
||||
- infoPtr->hic = fnIC.fnICOpen(ICTYPE_VIDEO, infoPtr->ash.fccHandler, ICMODE_DECOMPRESS);
|
||||
- if (!infoPtr->hic) {
|
||||
- WARN("Can't load codec for the file\n");
|
||||
- return FALSE;
|
||||
- }
|
||||
-
|
||||
- outSize = fnIC.fnICSendMessage(infoPtr->hic, ICM_DECOMPRESS_GET_FORMAT,
|
||||
- (DWORD_PTR)infoPtr->inbih, 0L);
|
||||
-
|
||||
- if (!(infoPtr->outbih = Alloc(outSize)))
|
||||
- return FALSE;
|
||||
-
|
||||
- if (fnIC.fnICSendMessage(infoPtr->hic, ICM_DECOMPRESS_GET_FORMAT,
|
||||
- (DWORD_PTR)infoPtr->inbih, (DWORD_PTR)infoPtr->outbih) != ICERR_OK)
|
||||
- {
|
||||
- WARN("Can't get output BIH\n");
|
||||
- return FALSE;
|
||||
+ return TRUE;
|
||||
}
|
||||
|
||||
- if (!(infoPtr->outdata = Alloc(infoPtr->outbih->biSizeImage)))
|
||||
- return FALSE;
|
||||
+ FIXME("Unsupported %s\n", debugstr_fourcc(infoPtr->ash.fccHandler));
|
||||
|
||||
- if (fnIC.fnICSendMessage(infoPtr->hic, ICM_DECOMPRESS_BEGIN,
|
||||
- (DWORD_PTR)infoPtr->inbih, (DWORD_PTR)infoPtr->outbih) != ICERR_OK) {
|
||||
- WARN("Can't begin decompression\n");
|
||||
- return FALSE;
|
||||
- }
|
||||
-
|
||||
- return TRUE;
|
||||
+ return FALSE;
|
||||
}
|
||||
|
||||
|
||||
@@ -790,17 +743,6 @@ static BOOL ANIMATE_Create(HWND hWnd, const CREATESTRUCTW *lpcs)
|
||||
{
|
||||
ANIMATE_INFO *infoPtr;
|
||||
|
||||
- if (!fnIC.hModule)
|
||||
- {
|
||||
- fnIC.hModule = LoadLibraryW(L"msvfw32.dll");
|
||||
- if (!fnIC.hModule) return FALSE;
|
||||
-
|
||||
- fnIC.fnICOpen = (void*)GetProcAddress(fnIC.hModule, "ICOpen");
|
||||
- fnIC.fnICClose = (void*)GetProcAddress(fnIC.hModule, "ICClose");
|
||||
- fnIC.fnICSendMessage = (void*)GetProcAddress(fnIC.hModule, "ICSendMessage");
|
||||
- fnIC.fnICDecompress = (void*)GetProcAddress(fnIC.hModule, "ICDecompress");
|
||||
- }
|
||||
-
|
||||
/* allocate memory for info structure */
|
||||
infoPtr = Alloc(sizeof(*infoPtr));
|
||||
if (!infoPtr) return FALSE;
|
||||
--
|
||||
2.47.2
|
||||
|
2
patches/comctl32_animate_avi/definition
Normal file
2
patches/comctl32_animate_avi/definition
Normal file
@@ -0,0 +1,2 @@
|
||||
Fixes: [52278] comctl32: Animate support AVI msvc codex.
|
||||
|
@@ -0,0 +1,97 @@
|
||||
From 2135156d666a6a7a779326b7f1fdcbd2a8d58c8a Mon Sep 17 00:00:00 2001
|
||||
From: Spencer Wallace <spencerwallace@esri.com>
|
||||
Date: Mon, 24 Feb 2025 13:33:18 -0800
|
||||
Subject: [PATCH] msxml3: Correct looping of Document Element properties.
|
||||
|
||||
---
|
||||
dlls/msxml3/element.c | 2 ++
|
||||
dlls/msxml3/tests/domdoc.c | 53 ++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 55 insertions(+)
|
||||
|
||||
diff --git a/dlls/msxml3/element.c b/dlls/msxml3/element.c
|
||||
index 0fe72dcef9c..3e3c2d06169 100644
|
||||
--- a/dlls/msxml3/element.c
|
||||
+++ b/dlls/msxml3/element.c
|
||||
@@ -1812,6 +1812,8 @@ static HRESULT domelem_get_item(const xmlNodePtr node, LONG index, IXMLDOMNode *
|
||||
*item = create_node( (xmlNodePtr) curr );
|
||||
return S_OK;
|
||||
}
|
||||
+
|
||||
+ ++attrIndex;
|
||||
}
|
||||
|
||||
if (!node->nsDef)
|
||||
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
|
||||
index dcb83f781ba..84a1f330582 100644
|
||||
--- a/dlls/msxml3/tests/domdoc.c
|
||||
+++ b/dlls/msxml3/tests/domdoc.c
|
||||
@@ -10224,6 +10224,15 @@ static void test_get_attributes(void)
|
||||
L"xmlns:dcterms",
|
||||
L"xmlns:foaf"
|
||||
};
|
||||
+ const WCHAR *attributes[] =
|
||||
+ {
|
||||
+ L"rdf:about",
|
||||
+ L"dcterms:created",
|
||||
+ L"xmlns:oslc_am",
|
||||
+ L"xmlns:rdf",
|
||||
+ L"xmlns:dcterms",
|
||||
+ L"xmlns:foaf"
|
||||
+ };
|
||||
const get_attributes_t *entry = get_attributes;
|
||||
IXMLDOMNamedNodeMap *map;
|
||||
IXMLDOMDocument *doc, *doc2;
|
||||
@@ -10505,6 +10514,50 @@ static void test_get_attributes(void)
|
||||
|
||||
IXMLDOMDocument_Release(doc);
|
||||
|
||||
+ str = SysAllocString(L"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
+ L"<rdf:RDF rdf:about=\"foo\""
|
||||
+ L" dcterms:created=\"2025\""
|
||||
+ L" xmlns:oslc_am=\"http://open-services.net/ns/am#\""
|
||||
+ L" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\""
|
||||
+ L" xmlns:dcterms=\"http://purl.org/dc/terms/\""
|
||||
+ L" xmlns:foaf=\"http://xmlns.com/foaf/0.1/\" >"
|
||||
+ L"</rdf:RDF>");
|
||||
+
|
||||
+ doc = create_document(&IID_IXMLDOMDocument2);
|
||||
+
|
||||
+ hr = IXMLDOMDocument_loadXML(doc, str, &b);
|
||||
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
+ ok(b == VARIANT_TRUE, "got %d\n", b);
|
||||
+
|
||||
+ hr = IXMLDOMDocument_get_documentElement(doc, &elem);
|
||||
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
+
|
||||
+ hr = IXMLDOMElement_get_attributes(elem, &map);
|
||||
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
+
|
||||
+ length = -1;
|
||||
+ hr = IXMLDOMNamedNodeMap_get_length(map, &length);
|
||||
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
+ ok(length == 6, "length %#lx.\n", length);
|
||||
+
|
||||
+ for(i=0; i < length; i++)
|
||||
+ {
|
||||
+ hr = IXMLDOMNamedNodeMap_get_item(map, i, &node2);
|
||||
+ ok( hr == S_OK, "Unexpected hr %#lx (%ld).\n", hr, i);
|
||||
+
|
||||
+ hr = IXMLDOMNode_get_nodeName(node2, &str);
|
||||
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
+ ok(!lstrcmpW(str, attributes[i]), "got %s\n", wine_dbgstr_w(str));
|
||||
+ SysFreeString(str);
|
||||
+
|
||||
+ IXMLDOMNode_Release(node2);
|
||||
+ }
|
||||
+
|
||||
+ IXMLDOMNamedNodeMap_Release(map);
|
||||
+ IXMLDOMElement_Release(elem);
|
||||
+
|
||||
+ IXMLDOMDocument_Release(doc);
|
||||
+
|
||||
free_bstrs();
|
||||
}
|
||||
|
||||
--
|
||||
2.47.2
|
||||
|
@@ -0,0 +1,46 @@
|
||||
From 9be306cd143e6bf5f300a321101fb713edb9155b Mon Sep 17 00:00:00 2001
|
||||
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
|
||||
Date: Sat, 12 Jul 2025 15:20:04 +1000
|
||||
Subject: [PATCH] msxml: Support ISAXXMLReader::putFeature
|
||||
normalize-line-breaks option
|
||||
|
||||
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=36686
|
||||
---
|
||||
dlls/msxml3/saxreader.c | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/msxml3/saxreader.c b/dlls/msxml3/saxreader.c
|
||||
index 71a7f334420..9650af38597 100644
|
||||
--- a/dlls/msxml3/saxreader.c
|
||||
+++ b/dlls/msxml3/saxreader.c
|
||||
@@ -60,7 +60,8 @@ typedef enum
|
||||
SuppressValidationfatalError = 1 << 12,
|
||||
UseInlineSchema = 1 << 13,
|
||||
UseSchemaLocation = 1 << 14,
|
||||
- LexicalHandlerParEntities = 1 << 15
|
||||
+ LexicalHandlerParEntities = 1 << 15,
|
||||
+ NormalizeLineBreaks = 1 << 16,
|
||||
} saxreader_feature;
|
||||
|
||||
struct saxreader_feature_pair
|
||||
@@ -78,6 +79,7 @@ static const struct saxreader_feature_pair saxreader_feature_map[] = {
|
||||
{ Namespaces, L"http://xml.org/sax/features/namespaces" },
|
||||
{ ProhibitDTD, L"prohibit-dtd" },
|
||||
{ SchemaValidation, L"schema-validation" },
|
||||
+ { NormalizeLineBreaks, L"normalize-line-breaks" },
|
||||
};
|
||||
|
||||
static saxreader_feature get_saxreader_feature(const WCHAR *name)
|
||||
@@ -3159,7 +3161,8 @@ static HRESULT WINAPI isaxxmlreader_putFeature(
|
||||
if (feature == LexicalHandlerParEntities ||
|
||||
feature == ProhibitDTD ||
|
||||
feature == ExternalGeneralEntities ||
|
||||
- feature == ExternalParameterEntities)
|
||||
+ feature == ExternalParameterEntities ||
|
||||
+ feature == NormalizeLineBreaks)
|
||||
{
|
||||
FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
|
||||
return set_feature_value(This, feature, value);
|
||||
--
|
||||
2.47.2
|
||||
|
2
patches/msxml_normalize_line/definition
Normal file
2
patches/msxml_normalize_line/definition
Normal file
@@ -0,0 +1,2 @@
|
||||
Fixes: [36686] msxml: Support ISAXXMLReader::putFeature normalize-line-breaks option
|
||||
|
@@ -38,190 +38,6 @@ index f7558bb5d86..aad14d17e61 100644
|
||||
|
||||
EXTRADLLFLAGS = -nodefaultlibs
|
||||
i386_EXTRADLLFLAGS = -Wl,--image-base,0x7bc00000
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index a2ccf3f5332..121ebe5d62a 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "winuser.h"
|
||||
#include "winioctl.h"
|
||||
#include "winnls.h"
|
||||
+#include "ddk/ntifs.h"
|
||||
|
||||
#ifndef IO_COMPLETION_ALL_ACCESS
|
||||
#define IO_COMPLETION_ALL_ACCESS 0x001F0003
|
||||
@@ -5970,32 +5971,154 @@ static void test_mailslot_name(void)
|
||||
CloseHandle( device );
|
||||
}
|
||||
|
||||
+static INT build_reparse_buffer(const WCHAR *filename, REPARSE_DATA_BUFFER **pbuffer)
|
||||
+{
|
||||
+ static INT header_size = offsetof(REPARSE_DATA_BUFFER, GenericReparseBuffer);
|
||||
+ INT buffer_size, struct_size, data_size, string_len, prefix_len;
|
||||
+ WCHAR *subst_dest, *print_dest;
|
||||
+ REPARSE_DATA_BUFFER *buffer;
|
||||
+
|
||||
+ struct_size = offsetof(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer[0]);
|
||||
+ prefix_len = strlen("\\??\\");
|
||||
+ string_len = lstrlenW(&filename[prefix_len]);
|
||||
+ data_size = (prefix_len + 2 * string_len + 2) * sizeof(WCHAR);
|
||||
+ buffer_size = struct_size + data_size;
|
||||
+ buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer_size);
|
||||
+ buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
|
||||
+ buffer->ReparseDataLength = struct_size - header_size + data_size;
|
||||
+ buffer->MountPointReparseBuffer.SubstituteNameLength = (prefix_len + string_len) * sizeof(WCHAR);
|
||||
+ buffer->MountPointReparseBuffer.PrintNameOffset = (prefix_len + string_len + 1) * sizeof(WCHAR);
|
||||
+ buffer->MountPointReparseBuffer.PrintNameLength = string_len * sizeof(WCHAR);
|
||||
+ subst_dest = &buffer->MountPointReparseBuffer.PathBuffer[0];
|
||||
+ print_dest = &buffer->MountPointReparseBuffer.PathBuffer[prefix_len + string_len + 1];
|
||||
+ lstrcpyW(subst_dest, filename);
|
||||
+ lstrcpyW(print_dest, &filename[prefix_len]);
|
||||
+ *pbuffer = buffer;
|
||||
+ return buffer_size;
|
||||
+}
|
||||
+
|
||||
static void test_reparse_points(void)
|
||||
{
|
||||
- OBJECT_ATTRIBUTES attr;
|
||||
- HANDLE handle;
|
||||
- IO_STATUS_BLOCK io;
|
||||
- NTSTATUS status;
|
||||
+ WCHAR path[MAX_PATH], reparse_path[MAX_PATH], target_path[MAX_PATH], volnameW[MAX_PATH];
|
||||
+ static const WCHAR reparseW[] = {'\\','r','e','p','a','r','s','e',0};
|
||||
+ static const WCHAR targetW[] = {'\\','t','a','r','g','e','t',0};
|
||||
+ static const WCHAR parentW[] = {'\\','.','.','\\',0};
|
||||
+ static const WCHAR fooW[] = {'f','o','o',0};
|
||||
+ static WCHAR volW[] = {'c',':','\\',0};
|
||||
+ static const WCHAR dotW[] = {'.',0};
|
||||
+ REPARSE_DATA_BUFFER *buffer = NULL;
|
||||
+ DWORD dwret, dwLen, dwFlags;
|
||||
UNICODE_STRING nameW;
|
||||
- unsigned char reparse_data[1];
|
||||
+ WCHAR *long_path;
|
||||
+ INT buffer_len;
|
||||
+ HANDLE handle;
|
||||
+ BOOL bret;
|
||||
+
|
||||
+ /* Create a temporary folder for the junction point tests */
|
||||
+ GetTempFileNameW(dotW, fooW, 0, path);
|
||||
+ DeleteFileW(path);
|
||||
+ if (!CreateDirectoryW(path, NULL))
|
||||
+ {
|
||||
+ win_skip("Unable to create a temporary junction point directory.\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* Check that the volume this folder is located on supports junction points */
|
||||
+ pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
|
||||
+ volW[0] = nameW.Buffer[4];
|
||||
+ pRtlFreeUnicodeString( &nameW );
|
||||
+ if (!GetVolumeNameForVolumeMountPointW(volW, volnameW, MAX_PATH))
|
||||
+ {
|
||||
+ win_skip("Failed to obtain volume name for current volume.\n");
|
||||
+ return;
|
||||
+ }
|
||||
+ GetVolumeInformationW(volnameW, 0, 0, 0, &dwLen, &dwFlags, 0, 0);
|
||||
+ if (!(dwFlags & FILE_SUPPORTS_REPARSE_POINTS))
|
||||
+ {
|
||||
+ skip("File system does not support reparse points.\n");
|
||||
+ RemoveDirectoryW(path);
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
- pRtlInitUnicodeString( &nameW, L"\\??\\C:\\" );
|
||||
- InitializeObjectAttributes( &attr, &nameW, 0, NULL, NULL );
|
||||
+ /* Create the folder to be replaced by a junction point */
|
||||
+ lstrcpyW(reparse_path, path);
|
||||
+ lstrcatW(reparse_path, reparseW);
|
||||
+ bret = CreateDirectoryW(reparse_path, NULL);
|
||||
+ ok(bret, "Failed to create junction point directory.\n");
|
||||
|
||||
- status = pNtOpenFile( &handle, READ_CONTROL, &attr, &io, 0, 0 );
|
||||
- ok( !status, "open %s failed %#lx\n", wine_dbgstr_w(nameW.Buffer), status );
|
||||
+ /* Create a destination folder for the junction point to target */
|
||||
+ lstrcpyW(target_path, path);
|
||||
+ for (int i=0; i<1; i++)
|
||||
+ {
|
||||
+ lstrcatW(target_path, parentW);
|
||||
+ lstrcatW(target_path, path);
|
||||
+ }
|
||||
+ lstrcatW(target_path, targetW);
|
||||
+ bret = CreateDirectoryW(target_path, NULL);
|
||||
+ ok(bret, "Failed to create junction point target directory.\n");
|
||||
+ pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
|
||||
|
||||
- status = pNtFsControlFile( handle, NULL, NULL, NULL, &io, FSCTL_GET_REPARSE_POINT, NULL, 0, NULL, 0 );
|
||||
- ok( status == STATUS_INVALID_USER_BUFFER, "expected %#lx, got %#lx\n", STATUS_INVALID_USER_BUFFER, status );
|
||||
+ /* construct a too long pathname (resulting reparse buffer over 16 kiB limit) */
|
||||
+ long_path = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 32767);
|
||||
+ lstrcpyW(long_path, nameW.Buffer);
|
||||
+ for (int i=0; i<250; i++)
|
||||
+ {
|
||||
+ lstrcatW(long_path, parentW);
|
||||
+ lstrcatW(long_path, path);
|
||||
+ }
|
||||
+ lstrcatW(long_path, targetW);
|
||||
|
||||
- status = pNtFsControlFile( handle, NULL, NULL, NULL, &io, FSCTL_GET_REPARSE_POINT, NULL, 0, reparse_data, 0 );
|
||||
- ok( status == STATUS_INVALID_USER_BUFFER, "expected %#lx, got %#lx\n", STATUS_INVALID_USER_BUFFER, status );
|
||||
+ /* Create the junction point */
|
||||
+ handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
|
||||
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
|
||||
+ if (handle == INVALID_HANDLE_VALUE)
|
||||
+ {
|
||||
+ win_skip("Failed to open junction point directory handle (0x%lx).\n", GetLastError());
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ buffer_len = build_reparse_buffer(long_path, &buffer);
|
||||
+ bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
|
||||
+ ok(!bret && GetLastError()==ERROR_INVALID_REPARSE_DATA, "Unexpected error (0x%lx)\n", GetLastError());
|
||||
+ HeapFree(GetProcessHeap(), 0, buffer);
|
||||
+ CloseHandle(handle);
|
||||
|
||||
- /* a volume cannot be a reparse point by definition */
|
||||
- status = pNtFsControlFile( handle, NULL, NULL, NULL, &io, FSCTL_GET_REPARSE_POINT, NULL, 0, reparse_data, 1 );
|
||||
- ok( status == STATUS_NOT_A_REPARSE_POINT, "expected %#lx, got %#lx\n", STATUS_NOT_A_REPARSE_POINT, status );
|
||||
+ /* construct a long pathname to demonstrate correct behavior with very large reparse points */
|
||||
+ pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
|
||||
+ lstrcpyW(long_path, nameW.Buffer);
|
||||
+ for (int i=0; i<200; i++)
|
||||
+ {
|
||||
+ lstrcatW(long_path, parentW);
|
||||
+ lstrcatW(long_path, path);
|
||||
+ }
|
||||
+ lstrcatW(long_path, targetW);
|
||||
|
||||
- CloseHandle( handle );
|
||||
+ /* use a sane (not obscenely long) target for the rest of testing */
|
||||
+ pRtlFreeUnicodeString(&nameW);
|
||||
+ pRtlDosPathNameToNtPathName_U(target_path, &nameW, NULL, NULL);
|
||||
+
|
||||
+ /* Create the junction point */
|
||||
+ handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
|
||||
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
|
||||
+ if (handle == INVALID_HANDLE_VALUE)
|
||||
+ {
|
||||
+ win_skip("Failed to open junction point directory handle (0x%lx).\n", GetLastError());
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ buffer_len = build_reparse_buffer(long_path, &buffer);
|
||||
+ bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
|
||||
+ ok(bret, "Failed to create junction point! (0x%lx)\n", GetLastError());
|
||||
+ CloseHandle(handle);
|
||||
+
|
||||
+cleanup:
|
||||
+ /* Cleanup */
|
||||
+ pRtlFreeUnicodeString(&nameW);
|
||||
+ HeapFree(GetProcessHeap(), 0, long_path);
|
||||
+ HeapFree(GetProcessHeap(), 0, buffer);
|
||||
+ bret = RemoveDirectoryW(reparse_path);
|
||||
+ todo_wine ok(bret, "Failed to remove temporary reparse point directory!\n");
|
||||
+ bret = RemoveDirectoryW(target_path);
|
||||
+ ok(bret, "Failed to remove temporary target directory!\n");
|
||||
+ RemoveDirectoryW(path);
|
||||
}
|
||||
|
||||
static void test_set_io_completion_ex(void)
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index 8d2809ca193..672a1d1fa27 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
|
@@ -5,55 +5,9 @@ Subject: [PATCH] ntdll: Add support for reading reparse points.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/ntdll/tests/file.c | 21 +++-
|
||||
dlls/ntdll/unix/file.c | 221 ++++++++++++++++++++++++++++++++++++++--
|
||||
2 files changed, 231 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index 148b6058cee..441bb69adcb 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -5896,14 +5896,14 @@ static void test_reparse_points(void)
|
||||
static const WCHAR reparseW[] = {'\\','r','e','p','a','r','s','e',0};
|
||||
static const WCHAR targetW[] = {'\\','t','a','r','g','e','t',0};
|
||||
static const WCHAR parentW[] = {'\\','.','.','\\',0};
|
||||
+ INT buffer_len, string_len, path_len, total_len;
|
||||
static const WCHAR fooW[] = {'f','o','o',0};
|
||||
static WCHAR volW[] = {'c',':','\\',0};
|
||||
static const WCHAR dotW[] = {'.',0};
|
||||
REPARSE_DATA_BUFFER *buffer = NULL;
|
||||
DWORD dwret, dwLen, dwFlags;
|
||||
+ WCHAR *dest, *long_path;
|
||||
UNICODE_STRING nameW;
|
||||
- WCHAR *long_path;
|
||||
- INT buffer_len;
|
||||
HANDLE handle;
|
||||
BOOL bret;
|
||||
|
||||
@@ -6000,6 +6000,23 @@ static void test_reparse_points(void)
|
||||
buffer_len = build_reparse_buffer(long_path, &buffer);
|
||||
bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
|
||||
ok(bret, "Failed to create junction point! (0x%lx)\n", GetLastError());
|
||||
+
|
||||
+ /* Read back the junction point */
|
||||
+ HeapFree(GetProcessHeap(), 0, buffer);
|
||||
+ buffer_len = sizeof(*buffer) + 2*32767;
|
||||
+ buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer_len);
|
||||
+ bret = DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0, (LPVOID)buffer, buffer_len, &dwret, 0);
|
||||
+ ok(bret, "Failed to read junction point! (last error=0x%lx)\n", GetLastError());
|
||||
+ string_len = buffer->MountPointReparseBuffer.SubstituteNameLength;
|
||||
+ dest = &buffer->MountPointReparseBuffer.PathBuffer[buffer->MountPointReparseBuffer.SubstituteNameOffset/sizeof(WCHAR)];
|
||||
+ ok((memcmp(dest, long_path, string_len) == 0), "Junction point destination does not match ('%s' != '%s')!\n",
|
||||
+ wine_dbgstr_w(dest), wine_dbgstr_w(long_path));
|
||||
+ path_len = buffer->MountPointReparseBuffer.PrintNameOffset/sizeof(WCHAR);
|
||||
+ path_len += buffer->MountPointReparseBuffer.PrintNameLength/sizeof(WCHAR);
|
||||
+ total_len = FIELD_OFFSET(typeof(*buffer), MountPointReparseBuffer.PathBuffer[path_len+1])
|
||||
+ - FIELD_OFFSET(typeof(*buffer), GenericReparseBuffer);
|
||||
+ ok(buffer->ReparseDataLength == total_len, "ReparseDataLength has unexpected value (%d != %d)\n",
|
||||
+ buffer->ReparseDataLength, total_len);
|
||||
CloseHandle(handle);
|
||||
|
||||
cleanup:
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index 0d58abbfa84..3e160fb1e5c 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
|
@@ -5,71 +5,9 @@ Subject: [PATCH] ntdll: Add support for deleting reparse points.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/ntdll/tests/file.c | 23 +++++++++-
|
||||
dlls/ntdll/unix/file.c | 99 +++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 121 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index b9ec79e37e0..f90509d62a1 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -5388,12 +5388,15 @@ static void test_reparse_points(void)
|
||||
static const WCHAR targetW[] = {'\\','t','a','r','g','e','t',0};
|
||||
static const WCHAR parentW[] = {'\\','.','.','\\',0};
|
||||
INT buffer_len, string_len, path_len, total_len;
|
||||
+ FILE_BASIC_INFORMATION old_attrib, new_attrib;
|
||||
static const WCHAR fooW[] = {'f','o','o',0};
|
||||
static WCHAR volW[] = {'c',':','\\',0};
|
||||
+ REPARSE_GUID_DATA_BUFFER guid_buffer;
|
||||
static const WCHAR dotW[] = {'.',0};
|
||||
REPARSE_DATA_BUFFER *buffer = NULL;
|
||||
DWORD dwret, dwLen, dwFlags;
|
||||
WCHAR *dest, *long_path;
|
||||
+ IO_STATUS_BLOCK iosb;
|
||||
UNICODE_STRING nameW;
|
||||
HANDLE handle;
|
||||
BOOL bret;
|
||||
@@ -5488,6 +5491,8 @@ static void test_reparse_points(void)
|
||||
win_skip("Failed to open junction point directory handle (0x%lx).\n", GetLastError());
|
||||
goto cleanup;
|
||||
}
|
||||
+ dwret = NtQueryInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation);
|
||||
+ ok(dwret == STATUS_SUCCESS, "Failed to get junction point folder's attributes (0x%lx).\n", dwret);
|
||||
buffer_len = build_reparse_buffer(long_path, &buffer);
|
||||
bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
|
||||
ok(bret, "Failed to create junction point! (0x%lx)\n", GetLastError());
|
||||
@@ -5508,6 +5513,22 @@ static void test_reparse_points(void)
|
||||
- FIELD_OFFSET(typeof(*buffer), GenericReparseBuffer);
|
||||
ok(buffer->ReparseDataLength == total_len, "ReparseDataLength has unexpected value (%d != %d)\n",
|
||||
buffer->ReparseDataLength, total_len);
|
||||
+
|
||||
+ /* Delete the junction point */
|
||||
+ memset(&old_attrib, 0x00, sizeof(old_attrib));
|
||||
+ old_attrib.LastAccessTime.QuadPart = 0x200deadcafebeef;
|
||||
+ dwret = NtSetInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation);
|
||||
+ ok(dwret == STATUS_SUCCESS, "Failed to set junction point folder's attributes (0x%lx).\n", dwret);
|
||||
+ memset(&guid_buffer, 0x00, sizeof(guid_buffer));
|
||||
+ guid_buffer.ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
|
||||
+ bret = DeviceIoControl(handle, FSCTL_DELETE_REPARSE_POINT, (LPVOID)&guid_buffer,
|
||||
+ REPARSE_GUID_DATA_BUFFER_HEADER_SIZE, NULL, 0, &dwret, 0);
|
||||
+ ok(bret, "Failed to delete junction point! (0x%lx)\n", GetLastError());
|
||||
+ memset(&new_attrib, 0x00, sizeof(new_attrib));
|
||||
+ dwret = NtQueryInformationFile(handle, &iosb, &new_attrib, sizeof(new_attrib), FileBasicInformation);
|
||||
+ ok(dwret == STATUS_SUCCESS, "Failed to get junction point folder's attributes (0x%lx).\n", dwret);
|
||||
+ ok(old_attrib.LastAccessTime.QuadPart == new_attrib.LastAccessTime.QuadPart,
|
||||
+ "Junction point folder's access time does not match.\n");
|
||||
CloseHandle(handle);
|
||||
|
||||
cleanup:
|
||||
@@ -5516,7 +5537,7 @@ cleanup:
|
||||
HeapFree(GetProcessHeap(), 0, long_path);
|
||||
HeapFree(GetProcessHeap(), 0, buffer);
|
||||
bret = RemoveDirectoryW(reparse_path);
|
||||
- todo_wine ok(bret, "Failed to remove temporary reparse point directory!\n");
|
||||
+ ok(bret, "Failed to remove temporary reparse point directory!\n");
|
||||
bret = RemoveDirectoryW(target_path);
|
||||
ok(bret, "Failed to remove temporary target directory!\n");
|
||||
RemoveDirectoryW(path);
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index 92ce83b685e..ba77aab61b7 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
|
@@ -6,26 +6,9 @@ Subject: ntdll: Add support for testing for reparse points with
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/ntdll/tests/file.c | 5 +++++
|
||||
dlls/ntdll/unix/file.c | 23 +++++++++++++++++++----
|
||||
2 files changed, 24 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index a127a2f4f88..ffc4ca44e32 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -5469,6 +5469,11 @@ static void test_reparse_points(void)
|
||||
bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
|
||||
ok(bret, "Failed to create junction point! (0x%lx)\n", GetLastError());
|
||||
|
||||
+ /* Check the file attributes of the junction point */
|
||||
+ dwret = GetFileAttributesW(reparse_path);
|
||||
+ ok(dwret != (DWORD)~0, "Reparse point doesn't exist (attributes: 0x%lx)!\n", dwret);
|
||||
+ ok(dwret & FILE_ATTRIBUTE_REPARSE_POINT, "File is not a reparse point! (attributes: 0x%lx)\n", dwret);
|
||||
+
|
||||
/* Read back the junction point */
|
||||
HeapFree(GetProcessHeap(), 0, buffer);
|
||||
buffer_len = sizeof(*buffer) + 2*32767;
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index 4c221f53bfd..948074b35ec 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
|
@@ -7,7 +7,6 @@ Subject: kernelbase: Add support for deleting reparse points with
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/kernelbase/file.c | 2 +-
|
||||
dlls/ntdll/tests/file.c | 28 +++++++++++++++++++++++++++-
|
||||
2 files changed, 28 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c
|
||||
@@ -23,63 +22,6 @@ index bfb291fa925..6214f549406 100644
|
||||
RtlFreeUnicodeString( &nt_name );
|
||||
|
||||
if (!status)
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index ffc4ca44e32..f3aad01ee93 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -5363,11 +5363,11 @@ static void test_reparse_points(void)
|
||||
FILE_BASIC_INFORMATION old_attrib, new_attrib;
|
||||
static const WCHAR fooW[] = {'f','o','o',0};
|
||||
static WCHAR volW[] = {'c',':','\\',0};
|
||||
+ WCHAR *dest, *long_path, *abs_target;
|
||||
REPARSE_GUID_DATA_BUFFER guid_buffer;
|
||||
static const WCHAR dotW[] = {'.',0};
|
||||
REPARSE_DATA_BUFFER *buffer = NULL;
|
||||
DWORD dwret, dwLen, dwFlags;
|
||||
- WCHAR *dest, *long_path;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
UNICODE_STRING nameW;
|
||||
HANDLE handle;
|
||||
@@ -5454,6 +5454,7 @@ static void test_reparse_points(void)
|
||||
/* use a sane (not obscenely long) target for the rest of testing */
|
||||
pRtlFreeUnicodeString(&nameW);
|
||||
pRtlDosPathNameToNtPathName_U(target_path, &nameW, NULL, NULL);
|
||||
+ abs_target = nameW.Buffer;
|
||||
|
||||
/* Create the junction point */
|
||||
handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
|
||||
@@ -5508,6 +5509,31 @@ static void test_reparse_points(void)
|
||||
"Junction point folder's access time does not match.\n");
|
||||
CloseHandle(handle);
|
||||
|
||||
+ /* Check deleting a junction point as if it were a directory */
|
||||
+ HeapFree(GetProcessHeap(), 0, buffer);
|
||||
+ handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
|
||||
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
|
||||
+ buffer_len = build_reparse_buffer(abs_target, &buffer);
|
||||
+ bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
|
||||
+ ok(bret, "Failed to create junction point! (0x%lx)\n", GetLastError());
|
||||
+ CloseHandle(handle);
|
||||
+ bret = RemoveDirectoryW(reparse_path);
|
||||
+ ok(bret, "Failed to delete junction point as directory!\n");
|
||||
+ dwret = GetFileAttributesW(reparse_path);
|
||||
+ ok(dwret == (DWORD)~0, "Junction point still exists (attributes: 0x%lx)!\n", dwret);
|
||||
+
|
||||
+ /* Check deleting a junction point as if it were a file */
|
||||
+ HeapFree(GetProcessHeap(), 0, buffer);
|
||||
+ bret = CreateDirectoryW(reparse_path, NULL);
|
||||
+ ok(bret, "Failed to create junction point target directory.\n");
|
||||
+ handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
|
||||
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
|
||||
+ buffer_len = build_reparse_buffer(abs_target, &buffer);
|
||||
+ bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
|
||||
+ ok(bret, "Failed to create junction point! (0x%lx)\n", GetLastError());
|
||||
+ CloseHandle(handle);
|
||||
+ /* TODO: use DeleteFile on reparse point */
|
||||
+
|
||||
cleanup:
|
||||
/* Cleanup */
|
||||
pRtlFreeUnicodeString(&nameW);
|
||||
--
|
||||
2.17.1
|
||||
|
||||
|
@@ -7,7 +7,6 @@ Subject: [PATCH] kernelbase: Add support for deleting reparse points with
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/kernelbase/file.c | 3 ++-
|
||||
dlls/ntdll/tests/file.c | 11 +++++++++--
|
||||
2 files changed, 11 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c
|
||||
@@ -24,35 +23,6 @@ index 36b43d345d6..b7d16410d75 100644
|
||||
if (status == STATUS_SUCCESS) status = NtClose(hFile);
|
||||
|
||||
RtlFreeUnicodeString( &nameW );
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index d4833d84906..598fdc77830 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -6007,7 +6007,7 @@ static void test_reparse_points(void)
|
||||
REPARSE_GUID_DATA_BUFFER guid_buffer;
|
||||
static const WCHAR dotW[] = {'.',0};
|
||||
REPARSE_DATA_BUFFER *buffer = NULL;
|
||||
- DWORD dwret, dwLen, dwFlags;
|
||||
+ DWORD dwret, dwLen, dwFlags, err;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
UNICODE_STRING nameW;
|
||||
HANDLE handle;
|
||||
@@ -6172,7 +6172,14 @@ static void test_reparse_points(void)
|
||||
bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
|
||||
ok(bret, "Failed to create junction point! (0x%lx)\n", GetLastError());
|
||||
CloseHandle(handle);
|
||||
- /* TODO: use DeleteFile on reparse point */
|
||||
+ bret = DeleteFileW(reparse_path);
|
||||
+ ok(!bret, "Succeeded in deleting junction point as file!\n");
|
||||
+ err = GetLastError();
|
||||
+ ok(err == ERROR_ACCESS_DENIED, "Expected last error 0x%x for DeleteFile on junction point (actually 0x%lx)!\n",
|
||||
+ ERROR_ACCESS_DENIED, err);
|
||||
+ dwret = GetFileAttributesW(reparse_path);
|
||||
+ ok(dwret != (DWORD)~0, "Junction point doesn't exist (attributes: 0x%lx)!\n", dwret);
|
||||
+ ok(dwret & FILE_ATTRIBUTE_REPARSE_POINT, "File is not a junction point! (attributes: 0x%lx)\n", dwret);
|
||||
|
||||
cleanup:
|
||||
/* Cleanup */
|
||||
--
|
||||
2.47.2
|
||||
|
||||
|
@@ -1,323 +0,0 @@
|
||||
From caaa38a56b7bb5e81bb71f5a6c3489755ebaee98 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
|
||||
Date: Sat, 6 Feb 2021 12:52:51 -0700
|
||||
Subject: [PATCH] ntdll: Add tests for NT symlink reparse points.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/ntdll/tests/file.c | 239 +++++++++++++++++++++++++++++++++++++---
|
||||
1 file changed, 225 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index 4e3f0f04a3e..48abcd338bb 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -5327,26 +5327,52 @@ static void test_mailslot_name(void)
|
||||
CloseHandle( device );
|
||||
}
|
||||
|
||||
-static INT build_reparse_buffer(const WCHAR *filename, REPARSE_DATA_BUFFER **pbuffer)
|
||||
+static INT build_reparse_buffer(const WCHAR *filename, ULONG tag, ULONG flags,
|
||||
+ REPARSE_DATA_BUFFER **pbuffer)
|
||||
{
|
||||
static INT header_size = offsetof(REPARSE_DATA_BUFFER, GenericReparseBuffer);
|
||||
INT buffer_size, struct_size, data_size, string_len, prefix_len;
|
||||
WCHAR *subst_dest, *print_dest;
|
||||
REPARSE_DATA_BUFFER *buffer;
|
||||
|
||||
- struct_size = offsetof(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer[0]);
|
||||
- prefix_len = strlen("\\??\\");
|
||||
+ switch(tag)
|
||||
+ {
|
||||
+ case IO_REPARSE_TAG_MOUNT_POINT:
|
||||
+ struct_size = offsetof(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer[0]);
|
||||
+ break;
|
||||
+ case IO_REPARSE_TAG_SYMLINK:
|
||||
+ struct_size = offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer[0]);
|
||||
+ break;
|
||||
+ default:
|
||||
+ return 0;
|
||||
+ }
|
||||
+ prefix_len = (flags == SYMLINK_FLAG_RELATIVE) ? 0 : strlen("\\??\\");
|
||||
string_len = lstrlenW(&filename[prefix_len]);
|
||||
data_size = (prefix_len + 2 * string_len + 2) * sizeof(WCHAR);
|
||||
buffer_size = struct_size + data_size;
|
||||
buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer_size);
|
||||
- buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
|
||||
+ buffer->ReparseTag = tag;
|
||||
buffer->ReparseDataLength = struct_size - header_size + data_size;
|
||||
- buffer->MountPointReparseBuffer.SubstituteNameLength = (prefix_len + string_len) * sizeof(WCHAR);
|
||||
- buffer->MountPointReparseBuffer.PrintNameOffset = (prefix_len + string_len + 1) * sizeof(WCHAR);
|
||||
- buffer->MountPointReparseBuffer.PrintNameLength = string_len * sizeof(WCHAR);
|
||||
- subst_dest = &buffer->MountPointReparseBuffer.PathBuffer[0];
|
||||
- print_dest = &buffer->MountPointReparseBuffer.PathBuffer[prefix_len + string_len + 1];
|
||||
+ switch(tag)
|
||||
+ {
|
||||
+ case IO_REPARSE_TAG_MOUNT_POINT:
|
||||
+ buffer->MountPointReparseBuffer.SubstituteNameLength = (prefix_len + string_len) * sizeof(WCHAR);
|
||||
+ buffer->MountPointReparseBuffer.PrintNameOffset = (prefix_len + string_len + 1) * sizeof(WCHAR);
|
||||
+ buffer->MountPointReparseBuffer.PrintNameLength = string_len * sizeof(WCHAR);
|
||||
+ subst_dest = &buffer->MountPointReparseBuffer.PathBuffer[0];
|
||||
+ print_dest = &buffer->MountPointReparseBuffer.PathBuffer[prefix_len + string_len + 1];
|
||||
+ break;
|
||||
+ case IO_REPARSE_TAG_SYMLINK:
|
||||
+ buffer->SymbolicLinkReparseBuffer.SubstituteNameLength = (prefix_len + string_len) * sizeof(WCHAR);
|
||||
+ buffer->SymbolicLinkReparseBuffer.PrintNameOffset = (prefix_len + string_len + 1) * sizeof(WCHAR);
|
||||
+ buffer->SymbolicLinkReparseBuffer.PrintNameLength = string_len * sizeof(WCHAR);
|
||||
+ buffer->SymbolicLinkReparseBuffer.Flags = flags;
|
||||
+ subst_dest = &buffer->SymbolicLinkReparseBuffer.PathBuffer[0];
|
||||
+ print_dest = &buffer->SymbolicLinkReparseBuffer.PathBuffer[prefix_len + string_len + 1];
|
||||
+ break;
|
||||
+ default:
|
||||
+ return 0;
|
||||
+ }
|
||||
lstrcpyW(subst_dest, filename);
|
||||
lstrcpyW(print_dest, &filename[prefix_len]);
|
||||
*pbuffer = buffer;
|
||||
@@ -5363,14 +5389,18 @@ static void test_reparse_points(void)
|
||||
FILE_BASIC_INFORMATION old_attrib, new_attrib;
|
||||
static const WCHAR fooW[] = {'f','o','o',0};
|
||||
static WCHAR volW[] = {'c',':','\\',0};
|
||||
+ const WCHAR *rel_target = &targetW[1];
|
||||
WCHAR *dest, *long_path, *abs_target;
|
||||
REPARSE_GUID_DATA_BUFFER guid_buffer;
|
||||
static const WCHAR dotW[] = {'.',0};
|
||||
REPARSE_DATA_BUFFER *buffer = NULL;
|
||||
DWORD dwret, dwLen, dwFlags, err;
|
||||
+ WCHAR buf[] = {0,0,0,0};
|
||||
+ HANDLE handle, token;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
UNICODE_STRING nameW;
|
||||
- HANDLE handle;
|
||||
+ TOKEN_PRIVILEGES tp;
|
||||
+ LUID luid;
|
||||
BOOL bret;
|
||||
|
||||
/* Create a temporary folder for the junction point tests */
|
||||
@@ -5435,7 +5465,7 @@ static void test_reparse_points(void)
|
||||
win_skip("Failed to open junction point directory handle (0x%lx).\n", GetLastError());
|
||||
goto cleanup;
|
||||
}
|
||||
- buffer_len = build_reparse_buffer(long_path, &buffer);
|
||||
+ buffer_len = build_reparse_buffer(long_path, IO_REPARSE_TAG_MOUNT_POINT, 0, &buffer);
|
||||
bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
|
||||
ok(!bret && GetLastError()==ERROR_INVALID_REPARSE_DATA, "Unexpected error (0x%lx)\n", GetLastError());
|
||||
HeapFree(GetProcessHeap(), 0, buffer);
|
||||
@@ -5466,7 +5496,7 @@ static void test_reparse_points(void)
|
||||
}
|
||||
dwret = NtQueryInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation);
|
||||
ok(dwret == STATUS_SUCCESS, "Failed to get junction point folder's attributes (0x%lx).\n", dwret);
|
||||
- buffer_len = build_reparse_buffer(long_path, &buffer);
|
||||
+ buffer_len = build_reparse_buffer(long_path, IO_REPARSE_TAG_MOUNT_POINT, 0, &buffer);
|
||||
bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
|
||||
ok(bret, "Failed to create junction point! (0x%lx)\n", GetLastError());
|
||||
|
||||
@@ -5513,7 +5543,7 @@ static void test_reparse_points(void)
|
||||
HeapFree(GetProcessHeap(), 0, buffer);
|
||||
handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
|
||||
- buffer_len = build_reparse_buffer(abs_target, &buffer);
|
||||
+ buffer_len = build_reparse_buffer(abs_target, IO_REPARSE_TAG_MOUNT_POINT, 0, &buffer);
|
||||
bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
|
||||
ok(bret, "Failed to create junction point! (0x%lx)\n", GetLastError());
|
||||
CloseHandle(handle);
|
||||
@@ -5528,7 +5558,7 @@ static void test_reparse_points(void)
|
||||
ok(bret, "Failed to create junction point target directory.\n");
|
||||
handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
|
||||
- buffer_len = build_reparse_buffer(abs_target, &buffer);
|
||||
+ buffer_len = build_reparse_buffer(abs_target, IO_REPARSE_TAG_MOUNT_POINT, 0, &buffer);
|
||||
bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
|
||||
ok(bret, "Failed to create junction point! (0x%lx)\n", GetLastError());
|
||||
CloseHandle(handle);
|
||||
@@ -5541,6 +5571,187 @@ static void test_reparse_points(void)
|
||||
ok(dwret != (DWORD)~0, "Junction point doesn't exist (attributes: 0x%lx)!\n", dwret);
|
||||
ok(dwret & FILE_ATTRIBUTE_REPARSE_POINT, "File is not a junction point! (attributes: 0x%lx)\n", dwret);
|
||||
|
||||
+ /* Test deleting a junction point's target */
|
||||
+ dwret = GetFileAttributesW(reparse_path);
|
||||
+ ok(dwret == 0x410 || broken(dwret == 0x430) /* win2k */ || broken(dwret == 0xc10) /* vista */,
|
||||
+ "Unexpected junction point attributes (0x%lx != 0x410)!\n", dwret);
|
||||
+ bret = RemoveDirectoryW(target_path);
|
||||
+ ok(bret, "Failed to delete junction point target!\n");
|
||||
+ bret = CreateDirectoryW(target_path, NULL);
|
||||
+ ok(bret, "Failed to create junction point target directory.\n");
|
||||
+
|
||||
+ /* Establish permissions for symlink creation */
|
||||
+ bret = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token);
|
||||
+ ok(bret, "OpenProcessToken failed: %lx\n", GetLastError());
|
||||
+ bret = LookupPrivilegeValueA(NULL, "SeCreateSymbolicLinkPrivilege", &luid);
|
||||
+ todo_wine ok(bret || broken(!bret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE) /* winxp */,
|
||||
+ "LookupPrivilegeValue failed: %lx\n", GetLastError());
|
||||
+ if (bret)
|
||||
+ {
|
||||
+ tp.PrivilegeCount = 1;
|
||||
+ tp.Privileges[0].Luid = luid;
|
||||
+ tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
+ bret = AdjustTokenPrivileges(token, FALSE, &tp, 0, NULL, NULL);
|
||||
+ ok(bret, "AdjustTokenPrivileges failed: %lx\n", GetLastError());
|
||||
+ if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
|
||||
+ {
|
||||
+ win_skip("Insufficient permissions to perform symlink tests.\n");
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Delete the junction point directory and create a blank slate for symlink tests */
|
||||
+ bret = RemoveDirectoryW(reparse_path);
|
||||
+ ok(bret, "Failed to delete junction point!\n");
|
||||
+ bret = RemoveDirectoryW(target_path);
|
||||
+ ok(bret, "Failed to delete junction point target!\n");
|
||||
+ handle = CreateFileW(target_path, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_NEW, 0, 0);
|
||||
+ ok(handle != INVALID_HANDLE_VALUE, "Failed to create symlink target file.\n");
|
||||
+ bret = WriteFile(handle, fooW, sizeof(fooW), &dwLen, NULL);
|
||||
+ ok(bret, "Failed to write data to the symlink target file.\n");
|
||||
+ ok(GetFileSize(handle, NULL) == sizeof(fooW), "target size is incorrect (%ld vs %d)\n",
|
||||
+ GetFileSize(handle, NULL), (int)sizeof(fooW));
|
||||
+ CloseHandle(handle);
|
||||
+
|
||||
+ /* Create the file symlink */
|
||||
+ HeapFree(GetProcessHeap(), 0, buffer);
|
||||
+ handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_NEW,
|
||||
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
|
||||
+ ok(handle != INVALID_HANDLE_VALUE, "Failed to create symlink file.\n");
|
||||
+ dwret = NtQueryInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation);
|
||||
+ ok(dwret == STATUS_SUCCESS, "Failed to get symlink file's attributes (0x%lx).\n", dwret);
|
||||
+ buffer_len = build_reparse_buffer(nameW.Buffer, IO_REPARSE_TAG_SYMLINK, 0, &buffer);
|
||||
+ bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
|
||||
+ ok(bret, "Failed to create symlink! (0x%lx)\n", GetLastError());
|
||||
+ CloseHandle(handle);
|
||||
+
|
||||
+ /* Check the size/data of the symlink target when opened with FILE_FLAG_OPEN_REPARSE_POINT */
|
||||
+ handle = CreateFileW(target_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
|
||||
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
|
||||
+ if (handle == INVALID_HANDLE_VALUE)
|
||||
+ {
|
||||
+ win_skip("Failed to open symlink file handle (0x%lx).\n", GetLastError());
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ ok(GetFileSize(handle, NULL) == sizeof(fooW), "symlink target size does not match (%ld != %d)\n",
|
||||
+ GetFileSize(handle, NULL), (int)sizeof(fooW));
|
||||
+ bret = ReadFile(handle, &buf, sizeof(buf), &dwLen, NULL);
|
||||
+ ok(bret, "Failed to read data from the symlink target.\n");
|
||||
+ ok(dwLen == sizeof(fooW), "Length of symlink target data does not match (%ld != %d).\n",
|
||||
+ dwLen, (int)sizeof(fooW));
|
||||
+ ok(!memcmp(fooW, &buf, sizeof(fooW)), "Symlink target data does not match (%s != %s).\n",
|
||||
+ wine_dbgstr_wn(buf, dwLen), wine_dbgstr_w(fooW));
|
||||
+ CloseHandle(handle);
|
||||
+
|
||||
+ /* Check deleting a file symlink as if it were a directory */
|
||||
+ bret = RemoveDirectoryW(reparse_path);
|
||||
+ ok(!bret, "Succeeded in deleting file symlink as a directory!\n");
|
||||
+ err = GetLastError();
|
||||
+ ok(err == ERROR_DIRECTORY,
|
||||
+ "Expected last error 0x%x for RemoveDirectory on file symlink (actually 0x%lx)!\n",
|
||||
+ ERROR_DIRECTORY, err);
|
||||
+ dwret = GetFileAttributesW(reparse_path);
|
||||
+ ok(dwret != (DWORD)~0, "Symlink doesn't exist (attributes: 0x%lx)!\n", dwret);
|
||||
+ ok(dwret & FILE_ATTRIBUTE_REPARSE_POINT, "File is not a symlink! (attributes: 0x%lx)\n", dwret);
|
||||
+
|
||||
+ /* Delete the symlink as a file */
|
||||
+ bret = DeleteFileW(reparse_path);
|
||||
+ ok(bret, "Failed to delete symlink as a file!\n");
|
||||
+
|
||||
+ /* Create a blank slate for directory symlink tests */
|
||||
+ bret = CreateDirectoryW(reparse_path, NULL);
|
||||
+ ok(bret, "Failed to create junction point directory.\n");
|
||||
+ dwret = GetFileAttributesW(reparse_path);
|
||||
+ ok(dwret != (DWORD)~0, "Path doesn't exist (attributes: 0x%lx)!\n", dwret);
|
||||
+ ok(!(dwret & FILE_ATTRIBUTE_REPARSE_POINT), "File is already a reparse point! (attributes: %lx)\n", dwret);
|
||||
+ bret = DeleteFileW(target_path);
|
||||
+ ok(bret, "Failed to delete symlink target!\n");
|
||||
+ bret = CreateDirectoryW(target_path, NULL);
|
||||
+ ok(bret, "Failed to create symlink target directory.\n");
|
||||
+
|
||||
+ /* Create the directory symlink */
|
||||
+ HeapFree(GetProcessHeap(), 0, buffer);
|
||||
+ handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
|
||||
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
|
||||
+ if (handle == INVALID_HANDLE_VALUE)
|
||||
+ {
|
||||
+ win_skip("Failed to open symlink directory handle (0x%lx).\n", GetLastError());
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ dwret = NtQueryInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation);
|
||||
+ ok(dwret == STATUS_SUCCESS, "Failed to get symlink folder's attributes (0x%lx).\n", dwret);
|
||||
+ buffer_len = build_reparse_buffer(abs_target, IO_REPARSE_TAG_SYMLINK, 0, &buffer);
|
||||
+ bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
|
||||
+ ok(bret, "Failed to create symlink! (0x%lx)\n", GetLastError());
|
||||
+
|
||||
+ /* Check the file attributes of the symlink */
|
||||
+ dwret = GetFileAttributesW(reparse_path);
|
||||
+ ok(dwret != (DWORD)~0, "Symlink doesn't exist (attributes: 0x%lx)!\n", dwret);
|
||||
+ ok(dwret & FILE_ATTRIBUTE_REPARSE_POINT, "File is not a symlink! (attributes: %lx)\n", dwret);
|
||||
+
|
||||
+ /* Read back the symlink */
|
||||
+ HeapFree(GetProcessHeap(), 0, buffer);
|
||||
+ buffer_len = sizeof(*buffer) + MAX_PATH*sizeof(WCHAR);
|
||||
+ buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer_len);
|
||||
+ bret = DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0, (LPVOID)buffer, buffer_len, &dwret, 0);
|
||||
+ string_len = buffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
|
||||
+ dest = &buffer->SymbolicLinkReparseBuffer.PathBuffer[buffer->SymbolicLinkReparseBuffer.SubstituteNameOffset/sizeof(WCHAR)];
|
||||
+ ok(bret, "Failed to read symlink!\n");
|
||||
+ ok((memcmp(dest, nameW.Buffer, string_len) == 0), "Symlink destination does not match ('%s' != '%s')!\n",
|
||||
+ wine_dbgstr_w(dest), wine_dbgstr_w(nameW.Buffer));
|
||||
+ path_len = buffer->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR);
|
||||
+ path_len += buffer->SymbolicLinkReparseBuffer.PrintNameLength/sizeof(WCHAR);
|
||||
+ total_len = FIELD_OFFSET(typeof(*buffer), SymbolicLinkReparseBuffer.PathBuffer[path_len+1])
|
||||
+ - FIELD_OFFSET(typeof(*buffer), GenericReparseBuffer);
|
||||
+ ok(buffer->ReparseDataLength == total_len, "ReparseDataLength has unexpected value (%d != %d)\n",
|
||||
+ buffer->ReparseDataLength, total_len);
|
||||
+
|
||||
+ /* Delete the symlink */
|
||||
+ memset(&old_attrib, 0x00, sizeof(old_attrib));
|
||||
+ old_attrib.LastAccessTime.QuadPart = 0x200deadcafebeef;
|
||||
+ dwret = NtSetInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation);
|
||||
+ ok(dwret == STATUS_SUCCESS, "Failed to set symlink folder's attributes (0x%lx).\n", dwret);
|
||||
+ memset(&guid_buffer, 0x00, sizeof(guid_buffer));
|
||||
+ guid_buffer.ReparseTag = IO_REPARSE_TAG_SYMLINK;
|
||||
+ bret = DeviceIoControl(handle, FSCTL_DELETE_REPARSE_POINT, (LPVOID)&guid_buffer,
|
||||
+ REPARSE_GUID_DATA_BUFFER_HEADER_SIZE, NULL, 0, &dwret, 0);
|
||||
+ ok(bret, "Failed to delete symlink! (0x%lx)\n", GetLastError());
|
||||
+ memset(&new_attrib, 0x00, sizeof(new_attrib));
|
||||
+ dwret = NtQueryInformationFile(handle, &iosb, &new_attrib, sizeof(new_attrib), FileBasicInformation);
|
||||
+ ok(dwret == STATUS_SUCCESS, "Failed to get symlink folder's attributes (0x%lx).\n", dwret);
|
||||
+ ok(old_attrib.LastAccessTime.QuadPart == new_attrib.LastAccessTime.QuadPart,
|
||||
+ "Symlink folder's access time does not match.\n");
|
||||
+ CloseHandle(handle);
|
||||
+
|
||||
+ /* Create a relative directory symlink */
|
||||
+ HeapFree(GetProcessHeap(), 0, buffer);
|
||||
+ handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
|
||||
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
|
||||
+ if (handle == INVALID_HANDLE_VALUE)
|
||||
+ {
|
||||
+ win_skip("Failed to open symlink directory handle (0x%lx).\n", GetLastError());
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ dwret = NtQueryInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation);
|
||||
+ ok(dwret == STATUS_SUCCESS, "Failed to get symlink folder's attributes (0x%lx).\n", dwret);
|
||||
+ buffer_len = build_reparse_buffer(rel_target, IO_REPARSE_TAG_SYMLINK, SYMLINK_FLAG_RELATIVE, &buffer);
|
||||
+ bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
|
||||
+ ok(bret, "Failed to create symlink! (0x%lx)\n", GetLastError());
|
||||
+
|
||||
+ /* Read back the relative symlink */
|
||||
+ HeapFree(GetProcessHeap(), 0, buffer);
|
||||
+ buffer_len = sizeof(*buffer) + MAX_PATH*sizeof(WCHAR);
|
||||
+ buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer_len);
|
||||
+ bret = DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0, (LPVOID)buffer, buffer_len, &dwret, 0);
|
||||
+ ok(bret, "Failed to read relative symlink!\n");
|
||||
+ string_len = buffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
|
||||
+ ok(string_len != lstrlenW(rel_target), "Symlink destination length does not match ('%d' != '%d')!\n",
|
||||
+ string_len, lstrlenW(rel_target));
|
||||
+ dest = &buffer->SymbolicLinkReparseBuffer.PathBuffer[buffer->SymbolicLinkReparseBuffer.SubstituteNameOffset/sizeof(WCHAR)];
|
||||
+ ok((memcmp(dest, rel_target, string_len) == 0), "Symlink destination does not match ('%s' != '%s')!\n",
|
||||
+ wine_dbgstr_w(dest), wine_dbgstr_w(rel_target));
|
||||
+ CloseHandle(handle);
|
||||
+
|
||||
cleanup:
|
||||
/* Cleanup */
|
||||
pRtlFreeUnicodeString(&nameW);
|
||||
--
|
||||
2.37.2
|
||||
|
@@ -1,4 +1,4 @@
|
||||
From fea1d301c573d3410e2f7d66b21609663ee47880 Mon Sep 17 00:00:00 2001
|
||||
From 51373e0350ff1b507d7b47d6e5acd84b8af9d328 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
|
||||
Date: Sat, 6 Feb 2021 12:46:30 -0700
|
||||
Subject: [PATCH] kernelbase: Add support for moving reparse points with
|
||||
@@ -6,17 +6,16 @@ Subject: [PATCH] kernelbase: Add support for moving reparse points with
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/kernelbase/file.c | 2 +-
|
||||
dlls/ntdll/tests/file.c | 12 +++++++++++-
|
||||
dlls/ntdll/unix/file.c | 23 ++++++++++++++++++++++-
|
||||
server/fd.c | 6 ++++--
|
||||
4 files changed, 38 insertions(+), 5 deletions(-)
|
||||
dlls/kernelbase/file.c | 2 +-
|
||||
dlls/ntdll/unix/file.c | 24 ++++++++++++++++++++++--
|
||||
server/fd.c | 6 ++++--
|
||||
3 files changed, 27 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c
|
||||
index 51459402e75..d70e0fc833c 100644
|
||||
index 36045116e43..f1b1326353f 100644
|
||||
--- a/dlls/kernelbase/file.c
|
||||
+++ b/dlls/kernelbase/file.c
|
||||
@@ -2538,7 +2538,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH MoveFileWithProgressW( const WCHAR *source, const
|
||||
@@ -2597,7 +2597,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH MoveFileWithProgressW( const WCHAR *source, const
|
||||
InitializeObjectAttributes( &attr, &nt_name, OBJ_CASE_INSENSITIVE, 0, NULL );
|
||||
status = NtOpenFile( &source_handle, DELETE | SYNCHRONIZE, &attr, &io,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
@@ -25,41 +24,11 @@ index 51459402e75..d70e0fc833c 100644
|
||||
RtlFreeUnicodeString( &nt_name );
|
||||
if (!set_ntstatus( status )) goto error;
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index b592036d2d0..6e2c7906644 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -6025,7 +6025,8 @@ static INT build_reparse_buffer(const WCHAR *filename, ULONG tag, ULONG flags,
|
||||
|
||||
static void test_reparse_points(void)
|
||||
{
|
||||
- WCHAR path[MAX_PATH], reparse_path[MAX_PATH], target_path[MAX_PATH], volnameW[MAX_PATH];
|
||||
+ WCHAR path[MAX_PATH], reparse_path[MAX_PATH], target_path[MAX_PATH], volnameW[MAX_PATH], new_path[MAX_PATH];
|
||||
+ static const WCHAR new_reparseW[] = {'\\','n','e','w','_','r','e','p','a','r','s','e',0};
|
||||
static const WCHAR reparseW[] = {'\\','r','e','p','a','r','s','e',0};
|
||||
static const WCHAR targetW[] = {'\\','t','a','r','g','e','t',0};
|
||||
static const WCHAR parentW[] = {'\\','.','.','\\',0};
|
||||
@@ -6396,6 +6397,15 @@ static void test_reparse_points(void)
|
||||
wine_dbgstr_w(dest), wine_dbgstr_w(rel_target));
|
||||
CloseHandle(handle);
|
||||
|
||||
+ /* Check moving a reparse point to another location */
|
||||
+ lstrcpyW(new_path, path);
|
||||
+ lstrcatW(new_path, parentW);
|
||||
+ lstrcatW(new_path, new_reparseW);
|
||||
+ bret = MoveFileW(reparse_path, new_path);
|
||||
+ ok(bret, "Failed to move and rename reparse point.\n");
|
||||
+ bret = MoveFileW(new_path, reparse_path);
|
||||
+ ok(bret, "Failed to move and rename reparse point.\n");
|
||||
+
|
||||
cleanup:
|
||||
/* Cleanup */
|
||||
pRtlFreeUnicodeString(&nameW);
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index 8e9e28269f8..6385a26bee7 100644
|
||||
index 3c341a6d702..9076da9f763 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
+++ b/dlls/ntdll/unix/file.c
|
||||
@@ -5675,6 +5675,8 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io,
|
||||
@@ -5572,6 +5572,8 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io,
|
||||
unsigned int flags;
|
||||
UNICODE_STRING name_str, nt_name;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
@@ -68,7 +37,7 @@ index 8e9e28269f8..6385a26bee7 100644
|
||||
char *unix_name;
|
||||
|
||||
if (class == FileRenameInformation)
|
||||
@@ -5689,6 +5691,20 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io,
|
||||
@@ -5586,6 +5588,20 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io,
|
||||
name_str.Length = info->FileNameLength;
|
||||
name_str.MaximumLength = info->FileNameLength + sizeof(WCHAR);
|
||||
InitializeObjectAttributes( &attr, &name_str, OBJ_CASE_INSENSITIVE, info->RootDirectory, NULL );
|
||||
@@ -89,7 +58,7 @@ index 8e9e28269f8..6385a26bee7 100644
|
||||
status = get_nt_and_unix_names( &attr, &nt_name, &unix_name, FILE_OPEN_IF );
|
||||
if (status == STATUS_SUCCESS || status == STATUS_NO_SUCH_FILE)
|
||||
{
|
||||
@@ -5705,8 +5721,13 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io,
|
||||
@@ -5602,8 +5618,13 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io,
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
@@ -104,6 +73,14 @@ index 8e9e28269f8..6385a26bee7 100644
|
||||
free( nt_name.Buffer );
|
||||
}
|
||||
else status = STATUS_INVALID_PARAMETER_3;
|
||||
@@ -5646,7 +5667,6 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io,
|
||||
status = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
-
|
||||
}
|
||||
free( unix_name );
|
||||
free( nt_name.Buffer );
|
||||
diff --git a/server/fd.c b/server/fd.c
|
||||
index 466259ae567..7f88fcd6e33 100644
|
||||
--- a/server/fd.c
|
||||
|
@@ -1,30 +0,0 @@
|
||||
From 2cf08dad55bea4bbf5ca37ff0bf4a0553d1f6be3 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Sat, 3 Sep 2022 08:57:05 -0600
|
||||
Subject: kernelbase: Add test for reparse point copy behavior.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/ntdll/tests/file.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index 808d863ea55..390768f557d 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -5762,6 +5762,12 @@ static void test_reparse_points(void)
|
||||
bret = MoveFileW(new_path, reparse_path);
|
||||
ok(bret, "Failed to move and rename reparse point.\n");
|
||||
|
||||
+ /* Check copying a reparse point to another location */
|
||||
+ lstrcpyW(new_path, path);
|
||||
+ lstrcatW(new_path, new_reparseW);
|
||||
+ bret = CopyFileW(reparse_path, new_path, TRUE);
|
||||
+ ok(!bret, "Reparse points cannot be copied.\n");
|
||||
+
|
||||
cleanup:
|
||||
/* Cleanup */
|
||||
pRtlFreeUnicodeString(&nameW);
|
||||
--
|
||||
2.17.1
|
||||
|
@@ -5,44 +5,9 @@ Subject: [PATCH] ntdll: Follow reparse points during path resolution.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/ntdll/tests/file.c | 11 ++-
|
||||
dlls/ntdll/unix/file.c | 196 +++++++++++++++++++++++++++++++++++-----
|
||||
2 files changed, 184 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index 9bd4bbdd245..84a0957b040 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -6025,7 +6025,7 @@ static INT build_reparse_buffer(const WCHAR *filename, ULONG tag, ULONG flags,
|
||||
|
||||
static void test_reparse_points(void)
|
||||
{
|
||||
- WCHAR path[MAX_PATH], reparse_path[MAX_PATH], target_path[MAX_PATH], volnameW[MAX_PATH], new_path[MAX_PATH];
|
||||
+ WCHAR path[MAX_PATH], reparse_path[MAX_PATH], target_path[MAX_PATH], volnameW[MAX_PATH], new_path[MAX_PATH], thru_path[MAX_PATH];
|
||||
static const WCHAR new_reparseW[] = {'\\','n','e','w','_','r','e','p','a','r','s','e',0};
|
||||
static const WCHAR reparseW[] = {'\\','r','e','p','a','r','s','e',0};
|
||||
static const WCHAR targetW[] = {'\\','t','a','r','g','e','t',0};
|
||||
@@ -6412,11 +6412,20 @@ static void test_reparse_points(void)
|
||||
bret = CopyFileW(reparse_path, new_path, TRUE);
|
||||
ok(!bret, "Reparse points cannot be copied.\n");
|
||||
|
||||
+ /* Create a file on the other side of a reparse point */
|
||||
+ lstrcpyW(thru_path, reparse_path);
|
||||
+ lstrcatW(thru_path, new_reparseW);
|
||||
+ handle = CreateFileW(thru_path, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_NEW, 0, 0);
|
||||
+ ok( handle != INVALID_HANDLE_VALUE, "Failed to create file on other side of reparse point: %lx.\n", GetLastError() );
|
||||
+ CloseHandle(handle);
|
||||
+
|
||||
cleanup:
|
||||
/* Cleanup */
|
||||
pRtlFreeUnicodeString(&nameW);
|
||||
HeapFree(GetProcessHeap(), 0, long_path);
|
||||
HeapFree(GetProcessHeap(), 0, buffer);
|
||||
+ bret = DeleteFileW(thru_path);
|
||||
+ ok(bret, "Failed to delete file on other side of junction point!\n");
|
||||
bret = RemoveDirectoryW(reparse_path);
|
||||
ok(bret, "Failed to remove temporary reparse point directory!\n");
|
||||
bret = RemoveDirectoryW(target_path);
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index f3274478ae2..860e563f69d 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
|
@@ -1,4 +1,4 @@
|
||||
From f1675a9b37980cafd0b6f76e23ef8b042b60bb1e Mon Sep 17 00:00:00 2001
|
||||
From 5b94720ada0b6f75ddff60cf19472a2685dbeaf0 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Sun, 4 Sep 2022 13:19:16 -0600
|
||||
Subject: [PATCH] ntdll: Allow reparse points to target the applicable Unix
|
||||
@@ -9,14 +9,14 @@ the user to follow the symlink outside of Wine.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/ntdll/unix/file.c | 129 +++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 129 insertions(+)
|
||||
dlls/ntdll/unix/file.c | 118 +++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 118 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index f2e182d9076..63a27b89e20 100644
|
||||
index c54fd1119e1..33f26ceb89a 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
+++ b/dlls/ntdll/unix/file.c
|
||||
@@ -3577,6 +3577,125 @@ static NTSTATUS get_reparse_target( UNICODE_STRING *nt_target, REPARSE_DATA_BUFF
|
||||
@@ -3712,6 +3712,114 @@ static NTSTATUS get_reparse_target( UNICODE_STRING *nt_target, REPARSE_DATA_BUFF
|
||||
}
|
||||
|
||||
|
||||
@@ -50,18 +50,7 @@ index f2e182d9076..63a27b89e20 100644
|
||||
+ d = dirname( unix_path );
|
||||
+ if (d != unix_path) strcpy( unix_path, d );
|
||||
+ strcat( unix_path, "/");
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ nt_path = malloc( nt_path_len * sizeof(WCHAR) );
|
||||
+ if (!nt_path)
|
||||
+ {
|
||||
+ free( unix_path );
|
||||
+ return STATUS_NO_MEMORY;
|
||||
+ }
|
||||
+ status = wine_unix_to_nt_file_name( unix_path, nt_path, &nt_path_len );
|
||||
+ if (status != STATUS_BUFFER_TOO_SMALL) break;
|
||||
+ free( nt_path );
|
||||
+ }
|
||||
+ status = unix_to_nt_file_name( unix_path, &nt_path, FILE_OPEN );
|
||||
+ free( unix_path );
|
||||
+ if (status != STATUS_SUCCESS)
|
||||
+ return status;
|
||||
@@ -142,7 +131,7 @@ index f2e182d9076..63a27b89e20 100644
|
||||
/*
|
||||
* Retrieve the unix name corresponding to a file handle, remove that directory, and then symlink
|
||||
* the requested directory to the location of the old directory.
|
||||
@@ -3710,6 +3829,16 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
@@ -3845,6 +3953,16 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
link_dir_fd = fd;
|
||||
}
|
||||
|
||||
@@ -160,5 +149,5 @@ index f2e182d9076..63a27b89e20 100644
|
||||
if (!renameat2( -1, tmplink, -1, unix_src, RENAME_EXCHANGE ))
|
||||
{
|
||||
--
|
||||
2.43.0
|
||||
2.47.2
|
||||
|
||||
|
@@ -5,60 +5,9 @@ Subject: ntdll: Always report symbolic links as containing zero bytes.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/ntdll/tests/file.c | 32 ++++++++++++++++++++++++++++++++
|
||||
dlls/ntdll/unix/file.c | 4 ++++
|
||||
2 files changed, 36 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index a0b84849490..35ba5f03097 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -5396,6 +5396,7 @@ static void test_reparse_points(void)
|
||||
static const WCHAR dotW[] = {'.',0};
|
||||
REPARSE_DATA_BUFFER *buffer = NULL;
|
||||
DWORD dwret, dwLen, dwFlags, err;
|
||||
+ WIN32_FILE_ATTRIBUTE_DATA fad;
|
||||
WCHAR buf[] = {0,0,0,0};
|
||||
HANDLE handle, token;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
@@ -5626,6 +5627,37 @@ static void test_reparse_points(void)
|
||||
ok(bret, "Failed to create symlink! (0x%lx)\n", GetLastError());
|
||||
CloseHandle(handle);
|
||||
|
||||
+ /* Check the size of the symlink */
|
||||
+ bret = GetFileAttributesExW(reparse_path, GetFileExInfoStandard, &fad);
|
||||
+ ok(bret, "Failed to read file attributes from the symlink target.\n");
|
||||
+ ok(fad.nFileSizeLow == 0 && fad.nFileSizeHigh == 0, "Size of symlink is not zero.\n");
|
||||
+ handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
|
||||
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
|
||||
+ ok(handle != INVALID_HANDLE_VALUE, "Failed to open symlink file.\n");
|
||||
+ ok(GetFileSize(handle, NULL) == 0, "symlink size is not zero\n");
|
||||
+ bret = ReadFile(handle, &buf, sizeof(buf), &dwLen, NULL);
|
||||
+ todo_wine ok(bret, "Failed to read data from the symlink.\n");
|
||||
+ ok(dwLen == 0, "Length of symlink data is not zero.\n");
|
||||
+ CloseHandle(handle);
|
||||
+
|
||||
+ /* Check the size/data of the symlink target */
|
||||
+ handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
|
||||
+ FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||
+ if (handle == INVALID_HANDLE_VALUE)
|
||||
+ {
|
||||
+ win_skip("Failed to open symlink file handle (0x%lx).\n", GetLastError());
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ ok(GetFileSize(handle, NULL) == sizeof(fooW), "symlink target size does not match (%ld != %d)\n",
|
||||
+ GetFileSize(handle, NULL), (int)sizeof(fooW));
|
||||
+ bret = ReadFile(handle, &buf, sizeof(buf), &dwLen, NULL);
|
||||
+ ok(bret, "Failed to read data from the symlink.\n");
|
||||
+ ok(dwLen == sizeof(fooW), "Length of symlink target data does not match (%ld != %d).\n",
|
||||
+ dwLen, (int)sizeof(fooW));
|
||||
+ ok(!memcmp(fooW, &buf, sizeof(fooW)), "Symlink target data does not match (%s != %s).\n",
|
||||
+ wine_dbgstr_wn(buf, dwLen), wine_dbgstr_w(fooW));
|
||||
+ CloseHandle(handle);
|
||||
+
|
||||
/* Check the size/data of the symlink target when opened with FILE_FLAG_OPEN_REPARSE_POINT */
|
||||
handle = CreateFileW(target_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index f298b1f7a6c..caa454c024f 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user