Re: [RFC] gdb/testsuite/gdb.base/fileio.exp patch for cygwin

Pedro Alves
2007-12-06T03:42:39Z

Pedro Alves wrote:
> Daniel Jacobowitz wrote:
>
> > I might be mistaken, but I don't think there's any way to figure out
> > the original identity of the pipe. Handles aren't globally unique,
> > are they?
> >
>
> Yeah, I keep thinking CE, where they *are* global.
>
> There may be other ways to identify the pipes, like using
> named pipes for the ttys if possible -- but I don't know if
> it's possible to get a pipe name from a pipe handle. If
> there's a way to know if two handles point to the same
> object it should work too, but I don't think that's possible either...
>

Just for completeness:

Been googling a bit, and, as the Cygwin folks sure know,
under NT it is possible to get the internal names of objects,
and NT assigns unique names to pipes.

This is from the test files pasted at the bottom:

>./parent.exe
par: Filename from handle (STD_INPUT_HANDLE) returned :
\Device\NamedPipe\Win32Pipes.00000c70.00000002
par: Filename from handle (STD_OUTPUT_HANDLE) returned :
\Device\NamedPipe\Win32Pipes.00000c70.00000003
par: Filename from handle (STD_ERROR_HANDLE) returned :
\Device\NamedPipe\Win32Pipes.00000c70.00000003
par: Filename from handle (hReadPipe) returned :
\Device\NamedPipe\Win32Pipes.00000290.00000002
par: Filename from handle (hWritePipe) returned :
\Device\NamedPipe\Win32Pipes.00000290.00000002
par: Filename from handle (h) returned :
\Device\NamedPipe\testpipe
par: Filename from handle (duph) returned :
\Device\NamedPipe\Win32Pipes.00000290.00000002
child: Filename from handle (STD_INPUT_HANDLE) returned :
\Device\NamedPipe\Win32Pipes.00000c70.00000002
child: Filename from handle (STD_OUTPUT_HANDLE) returned :
\Device\NamedPipe\Win32Pipes.00000c70.00000003
child: Filename from handle (STD_ERROR_HANDLE) returned :
\Device\NamedPipe\Win32Pipes.00000c70.00000003

Notice that the STD_{INPUT|OUTPUT|ERROR}_HANDLEs are the
same pipes.

Since the next big Cygwin release will be NT only, perhaps this could
be used to map pipes to ttys.

Disclosure: I haven't really looked into Cygwin's sources to see
what it would take. It may be saying something plain dumb.

--
Pedro Alves

parent.c:

#include <stdio.h>
#include <windows.h>

typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING;
typedef UNICODE_STRING *PUNICODE_STRING;

#define STATUS_SUCCESS 0
typedef ULONG NTSTATUS;

typedef enum _OBJECT_INFO_CLASS {
ObjectBasicInfo,
ObjectNameInfo,
ObjectTypeInfo,
ObjectAllTypesInfo,
ObjectProtectionInfo
} OBJECT_INFO_CLASS;

typedef NTSTATUS (NTAPI * NTQUERYOBJECT)(HANDLE, OBJECT_INFO_CLASS,
PVOID, ULONG, PULONG);

typedef struct ObjectNameInfo_t {
UNICODE_STRING ObjectName;
WCHAR ObjectNameBuffer[1];
} OBJECT_NAME_INFO, *POBJECT_NAME_INFO;

static BOOL
print_object_name (const char *var, HANDLE h)
{
HMODULE ntdll = GetModuleHandle ("ntdll.dll");
NTQUERYOBJECT NtQueryObject
= (NTQUERYOBJECT) GetProcAddress (ntdll, "NtQueryObject");

char buf1[1024];
char buf2[1024];

POBJECT_NAME_INFO pObjectNameInfo = (POBJECT_NAME_INFO) buf1;

int rc = NtQueryObject (h, ObjectNameInfo, buf1, sizeof (buf1), NULL);
if (rc != STATUS_SUCCESS)
{
printf ("NtQueryObject failed with rc = 0x%x\n", rc);
return FALSE;
}

wcstombs (buf2, pObjectNameInfo->ObjectName.Buffer, 1024);
printf ("par: Filename from handle (%s) returned :\n%s\n", var, buf2);
return 0;
}

