Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F625695
Win32PtyProcess.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
4 KB
Referenced Files
None
Subscribers
None
Win32PtyProcess.cpp
View Options
#include
<windows.h>
#include
"Win32PtyProcess.h"
#include
<deque>
#include
<winpty.h>
#include
<QDir>
#include
<QMutex>
namespace
{
class
OutputReaderThread
:
public
QThread
{
friend
class
::
Win32PtyProcess
;
private
:
HANDLE
handle
;
std
::
deque
<
char
>
result1
;
std
::
vector
<
char
>
result2
;
protected
:
void
run
();
public
:
void
start
(
HANDLE
hOutput
);
std
::
vector
<
char
>
const
*
result
()
const
{
return
&
result2
;
}
};
void
OutputReaderThread::run
()
{
char
buf
[
1024
];
while
(
1
)
{
if
(
isInterruptionRequested
())
break
;
DWORD
amount
=
0
;
BOOL
ret
=
ReadFile
(
handle
,
buf
,
sizeof
(
buf
),
&
amount
,
nullptr
);
if
(
!
ret
||
amount
==
0
)
{
break
;
}
result1
.
insert
(
result1
.
end
(),
buf
,
buf
+
amount
);
result2
.
insert
(
result2
.
end
(),
buf
,
buf
+
amount
);
}
}
void
OutputReaderThread::start
(
HANDLE
hOutput
)
{
result2
.
clear
();
handle
=
hOutput
;
QThread
::
start
();
}
}
// namespace
// Win32PtyProcess
struct
Win32PtyProcess
::
Private
{
QMutex
mutex
;
QString
command
;
OutputReaderThread
th_output_reader
;
HANDLE
hProcess
=
INVALID_HANDLE_VALUE
;
HANDLE
hOutput
=
INVALID_HANDLE_VALUE
;
HANDLE
hInput
=
INVALID_HANDLE_VALUE
;
DWORD
exit_code
=
0
;
};
Win32PtyProcess
::
Win32PtyProcess
()
:
m
(
new
Private
)
{
}
Win32PtyProcess
::~
Win32PtyProcess
()
{
delete
m
;
}
bool
Win32PtyProcess
::
isRunning
()
const
{
return
QThread
::
isRunning
();
}
QString
Win32PtyProcess
::
getProgram
(
const
QString
&
cmdline
)
{
ushort
const
*
begin
=
cmdline
.
utf16
();
ushort
const
*
end
=
begin
+
cmdline
.
size
();
ushort
const
*
ptr
=
begin
;
bool
quote
=
0
;
while
(
1
)
{
ushort
c
=
0
;
if
(
ptr
<
end
)
{
c
=
*
ptr
;
}
if
(
c
==
'\"'
)
{
if
(
quote
)
{
quote
=
false
;
}
else
{
quote
=
true
;
}
ptr
++
;
}
else
if
(
quote
&&
c
!=
0
)
{
ptr
++
;
}
else
if
(
QChar
(
c
).
isSpace
()
||
c
==
0
)
{
break
;
}
else
{
ptr
++
;
}
}
ushort
const
*
left
=
begin
;
ushort
const
*
right
=
ptr
;
if
(
left
+
1
<
right
)
{
if
(
left
[
0
]
==
'\"'
&&
right
[
-1
]
==
'\"'
)
{
left
++
;
right
--
;
}
}
return
QString
::
fromUtf16
(
left
,
right
-
left
);
}
void
Win32PtyProcess
::
run
()
{
QString
program
;
program
=
getProgram
(
m
->
command
);
QDir
::
setCurrent
(
change_dir
);
winpty_config_t
*
agent_cfg
=
winpty_config_new
(
WINPTY_FLAG_PLAIN_OUTPUT
,
nullptr
);
winpty_t
*
pty
=
winpty_open
(
agent_cfg
,
nullptr
);
winpty_config_free
(
agent_cfg
);
m
->
hInput
=
CreateFileW
(
winpty_conin_name
(
pty
),
GENERIC_WRITE
,
0
,
nullptr
,
OPEN_EXISTING
,
0
,
nullptr
);
m
->
hOutput
=
CreateFileW
(
winpty_conout_name
(
pty
),
GENERIC_READ
,
0
,
nullptr
,
OPEN_EXISTING
,
0
,
nullptr
);
m
->
th_output_reader
.
start
(
m
->
hOutput
);
winpty_spawn_config_t
*
spawn_cfg
=
winpty_spawn_config_new
(
WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN
,
(
wchar_t
const
*
)
program
.
utf16
(),
(
wchar_t
const
*
)
m
->
command
.
utf16
(),
nullptr
,
nullptr
,
nullptr
);
BOOL
spawnSuccess
=
winpty_spawn
(
pty
,
spawn_cfg
,
&
m
->
hProcess
,
nullptr
,
nullptr
,
nullptr
);
if
(
spawnSuccess
)
{
while
(
1
)
{
if
(
isInterruptionRequested
())
break
;
GetExitCodeProcess
(
m
->
hProcess
,
&
m
->
exit_code
);
if
(
m
->
exit_code
==
STILL_ACTIVE
)
{
// running
msleep
(
1
);
}
else
{
break
;
}
}
}
winpty_free
(
pty
);
CloseHandle
(
m
->
hInput
);
CloseHandle
(
m
->
hOutput
);
CloseHandle
(
m
->
hProcess
);
m
->
hInput
=
INVALID_HANDLE_VALUE
;
m
->
hOutput
=
INVALID_HANDLE_VALUE
;
m
->
hProcess
=
INVALID_HANDLE_VALUE
;
emit
completed
();
}
int
Win32PtyProcess
::
readOutput
(
char
*
dstptr
,
int
maxlen
)
{
int
len
=
m
->
th_output_reader
.
result1
.
size
();
if
(
len
>
maxlen
)
{
len
=
maxlen
;
}
if
(
len
>
0
)
{
auto
begin
=
m
->
th_output_reader
.
result1
.
begin
();
std
::
copy
(
begin
,
begin
+
len
,
dstptr
);
m
->
th_output_reader
.
result1
.
erase
(
begin
,
begin
+
len
);
}
return
len
;
}
void
Win32PtyProcess
::
writeInput
(
const
char
*
ptr
,
int
len
)
{
char
const
*
begin
=
ptr
;
char
const
*
end
=
begin
+
len
;
char
const
*
left
=
begin
;
char
const
*
right
=
begin
;
while
(
1
)
{
int
c
=
-1
;
if
(
right
<
end
)
{
c
=
*
right
&
0xff
;
}
if
(
c
==
'\r'
||
c
==
'\n'
||
c
<
0
)
{
if
(
left
<
right
)
{
DWORD
written
;
WriteFile
(
m
->
hInput
,
left
,
right
-
left
,
&
written
,
0
);
}
if
(
c
<
0
)
break
;
right
++
;
if
(
c
==
'\r'
)
{
if
(
*
right
==
'\n'
)
{
right
++
;
}
c
=
'\r'
;
}
else
if
(
c
==
'\n'
)
{
c
=
'\r'
;
}
else
{
c
=
-1
;
}
if
(
c
>=
0
)
{
DWORD
written
;
WriteFile
(
m
->
hInput
,
&
c
,
1
,
&
written
,
0
);
}
left
=
right
;
}
else
{
right
++
;
}
}
}
void
Win32PtyProcess
::
start
(
const
QString
&
cmdline
)
{
if
(
isRunning
())
return
;
m
->
command
=
cmdline
;
QThread
::
start
();
}
bool
Win32PtyProcess
::
wait
(
unsigned
long
time
)
{
return
QThread
::
wait
(
time
);
}
void
Win32PtyProcess
::
stop
()
{
m
->
th_output_reader
.
requestInterruption
();
requestInterruption
();
m
->
th_output_reader
.
wait
();
wait
();
}
const
std
::
vector
<
char
>
*
Win32PtyProcess
::
result
()
const
{
return
m
->
th_output_reader
.
result
();
}
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Sat, Nov 14, 11:47 PM (1 d, 13 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
127491
Default Alt Text
Win32PtyProcess.cpp (4 KB)
Attached To
Mode
R77 Guitar
Attached
Detach File
Event Timeline