testsuite tests for Cygwin<->Win32 process interaction
Corinna Vinschen
corinna-cygwin@cygwin.com
Thu Jun 26 08:21:26 GMT 2025
On Jun 25 16:15, Jeremy Drake via Cygwin-developers wrote:
> On Wed, 25 Jun 2025, Jon Turney wrote:
>
> > On 25/06/2025 20:52, Jeremy Drake via Cygwin-developers wrote:
> > > I would like to add tests of invoking non-Cygwin processes using
> > > posix_spawn and making sure their stdin/out/err and cwd are as expected.
> > > I see that there is a mingw directory for building with the cross-mingw
> > > compiler, and I could make a test child process built through that which
> > > uses GetFileInformationByHandleEx and GetCurrentDirectoryW.
>
> This turned out to be more complicated than I expected,
> GetFileInformationByHandleEx(FileNameInfo) sucks badly, and seems to only
> actually work for regular files.
This is unexpected. GetFileInformationByHandleEx is basically just a
wrapper for NtQueryInformationFile and that goes especially for the
FileNameInfo class which even neglects to prepend a drive letter or
UNC path to make the result useful in a DOS Path environment.
But naturally it should work for files and dirs the same.
I attached a Q&D(*) STC. The output shows that it works the same for
files and dirs:
$ tests/x86_64/ntfilename xxx
NtOpenFile(\??\C:\cygwin64\home\corinna\xxx)
NtQueryObject: "\Device\HarddiskVolume3\cygwin64\home\corinna\xxx"
FileNameInformation: "\cygwin64\home\corinna\xxx"
FileNormalizedNameInformation: "\cygwin64\home\corinna\xxx"
FileNameInfo: "\cygwin64\home\corinna\xxx"
$ tests/x86_64/ntfilename .
NtOpenFile(\??\C:\cygwin64\home\corinna)
NtQueryObject: "\Device\HarddiskVolume3\cygwin64\home\corinna"
FileNameInformation: "\cygwin64\home\corinna"
FileNormalizedNameInformation: "\cygwin64\home\corinna"
FileNameInfo: "\cygwin64\home\corinna"
So, my question at this point would be, what is the *real* problem here?
> Which is probably why Cygwin uses
> NtQueryObject(ObjectNameInformation) instead, which I switched to
Uh, we use NtQueryObject in cases where we want valid return values
for real NT objects or device paths like \Device\Null.
> This
> has the downside of giving NT native paths (\Device\HarddiskVolumeN\path).
Downside? *grin*
Corinna
(*) Don't use non-ASCII chars in the filename when testing...
-------------- next part --------------
#define _WIN32_WINNT 0x0a00
#include <stdio.h>
#include <windows.h>
#include <winternl.h>
#include <locale.h>
#include <wchar.h>
#include <wctype.h>
int
main (int argc, char **argv)
{
UNICODE_STRING wpath;
UNICODE_STRING upath;
HANDLE h;
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
NTSTATUS status;
ULONG size;
POBJECT_NAME_INFORMATION poni = (POBJECT_NAME_INFORMATION) alloca (32000);
PFILE_NAME_INFORMATION pfni = (PFILE_NAME_INFORMATION) alloca (32000);
PFILE_NAME_INFO pfni2 = (PFILE_NAME_INFO) pfni;
setlocale (LC_ALL, "");
if (argc < 2)
{
fprintf (stderr, "usage: %s DOS-PATH\n", argv[0]);
return 1;
}
if (!RtlCreateUnicodeStringFromAsciiz (&wpath, argv[1]))
{
fprintf (stderr, "RtlCreateUnicodeStringFromAsciiz failed\n");
return 1;
}
if (!RtlDosPathNameToNtPathName_U (wpath.Buffer, &upath, NULL, NULL))
{
fprintf (stderr, "RtlDosPathNameToNtPathName_U failed\n");
RtlFreeUnicodeString (&wpath);
return 1;
}
InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE, NULL, NULL);
fprintf (stderr, "NtOpenFile(%ls)\n", upath.Buffer);
status = NtOpenFile (&h, GENERIC_READ | SYNCHRONIZE,
&attr, &io, FILE_SHARE_VALID_FLAGS,
FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT);
if (!NT_SUCCESS (status))
{
fprintf (stderr, "NtOpenFile(%ls): 0x%08X\n", upath.Buffer, status);
return 1;
}
status = NtQueryObject (h, ObjectNameInformation, poni, 32000, &size);
if (!NT_SUCCESS (status))
fprintf (stderr, "NtQueryObject: 0x%08X\n", status);
else
printf ("NtQueryObject: \"%*ls\"\n",
poni->Name.Length / sizeof (WCHAR),
poni->Name.Buffer);
status = NtQueryInformationFile (h, &io, pfni, 32000, FileNameInformation);
if (!NT_SUCCESS (status))
fprintf (stderr, "FileNameInformation: 0x%08X\n", status);
else
printf ("FileNameInformation: \"%*ls\"\n",
pfni->FileNameLength / sizeof (WCHAR),
pfni->FileName);
status = NtQueryInformationFile (h, &io, pfni, 32000,
FileNormalizedNameInformation);
if (!NT_SUCCESS (status))
fprintf (stderr, "FileNormalizedNameInformation: 0x%08X\n", status);
else
printf ("FileNormalizedNameInformation: \"%*ls\"\n",
pfni->FileNameLength / sizeof (WCHAR),
pfni->FileName);
if (!GetFileInformationByHandleEx (h, FileNameInfo, pfni2, 32000))
fprintf (stderr, "FileNameInfo: Win32 error %u\n", GetLastError ());
else
printf ("FileNameInfo: \"%*ls\"\n",
pfni2->FileNameLength / sizeof (WCHAR),
pfni2->FileName);
NtClose (h);
return 0;
}
More information about the Cygwin-developers
mailing list