1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
index 0f66429fc9d..9d5975fbe86 100644
--- a/dlls/ntdll/unix/virtual.c
+++ b/dlls/ntdll/unix/virtual.c
@@ -112,6 +112,8 @@ struct file_view
unsigned int protect; /* protection for all pages at allocation time and SEC_* flags */
};
+#define SYMBOLIC_LINK_QUERY 0x0001
+
/* per-page protection flags */
#define VPROT_READ 0x01
#define VPROT_WRITE 0x02
@@ -4480,34 +4482,96 @@ static NTSTATUS get_working_set_ex( HANDLE process, LPCVOID addr,
return STATUS_SUCCESS;
}
+static NTSTATUS read_nt_symlink( UNICODE_STRING *name, WCHAR *target, DWORD size )
+{
+ NTSTATUS status;
+ OBJECT_ATTRIBUTES attr;
+ HANDLE handle;
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.Attributes = OBJ_CASE_INSENSITIVE;
+ attr.ObjectName = name;
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+
+ if (!(status = NtOpenSymbolicLinkObject( &handle, SYMBOLIC_LINK_QUERY, &attr )))
+ {
+ UNICODE_STRING targetW;
+ targetW.Buffer = target;
+ targetW.MaximumLength = (size - 1) * sizeof(WCHAR);
+ status = NtQuerySymbolicLinkObject( handle, &targetW, NULL );
+ if (!status) target[targetW.Length / sizeof(WCHAR)] = 0;
+ NtClose( handle );
+ }
+ return status;
+}
+
+static NTSTATUS follow_device_symlink( WCHAR *buffer, SIZE_T max_path_len, WCHAR *name, SIZE_T *current_path_len )
+{
+ WCHAR *p = buffer;
+ NTSTATUS status = STATUS_SUCCESS;
+ SIZE_T devname_len = 6; // e.g. \??\C:
+ UNICODE_STRING devname;
+ DWORD target_len;
+
+ if (*current_path_len >= devname_len * sizeof(WCHAR) && name[devname_len - 1] == ':') {
+ devname.Buffer = name;
+ devname.Length = devname_len * sizeof(WCHAR);
+ if (!(status = read_nt_symlink( &devname, p, (max_path_len - *current_path_len) / sizeof(WCHAR) + devname_len + 1 )))
+ {
+ target_len = lstrlenW(p);
+ *current_path_len -= devname_len * sizeof(WCHAR); // skip the device name
+ p += target_len;
+
+ memcpy( p, name + devname_len, *current_path_len );
+ *current_path_len += target_len * sizeof(WCHAR);
+ }
+ }
+ else memcpy( p, name, *current_path_len );
+
+ return status;
+}
+
static unsigned int get_memory_section_name( HANDLE process, LPCVOID addr,
MEMORY_SECTION_NAME *info, SIZE_T len, SIZE_T *ret_len )
{
+ SIZE_T current_path_len, max_path_len;
+ WCHAR *name;
unsigned int status;
if (!info) return STATUS_ACCESS_VIOLATION;
+ max_path_len = len - sizeof(*info) - sizeof(WCHAR); // dont count null char
+ if (!(name = malloc( max_path_len ))) return STATUS_NO_MEMORY;
SERVER_START_REQ( get_mapping_filename )
{
req->process = wine_server_obj_handle( process );
req->addr = wine_server_client_ptr( addr );
if (len > sizeof(*info) + sizeof(WCHAR))
- wine_server_set_reply( req, info + 1, len - sizeof(*info) - sizeof(WCHAR) );
+ wine_server_set_reply( req, name, max_path_len );
status = wine_server_call( req );
if (!status || status == STATUS_BUFFER_OVERFLOW)
{
- if (ret_len) *ret_len = sizeof(*info) + reply->len + sizeof(WCHAR);
- if (len < sizeof(*info)) status = STATUS_INFO_LENGTH_MISMATCH;
+ current_path_len = reply->len;
+ if (len < sizeof(*info))
+ {
+ status = STATUS_INFO_LENGTH_MISMATCH;
+ }
+ else if (!status) status = follow_device_symlink( (WCHAR *)(info + 1), max_path_len, name, ¤t_path_len);
+
+ if (ret_len) *ret_len = sizeof(*info) + current_path_len + sizeof(WCHAR);
if (!status)
{
info->SectionFileName.Buffer = (WCHAR *)(info + 1);
- info->SectionFileName.Length = reply->len;
- info->SectionFileName.MaximumLength = reply->len + sizeof(WCHAR);
- info->SectionFileName.Buffer[reply->len / sizeof(WCHAR)] = 0;
+ info->SectionFileName.Length = current_path_len;
+ info->SectionFileName.MaximumLength = current_path_len + sizeof(WCHAR);
+ info->SectionFileName.Buffer[current_path_len / sizeof(WCHAR)] = 0;
}
}
}
SERVER_END_REQ;
+ free(name);
return status;
}
diff --git a/dlls/psapi/tests/psapi_main.c b/dlls/psapi/tests/psapi_main.c
index 185a4062092..b4eabf986ed 100644
--- a/dlls/psapi/tests/psapi_main.c
+++ b/dlls/psapi/tests/psapi_main.c
@@ -471,7 +471,6 @@ static void test_GetMappedFileName(void)
ret = GetMappedFileNameA(GetCurrentProcess(), base, map_name, sizeof(map_name));
ok(ret, "GetMappedFileName error %ld\n", GetLastError());
ok(ret > strlen(device_name), "map_name should be longer than device_name\n");
- todo_wine
ok(memcmp(map_name, device_name, strlen(device_name)) == 0, "map name does not start with a device name: %s\n", map_name);
SetLastError(0xdeadbeef);
@@ -482,7 +481,6 @@ static void test_GetMappedFileName(void)
{
ok(memcmp(map_nameW, nt_map_name, lstrlenW(map_nameW)) == 0, "map name does not start with a device name: %s\n", map_name);
WideCharToMultiByte(CP_ACP, 0, map_nameW, -1, map_name, MAX_PATH, NULL, NULL);
- todo_wine
ok(memcmp(map_name, device_name, strlen(device_name)) == 0, "map name does not start with a device name: %s\n", map_name);
}
@@ -490,7 +488,6 @@ static void test_GetMappedFileName(void)
ret = GetMappedFileNameA(GetCurrentProcess(), base + 0x2000, map_name, sizeof(map_name));
ok(ret, "GetMappedFileName error %ld\n", GetLastError());
ok(ret > strlen(device_name), "map_name should be longer than device_name\n");
- todo_wine
ok(memcmp(map_name, device_name, strlen(device_name)) == 0, "map name does not start with a device name: %s\n", map_name);
SetLastError(0xdeadbeef);
@@ -566,7 +563,7 @@ static void test_GetProcessImageFileName(void)
{
/* Windows returns 2*strlen-1 */
ok(ret >= strlen(szImgPath), "szImgPath=\"%s\" ret=%ld\n", szImgPath, ret);
- todo_wine ok(!strcmp(szImgPath, szMapPath), "szImgPath=\"%s\" szMapPath=\"%s\"\n", szImgPath, szMapPath);
+ ok(!strcmp(szImgPath, szMapPath), "szImgPath=\"%s\" szMapPath=\"%s\"\n", szImgPath, szMapPath);
}
SetLastError(0xdeadbeef);
|