ReactOS 0.4.17-dev-966-gf06eace
GetConnectionAttributes.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS API tests
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Named Pipe File System (NPFS) Extended Attributes test
5 * COPYRIGHT: Copyright 2026 Mohammad Amin Mollazadeh <madamin@proton.me>
6 */
7
8#include <apitest.h>
9#include <ndk/ntndk.h>
10
11static char ClientProcessIdAttributeName[] = "ClientProcessId";
12static char ClientSessionIdAttributeName[] = "ClientSessionId";
13
14static char NonExistentAttributeName[] = "NonExistentAttribute";
15static char CustomAttributeName1[] = "MyOwnAttribute1";
16static char CustomAttributeName2[] = "MyOwnAttribute2";
17static char CustomAttributeName1Upper[] = "MYOWNATTRIBUTE1";
18
19static int TestValue1 = 0xC001D00D;
20static char TestValue2[] = "The Test Value";
21static char TestValue3[] = "The Third Test Value";
22
24{
26 DWORD BytesRead = 0;
27 BYTE Buffer[255];
28
29 hPipe = CreateFileW(L"\\\\.\\pipe\\NpfsApiTestPipe",
31 0,
32 NULL,
34 0,
35 NULL);
36 if (hPipe == INVALID_HANDLE_VALUE)
37 {
38 skip("Failed to open the named pipe: 0x%08X\n", GetLastError());
39 return;
40 }
41
42 /* Keep the child process alive while the pipe is still connected. */
43 ReadFile(hPipe, Buffer, sizeof(Buffer), &BytesRead, NULL);
44
45 CloseHandle(hPipe);
46}
47
49{
50 char cmdline[MAX_PATH];
51 char exe[MAX_PATH];
52 STARTUPINFOA si = { sizeof(si) };
53
54 GetModuleFileNameA(NULL, exe, sizeof(exe));
55 sprintf(cmdline, "\"%s\" %s %s", exe, "NpfsGetConnectionAttributes", "subtest");
56
57 return CreateProcessA(exe, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, ppi);
58}
59
60START_TEST(NpfsGetConnectionAttributes)
61{
64 char Buffer[256]; /* For extended attribute data */
66 PROCESS_INFORMATION ProcessInfo = {0};
68
69 char** argv;
71 if (argc > 2)
72 {
74 return;
75 }
76
77 hPipe = CreateNamedPipeW(L"\\\\.\\pipe\\NpfsApiTestPipe",
80 1,
81 256, 256, /* Pipe Read/Write buffer size */
82 0, NULL);
83 if (hPipe == INVALID_HANDLE_VALUE)
84 {
85 skip("Failed to create/open the named pipe: 0x%08X\n", GetLastError());
86 return;
87 }
88
89 /* Query for a non-existence attribute */
94 Buffer, sizeof(Buffer));
96
97 /* Set a custom attribute and query it back */
103 Buffer, sizeof(CustomAttributeName1) + sizeof(TestValue1),
104 NULL, 0);
106 ok_eq_ulong(IoStatusBlock.Information, 0);
107
108 *(int*)Buffer = 0xdeadbeef;
113 Buffer, sizeof(int));
115 ok_eq_ulong(IoStatusBlock.Information, sizeof(int));
116 ok_eq_hex(*(int*)Buffer, 0xC001D00D);
117
118 /* Set a second custom attribute and query attributes back */
124 Buffer, sizeof(CustomAttributeName2) + sizeof(TestValue2),
125 NULL, 0);
127 ok_eq_ulong(IoStatusBlock.Information, 0);
128
129 *(int*)Buffer = 0xdeadbeef;
134 Buffer, sizeof(int));
136 ok_eq_ulong(IoStatusBlock.Information, sizeof(int));
137 ok_eq_hex(*(int*)Buffer, 0xC001D00D);
138
139 RtlZeroMemory(Buffer, sizeof(Buffer));
144 Buffer, sizeof(TestValue2));
146 ok_eq_ulong(IoStatusBlock.Information, sizeof(TestValue2));
148
149 /* Set the first attribute to a bigger value */
155 Buffer, sizeof(CustomAttributeName1) + sizeof(TestValue3),
156 NULL, 0);
158 ok_eq_ulong(IoStatusBlock.Information, 0);
159
165 Buffer, sizeof(TestValue3));
167 ok_eq_ulong(IoStatusBlock.Information, sizeof(TestValue3));
169
170 /* Query NULL attribute */
171 RtlZeroMemory(Buffer, sizeof(Buffer));
176 NULL, 0,
177 Buffer, sizeof(Buffer));
179 ok_eq_ulong(IoStatusBlock.Information, 0);
180
181 /* Query with NULL as buffer */
182 RtlZeroMemory(Buffer, sizeof(Buffer));
187 NULL, 0);
189 ok_eq_ulong(IoStatusBlock.Information, 0);
190
191 /* Query with a small buffer */
196 Buffer, sizeof(char));
198 ok_eq_ulong(IoStatusBlock.Information, 0);
199
200 /* Query case-sensitivity */
206 Buffer, sizeof(TestValue1));
208
209 /* Zero-length value: Unset the attribute */
214 NULL, 0);
216 ok_eq_ulong(IoStatusBlock.Information, 0);
217
223 Buffer, sizeof(TestValue1));
225 ok_eq_ulong(IoStatusBlock.Information, 0);
226
227 /* Empty name */
228 RtlZeroMemory(Buffer, sizeof(Buffer));
233 Buffer, 1 + sizeof(TestValue1),
234 NULL, 0);
236
237 RtlZeroMemory(Buffer, sizeof(Buffer));
241 "", sizeof(""),
242 Buffer, sizeof(TestValue1));
244
245 /* Query for the PID and process session ID attributes.
246 * These attributes are set by NpCreateClientEnd. */
247
248 /* ClientProcessId and ClientSessionId should return STATUS_NOT_FOUND
249 * when there's no client connected to the pipe. */
254 Buffer, sizeof(DWORD));
256
261 Buffer, sizeof(DWORD));
263
264 if (!RunChildProcess(&ProcessInfo))
265 {
266 skip("Failed to create the child process: 0x%08X\n", GetLastError());
267 goto Cleanup;
268 }
269 /* Wait for client connection */
271 {
272 skip("Failed to connect the named pipe: 0x%08X\n", GetLastError());
273 goto Cleanup;
274 }
275
276 *(DWORD*)Buffer = 0xdeadbeef;
281 Buffer, sizeof(DWORD));
283 ok_eq_ulong(IoStatusBlock.Information, sizeof(DWORD));
284 ok_eq_ulong(*(DWORD*)Buffer, ProcessInfo.dwProcessId);
285
286 if (!ProcessIdToSessionId(ProcessInfo.dwProcessId, &SessionId))
287 {
288 skip("Failed to get the session ID of the client process: 0x%08X\n", GetLastError());
289 goto Cleanup;
290 }
291
296 Buffer, sizeof(DWORD));
298 ok_eq_ulong(IoStatusBlock.Information, sizeof(DWORD));
300
301 /* Disconnect the named pipe and wait for the child process to exit */
302 DisconnectNamedPipe(hPipe);
304
305Cleanup:
306 if (ProcessInfo.hThread != NULL)
307 CloseHandle(ProcessInfo.hThread);
308 if (ProcessInfo.hProcess != NULL)
309 CloseHandle(ProcessInfo.hProcess);
310 if (hPipe != INVALID_HANDLE_VALUE)
311 NtClose(hPipe);
312}
static char TestValue3[]
static char TestValue2[]
static int TestValue1
static void NamedPipeClientChildProcess(void)
static char NonExistentAttributeName[]
static char CustomAttributeName2[]
static BOOL RunChildProcess(PPROCESS_INFORMATION ppi)
static char CustomAttributeName1[]
static char CustomAttributeName1Upper[]
static char ClientSessionIdAttributeName[]
static char ClientProcessIdAttributeName[]
#define FSCTL_PIPE_GET_CONNECTION_ATTRIBUTE
#define ok_eq_str(value, expected)
Definition: apitest.h:140
#define ok_eq_hex(value, expected)
Definition: apitest.h:134
#define ok_eq_ulong(value, expected)
Definition: apitest.h:120
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
LONG NTSTATUS
Definition: precomp.h:26
Definition: bufpool.h:45
_In_ PIO_STATUS_BLOCK IoStatusBlock
Definition: dispmprt.h:608
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define CloseHandle
Definition: compat.h:739
#define OPEN_EXISTING
Definition: compat.h:775
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define CreateFileW
Definition: compat.h:741
ULONG SessionId
Definition: dllmain.c:28
DWORD WINAPI GetModuleFileNameA(HINSTANCE hModule, LPSTR lpFilename, DWORD nSize)
Definition: loader.c:539
BOOL WINAPI ProcessIdToSessionId(IN DWORD dwProcessId, OUT PDWORD pSessionId)
Definition: proc.c:2074
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA(const char *app_name, char *cmd_line, SECURITY_ATTRIBUTES *process_attr, SECURITY_ATTRIBUTES *thread_attr, BOOL inherit, DWORD flags, void *env, const char *cur_dir, STARTUPINFOA *startup_info, PROCESS_INFORMATION *info)
Definition: process.c:686
MonoAssembly int argc
Definition: metahost.c:107
static const WCHAR Cleanup[]
Definition: register.c:80
#define L(x)
Definition: resources.c:13
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
Status
Definition: gdiplustypes.h:24
#define sprintf
Definition: sprintf.c:45
static SYSTEM_INFO si
Definition: virtual.c:39
#define argv
Definition: mplay32.c:18
BOOL WINAPI ConnectNamedPipe(IN HANDLE hNamedPipe, IN LPOVERLAPPED lpOverlapped)
Definition: npipe.c:701
BOOL WINAPI DisconnectNamedPipe(HANDLE hNamedPipe)
Definition: npipe.c:961
HANDLE WINAPI CreateNamedPipeW(LPCWSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: npipe.c:246
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3429
NTSYSAPI NTSTATUS NTAPI NtFsControlFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG DeviceIoControlCode, IN PVOID InBuffer OPTIONAL, IN ULONG InBufferLength, OUT PVOID OutBuffer OPTIONAL, IN ULONG OutBufferLength)
int winetest_get_mainargs(char ***pargv)
void winetest_wait_child_process(HANDLE process)
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
TCHAR * cmdline
Definition: stretchblt.cpp:32
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PLONGLONG _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_opt_ PULONG_PTR BytesRead
Definition: wdfiotarget.h:870
#define PIPE_READMODE_BYTE
Definition: winbase.h:172
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define PIPE_ACCESS_DUPLEX
Definition: winbase.h:167
#define PIPE_WAIT
Definition: winbase.h:174
#define PIPE_TYPE_BYTE
Definition: winbase.h:170
#define ERROR_PIPE_CONNECTED
Definition: winerror.h:624
#define FSCTL_PIPE_SET_CONNECTION_ATTRIBUTE
Definition: iotypes.h:7271
unsigned char BYTE
Definition: xxhash.c:193