winexe 0.6 patch [psexec for linux]

AH andrzej.hajda at wp.pl
Fri Jul 7 00:02:21 GMT 2006


Hello

According to discussion I send latest winexe patch.
I have changed code style, comments, headers thx to Jelmer remarks.
This patch includes also few svcctl.idl changes to my primary patch, thx 
metze.
Statically compiled version of winexe is available at 
http://eol.ovh.org/winexe/, be aware of linker warnings described on the 
page.

Returning to remarks:
About CamelCasing: I have removed ugly MyArgs, I still have names of 2 
types(examples): onIoPipeOpen and svc_CloseServiceHandle.
I see samba uses also CC, for example: poptSetOtherOptionHelp, 
dcerpc_svcctl_StartServiceW,
so question is what naming strategy use?

AH

-------------- next part --------------
Index: main.mk
===================================================================
--- main.mk	(revision 16844)
+++ main.mk	(working copy)
@@ -25,6 +25,7 @@
 include ntvfs/config.mk
 include ntptr/config.mk
 include torture/config.mk
+include winexe/config.mk
 include librpc/config.mk
 include client/config.mk
 include libcli/config.mk
Index: winexe/winexe.c
===================================================================
--- winexe/winexe.c	(revision 0)
+++ winexe/winexe.c	(revision 0)
@@ -0,0 +1,269 @@
+/*
+   Copyright (C) Andrzej Hajda 2006
+   Contact: andrzej.hajda at wp.pl
+   License: GNU General Public License version 2
+*/
+
+#include "includes.h"
+#include "lib/cmdline/popt_common.h"
+#include "librpc/rpc/dcerpc.h"
+#include "librpc/gen_ndr/ndr_svcctl_c.h"
+#include "librpc/gen_ndr/ndr_security.h"
+#include "libcli/libcli.h"
+#include "lib/events/events.h"
+
+#include "winexe.h"
+#include "winexesvc/shared.h"
+
+#include <sys/fcntl.h>
+#include <sys/unistd.h>
+#include <sys/termios.h>
+
+struct program_args {
+	char *hostname;
+	char *cmd;
+	struct cli_credentials *credentials;
+	int reinstall;
+	int uninstall;
+};
+
+void parse_args(int argc, char *argv[], struct program_args *pmyargs)
+{
+	poptContext pc;
+	int opt, i;
+
+	int argc_new;
+	char **argv_new;
+
+	struct poptOption long_options[] = {
+		POPT_AUTOHELP
+		    POPT_COMMON_SAMBA
+		    POPT_COMMON_CONNECTION
+		    POPT_COMMON_CREDENTIALS
+		    POPT_COMMON_VERSION
+		    {"uninstall", 0, POPT_ARG_NONE, &pmyargs->uninstall, 0,
+		     "uninstall winexe service after remote execution",
+		     NULL},
+		{"reinstall", 0, POPT_ARG_NONE, &pmyargs->reinstall, 0,
+		 "reinstall winexe service", NULL},
+		POPT_TABLEEND
+	};
+
+	pc = poptGetContext("winexe", argc, (const char **) argv,
+			    long_options, POPT_CONTEXT_KEEP_FIRST);
+
+	poptSetOtherOptionHelp(pc, "//host command");
+
+	while ((opt = poptGetNextOpt(pc)) != -1) {
+		poptPrintUsage(pc, stdout, 0);
+		exit(1);
+	}
+
+	argv_new = discard_const_p(char *, poptGetArgs(pc));
+
+	argc_new = argc;
+	for (i = 0; i < argc; i++) {
+		if (argv_new[i] == NULL) {
+			argc_new = i;
+			break;
+		}
+	}
+
+	if (argc_new != 3 || argv_new[1][0] != '/'
+	    || argv_new[1][1] != '/') {
+		poptPrintUsage(pc, stdout, 0);
+		exit(1);
+	}
+
+	pmyargs->hostname = argv_new[1] + 2;
+	pmyargs->cmd = argv_new[2];
+}
+
+struct winexe_context {
+	struct program_args *args;
+	struct smbcli_tree *tree;
+	struct async_context *ac_ctrl;
+	struct async_context *ac_io;
+	struct async_context *ac_err;
+	int return_code;
+};
+
+void exit_program(struct winexe_context *c);
+
+void onCtrlPipeError(struct winexe_context *c, int func, NTSTATUS status)
+{
+	DEBUG(1, ("ERROR: onCtrlPipeError - %s\n", nt_errstr(status)));
+	static int activated = 0;
+	if (!activated
+	    && NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+		status =
+		    svc_install(c->args->hostname, c->args->credentials);
+		if (!NT_STATUS_IS_OK(status)) {
+			DEBUG(0,
+			      ("ERROR: Failed to install service winexesvc - %s\n",
+			       nt_errstr(status)));
+			c->return_code = 1;
+			exit_program(c);
+		}
+		activated = 1;
+		async_open(c->ac_ctrl, PIPE_NAME, OPENX_MODE_ACCESS_RDWR);
+	} else if (func == ASYNC_OPEN_RECV) {
+		DEBUG(0,
+		      ("ERROR: Cannot open control pipe - %s\n",
+		       nt_errstr(status)));
+		c->return_code = 1;
+		exit_program(c);
+	} else
+		exit_program(c);
+}
+
+void onIoPipeOpen(struct winexe_context *c);
+void onIoPipeRead(struct winexe_context *c, const char *data, int len);
+void onIoPipeError(struct winexe_context *c, int func, NTSTATUS status);
+void onErrPipeRead(struct winexe_context *c, const char *data, int len);
+void onErrPipeError(struct winexe_context *c, int func, NTSTATUS status);
+
+const char *cmd_check(const char *data, const char *cmd, int len)
+{
+	int lcmd = strlen(cmd);
+	if (lcmd >= len)
+		return 0;
+	if (!strncmp(data, cmd, lcmd)
+	    && (data[lcmd] == ' ' || data[lcmd] == '\n')) {
+		return data + lcmd + 1;
+	}
+	return 0;
+}
+
+void onCtrlPipeOpen(struct winexe_context *c)
+{
+	char *str = talloc_asprintf(c, "run %s\n", c->args->cmd);
+	DEBUG(1, ("CTRL: Sending command: %s", str));
+	async_write(c->ac_ctrl, str, strlen(str));
+	talloc_free(str);
+}
+
+void onCtrlPipeRead(struct winexe_context *c, const char *data, int len)
+{
+	const char *p;
+	if ((p = cmd_check(data, CMD_STD_IO_ERR, len))) {
+		DEBUG(1, ("CTRL: Recieved command: %.*s", len, data));
+		unsigned int npipe = strtoul(p, 0, 16);
+		c->ac_io = talloc_zero(c, struct async_context);
+		c->ac_io->tree = c->tree;
+		c->ac_io->cb_ctx = c;
+		c->ac_io->cb_open = (async_cb_open) onIoPipeOpen;
+		c->ac_io->cb_read = (async_cb_read) onIoPipeRead;
+		c->ac_io->cb_error = (async_cb_error) onIoPipeError;
+		char *fn = talloc_asprintf(c->ac_io, PIPE_NAME_IO, npipe);
+		async_open(c->ac_io, fn, OPENX_MODE_ACCESS_RDWR);
+		c->ac_err = talloc_zero(c, struct async_context);
+		c->ac_err->tree = c->tree;
+		c->ac_err->cb_ctx = c;
+		c->ac_err->cb_read = (async_cb_read) onErrPipeRead;
+		c->ac_err->cb_error = (async_cb_error) onErrPipeError;
+		fn = talloc_asprintf(c->ac_err, PIPE_NAME_ERR, npipe);
+		async_open(c->ac_err, fn, OPENX_MODE_ACCESS_READ);
+	} else if ((p = cmd_check(data, CMD_RETURN_CODE, len))) {
+		c->return_code = strtoul(p, 0, 16);
+	} else {
+		DEBUG(0, ("CTRL: Unknown command: %.*s", len, data));
+	}
+}
+
+static void onStdinReadEvent(struct event_context *event_ctx,
+			     struct fd_event *fde, uint16_t flags,
+			     struct winexe_context *c)
+{
+	char buf[256];
+	int len;
+	if ((len = read(0, &buf, sizeof(buf))) > 0) {
+		async_write(c->ac_io, buf, len);
+	}
+}
+
+void onIoPipeOpen(struct winexe_context *c)
+{
+	event_add_fd(c->tree->session->transport->socket->event.ctx,
+		     c->tree, 0, EVENT_FD_READ,
+		     (event_fd_handler_t) onStdinReadEvent, c);
+	struct termios term;
+	tcgetattr(0, &term);
+	term.c_lflag &= ~ICANON;
+	tcsetattr(0, TCSANOW, &term);
+	setbuf(stdin, NULL);
+}
+
+void onIoPipeRead(struct winexe_context *c, const char *data, int len)
+{
+	write(1, data, len);
+}
+
+void onIoPipeError(struct winexe_context *c, int func, NTSTATUS status)
+{
+	async_close(c->ac_io);
+}
+
+void onErrPipeRead(struct winexe_context *c, const char *data, int len)
+{
+	write(2, data, len);
+}
+
+void onErrPipeError(struct winexe_context *c, int func, NTSTATUS status)
+{
+	async_close(c->ac_err);
+}
+
+void exit_program(struct winexe_context *c)
+{
+	if (c->args->uninstall)
+		svc_uninstall(c->args->hostname, c->args->credentials);
+	exit(c->return_code);
+}
+
+int main(int argc, char *argv[])
+{
+	NTSTATUS status;
+	struct smbcli_state *cli;
+	struct program_args myargs = {.reinstall = 0,.uninstall = 0 };
+
+	parse_args(argc, argv, &myargs);
+
+	dcerpc_init();
+
+	if (myargs.reinstall)
+		svc_uninstall(myargs.hostname, cmdline_credentials);
+	status =
+	    smbcli_full_connection(NULL, &cli, myargs.hostname, "IPC$",
+				   NULL, cmdline_credentials, NULL);
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(0,
+		      ("ERROR: Failed to open connection - %s\n",
+		       nt_errstr(status)));
+		return 1;
+	}
+
+	struct winexe_context *c =
+	    talloc_zero(cli->tree, struct winexe_context);
+	if (c == NULL) {
+		DEBUG(0,
+		      ("ERROR: Failed to allocate struct winexe_context\n"));
+		return 1;
+	}
+
+	c->tree = cli->tree;
+	c->ac_ctrl = talloc_zero(cli->tree, struct async_context);
+	c->ac_ctrl->tree = cli->tree;
+	c->ac_ctrl->cb_ctx = c;
+	c->ac_ctrl->cb_open = (async_cb_open) onCtrlPipeOpen;
+	c->ac_ctrl->cb_read = (async_cb_read) onCtrlPipeRead;
+	c->ac_ctrl->cb_error = (async_cb_error) onCtrlPipeError;
+	c->args = &myargs;
+	c->args->credentials = cmdline_credentials;
+	c->return_code = 99;
+
+	async_open(c->ac_ctrl, PIPE_NAME, OPENX_MODE_ACCESS_RDWR);
+
+	event_loop_wait(cli->tree->session->transport->socket->event.ctx);
+	return 0;
+}
Index: winexe/service.c
===================================================================
--- winexe/service.c	(revision 0)
+++ winexe/service.c	(revision 0)
@@ -0,0 +1,256 @@
+/*
+   Copyright (C) Andrzej Hajda 2006
+   Contact: andrzej.hajda at wp.pl
+   License: GNU General Public License version 2
+*/
+
+
+#include "includes.h"
+#include "lib/cmdline/popt_common.h"
+#include "librpc/rpc/dcerpc.h"
+#include "librpc/gen_ndr/ndr_svcctl_c.h"
+#include "librpc/gen_ndr/ndr_security.h"
+#define SERVICE_ALL_ACCESS (0xF01FF)
+#define SERVICE_WIN32_OWN_PROCESS (0x00000010)
+#define SERVICE_DEMAND_START (0x00000003)
+#define SERVICE_ERROR_NORMAL (0x00000001)
+#define SERVICE_CONTROL_STOP (0x00000001)
+#define NT_STATUS_SERVICE_DOES_NOT_EXIST NT_STATUS(0xc0000424)
+#include "libcli/libcli.h"
+#include "libcli/smb_composite/smb_composite.h"
+
+/* FIX We need it for dirty usleep */
+#include <sys/unistd.h>
+
+#include "winexe.h"
+
+#define NT_ERR(status, lvl, args...) if (!NT_STATUS_IS_OK(status)) { DEBUG(lvl,("ERROR: " args)); DEBUG(lvl,(". %s.\n", nt_errstr(status))); return status; }
+#define NT_RES(status, werr) (NT_STATUS_IS_OK(status) ? werror_to_ntstatus(werr) : status)
+
+NTSTATUS svc_pipe_connect(struct dcerpc_pipe **psvc_pipe,
+			  const char *hostname,
+			  struct cli_credentials *credentials)
+{
+	NTSTATUS status;
+	char *binding;
+
+	asprintf(&binding, "ncacn_np:%s", hostname);
+	status =
+	    dcerpc_pipe_connect(NULL, psvc_pipe, binding,
+				&dcerpc_table_svcctl, credentials, NULL);
+	free(binding);
+	return status;
+}
+
+NTSTATUS svc_OpenSCManager(struct dcerpc_pipe * svc_pipe,
+			   const char *hostname,
+			   struct policy_handle * pscm_handle)
+{
+	NTSTATUS status;
+	struct svcctl_OpenSCManagerW r;
+
+	r.in.MachineName = hostname;
+	r.in.DatabaseName = NULL;
+	r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+	r.out.handle = pscm_handle;
+	status = dcerpc_svcctl_OpenSCManagerW(svc_pipe, NULL, &r);
+	return NT_RES(status, r.out.result);
+}
+
+NTSTATUS svc_OpenService(struct dcerpc_pipe * svc_pipe,
+			 struct policy_handle * pscm_handle,
+			 const char *ServiceName,
+			 struct policy_handle * psvc_handle)
+{
+	NTSTATUS status;
+	struct svcctl_OpenServiceW r;
+
+	r.in.scmanager_handle = pscm_handle;
+	r.in.ServiceName = ServiceName;
+	r.in.access_mask = SERVICE_ALL_ACCESS;
+	r.out.handle = psvc_handle;
+	status = dcerpc_svcctl_OpenServiceW(svc_pipe, NULL, &r);
+	return NT_RES(status, r.out.result);
+}
+
+NTSTATUS svc_CreateService(struct dcerpc_pipe * svc_pipe,
+			   struct policy_handle * pscm_handle,
+			   const char *ServiceName,
+			   const char *binary_path,
+			   struct policy_handle * psvc_handle)
+{
+	NTSTATUS status;
+	struct svcctl_CreateServiceW r;
+
+	r.in.scmanager_handle = pscm_handle;
+	r.in.ServiceName = ServiceName;
+	r.in.DisplayName = NULL;
+	r.in.desired_access = SERVICE_ALL_ACCESS;
+	r.in.type = SERVICE_WIN32_OWN_PROCESS;
+	r.in.start_type = SERVICE_DEMAND_START;
+	r.in.error_control = SERVICE_ERROR_NORMAL;
+	r.in.binary_path = binary_path;
+	r.in.LoadOrderGroupKey = NULL;
+	r.in.TagId = NULL;
+	r.in.dependencies = NULL;
+	r.in.dependencies_size = 0;
+	r.in.service_start_name = NULL;
+	r.in.password = NULL;
+	r.in.password_size = 0;
+	r.out.handle = psvc_handle;
+	r.out.TagId = NULL;
+	status = dcerpc_svcctl_CreateServiceW(svc_pipe, NULL, &r);
+	return NT_RES(status, r.out.result);
+}
+
+NTSTATUS svc_StartService(struct dcerpc_pipe * svc_pipe,
+			  struct policy_handle * psvc_handle)
+{
+	NTSTATUS status;
+	struct svcctl_StartServiceW r;
+
+	r.in.handle = psvc_handle;
+	r.in.NumArgs = 0;
+	r.in.Arguments = NULL;
+	status = dcerpc_svcctl_StartServiceW(svc_pipe, NULL, &r);
+	return NT_RES(status, r.out.result);
+}
+
+NTSTATUS svc_ControlService(struct dcerpc_pipe * svc_pipe,
+			    struct policy_handle * psvc_handle,
+			    int control, struct SERVICE_STATUS * sstatus)
+{
+	NTSTATUS status;
+	struct svcctl_ControlService r;
+
+	r.in.handle = psvc_handle;
+	r.in.control = control;
+	r.out.status = sstatus;
+	status = dcerpc_svcctl_ControlService(svc_pipe, NULL, &r);
+	return NT_RES(status, r.out.result);
+}
+
+NTSTATUS svc_DeleteService(struct dcerpc_pipe * svc_pipe,
+			   struct policy_handle * psvc_handle)
+{
+	NTSTATUS status;
+	struct svcctl_DeleteService r;
+
+	r.in.handle = psvc_handle;
+	status = dcerpc_svcctl_DeleteService(svc_pipe, NULL, &r);
+	return NT_RES(status, r.out.result);
+}
+
+NTSTATUS svc_CloseServiceHandle(struct dcerpc_pipe * svc_pipe,
+				struct policy_handle * psvc_handle)
+{
+	NTSTATUS status;
+	struct svcctl_CloseServiceHandle r;
+
+	r.in.handle = psvc_handle;
+	r.out.handle = psvc_handle;
+	status = dcerpc_svcctl_CloseServiceHandle(svc_pipe, NULL, &r);
+	return status;
+}
+
+NTSTATUS svc_UploadService(const char *hostname,
+			   struct cli_credentials * credentials)
+{
+	struct smb_composite_savefile *io;
+	struct smbcli_state *cli;
+	NTSTATUS status;
+
+	status =
+	    smbcli_full_connection(NULL, &cli, hostname, "ADMIN$", NULL,
+				   credentials, NULL);
+	NT_ERR(status, 1, "Failed to open ADMIN$ share");
+	io = talloc_zero(cli->tree, struct smb_composite_savefile);
+	io->in.fname = "winexesvc.exe";
+	io->in.data = winexesvc_exe;
+	io->in.size = winexesvc_exe_len;
+	smbcli_unlink(cli->tree, io->in.fname);
+	status = smb_composite_savefile(cli->tree, io);
+	talloc_free(io);
+	smbcli_tdis(cli);
+	NT_ERR(status, 1, "Failed to save ADMIN$/%s", io->in.fname);
+	return status;
+}
+
+/* Start, Creates, Install service if necccesary */
+NTSTATUS svc_install(const char *hostname,
+		     struct cli_credentials * credentials)
+{
+	NTSTATUS status;
+	struct dcerpc_pipe *svc_pipe;
+	struct policy_handle scm_handle;
+	struct policy_handle svc_handle;
+
+	status = svc_pipe_connect(&svc_pipe, hostname, credentials);
+	NT_ERR(status, 1, "Cannot connect to svcctl pipe");
+	status = svc_OpenSCManager(svc_pipe, hostname, &scm_handle);
+	NT_ERR(status, 1, "OpenSCManager failed");
+	status =
+	    svc_OpenService(svc_pipe, &scm_handle, "winexesvc",
+			    &svc_handle);
+	if (NT_STATUS_EQUAL(status, NT_STATUS_SERVICE_DOES_NOT_EXIST)) {
+		status = svc_UploadService(hostname, credentials);
+		NT_ERR(status, 1, "UploadService failed");
+		status =
+		    svc_CreateService(svc_pipe, &scm_handle, "winexesvc",
+				      "winexesvc.exe", &svc_handle);
+		NT_ERR(status, 1, "CreateService failed");
+	} else {
+		NT_ERR(status, 1, "OpenService failed");
+	}
+	status = svc_StartService(svc_pipe, &svc_handle);
+	NT_ERR(status, 1, "StartService failed");
+	/* FIXME wait to service real activation */
+	sleep(1);
+	svc_CloseServiceHandle(svc_pipe, &svc_handle);
+	svc_CloseServiceHandle(svc_pipe, &scm_handle);
+	/* FIXME we need to disconnect/close/destroy svc_pipe, how???? */
+	return status;
+}
+
+NTSTATUS svc_uninstall(const char *hostname,
+		       struct cli_credentials * credentials)
+{
+	NTSTATUS status;
+	struct dcerpc_pipe *svc_pipe;
+	struct policy_handle scm_handle;
+	struct policy_handle svc_handle;
+	struct SERVICE_STATUS svc_status;
+
+	status = svc_pipe_connect(&svc_pipe, hostname, credentials);
+	NT_ERR(status, 1, "Cannot connect to svcctl pipe");
+	status = svc_OpenSCManager(svc_pipe, hostname, &scm_handle);
+	NT_ERR(status, 1, "OpenSCManager failed");
+	status =
+	    svc_OpenService(svc_pipe, &scm_handle, "winexesvc",
+			    &svc_handle);
+	NT_ERR(status, 1, "OpenService failed");
+	DEBUG(1, ("OpenService - %s\n", nt_errstr(status)));
+	if (NT_STATUS_IS_OK(status)) {
+		status =
+		    svc_ControlService(svc_pipe, &svc_handle,
+				       SERVICE_CONTROL_STOP, &svc_status);
+		DEBUG(1, ("StopService - %s\n", nt_errstr(status)));
+		status = svc_DeleteService(svc_pipe, &svc_handle);
+		DEBUG(1, ("DeleteService - %s\n", nt_errstr(status)));
+		status = svc_CloseServiceHandle(svc_pipe, &svc_handle);
+		DEBUG(1, ("CloseServiceHandle - %s\n", nt_errstr(status)));
+	}
+	svc_CloseServiceHandle(svc_pipe, &scm_handle);
+	DEBUG(1, ("CloseSCMHandle - %s\n", nt_errstr(status)));
+
+	struct smbcli_state *cli;
+	status =
+	    smbcli_full_connection(NULL, &cli, hostname, "ADMIN$", NULL,
+				   credentials, NULL);
+	NT_ERR(status, 1, "Failed to open ADMIN$ share");
+	status = smbcli_unlink(cli->tree, "winexesvc.exe");
+	DEBUG(1, ("Delete winexesvc.exe - %s\n", nt_errstr(status)));
+	status = smbcli_tdis(cli);
+	DEBUG(1, ("Closing ADMIN$ - %s\n", nt_errstr(status)));
+	return status;
+}
Index: winexe/winexe.h
===================================================================
--- winexe/winexe.h	(revision 0)
+++ winexe/winexe.h	(revision 0)
@@ -0,0 +1,59 @@
+/*
+   Copyright (C) Andrzej Hajda 2006
+   Contact: andrzej.hajda at wp.pl
+   License: GNU General Public License version 2
+*/
+
+/* service.c */
+NTSTATUS svc_install(const char *hostname,
+		     struct cli_credentials *credentials);
+NTSTATUS svc_uninstall(const char *hostname,
+		       struct cli_credentials *credentials);
+
+/* async.c */
+enum { ASYNC_OPEN, ASYNC_OPEN_RECV, ASYNC_READ, ASYNC_READ_RECV,
+	    ASYNC_WRITE, ASYNC_WRITE_RECV, ASYNC_CLOSE, ASYNC_CLOSE_RECV };
+typedef void (*async_cb_open) (void *ctx);
+typedef void (*async_cb_read) (void *ctx, const char *data, int len);
+typedef void (*async_cb_close) (void *ctx);
+typedef void (*async_cb_error) (void *ctx, int func, NTSTATUS status);
+
+struct list_item {
+	struct list_item *next;
+	int size;
+	char data[0];
+};
+
+struct list {
+	struct list_item *begin;
+	struct list_item *end;
+};
+
+struct async_context {
+/* Public - must be initialized by client */
+	struct smbcli_tree *tree;
+	void *cb_ctx;
+	async_cb_open cb_open;
+	async_cb_read cb_read;
+	async_cb_close cb_close;
+	async_cb_error cb_error;
+/* Private - internal usage, initialize to zeros */
+	int fd;
+	union smb_open *io_open;
+	union smb_read *io_read;
+	union smb_write *io_write;
+	union smb_close *io_close;
+	struct smbcli_request *rreq;
+	struct smbcli_request *wreq;
+	struct list wq;
+	char buffer[256];
+};
+
+int async_open(struct async_context *c, const char *fn, int open_mode);
+int async_read(struct async_context *c);
+int async_write(struct async_context *c, const void *buf, int len);
+int async_close(struct async_context *c);
+
+/* winexesvc_exe.c */
+extern unsigned int winexesvc_exe_len;
+extern unsigned char winexesvc_exe[];
Index: winexe/TODO
===================================================================
--- winexe/TODO	(revision 0)
+++ winexe/TODO	(revision 0)
@@ -0,0 +1,6 @@
+- add service config options, esp. "interactive",
+- encryption of pipes (I hope it can be done using smb proto),
+- impersonation (after encryption),
+- other psexec/beyondexec options
+- turn off line buffering of stdin on windows side (how???)
+- review/fix code :)
Index: winexe/changes
===================================================================
--- winexe/changes	(revision 0)
+++ winexe/changes	(revision 0)
@@ -0,0 +1,26 @@
+0.6 - 07/07/06 svcctl.idl cosmetics
+    Linux code style applied, semi automatic.
+    Removed // style comments.
+    Changed includes <xx.h> to <sys/xx.h>
+0.5 - 06/07/06 Cleaned up winexe/service code.
+    Changed deps in winexe/config.mk.
+    Renamed directory service to winexesvc.
+    STDIN read corrected.
+    async_write serialized - now server should receive input in correct order.
+0.4 - 02/07/06 Added dependencies in winexe/config.mk to auto rebuild service.
+    Turned off timeouts - proces do not disconnect after 60sec.
+    Added some debug messages.
+    Removed small leaks in winexesvc.
+0.3 - 02/07/06 winexe is fully integrated with smb_build system. Now there is
+    no need to separately compile winexe/service. I have also removed symlink
+    to winexesvc_exe.c, should be cleaner.
+0.2 - 02/07/06 Now it works with NT - all pipes are created with security 
+    descriptor allowing admins to open it.
+    Added options --reinstall/--uninstall.
+    Added error messages, cleaned debug messages(-d 1).
+    Some code cleaning.
+    Added 'precompiled' winexe/service/winexesvc_exe.c, for users without 
+    crosscompiler or windows compile enironment.
+0.1 - 01/07/06 In winexe dir added link to winexe/service/winexesvc_exe.c, 
+    I am not sure if patch utility supports it.
+0.0 - 30/06/06 Initial release
Index: winexe/config.mk
===================================================================
--- winexe/config.mk	(revision 0)
+++ winexe/config.mk	(revision 0)
@@ -0,0 +1,19 @@
+#################################
+# Start BINARY winexe
+[BINARY::winexe]
+INSTALLDIR = BINDIR
+OBJ_FILES = \
+                winexe.o \
+		service.o \
+		async.o \
+		winexesvc/winexesvc_exe.o
+PRIVATE_DEPENDENCIES = \
+                POPT_SAMBA \
+                POPT_CREDENTIALS \
+                LIBPOPT \
+		RPC_NDR_SVCCTL
+# End BINARY winexe
+#################################
+
+winexe/winexesvc/winexesvc_exe.c: winexe/winexesvc
+	@$(MAKE) -C winexe/winexesvc
Index: winexe/winexesvc/service.c
===================================================================
--- winexe/winexesvc/service.c	(revision 0)
+++ winexe/winexesvc/service.c	(revision 0)
@@ -0,0 +1,156 @@
+/*
+   Copyright (C) Andrzej Hajda 2006
+   Contact: andrzej.hajda at wp.pl
+   License: GNU General Public License version 2
+*/
+
+#include <windows.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "shared.h"
+
+#if 0
+static void SvcDebugOut(const char *a, int b)
+{
+	FILE *f = fopen("C:\\" SERVICE_NAME ".log", "at");
+	fprintf(f, a, b);
+	fclose(f);
+}
+#else
+#define SvcDebugOut(a,b) 0
+#endif
+
+DWORD WINAPI server_loop(LPVOID lpParameter);
+
+SERVICE_STATUS winexesvcStatus;
+SERVICE_STATUS_HANDLE winexesvcStatusHandle;
+
+VOID WINAPI winexesvcCtrlHandler(DWORD Opcode)
+{
+	DWORD status;
+
+	switch (Opcode) {
+	case SERVICE_CONTROL_PAUSE:
+		winexesvcStatus.dwCurrentState = SERVICE_PAUSED;
+		break;
+
+	case SERVICE_CONTROL_CONTINUE:
+		winexesvcStatus.dwCurrentState = SERVICE_RUNNING;
+		break;
+
+	case SERVICE_CONTROL_STOP:
+		winexesvcStatus.dwWin32ExitCode = 0;
+		winexesvcStatus.dwCurrentState = SERVICE_STOPPED;
+		winexesvcStatus.dwCheckPoint = 0;
+		winexesvcStatus.dwWaitHint = 0;
+
+		if (!SetServiceStatus
+		    (winexesvcStatusHandle, &winexesvcStatus)) {
+			status = GetLastError();
+			SvcDebugOut(SERVICE_NAME
+				    ": SetServiceStatus error %ld\n",
+				    status);
+		}
+
+		SvcDebugOut(SERVICE_NAME ": Leaving winexesvc \n", 0);
+		return;
+
+	case SERVICE_CONTROL_INTERROGATE:
+		break;
+
+	default:
+		SvcDebugOut(SERVICE_NAME ": Unrecognized opcode %ld\n",
+			    Opcode);
+	}
+
+	if (!SetServiceStatus(winexesvcStatusHandle, &winexesvcStatus)) {
+		status = GetLastError();
+		SvcDebugOut(SERVICE_NAME ": SetServiceStatus error %ld\n",
+			    status);
+	}
+	return;
+}
+
+DWORD winexesvcInitialization(DWORD argc, LPTSTR * argv,
+			      DWORD * specificError)
+{
+	HANDLE th = CreateThread(NULL, 0, server_loop, NULL, 0, NULL);
+	if (th) {
+		CloseHandle(th);
+		return NO_ERROR;
+	}
+	return !NO_ERROR;
+}
+
+void WINAPI winexesvcStart(DWORD argc, LPTSTR * argv)
+{
+	DWORD status;
+	DWORD specificError;
+
+	winexesvcStatus.dwServiceType = SERVICE_WIN32;
+	winexesvcStatus.dwCurrentState = SERVICE_START_PENDING;
+	winexesvcStatus.dwControlsAccepted =
+	    SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
+	winexesvcStatus.dwWin32ExitCode = 0;
+	winexesvcStatus.dwServiceSpecificExitCode = 0;
+	winexesvcStatus.dwCheckPoint = 0;
+	winexesvcStatus.dwWaitHint = 0;
+
+	SvcDebugOut(SERVICE_NAME ": RegisterServiceCtrlHandler\n", 0);
+
+	winexesvcStatusHandle =
+	    RegisterServiceCtrlHandler(SERVICE_NAME, winexesvcCtrlHandler);
+
+	if (winexesvcStatusHandle == (SERVICE_STATUS_HANDLE) 0) {
+		SvcDebugOut(SERVICE_NAME
+			    ": RegisterServiceCtrlHandler failed %d\n",
+			    GetLastError());
+		return;
+	}
+	status = winexesvcInitialization(argc, argv, &specificError);
+
+	if (status != NO_ERROR) {
+		winexesvcStatus.dwCurrentState = SERVICE_STOPPED;
+		winexesvcStatus.dwCheckPoint = 0;
+		winexesvcStatus.dwWaitHint = 0;
+		winexesvcStatus.dwWin32ExitCode = status;
+		winexesvcStatus.dwServiceSpecificExitCode = specificError;
+
+		SetServiceStatus(winexesvcStatusHandle, &winexesvcStatus);
+		return;
+	}
+
+	winexesvcStatus.dwCurrentState = SERVICE_RUNNING;
+	winexesvcStatus.dwCheckPoint = 0;
+	winexesvcStatus.dwWaitHint = 0;
+
+	if (!SetServiceStatus(winexesvcStatusHandle, &winexesvcStatus)) {
+		status = GetLastError();
+		SvcDebugOut(SERVICE_NAME ": SetServiceStatus error %ld\n",
+			    status);
+	}
+
+	SvcDebugOut(SERVICE_NAME ": Returning the Main Thread \n", 0);
+
+	return;
+}
+
+int main(int argc, char *argv[])
+{
+	SERVICE_TABLE_ENTRY DispatchTable[] = {
+		{SERVICE_NAME, winexesvcStart},
+		{NULL, NULL}
+	};
+
+	SvcDebugOut(SERVICE_NAME ": StartServiceCtrlDispatcher\n",
+		    GetLastError());
+	if (!StartServiceCtrlDispatcher(DispatchTable)) {
+		SvcDebugOut(SERVICE_NAME
+			    ": StartServiceCtrlDispatcher (%d)\n",
+			    GetLastError());
+	}
+	return 0;
+}
Index: winexe/winexesvc/winexesvc.c
===================================================================
--- winexe/winexesvc/winexesvc.c	(revision 0)
+++ winexe/winexesvc/winexesvc.c	(revision 0)
@@ -0,0 +1,326 @@
+/*
+   Copyright (C) Andrzej Hajda 2006
+   Contact: andrzej.hajda at wp.pl
+   License: GNU General Public License version 2
+*/
+
+#include <windows.h>
+#include <aclapi.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "shared.h"
+
+#define BUFSIZE 256
+
+#if 0
+static void SvcDebugOut(const char *a, int b)
+{
+	FILE *f = fopen("C:\\" SERVICE_NAME ".log", "at");
+	fprintf(f, a, b);
+	fclose(f);
+}
+#else
+#define SvcDebugOut(a,b) 0
+#endif
+
+SECURITY_ATTRIBUTES sa;
+
+/* Creates SECURITY_ATTRIBUTES sa with full access for BUILTIN\Administrators */
+int CreatePipesSA()
+{
+	DWORD dwRes;
+	PSID pAdminSID = NULL;
+	PACL pACL = NULL;
+	PSECURITY_DESCRIPTOR pSD = NULL;
+	EXPLICIT_ACCESS ea;
+	SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
+
+	/* Create a SID for the BUILTIN\Administrators group. */
+	if (!AllocateAndInitializeSid(&SIDAuthNT, 2,
+				      SECURITY_BUILTIN_DOMAIN_RID,
+				      DOMAIN_ALIAS_RID_ADMINS,
+				      0, 0, 0, 0, 0, 0, &pAdminSID)) {
+		SvcDebugOut("AllocateAndInitializeSid Error %u\n",
+			    GetLastError());
+		return 0;
+	}
+	/* Initialize an EXPLICIT_ACCESS structure for an ACE.
+	   The ACE will allow the Administrators group full access to the key.
+	*/
+	ea.grfAccessPermissions = FILE_ALL_ACCESS;
+	ea.grfAccessMode = SET_ACCESS;
+	ea.grfInheritance = NO_INHERITANCE;
+	ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
+	ea.Trustee.TrusteeType = TRUSTEE_IS_GROUP;
+	ea.Trustee.ptstrName = (LPTSTR) pAdminSID;
+
+	/* Create a new ACL that contains the new ACEs */
+	dwRes = SetEntriesInAcl(1, &ea, NULL, &pACL);
+	if (ERROR_SUCCESS != dwRes) {
+		SvcDebugOut("SetEntriesInAcl Error %u\n", GetLastError());
+		return 0;
+	}
+	/* Initialize a security descriptor */
+	pSD =
+	    (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR,
+					      SECURITY_DESCRIPTOR_MIN_LENGTH);
+	if (NULL == pSD) {
+		SvcDebugOut("LocalAlloc Error %u\n", GetLastError());
+		return 0;
+	}
+
+	if (!InitializeSecurityDescriptor
+	    (pSD, SECURITY_DESCRIPTOR_REVISION)) {
+		SvcDebugOut("InitializeSecurityDescriptor Error %u\n",
+			    GetLastError());
+		return 0;
+	}
+	/* Add the ACL to the security descriptor */
+	if (!SetSecurityDescriptorDacl(pSD, TRUE,	/* bDaclPresent flag */
+				       pACL, FALSE))	/* not a default DACL */
+	{
+		SvcDebugOut("SetSecurityDescriptorDacl Error %u\n",
+			    GetLastError());
+		return 0;
+	}
+	/* Initialize a security attributes structure */
+	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+	sa.lpSecurityDescriptor = pSD;
+	sa.bInheritHandle = FALSE;
+	return 1;
+}
+
+/* FIXME make read bufferd ??/read whole lines */
+int ReadStringToDelimiter(HANDLE pipe, char *dest, int size, int delim)
+{
+	DWORD res;
+	DWORD count = 0;
+	while (--size >= 0) {
+		if (!ReadFile(pipe, dest, 1, &res, NULL) || !res
+		    || *dest == delim)
+			return count;
+		++count;
+		++dest;
+	}
+	return count;
+}
+
+int hprintf(HANDLE pipe, const char *fmt, ...)
+{
+	int res;
+	char buf[1024];
+	va_list ap;
+	va_start(ap, fmt);
+	vsnprintf(buf, sizeof(buf), fmt, ap);
+	va_end(ap);
+	WriteFile(pipe, buf, strlen(buf), (LPDWORD) & res, NULL);
+	FlushFileBuffers(pipe);
+	return res;
+}
+
+void cmd_run(HANDLE pipe)
+{
+	char buf[256];
+	int res;
+	char cmdline[1024];
+	HANDLE pio, perr;
+
+	res =
+	    ReadStringToDelimiter(pipe, cmdline, sizeof(cmdline) - 1,
+				  '\n');
+	if (res <= 0) {
+		hprintf(pipe, "error Invalid command\n");
+		CloseHandle(pipe);
+		return;
+	}
+	cmdline[res] = 0;
+
+
+	sprintf(buf, "\\\\." PIPE_NAME_IO, (unsigned int) pipe);
+	pio = CreateNamedPipe(buf,		/* pipe name */
+			      PIPE_ACCESS_DUPLEX,	/* read/write access */
+			      PIPE_WAIT,	/* blocking mode */
+			      1,	/* max. instances */
+			      BUFSIZE,	/* output buffer size */
+			      BUFSIZE,	/* input buffer size */
+			      NMPWAIT_USE_DEFAULT_WAIT,	/* client time-out */
+			      &sa);	/* default security attribute */
+	if (pio == INVALID_HANDLE_VALUE) {
+		hprintf(pipe, "error Cannot create io pipe\n");
+		CloseHandle(pipe);
+		return;
+	}
+
+	sprintf(buf, "\\\\." PIPE_NAME_ERR, (unsigned int) pipe);
+	perr = CreateNamedPipe(buf,	/* pipe name */
+			       PIPE_ACCESS_DUPLEX,	/* read/write access */
+			       PIPE_WAIT,	/* blocking mode */
+			       1,	/* max. instances */
+			       BUFSIZE,	/* output buffer size */
+			       BUFSIZE,	/* input buffer size */
+			       NMPWAIT_USE_DEFAULT_WAIT,	/* client time-out */
+			       &sa);	/* default security attribute */
+	if (perr == INVALID_HANDLE_VALUE) {
+		hprintf(pipe, "error Cannot create err pipe\n");
+		CloseHandle(pio);
+		CloseHandle(pipe);
+		return;
+	}
+	/* Send handle to client (it will use it to connect pipes) */
+	hprintf(pipe, CMD_STD_IO_ERR " %08X\n", (unsigned int) pipe);
+
+	res =
+	    ConnectNamedPipe(pio,
+			     NULL) ? TRUE : (GetLastError() ==
+					     ERROR_PIPE_CONNECTED);
+	if (!res) {
+		hprintf(pipe, "error ConnectNamedPipe(pio)\n");
+		CloseHandle(pio);
+		CloseHandle(perr);
+		CloseHandle(pipe);
+		return;
+	}
+
+	res =
+	    ConnectNamedPipe(perr,
+			     NULL) ? TRUE : (GetLastError() ==
+					     ERROR_PIPE_CONNECTED);
+	if (!res) {
+		hprintf(pipe, "error ConnectNamedPipe(perr)\n");
+		CloseHandle(pio);
+		CloseHandle(perr);
+		CloseHandle(pipe);
+		return;
+	}
+
+	SetHandleInformation(pio, HANDLE_FLAG_INHERIT, 1);
+	SetHandleInformation(perr, HANDLE_FLAG_INHERIT, 1);
+
+
+	SECURITY_ATTRIBUTES sattr;
+	sattr.nLength = sizeof(SECURITY_ATTRIBUTES);
+	sattr.bInheritHandle = TRUE;
+	sattr.lpSecurityDescriptor = NULL;
+
+	PROCESS_INFORMATION pi;
+	ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
+
+	STARTUPINFO si;
+	ZeroMemory(&si, sizeof(STARTUPINFO));
+	si.cb = sizeof(STARTUPINFO);
+	si.hStdInput = pio;
+	si.hStdOutput = pio;
+	si.hStdError = perr;
+	si.dwFlags |= STARTF_USESTDHANDLES;
+
+	if (CreateProcess(NULL, cmdline,	/* command line */
+			  NULL,	/* process security attributes */
+			  NULL,	/* primary thread security attributes */
+			  TRUE,	/* handles are inherited */
+			  0,	/* creation flags */
+			  NULL,	/* use parent's environment */
+			  NULL,	/* use parent's current directory */
+			  &si,	/* STARTUPINFO pointer */
+			  &pi))	/* receives PROCESS_INFORMATION */
+	{
+		WaitForSingleObject(pi.hProcess, INFINITE);
+		DWORD ec;
+		GetExitCodeProcess(pi.hProcess, &ec);
+		FlushFileBuffers(pio);
+		FlushFileBuffers(perr);
+		CloseHandle(pi.hProcess);
+		CloseHandle(pi.hThread);
+		hprintf(pipe, CMD_RETURN_CODE " %08X\n", ec);
+	} else {
+		hprintf(pipe, "error Creating process\n");
+	}
+	DisconnectNamedPipe(pio);
+	CloseHandle(pio);
+	DisconnectNamedPipe(perr);
+	CloseHandle(perr);
+	DisconnectNamedPipe(pipe);
+	CloseHandle(pipe);
+}
+
+typedef void CMD_FUNC(HANDLE);
+
+typedef struct {
+	const char *name;
+	CMD_FUNC *func;
+} CMD_ITEM;
+
+CMD_ITEM cmd_table[] = {
+	{"run", cmd_run},
+	{NULL, NULL}
+};
+
+VOID handle_connection(HANDLE pipe)
+{
+	char cmd[17];
+	int res;
+	res = ReadStringToDelimiter(pipe, cmd, sizeof(cmd) - 1, ' ');
+	if (res > 0) {
+		cmd[res] = 0;
+		CMD_ITEM *ci;
+		for (ci = cmd_table; ci->name; ++ci)
+			if (!strcmp(ci->name, cmd))
+				break;
+		if (ci->name)
+			ci->func(pipe);
+		else
+			SvcDebugOut("Unknown command %s\n", (int) cmd);
+	} else
+		SvcDebugOut("Error reading from pipe(%08X)\n", (int) pipe);
+	FlushFileBuffers(pipe);
+	DisconnectNamedPipe(pipe);
+	CloseHandle(pipe);
+}
+
+DWORD WINAPI server_loop(LPVOID lpParameter)
+{
+	HANDLE pipe;
+	BOOL res;
+	if (!CreatePipesSA()) {
+		SvcDebugOut("CreatePipesSA failed (%08X)\n",
+			    GetLastError());
+		return -1;
+	}
+	for (;;) {
+		pipe = CreateNamedPipe("\\\\." PIPE_NAME,	/* pipe name */
+				       PIPE_ACCESS_DUPLEX,	/* read/write access */
+				       PIPE_WAIT,	/* blocking mode */
+				       PIPE_UNLIMITED_INSTANCES,	/* max. instances */
+				       BUFSIZE,	/* output buffer size */
+				       BUFSIZE,	/* input buffer size */
+				       NMPWAIT_USE_DEFAULT_WAIT,	/* client time-out */
+				       &sa);	/* default security attribute */
+
+		if (pipe == INVALID_HANDLE_VALUE) {
+			SvcDebugOut("CreatePipe failed(%08X)\n",
+				    GetLastError());
+			return 0;
+		}
+		res =
+		    ConnectNamedPipe(pipe,
+				     NULL) ? TRUE : (GetLastError() ==
+						     ERROR_PIPE_CONNECTED);
+		if (res) {
+			HANDLE th = CreateThread(NULL,	/* no security attribute */
+						 0,	/* default stack size */
+						 (LPTHREAD_START_ROUTINE)
+						 handle_connection,
+						 (LPVOID) pipe,	/* thread parameter */
+						 0,	/* not suspended */
+						 NULL);	/* returns thread ID */
+			if (!th) {
+				SvcDebugOut("Cannot create thread\n", 0);
+			} else
+				CloseHandle(th);
+		} else {
+			CloseHandle(pipe);
+		}
+	}
+}
Index: winexe/winexesvc/shared.h
===================================================================
--- winexe/winexesvc/shared.h	(revision 0)
+++ winexe/winexesvc/shared.h	(revision 0)
@@ -0,0 +1,14 @@
+/*
+   Copyright (C) Andrzej Hajda 2006
+   Contact: andrzej.hajda at wp.pl
+   License: GNU General Public License version 2
+*/
+
+#define SERVICE_NAME "winexesvc"
+
+#define PIPE_NAME "\\pipe\\ahexec"
+#define PIPE_NAME_IO "\\pipe\\ahexec_stdio%08X"
+#define PIPE_NAME_ERR "\\pipe\\ahexec_stderr%08X"
+
+#define CMD_STD_IO_ERR "std_io_err"
+#define CMD_RETURN_CODE "return_code"
Index: winexe/winexesvc/Makefile
===================================================================
--- winexe/winexesvc/Makefile	(revision 0)
+++ winexe/winexesvc/Makefile	(revision 0)
@@ -0,0 +1,20 @@
+CFLAGS=-mno-cygwin -Os
+LDFLAGS=-mno-cygwin -s -Os
+
+CC := $(shell uname | grep -qi linux && echo i386-mingw32-gcc || echo gcc)
+
+LD=$(CC)
+
+all: winexesvc_exe.c
+
+winexesvc.exe: winexesvc.o service.o
+	$(LD) $(LDFLAGS) -o $@ $^
+
+winexesvc_exe.c: winexesvc.exe bin2c.exe
+	./bin2c.exe winexesvc_exe winexesvc.exe > $@
+
+bin2c.exe: bin2c.c
+	gcc -s -o $@ $^
+
+clean:
+	- at rm *.exe *.o winexesvc_exe.c
Index: winexe/winexesvc/winexesvc_exe.c
===================================================================
--- winexe/winexesvc/winexesvc_exe.c	(revision 0)
+++ winexe/winexesvc/winexesvc_exe.c	(revision 0)
@@ -0,0 +1,267 @@
+unsigned int winexesvc_exe_len = 7168;
+unsigned char winexesvc_exe[] = {
+  77,90,144,0,3,0,0,0,4,0,0,0,255,255,0,0,184,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,14,31,186,14,
+  0,180,9,205,33,184,1,76,205,33,84,104,105,115,32,112,114,111,103,114,97,109,
+  32,99,97,110,110,111,116,32,98,101,32,114,117,110,32,105,110,32,68,79,83,32,
+  109,111,100,101,46,13,13,10,36,0,0,0,0,0,0,0,80,69,0,0,76,1,5,0,165,156,173,
+  68,0,0,0,0,0,0,0,0,224,0,15,3,11,1,2,56,0,14,0,0,0,10,0,0,0,2,0,0,47,18,0,0,
+  0,16,0,0,0,32,0,0,0,0,64,0,0,16,0,0,0,2,0,0,4,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,
+  0,96,0,0,0,4,0,0,163,96,0,0,3,0,0,0,0,0,32,0,0,16,0,0,0,0,16,0,0,16,0,0,0,0,
+  0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,80,0,0,28,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,46,116,101,120,116,0,0,0,208,12,0,
+  0,0,16,0,0,0,14,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,96,46,100,97,116,
+  97,0,0,0,64,0,0,0,0,32,0,0,0,2,0,0,0,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,
+  192,46,114,100,97,116,97,0,0,48,1,0,0,0,48,0,0,0,2,0,0,0,20,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,64,0,0,64,46,98,115,115,0,0,0,0,160,0,0,0,0,64,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,192,46,105,100,97,116,97,0,0,28,5,0,0,0,80,
+  0,0,0,6,0,0,0,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,192,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,85,137,229,131,236,8,199,69,248,0,0,
+  0,0,131,236,12,141,69,248,80,255,53,16,32,64,0,141,69,252,80,104,4,64,64,0,
+  104,0,64,64,0,232,211,10,0,0,131,196,32,201,195,85,137,229,131,236,8,131,61,
+  16,64,64,0,0,116,118,161,16,64,64,0,163,32,32,64,0,131,61,128,81,64,0,0,116,
+  25,131,236,8,255,53,16,64,64,0,161,128,81,64,0,255,112,16,232,134,10,0,0,131,
+  196,16,131,61,128,81,64,0,224,116,28,131,236,8,255,53,16,64,64,0,161,128,81,
+  64,0,131,192,32,255,112,16,232,97,10,0,0,131,196,16,131,61,128,81,64,0,192,
+  116,28,131,236,8,255,53,16,64,64,0,161,128,81,64,0,131,192,64,255,112,16,232,
+  60,10,0,0,131,196,16,232,36,10,0,0,137,194,161,32,32,64,0,137,2,201,195,85,
+  137,229,131,236,24,199,69,248,0,0,0,0,199,69,244,0,0,0,0,139,69,8,139,0,139,
+  0,137,69,240,129,125,240,145,0,0,192,119,23,129,125,240,141,0,0,192,115,113,
+  129,125,240,5,0,0,192,116,28,233,191,0,0,0,129,125,240,147,0,0,192,116,90,
+  129,125,240,148,0,0,192,116,88,233,168,0,0,0,131,236,8,106,0,106,11,232,168,
+  9,0,0,131,196,16,137,69,252,131,125,252,1,117,24,131,236,8,106,1,106,11,232,
+  144,9,0,0,131,196,16,199,69,248,255,255,255,255,235,120,131,125,252,0,116,
+  114,131,236,12,106,11,139,69,252,255,208,131,196,16,199,69,248,255,255,255,
+  255,235,92,199,69,244,1,0,0,0,131,236,8,106,0,106,8,232,85,9,0,0,131,196,16,
+  137,69,252,131,125,252,1,117,35,131,236,8,106,1,106,8,232,61,9,0,0,131,196,
+  16,131,125,244,0,116,5,232,63,8,0,0,199,69,248,255,255,255,255,235,26,131,
+  125,252,0,116,20,131,236,12,106,8,139,69,252,255,208,131,196,16,199,69,248,
+  255,255,255,255,139,69,248,201,194,4,0,85,137,229,131,236,8,131,236,12,104,
+  199,16,64,0,232,114,9,0,0,131,196,12,232,250,7,0,0,232,21,254,255,255,232,66,
+  254,255,255,232,196,7,0,0,131,228,240,131,236,4,131,236,12,232,189,8,0,0,131,
+  196,12,255,48,255,53,4,64,64,0,255,53,0,64,64,0,232,45,7,0,0,131,196,16,137,
+  69,252,232,140,8,0,0,131,236,12,255,117,252,232,49,9,0,0,85,137,229,131,236,
+  8,131,236,12,106,1,161,120,81,64,0,255,208,131,196,16,232,130,255,255,255,85,
+  137,229,131,236,8,131,236,12,106,2,161,120,81,64,0,255,208,131,196,16,232,
+  104,255,255,255,85,137,229,131,236,8,131,236,12,255,117,8,161,144,81,64,0,
+  255,208,131,196,16,201,195,85,137,229,131,236,8,131,236,12,255,117,8,161,132,
+  81,64,0,255,208,131,196,16,201,195,144,144,144,144,144,144,144,144,144,144,
+  144,144,144,85,137,229,49,192,87,252,141,125,204,185,6,0,0,0,131,236,56,199,
+  69,200,0,0,0,0,199,69,196,0,0,0,0,243,170,141,69,200,80,106,0,106,0,106,0,
+  106,0,106,0,106,0,104,32,2,0,0,106,32,106,2,141,69,204,80,198,69,209,5,232,
+  104,9,0,0,49,210,133,192,15,132,142,0,0,0,139,69,200,137,69,248,141,69,196,
+  80,106,0,141,69,220,80,106,1,199,69,220,255,1,31,0,199,69,224,2,0,0,0,199,69,
+  228,0,0,0,0,199,69,240,0,0,0,0,199,69,244,2,0,0,0,232,52,9,0,0,49,210,133,
+  192,117,78,106,20,106,64,232,53,8,0,0,49,210,133,192,137,199,116,61,106,1,80,
+  232,37,9,0,0,49,210,133,192,116,47,106,0,255,117,196,106,1,87,232,34,9,0,0,
+  49,210,133,192,116,28,199,5,64,64,64,0,12,0,0,0,137,61,68,64,64,0,199,5,72,
+  64,64,0,0,0,0,0,178,1,137,208,139,125,252,201,195,85,137,229,87,86,83,80,139,
+  93,12,49,255,139,117,16,78,120,39,106,0,141,69,240,80,106,1,83,255,117,8,232,
+  214,7,0,0,133,192,116,18,131,125,240,0,116,12,15,190,3,59,69,20,116,4,71,67,
+  235,214,141,101,244,91,94,137,248,95,201,195,85,137,229,87,86,83,129,236,4,4,
+  0,0,141,69,16,80,255,117,12,141,157,244,251,255,255,104,0,4,0,0,83,139,117,8,
+  232,79,7,0,0,131,196,16,106,0,141,133,240,251,255,255,80,137,223,252,49,192,
+  131,201,255,242,174,247,209,73,81,83,86,232,126,7,0,0,86,232,136,7,0,0,139,
+  133,240,251,255,255,141,101,244,91,94,95,201,195,85,137,229,87,86,83,129,236,
+  120,5,0,0,106,10,104,255,3,0,0,141,133,244,250,255,255,80,255,117,8,232,63,
+  255,255,255,131,196,16,133,192,127,7,104,4,48,64,0,235,72,198,132,5,244,250,
+  255,255,0,255,117,8,104,27,48,64,0,141,157,244,254,255,255,83,232,190,6,0,0,
+  104,64,64,64,0,106,0,104,0,1,0,0,104,0,1,0,0,106,1,106,0,106,3,83,232,33,7,0,
+  0,131,196,12,131,248,255,137,198,117,18,104,53,48,64,0,255,117,8,232,36,255,
+  255,255,233,252,1,0,0,255,117,8,104,82,48,64,0,83,232,119,6,0,0,104,64,64,64,
+  0,106,0,104,0,1,0,0,104,0,1,0,0,106,1,106,0,106,3,83,232,218,6,0,0,137,133,
+  124,250,255,255,131,196,12,64,117,16,104,109,48,64,0,255,117,8,232,219,254,
+  255,255,86,235,68,255,117,8,104,139,48,64,0,255,117,8,232,200,254,255,255,
+  106,0,86,232,182,6,0,0,131,196,12,133,192,117,47,232,186,6,0,0,61,23,2,0,0,
+  116,35,104,156,48,64,0,255,117,8,232,160,254,255,255,86,232,176,6,0,0,255,
+  181,124,250,255,255,232,165,6,0,0,233,103,1,0,0,106,0,255,181,124,250,255,
+  255,232,115,6,0,0,133,192,117,19,232,122,6,0,0,61,23,2,0,0,116,7,104,185,48,
+  64,0,235,190,106,1,106,1,86,232,130,6,0,0,106,1,106,1,255,181,124,250,255,
+  255,232,115,6,0,0,141,189,212,250,255,255,252,49,192,185,4,0,0,0,243,171,106,
+  68,106,0,141,157,132,250,255,255,83,199,133,228,250,255,255,12,0,0,0,199,133,
+  236,250,255,255,1,0,0,0,199,133,232,250,255,255,0,0,0,0,232,85,5,0,0,139,133,
+  124,250,255,255,137,133,196,250,255,255,141,133,212,250,255,255,80,83,106,0,
+  106,0,106,0,106,1,106,0,106,0,141,133,244,250,255,255,80,106,0,129,141,176,
+  250,255,255,0,1,0,0,199,133,132,250,255,255,68,0,0,0,137,181,188,250,255,255,
+  137,181,192,250,255,255,232,247,5,0,0,131,196,12,133,192,116,94,106,255,255,
+  181,212,250,255,255,232,243,5,0,0,141,133,128,250,255,255,80,255,181,212,250,
+  255,255,232,241,5,0,0,86,232,107,5,0,0,255,181,124,250,255,255,232,96,5,0,0,
+  255,181,212,250,255,255,232,149,5,0,0,255,181,216,250,255,255,232,138,5,0,0,
+  255,181,128,250,255,255,104,215,48,64,0,255,117,8,232,97,253,255,255,131,196,
+  12,235,15,104,233,48,64,0,255,117,8,232,79,253,255,255,90,89,86,232,173,5,0,
+  0,86,232,87,5,0,0,255,181,124,250,255,255,232,156,5,0,0,255,181,124,250,255,
+  255,232,65,5,0,0,255,117,8,232,137,5,0,0,255,117,8,232,49,5,0,0,141,101,244,
+  91,94,95,201,195,85,137,229,86,83,131,236,32,106,32,106,16,141,69,216,80,139,
+  117,8,86,232,183,252,255,255,131,196,16,133,192,126,54,198,68,5,216,0,187,0,
+  32,64,0,131,61,0,32,64,0,0,116,35,141,69,216,80,255,51,232,43,4,0,0,133,192,
+  90,89,116,8,131,195,8,131,59,0,235,229,131,59,0,116,5,86,255,83,4,91,86,232,
+  141,4,0,0,86,232,23,5,0,0,86,232,193,4,0,0,141,101,248,91,94,201,195,85,137,
+  229,83,232,113,251,255,255,131,202,255,133,192,116,107,235,4,49,210,235,101,
+  104,64,64,64,0,106,0,104,0,1,0,0,104,0,1,0,0,104,255,0,0,0,106,0,106,3,104,1,
+  49,64,0,232,80,4,0,0,131,248,255,137,195,116,209,106,0,80,232,81,4,0,0,133,
+  192,117,12,232,88,4,0,0,61,23,2,0,0,117,26,106,0,106,0,83,104,183,22,64,0,
+  106,0,106,0,232,174,4,0,0,133,192,116,166,80,235,1,83,232,65,4,0,0,235,155,
+  137,208,139,93,252,201,194,4,0,144,144,144,144,144,144,85,137,229,139,69,8,
+  131,248,2,116,14,119,5,72,116,33,235,71,131,248,3,116,14,235,64,199,5,84,64,
+  64,0,7,0,0,0,235,52,199,5,84,64,64,0,4,0,0,0,235,40,199,5,92,64,64,0,0,0,0,0,
+  199,5,84,64,64,0,1,0,0,0,199,5,100,64,64,0,0,0,0,0,199,5,104,64,64,0,0,0,0,0,
+  104,80,64,64,0,255,53,112,64,64,0,232,119,4,0,0,133,192,117,5,232,174,3,0,0,
+  201,194,4,0,85,137,229,106,0,106,0,106,0,104,38,23,64,0,106,0,106,0,232,3,4,
+  0,0,133,192,186,1,0,0,0,116,8,80,232,148,3,0,0,49,210,137,208,201,195,85,137,
+  229,80,104,176,23,64,0,104,32,49,64,0,199,5,80,64,64,0,48,0,0,0,199,5,84,64,
+  64,0,2,0,0,0,199,5,88,64,64,0,3,0,0,0,199,5,92,64,64,0,0,0,0,0,199,5,96,64,
+  64,0,0,0,0,0,199,5,100,64,64,0,0,0,0,0,199,5,104,64,64,0,0,0,0,0,232,245,3,0,
+  0,133,192,163,112,64,64,0,15,132,138,0,0,0,141,69,252,80,255,117,12,255,117,
+  8,232,95,255,255,255,131,196,12,133,192,116,61,104,80,64,64,0,163,92,64,64,0,
+  255,53,112,64,64,0,139,69,252,199,5,84,64,64,0,1,0,0,0,199,5,100,64,64,0,0,0,
+  0,0,199,5,104,64,64,0,0,0,0,0,163,96,64,64,0,232,135,3,0,0,235,55,104,80,64,
+  64,0,255,53,112,64,64,0,199,5,84,64,64,0,4,0,0,0,199,5,100,64,64,0,0,0,0,0,
+  199,5,104,64,64,0,0,0,0,0,232,87,3,0,0,133,192,117,5,232,142,2,0,0,201,194,8,
+  0,85,137,229,131,236,16,232,35,1,0,0,141,69,240,80,199,69,240,32,49,64,0,199,
+  69,244,82,24,64,0,199,69,248,0,0,0,0,199,69,252,0,0,0,0,232,58,3,0,0,49,192,
+  201,195,144,144,144,144,144,144,85,137,229,131,236,8,139,69,8,137,69,248,139,
+  69,248,59,69,12,115,35,139,85,248,139,69,16,3,66,4,137,69,252,139,77,252,139,
+  85,252,139,69,248,139,0,3,2,137,1,141,69,248,131,0,8,235,213,201,195,85,137,
+  229,104,0,0,64,0,104,48,49,64,0,104,48,49,64,0,232,176,255,255,255,131,196,
+  12,201,195,144,144,144,144,144,144,144,144,144,144,144,85,137,229,219,227,
+  201,195,144,144,144,144,144,144,144,144,144,85,137,229,131,236,8,161,48,32,
+  64,0,131,56,0,116,18,161,48,32,64,0,139,0,255,208,131,5,48,32,64,0,4,235,228,
+  201,195,85,137,229,131,236,8,161,192,28,64,0,137,69,252,131,125,252,255,117,
+  27,199,69,252,0,0,0,0,139,69,252,131,60,133,196,28,64,0,0,116,7,141,69,252,
+  255,0,235,236,139,69,252,137,69,248,131,125,248,0,116,19,139,69,248,139,4,
+  133,192,28,64,0,255,208,141,69,248,255,8,235,231,131,236,12,104,240,25,64,0,
+  232,244,247,255,255,131,196,16,201,195,85,137,229,131,236,8,131,61,32,64,64,
+  0,0,117,15,199,5,32,64,64,0,1,0,0,0,232,130,255,255,255,201,195,144,144,144,
+  144,144,144,144,144,144,144,144,144,255,37,120,81,64,0,144,144,0,0,0,0,0,0,0,
+  0,255,37,124,81,64,0,144,144,0,0,0,0,0,0,0,0,255,37,112,81,64,0,144,144,0,0,
+  0,0,0,0,0,0,255,37,152,81,64,0,144,144,0,0,0,0,0,0,0,0,255,37,116,81,64,0,
+  144,144,0,0,0,0,0,0,0,0,255,37,136,81,64,0,144,144,0,0,0,0,0,0,0,0,255,37,
+  108,81,64,0,144,144,0,0,0,0,0,0,0,0,255,37,148,81,64,0,144,144,0,0,0,0,0,0,0,
+  0,255,37,160,81,64,0,144,144,0,0,0,0,0,0,0,0,255,37,156,81,64,0,144,144,0,0,
+  0,0,0,0,0,0,255,37,140,81,64,0,144,144,0,0,0,0,0,0,0,0,255,37,88,81,64,0,144,
+  144,0,0,0,0,0,0,0,0,255,37,60,81,64,0,144,144,0,0,0,0,0,0,0,0,255,37,76,81,
+  64,0,144,144,0,0,0,0,0,0,0,0,255,37,80,81,64,0,144,144,0,0,0,0,0,0,0,0,255,
+  37,96,81,64,0,144,144,0,0,0,0,0,0,0,0,255,37,64,81,64,0,144,144,0,0,0,0,0,0,
+  0,0,255,37,44,81,64,0,144,144,0,0,0,0,0,0,0,0,255,37,40,81,64,0,144,144,0,0,
+  0,0,0,0,0,0,255,37,72,81,64,0,144,144,0,0,0,0,0,0,0,0,255,37,36,81,64,0,144,
+  144,0,0,0,0,0,0,0,0,255,37,84,81,64,0,144,144,0,0,0,0,0,0,0,0,255,37,48,81,
+  64,0,144,144,0,0,0,0,0,0,0,0,255,37,92,81,64,0,144,144,0,0,0,0,0,0,0,0,255,
+  37,68,81,64,0,144,144,0,0,0,0,0,0,0,0,255,37,56,81,64,0,144,144,0,0,0,0,0,0,
+  0,0,255,37,52,81,64,0,144,144,0,0,0,0,0,0,0,0,255,37,0,81,64,0,144,144,0,0,0,
+  0,0,0,0,0,255,37,12,81,64,0,144,144,0,0,0,0,0,0,0,0,255,37,4,81,64,0,144,144,
+  0,0,0,0,0,0,0,0,255,37,16,81,64,0,144,144,0,0,0,0,0,0,0,0,255,37,20,81,64,0,
+  144,144,0,0,0,0,0,0,0,0,255,37,8,81,64,0,144,144,0,0,0,0,0,0,0,0,255,37,24,
+  81,64,0,144,144,0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,48,64,0,38,20,64,0,0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,204,28,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,114,117,110,0,101,
+  114,114,111,114,32,73,110,118,97,108,105,100,32,99,111,109,109,97,110,100,10,
+  0,92,92,46,92,112,105,112,101,92,97,104,101,120,101,99,95,115,116,100,105,
+  111,37,48,56,88,0,101,114,114,111,114,32,67,97,110,110,111,116,32,99,114,101,
+  97,116,101,32,105,111,32,112,105,112,101,10,0,92,92,46,92,112,105,112,101,92,
+  97,104,101,120,101,99,95,115,116,100,101,114,114,37,48,56,88,0,101,114,114,
+  111,114,32,67,97,110,110,111,116,32,99,114,101,97,116,101,32,101,114,114,32,
+  112,105,112,101,10,0,115,116,100,95,105,111,95,101,114,114,32,37,48,56,88,10,
+  0,101,114,114,111,114,32,67,111,110,110,101,99,116,78,97,109,101,100,80,105,
+  112,101,40,112,105,111,41,10,0,101,114,114,111,114,32,67,111,110,110,101,99,
+  116,78,97,109,101,100,80,105,112,101,40,112,101,114,114,41,10,0,114,101,116,
+  117,114,110,95,99,111,100,101,32,37,48,56,88,10,0,101,114,114,111,114,32,67,
+  114,101,97,116,105,110,103,32,112,114,111,99,101,115,115,10,0,92,92,46,92,
+  112,105,112,101,92,97,104,101,120,101,99,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,119,
+  105,110,101,120,101,115,118,99,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,84,80,0,0,0,0,0,0,0,0,0,0,120,84,0,0,0,81,0,0,120,80,0,0,0,0,0,0,0,0,0,0,
+  200,84,0,0,36,81,0,0,192,80,0,0,0,0,0,0,0,0,0,0,16,85,0,0,108,81,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,168,81,0,0,196,81,0,0,228,81,0,0,4,
+  82,0,0,24,82,0,0,52,82,0,0,72,82,0,0,0,0,0,0,0,0,0,0,104,82,0,0,120,82,0,0,
+  140,82,0,0,160,82,0,0,180,82,0,0,196,82,0,0,220,82,0,0,236,82,0,0,0,83,0,0,
+  24,83,0,0,40,83,0,0,56,83,0,0,68,83,0,0,92,83,0,0,124,83,0,0,148,83,0,0,0,0,
+  0,0,0,0,0,0,160,83,0,0,176,83,0,0,192,83,0,0,208,83,0,0,228,83,0,0,240,83,0,
+  0,248,83,0,0,4,84,0,0,16,84,0,0,32,84,0,0,44,84,0,0,56,84,0,0,68,84,0,0,80,
+  84,0,0,0,0,0,0,0,0,0,0,168,81,0,0,196,81,0,0,228,81,0,0,4,82,0,0,24,82,0,0,
+  52,82,0,0,72,82,0,0,0,0,0,0,0,0,0,0,104,82,0,0,120,82,0,0,140,82,0,0,160,82,
+  0,0,180,82,0,0,196,82,0,0,220,82,0,0,236,82,0,0,0,83,0,0,24,83,0,0,40,83,0,0,
+  56,83,0,0,68,83,0,0,92,83,0,0,124,83,0,0,148,83,0,0,0,0,0,0,0,0,0,0,160,83,0,
+  0,176,83,0,0,192,83,0,0,208,83,0,0,228,83,0,0,240,83,0,0,248,83,0,0,4,84,0,0,
+  16,84,0,0,32,84,0,0,44,84,0,0,56,84,0,0,68,84,0,0,80,84,0,0,0,0,0,0,26,0,65,
+  108,108,111,99,97,116,101,65,110,100,73,110,105,116,105,97,108,105,122,101,
+  83,105,100,0,0,254,0,73,110,105,116,105,97,108,105,122,101,83,101,99,117,114,
+  105,116,121,68,101,115,99,114,105,112,116,111,114,0,0,183,1,82,101,103,105,
+  115,116,101,114,83,101,114,118,105,99,101,67,116,114,108,72,97,110,100,108,
+  101,114,65,0,0,0,197,1,83,101,116,69,110,116,114,105,101,115,73,110,65,99,
+  108,65,0,0,211,1,83,101,116,83,101,99,117,114,105,116,121,68,101,115,99,114,
+  105,112,116,111,114,68,97,99,108,0,221,1,83,101,116,83,101,114,118,105,99,
+  101,83,116,97,116,117,115,0,0,227,1,83,116,97,114,116,83,101,114,118,105,99,
+  101,67,116,114,108,68,105,115,112,97,116,99,104,101,114,65,0,0,0,38,0,67,108,
+  111,115,101,72,97,110,100,108,101,0,0,0,46,0,67,111,110,110,101,99,116,78,97,
+  109,101,100,80,105,112,101,0,0,81,0,67,114,101,97,116,101,78,97,109,101,100,
+  80,105,112,101,65,0,0,84,0,67,114,101,97,116,101,80,114,111,99,101,115,115,
+  65,0,0,0,0,90,0,67,114,101,97,116,101,84,104,114,101,97,100,0,0,117,0,68,105,
+  115,99,111,110,110,101,99,116,78,97,109,101,100,80,105,112,101,0,0,0,155,0,
+  69,120,105,116,80,114,111,99,101,115,115,0,0,0,203,0,70,108,117,115,104,70,
+  105,108,101,66,117,102,102,101,114,115,0,0,48,1,71,101,116,69,120,105,116,67,
+  111,100,101,80,114,111,99,101,115,115,0,0,0,0,67,1,71,101,116,76,97,115,116,
+  69,114,114,111,114,0,0,16,2,76,111,99,97,108,65,108,108,111,99,0,0,0,0,101,2,
+  82,101,97,100,70,105,108,101,0,0,194,2,83,101,116,72,97,110,100,108,101,73,
+  110,102,111,114,109,97,116,105,111,110,0,0,223,2,83,101,116,85,110,104,97,
+  110,100,108,101,100,69,120,99,101,112,116,105,111,110,70,105,108,116,101,114,
+  0,0,0,37,3,87,97,105,116,70,111,114,83,105,110,103,108,101,79,98,106,101,99,
+  116,0,0,0,54,3,87,114,105,116,101,70,105,108,101,0,39,0,95,95,103,101,116,
+  109,97,105,110,97,114,103,115,0,60,0,95,95,112,95,95,101,110,118,105,114,111,
+  110,0,0,62,0,95,95,112,95,95,102,109,111,100,101,0,0,0,0,80,0,95,95,115,101,
+  116,95,97,112,112,95,116,121,112,101,0,0,0,0,121,0,95,99,101,120,105,116,0,0,
+  0,0,233,0,95,105,111,98,0,0,94,1,95,111,110,101,120,105,116,0,0,0,132,1,95,
+  115,101,116,109,111,100,101,0,0,189,1,95,118,115,110,112,114,105,110,116,102,
+  0,0,0,0,28,2,97,116,101,120,105,116,0,0,0,0,122,2,109,101,109,115,101,116,0,
+  0,0,0,144,2,115,105,103,110,97,108,0,0,0,0,147,2,115,112,114,105,110,116,102,
+  0,0,0,153,2,115,116,114,99,109,112,0,0,0,0,0,80,0,0,0,80,0,0,0,80,0,0,0,80,0,
+  0,0,80,0,0,0,80,0,0,0,80,0,0,65,68,86,65,80,73,51,50,46,68,76,76,0,0,0,0,20,
+  80,0,0,20,80,0,0,20,80,0,0,20,80,0,0,20,80,0,0,20,80,0,0,20,80,0,0,20,80,0,0,
+  20,80,0,0,20,80,0,0,20,80,0,0,20,80,0,0,20,80,0,0,20,80,0,0,20,80,0,0,20,80,
+  0,0,75,69,82,78,69,76,51,50,46,100,108,108,0,0,0,0,40,80,0,0,40,80,0,0,40,80,
+  0,0,40,80,0,0,40,80,0,0,40,80,0,0,40,80,0,0,40,80,0,0,40,80,0,0,40,80,0,0,40,
+  80,0,0,40,80,0,0,40,80,0,0,40,80,0,0,109,115,118,99,114,116,46,100,108,108,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,
+};
Index: winexe/winexesvc/bin2c.c
===================================================================
--- winexe/winexesvc/bin2c.c	(revision 0)
+++ winexe/winexesvc/bin2c.c	(revision 0)
@@ -0,0 +1,35 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+int main(int argc, char **argv)
+{
+	char buf[256], s[100];
+	int c;
+	FILE *fp;
+	if (argc != 3) {
+		fprintf(stderr, "Usage: %s varname file\n", *argv);
+		return 1;
+	}
+	if (!(fp = fopen(argv[2], "rb"))) {
+		fputs("Cannot open ", stderr);
+		perror(argv[2]);
+		return 1;
+	}
+	fseek(fp, 0, SEEK_END);
+	long len = ftell(fp);
+	fseek(fp, 0, SEEK_SET);
+	printf("unsigned int %s_len = %u;\nunsigned char %s[] = {\n",
+	       argv[1], len, argv[1]);
+	strcpy(buf, "  ");
+	while ((c = getc(fp)) != EOF) {
+		sprintf(s, "%u,", (unsigned char) c);
+		if (strlen(s) + strlen(buf) >= 80)
+			puts(buf), strcpy(buf, "  ");
+		strcat(buf, s);
+	}
+	if (*buf)
+		strcat(buf, "\n");
+	printf("%s};\n", buf);
+	return 0;
+}
Index: winexe/async.c
===================================================================
--- winexe/async.c	(revision 0)
+++ winexe/async.c	(revision 0)
@@ -0,0 +1,233 @@
+/*
+   Copyright (C) Andrzej Hajda 2006
+   Contact: andrzej.hajda at wp.pl
+   License: GNU General Public License version 2
+*/
+
+#include "includes.h"
+#include "libcli/libcli.h"
+#include "winexe.h"
+
+void list_enqueue(struct list *l, const void *data, int size)
+{
+	struct list_item *li =
+	    talloc_size(0, sizeof(struct list_item) + size);
+	memcpy(li->data, data, size);
+	li->size = size;
+	li->next = 0;
+	if (l->end)
+		l->end->next = li;
+	else
+		l->begin = li;
+	l->end = li;
+}
+
+void list_dequeue(struct list *l)
+{
+	struct list_item *li = l->begin;
+	if (!li)
+		return;
+	l->begin = li->next;
+	if (!l->begin)
+		l->end = 0;
+	talloc_free(li);
+}
+
+static void async_read_recv(struct smbcli_request *req)
+{
+	struct async_context *c = req->async.private;
+	NTSTATUS status;
+
+	status = smb_raw_read_recv(c->rreq, c->io_read);
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(1,
+		      ("ERROR: smb_raw_read_recv - %s\n",
+		       nt_errstr(status)));
+		if (c->cb_error)
+			c->cb_error(c->cb_ctx, ASYNC_READ_RECV, status);
+		return;
+	}
+
+	if (c->cb_read)
+		c->cb_read(c->cb_ctx, c->buffer,
+			   c->io_read->readx.out.nread);
+
+	async_read(c);
+}
+
+static void async_write_recv(struct smbcli_request *req)
+{
+	struct async_context *c = req->async.private;
+	NTSTATUS status;
+
+	status = smb_raw_write_recv(req, c->io_write);
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(1,
+		      ("ERROR: smb_raw_write_recv - %s\n",
+		       nt_errstr(status)));
+		talloc_free(c->io_write);
+		c->io_write = 0;
+		if (c->cb_error)
+			c->cb_error(c->cb_ctx, ASYNC_WRITE_RECV, status);
+		return;
+	}
+	if (c->wq.begin) {
+		async_write(c, c->wq.begin->data, c->wq.begin->size);
+		list_dequeue(&c->wq);
+	}
+}
+
+static void async_open_recv(struct smbcli_request *req)
+{
+	struct async_context *c = req->async.private;
+	NTSTATUS status;
+
+	status = smb_raw_open_recv(req, c, c->io_open);
+	if (NT_STATUS_IS_OK(status))
+		c->fd = c->io_open->openx.out.file.fnum;
+	talloc_free(c->io_open);
+	c->io_open = 0;
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(1,
+		      ("ERROR: smb_raw_open_recv - %s\n",
+		       nt_errstr(status)));
+		if (c->cb_error)
+			c->cb_error(c->cb_ctx, ASYNC_OPEN_RECV, status);
+		return;
+	}
+	if (c->cb_open)
+		c->cb_open(c->cb_ctx);
+	async_read(c);
+}
+
+static void async_close_recv(struct smbcli_request *req)
+{
+	struct async_context *c = req->async.private;
+	NTSTATUS status;
+
+	status = smbcli_request_simple_recv(req);
+	talloc_free(c->io_close);
+	c->io_close = 0;
+	if (c->io_open) {
+		talloc_free(c->io_open);
+		c->io_open = 0;
+	}
+	if (c->io_read) {
+		talloc_free(c->io_read);
+		c->io_read = 0;
+	}
+	if (c->io_write) {
+		talloc_free(c->io_write);
+		c->io_write = 0;
+	}
+	if (c->cb_close)
+		c->cb_close(c->cb_ctx);
+}
+
+int async_read(struct async_context *c)
+{
+	if (!c->io_read) {
+		c->io_read = talloc(c->tree, union smb_read);
+		c->io_read->readx.level = RAW_READ_READX;
+		c->io_read->readx.in.file.fnum = c->fd;
+		c->io_read->readx.in.offset = 0;
+		c->io_read->readx.in.mincnt = sizeof(c->buffer);
+		c->io_read->readx.in.maxcnt = sizeof(c->buffer);
+		c->io_read->readx.in.remaining = 0;
+		c->io_read->readx.in.read_for_execute = False;
+		c->io_read->readx.out.data = c->buffer;
+	}
+	c->rreq = smb_raw_read_send(c->tree, c->io_read);
+	if (!c->rreq) {
+		if (c->cb_error)
+			c->cb_error(c->cb_ctx, ASYNC_READ,
+				    NT_STATUS_NO_MEMORY);
+		return 0;
+	}
+	c->rreq->transport->options.request_timeout = 0;
+	c->rreq->async.fn = async_read_recv;
+	c->rreq->async.private = c;
+	return 1;
+}
+
+int async_open(struct async_context *c, const char *fn, int open_mode)
+{
+	DEBUG(1, ("IN: async_open(%s, %d)\n", fn, open_mode));
+	c->io_open = talloc_zero(c, union smb_open);
+	if (!c->io_open)
+		goto failed;
+	c->io_open->openx.level = RAW_OPEN_OPENX;
+	c->io_open->openx.in.flags = 0;
+	c->io_open->openx.in.open_mode = open_mode;
+	c->io_open->openx.in.search_attrs =
+	    FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
+	c->io_open->openx.in.file_attrs = 0;
+	c->io_open->openx.in.write_time = 0;
+	c->io_open->openx.in.open_func = 0;
+	c->io_open->openx.in.size = 0;
+	c->io_open->openx.in.timeout = 0;
+	c->io_open->openx.in.fname = fn;
+	c->rreq = smb_raw_open_send(c->tree, c->io_open);
+	if (!c->rreq)
+		goto failed;
+	c->rreq->async.fn = async_open_recv;
+	c->rreq->async.private = c;
+	return 1;
+      failed:
+	DEBUG(1, ("ERROR: async_open\n"));
+	talloc_free(c);
+	return 0;
+}
+
+int async_write(struct async_context *c, const void *buf, int len)
+{
+	if (c->wreq) {
+		list_enqueue(&c->wq, buf, len);
+		return 0;
+	}
+	if (!c->io_write) {
+		c->io_write = talloc_zero(c, union smb_write);
+		if (!c->io_write)
+			goto failed;
+		c->io_write->write.level = RAW_WRITE_WRITE;
+		c->io_write->write.in.remaining = 0;
+		c->io_write->write.in.file.fnum = c->fd;
+		c->io_write->write.in.offset = 0;
+	}
+	c->io_write->write.in.count = len;
+	c->io_write->write.in.data = buf;
+	struct smbcli_request *req =
+	    smb_raw_write_send(c->tree, c->io_write);
+	if (!req)
+		goto failed;
+	req->async.fn = async_write_recv;
+	req->async.private = c;
+	return 1;
+      failed:
+	DEBUG(1, ("ERROR: async_write\n"));
+	talloc_free(c->io_write);
+	c->io_write = 0;
+	return 0;
+}
+
+int async_close(struct async_context *c)
+{
+	c->io_close = talloc_zero(c, union smb_close);
+	if (!c->io_close)
+		goto failed;
+	c->io_close->close.level = RAW_CLOSE_CLOSE;
+	c->io_close->close.in.file.fnum = c->fd;
+	c->io_close->close.in.write_time = 0;
+	struct smbcli_request *req =
+	    smb_raw_close_send(c->tree, c->io_close);
+	if (!req)
+		goto failed;
+	req->async.fn = async_close_recv;
+	req->async.private = c;
+	return 1;
+      failed:
+	DEBUG(1, ("ERROR: async_close\n"));
+	talloc_free(c->io_close);
+	c->io_close = 0;
+	return 0;
+}
Index: librpc/idl/svcctl.idl
===================================================================
--- librpc/idl/svcctl.idl	(revision 16844)
+++ librpc/idl/svcctl.idl	(working copy)
@@ -165,20 +165,21 @@
 	/*****************/
 	/* Function 0x0c */
 	WERROR svcctl_CreateServiceW([in,ref] policy_handle *scmanager_handle,
-								[in,ref] [string,charset(UTF16)] uint16 *ServiceName,
+								[in] [string,charset(UTF16)] uint16 ServiceName[],
 								[in] [string,charset(UTF16)] uint16 *DisplayName,
 								[in] uint32 desired_access,
 								[in] uint32 type,
 								[in] uint32 start_type,
 								[in] uint32 error_control,
-								[in,ref] [string,charset(UTF16)] uint16 *binary_path,
+								[in] [string,charset(UTF16)] uint16 binary_path[],
 								[in] [string,charset(UTF16)] uint16 *LoadOrderGroupKey,
   								[in,out] uint32 *TagId,
-								[in] [string,charset(UTF16)] uint16 *dependencies,
+								[in,size_is(dependencies_size)] uint8 dependencies[*],
+								[in] uint32 dependencies_size,
 								[in] uint32 fix_len_dependencies,
 								[in] [string,charset(UTF16)] uint16 *service_start_name,
-								[in] [string,charset(UTF16)] uint16 *password,
-								[in] uint32 fix_len_password,
+								[in,size_is(password_size)] uint8 password[*],
+								[in] uint32 password_size,
 								[out,ref] policy_handle *handle);
 
 	/*****************/
@@ -213,7 +214,7 @@
 	/*****************/
 	/* Function 0x10 */
 	WERROR svcctl_OpenServiceW([in,ref] policy_handle *scmanager_handle,
-							  [in,ref] [string,charset(UTF16)] uint16 *ServiceName,
+							  [in] [string,charset(UTF16)] uint16 ServiceName[],
 							  [in] uint32 access_mask,
 					                  [out,ref] policy_handle *handle);
 


More information about the samba-technical mailing list