int
main (int argc, char **argv)
{
print_object_name ("STD_INPUT_HANDLE", GetStdHandle (STD_INPUT_HANDLE));
print_object_name ("STD_OUTPUT_HANDLE", GetStdHandle (STD_OUTPUT_HANDLE));
print_object_name ("STD_ERROR_HANDLE", GetStdHandle (STD_ERROR_HANDLE));

DWORD bufferSize = 1024;

HANDLE h = CreateNamedPipe ("\\\\.\\pipe\\testpipe",
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_BYTE,
PIPE_UNLIMITED_INSTANCES,
bufferSize,
bufferSize,
1,
NULL);

if (h == INVALID_HANDLE_VALUE)
{
printf ("CreateNamedPipe failed\n");
return 1;
}

HANDLE hReadPipe;
HANDLE hWritePipe;
BOOL good = CreatePipe (&hReadPipe, &hWritePipe, NULL, 100);
if (!good)
{
printf ("CreatePipe failed\n");
return 1;
}

print_object_name ("hReadPipe", hReadPipe);
print_object_name ("hWritePipe", hWritePipe);
print_object_name ("h", h);

HANDLE duph = INVALID_HANDLE_VALUE;
if (!DuplicateHandle (GetCurrentProcess(),
hReadPipe,
GetCurrentProcess(),
&duph,
0,
TRUE,
DUPLICATE_SAME_ACCESS))
{
printf ("DuplicateHandle failed\n");
return 1;
}

print_object_name ("duph", duph);

PROCESS_INFORMATION pi;

STARTUPINFO si;
memset (&si, 0, sizeof (si));
si.cb = sizeof (si);

CreateProcess (0,
"child.exe",/* command line */
NULL, /* Security */
NULL, /* thread */
TRUE, /* inherit handles */
0, /* start flags */
NULL, /* environment */
NULL, /* current directory */
&si,
&pi);

return 0;
}

---------
child.c:

#include <stdio.h>
#include <windows.h>

typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING;
typedef UNICODE_STRING *PUNICODE_STRING;

#define STATUS_SUCCESS 0
typedef ULONG NTSTATUS;

typedef enum _OBJECT_INFO_CLASS {
ObjectBasicInfo,
ObjectNameInfo,
ObjectTypeInfo,
ObjectAllTypesInfo,
ObjectProtectionInfo
} OBJECT_INFO_CLASS;

typedef NTSTATUS (NTAPI * NTQUERYOBJECT)(HANDLE, OBJECT_INFO_CLASS,
PVOID, ULONG, PULONG);

typedef struct ObjectNameInfo_t {
UNICODE_STRING ObjectName;
WCHAR ObjectNameBuffer[1];
} OBJECT_NAME_INFO, *POBJECT_NAME_INFO;

static BOOL
print_object_name (const char *var, HANDLE h)
{
HMODULE ntdll = GetModuleHandle ("ntdll.dll");
NTQUERYOBJECT NtQueryObject
= (NTQUERYOBJECT) GetProcAddress (ntdll, "NtQueryObject");

char buf1[1024];
char buf2[1024];

POBJECT_NAME_INFO pObjectNameInfo = (POBJECT_NAME_INFO) buf1;

int rc = NtQueryObject (h, ObjectNameInfo, buf1, sizeof (buf1), NULL);
if (rc != STATUS_SUCCESS)
{
printf ("NtQueryObject failed with rc = 0x%x\n", rc);
return FALSE;
}

wcstombs (buf2, pObjectNameInfo->ObjectName.Buffer, 1024);
printf ("child: Filename from handle (%s) returned :\n%s\n", var, buf2);
return 0;
}

int
main (int argc, char **argv)
{
print_object_name ("STD_INPUT_HANDLE", GetStdHandle (STD_INPUT_HANDLE));
print_object_name ("STD_OUTPUT_HANDLE", GetStdHandle (STD_OUTPUT_HANDLE));
print_object_name ("STD_ERROR_HANDLE", GetStdHandle (STD_ERROR_HANDLE));

return 0;
}