| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- // Copyright 2019 Espressif Systems (Shanghai) PTE LTD
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at",
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License
- #define CMDLINERUNNER_EXPORTS
- #include <windows.h>
- #include <tchar.h>
- #include <strsafe.h>
- #include "cmdlinerunner.h"
- #define LINESIZE 1024
- #ifdef WITH_DEBUG
- #include <stdio.h>
- #define DEBUGV(...) do { fprintf(stderr, __VA_ARG__); } while(0)
- #else
- #define DEBUGV(...)
- #endif
- struct proc_instance_s {
- PROCESS_INFORMATION child_process;
- HANDLE pipe_server_handle;
- HANDLE pipe_client_handle;
- };
- #ifdef WITH_DEBUG
- static void print_last_error(void)
- {
- DWORD dw;
- TCHAR errmsg[LINESIZE];
- dw = GetLastError();
- FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- errmsg, sizeof(errmsg) - 1, NULL );
- DEBUGV("error %d: %s\n", dw, errmsg);
- }
- #define PRINT_LAST_ERROR() print_last_error()
- #else
- #define PRINT_LAST_ERROR()
- #endif
- static proc_instance_t *proc_instance_allocate(void)
- {
- return (proc_instance_t*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(proc_instance_t));
- }
- static void proc_instance_free(proc_instance_t *instance)
- {
- if (instance->pipe_server_handle) {
- CloseHandle(instance->pipe_server_handle);
- }
- if (instance->pipe_client_handle) {
- CloseHandle(instance->pipe_client_handle);
- }
- if (instance->child_process.hProcess) {
- TerminateProcess(instance->child_process.hProcess, 1);
- CloseHandle(instance->child_process.hProcess);
- CloseHandle(instance->child_process.hThread);
- }
- HeapFree(GetProcessHeap(), 0, instance);
- }
- void proc_end(proc_instance_t *inst)
- {
- if (inst == NULL) {
- return;
- }
- proc_instance_free(inst);
- }
- CMDLINERUNNER_API proc_instance_t * proc_start(LPCTSTR cmdline, LPCTSTR workdir)
- {
- proc_instance_t *inst = proc_instance_allocate();
- if (inst == NULL) {
- return NULL;
- }
- SECURITY_ATTRIBUTES sec_attr = {
- .nLength = sizeof(SECURITY_ATTRIBUTES),
- .bInheritHandle = TRUE,
- .lpSecurityDescriptor = NULL
- };
- LPCTSTR pipename = TEXT("\\\\.\\pipe\\cmdlinerunner_pipe");
- inst->pipe_server_handle = CreateNamedPipe(pipename, PIPE_ACCESS_DUPLEX,
- PIPE_TYPE_BYTE | PIPE_WAIT, 1, 1024 * 16, 1024 * 16,
- NMPWAIT_WAIT_FOREVER, &sec_attr);
- if (inst->pipe_server_handle == INVALID_HANDLE_VALUE) {
- DEBUGV("inst->pipe_server_handle == INVALID_HANDLE_VALUE\n");
- goto error;
- }
- inst->pipe_client_handle = CreateFile(pipename, GENERIC_WRITE | GENERIC_READ,
- 0, &sec_attr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (inst->pipe_client_handle == INVALID_HANDLE_VALUE) {
- DEBUGV("inst->pipe_client_handle == INVALID_HANDLE_VALUE\n");
- goto error;
- }
- DWORD new_mode = PIPE_READMODE_BYTE | PIPE_NOWAIT;
- if (!SetNamedPipeHandleState(inst->pipe_server_handle, &new_mode, NULL,
- NULL)) {
- DEBUGV("SetNamedPipeHandleState failed\n");
- goto error;
- }
- if (!SetHandleInformation(inst->pipe_server_handle, HANDLE_FLAG_INHERIT, 0)) {
- DEBUGV("SetHandleInformation failed\n");
- goto error;
- }
- if (!SetHandleInformation(inst->pipe_client_handle, HANDLE_FLAG_INHERIT,
- HANDLE_FLAG_INHERIT)) {
- DEBUGV("SetHandleInformation failed\n");
- goto error;
- }
- STARTUPINFO siStartInfo = {
- .cb = sizeof(STARTUPINFO),
- .hStdError = inst->pipe_client_handle,
- .hStdOutput = inst->pipe_client_handle,
- .hStdInput = inst->pipe_client_handle,
- .dwFlags = STARTF_USESTDHANDLES
- };
- size_t workdir_len = 0;
- StringCbLength(workdir, STRSAFE_MAX_CCH * sizeof(TCHAR), &workdir_len);
- if (workdir_len == 0) {
- workdir = NULL;
- }
- TCHAR cmdline_tmp[LINESIZE];
- StringCbCopy(cmdline_tmp, sizeof(cmdline_tmp), cmdline);
- if (!CreateProcess(NULL, cmdline_tmp,
- NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, workdir, &siStartInfo,
- &inst->child_process)) {
- DEBUGV("CreateProcess failed\n");
- goto error;
- }
- return inst;
- error:
- PRINT_LAST_ERROR();
- proc_instance_free(inst);
- return NULL;
- }
- int proc_get_exit_code(proc_instance_t *inst)
- {
- DWORD result;
- if (!GetExitCodeProcess(inst->child_process.hProcess, &result)) {
- return -2;
- }
- if (result == STILL_ACTIVE) {
- return -1;
- }
- return (int) result;
- }
- DWORD proc_get_output(proc_instance_t *inst, LPSTR dest, DWORD sz)
- {
- DWORD read_bytes;
- BOOL res = ReadFile(inst->pipe_server_handle, dest,
- sz - 1, &read_bytes, NULL);
- if (!res) {
- if (GetLastError() == ERROR_NO_DATA) {
- return 0;
- } else {
- PRINT_LAST_ERROR();
- return 0;
- }
- }
- dest[read_bytes] = 0;
- return read_bytes;
- }
- BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved )
- {
- return TRUE;
- }
|