2 * Copyright 2023 Akihiro Sagawa
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "wine/test.h"
22 #define MAX_BUFFER 65536
24 static char stdout_buffer
[MAX_BUFFER
], stderr_buffer
[MAX_BUFFER
];
25 static DWORD stdout_size
, stderr_size
;
26 static char work_dir
[MAX_PATH
];
28 static void read_all_from_handle(HANDLE handle
, char *buffer
, DWORD
*size
)
33 memset(buffer
, 0, MAX_BUFFER
);
37 BOOL success
= ReadFile(handle
, bytes
, sizeof(bytes
), &bytes_read
, NULL
);
38 if (!success
|| !bytes_read
)
40 if (*size
+ bytes_read
> MAX_BUFFER
)
42 ok(FALSE
, "Insufficient buffer.\n");
45 memcpy(buffer
+ *size
, bytes
, bytes_read
);
50 #define run_dir(a, b) _run_dir(__FILE__, __LINE__, a, b)
51 static void _run_dir(const char *file
, int line
, const char *commandline
, int exitcode_expected
)
53 HANDLE child_stdout_write
, child_stderr_write
, parent_stdout_read
, parent_stderr_read
;
54 SECURITY_ATTRIBUTES security_attributes
= {0};
55 PROCESS_INFORMATION process_info
= {0};
56 STARTUPINFOA startup_info
= {0};
60 security_attributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
61 security_attributes
.bInheritHandle
= TRUE
;
63 CreatePipe(&parent_stdout_read
, &child_stdout_write
, &security_attributes
, 0);
64 CreatePipe(&parent_stderr_read
, &child_stderr_write
, &security_attributes
, 0);
65 SetHandleInformation(parent_stdout_read
, HANDLE_FLAG_INHERIT
, 0);
66 SetHandleInformation(parent_stderr_read
, HANDLE_FLAG_INHERIT
, 0);
68 startup_info
.cb
= sizeof(STARTUPINFOA
);
69 startup_info
.hStdOutput
= child_stdout_write
;
70 startup_info
.hStdError
= child_stderr_write
;
71 startup_info
.dwFlags
|= STARTF_USESTDHANDLES
;
73 sprintf(cmd
, "cmd.exe /d /c dir %s", commandline
);
74 CreateProcessA(NULL
, cmd
, NULL
, NULL
, TRUE
, 0, NULL
, NULL
, &startup_info
, &process_info
);
75 CloseHandle(child_stdout_write
);
76 CloseHandle(child_stderr_write
);
78 read_all_from_handle(parent_stdout_read
, stdout_buffer
, &stdout_size
);
79 read_all_from_handle(parent_stderr_read
, stderr_buffer
, &stderr_size
);
80 CloseHandle(parent_stdout_read
);
81 CloseHandle(parent_stderr_read
);
83 WaitForSingleObject(process_info
.hProcess
, INFINITE
);
84 GetExitCodeProcess(process_info
.hProcess
, &exitcode
);
85 CloseHandle(process_info
.hProcess
);
86 CloseHandle(process_info
.hThread
);
87 ok_(file
, line
)(exitcode
== exitcode_expected
, "expected exitcode %d, got %ld\n",
88 exitcode_expected
, exitcode
);
91 static void test_basic(void)
95 ok(stdout_size
> 0, "unexpected stdout buffer size %ld.\n", stdout_size
);
96 ok(stderr_size
== 0, "unexpected stderr buffer size %ld.\n", stderr_size
);
98 /* if file doesn't exist, cmd.exe prints an error message to stderr. */
99 run_dir("nonexistent", 1);
100 ok(stdout_size
> 0, "unexpected stdout buffer size %ld.\n", stdout_size
);
101 ok(stderr_size
> 0, "unexpected stderr buffer size %ld.\n", stderr_size
);
103 /* unknown option produces an error message to stderr. */
105 ok(stdout_size
== 0, "unexpected stdout buffer size %ld.\n", stdout_size
);
106 ok(stderr_size
> 0, "unexpected stderr buffer size %ld.\n", stderr_size
);
108 /* errorlevel for usage is 0. But, cmd.exe's exit code is 1. */
109 todo_wine
run_dir("/?", 1);
110 ok(stdout_size
> 0, "unexpected stdout buffer size %ld.\n", stdout_size
);
111 ok(stderr_size
== 0, "unexpected stderr buffer size %ld.\n", stderr_size
);
114 START_TEST(directory
)
116 WCHAR curdir
[MAX_PATH
];
119 GetCurrentDirectoryW(ARRAY_SIZE(curdir
), curdir
);
120 GetTempPathA(ARRAY_SIZE(work_dir
), work_dir
);
121 lstrcatA(work_dir
, "winetest.dir");
122 ret
= CreateDirectoryA(work_dir
, NULL
);
123 ok(ret
, "Failed to create %s\n", work_dir
);
124 ret
= SetCurrentDirectoryA(work_dir
);
125 ok(ret
, "Failed to set the working directory\n");
129 ret
= SetCurrentDirectoryW(curdir
);
130 ok(ret
, "Failed to restore the current directory\n");
131 ret
= RemoveDirectoryA(work_dir
);
132 ok(ret
, "Failed to remove the working directory\n");