Skip to content

Instantly share code, notes, and snippets.

@k-takata
Last active April 7, 2019 18:27
Show Gist options
  • Save k-takata/68796375f825dfef730f3f4ad83c7785 to your computer and use it in GitHub Desktop.
Save k-takata/68796375f825dfef730f3f4ad83c7785 to your computer and use it in GitHub Desktop.
Output some data to Cygwin pty from a normal Win32 program

About

These are sample programs to output some data to Cygwin pty from a normal Win32 program.

Usage of cygpty

  1. Download go-iscygpty

    https://github.com/k-takata/go-iscygpty

  2. Execute the sample program in mintty

    You will see the name of pipes.

    $ cd _example
    $ go run example.go
    Stdin is Cygwin/MSYS pty. (\cygwin-e022582115c10879-pty4-from-master)
    Stdout is Cygwin/MSYS pty. (\cygwin-e022582115c10879-pty4-to-master)
    Stderr is Cygwin/MSYS pty. (\cygwin-e022582115c10879-pty4-to-master)
    Cygwin/MSYS pty is used.
    
  3. Open another command prompt and execute cygpty

    Change the last part of the pipe name from -{from,to}-master to -master-ctl.

    > cygpty \cygwin-e022582115c10879-pty4-master-ctl
    Pipe name: \\.\pipe\cygwin-e022582115c10879-pty4-master-ctl
    OpenProcess success
    Server pid: 12864, 64bit: 1
    in: 00000088, out: 0000008C, out2: 00000090 err: 232, read: 32
    26 bytes written.
    

    You will see an output in mintty with red and green color.

    Hello World!
    

Usage of findcygpty

This enumulates opened handles in its process and finds cygwin pty handles, then it outputs "Hello World!" to the cygwin pty.

$ ./findcygpty
[00000008]
[000003A8] \cygwin-e022582115c10879-pty4-from-master
[000003AC] \cygwin-e022582115c10879-pty4-to-master
[000003B0] \cygwin-e022582115c10879-pty4-to-master-cyg
from_master: 000003A8, to_master: 000003AC
Hello World!
26 bytes written.

It outputs the message directly to the cygwin pty, so the message will not be redirected.

$ ./findcygpty > /dev/null 2>&1
Hello World!

Based on http://forum.sysinternals.com/howto-enumerate-handles_topic18892.html

