예제 #1
0
파일: win.c 프로젝트: 0xe/win-sshd
int win_makedir(char *path, char **emsg) {
    if (!CreateDirectory(path, NULL)) {
		int ret, ecode = GetLastError();

		*emsg = get_error_msg(ecode);
		switch (ecode) {
		case ERROR_FILE_NOT_FOUND:
		case ERROR_PATH_NOT_FOUND: ret = FX_NO_SUCH_FILE; break;
		case ERROR_ACCESS_DENIED:  ret = FX_PERMISSION_DENIED; break;
		case ERROR_ALREADY_EXISTS: ret = FX_FAILURE; break;
		default: ret = FX_FAILURE;
		}
		return ret;
    }
    *emsg = NULL;
    return FX_OK;
}
예제 #2
0
파일: win.c 프로젝트: 0xe/win-sshd
int win_createfile(char *path, unsigned int flags, void **handle, char **emsg) {
    DWORD access = 0, shared = 0, dispo = 0;
    HANDLE fd;
    int len = (int)strlen(path);

    if (flags & FXF_READ)  {
		access |= GENERIC_READ;
    }
    if (flags & FXF_WRITE) {
		access |= GENERIC_WRITE;
    }
    if (flags & FXF_APPEND) {
		access |= FILE_APPEND_DATA;
    }
    if (flags & FXF_CREAT) {
		dispo |= CREATE_ALWAYS;
    }
    if (!(flags & FXF_CREAT) && (flags & FXF_TRUNC)) {
		dispo |= TRUNCATE_EXISTING;
    }
    if (flags & FXF_EXCL)  {
		shared = 0;
    }
    else {
		shared = FILE_SHARE_READ | FILE_SHARE_WRITE;
    }

    fd = CreateFile(path, access, shared, NULL, dispo, FILE_ATTRIBUTE_NORMAL, NULL);
    if (fd == INVALID_HANDLE_VALUE) {
		int ret, ecode = GetLastError();

		*emsg = get_error_msg(ecode);
		switch (ecode) {
		case ERROR_FILE_NOT_FOUND:
		case ERROR_PATH_NOT_FOUND: ret = FX_NO_SUCH_FILE; break;
		case ERROR_ACCESS_DENIED:  ret = FX_PERMISSION_DENIED; break;
		case ERROR_ALREADY_EXISTS: ret = FX_FAILURE; break;
		default: ret = FX_FAILURE;
		}
		return ret;
    }
    *handle = fd;
    return FX_OK;
}
예제 #3
0
void WatchWin32::watch(const std::string &dir, uint32_t filters, const Callback &callback){
	auto fnd = watchers.find(dir);
	if (fnd != watchers.end() && fnd->second.filter != filters){
		fnd->second.filter = filters;
		fnd->second.callback = callback;
		register_watch(fnd->second);
		return;
	}
	HANDLE handle = CreateFile(dir.c_str(), FILE_LIST_DIRECTORY,
		FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
		nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
		nullptr);
	if (handle == INVALID_HANDLE_VALUE){
		std::cerr << "lfw Error: failed to create handle for " << dir
			<< ": " << get_error_msg(GetLastError()) << std::endl;
		return;
	}
	auto it = watchers.emplace(std::make_pair(dir, WatchData{handle, dir, filters, callback}));
	register_watch(it.first->second);
}
예제 #4
0
// python function stop(channel)
static PyObject *py_stop_channel(PyObject *self, PyObject *args, PyObject *kwargs)
{
    char key[8];
    char *channel;
    int gpio;
    int allowed = -1;

    clear_error_msg();

    if (!PyArg_ParseTuple(args, "s", &channel))
        return NULL;

    if (!get_key(channel, key)) {
        PyErr_SetString(PyExc_ValueError, "Invalid PWM key or name.");
        return NULL;
    }

    // check to ensure gpio is one of the allowed pins
    // Not protecting the call as if the get_key() fails, we won't make it here
    get_gpio_number(channel, &gpio);

    // Check to see if GPIO is allowed on the hardware
    // A 1 means we're good to go
    allowed = gpio_allowed(gpio);
    if (allowed == -1) {
        char err[2000];
        snprintf(err, sizeof(err), "Error determining hardware. (%s)", get_error_msg());
        PyErr_SetString(PyExc_ValueError, err);
        return NULL;
    } else if (allowed == 0) {
        char err[2000];
        snprintf(err, sizeof(err), "GPIO %d not available on current Hardware", gpio);
        PyErr_SetString(PyExc_ValueError, err);
        return NULL;
    }

    softpwm_disable(key);

    Py_RETURN_NONE;
}
예제 #5
0
void display_db_error_msg(void) {
  Errors::display_error_msg(db_error);
  db_error = get_error_msg(Errors::error_no_error);
}
예제 #6
0
void update_last_error(void) {
  last_error = db_error;
  db_error = get_error_msg(Errors::error_no_error);
}
예제 #7
0
namespace DBase {

// TODO(Garcia): CONTINUE WORKING ON THIS DATABASE FILE.
static Errors::err_info db_error = get_error_msg(Errors::error_no_error);
static Errors::err_info last_error = get_error_msg(Errors::error_no_error);

void update_last_error(void) {
  last_error = db_error;
  db_error = get_error_msg(Errors::error_no_error);
}

// Table map used to store information of each database table.
std::unordered_map<std::string, Table&> table_map;

// Still needing to update this thing.
Table* add_table(Database& database, std::string password) {
  std::pair<std::string, Table&> stored_pair(password, database);
  table_map.insert(stored_pair);
  return NULL; // for now...
}

Database::Database(void) 
: containers()
, table_name("no name")
, directory_path(default_path + table_name)
{
}

Database::Database(std::string table_name) : Database() {
  this->table_name = table_name;
  directory_path = default_path + table_name;
}

Database::~Database(void) {
}

// Merges database to this one.
bool Database::merge(Database* database) {
  if(database == NULL) {
    db_error = last_error = Errors::get_error_msg(Errors::error_null_value);
    return false;
  }

  for(size_t i = 0; i < database->get_number_of_containers(); ++i) {
    _iter iter = std::find(containers.begin(),
                           containers.end(),
                           (*database)[i]);
    if(iter == containers.end()) {
      containers.push_back((*database)[i]);
    }
  }
  return true;
}

// Checks if database is a subset of this one.
bool Database::is_subset(Database* database) {
  return true;
}

/**
 * Saves the database into its own folder.
 * Still working on this!!!!
 */
bool Database::save_table(std::string name) {
  folder_create();
  if(db_error.code_number == Errors::error_path_not_found) {
    return false;
  }
  if(!containers.empty()) {
    std::ofstream file;
    serialization::ObjectStream temp_stream;
    for(int i = 0; i < containers.size(); ++i) {
      Container* container = &containers.at(i);
      file.open(directory_path + "/" + container->get_container_name() + ".txt"
              , std::fstream::in | std::fstream::out | std::fstream::trunc);
      if(file.is_open()) {
        container->serialize(temp_stream);
        temp_stream.write_to_file(file);
        file.close();
      }
    }
  }
  update_last_error();
  return true;
}

// Load up a database to this one. Will override everything on this database object.
bool Database::load_table(std::string name) {
  return true;
}

bool Database::folder_create(void) {
  _BOOL_ success = create_folder(directory_path.c_str(), NULL);
  if(success == 0) {
    _ERR_ err = _OBTAIN_LAST_ERROR;
    // These are windows api macros that must be changed later on for compatibility reasons.
    if(err == ERROR_ALREADY_EXISTS) {
      db_error = get_error_msg(Errors::error_folder_already_exists);
    } else if(err == ERROR_PATH_NOT_FOUND) {
      db_error = get_error_msg(Errors::error_path_not_found);
    }
  }
  return bool(success);
}

bool Database::change_database_name(std::string new_name) {
  if(table_name.compare(new_name) == STR_MATCH) {
    return false;
  }

  table_name = new_name;

  return true;
}

bool Database::add_container(Container* container) {
  bool is_unique = true;
  _iter iter = std::find(containers.begin(),
                        containers.end(),
                        *container);
  if(iter == containers.end()) {
    containers.push_back(*container);
  } else {
    is_unique = false;
  }
  return is_unique;
}

bool Database::remove_container(std::string container_name) {
  bool removed = false;
  Container temp(container_name);
  _iter iter = std::find(containers.begin(),
                         containers.end(),
                         temp);
  if(iter != containers.end()) {
    containers.erase(iter);
    removed = true;
  }
  return removed;
}

Container* Database::get_container(std::string container_name) {
  Container* container_ptr = NULL;
  for(size_t i = 0; i < containers.size(); ++i) {
    Container* cont = &containers.at(i);
    if(cont->get_container_name().compare(container_name) == STR_MATCH) {
      container_ptr = cont;
      break;
    }
  }
  return container_ptr;
}

Database Database::intersection(Database* database) {
  Database new_database;
  return new_database;
}

Database Database::clone(void) {
  return *this;
}

Column* Database::find_column(std::string column_name) {
  Column* container_ptr = new Column(column_name);

  for(size_t i = 0; i < containers.size(); ++i) {
    Container* container = &containers[i];
    for(size_t j = 0; j < container->get_size(); ++j) {
      Element* element = &(*container)[j];
      if(element->get_column_name().compare(column_name) == STR_MATCH) {
        container_ptr->insert_element(*element);
        break;
      }
    }
  }
  return container_ptr;
}

Column* Database::find_column(Column column) {
  return find_column(column.get_column_name());
}

std::string Database::display_all_containers() {
  std::string result = "";

  return result;
}

int Database::compare_to(const Database& _right) {
  if(containers.size() == _right.containers.size()) {
    return (_EQUAL);
  } else if(containers.size() > _right.containers.size()) {
    return (_GREATER);
  } else {
    return (_LESSER);
  }
}

bool Database::equals(const Database& _right) {
  bool is_equal = false;
  if(table_name.compare(_right.table_name) == STR_MATCH) {
    if(directory_path.compare(_right.directory_path) == STR_MATCH) {
      if(containers.size() == _right.containers.size()) {
        bool result = true;
        for(size_t i = 0; i < containers.size(); ++i) {
          Container& container = containers.at(i);
          std::vector<Container>& vec_containers = (std::vector<Container>)_right.containers;
          _iter iter = std::find(vec_containers.begin(),
                                 vec_containers.end(),
                                 container);
          if(iter == vec_containers.end()) {
            result = false;
            break;
          }
        }
        if(result) {
          is_equal = true;
        }
      }
    }
  }

  return is_equal;
}

const Database& Database::operator=(const Database& _right) {
  this->table_name = _right.table_name;
  this->directory_path = _right.directory_path;

  this->containers = _right.containers;
  return (*this);
}

void display_db_error_msg(void) {
  Errors::display_error_msg(db_error);
  db_error = get_error_msg(Errors::error_no_error);
}

void display_last_error(void) {
  Errors::display_error_msg(last_error);
}
} // Database nameapace 
예제 #8
0
파일: scanner.c 프로젝트: lgarsten/vpcc
void printDebug(int errorcode) {
	char *msg;
	msg = get_error_msg(errorcode);
	
	printf("D: %s, SYM: %s, Lahead: %s, LINENR: %d \n",msg, get_token_name(symbol), get_token_name(lookahead), lineNR);
}
예제 #9
0
파일: scanner.c 프로젝트: lgarsten/vpcc
void printError(int errorcode) {
	char *msg;
	msg = get_error_msg(errorcode);
	
	printf("Syntax error at: %d %s \n", lineNR, msg);
}
예제 #10
0
static VALUE oci8_make_exc(dvoid *errhp, sword status, ub4 type, OCIStmt *stmthp, const char *file, int line)
{
    VALUE exc;
    char errmsg[128];
    sb4 errcode = -1;
    VALUE msg;
    VALUE parse_error_offset = Qnil;
    VALUE sql = Qnil;
    int rv;
    int numarg = 1;

    switch (status) {
    case OCI_ERROR:
        exc = eOCIError;
        msg = get_error_msg(errhp, type, "Error", &errcode);
        numarg = 4;
        break;
    case OCI_SUCCESS_WITH_INFO:
        exc = eOCISuccessWithInfo;
        msg = get_error_msg(errhp, type, "Error", &errcode);
        numarg = 4;
        break;
    case OCI_NO_DATA:
        exc = eOCINoData;
        msg = get_error_msg(errhp, type, "No Data", &errcode);
        numarg = 4;
        break;
    case OCI_INVALID_HANDLE:
        exc = eOCIInvalidHandle;
        msg = rb_usascii_str_new_cstr("Invalid Handle");
        break;
    case OCI_NEED_DATA:
        exc = eOCINeedData;
        msg = rb_usascii_str_new_cstr("Need Data");
        break;
    case OCI_STILL_EXECUTING:
        exc = eOCIStillExecuting;
        msg = rb_usascii_str_new_cstr("Still Executing");
        break;
    case OCI_CONTINUE:
        exc = eOCIContinue;
        msg = rb_usascii_str_new_cstr("Continue");
        break;
    default:
        sprintf(errmsg, "Unknown error (%d)", status);
        exc = eOCIException;
        msg = rb_usascii_str_new_cstr(errmsg);
    }
    if (stmthp != NULL) {
        ub2 offset;
        text *text;
        ub4 size;

        rv = OCIAttrGet(stmthp, OCI_HTYPE_STMT, &offset, 0, OCI_ATTR_PARSE_ERROR_OFFSET, errhp);
        if (rv == OCI_SUCCESS) {
            parse_error_offset = INT2FIX(offset);
        }
        rv = OCIAttrGet(stmthp, OCI_HTYPE_STMT, &text, &size, OCI_ATTR_STATEMENT, errhp);
        if (rv == OCI_SUCCESS) {
            sql = rb_external_str_new_with_enc(TO_CHARPTR(text), size, oci8_encoding);
        }
    }
    exc = rb_funcall(exc, oci8_id_new, numarg, msg, INT2FIX(errcode), sql, parse_error_offset);
    return set_backtrace(exc, file, line);
}
예제 #11
0
// python function start(channel, duty_cycle, freq, polarity)
static PyObject *py_start_channel(PyObject *self, PyObject *args, PyObject *kwargs)
{
    char key[8];
    char *channel = NULL;
    float frequency = 2000.0;
    float duty_cycle = 0.0;
    int polarity = 0;
    int gpio;
    int allowed = -1;
    static char *kwlist[] = {"channel", "duty_cycle", "frequency", "polarity", NULL};

    clear_error_msg();

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ffi", kwlist, &channel, &duty_cycle, &frequency, &polarity)) {
        return NULL;
    }
    ASSRT(channel != NULL);

    if (!module_setup) {
        init_module();
    }

    if (!get_key(channel, key)) {
        PyErr_SetString(PyExc_ValueError, "Invalid SOFTPWM key or name.");
        return NULL;
    }

    // check to ensure gpio is one of the allowed pins
    // Not protecting the call as if the get_key() fails, we won't make it here
    get_gpio_number(channel, &gpio);

    // Check to see if GPIO is allowed on the hardware
    // A 1 means we're good to go
    allowed = gpio_allowed(gpio);
    if (allowed == -1) {
        char err[2000];
        snprintf(err, sizeof(err), "Error determining hardware. (%s)", get_error_msg());
        PyErr_SetString(PyExc_ValueError, err);
        return NULL;
    } else if (allowed == 0) {
        char err[2000];
        snprintf(err, sizeof(err), "GPIO %d not available on current Hardware", gpio);
        PyErr_SetString(PyExc_ValueError, err);
        return NULL;
    }

    if (duty_cycle < 0.0 || duty_cycle > 100.0) {
        PyErr_SetString(PyExc_ValueError, "duty_cycle must have a value from 0.0 to 100.0");
        return NULL;
    }

    if (frequency <= 0.0) {
        PyErr_SetString(PyExc_ValueError, "frequency must be greater than 0.0");
        return NULL;
    }

    if (polarity < 0 || polarity > 1) {
        PyErr_SetString(PyExc_ValueError, "polarity must be either 0 or 1");
        return NULL;
    }

    if (softpwm_start(key, duty_cycle, frequency, polarity) < 0) {
       printf("softpwm_start failed");
       char err[2000];
       snprintf(err, sizeof(err), "Error starting softpwm on pin %s (%s)", key, get_error_msg());
       PyErr_SetString(PyExc_RuntimeError, err);
       return NULL;
    }

    Py_RETURN_NONE;
}
예제 #12
0
파일: win.c 프로젝트: 0xe/win-sshd
/**
   stat a file on winnt - this is *very* painful
**/
int win_filestat(stat_b *st, char *path, unsigned int want, unsigned int *give, char **err) {
    WIN32_FILE_ATTRIBUTE_DATA stat;
    SID_IDENTIFIER_AUTHORITY world_auth = SECURITY_WORLD_SID_AUTHORITY;
    PSID owner, group, world = NULL;
    PACL dacl;
    PSECURITY_DESCRIPTOR pdesc;
    int have_sec = 0;

    *give = 0;
    
    if (!GetFileAttributesEx(path, GetFileExInfoStandard, &stat)) {
		int ret, ecode = GetLastError();

		*err = get_error_msg(ecode);
		switch (ecode) {
		case ERROR_FILE_NOT_FOUND:
		case ERROR_PATH_NOT_FOUND: ret = FX_NO_SUCH_FILE; break;
		case ERROR_ACCESS_DENIED:  ret = FX_PERMISSION_DENIED; break;
		default: ret = FX_FAILURE;
		}
		return ret;
    }

    /* create a PSID for well known group "world"  - this is equivalent to "others" on POSIX */
    if (!AllocateAndInitializeSid(&world_auth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &world)) 
		world = NULL;
    
    memset(st, 0x0, sizeof(*st));
    
    *give |= ATTR_SIZE;
    if (!(stat.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
		st->size = ((unsigned __int64)stat.nFileSizeHigh << 32) + (unsigned __int64)stat.nFileSizeLow;
    else 
		st->size = 0;

    if (GetNamedSecurityInfo(path, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION 
							 | DACL_SECURITY_INFORMATION, &owner, &group, &dacl, NULL, &pdesc) != ERROR_SUCCESS) {
		ERR(have_sec, "Could not retrieve security info");
		have_sec = 0;
    } else
		have_sec = 1;

    if (have_sec) {
		/* fake unix style uid & gid.
		   We will do this by getting the string representations of the owner & group PIDS
		   and converting them to numbers (hopefully unique)
	
		   char *temp;
		   ConvertSidToStringSid(owner, &temp);
		   st->uid = st->gid = atol(temp);
		   printf("(%s) sid = %l , %l\n", temp, st->uid, st->gid);
		   LocalFree(temp);
		*/
		st->uid = st->gid = 42;
		*give |= ATTR_UIDGID;
    }
    /*
      not applicable for v3 - the commented code is for v6

	  if ((want & ATTR_UIDGID) & have_sec){
	  wchar_t uname[UNLEN + 1], dname[DNLEN + 1], gname[1000], gname2[1000];
	  DWORD unlen = UNLEN, dnlen = DNLEN, gnlen = 1000, gnlen2 = 1000;
	  SID_NAME_USE stype;
	
	  st->owner = malloc(UNLEN + DNLEN + 2);
	  if (!LookupAccountSidW(NULL, owner, uname, &unlen, dname, &dnlen, &stype)) {
	  ERR(GetLastError(), "Could not lookup ownername");
	  free(st->owner);
	  st->owner = NULL;
	  } else 
	  swprintf(st->owner, UNLEN + DNLEN + 2, L"%s@%s", uname, dname);
	
	  st->group = malloc(UNLEN + DNLEN + 2 + 2000);
	  if (!LookupAccountSidW(NULL, group, gname, &gnlen, gname2, &gnlen2, &stype)) {
	  ERR(GetLastError(), "Could not lookup group name");
	  if (st->owner) 
	  swprintf(st->group, UNLEN + DNLEN + 2 + 2000, L"None@%", dname);
	  else {
	  free(st->group);
	  st->group = NULL;
	  }
	  } else 
	  swprintf(st->group, UNLEN + DNLEN + 2 + 2000, L"%s@%s", gname, gname2);

	  *give |= ATTR_OWNERGROUP;
	  } 
    */
    st->perms = 0;
    st->perms |= stat.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? FX_S_IFDIR : FX_S_IFREG;

    if (have_sec) {
		TRUSTEE_W ident = {NULL, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID};
		ACCESS_MASK acc;
	
		ident.TrusteeType = TRUSTEE_IS_USER;
		ident.ptstrName = owner;
		if (GetEffectiveRightsFromAclW(dacl, &ident, &acc) == ERROR_SUCCESS) {
			if (acc & FILE_EXECUTE) 
				st->perms |= FX_S_IXUSR;
			if (acc & FILE_WRITE_DATA)
				st->perms |= FX_S_IWUSR;
			if (acc & FILE_READ_DATA)
				st->perms |= FX_S_IRUSR;
		}
		ident.TrusteeType = TRUSTEE_IS_GROUP;
		ident.ptstrName = group;
		if (GetEffectiveRightsFromAclW(dacl, &ident, &acc) == ERROR_SUCCESS) {
			if (acc & FILE_EXECUTE) 
				st->perms |= FX_S_IXGRP;
			if (acc & FILE_WRITE_DATA)
				st->perms |= FX_S_IWGRP;
			if (acc & FILE_READ_DATA)
				st->perms |= FX_S_IRGRP;
		}
	
		if (world) {
			ident.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
			ident.ptstrName = world;
			if (GetEffectiveRightsFromAclW(dacl, &ident, &acc) == ERROR_SUCCESS) {
				if (acc & FILE_EXECUTE)
					st->perms |= FX_S_IROTH;
				if (acc & FILE_WRITE_DATA)
					st->perms |= FX_S_IWOTH;
				if (acc & FILE_READ_DATA)
					st->perms |= FX_S_IROTH;
			}
		}
		/* we can't do shit about the S_ISUID, S_ISGUID & S_ISVTX flags */
		*give |= ATTR_PERMISSIONS;
    }
    
    win_to_unix_time(stat.ftLastAccessTime, &st->atime);
    win_to_unix_time(stat.ftLastWriteTime, &st->mtime);
    *give |= ATTR_ACMODTIME;

    /*
	  st->acl = NULL;
	  if (want & ATTR_BITS) {
	  st->attrib_bits_valid = ATTR_ARCHIVE | ATTR_COMPRESSED | ATTR_READONLY
	  | ATTR_SYSTEM | ATTR_SPARSE | ATTR_HIDDEN | ATTR_ENCRYPTED;
	  st->attrib_bits = (stat.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) 
	  | (stat.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED)
	  | (stat.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
	  | (stat.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
	  | (stat.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE)
	  | (stat.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
	  | (stat.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED);
	  *give |= ATTR_BITS;
	  }
    */

    if (world) 
		FreeSid(world);
    if (pdesc)
		LocalFree(pdesc);
    return FX_OK;
}
예제 #13
0
파일: win.c 프로젝트: 0xe/win-sshd
/*
  Execute a command as a "user". The command is run as cmd.exe /c <command>
  The command is executed from the user's HOME (as determined by the user profile)
  Input, Output & Err streams are redirected. 
*/
void *win_execute_command(wchar_t *shell, wchar_t *command, wchar_t *user, wchar_t *password, wchar_t *domain, wchar_t *root, int pty_mode) {
    SECURITY_ATTRIBUTES sa;
    STARTUPINFOW si;
    HANDLE out_rd_tmp, in_wr_tmp, out_wr, in_rd, in_wr, err_wr;
    exec_ctx *ctx;
    HANDLE ttok, ntok;
	int ret;

    ZeroMemory(&sa, sizeof(sa));
    sa.nLength = sizeof(sa);
    sa.bInheritHandle = TRUE;

    ctx = malloc(sizeof(*ctx));
    ZeroMemory(ctx, sizeof(*ctx));
    ctx->pty_mode = pty_mode;
 
    /* setup the parent child plumbing */
    if (!CreatePipe(&in_rd, &in_wr_tmp, &sa, 0)) {
        printf("Couldn't set up in pipe to child %s", get_error_msg(GetLastError()));
        free(ctx);
        return NULL;
    }

    if (!CreatePipe(&out_rd_tmp, &out_wr, &sa, 0)) {
        printf("Couldn't set up stdout pipe to child %s", get_error_msg(GetLastError()));
		free(ctx);
        return NULL;
    }

    if (!DuplicateHandle(GetCurrentProcess(), out_wr, GetCurrentProcess(), &err_wr, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
		printf("Couldn't set up stderr pipe to child %s", get_error_msg(GetLastError()));
		free(ctx);
		return NULL;
    }

    if (!DuplicateHandle(GetCurrentProcess(), out_rd_tmp, GetCurrentProcess(), &ctx->out_rd, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
		return NULL;
    }
    if (!DuplicateHandle(GetCurrentProcess(), in_wr_tmp, GetCurrentProcess(), &in_wr, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
		return NULL;
    }
    CloseHandle(out_rd_tmp);
    CloseHandle(in_wr_tmp);

    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    si.wShowWindow = SW_HIDE;
    si.hStdInput = in_rd;
    si.hStdOutput = out_wr; 
    si.hStdError = err_wr;
/*
    if (!CreateProcessWithLogonW(user, domain, password, LOGON_WITH_PROFILE, shell, command, 0, NULL, root, &si, &ctx->pi)) {
	*/
	ret = LogonUserW(user, domain, password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &ttok);
	if (!ret) {
		CloseHandle(ttok);
		INFO(GetLastError(), "Login failed for user");
		return NULL;
	}
	ret = DuplicateTokenEx(ttok, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &ntok);
	if (!ret) {
		CloseHandle(ttok);
		INFO(GetLastError(), "Can't impersonate user");
		return NULL;
	}
	CloseHandle(ttok);
	if (!CreateProcessAsUserW(ntok, shell, command, NULL, NULL, TRUE, 0, NULL, root, &si, &ctx->pi)) {
		int ecode = GetLastError();
		INFO(GetLastError(), "CreateProcess failed");
        free(ctx);
		CloseHandle(ntok);
        return NULL;
    }
	CloseHandle(ntok);
    CloseHandle(out_wr);
    CloseHandle(err_wr);
    CloseHandle(in_rd);
    return ctx;
}
bool CmdexSync::execute()
{
	set_error_msg("");  // clear old error if present

	bool slot_connected = !(signal_execute_tick.slots().begin() == signal_execute_tick.slots().end());

	if (slot_connected && !signal_execute_tick.emit(status_starting))
		return false;

	if (!cmdex_.execute()) {  // try to execute
		debug_out_error("app", DBG_FUNC_MSG << "cmdex_.execute() failed.\n");
		import_error();  // get error from cmdex and display warnings if needed

		// emit this for execution loggers
		cmdex_sync_signal_execute_finish()->emit(CmdexSyncCommandInfo(get_command_name(),
				get_command_args(), get_stdout_str(), get_stderr_str(), get_error_msg()));

		if (slot_connected)
			signal_execute_tick.emit(status_failed);
		return false;
	}

	bool stop_requested = false;  // stop requested from tick function
	bool signals_sent = false;  // stop signals sent

	while(!cmdex_.stopped_cleanup_needed()) {

		if (!stop_requested) {  // running and no stop requested yet
			// call the tick function with "running" periodically.
			// if it returns false, try to stop.
			if (slot_connected && !signal_execute_tick.emit(status_running)) {
				debug_out_info("app", DBG_FUNC_MSG << "execute_tick slot returned false, trying to stop the program.\n");
				stop_requested = true;
			}
		}


		if (stop_requested && !signals_sent) {  // stop request received
			// send the stop request to the command
			if (!cmdex_.try_stop()) {  // try sigterm. this returns false if it can't be done (no permissions, zombie)
				debug_out_warn("app", DBG_FUNC_MSG << "cmdex_.try_stop() returned false.\n");
			}

			// set sigkill timeout to 3 sec (in case sigterm fails); won't do anything if already exited.
			cmdex_.set_stop_timeouts(0, forced_kill_timeout_msec);
			// import_error();  // don't need errors here - they will be available later anyway.

			signals_sent = true;
		}


		// alert the tick function
		if (stop_requested && slot_connected) {
			signal_execute_tick.emit(status_stopping);  // ignore returned value here
		}


		// without this, no event sources will be processed and the program will
		// hang waiting for the child to exit (the watch handler won't be called).
		while(g_main_context_pending(NULL)) {
			g_main_context_iteration(NULL, false);
		}

		Glib::usleep(50*1000);  // 50 msec. avoids 100% CPU usage.
	}

	// command exited, do a cleanup.
	cmdex_.stopped_cleanup();
	import_error();  // get error from cmdex and display warnings if needed

	// emit this for execution loggers
	cmdex_sync_signal_execute_finish()->emit(CmdexSyncCommandInfo(get_command_name(),
			get_command_args(), get_stdout_str(), get_stderr_str(), get_error_msg()));

	if (slot_connected)
		signal_execute_tick.emit(status_stopped);  // last call

	return true;
}