#define _WIN32_WINNT 0x0600
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
DWORD pid;
} pipe_request;
// 12 bytes
typedef struct {
unsigned from_master;
unsigned to_master;
DWORD error;
} pipe_reply32_1;
// 16 bytes
typedef struct {
unsigned from_master;
unsigned to_master;
unsigned to_master_cyg;
DWORD error;
} pipe_reply32_2;
// 20 bytes
typedef struct {
unsigned __int64 from_master;
unsigned __int64 to_master;
DWORD error;
} pipe_reply64_1;
// 28 bytes
typedef struct {
unsigned __int64 from_master;
unsigned __int64 to_master;
unsigned __int64 to_master_cyg;
DWORD error;
} pipe_reply64_2;
typedef union {
pipe_reply32_1 r32_1;
pipe_reply32_2 r32_2;
pipe_reply64_1 r64_1;
pipe_reply64_2 r64_2;
} pipe_reply;
typedef BOOL (WINAPI *pfnIsWow64Process)(HANDLE, PBOOL);
pfnIsWow64Process pIsWow64Process;
BOOL Is64bitProcess(DWORD pid)
{
HANDLE handle;
SYSTEM_INFO si;
BOOL wow64 = TRUE;
pIsWow64Process = (pfnIsWow64Process) GetProcAddress(
GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
if (pIsWow64Process == NULL) {
printf("IsWow64Process not found\n");
return FALSE;
}
GetNativeSystemInfo(&si);
if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) {
printf("32-bit OS\n");
return FALSE;
}
handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
if (handle != NULL) {
printf("OpenProcess success\n");
pIsWow64Process(handle, &wow64);
CloseHandle(handle);
}
return !wow64;
}
int main(int argc, char *argv[])
{
HANDLE hPipe;
char buf[MAX_PATH];
ULONG pid;
pipe_request req;
pipe_reply repl;
DWORD read, len;
BOOL is64 = FALSE;
char *s;
if (argc < 2) {
printf("usage: cygpty <master-ctl pipe name>\n"
"e.g. cygpty \\cygwin-c5e39b7a9d22bafb-pty3-master-ctl\n");
return 1;
}
sprintf(buf, "\\\\.\\pipe%s", argv[1]);
printf("Pipe name: %s\n", buf);
hPipe = CreateFile(buf, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, 0, NULL);
if (hPipe == INVALID_HANDLE_VALUE) {
printf("Open pipe error: %ld\n", GetLastError());
return 1;
}
if (GetNamedPipeServerProcessId(hPipe, &pid)) {
is64 = Is64bitProcess(pid);
printf("Server pid: %ld, 64bit: %d\n", pid, is64);
}
CloseHandle(hPipe);
req.pid = GetCurrentProcessId();
if (CallNamedPipe(buf, &req, sizeof(req), &repl,
sizeof(repl), &read, 500)) {
DWORD error;
HANDLE from_master, to_master, to_master_cyg;
if (is64) {
if (read == sizeof(pipe_reply64_1)) {
from_master = (HANDLE) repl.r64_1.from_master;
to_master = (HANDLE) repl.r64_1.to_master;
to_master_cyg = INVALID_HANDLE_VALUE;
error = repl.r64_1.error;
} else if (read == sizeof(pipe_reply64_2)) {
from_master = (HANDLE) repl.r64_2.from_master;
to_master = (HANDLE) repl.r64_2.to_master;
to_master_cyg = (HANDLE) repl.r64_2.to_master_cyg;
error = repl.r64_2.error;
} else {
printf("Reply size error: %ld\n", read);
}
} else {
if (read == sizeof(pipe_reply32_1)) {
from_master = (HANDLE) repl.r32_1.from_master;
to_master = (HANDLE) repl.r32_1.to_master;
to_master_cyg = INVALID_HANDLE_VALUE;
error = repl.r32_1.error;
} else if (read == sizeof(pipe_reply32_2)) {
from_master = (HANDLE) repl.r32_2.from_master;
to_master = (HANDLE) repl.r32_2.to_master;
to_master_cyg = (HANDLE) repl.r32_2.to_master_cyg;
error = repl.r32_2.error;
} else {
printf("Reply size error: %ld\n", read);
}
}
printf("in: %p, out: %p, out2: %p err: %ld, read: %ld\n",
from_master, to_master, to_master_cyg,
error, read);
s = "\x1b[31mHello \x1b[32mWorld!\x1b[m\n";
len = strlen(s);
if (WriteFile(to_master, s, len, &read, NULL)) {
printf("%ld bytes written.\n", read);
} else {
printf("WriteFile error: %ld\n", GetLastError());
}
CloseHandle(from_master);
CloseHandle(to_master);
if (to_master_cyg != INVALID_HANDLE_VALUE) {
CloseHandle(to_master_cyg);
}
} else {
printf("CallNamedPipe error: %ld\n", GetLastError());
return 1;
}
return 0;
}
#ifndef UNICODE
#define UNICODE
#endif
#define _WIN32_WINNT 0x0600
#include <windows.h>
#include <stdio.h>
#include <string.h>
#define NT_SUCCESS(x) ((x) >= 0)
#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004
#define SystemExtendedHandleInformation 64
#define ObjectBasicInformation 0
#define ObjectNameInformation 1
#define ObjectTypeInformation 2
typedef NTSTATUS (NTAPI *_NtQuerySystemInformation)(
ULONG SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX
{
PVOID Object;
HANDLE UniqueProcessId;
HANDLE HandleValue;
ULONG GrantedAccess;
USHORT CreatorBackTraceIndex;
USHORT ObjectTypeIndex;
ULONG HandleAttributes;
ULONG Reserved;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX;
typedef struct _SYSTEM_HANDLE_INFORMATION_EX
{
ULONG_PTR NumberOfHandles;
ULONG_PTR Reserved;
SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[1];
} SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;
#define is_wprefix(s, prefix) \
(wcsncmp((s), (prefix), sizeof(prefix) / sizeof(WCHAR) - 1) == 0)
PVOID GetLibraryProcAddress(PSTR LibraryName, PSTR ProcName)
{
return GetProcAddress(GetModuleHandleA(LibraryName), ProcName);
}
int wmain(int argc, WCHAR *argv[])
{
_NtQuerySystemInformation NtQuerySystemInformation =
GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation");
NTSTATUS status;
PSYSTEM_HANDLE_INFORMATION_EX handleInfo;
ULONG handleInfoSize = 0x10000;
ULONG pid;
ULONG i;
int size = sizeof(FILE_NAME_INFO) + sizeof(WCHAR) * MAX_PATH;
FILE_NAME_INFO *nameinfo;
HANDLE from_master = INVALID_HANDLE_VALUE;
HANDLE to_master = INVALID_HANDLE_VALUE;
pid = GetCurrentProcessId();
handleInfo = (PSYSTEM_HANDLE_INFORMATION_EX)malloc(handleInfoSize);
if (handleInfo == NULL) {
return 1;
}
/* NtQuerySystemInformation won't give us the correct buffer size,
so we guess by doubling the buffer size. */
while ((status = NtQuerySystemInformation(
SystemExtendedHandleInformation,
handleInfo,
handleInfoSize,
NULL
)) == STATUS_INFO_LENGTH_MISMATCH)
{
PSYSTEM_HANDLE_INFORMATION_EX handleInfoTmp;
handleInfoSize *= 2;
handleInfoTmp =
(PSYSTEM_HANDLE_INFORMATION_EX)realloc(handleInfo, handleInfoSize);
if (handleInfoTmp == NULL) {
free(handleInfo);
return 1;
}
handleInfo = handleInfoTmp;
}
/* NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH. */
if (!NT_SUCCESS(status))
{
printf("NtQuerySystemInformation failed!\n");
free(handleInfo);
return 1;
}
nameinfo = malloc(size);
if (nameinfo == NULL) {
free(handleInfo);
return 1;
}
for (i = 0; i < handleInfo->NumberOfHandles; i++)
{
SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handle = handleInfo->Handles[i];
WCHAR *p = nameinfo->FileName;
/* Check if this handle belongs to the PID the user specified. */
if (handle.UniqueProcessId != (HANDLE)pid)
continue;
if (GetFileType(handle.HandleValue) != FILE_TYPE_PIPE)
continue;
if (!GetFileInformationByHandleEx(handle.HandleValue,
FileNameInfo, nameinfo, size))
continue;
nameinfo->FileName[nameinfo->FileNameLength / sizeof(WCHAR)] = L'\0';
printf("[%p] %S\n", handle.HandleValue, nameinfo->FileName);
if (is_wprefix(p, L"\\cygwin-")) { /* Cygwin */
p += 8;
} else if (is_wprefix(p, L"\\msys-")) { /* MSYS and MSYS2 */
p += 6;
} else {
p = NULL;
}
if (p != NULL) {
while (*p && isxdigit(*p)) /* Skip 16-digit hexadecimal. */
++p;
if (is_wprefix(p, L"-pty")) {
p += 4;
} else {
p = NULL;
}
}
if (p != NULL) {
while (*p && isdigit(*p)) /* Skip pty number. */
++p;
if (wcscmp(p, L"-from-master") == 0) {
from_master = handle.HandleValue;
} else if (wcscmp(p, L"-to-master") == 0) {
to_master = handle.HandleValue;
}
}
}
printf("from_master: %p, to_master: %p\n", from_master, to_master);
free(nameinfo);
free(handleInfo);
fflush(stdout);
if (to_master != INVALID_HANDLE_VALUE) {
DWORD read;
char *s = "\x1b[31mHello \x1b[32mWorld!\x1b[m\n";
int len = strlen(s);
if (WriteFile(to_master, s, len, &read, NULL)) {
printf("%ld bytes written.\n", read);
} else {
printf("WriteFile error: %ld\n", GetLastError());
}
}
return 0;
}
#ifndef UNICODE
#define UNICODE
#endif
#define _WIN32_WINNT 0x0600
#include <windows.h>
#include <stdio.h>
#include <string.h>
#define NT_SUCCESS(x) ((x) >= 0)
#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004
#define SystemExtendedHandleInformation 64
#define ObjectBasicInformation 0
#define ObjectNameInformation 1
#define ObjectTypeInformation 2
typedef NTSTATUS (NTAPI *_NtQuerySystemInformation)(
ULONG SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
typedef NTSTATUS (NTAPI *_NtQueryObject)(
HANDLE ObjectHandle,
ULONG ObjectInformationClass,
PVOID ObjectInformation,
ULONG ObjectInformationLength,
PULONG ReturnLength
);
typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX
{
PVOID Object;
HANDLE UniqueProcessId;
HANDLE HandleValue;
ULONG GrantedAccess;
USHORT CreatorBackTraceIndex;
USHORT ObjectTypeIndex;
ULONG HandleAttributes;
ULONG Reserved;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX;
typedef struct _SYSTEM_HANDLE_INFORMATION_EX
{
ULONG_PTR NumberOfHandles;
ULONG_PTR Reserved;
SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[1];
} SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;
typedef enum _POOL_TYPE
{
NonPagedPool,
PagedPool,
NonPagedPoolMustSucceed,
DontUseThisType,
NonPagedPoolCacheAligned,
PagedPoolCacheAligned,
NonPagedPoolCacheAlignedMustS
} POOL_TYPE, *PPOOL_TYPE;
typedef struct _OBJECT_TYPE_INFORMATION
{
UNICODE_STRING Name;
ULONG TotalNumberOfObjects;
ULONG TotalNumberOfHandles;
ULONG TotalPagedPoolUsage;
ULONG TotalNonPagedPoolUsage;
ULONG TotalNamePoolUsage;
ULONG TotalHandleTableUsage;
ULONG HighWaterNumberOfObjects;
ULONG HighWaterNumberOfHandles;
ULONG HighWaterPagedPoolUsage;
ULONG HighWaterNonPagedPoolUsage;
ULONG HighWaterNamePoolUsage;
ULONG HighWaterHandleTableUsage;
ULONG InvalidAttributes;
GENERIC_MAPPING GenericMapping;
ULONG ValidAccess;
BOOLEAN SecurityRequired;
BOOLEAN MaintainHandleCount;
USHORT MaintainTypeList;
POOL_TYPE PoolType;
ULONG PagedPoolUsage;
ULONG NonPagedPoolUsage;
} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
#define is_wprefix(s, prefix) \
(wcsncmp((s), (prefix), sizeof(prefix) / sizeof(WCHAR) - 1) == 0)
PVOID GetLibraryProcAddress(PSTR LibraryName, PSTR ProcName)
{
return GetProcAddress(GetModuleHandleA(LibraryName), ProcName);
}
/* return: 0: error
* 1: from_master found
* 2: to_master found */
int GetCygptyIoHandle(HANDLE handle,
HANDLE *from_master, HANDLE *to_master,
int *ptynum)
{
WCHAR buf[sizeof(FILE_NAME_INFO) / sizeof(WCHAR) + MAX_PATH];
FILE_NAME_INFO *nameinfo = (FILE_NAME_INFO*) buf;
WCHAR *p = nameinfo->FileName;
int num, ret = 0;
if (!GetFileInformationByHandleEx(handle,
FileNameInfo, nameinfo, sizeof(buf)))
return 0;
nameinfo->FileName[nameinfo->FileNameLength / sizeof(WCHAR)] = L'\0';
printf("[%p] Pipe: %S\n", handle, nameinfo->FileName);
if (is_wprefix(p, L"\\cygwin-")) { /* Cygwin */
p += 8;
} else if (is_wprefix(p, L"\\msys-")) { /* MSYS and MSYS2 */
p += 6;
} else {
return 0;
}
while (*p && isxdigit(*p)) /* Skip 16-digit hexadecimal. */
++p;
if (is_wprefix(p, L"-pty")) {
p += 4;
} else {
return 0;
}
num = (int) wcstol(p, &p, 10); /* pty number */
if (wcscmp(p, L"-from-master") == 0) {
if (from_master != NULL) {
*from_master = handle;
}
ret = 1;
} else if (wcscmp(p, L"-to-master") == 0) {
if (to_master != NULL) {
*to_master = handle;
}
ret = 2;
} else {
return 0;
}
if (ptynum != NULL) {
*ptynum = num;
}
return ret;
}
/* Get handle for synchronization objects. */
int GetCygptySyncHandle(HANDLE handle,
HANDLE *input_mutex, HANDLE *output_mutex,
HANDLE *input_avail, HANDLE *slave_alive,
int *ptynum)
{
_NtQueryObject NtQueryObject =
GetLibraryProcAddress("ntdll.dll", "NtQueryObject");
POBJECT_TYPE_INFORMATION objectTypeInfo = NULL;
PUNICODE_STRING objectNameInfo = NULL;
ULONG returnLength;
int num, ret = 0;
int len, size;
enum { Mutant, Event } handleType;
/* Query the object type. */
size = 0x1000;
objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(size);
if (!NT_SUCCESS(NtQueryObject(
handle,
ObjectTypeInformation,
objectTypeInfo,
size,
NULL)))
{
printf("[%p] Error!\n", handle);
goto end;
}
len = objectTypeInfo->Name.Length / sizeof(WCHAR);
if (len == 5
&& wcsncmp(objectTypeInfo->Name.Buffer, L"Event", len) == 0) {
handleType = Event;
} else if (len == 6
&& wcsncmp(objectTypeInfo->Name.Buffer, L"Mutant", len) == 0) {
handleType = Mutant;
} else {
goto end;
}
/* Query the object name. */
size = 0x1000;
objectNameInfo = (PUNICODE_STRING)malloc(size);
if (!NT_SUCCESS(NtQueryObject(
handle,
ObjectNameInformation,
objectNameInfo,
size,
&returnLength)))
{
/* We have the type name, so just display that. */
printf(
"[%p] %.*S: (could not get name)\n",
handle,
objectTypeInfo->Name.Length / 2,
objectTypeInfo->Name.Buffer
);
goto end;
}
/* Print the information! */
if (objectNameInfo->Length)
{
WCHAR cygid[20];
WCHAR name[20];
/* The object has a name. */
printf(
"[%p] %.*S: %.*S\n",
handle,
objectTypeInfo->Name.Length / 2,
objectTypeInfo->Name.Buffer,
objectNameInfo->Length / 2,
objectNameInfo->Buffer
);
if (swscanf(objectNameInfo->Buffer,
L"\\BaseNamedObjects\\cygwin%*16[^-]-%16[0-9a-f]\\cygtty.%16[a-z._]%d",
cygid, name, &num) != 3
&& swscanf(objectNameInfo->Buffer,
L"\\BaseNamedObjects\\msys-%*16[^-]-%16[0-9a-f]\\cygtty.%16[a-z._]%d",
cygid, name, &num) != 3) {
ret = 0;
goto end;
}
printf("num=%d, %S, %S\n", num, cygid, name);
if (handleType == Mutant) {
if (wcscmp(name, L"input.mutex.") == 0) {
if (input_mutex != NULL) {
*input_mutex = handle;
}
ret = 1;
} else if (wcscmp(name, L"output.mutex.") == 0) {
if (output_mutex != NULL) {
*output_mutex = handle;
}
ret = 2;
}
} else if (handleType == Event) {
if (wcscmp(name, L"input.avail.") == 0) {
if (input_avail != NULL) {
*input_avail = handle;
}
ret = 3;
} else if (wcscmp(name, L"slave_alive.") == 0) {
if (slave_alive != NULL) {
*slave_alive = handle;
}
ret = 4;
}
}
if (ptynum != NULL) {
*ptynum = num;
}
}
else
{
/* Print something else. */
printf(
"[%p] %.*S: (unnamed)\n",
handle,
objectTypeInfo->Name.Length / 2,
objectTypeInfo->Name.Buffer
);
ret = 0;
}
end:
free(objectTypeInfo);
free(objectNameInfo);
return ret;
}
BOOL GetCygptyHandles(
HANDLE *from_master, HANDLE *to_master,
HANDLE *input_mutex, HANDLE *output_mutex,
HANDLE *input_avail, HANDLE *slave_alive,
int *ptynum)
{
_NtQuerySystemInformation NtQuerySystemInformation =
GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation");
NTSTATUS status;
PSYSTEM_HANDLE_INFORMATION_EX handleInfo;
ULONG handleInfoSize = 0x10000;
ULONG pid;
ULONG i;
BOOL ret = TRUE;
int n, r;
if (from_master == NULL || to_master == NULL
|| input_mutex == NULL || output_mutex == NULL
|| input_avail == NULL || slave_alive == NULL
|| ptynum == NULL) {
return FALSE;
}
*from_master = INVALID_HANDLE_VALUE;
*to_master = INVALID_HANDLE_VALUE;
*input_mutex = INVALID_HANDLE_VALUE;
*output_mutex = INVALID_HANDLE_VALUE;
*input_avail = INVALID_HANDLE_VALUE;
*slave_alive = INVALID_HANDLE_VALUE;
*ptynum = -1;
pid = GetCurrentProcessId();
handleInfo = (PSYSTEM_HANDLE_INFORMATION_EX)malloc(handleInfoSize);
if (handleInfo == NULL) {
return FALSE;
}
/* NtQuerySystemInformation won't give us the correct buffer size,
so we guess by doubling the buffer size. */
while ((status = NtQuerySystemInformation(
SystemExtendedHandleInformation,
handleInfo,
handleInfoSize,
NULL
)) == STATUS_INFO_LENGTH_MISMATCH)
{
PSYSTEM_HANDLE_INFORMATION_EX handleInfoTmp;
handleInfoSize *= 2;
handleInfoTmp =
(PSYSTEM_HANDLE_INFORMATION_EX)realloc(handleInfo, handleInfoSize);
if (handleInfoTmp == NULL) {
ret = FALSE;
goto end;
}
handleInfo = handleInfoTmp;
}
/* NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH. */
if (!NT_SUCCESS(status))
{
printf("NtQuerySystemInformation failed!\n");
ret = FALSE;
goto end;
}
for (i = 0; i < handleInfo->NumberOfHandles; i++)
{
SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handle = handleInfo->Handles[i];
/* Check if this handle belongs to the PID the user specified. */
if (handle.UniqueProcessId != (HANDLE)pid)
continue;
if (GetFileType(handle.HandleValue) == FILE_TYPE_PIPE) {
r = GetCygptyIoHandle(handle.HandleValue,
from_master, to_master, &n);
} else {
r = GetCygptySyncHandle(handle.HandleValue,
input_mutex, output_mutex,
input_avail, slave_alive, &n);
}
if (r > 0) {
if (*ptynum == -1) {
*ptynum = n;
} else if (*ptynum != n) {
ret = FALSE;
goto end;
}
}
}
if (*from_master == INVALID_HANDLE_VALUE
|| *to_master == INVALID_HANDLE_VALUE
|| *input_mutex == INVALID_HANDLE_VALUE
|| *output_mutex == INVALID_HANDLE_VALUE
|| *input_avail == INVALID_HANDLE_VALUE
|| *slave_alive == INVALID_HANDLE_VALUE
|| *ptynum == -1) {
ret = FALSE;
}
end:
free(handleInfo);
return ret;
}
int wmain(int argc, WCHAR *argv[])
{
int ptynum;
HANDLE from_master = INVALID_HANDLE_VALUE;
HANDLE to_master = INVALID_HANDLE_VALUE;
HANDLE input_mutex = INVALID_HANDLE_VALUE;
HANDLE output_mutex = INVALID_HANDLE_VALUE;
HANDLE input_avail = INVALID_HANDLE_VALUE;
HANDLE slave_alive = INVALID_HANDLE_VALUE;
BOOL ret;
ret = GetCygptyHandles(
&from_master, &to_master,
&input_mutex, &output_mutex,
&input_avail, &slave_alive,
&ptynum);
if (ret) {
DWORD num;
char *s = "\x1b[31mHello \x1b[32mWorld!\x1b[m\nType some key, then type Enter.\n";
int len = strlen(s);
printf("pty%d, from_master: %p, to_master: %p\n", ptynum, from_master, to_master);
printf("input_mutex: %p, output_mutex: %p, input_avail: %p, slave_alive: %p\n", input_mutex, output_mutex, input_avail, slave_alive);
fflush(stdout);
if (WaitForSingleObject(output_mutex, 500) == WAIT_OBJECT_0) {
if (WriteFile(to_master, s, len, &num, NULL)) {
printf("%ld bytes written.\n", num);
} else {
printf("WriteFile error: %ld\n", GetLastError());
}
ReleaseMutex(output_mutex);
} else {
printf("Cannot acquire output mutex.\n");
}
if (WaitForSingleObject(input_avail, 5 * 1000) == WAIT_OBJECT_0) {
if (WaitForSingleObject(input_mutex, 500) == WAIT_OBJECT_0) {
char buf[10];
if (ReadFile(from_master, buf, 10, &num, NULL)) {
int i;
for (i = 0; i < num; i++) {
printf("0x%02x ", buf[i]);
}
printf("\n");
} else {
printf("ReadFile error: %ld\n", GetLastError());
}
ReleaseMutex(input_mutex);
} else {
printf("Cannot acquire input mutex.\n");
}
} else {
printf("Input timeout.\n");
}
} else {
printf("Cygwin pty not found\n");
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment