diff --git a/auth-passwd.c b/auth-passwd.c
index 996c2cf71..3b81c2d68 100644
--- a/auth-passwd.c
+++ b/auth-passwd.c
@@ -222,4 +222,41 @@ sys_auth_passwd(Authctxt *authctxt, const char *password)
return encrypted_password != NULL &&
strcmp(encrypted_password, pw_password) == 0;
}
-#endif
+
+#elif defined(WINDOWS)
+/*
+* Authenticate on Windows - Pass creds to ssh-agent and retrieve token
+* upon succesful authentication
+*/
+extern int auth_sock;
+int sys_auth_passwd(Authctxt *authctxt, const char *password)
+{
+ u_char *blob = NULL;
+ size_t blen = 0;
+ DWORD token = 0;
+ struct sshbuf *msg = NULL;
+
+ msg = sshbuf_new();
+ if (!msg)
+ return 0;
+ if (sshbuf_put_u8(msg, 100) != 0 ||
+ sshbuf_put_cstring(msg, "password") != 0 ||
+ sshbuf_put_cstring(msg, authctxt->user) != 0 ||
+ sshbuf_put_cstring(msg, password) != 0 ||
+ ssh_request_reply(auth_sock, msg, msg) != 0 ||
+ sshbuf_get_u32(msg, &token) != 0) {
+ debug("auth agent did not authorize client %s", authctxt->pw->pw_name);
+ return 0;
+ }
+
+
+ if (blob)
+ free(blob);
+ if (msg)
+ sshbuf_free(msg);
+
+ authctxt->methoddata = (void*)(INT_PTR)token;
+
+ return 1;
+}
+#endif /* WINDOWS */
diff --git a/auth.c b/auth.c
index 6ee6116df..a6ba4d457 100644
--- a/auth.c
+++ b/auth.c
@@ -489,6 +489,10 @@ int
auth_secure_path(const char *name, struct stat *stp, const char *pw_dir,
uid_t uid, char *err, size_t errlen)
{
+#ifdef WINDOWS
+ error("auth_secure_path should not be called in Windows");
+ return -1;
+#else /* !WINDOWS */
char buf[PATH_MAX], homedir[PATH_MAX];
char *cp;
int comparehome = 0;
@@ -541,6 +545,7 @@ auth_secure_path(const char *name, struct stat *stp, const char *pw_dir,
break;
}
return 0;
+#endif /* !WINDOWS */
}
/*
@@ -573,6 +578,15 @@ auth_openfile(const char *file, struct passwd *pw, int strict_modes,
int fd;
FILE *f;
+#ifdef WINDOWS
+ /* Windows POSIX adpater does not support fdopen() on open(file)*/
+ if ((f = fopen(file, "r")) == NULL) {
+ debug("Could not open %s '%s': %s", file_type, file,
+ strerror(errno));
+ return NULL;
+ }
+ /* TODO check permissions */
+#else /* !WINDOWS */
if ((fd = open(file, O_RDONLY|O_NONBLOCK)) == -1) {
if (log_missing || errno != ENOENT)
debug("Could not open %s '%s': %s", file_type, file,
@@ -602,6 +616,7 @@ auth_openfile(const char *file, struct passwd *pw, int strict_modes,
auth_debug_add("Ignored %s: %s", file_type, line);
return NULL;
}
+#endif /* !WINDOWS */
return f;
}
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index 20f3309e1..949a864ac 100644
--- a/auth2-pubkey.c
+++ b/auth2-pubkey.c
@@ -175,6 +175,51 @@ userauth_pubkey(Authctxt *authctxt)
/* test for correct signature */
authenticated = 0;
+
+#ifdef WINDOWS
+ /* Pass key challenge material to ssh-agent to retrieve token upon succesful authentication */
+ {
+ extern int auth_sock;
+ int r;
+ u_char *blob = NULL;
+ size_t blen = 0;
+ DWORD token = 0;
+ struct sshbuf *msg = NULL;
+
+ while (1) {
+ msg = sshbuf_new();
+ if (!msg)
+ break;
+ if ((r = sshbuf_put_u8(msg, 100)) != 0 ||
+ (r = sshbuf_put_cstring(msg, "pubkey")) != 0 ||
+ (r = sshkey_to_blob(key, &blob, &blen)) != 0 ||
+ (r = sshbuf_put_string(msg, blob, blen)) != 0 ||
+ (r = sshbuf_put_cstring(msg, authctxt->pw->pw_name)) != 0 ||
+ (r = sshbuf_put_string(msg, sig, slen)) != 0 ||
+ (r = sshbuf_put_string(msg, buffer_ptr(&b), buffer_len(&b))) != 0 ||
+ (r = ssh_request_reply(auth_sock, msg, msg)) != 0 ||
+ (r = sshbuf_get_u32(msg, &token)) != 0) {
+ debug("auth agent did not authorize client %s", authctxt->pw->pw_name);
+ break;
+ }
+
+ debug3("auth agent authenticated %s", authctxt->pw->pw_name);
+ break;
+
+ }
+ if (blob)
+ free(blob);
+ if (msg)
+ sshbuf_free(msg);
+
+ if (token) {
+ authenticated = 1;
+ authctxt->methoddata = (void*)(INT_PTR)token;
+ }
+
+ }
+
+#else /* !WINDOWS */
if (PRIVSEP(user_key_allowed(authctxt->pw, key, 1)) &&
PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
buffer_len(&b))) == 1) {
@@ -185,6 +230,8 @@ userauth_pubkey(Authctxt *authctxt)
}
buffer_free(&b);
free(sig);
+#endif /* !WINDOWS */
+
} else {
debug("%s: test whether pkalg/pkblob are acceptable for %s %s",
__func__, sshkey_type(key), fp);
@@ -198,7 +245,11 @@ userauth_pubkey(Authctxt *authctxt)
* if a user is not allowed to login. is this an
* issue? -markus
*/
+#ifdef WINDOWS /* key validation in done in agent for Windows */
+ {
+#else /* !WINDOWS */
if (PRIVSEP(user_key_allowed(authctxt->pw, key, 0))) {
+#endif /* !WINDOWS */
packet_start(SSH2_MSG_USERAUTH_PK_OK);
packet_put_string(pkalg, alen);
packet_put_string(pkblob, blen);
@@ -395,6 +446,10 @@ static pid_t
subprocess(const char *tag, struct passwd *pw, const char *command,
int ac, char **av, FILE **child)
{
+#ifdef WINDOWS
+ logit("AuthorizedPrincipalsCommand and AuthorizedKeysCommand are not supported in Windows yet");
+ return 0;
+#else /* !WINDOWS */
FILE *f;
struct stat st;
int devnull, p[2], i;
@@ -514,6 +569,7 @@ subprocess(const char *tag, struct passwd *pw, const char *command,
debug3("%s: %s pid %ld", __func__, tag, (long)pid);
*child = f;
return pid;
+#endif /* !WINDOWS */
}
/* Returns 0 if pid exited cleanly, non-zero otherwise */
diff --git a/authfd.c b/authfd.c
index a634bcb81..b6ec0ffcd 100644
--- a/authfd.c
+++ b/authfd.c
@@ -94,6 +94,42 @@ ssh_get_authentication_socket(int *fdp)
if (fdp != NULL)
*fdp = -1;
+#ifdef WINDOWS
+ /* Auth socket in Windows is a static-named pipe listener in ssh-agent */
+ {
+#define SSH_AGENT_REG_ROOT L"SOFTWARE\\SSH\\Agent"
+#define SSH_AGENT_PIPE_NAME L"\\\\.\\pipe\\ssh-agent"
+ HKEY agent_root = 0;
+ DWORD agent_pid = 0, tmp_size = 4, pipe_server_pid = 0xff;
+ HANDLE h;
+ RegOpenKeyExW(HKEY_LOCAL_MACHINE, SSH_AGENT_REG_ROOT, 0, KEY_QUERY_VALUE, &agent_root);
+ if (agent_root) {
+ RegQueryValueEx(agent_root, "ProcessId", 0, NULL, (LPBYTE)&agent_pid, &tmp_size);
+ RegCloseKey(agent_root);
+ }
+
+ h = CreateFileW(SSH_AGENT_PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0,
+ NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ return SSH_ERR_AGENT_NOT_PRESENT;
+
+ /*
+ * ensure that connected server pid matches published pid. this provides service side
+ * auth and prevents mitm
+ */
+ if (!GetNamedPipeServerProcessId(h, &pipe_server_pid) || (agent_pid != pipe_server_pid)) {
+ debug("agent pid mismatch");
+ CloseHandle(h);
+ return SSH_ERR_AGENT_COMMUNICATION;
+ }
+
+ /* alloc fd for pipe handle */
+ if ((sock = w32_allocate_fd_for_handle(h, FALSE)) < 0) {
+ CloseHandle(h);
+ return SSH_ERR_SYSTEM_ERROR;
+ }
+ }
+#else /* !WINDOWS */
authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
if (!authsocket)
return SSH_ERR_AGENT_NOT_PRESENT;
@@ -113,6 +149,8 @@ ssh_get_authentication_socket(int *fdp)
errno = oerrno;
return SSH_ERR_SYSTEM_ERROR;
}
+#endif /* !WINDOWS */
+
if (fdp != NULL)
*fdp = sock;
else
@@ -121,7 +159,12 @@ ssh_get_authentication_socket(int *fdp)
}
/* Communicate with agent: send request and read reply */
+#ifdef WINDOWS
+/* for Windows we need to access this function from other places to talk to agent*/
+int
+#else /* !WINDOWS */
static int
+#endif /* !WINDOWS */
ssh_request_reply(int sock, struct sshbuf *request, struct sshbuf *reply)
{
int r;
diff --git a/authfile.c b/authfile.c
index 7411b68f6..255907e4e 100644
--- a/authfile.c
+++ b/authfile.c
@@ -193,6 +193,8 @@ sshkey_perm_ok(int fd, const char *filename)
#ifdef HAVE_CYGWIN
if (check_ntsec(filename))
#endif
+
+#ifndef WINDOWS /*TODO - implement permission checks on Windows*/
if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) {
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @");
@@ -203,6 +205,7 @@ sshkey_perm_ok(int fd, const char *filename)
error("This private key will be ignored.");
return SSH_ERR_KEY_BAD_PERMISSIONS;
}
+#endif /* !WINDOWS */
return 0;
}
diff --git a/buffer.c b/buffer.c
index c5f708ab2..8734fae26 100644
--- a/buffer.c
+++ b/buffer.c
@@ -56,6 +56,7 @@ buffer_check_alloc(Buffer *buffer, u_int len)
if (ret == SSH_ERR_NO_BUFFER_SPACE)
return 0;
fatal("%s: %s", __func__, ssh_err(ret));
+ return -1;
}
int
@@ -87,6 +88,7 @@ buffer_consume_ret(Buffer *buffer, u_int bytes)
if (ret == SSH_ERR_MESSAGE_INCOMPLETE)
return -1;
fatal("%s: %s", __func__, ssh_err(ret));
+ return -1;
}
void
@@ -106,6 +108,7 @@ buffer_consume_end_ret(Buffer *buffer, u_int bytes)
if (ret == SSH_ERR_MESSAGE_INCOMPLETE)
return -1;
fatal("%s: %s", __func__, ssh_err(ret));
+ return -1;
}
void
diff --git a/channels.c b/channels.c
index bef8ad6aa..ef4018b0e 100644
--- a/channels.c
+++ b/channels.c
@@ -2050,6 +2050,7 @@ channel_post_mux_listener(Channel *c, fd_set *readset, fd_set *writeset)
return;
}
+#ifndef WINDOWS /*TODO - implement user check for Windows*/
if (getpeereid(newsock, &euid, &egid) < 0) {
error("%s getpeereid failed: %s", __func__,
strerror(errno));
@@ -2062,6 +2063,7 @@ channel_post_mux_listener(Channel *c, fd_set *readset, fd_set *writeset)
close(newsock);
return;
}
+#endif /* !WINDOWS */
nc = channel_new("multiplex client", SSH_CHANNEL_MUX_CLIENT,
newsock, newsock, -1, c->local_window_max,
c->local_maxpacket, 0, "mux-control", 1);
diff --git a/clientloop.c b/clientloop.c
index 4289a4081..5bec8c0f4 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1219,6 +1219,9 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
continue;
case '&':
+#ifdef WINDOWS
+ fatal("Background execution is not supported in Windows");
+#else /* !WINDOWS */
if (c && c->ctl_chan != -1)
goto noescape;
/*
@@ -1269,6 +1272,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
}
}
continue;
+#endif /* !WINDOWS */
case '?':
print_escape_help(berr, escape_char, compat20,
diff --git a/contrib/win32/openssh/README.txt b/contrib/win32/openssh/README.txt
new file mode 100644
index 000000000..97ebd10a4
--- /dev/null
+++ b/contrib/win32/openssh/README.txt
@@ -0,0 +1,22 @@
+Custom paths for the visual studio projects are defined in paths.targets.
+
+All projects import this targets file, and it should be in the same directory as the project.
+
+The custom paths are:
+
+OpenSSH-Src-Path = The directory path of the OpenSSH root source directory (with trailing slash)
+OpenSSH-Bin-Path = The directory path of the location to which binaries are placed. This is the output of the binary projects
+OpenSSH-Lib-Path = The directory path of the location to which libraries are placed. This is the output of the libary projects
+OpenSSL-Win32-Release-Path = The directory path of OpenSSL statically linked compiled for Win32-Release. This path is used for
+ include and library paths and for Win32-Release.
+OpenSSL-Win32-Debug-Path = The directory path of OpenSSL statically linked compiled for Win32-Debug. This path is used for
+ include and library paths and for Win32-Debug.
+OpenSSL-x64-Release-Path = The directory path of OpenSSL statically linked compiled for x64-Release. This path is used for
+ include and library paths and for x64-Release.
+OpenSSL-x64-Debug-Path = The directory path of OpenSSL statically linked compiled for x64-Debug. This path is used for
+ include and library paths and for x64-Debug.
+
+
+
+The Release/Debug OpenSSL directories output is the standard 'install' output of OpenSSL compiled under Visual Studio 2015 using static c-runtimes.
+
diff --git a/contrib/win32/openssh/VSWithBuildTools.xml b/contrib/win32/openssh/VSWithBuildTools.xml
new file mode 100644
index 000000000..279fedf85
--- /dev/null
+++ b/contrib/win32/openssh/VSWithBuildTools.xml
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/contrib/win32/openssh/Win32-OpenSSH.sln b/contrib/win32/openssh/Win32-OpenSSH.sln
new file mode 100644
index 000000000..ee8c928b7
--- /dev/null
+++ b/contrib/win32/openssh/Win32-OpenSSH.sln
@@ -0,0 +1,343 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25123.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssh", "ssh.vcxproj", "{74E69D5E-A1EF-46EA-9173-19A412774104}"
+ ProjectSection(ProjectDependencies) = postProject
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7} = {05E1115F-8529-46D0-AAAF-52A404CE79A7}
+ {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4} = {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}
+ {DD483F7D-C553-4740-BC1A-903805AD0174} = {DD483F7D-C553-4740-BC1A-903805AD0174}
+ {0D02F0F0-013B-4EE3-906D-86517F3822C0} = {0D02F0F0-013B-4EE3-906D-86517F3822C0}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libssh", "libssh.vcxproj", "{05E1115F-8529-46D0-AAAF-52A404CE79A7}"
+ ProjectSection(ProjectDependencies) = postProject
+ {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4} = {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openbsd_compat", "openbsd_compat.vcxproj", "{DD483F7D-C553-4740-BC1A-903805AD0174}"
+ ProjectSection(ProjectDependencies) = postProject
+ {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4} = {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssh-keygen", "keygen.vcxproj", "{47496135-131B-41D6-BF2B-EE7144873DD0}"
+ ProjectSection(ProjectDependencies) = postProject
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7} = {05E1115F-8529-46D0-AAAF-52A404CE79A7}
+ {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4} = {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}
+ {DD483F7D-C553-4740-BC1A-903805AD0174} = {DD483F7D-C553-4740-BC1A-903805AD0174}
+ {0D02F0F0-013B-4EE3-906D-86517F3822C0} = {0D02F0F0-013B-4EE3-906D-86517F3822C0}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sftp", "sftp.vcxproj", "{BBEFF9D7-0BC3-41D1-908B-8052158B5052}"
+ ProjectSection(ProjectDependencies) = postProject
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7} = {05E1115F-8529-46D0-AAAF-52A404CE79A7}
+ {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4} = {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}
+ {DD483F7D-C553-4740-BC1A-903805AD0174} = {DD483F7D-C553-4740-BC1A-903805AD0174}
+ {0D02F0F0-013B-4EE3-906D-86517F3822C0} = {0D02F0F0-013B-4EE3-906D-86517F3822C0}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sftp-server", "sftp-server.vcxproj", "{6657614F-7821-4D55-96EF-7C3C4B551880}"
+ ProjectSection(ProjectDependencies) = postProject
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7} = {05E1115F-8529-46D0-AAAF-52A404CE79A7}
+ {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4} = {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}
+ {DD483F7D-C553-4740-BC1A-903805AD0174} = {DD483F7D-C553-4740-BC1A-903805AD0174}
+ {0D02F0F0-013B-4EE3-906D-86517F3822C0} = {0D02F0F0-013B-4EE3-906D-86517F3822C0}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sshd", "sshd.vcxproj", "{F58FF6BA-098B-4DB9-9609-A030DFB4D03F}"
+ ProjectSection(ProjectDependencies) = postProject
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7} = {05E1115F-8529-46D0-AAAF-52A404CE79A7}
+ {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4} = {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}
+ {DD483F7D-C553-4740-BC1A-903805AD0174} = {DD483F7D-C553-4740-BC1A-903805AD0174}
+ {0D02F0F0-013B-4EE3-906D-86517F3822C0} = {0D02F0F0-013B-4EE3-906D-86517F3822C0}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "config", "config.vcxproj", "{8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssh-lsa", "ssh-lsa.vcxproj", "{02FB3D98-6516-42C6-9762-98811A99960F}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "posix_compat", "win32iocompat.vcxproj", "{0D02F0F0-013B-4EE3-906D-86517F3822C0}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssh-shellhost", "ssh-shellhost.vcxproj", "{C0AE8A30-E4FA-49CE-A2B5-0C072C77EC64}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssh-agent", "ssh-agent.vcxproj", "{F6644EC5-D6B6-42A1-828C-75E2977470E0}"
+ ProjectSection(ProjectDependencies) = postProject
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7} = {05E1115F-8529-46D0-AAAF-52A404CE79A7}
+ {DD483F7D-C553-4740-BC1A-903805AD0174} = {DD483F7D-C553-4740-BC1A-903805AD0174}
+ {0D02F0F0-013B-4EE3-906D-86517F3822C0} = {0D02F0F0-013B-4EE3-906D-86517F3822C0}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssh-add", "ssh-add.vcxproj", "{029797FF-C986-43DE-95CD-2E771E86AEBC}"
+ ProjectSection(ProjectDependencies) = postProject
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7} = {05E1115F-8529-46D0-AAAF-52A404CE79A7}
+ {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4} = {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}
+ {DD483F7D-C553-4740-BC1A-903805AD0174} = {DD483F7D-C553-4740-BC1A-903805AD0174}
+ {0D02F0F0-013B-4EE3-906D-86517F3822C0} = {0D02F0F0-013B-4EE3-906D-86517F3822C0}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scp", "scp.vcxproj", "{29B98ADF-1285-49CE-BF6C-AA92C5D2FB24}"
+ ProjectSection(ProjectDependencies) = postProject
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7} = {05E1115F-8529-46D0-AAAF-52A404CE79A7}
+ {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4} = {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}
+ {DD483F7D-C553-4740-BC1A-903805AD0174} = {DD483F7D-C553-4740-BC1A-903805AD0174}
+ {0D02F0F0-013B-4EE3-906D-86517F3822C0} = {0D02F0F0-013B-4EE3-906D-86517F3822C0}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unittest-bitmap", "unittest-bitmap.vcxproj", "{D901596E-76C7-4608-9CFA-2B42A9FD7250}"
+ ProjectSection(ProjectDependencies) = postProject
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7} = {05E1115F-8529-46D0-AAAF-52A404CE79A7}
+ {DD483F7D-C553-4740-BC1A-903805AD0174} = {DD483F7D-C553-4740-BC1A-903805AD0174}
+ {0D02F0F0-013B-4EE3-906D-86517F3822C0} = {0D02F0F0-013B-4EE3-906D-86517F3822C0}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unittest-kex", "unittest-kex.vcxproj", "{8EC56B06-5A9A-4D6D-804D-037FE26FD43E}"
+ ProjectSection(ProjectDependencies) = postProject
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7} = {05E1115F-8529-46D0-AAAF-52A404CE79A7}
+ {DD483F7D-C553-4740-BC1A-903805AD0174} = {DD483F7D-C553-4740-BC1A-903805AD0174}
+ {0D02F0F0-013B-4EE3-906D-86517F3822C0} = {0D02F0F0-013B-4EE3-906D-86517F3822C0}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unittest-sshbuf", "unittest-sshbuf.vcxproj", "{CD9740CE-C96E-49B3-823F-012E09D17806}"
+ ProjectSection(ProjectDependencies) = postProject
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7} = {05E1115F-8529-46D0-AAAF-52A404CE79A7}
+ {DD483F7D-C553-4740-BC1A-903805AD0174} = {DD483F7D-C553-4740-BC1A-903805AD0174}
+ {0D02F0F0-013B-4EE3-906D-86517F3822C0} = {0D02F0F0-013B-4EE3-906D-86517F3822C0}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unittest-win32compat", "unittest-win32compat.vcxproj", "{BF295BA9-4BF8-43F8-8CBF-FAE84815466C}"
+ ProjectSection(ProjectDependencies) = postProject
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7} = {05E1115F-8529-46D0-AAAF-52A404CE79A7}
+ {DD483F7D-C553-4740-BC1A-903805AD0174} = {DD483F7D-C553-4740-BC1A-903805AD0174}
+ {0D02F0F0-013B-4EE3-906D-86517F3822C0} = {0D02F0F0-013B-4EE3-906D-86517F3822C0}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unittest-utf8", "unittest-utf8.vcxproj", "{114CAA59-46C0-4B87-BA86-C1946A68101D}"
+ ProjectSection(ProjectDependencies) = postProject
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7} = {05E1115F-8529-46D0-AAAF-52A404CE79A7}
+ {DD483F7D-C553-4740-BC1A-903805AD0174} = {DD483F7D-C553-4740-BC1A-903805AD0174}
+ {0D02F0F0-013B-4EE3-906D-86517F3822C0} = {0D02F0F0-013B-4EE3-906D-86517F3822C0}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unittest-hostkeys", "unittest-hostkeys.vcxproj", "{890C6129-286F-4CD8-8252-FB8D3B4E6E1B}"
+ ProjectSection(ProjectDependencies) = postProject
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7} = {05E1115F-8529-46D0-AAAF-52A404CE79A7}
+ {DD483F7D-C553-4740-BC1A-903805AD0174} = {DD483F7D-C553-4740-BC1A-903805AD0174}
+ {0D02F0F0-013B-4EE3-906D-86517F3822C0} = {0D02F0F0-013B-4EE3-906D-86517F3822C0}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unittest-sshkey", "unittest-sshkey.vcxproj", "{FC568FF0-60F2-4B2E-AF62-FD392EDBA1B9}"
+ ProjectSection(ProjectDependencies) = postProject
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7} = {05E1115F-8529-46D0-AAAF-52A404CE79A7}
+ {DD483F7D-C553-4740-BC1A-903805AD0174} = {DD483F7D-C553-4740-BC1A-903805AD0174}
+ {0D02F0F0-013B-4EE3-906D-86517F3822C0} = {0D02F0F0-013B-4EE3-906D-86517F3822C0}
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "core", "core", "{17322AAF-808F-4646-AD37-5B0EDDCB8F3E}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{A8096E32-E084-4FA0-AE01-A8D909EB2BB4}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {74E69D5E-A1EF-46EA-9173-19A412774104}.Debug|x64.ActiveCfg = Debug|x64
+ {74E69D5E-A1EF-46EA-9173-19A412774104}.Debug|x64.Build.0 = Debug|x64
+ {74E69D5E-A1EF-46EA-9173-19A412774104}.Debug|x86.ActiveCfg = Debug|Win32
+ {74E69D5E-A1EF-46EA-9173-19A412774104}.Debug|x86.Build.0 = Debug|Win32
+ {74E69D5E-A1EF-46EA-9173-19A412774104}.Release|x64.ActiveCfg = Release|x64
+ {74E69D5E-A1EF-46EA-9173-19A412774104}.Release|x64.Build.0 = Release|x64
+ {74E69D5E-A1EF-46EA-9173-19A412774104}.Release|x86.ActiveCfg = Release|Win32
+ {74E69D5E-A1EF-46EA-9173-19A412774104}.Release|x86.Build.0 = Release|Win32
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7}.Debug|x64.ActiveCfg = Debug|x64
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7}.Debug|x64.Build.0 = Debug|x64
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7}.Debug|x86.ActiveCfg = Debug|Win32
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7}.Debug|x86.Build.0 = Debug|Win32
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7}.Release|x64.ActiveCfg = Release|x64
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7}.Release|x64.Build.0 = Release|x64
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7}.Release|x86.ActiveCfg = Release|Win32
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7}.Release|x86.Build.0 = Release|Win32
+ {DD483F7D-C553-4740-BC1A-903805AD0174}.Debug|x64.ActiveCfg = Debug|x64
+ {DD483F7D-C553-4740-BC1A-903805AD0174}.Debug|x64.Build.0 = Debug|x64
+ {DD483F7D-C553-4740-BC1A-903805AD0174}.Debug|x86.ActiveCfg = Debug|Win32
+ {DD483F7D-C553-4740-BC1A-903805AD0174}.Debug|x86.Build.0 = Debug|Win32
+ {DD483F7D-C553-4740-BC1A-903805AD0174}.Release|x64.ActiveCfg = Release|x64
+ {DD483F7D-C553-4740-BC1A-903805AD0174}.Release|x64.Build.0 = Release|x64
+ {DD483F7D-C553-4740-BC1A-903805AD0174}.Release|x86.ActiveCfg = Release|Win32
+ {DD483F7D-C553-4740-BC1A-903805AD0174}.Release|x86.Build.0 = Release|Win32
+ {47496135-131B-41D6-BF2B-EE7144873DD0}.Debug|x64.ActiveCfg = Debug|x64
+ {47496135-131B-41D6-BF2B-EE7144873DD0}.Debug|x64.Build.0 = Debug|x64
+ {47496135-131B-41D6-BF2B-EE7144873DD0}.Debug|x86.ActiveCfg = Debug|Win32
+ {47496135-131B-41D6-BF2B-EE7144873DD0}.Debug|x86.Build.0 = Debug|Win32
+ {47496135-131B-41D6-BF2B-EE7144873DD0}.Release|x64.ActiveCfg = Release|x64
+ {47496135-131B-41D6-BF2B-EE7144873DD0}.Release|x64.Build.0 = Release|x64
+ {47496135-131B-41D6-BF2B-EE7144873DD0}.Release|x86.ActiveCfg = Release|Win32
+ {47496135-131B-41D6-BF2B-EE7144873DD0}.Release|x86.Build.0 = Release|Win32
+ {BBEFF9D7-0BC3-41D1-908B-8052158B5052}.Debug|x64.ActiveCfg = Debug|x64
+ {BBEFF9D7-0BC3-41D1-908B-8052158B5052}.Debug|x64.Build.0 = Debug|x64
+ {BBEFF9D7-0BC3-41D1-908B-8052158B5052}.Debug|x86.ActiveCfg = Debug|Win32
+ {BBEFF9D7-0BC3-41D1-908B-8052158B5052}.Debug|x86.Build.0 = Debug|Win32
+ {BBEFF9D7-0BC3-41D1-908B-8052158B5052}.Release|x64.ActiveCfg = Release|x64
+ {BBEFF9D7-0BC3-41D1-908B-8052158B5052}.Release|x64.Build.0 = Release|x64
+ {BBEFF9D7-0BC3-41D1-908B-8052158B5052}.Release|x86.ActiveCfg = Release|Win32
+ {BBEFF9D7-0BC3-41D1-908B-8052158B5052}.Release|x86.Build.0 = Release|Win32
+ {6657614F-7821-4D55-96EF-7C3C4B551880}.Debug|x64.ActiveCfg = Debug|x64
+ {6657614F-7821-4D55-96EF-7C3C4B551880}.Debug|x64.Build.0 = Debug|x64
+ {6657614F-7821-4D55-96EF-7C3C4B551880}.Debug|x86.ActiveCfg = Debug|Win32
+ {6657614F-7821-4D55-96EF-7C3C4B551880}.Debug|x86.Build.0 = Debug|Win32
+ {6657614F-7821-4D55-96EF-7C3C4B551880}.Release|x64.ActiveCfg = Release|x64
+ {6657614F-7821-4D55-96EF-7C3C4B551880}.Release|x64.Build.0 = Release|x64
+ {6657614F-7821-4D55-96EF-7C3C4B551880}.Release|x86.ActiveCfg = Release|Win32
+ {6657614F-7821-4D55-96EF-7C3C4B551880}.Release|x86.Build.0 = Release|Win32
+ {F58FF6BA-098B-4DB9-9609-A030DFB4D03F}.Debug|x64.ActiveCfg = Debug|x64
+ {F58FF6BA-098B-4DB9-9609-A030DFB4D03F}.Debug|x64.Build.0 = Debug|x64
+ {F58FF6BA-098B-4DB9-9609-A030DFB4D03F}.Debug|x86.ActiveCfg = Debug|Win32
+ {F58FF6BA-098B-4DB9-9609-A030DFB4D03F}.Debug|x86.Build.0 = Debug|Win32
+ {F58FF6BA-098B-4DB9-9609-A030DFB4D03F}.Release|x64.ActiveCfg = Release|x64
+ {F58FF6BA-098B-4DB9-9609-A030DFB4D03F}.Release|x64.Build.0 = Release|x64
+ {F58FF6BA-098B-4DB9-9609-A030DFB4D03F}.Release|x86.ActiveCfg = Release|Win32
+ {F58FF6BA-098B-4DB9-9609-A030DFB4D03F}.Release|x86.Build.0 = Release|Win32
+ {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}.Debug|x64.ActiveCfg = Debug|x64
+ {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}.Debug|x64.Build.0 = Debug|x64
+ {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}.Debug|x86.ActiveCfg = Debug|Win32
+ {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}.Debug|x86.Build.0 = Debug|Win32
+ {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}.Release|x64.ActiveCfg = Release|x64
+ {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}.Release|x64.Build.0 = Release|x64
+ {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}.Release|x86.ActiveCfg = Release|Win32
+ {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}.Release|x86.Build.0 = Release|Win32
+ {02FB3D98-6516-42C6-9762-98811A99960F}.Debug|x64.ActiveCfg = Debug|x64
+ {02FB3D98-6516-42C6-9762-98811A99960F}.Debug|x64.Build.0 = Debug|x64
+ {02FB3D98-6516-42C6-9762-98811A99960F}.Debug|x86.ActiveCfg = Debug|Win32
+ {02FB3D98-6516-42C6-9762-98811A99960F}.Debug|x86.Build.0 = Debug|Win32
+ {02FB3D98-6516-42C6-9762-98811A99960F}.Release|x64.ActiveCfg = Release|x64
+ {02FB3D98-6516-42C6-9762-98811A99960F}.Release|x64.Build.0 = Release|x64
+ {02FB3D98-6516-42C6-9762-98811A99960F}.Release|x86.ActiveCfg = Release|Win32
+ {02FB3D98-6516-42C6-9762-98811A99960F}.Release|x86.Build.0 = Release|Win32
+ {0D02F0F0-013B-4EE3-906D-86517F3822C0}.Debug|x64.ActiveCfg = Debug|x64
+ {0D02F0F0-013B-4EE3-906D-86517F3822C0}.Debug|x64.Build.0 = Debug|x64
+ {0D02F0F0-013B-4EE3-906D-86517F3822C0}.Debug|x86.ActiveCfg = Debug|Win32
+ {0D02F0F0-013B-4EE3-906D-86517F3822C0}.Debug|x86.Build.0 = Debug|Win32
+ {0D02F0F0-013B-4EE3-906D-86517F3822C0}.Release|x64.ActiveCfg = Release|x64
+ {0D02F0F0-013B-4EE3-906D-86517F3822C0}.Release|x64.Build.0 = Release|x64
+ {0D02F0F0-013B-4EE3-906D-86517F3822C0}.Release|x86.ActiveCfg = Release|Win32
+ {0D02F0F0-013B-4EE3-906D-86517F3822C0}.Release|x86.Build.0 = Release|Win32
+ {C0AE8A30-E4FA-49CE-A2B5-0C072C77EC64}.Debug|x64.ActiveCfg = Debug|x64
+ {C0AE8A30-E4FA-49CE-A2B5-0C072C77EC64}.Debug|x64.Build.0 = Debug|x64
+ {C0AE8A30-E4FA-49CE-A2B5-0C072C77EC64}.Debug|x86.ActiveCfg = Debug|Win32
+ {C0AE8A30-E4FA-49CE-A2B5-0C072C77EC64}.Debug|x86.Build.0 = Debug|Win32
+ {C0AE8A30-E4FA-49CE-A2B5-0C072C77EC64}.Release|x64.ActiveCfg = Release|x64
+ {C0AE8A30-E4FA-49CE-A2B5-0C072C77EC64}.Release|x64.Build.0 = Release|x64
+ {C0AE8A30-E4FA-49CE-A2B5-0C072C77EC64}.Release|x86.ActiveCfg = Release|Win32
+ {C0AE8A30-E4FA-49CE-A2B5-0C072C77EC64}.Release|x86.Build.0 = Release|Win32
+ {F6644EC5-D6B6-42A1-828C-75E2977470E0}.Debug|x64.ActiveCfg = Debug|x64
+ {F6644EC5-D6B6-42A1-828C-75E2977470E0}.Debug|x64.Build.0 = Debug|x64
+ {F6644EC5-D6B6-42A1-828C-75E2977470E0}.Debug|x86.ActiveCfg = Debug|Win32
+ {F6644EC5-D6B6-42A1-828C-75E2977470E0}.Debug|x86.Build.0 = Debug|Win32
+ {F6644EC5-D6B6-42A1-828C-75E2977470E0}.Release|x64.ActiveCfg = Release|x64
+ {F6644EC5-D6B6-42A1-828C-75E2977470E0}.Release|x64.Build.0 = Release|x64
+ {F6644EC5-D6B6-42A1-828C-75E2977470E0}.Release|x86.ActiveCfg = Release|Win32
+ {F6644EC5-D6B6-42A1-828C-75E2977470E0}.Release|x86.Build.0 = Release|Win32
+ {029797FF-C986-43DE-95CD-2E771E86AEBC}.Debug|x64.ActiveCfg = Debug|x64
+ {029797FF-C986-43DE-95CD-2E771E86AEBC}.Debug|x64.Build.0 = Debug|x64
+ {029797FF-C986-43DE-95CD-2E771E86AEBC}.Debug|x86.ActiveCfg = Debug|Win32
+ {029797FF-C986-43DE-95CD-2E771E86AEBC}.Debug|x86.Build.0 = Debug|Win32
+ {029797FF-C986-43DE-95CD-2E771E86AEBC}.Release|x64.ActiveCfg = Release|x64
+ {029797FF-C986-43DE-95CD-2E771E86AEBC}.Release|x64.Build.0 = Release|x64
+ {029797FF-C986-43DE-95CD-2E771E86AEBC}.Release|x86.ActiveCfg = Release|Win32
+ {029797FF-C986-43DE-95CD-2E771E86AEBC}.Release|x86.Build.0 = Release|Win32
+ {29B98ADF-1285-49CE-BF6C-AA92C5D2FB24}.Debug|x64.ActiveCfg = Debug|x64
+ {29B98ADF-1285-49CE-BF6C-AA92C5D2FB24}.Debug|x64.Build.0 = Debug|x64
+ {29B98ADF-1285-49CE-BF6C-AA92C5D2FB24}.Debug|x86.ActiveCfg = Debug|Win32
+ {29B98ADF-1285-49CE-BF6C-AA92C5D2FB24}.Debug|x86.Build.0 = Debug|Win32
+ {29B98ADF-1285-49CE-BF6C-AA92C5D2FB24}.Release|x64.ActiveCfg = Release|x64
+ {29B98ADF-1285-49CE-BF6C-AA92C5D2FB24}.Release|x64.Build.0 = Release|x64
+ {29B98ADF-1285-49CE-BF6C-AA92C5D2FB24}.Release|x86.ActiveCfg = Release|Win32
+ {29B98ADF-1285-49CE-BF6C-AA92C5D2FB24}.Release|x86.Build.0 = Release|Win32
+ {D901596E-76C7-4608-9CFA-2B42A9FD7250}.Debug|x64.ActiveCfg = Debug|x64
+ {D901596E-76C7-4608-9CFA-2B42A9FD7250}.Debug|x64.Build.0 = Debug|x64
+ {D901596E-76C7-4608-9CFA-2B42A9FD7250}.Debug|x86.ActiveCfg = Debug|Win32
+ {D901596E-76C7-4608-9CFA-2B42A9FD7250}.Debug|x86.Build.0 = Debug|Win32
+ {D901596E-76C7-4608-9CFA-2B42A9FD7250}.Release|x64.ActiveCfg = Release|x64
+ {D901596E-76C7-4608-9CFA-2B42A9FD7250}.Release|x64.Build.0 = Release|x64
+ {D901596E-76C7-4608-9CFA-2B42A9FD7250}.Release|x86.ActiveCfg = Release|Win32
+ {D901596E-76C7-4608-9CFA-2B42A9FD7250}.Release|x86.Build.0 = Release|Win32
+ {8EC56B06-5A9A-4D6D-804D-037FE26FD43E}.Debug|x64.ActiveCfg = Debug|x64
+ {8EC56B06-5A9A-4D6D-804D-037FE26FD43E}.Debug|x64.Build.0 = Debug|x64
+ {8EC56B06-5A9A-4D6D-804D-037FE26FD43E}.Debug|x86.ActiveCfg = Debug|Win32
+ {8EC56B06-5A9A-4D6D-804D-037FE26FD43E}.Debug|x86.Build.0 = Debug|Win32
+ {8EC56B06-5A9A-4D6D-804D-037FE26FD43E}.Release|x64.ActiveCfg = Release|x64
+ {8EC56B06-5A9A-4D6D-804D-037FE26FD43E}.Release|x64.Build.0 = Release|x64
+ {8EC56B06-5A9A-4D6D-804D-037FE26FD43E}.Release|x86.ActiveCfg = Release|Win32
+ {8EC56B06-5A9A-4D6D-804D-037FE26FD43E}.Release|x86.Build.0 = Release|Win32
+ {CD9740CE-C96E-49B3-823F-012E09D17806}.Debug|x64.ActiveCfg = Debug|x64
+ {CD9740CE-C96E-49B3-823F-012E09D17806}.Debug|x64.Build.0 = Debug|x64
+ {CD9740CE-C96E-49B3-823F-012E09D17806}.Debug|x86.ActiveCfg = Debug|Win32
+ {CD9740CE-C96E-49B3-823F-012E09D17806}.Debug|x86.Build.0 = Debug|Win32
+ {CD9740CE-C96E-49B3-823F-012E09D17806}.Release|x64.ActiveCfg = Release|x64
+ {CD9740CE-C96E-49B3-823F-012E09D17806}.Release|x64.Build.0 = Release|x64
+ {CD9740CE-C96E-49B3-823F-012E09D17806}.Release|x86.ActiveCfg = Release|Win32
+ {CD9740CE-C96E-49B3-823F-012E09D17806}.Release|x86.Build.0 = Release|Win32
+ {BF295BA9-4BF8-43F8-8CBF-FAE84815466C}.Debug|x64.ActiveCfg = Debug|x64
+ {BF295BA9-4BF8-43F8-8CBF-FAE84815466C}.Debug|x64.Build.0 = Debug|x64
+ {BF295BA9-4BF8-43F8-8CBF-FAE84815466C}.Debug|x86.ActiveCfg = Debug|Win32
+ {BF295BA9-4BF8-43F8-8CBF-FAE84815466C}.Debug|x86.Build.0 = Debug|Win32
+ {BF295BA9-4BF8-43F8-8CBF-FAE84815466C}.Release|x64.ActiveCfg = Release|x64
+ {BF295BA9-4BF8-43F8-8CBF-FAE84815466C}.Release|x64.Build.0 = Release|x64
+ {BF295BA9-4BF8-43F8-8CBF-FAE84815466C}.Release|x86.ActiveCfg = Release|Win32
+ {BF295BA9-4BF8-43F8-8CBF-FAE84815466C}.Release|x86.Build.0 = Release|Win32
+ {114CAA59-46C0-4B87-BA86-C1946A68101D}.Debug|x64.ActiveCfg = Debug|x64
+ {114CAA59-46C0-4B87-BA86-C1946A68101D}.Debug|x64.Build.0 = Debug|x64
+ {114CAA59-46C0-4B87-BA86-C1946A68101D}.Debug|x86.ActiveCfg = Debug|Win32
+ {114CAA59-46C0-4B87-BA86-C1946A68101D}.Debug|x86.Build.0 = Debug|Win32
+ {114CAA59-46C0-4B87-BA86-C1946A68101D}.Release|x64.ActiveCfg = Release|x64
+ {114CAA59-46C0-4B87-BA86-C1946A68101D}.Release|x64.Build.0 = Release|x64
+ {114CAA59-46C0-4B87-BA86-C1946A68101D}.Release|x86.ActiveCfg = Release|Win32
+ {114CAA59-46C0-4B87-BA86-C1946A68101D}.Release|x86.Build.0 = Release|Win32
+ {890C6129-286F-4CD8-8252-FB8D3B4E6E1B}.Debug|x64.ActiveCfg = Debug|x64
+ {890C6129-286F-4CD8-8252-FB8D3B4E6E1B}.Debug|x64.Build.0 = Debug|x64
+ {890C6129-286F-4CD8-8252-FB8D3B4E6E1B}.Debug|x86.ActiveCfg = Debug|Win32
+ {890C6129-286F-4CD8-8252-FB8D3B4E6E1B}.Debug|x86.Build.0 = Debug|Win32
+ {890C6129-286F-4CD8-8252-FB8D3B4E6E1B}.Release|x64.ActiveCfg = Release|x64
+ {890C6129-286F-4CD8-8252-FB8D3B4E6E1B}.Release|x64.Build.0 = Release|x64
+ {890C6129-286F-4CD8-8252-FB8D3B4E6E1B}.Release|x86.ActiveCfg = Release|Win32
+ {890C6129-286F-4CD8-8252-FB8D3B4E6E1B}.Release|x86.Build.0 = Release|Win32
+ {FC568FF0-60F2-4B2E-AF62-FD392EDBA1B9}.Debug|x64.ActiveCfg = Debug|x64
+ {FC568FF0-60F2-4B2E-AF62-FD392EDBA1B9}.Debug|x64.Build.0 = Debug|x64
+ {FC568FF0-60F2-4B2E-AF62-FD392EDBA1B9}.Debug|x86.ActiveCfg = Debug|Win32
+ {FC568FF0-60F2-4B2E-AF62-FD392EDBA1B9}.Debug|x86.Build.0 = Debug|Win32
+ {FC568FF0-60F2-4B2E-AF62-FD392EDBA1B9}.Release|x64.ActiveCfg = Release|x64
+ {FC568FF0-60F2-4B2E-AF62-FD392EDBA1B9}.Release|x64.Build.0 = Release|x64
+ {FC568FF0-60F2-4B2E-AF62-FD392EDBA1B9}.Release|x86.ActiveCfg = Release|Win32
+ {FC568FF0-60F2-4B2E-AF62-FD392EDBA1B9}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {74E69D5E-A1EF-46EA-9173-19A412774104} = {17322AAF-808F-4646-AD37-5B0EDDCB8F3E}
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7} = {17322AAF-808F-4646-AD37-5B0EDDCB8F3E}
+ {DD483F7D-C553-4740-BC1A-903805AD0174} = {17322AAF-808F-4646-AD37-5B0EDDCB8F3E}
+ {47496135-131B-41D6-BF2B-EE7144873DD0} = {17322AAF-808F-4646-AD37-5B0EDDCB8F3E}
+ {BBEFF9D7-0BC3-41D1-908B-8052158B5052} = {17322AAF-808F-4646-AD37-5B0EDDCB8F3E}
+ {6657614F-7821-4D55-96EF-7C3C4B551880} = {17322AAF-808F-4646-AD37-5B0EDDCB8F3E}
+ {F58FF6BA-098B-4DB9-9609-A030DFB4D03F} = {17322AAF-808F-4646-AD37-5B0EDDCB8F3E}
+ {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4} = {17322AAF-808F-4646-AD37-5B0EDDCB8F3E}
+ {02FB3D98-6516-42C6-9762-98811A99960F} = {17322AAF-808F-4646-AD37-5B0EDDCB8F3E}
+ {0D02F0F0-013B-4EE3-906D-86517F3822C0} = {17322AAF-808F-4646-AD37-5B0EDDCB8F3E}
+ {C0AE8A30-E4FA-49CE-A2B5-0C072C77EC64} = {17322AAF-808F-4646-AD37-5B0EDDCB8F3E}
+ {F6644EC5-D6B6-42A1-828C-75E2977470E0} = {17322AAF-808F-4646-AD37-5B0EDDCB8F3E}
+ {029797FF-C986-43DE-95CD-2E771E86AEBC} = {17322AAF-808F-4646-AD37-5B0EDDCB8F3E}
+ {29B98ADF-1285-49CE-BF6C-AA92C5D2FB24} = {17322AAF-808F-4646-AD37-5B0EDDCB8F3E}
+ {D901596E-76C7-4608-9CFA-2B42A9FD7250} = {A8096E32-E084-4FA0-AE01-A8D909EB2BB4}
+ {8EC56B06-5A9A-4D6D-804D-037FE26FD43E} = {A8096E32-E084-4FA0-AE01-A8D909EB2BB4}
+ {CD9740CE-C96E-49B3-823F-012E09D17806} = {A8096E32-E084-4FA0-AE01-A8D909EB2BB4}
+ {BF295BA9-4BF8-43F8-8CBF-FAE84815466C} = {A8096E32-E084-4FA0-AE01-A8D909EB2BB4}
+ {114CAA59-46C0-4B87-BA86-C1946A68101D} = {A8096E32-E084-4FA0-AE01-A8D909EB2BB4}
+ {890C6129-286F-4CD8-8252-FB8D3B4E6E1B} = {A8096E32-E084-4FA0-AE01-A8D909EB2BB4}
+ {FC568FF0-60F2-4B2E-AF62-FD392EDBA1B9} = {A8096E32-E084-4FA0-AE01-A8D909EB2BB4}
+ EndGlobalSection
+EndGlobal
diff --git a/contrib/win32/openssh/config.h.vs b/contrib/win32/openssh/config.h.vs
new file mode 100644
index 000000000..e798289b2
--- /dev/null
+++ b/contrib/win32/openssh/config.h.vs
@@ -0,0 +1,1715 @@
+#pragma once
+
+/* config.h. Generated from config.h.in by configure. */
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define if building universal (internal helper macro) */
+/* #undef AC_APPLE_UNIVERSAL_BUILD */
+
+/* Define if you have a getaddrinfo that fails
+ for the all-zeros IPv6 address
+ */
+/* #undef AIX_GETNAMEINFO_HACK */
+
+/* Define if your AIX loginfailed() function
+ takes 4 arguments (AIX >= 5.2)
+ */
+/* #undef AIX_LOGINFAILED_4ARG */
+
+/* System only supports IPv4 audit records */
+/* #undef AU_IPv4 */
+
+/* Define if your resolver libs need this for getrrsetbyname */
+/* #undef BIND_8_COMPAT */
+
+/* Define if cmsg_type is not passed correctly */
+/* #undef BROKEN_CMSG_TYPE */
+
+/* getaddrinfo is broken (if present) */
+/* #undef BROKEN_GETADDRINFO */
+
+/* getgroups(0,NULL) will return -1 */
+/* #undef BROKEN_GETGROUPS */
+
+/* FreeBSD glob does not do what we need */
+/* #undef BROKEN_GLOB */
+
+/* Define if you system's inet_ntoa is busted
+ (e.g. Irix gcc issue) */
+/* #undef BROKEN_INET_NTOA */
+
+/* ia_uinfo routines not supported by OS yet */
+/* #undef BROKEN_LIBIAF */
+
+/* Ultrix mmap can't map files */
+/* #undef BROKEN_MMAP */
+
+/* Define if your struct dirent expects you to
+ allocate extra space for
+ d_name */
+/* #undef BROKEN_ONE_BYTE_DIRENT_D_NAME */
+
+/* Can't do comparisons on readv */
+/* #undef BROKEN_READV_COMPARISON */
+
+/* Define if you have a broken realpath. */
+/* #undef BROKEN_REALPATH */
+
+/* Needed for NeXT */
+/* #undef BROKEN_SAVED_UIDS */
+
+/* Define if your setregid() is broken */
+/* #undef BROKEN_SETREGID */
+
+/* Define if your setresgid() is broken */
+/* #undef BROKEN_SETRESGID */
+
+/* Define if your setresuid() is broken */
+/* #undef BROKEN_SETRESUID */
+
+/* Define if your setreuid() is broken */
+/* #undef BROKEN_SETREUID */
+
+/* LynxOS has broken setvbuf() implementation */
+/* #undef BROKEN_SETVBUF */
+
+/* QNX shadow support is broken */
+/* #undef BROKEN_SHADOW_EXPIRE */
+
+/* Define if your snprintf is busted */
+/* #undef BROKEN_SNPRINTF */
+
+/* tcgetattr with ICANON may hang */
+#define BROKEN_TCGETATTR_ICANON 1
+
+/* updwtmpx is broken (if present) */
+/* #undef BROKEN_UPDWTMPX */
+
+/* Define if you have BSD auth support */
+/* #undef BSD_AUTH */
+
+/* Define if you want to specify the path to your lastlog file */
+#define CONF_LASTLOG_FILE "/var/log/lastlog"
+
+/* Define if you want to specify the path to your utmp file */
+#define CONF_UTMP_FILE "/var/run/utmp"
+
+/* Define if you want to specify the path to your wtmpx file */
+/* #undef CONF_WTMPX_FILE */
+
+/* Define if you want to specify the path to your wtmp file */
+/* #undef CONF_WTMP_FILE */
+
+/* Define if your platform needs to skip post auth
+ file descriptor passing */
+#define DISABLE_FD_PASSING 1
+
+/* Define if you don't want to use lastlog */
+/* #undef DISABLE_LASTLOG */
+
+/* Define if you don't want to use your
+ system's login() call */
+/* #undef DISABLE_LOGIN */
+
+/* Define if you don't want to use pututline()
+ etc. to write [uw]tmp */
+/* #undef DISABLE_PUTUTLINE */
+
+/* Define if you don't want to use pututxline()
+ etc. to write [uw]tmpx */
+/* #undef DISABLE_PUTUTXLINE */
+
+/* Define if you want to disable shadow passwords */
+#define DISABLE_SHADOW 1
+
+/* Define if you don't want to use utmp */
+#define DISABLE_UTMP 1
+
+/* Define if you don't want to use utmpx */
+#define DISABLE_UTMPX 1
+
+/* Define if you don't want to use wtmp */
+#define DISABLE_WTMP 1
+
+/* Define if you don't want to use wtmpx */
+#define DISABLE_WTMPX 1
+
+/* Enable for PKCS#11 support */
+/* #undef ENABLE_PKCS11 */
+
+/* File names may not contain backslash characters */
+/* #undef FILESYSTEM_NO_BACKSLASH */
+
+/* fsid_t has member val */
+/* #undef FSID_HAS_VAL */
+
+/* fsid_t has member __val */
+/* #undef FSID_HAS___VAL */
+
+/* Define to 1 if the `getpgrp' function requires zero arguments. */
+/* #undef GETPGRP_VOID */
+
+/* Conflicting defs for getspnam */
+/* #undef GETSPNAM_CONFLICTING_DEFS */
+
+/* Define if your system glob() function has
+ the GLOB_ALTDIRFUNC extension */
+/* #undef GLOB_HAS_ALTDIRFUNC */
+
+/* Define if your system glob() function has
+ gl_matchc options in glob_t */
+#define GLOB_HAS_GL_MATCHC 1
+
+/* Define if your system glob() function has
+ gl_statv options in glob_t */
+#define GLOB_HAS_GL_STATV 1
+
+/* Define this if you want GSSAPI
+ support in the version 2 protocol */
+/* #undef GSSAPI */
+
+/* Define if you want to use shadow password expire field */
+/* #undef HAS_SHADOW_EXPIRE */
+
+/* Define if your system uses access rights style
+ file descriptor passing */
+/* #undef HAVE_ACCRIGHTS_IN_MSGHDR */
+
+/* Define if you have ut_addr in utmp.h */
+/* #undef HAVE_ADDR_IN_UTMP */
+
+/* Define if you have ut_addr in utmpx.h */
+/* #undef HAVE_ADDR_IN_UTMPX */
+
+/* Define if you have ut_addr_v6 in utmp.h */
+/* #undef HAVE_ADDR_V6_IN_UTMP */
+
+/* Define if you have ut_addr_v6 in utmpx.h */
+/* #undef HAVE_ADDR_V6_IN_UTMPX */
+
+/* Define to 1 if you have the `arc4random' function. */
+/* #undef HAVE_ARC4RANDOM */
+
+/* Define to 1 if you have the `arc4random_buf' function. */
+/* #undef HAVE_ARC4RANDOM_BUF */
+
+/* Define to 1 if you have the `arc4random_uniform' function. */
+/* #undef HAVE_ARC4RANDOM_UNIFORM */
+
+/* Define to 1 if you have the `asprintf' function. */
+/* #undef HAVE_ASPRINTF */
+
+/* OpenBSD's gcc has bounded */
+/* #undef HAVE_ATTRIBUTE__BOUNDED__ */
+
+/* Have attribute nonnull */
+#define HAVE_ATTRIBUTE__NONNULL__ 1
+
+/* OpenBSD's gcc has sentinel */
+/* #undef HAVE_ATTRIBUTE__SENTINEL__ */
+
+/* Define to 1 if you have the `aug_get_machine' function. */
+/* #undef HAVE_AUG_GET_MACHINE */
+
+/* Define to 1 if you have the `b64_ntop' function. */
+/* #undef HAVE_B64_NTOP */
+
+/* Define to 1 if you have the `b64_pton' function. */
+/* #undef HAVE_B64_PTON */
+
+/* Define if you have the basename function. */
+#define HAVE_BASENAME 1
+
+/* Define to 1 if you have the `bcopy' function. */
+/* #undef HAVE_BCOPY */
+
+/* Define to 1 if you have the `bindresvport_sa' function. */
+/* #undef HAVE_BINDRESVPORT_SA */
+
+/* Define to 1 if you have the `BN_is_prime_ex' function. */
+#define HAVE_BN_IS_PRIME_EX 1
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_BSM_AUDIT_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_BSTRING_H */
+
+/* Define to 1 if you have the `clock' function. */
+#define HAVE_CLOCK 1
+
+/* define if you have clock_t data type */
+#define HAVE_CLOCK_T 1
+
+/* Define to 1 if you have the `closefrom' function. */
+/* #undef HAVE_CLOSEFROM */
+
+/* Define if gai_strerror() returns const char * */
+/* #undef HAVE_CONST_GAI_STRERROR_PROTO */
+
+/* Define if your system uses ancillary data style
+ file descriptor passing */
+/* #undef HAVE_CONTROL_IN_MSGHDR */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_CRYPTO_SHA2_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_CRYPT_H */
+
+/* Define if you are on Cygwin */
+/* #undef HAVE_CYGWIN */
+
+/* Define if your libraries define daemon() */
+/* #undef HAVE_DAEMON */
+
+/* Define to 1 if you have the declaration of `authenticate', and to 0 if you
+ don't. */
+/* #undef HAVE_DECL_AUTHENTICATE */
+
+/* Define to 1 if you have the declaration of `GLOB_NOMATCH', and to 0 if you
+ don't. */
+#define HAVE_DECL_GLOB_NOMATCH 1
+
+/* Define to 1 if you have the declaration of `h_errno', and to 0 if you
+ don't. */
+#define HAVE_DECL_H_ERRNO 0
+
+/* Define to 1 if you have the declaration of `loginfailed', and to 0 if you
+ don't. */
+/* #undef HAVE_DECL_LOGINFAILED */
+
+/* Define to 1 if you have the declaration of `loginrestrictions', and to 0 if
+ you don't. */
+/* #undef HAVE_DECL_LOGINRESTRICTIONS */
+
+/* Define to 1 if you have the declaration of `loginsuccess', and to 0 if you
+ don't. */
+/* #undef HAVE_DECL_LOGINSUCCESS */
+
+/* Define to 1 if you have the declaration of `MAXSYMLINKS', and to 0 if you
+ don't. */
+#define HAVE_DECL_MAXSYMLINKS 0
+
+/* Define to 1 if you have the declaration of `offsetof', and to 0 if you
+ don't. */
+#define HAVE_DECL_OFFSETOF 1
+
+/* Define to 1 if you have the declaration of `O_NONBLOCK', and to 0 if you
+ don't. */
+#define HAVE_DECL_O_NONBLOCK 0
+
+/* Define to 1 if you have the declaration of `passwdexpired', and to 0 if you
+ don't. */
+/* #undef HAVE_DECL_PASSWDEXPIRED */
+
+/* Define to 1 if you have the declaration of `setauthdb', and to 0 if you
+ don't. */
+/* #undef HAVE_DECL_SETAUTHDB */
+
+/* Define to 1 if you have the declaration of `SHUT_RD', and to 0 if you
+ don't. */
+#define HAVE_DECL_SHUT_RD 1
+
+/* Define to 1 if you have the declaration of `writev', and to 0 if you don't.
+ */
+#define HAVE_DECL_WRITEV 0
+
+/* Define to 1 if you have the declaration of `_getlong', and to 0 if you
+ don't. */
+/* #undef HAVE_DECL__GETLONG */
+
+/* Define to 1 if you have the declaration of `_getshort', and to 0 if you
+ don't. */
+/* #undef HAVE_DECL__GETSHORT */
+
+/* Define if you have /dev/ptmx */
+#define HAVE_DEV_PTMX 1
+
+/* Define if you have /dev/ptc */
+/* #undef HAVE_DEV_PTS_AND_PTC */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_DIRENT_H
+
+/* Define to 1 if you have the `dirfd' function. */
+/* #undef HAVE_DIRFD */
+
+/* Define to 1 if you have the `dirname' function. */
+/* #define HAVE_DIRNAME 1 */
+
+/* Define to 1 if you have the `DSA_generate_parameters_ex' function. */
+#define HAVE_DSA_GENERATE_PARAMETERS_EX 1
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_ENDIAN_H */
+
+/* Define to 1 if you have the `endutent' function. */
+/* #undef HAVE_ENDUTENT */
+
+/* Define to 1 if you have the `endutxent' function. */
+/* #undef HAVE_ENDUTXENT */
+
+/* Define if your system has /etc/default/login */
+/* #undef HAVE_ETC_DEFAULT_LOGIN */
+
+/* Define to 1 if you have the `EVP_sha256' function. */
+#define HAVE_EVP_SHA256 1
+
+/* Define if you have ut_exit in utmp.h */
+/* #undef HAVE_EXIT_IN_UTMP */
+
+/* Define to 1 if you have the `fchmod' function. */
+/* #undef HAVE_FCHMOD */
+
+/* Define to 1 if you have the `fchown' function. */
+/* #undef HAVE_FCHOWN */
+
+/* Use F_CLOSEM fcntl for closefrom */
+/* #undef HAVE_FCNTL_CLOSEM */
+
+/* Define to 1 if you have the header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_FEATURES_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_FLOATINGPOINT_H */
+
+/* Define to 1 if you have the `fmt_scaled' function. */
+/* #undef HAVE_FMT_SCALED */
+
+/* Define to 1 if you have the `freeaddrinfo' function. */
+/* #undef HAVE_FREEADDRINFO */
+
+/* Define to 1 if the system has the type `fsblkcnt_t'. */
+/* #undef HAVE_FSBLKCNT_T */
+
+/* Define to 1 if the system has the type `fsfilcnt_t'. */
+/* #undef HAVE_FSFILCNT_T */
+
+/* Define to 1 if you have the `fstatvfs' function. */
+#define HAVE_FSTATVFS 1
+
+/* Define to 1 if you have the `futimes' function. */
+/* #undef HAVE_FUTIMES */
+
+/* Define to 1 if you have the `gai_strerror' function. */
+/* #undef HAVE_GAI_STRERROR */
+
+/* Define to 1 if you have the `getaddrinfo' function. */
+/* #undef HAVE_GETADDRINFO */
+
+/* Define to 1 if you have the `getaudit' function. */
+/* #undef HAVE_GETAUDIT */
+
+/* Define to 1 if you have the `getaudit_addr' function. */
+/* #undef HAVE_GETAUDIT_ADDR */
+
+/* Define to 1 if you have the `getcwd' function. */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the `getgrouplist' function. */
+/* #undef HAVE_GETGROUPLIST */
+
+/* Define to 1 if you have the `getgrset' function. */
+/* #undef HAVE_GETGRSET */
+
+/* Define to 1 if you have the `getlastlogxbyname' function. */
+/* #undef HAVE_GETLASTLOGXBYNAME */
+
+/* Define to 1 if you have the `getluid' function. */
+/* #undef HAVE_GETLUID */
+
+/* Define to 1 if you have the `getnameinfo' function. */
+/* #undef HAVE_GETNAMEINFO */
+
+/* Define to 1 if you have the `getopt' function. */
+#define HAVE_GETOPT 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_GETOPT_H 1
+
+/* Define if your getopt(3) defines and uses optreset */
+/* #undef HAVE_GETOPT_OPTRESET */
+
+/* Define if your libraries define getpagesize() */
+#define HAVE_GETPAGESIZE 1
+
+/* Define to 1 if you have the `getpeereid' function. */
+/* #undef HAVE_GETPEEREID */
+
+/* Define to 1 if you have the `getpeerucred' function. */
+/* #undef HAVE_GETPEERUCRED */
+
+/* Define to 1 if you have the `getpwanam' function. */
+/* #undef HAVE_GETPWANAM */
+
+/* Define to 1 if you have the `getrlimit' function. */
+/* #undef HAVE_GETRLIMIT */
+
+/* Define if getrrsetbyname() exists */
+/* #undef HAVE_GETRRSETBYNAME */
+
+/* Define to 1 if you have the `getrusage' function. */
+/* #undef HAVE_GETRUSAGE */
+
+/* Define to 1 if you have the `getseuserbyname' function. */
+/* #undef HAVE_GETSEUSERBYNAME */
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the `getttyent' function. */
+/* #undef HAVE_GETTTYENT */
+
+/* Define to 1 if you have the `getutent' function. */
+/* #undef HAVE_GETUTENT */
+
+/* Define to 1 if you have the `getutid' function. */
+/* #undef HAVE_GETUTID */
+
+/* Define to 1 if you have the `getutline' function. */
+/* #undef HAVE_GETUTLINE */
+
+/* Define to 1 if you have the `getutxent' function. */
+/* #undef HAVE_GETUTXENT */
+
+/* Define to 1 if you have the `getutxid' function. */
+/* #undef HAVE_GETUTXID */
+
+/* Define to 1 if you have the `getutxline' function. */
+/* #undef HAVE_GETUTXLINE */
+
+/* Define to 1 if you have the `getutxuser' function. */
+/* #undef HAVE_GETUTXUSER */
+
+/* Define to 1 if you have the `get_default_context_with_level' function. */
+/* #undef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL */
+
+/* Define to 1 if you have the `glob' function. */
+/* #undef HAVE_GLOB */
+
+/* Define to 1 if you have the header file. */
+#define HAVE_GLOB_H 1
+
+/* Define to 1 if you have the `group_from_gid' function. */
+/* #undef HAVE_GROUP_FROM_GID */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_GSSAPI_GENERIC_H */
+
+/* Define to 1 if you have the header file. */
+#define HAVE_GSSAPI_GSSAPI_GENERIC_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_GSSAPI_GSSAPI_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_GSSAPI_GSSAPI_KRB5_H 1
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_GSSAPI_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_GSSAPI_KRB5_H */
+
+/* Define if HEADER.ad exists in arpa/nameser.h */
+/* #undef HAVE_HEADER_AD */
+
+/* Define if you have ut_host in utmp.h */
+/* #undef HAVE_HOST_IN_UTMP */
+
+/* Define if you have ut_host in utmpx.h */
+/* #undef HAVE_HOST_IN_UTMPX */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_IAF_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_IA_H */
+
+/* Define if you have ut_id in utmp.h */
+/* #undef HAVE_ID_IN_UTMP */
+
+/* Define if you have ut_id in utmpx.h */
+/* #undef HAVE_ID_IN_UTMPX */
+
+/* Define to 1 if you have the `inet_aton' function. */
+/* #undef HAVE_INET_ATON */
+
+/* Define to 1 if you have the `inet_ntoa' function. */
+/* #undef HAVE_INET_NTOA */
+
+/* Define to 1 if you have the `inet_ntop' function. */
+#define HAVE_INET_NTOP 1
+
+/* Define to 1 if you have the `innetgr' function. */
+/* #undef HAVE_INNETGR */
+
+/* define if you have int64_t data type */
+#define HAVE_INT64_T 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_INTTYPES_H 1
+
+/* define if you have intxx_t data type */
+#define HAVE_INTXX_T 1
+
+/* Define to 1 if the system has the type `in_addr_t'. */
+/* #undef HAVE_IN_ADDR_T */
+
+/* Define to 1 if the system has the type `in_port_t'. */
+/* #undef HAVE_IN_PORT_T */
+
+/* Define if you have isblank(3C). */
+#define HAVE_ISBLANK 1
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_LASTLOG_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_LIBAUDIT_H */
+
+/* Define to 1 if you have the `bsm' library (-lbsm). */
+/* #undef HAVE_LIBBSM */
+
+/* Define to 1 if you have the `crypt' library (-lcrypt). */
+/* #undef HAVE_LIBCRYPT */
+
+/* Define to 1 if you have the `dl' library (-ldl). */
+/* #undef HAVE_LIBDL */
+
+/* Define to 1 if you have the header file. */
+#define HAVE_LIBGEN_H 1
+
+/* Define if system has libiaf that supports set_id */
+/* #undef HAVE_LIBIAF */
+
+/* Define to 1 if you have the `network' library (-lnetwork). */
+/* #undef HAVE_LIBNETWORK */
+
+/* Define to 1 if you have the `nsl' library (-lnsl). */
+/* #undef HAVE_LIBNSL */
+
+/* Define to 1 if you have the `pam' library (-lpam). */
+/* #undef HAVE_LIBPAM */
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+/* #undef HAVE_LIBSOCKET */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_LIBUTIL_H */
+
+/* Define to 1 if you have the `xnet' library (-lxnet). */
+/* #undef HAVE_LIBXNET */
+
+/* Define to 1 if you have the `z' library (-lz). */
+#define HAVE_LIBZ 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_LINUX_IF_TUN_H */
+
+/* Define if your libraries define login() */
+/* #undef HAVE_LOGIN */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_LOGIN_CAP_H */
+
+/* Define to 1 if you have the `login_getcapbool' function. */
+/* #undef HAVE_LOGIN_GETCAPBOOL */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_LOGIN_H */
+
+/* Define to 1 if you have the `logout' function. */
+/* #undef HAVE_LOGOUT */
+
+/* Define to 1 if you have the `logwtmp' function. */
+/* #undef HAVE_LOGWTMP */
+
+/* Define to 1 if the system has the type `long double'. */
+#define HAVE_LONG_DOUBLE 1
+
+/* Define to 1 if the system has the type `long long'. */
+#define HAVE_LONG_LONG 1
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_MAILLOCK_H */
+
+/* Define to 1 if you have the `md5_crypt' function. */
+/* #undef HAVE_MD5_CRYPT */
+
+/* Define if you want to allow MD5 passwords */
+/* #undef HAVE_MD5_PASSWORDS */
+
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mkdtemp' function. */
+/* #undef HAVE_MKDTEMP */
+
+/* Define to 1 if you have the `mmap' function. */
+/* #undef HAVE_MMAP */
+
+/* define if you have mode_t data type */
+#define HAVE_MODE_T 1
+
+/* Some systems put nanosleep outside of libc */
+/* #undef HAVE_NANOSLEEP */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_NETDB_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_NETGROUP_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_NET_IF_TUN_H */
+
+/* Define if you are on NeXT */
+/* #undef HAVE_NEXT */
+
+/* Define to 1 if you have the `ngetaddrinfo' function. */
+/* #undef HAVE_NGETADDRINFO */
+
+/* Define to 1 if you have the `nsleep' function. */
+/* #undef HAVE_NSLEEP */
+
+/* Define to 1 if you have the `ogetaddrinfo' function. */
+/* #undef HAVE_OGETADDRINFO */
+
+/* Define if you have an old version of PAM
+ which takes only one argument to
+ pam_strerror */
+/* #undef HAVE_OLD_PAM */
+
+/* Define to 1 if you have the `openlog_r' function. */
+/* #undef HAVE_OPENLOG_R */
+
+/* Define to 1 if you have the `openpty' function. */
+/* #undef HAVE_OPENPTY */
+
+/* Define if your ssl headers are included
+ with #include
+ */
+#define HAVE_OPENSSL 1
+
+/* Define if you have Digital Unix Security
+ Integration Architecture */
+/* #undef HAVE_OSF_SIA */
+
+/* Define to 1 if you have the `pam_getenvlist' function. */
+/* #undef HAVE_PAM_GETENVLIST */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_PAM_PAM_APPL_H */
+
+/* Define to 1 if you have the `pam_putenv' function. */
+/* #undef HAVE_PAM_PUTENV */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_PATHS_H */
+
+/* Define if you have ut_pid in utmp.h */
+/* #undef HAVE_PID_IN_UTMP */
+
+/* define if you have pid_t data type */
+#define HAVE_PID_T 1
+
+/* Define to 1 if you have the `poll' function. */
+/* #undef HAVE_POLL */
+
+/* Define to 1 if you have the header file. */
+#define HAVE_POLL_H 1
+
+/* Define to 1 if you have the `prctl' function. */
+/* #undef HAVE_PRCTL */
+
+/* Define to 1 if you have priveleged-port concept */
+/* #undef HAVE_PRIV_CONCEPT */
+
+/* Define if you have /proc/$pid/fd */
+#define HAVE_PROC_PID 1
+
+/* Define to 1 if you have the `pstat' function. */
+/* #undef HAVE_PSTAT */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_PTY_H */
+
+/* Define to 1 if you have the `pututline' function. */
+/* #undef HAVE_PUTUTLINE */
+
+/* Define to 1 if you have the `pututxline' function. */
+/* #undef HAVE_PUTUTXLINE */
+
+/* Define if your password has a pw_change field */
+/* #undef HAVE_PW_CHANGE_IN_PASSWD */
+
+/* Define if your password has a pw_class field */
+/* #undef HAVE_PW_CLASS_IN_PASSWD */
+
+/* Define if your password has a pw_expire field */
+/* #undef HAVE_PW_EXPIRE_IN_PASSWD */
+
+/* Define to 1 if you have the `readpassphrase' function. */
+/* #undef HAVE_READPASSPHRASE */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_READPASSPHRASE_H */
+
+/* Define to 1 if you have the `realpath' function. */
+/* #define HAVE_REALPATH 1 */
+
+/* Define to 1 if you have the `recvmsg' function. */
+/* #undef HAVE_RECVMSG */
+
+/* sys/resource.h has RLIMIT_NPROC */
+/* #undef HAVE_RLIMIT_NPROC */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_RPC_TYPES_H */
+
+/* Define to 1 if you have the `rresvport_af' function. */
+/* #undef HAVE_RRESVPORT_AF */
+
+/* Define to 1 if you have the `RSA_generate_key_ex' function. */
+#define HAVE_RSA_GENERATE_KEY_EX 1
+
+/* Define to 1 if you have the `RSA_get_default_method' function. */
+#define HAVE_RSA_GET_DEFAULT_METHOD 1
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_SANDBOX_H */
+
+/* Define to 1 if you have the `sandbox_init' function. */
+/* #undef HAVE_SANDBOX_INIT */
+
+/* define if you have sa_family_t data type */
+/* #undef HAVE_SA_FAMILY_T */
+
+/* Define if you have SecureWare-based
+ protected password database */
+/* #undef HAVE_SECUREWARE */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_SECURITY_PAM_APPL_H */
+
+/* Define to 1 if you have the `sendmsg' function. */
+/* #undef HAVE_SENDMSG */
+
+/* Define to 1 if you have the `setauthdb' function. */
+/* #undef HAVE_SETAUTHDB */
+
+/* Define to 1 if you have the `setdtablesize' function. */
+/* #undef HAVE_SETDTABLESIZE */
+
+/* Define to 1 if you have the `setegid' function. */
+/* #undef HAVE_SETEGID */
+
+/* Define to 1 if you have the `setenv' function. */
+/* #undef HAVE_SETENV */
+
+/* Define to 1 if you have the `seteuid' function. */
+/* #undef HAVE_SETEUID */
+
+/* Define to 1 if you have the `setgroupent' function. */
+/* #undef HAVE_SETGROUPENT */
+
+/* Define to 1 if you have the `setgroups' function. */
+/* #undef HAVE_SETGROUPS */
+
+/* Define to 1 if you have the `setlogin' function. */
+/* #undef HAVE_SETLOGIN */
+
+/* Define to 1 if you have the `setluid' function. */
+/* #undef HAVE_SETLUID */
+
+/* Define to 1 if you have the `setpcred' function. */
+/* #undef HAVE_SETPCRED */
+
+/* Define to 1 if you have the `setproctitle' function. */
+/* #undef HAVE_SETPROCTITLE */
+
+/* Define to 1 if you have the `setregid' function. */
+/* #undef HAVE_SETREGID */
+
+/* Define to 1 if you have the `setresgid' function. */
+/* #undef HAVE_SETRESGID */
+
+/* Define to 1 if you have the `setresuid' function. */
+/* #undef HAVE_SETRESUID */
+
+/* Define to 1 if you have the `setreuid' function. */
+/* #undef HAVE_SETREUID */
+
+/* Define to 1 if you have the `setrlimit' function. */
+/* #undef HAVE_SETRLIMIT */
+
+/* Define to 1 if you have the `setsid' function. */
+#define HAVE_SETSID 1
+
+/* Define to 1 if you have the `setutent' function. */
+/* #undef HAVE_SETUTENT */
+
+/* Define to 1 if you have the `setutxdb' function. */
+/* #undef HAVE_SETUTXDB */
+
+/* Define to 1 if you have the `setutxent' function. */
+/* #undef HAVE_SETUTXENT */
+
+/* Define to 1 if you have the `setvbuf' function. */
+#define HAVE_SETVBUF 1
+
+/* Define to 1 if you have the `set_id' function. */
+/* #undef HAVE_SET_ID */
+
+/* Define to 1 if you have the `SHA256_Update' function. */
+#define HAVE_SHA256_UPDATE 1
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_SHA2_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_SHADOW_H */
+
+/* Define to 1 if you have the `sigaction' function. */
+/* #undef HAVE_SIGACTION */
+
+/* Define to 1 if you have the `sigvec' function. */
+/* #undef HAVE_SIGVEC */
+
+/* Define to 1 if the system has the type `sig_atomic_t'. */
+#define HAVE_SIG_ATOMIC_T 1
+
+/* define if you have size_t data type */
+#define HAVE_SIZE_T 1
+
+/* Define to 1 if you have the `snprintf' function. */
+#define HAVE_SNPRINTF 1
+
+/* Define to 1 if you have the `socketpair' function. */
+/* #undef HAVE_SOCKETPAIR */
+
+/* Have PEERCRED socket option */
+/* #undef HAVE_SO_PEERCRED */
+
+/* define if you have ssize_t data type */
+#define HAVE_SSIZE_T 1
+
+/* Fields in struct sockaddr_storage */
+#define HAVE_SS_FAMILY_IN_SS 1
+
+/* Define to 1 if you have the `statfs' function. */
+/* #undef HAVE_STATFS */
+
+/* Define to 1 if you have the `statvfs' function. */
+#define HAVE_STATVFS 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the `strftime' function. */
+#define HAVE_STRFTIME 1
+
+/* Silly mkstemp() */
+/* #undef HAVE_STRICT_MKSTEMP */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strlcat' function. */
+/* #undef HAVE_STRLCAT */
+
+/* Define to 1 if you have the `strlcpy' function. */
+/* #undef HAVE_STRLCPY */
+
+/* Define to 1 if you have the `strmode' function. */
+/* #undef HAVE_STRMODE */
+
+/* Define to 1 if you have the `strnvis' function. */
+/* #undef HAVE_STRNVIS */
+
+/* Define to 1 if you have the `strptime' function. */
+/* #undef HAVE_STRPTIME */
+
+/* Define to 1 if you have the `strsep' function. */
+/* #undef HAVE_STRSEP */
+
+/* Define to 1 if you have the `strtoll' function. */
+#define HAVE_STRTOLL 1
+
+/* Define to 1 if you have the `strtonum' function. */
+/* #undef HAVE_STRTONUM */
+
+/* Define to 1 if you have the `strtoul' function. */
+#define HAVE_STRTOUL 1
+
+/* define if you have struct addrinfo data type */
+#define HAVE_STRUCT_ADDRINFO 1
+
+/* define if you have struct in6_addr data type */
+/* #undef HAVE_STRUCT_IN6_ADDR */
+
+/* define if you have struct sockaddr_in6 data type */
+/* #undef HAVE_STRUCT_SOCKADDR_IN6 */
+
+/* Define to 1 if `sin6_scope_id' is a member of `struct sockaddr_in6'. */
+/* #undef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID */
+
+/* define if you have struct sockaddr_storage data type */
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+
+/* Define to 1 if `st_blksize' is a member of `struct stat'. */
+/* #undef HAVE_STRUCT_STAT_ST_BLKSIZE */
+
+/* Define to 1 if the system has the type `struct timespec'. */
+/* #undef HAVE_STRUCT_TIMESPEC */
+
+/* define if you have struct timeval */
+#define HAVE_STRUCT_TIMEVAL 1
+
+/* Define to 1 if you have the `swap32' function. */
+/* #undef HAVE_SWAP32 */
+
+/* Define to 1 if you have the `sysconf' function. */
+/* #undef HAVE_SYSCONF */
+
+/* Define if you have syslen in utmpx.h */
+/* #undef HAVE_SYSLEN_IN_UTMPX */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_SYS_AUDIT_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_SYS_BITYPES_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_SYS_BSDTTY_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_SYS_CDEFS_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define if your system defines sys_errlist[] */
+/* #undef HAVE_SYS_ERRLIST */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_SYS_MMAN_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_SYS_MOUNT_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define if your system defines sys_nerr */
+/* #undef HAVE_SYS_NERR */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_SYS_POLL_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_SYS_PRCTL_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_SYS_PSTAT_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_SYS_PTMS_H */
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_STATVFS_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_SYS_STREAM_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_SYS_STROPTS_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_SYS_STRTIO_H */
+
+/* Force use of sys/syslog.h on Ultrix */
+/* #undef HAVE_SYS_SYSLOG_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_SYS_SYSMACROS_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_SYS_TIMERS_H */
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_SYS_UN_H */
+
+/* Define to 1 if you have the `tcgetpgrp' function. */
+/* #undef HAVE_TCGETPGRP */
+
+/* Define to 1 if you have the `tcsendbreak' function. */
+/* #undef HAVE_TCSENDBREAK */
+
+/* Define to 1 if you have the `time' function. */
+#define HAVE_TIME 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_TIME_H 1
+
+/* Define if you have ut_time in utmp.h */
+/* #undef HAVE_TIME_IN_UTMP */
+
+/* Define if you have ut_time in utmpx.h */
+/* #undef HAVE_TIME_IN_UTMPX */
+
+/* Define to 1 if you have the `timingsafe_bcmp' function. */
+/* #undef HAVE_TIMINGSAFE_BCMP */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_TMPDIR_H */
+
+/* Define to 1 if you have the `truncate' function. */
+/* #undef HAVE_TRUNCATE */
+
+/* Define to 1 if you have tty support */
+/* #undef HAVE_TTY */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_TTYENT_H */
+
+/* Define if you have ut_tv in utmp.h */
+/* #undef HAVE_TV_IN_UTMP */
+
+/* Define if you have ut_tv in utmpx.h */
+/* #undef HAVE_TV_IN_UTMPX */
+
+/* Define if you have ut_type in utmp.h */
+/* #undef HAVE_TYPE_IN_UTMP */
+
+/* Define if you have ut_type in utmpx.h */
+/* #undef HAVE_TYPE_IN_UTMPX */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_UCRED_H */
+
+/* define if you have uintxx_t data type */
+#define HAVE_UINTXX_T 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `unsetenv' function. */
+/* #undef HAVE_UNSETENV */
+
+/* Define to 1 if the system has the type `unsigned long long'. */
+#define HAVE_UNSIGNED_LONG_LONG 1
+
+/* Define to 1 if you have the `updwtmp' function. */
+/* #undef HAVE_UPDWTMP */
+
+/* Define to 1 if you have the `updwtmpx' function. */
+/* #undef HAVE_UPDWTMPX */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_USERSEC_H */
+
+/* Define to 1 if you have the `user_from_uid' function. */
+#define HAVE_USER_FROM_UID 1
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_UTIL_H */
+
+/* Define to 1 if you have the `utimes' function. */
+#define HAVE_UTIMES 1
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_UTIME_H */
+
+/* Define to 1 if you have the `utmpname' function. */
+/* #undef HAVE_UTMPNAME */
+
+/* Define to 1 if you have the `utmpxname' function. */
+/* #undef HAVE_UTMPXNAME */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_UTMPX_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_UTMP_H */
+
+/* define if you have u_char data type */
+/* #undef HAVE_U_CHAR */
+
+/* define if you have u_int data type */
+/* #undef HAVE_U_INT */
+
+/* define if you have u_int64_t data type */
+/* #undef HAVE_U_INT64_T */
+
+/* define if you have u_intxx_t data type */
+/* #undef HAVE_U_INTXX_T */
+
+/* Define to 1 if you have the `vasprintf' function. */
+/* #undef HAVE_VASPRINTF */
+
+/* Define if va_copy exists */
+#define HAVE_VA_COPY 1
+
+/* Define to 1 if you have the `vhangup' function. */
+/* #undef HAVE_VHANGUP */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_VIS_H */
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#define HAVE_VSNPRINTF 1
+
+/* Define to 1 if you have the `waitpid' function. */
+#define HAVE_WAITPID 1
+
+/* Define to 1 if you have the `_getlong' function. */
+/* #undef HAVE__GETLONG */
+
+/* Define to 1 if you have the `_getpty' function. */
+/* #undef HAVE__GETPTY */
+
+/* Define to 1 if you have the `_getshort' function. */
+/* #undef HAVE__GETSHORT */
+
+/* Define if you have struct __res_state _res as an extern */
+#define HAVE__RES_EXTERN 1
+
+/* Define to 1 if you have the `__b64_ntop' function. */
+/* #undef HAVE___B64_NTOP */
+
+/* Define to 1 if you have the `__b64_pton' function. */
+/* #undef HAVE___B64_PTON */
+
+/* Define if compiler implements __FUNCTION__ */
+#define HAVE___FUNCTION__ 1
+
+/* Define if libc defines __progname */
+/* #undef HAVE___PROGNAME */
+
+/* Fields in struct sockaddr_storage */
+/* #undef HAVE___SS_FAMILY_IN_SS */
+
+/* Define if __va_copy exists */
+#define HAVE___VA_COPY 1
+
+/* Define if compiler implements __func__ */
+#define HAVE___func__ 1
+
+/* Define this if you are using the Heimdal
+ version of Kerberos V5 */
+/* #undef HEIMDAL */
+
+/* Define if you need to use IP address
+ instead of hostname in $DISPLAY */
+/* #undef IPADDR_IN_DISPLAY */
+
+/* Detect IPv4 in IPv6 mapped addresses
+ and treat as IPv4 */
+/* #undef IPV4_IN_IPV6 */
+
+/* Define if your system choked on IP TOS setting */
+#define IP_TOS_IS_BROKEN 1
+
+/* Define if you want Kerberos 5 support */
+/* #undef KRB5 */
+
+/* Define if pututxline updates lastlog too */
+/* #undef LASTLOG_WRITE_PUTUTXLINE */
+
+/* Define if you want
+ TCP Wrappers support */
+/* #undef LIBWRAP */
+
+/* Define to whatever link() returns for "not supported"
+ if it doesn't return
+ EOPNOTSUPP. */
+/* #undef LINK_OPNOTSUPP_ERRNO */
+
+/* Adjust Linux out-of-memory killer */
+/* #undef LINUX_OOM_ADJUST */
+
+/* max value of long long calculated by configure */
+/* #undef LLONG_MAX */
+
+/* min value of long long calculated by configure */
+/* #undef LLONG_MIN */
+
+/* Account locked with pw(1) */
+/* #undef LOCKED_PASSWD_PREFIX */
+
+/* String used in /etc/passwd to denote locked account */
+/* #undef LOCKED_PASSWD_STRING */
+
+/* String used in /etc/passwd to denote locked account */
+/* #undef LOCKED_PASSWD_SUBSTR */
+
+/* Some versions of /bin/login need the TERM supplied
+ on the commandline */
+/* #undef LOGIN_NEEDS_TERM */
+
+/* Some systems need a utmpx entry for /bin/login to work */
+/* #undef LOGIN_NEEDS_UTMPX */
+
+/* Define if your login program cannot handle end of options ("--") */
+/* #undef LOGIN_NO_ENDOPT */
+
+/* If your header files don't define LOGIN_PROGRAM,
+ then use this (detected)
+ from environment and PATH */
+#define LOGIN_PROGRAM_FALLBACK "/usr/bin/login"
+
+/* Set this to your mail directory if you do not have _PATH_MAILDIR */
+#define MAIL_DIRECTORY "/var/spool/mail"
+
+/* Define on *nto-qnx systems */
+/* #undef MISSING_FD_MASK */
+
+/* Define on *nto-qnx systems */
+/* #undef MISSING_HOWMANY */
+
+/* Define on *nto-qnx systems */
+/* #undef MISSING_NFDBITS */
+
+/* Need setpgrp to acquire controlling tty */
+/* #undef NEED_SETPGRP */
+
+/* Define if the concept of ports only accessible to
+ superusers isn't known
+ */
+#define NO_IPPORT_RESERVED_CONCEPT 1
+
+/* Define if you don't want to use lastlog in session.c */
+/* #undef NO_SSH_LASTLOG */
+
+/* Define if X11 doesn't support AF_UNIX sockets on that system */
+#define NO_X11_UNIX_SOCKETS 1
+
+/* Define if EVP_DigestUpdate returns void */
+/* #undef OPENSSL_EVP_DIGESTUPDATE_VOID */
+
+/* libcrypto includes complete ECC support */
+#define OPENSSL_HAS_ECC 1
+
+/* libcrypto is missing AES 192 and 256 bit functions */
+/* #undef OPENSSL_LOBOTOMISED_AES */
+
+/* Define if you want OpenSSL's internally seeded PRNG only */
+#define OPENSSL_PRNG_ONLY 1
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "openssh-unix-dev@mindrot.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "OpenSSH"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "OpenSSH Portable"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "openssh"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "Portable"
+
+/* Define if you are using Solaris-derived PAM which
+ passes pam_messages to
+ the conversation function
+ with an extra level of indirection */
+/* #undef PAM_SUN_CODEBASE */
+
+/* Work around problematic Linux PAM modules handling of PAM_TTY */
+/* #undef PAM_TTY_KLUDGE */
+
+/* must supply username to passwd */
+/* #undef PASSWD_NEEDS_USERNAME */
+
+/* Port number of PRNGD/EGD random number socket */
+/* #undef PRNGD_PORT */
+
+/* Location of PRNGD/EGD random number socket */
+/* #undef PRNGD_SOCKET */
+
+/* read(1) can return 0 for a non-closed fd */
+/* #undef PTY_ZEROREAD */
+
+/* Sandbox using Darwin sandbox_init(3) */
+/* #undef SANDBOX_DARWIN */
+
+/* no privsep sandboxing */
+#define SANDBOX_NULL 1
+
+/* Sandbox using setrlimit(2) */
+/* #undef SANDBOX_RLIMIT */
+
+/* Sandbox using systrace(4) */
+/* #undef SANDBOX_SYSTRACE */
+
+/* Define if your platform breaks doing a seteuid before a setuid */
+/* #undef SETEUID_BREAKS_SETUID */
+
+/* The size of `char', as computed by sizeof. */
+#define SIZEOF_CHAR 1
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of `long int', as computed by sizeof. */
+#define SIZEOF_LONG_INT 4
+
+/* The size of `long long int', as computed by sizeof. */
+#define SIZEOF_LONG_LONG_INT 8
+
+/* The size of `short int', as computed by sizeof. */
+#define SIZEOF_SHORT_INT 2
+
+/* Define if you want S/Key support */
+/* #undef SKEY */
+
+/* Define if your skeychallenge()
+ function takes 4 arguments (NetBSD) */
+/* #undef SKEYCHALLENGE_4ARG */
+
+/* Define as const if snprintf() can declare const char *fmt */
+#define SNPRINTF_CONST const
+
+/* Define to a Set Process Title type if your system is
+ supported by
+ bsd-setproctitle.c */
+/* #undef SPT_TYPE */
+
+/* Define if sshd somehow reacquires a controlling TTY
+ after setsid() */
+/* #undef SSHD_ACQUIRES_CTTY */
+
+/* Define if pam_chauthtok wants real uid set
+ to the unpriv'ed user */
+/* #undef SSHPAM_CHAUTHTOK_NEEDS_RUID */
+
+/* Use audit debugging module */
+/* #undef SSH_AUDIT_EVENTS */
+
+/* Windows is sensitive to read buffer size */
+/* #undef SSH_IOBUFSZ */
+
+/* non-privileged user for privilege separation */
+#define SSH_PRIVSEP_USER "sshd"
+
+/* Use tunnel device compatibility to OpenBSD */
+/* #undef SSH_TUN_COMPAT_AF */
+
+/* Open tunnel devices the FreeBSD way */
+/* #undef SSH_TUN_FREEBSD */
+
+/* Open tunnel devices the Linux tun/tap way */
+/* #undef SSH_TUN_LINUX */
+
+/* No layer 2 tunnel support */
+/* #undef SSH_TUN_NO_L2 */
+
+/* Open tunnel devices the OpenBSD way */
+/* #undef SSH_TUN_OPENBSD */
+
+/* Prepend the address family to IP tunnel traffic */
+/* #undef SSH_TUN_PREPEND_AF */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if you want a different $PATH
+ for the superuser */
+/* #undef SUPERUSER_PATH */
+
+/* syslog_r function is safe to use in in a signal handler */
+/* #undef SYSLOG_R_SAFE_IN_SIGHAND */
+
+/* Support passwords > 8 chars */
+/* #undef UNIXWARE_LONG_PASSWORDS */
+
+/* Specify default $PATH */
+#define USER_PATH "/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+
+/* Define this if you want to use libkafs' AFS support */
+/* #undef USE_AFS */
+
+/* Use BSM audit module */
+/* #undef USE_BSM_AUDIT */
+
+/* Use btmp to log bad logins */
+/* #undef USE_BTMP */
+
+/* Use libedit for sftp */
+/* #undef USE_LIBEDIT */
+
+/* Use Linux audit module */
+/* #undef USE_LINUX_AUDIT */
+
+/* Enable OpenSSL engine support */
+/* #undef USE_OPENSSL_ENGINE */
+
+/* Define if you want to enable PAM support */
+/* #undef USE_PAM */
+
+/* Use PIPES instead of a socketpair() */
+#define USE_PIPES 1
+
+/* Define if you want to sanitize fds */
+/* #undef USE_SANITISE_STDFD */
+
+/* Define if you have Solaris process contracts */
+/* #undef USE_SOLARIS_PROCESS_CONTRACTS */
+
+/* Define if you have Solaris projects */
+/* #undef USE_SOLARIS_PROJECTS */
+
+/* Define if you shouldn't strip 'tty' from your
+ ttyname in [uw]tmp */
+/* #undef WITH_ABBREV_NO_TTY */
+
+/* Define if you want to enable AIX4's authenticate function */
+/* #undef WITH_AIXAUTHENTICATE */
+
+/* Define if you have/want arrays
+ (cluster-wide session managment, not C
+ arrays) */
+/* #undef WITH_IRIX_ARRAY */
+
+/* Define if you want IRIX audit trails */
+/* #undef WITH_IRIX_AUDIT */
+
+/* Define if you want IRIX kernel jobs */
+/* #undef WITH_IRIX_JOBS */
+
+/* Define if you want IRIX project management */
+/* #undef WITH_IRIX_PROJECT */
+
+/* Define if you want SELinux support. */
+/* #undef WITH_SELINUX */
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+ significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+# define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+/* # undef WORDS_BIGENDIAN */
+# endif
+#endif
+
+/* Define if xauth is found in your path */
+/* #undef XAUTH_PATH */
+
+/* Enable large inode numbers on Mac OS X 10.5. */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* log for bad login attempts */
+/* #undef _PATH_BTMP */
+
+/* Full path of your "passwd" program */
+#define _PATH_PASSWD_PROG "/usr/bin/passwd"
+
+/* Specify location of ssh.pid */
+#define _PATH_SSH_PIDDIR "."
+
+/* Define if we don't have struct __res_state in resolv.h */
+#define __res_state state
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* type to use in place of socklen_t if not defined */
+/* #undef socklen_t */
+#define WIN32_LEAN_AND_MEAN 1
+#define _CRT_SECURE_NO_DEPRECATE 1
+#define _CRT_NONSTDC_NO_DEPRECATE 1
+#define WIN32_FIXME 1
+#define WINDOWS 1
+
+/* Define if you must implement a startup_needs function for your platform */
+#define HAVE_STARTUP_NEEDS 1
+
+/* Define if your platform uses Winsock instead of BSD sockets (yeah, there are a lot of platforms like this :) */
+#define HAVE_WINSOCK 1
+
+#ifndef WIN32
+#define snprintf _snprintf
+#endif
+
+#define BROKEN_READV_COMPARISON
+
+/* Override detection of some headers and functions on MinGW */
+#undef BROKEN_SNPRINTF
+#define GETPGRP_VOID 1
+#undef HAVE_CRYPT_H
+#define HAVE_DAEMON 1
+#undef HAVE_ENDIAN_H
+#undef HAVE_FCNTL_H
+#define HAVE_FREEADDRINFO 1
+#define HAVE_GAI_STRERROR 1
+#define HAVE_GETADDRINFO 1
+#define HAVE_GETGROUPLIST 1
+#define HAVE_GETNAMEINFO 1
+#undef HAVE_ID_IN_UTMPX
+#define HAVE_INET_ATON 1
+#define HAVE_INET_NTOA 1
+#define HAVE_INNETGR 1
+#undef HAVE_LIBCRYPT
+#define HAVE_NANOSLEEP 1
+#undef HAVE_PATHS_H
+#undef HAVE_PROC_PID
+#undef HAVE_PTY_H
+#define HAVE_NANOSLEEP 1
+#define HAVE_READPASSPHRASE 1
+#undef HAVE_SIG_ATOMIC_T
+#define HAVE_SIZE_T 1
+#undef HAVE_STRERROR
+#define HAVE_STRMODE 1
+#undef __USE_W32_SOCKETS
+
+#ifdef __MINGW32__ /* FIXME: Use autoconf to set this correctly */
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strncasecmp' function. */
+#define HAVE_STRNCASECMP 1
+#endif
+
+/* Define to 1 if you have the locale.h header. */
+#define HAVE_LOCALE_H 1
+
+#define HAVE_STRUCT_IN6_ADDR 1
+#define HAVE_STRUCT_SOCKADDR_IN6 1
+#define HAVE_STRUCT_TIMEVAL 1
+#undef HAVE_SYS_CDEFS_H
+#undef HAVE_SYS_SYSMACROS_H
+#undef HAVE_SYS_MMAN_H
+#undef HAVE_SYS_UN_H
+#define _STRUCT_WINSIZE 1
+
+#define HAVE_TCGETPGRP 1
+
+#undef HAVE_TIME
+
+#define HAVE_VIS_H 1
+
+#define MISSING_FD_MASK 1
+#define MISSING_HOWMANY 1
+#define MISSING_NFDBITS 1
+
+#undef SSH_PRIVSEP_USER
+
+#define HAVE_OPENPTY 1
+
+/* Fixes for loginrec.c */
+#undef CONF_UTMP_FILE
+#undef CONF_WTMPX_FILE
+#undef CONF_WTMP_FILE
+#undef CONF_UTMPX_FILE
+#undef CONF_LASTLOG_FILE
+
+#define BROKEN_SYS_TERMIO_H
+
+
+#define WITH_OPENSSL 1
+#define HAVE_DECL_NFDBITS 0
+#define HAVE_DECL_HOWMANY 0
+#define HAVE_STRTOULL 1
+#define HAVE_USLEEP 1
+
+#if defined ( WIN32 )
+#define __func__ __FUNCTION__
+#endif
+
+#define PATH_MAX MAX_PATH
+
+//#define IN_LOOPBACKNET INADDR_LOOPBACK
+
+#define S_IFIFO 0x1000
+//#define SHUT_RDWR 2
+//#define SHUT_WR 1
+//#define SHUT_RD 0
+
+#define HAVE_EXPLICIT_BZERO
+
+#define HAVE_MBTOWC 1
+
+#include
+#include
+
+#define __attribute__(A)
+
+// define building with MS Visual Studio Compiler and runtime and not with MingW/gcc compiler
+#define WIN32_VS 1
+
+/* disable inclusion of compatability defitnitions in CRT headers */
+#define __STDC__ 1
+
+#define umac128_new umac_new
+#define umac128_update umac_update
+#define umac_final umac128_final
+#define umac_delete umac128_delete
+
+#define HAVE_MBLEN 1
+
+#define SSHDIR "."
+#define _PATH_SFTP_SERVER "sftp-server.exe"
+#define _PATH_SSH_PROGRAM "ssh.exe"
+#define _PATH_LS "dir"
diff --git a/contrib/win32/openssh/config.vcxproj b/contrib/win32/openssh/config.vcxproj
new file mode 100644
index 000000000..540bf6567
--- /dev/null
+++ b/contrib/win32/openssh/config.vcxproj
@@ -0,0 +1,204 @@
+
+
+
+
+ true
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}
+ Win32Proj
+ config
+ 8.1
+ config
+
+
+
+ Application
+ true
+ v140
+ MultiByte
+
+
+ Application
+ false
+ v140
+ true
+ MultiByte
+
+
+ Utility
+ true
+ v140
+ MultiByte
+
+
+ Application
+ false
+ v140
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+
+
+ true
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+
+
+ false
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+
+
+ false
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+
+
+
+
+
+ Level1
+ Disabled
+ _WIN32_WINNT=0x501;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-Win32-Debug-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat\includes;$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+
+
+ Console
+ true
+ bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Debug-Path)lib;%(AdditionalLibraryDirectories)
+
+
+ copy /Y $(SolutionDir)config.h.vs $(OpenSSH-Src-Path)\config.h
+
+
+ Setup config.h in openssh source path for visual studio
+
+
+
+
+
+
+ Level1
+ Disabled
+ _WIN32_WINNT=0x501;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-x64-Debug-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat\includes;$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+
+
+ Console
+ true
+ bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Debug-Path)lib;%(AdditionalLibraryDirectories)
+
+
+ copy /Y $(SolutionDir)config.h.vs $(OpenSSH-Src-Path)\config.h
+
+
+ Setup config.h in openssh source path for visual studio
+
+
+
+
+ Level1
+
+
+ MaxSpeed
+ true
+ true
+ _WIN32_WINNT=0x501;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-Win32-Release-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat\includes;$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreaded
+
+
+ Console
+ No
+ true
+ true
+ bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Release-Path)lib;%(AdditionalLibraryDirectories)
+
+
+ copy /Y $(SolutionDir)config.h.vs $(OpenSSH-Src-Path)\config.h
+
+
+ Setup config.h in openssh source path for visual studio
+
+
+
+
+ Level1
+
+
+ MaxSpeed
+ true
+ true
+ _WIN32_WINNT=0x501;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-x64-Release-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat\includes;$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreaded
+
+
+ Console
+ No
+ true
+ true
+ bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Release-Path)lib;%(AdditionalLibraryDirectories)
+
+
+ copy /Y $(SolutionDir)config.h.vs $(OpenSSH-Src-Path)\config.h
+
+
+ Setup config.h in openssh source path for visual studio
+
+
+
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/config.vcxproj.filters b/contrib/win32/openssh/config.vcxproj.filters
new file mode 100644
index 000000000..34783958e
--- /dev/null
+++ b/contrib/win32/openssh/config.vcxproj.filters
@@ -0,0 +1,17 @@
+
+
+
+
+ {C40EA84D-1664-404D-95C2-79A9E794A94D}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {E2570738-658F-4541-9487-90ECF5F26A93}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {464A0812-84B6-4B3D-B5FD-B3E7F0E0C10E}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/install-sshd.ps1 b/contrib/win32/openssh/install-sshd.ps1
new file mode 100644
index 000000000..d9c08cc9d
--- /dev/null
+++ b/contrib/win32/openssh/install-sshd.ps1
@@ -0,0 +1,43 @@
+$scriptpath = $MyInvocation.MyCommand.Path
+$scriptdir = Split-Path $scriptpath
+
+$sshdpath = Join-Path $scriptdir "sshd.exe"
+$sshagentpath = Join-Path $scriptdir "ssh-agent.exe"
+$logsdir = Join-Path $scriptdir "logs"
+
+$ntrights = "ntrights.exe -u `"NT SERVICE\SSHD`" +r SeAssignPrimaryTokenPrivilege"
+
+if (-not (Test-Path $sshdpath)) {
+ throw "sshd.exe is not present in script path"
+}
+
+if (Get-Service sshd -ErrorAction SilentlyContinue)
+{
+ Stop-Service sshd
+ sc.exe delete sshd 1> null
+}
+
+if (Get-Service ssh-agent -ErrorAction SilentlyContinue)
+{
+ Stop-Service ssh-agent
+ sc.exe delete ssh-agent 1> null
+}
+
+New-Service -Name ssh-agent -BinaryPathName $sshagentpath -Description "SSH Agent" -StartupType Manual | Out-Null
+cmd.exe /c 'sc.exe sdset ssh-agent D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;RP;;;AU)'
+
+New-Service -Name sshd -BinaryPathName $sshdpath -Description "SSH Deamon" -StartupType Manual -DependsOn ssh-agent | Out-Null
+sc.exe config sshd obj= "NT SERVICE\SSHD"
+
+Push-Location
+cd $scriptdir
+cmd.exe /c $ntrights
+Pop-Location
+
+mkdir $logsdir > $null
+$sddl = "O:SYG:DUD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;0x12019f;;;S-1-5-80-3847866527-469524349-687026318-516638107-1125189541)"
+$acl = Get-Acl -Path $logsdir
+$acl.SetSecurityDescriptorSddlForm($sddl)
+Set-Acl -Path $logsdir -AclObject $acl
+Write-Host -ForegroundColor Green "sshd and ssh-agent services successfully installed"
+
diff --git a/contrib/win32/openssh/install-sshlsa.ps1 b/contrib/win32/openssh/install-sshlsa.ps1
new file mode 100644
index 000000000..76a4087a9
--- /dev/null
+++ b/contrib/win32/openssh/install-sshlsa.ps1
@@ -0,0 +1,10 @@
+Copy-Item -Path $PSScriptRoot\ssh-lsa.dll -Destination "$env:windir\system32"
+$subkey = 'SYSTEM\CurrentControlSet\Control\Lsa'
+$value = 'Authentication Packages'
+$reg = [Microsoft.Win32.RegistryKey]::OpenBaseKey('LocalMachine', 0)
+$key = $reg.OpenSubKey($subkey, $true)
+$arr = $key.GetValue($value)
+if ($arr -notcontains 'ssh-lsa') {
+ $arr += 'ssh-lsa'
+ $key.SetValue($value, [string[]]$arr, 'MultiString')
+}
diff --git a/contrib/win32/openssh/keygen.vcxproj b/contrib/win32/openssh/keygen.vcxproj
new file mode 100644
index 000000000..9017c4485
--- /dev/null
+++ b/contrib/win32/openssh/keygen.vcxproj
@@ -0,0 +1,194 @@
+
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ {47496135-131B-41D6-BF2B-EE7144873DD0}
+ Win32Proj
+ keygen
+ 8.1
+ ssh-keygen
+
+
+
+ Application
+ true
+ v140
+ MultiByte
+
+
+ Application
+ false
+ v140
+ true
+ MultiByte
+
+
+ Application
+ true
+ v140
+ MultiByte
+
+
+ Application
+ false
+ v140
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ true
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ false
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ false
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+
+
+
+ Level1
+ Disabled
+ _WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-Win32-Debug-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+ ProgramDatabase
+
+
+ Console
+ true
+ posix_compat.lib;bcrypt.lib;Netapi32.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Debug-Path)lib;%(AdditionalLibraryDirectories)
+ wmainCRTStartup
+
+
+
+
+
+
+ Level1
+ Disabled
+ _WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-x64-Debug-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+ ProgramDatabase
+
+
+ Console
+ true
+ posix_compat.lib;bcrypt.lib;Netapi32.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Debug-Path)lib;%(AdditionalLibraryDirectories)
+ wmainCRTStartup
+
+
+
+
+ Level1
+
+
+ MaxSpeed
+ true
+ true
+ _WIN32_WINNT=0x600;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-Win32-Release-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ posix_compat.lib;bcrypt.lib;Netapi32.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Release-Path)lib;%(AdditionalLibraryDirectories)
+ wmainCRTStartup
+
+
+
+
+ Level1
+
+
+ MaxSpeed
+ true
+ true
+ _WIN32_WINNT=0x600;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-x64-Release-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ posix_compat.lib;bcrypt.lib;Netapi32.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Release-Path)lib;%(AdditionalLibraryDirectories)
+ wmainCRTStartup
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/keygen.vcxproj.filters b/contrib/win32/openssh/keygen.vcxproj.filters
new file mode 100644
index 000000000..dd9dd237d
--- /dev/null
+++ b/contrib/win32/openssh/keygen.vcxproj.filters
@@ -0,0 +1,30 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Resource Files
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/libssh.vcxproj b/contrib/win32/openssh/libssh.vcxproj
new file mode 100644
index 000000000..deffb3d68
--- /dev/null
+++ b/contrib/win32/openssh/libssh.vcxproj
@@ -0,0 +1,296 @@
+
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {05E1115F-8529-46D0-AAAF-52A404CE79A7}
+ Win32Proj
+ libssh
+ 8.1
+
+
+
+ StaticLibrary
+ true
+ v140
+ MultiByte
+
+
+ StaticLibrary
+ true
+ v140
+ MultiByte
+
+
+ StaticLibrary
+ false
+ v140
+ true
+ MultiByte
+
+
+ StaticLibrary
+ false
+ v140
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+
+ NotUsing
+ Level1
+ Disabled
+ _WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-Win32-Debug-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ false
+ MultiThreadedDebug
+ CompileAsC
+ ProgramDatabase
+
+
+ Windows
+ true
+
+
+
+
+ NotUsing
+ Level1
+ Disabled
+ _WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-x64-Debug-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ false
+ MultiThreadedDebug
+ CompileAsC
+ ProgramDatabase
+
+
+ Windows
+ true
+
+
+
+
+ Level1
+ NotUsing
+ MaxSpeed
+ true
+ true
+ _WIN32_WINNT=0x600;WIN32;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-Win32-Release-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreaded
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+ Level1
+ NotUsing
+ MaxSpeed
+ true
+ true
+ _WIN32_WINNT=0x600;WIN32;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-x64-Release-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreaded
+ true
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+ true
+
+
+ true
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/libssh.vcxproj.filters b/contrib/win32/openssh/libssh.vcxproj.filters
new file mode 100644
index 000000000..2cdb21d1f
--- /dev/null
+++ b/contrib/win32/openssh/libssh.vcxproj.filters
@@ -0,0 +1,300 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/openbsd_compat.vcxproj b/contrib/win32/openssh/openbsd_compat.vcxproj
new file mode 100644
index 000000000..198ae3dc5
--- /dev/null
+++ b/contrib/win32/openssh/openbsd_compat.vcxproj
@@ -0,0 +1,265 @@
+
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {DD483F7D-C553-4740-BC1A-903805AD0174}
+ Win32Proj
+ openbsd_compat
+ 8.1
+
+
+
+ StaticLibrary
+ true
+ v140
+ MultiByte
+
+
+ StaticLibrary
+ true
+ v140
+ MultiByte
+
+
+ StaticLibrary
+ false
+ v140
+ true
+ MultiByte
+
+
+ StaticLibrary
+ false
+ v140
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+
+ NotUsing
+ Level1
+ Disabled
+ _WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-Win32-Debug-Path)include;$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)openbsd-compat;$(OpenSSH-Src-Path)libkrb;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+ ProgramDatabase
+
+
+ Windows
+ true
+
+
+
+
+ NotUsing
+ Level1
+ Disabled
+ _WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-x64-Debug-Path)include;$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)openbsd-compat;$(OpenSSH-Src-Path)libkrb;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+ ProgramDatabase
+
+
+ Windows
+ true
+
+
+
+
+ Level1
+ NotUsing
+ MaxSpeed
+ true
+ true
+ _LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;_WIN32_WINNT=0x600;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-Win32-Release-Path)include;$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)openbsd-compat;$(OpenSSH-Src-Path)libkrb;%(AdditionalIncludeDirectories)
+ MultiThreaded
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+ Level1
+ NotUsing
+ MaxSpeed
+ true
+ true
+ _LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;_WIN32_WINNT=0x600;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-x64-Release-Path)include;$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)openbsd-compat;$(OpenSSH-Src-Path)libkrb;%(AdditionalIncludeDirectories)
+ MultiThreaded
+ true
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/openbsd_compat.vcxproj.filters b/contrib/win32/openssh/openbsd_compat.vcxproj.filters
new file mode 100644
index 000000000..978263787
--- /dev/null
+++ b/contrib/win32/openssh/openbsd_compat.vcxproj.filters
@@ -0,0 +1,303 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/openssh_build.cmd b/contrib/win32/openssh/openssh_build.cmd
new file mode 100644
index 000000000..3ddb6a63e
--- /dev/null
+++ b/contrib/win32/openssh/openssh_build.cmd
@@ -0,0 +1,4 @@
+msbuild /property:Configuration=Release /property:Platform=x64 Win32-OpenSSH.sln
+msbuild /property:Configuration=Release /property:Platform=x86 Win32-OpenSSH.sln
+msbuild /property:Configuration=Debug /property:Platform=x64 Win32-OpenSSH.sln
+msbuild /property:Configuration=Debug /property:Platform=x86 Win32-OpenSSH.sln
diff --git a/contrib/win32/openssh/paths.targets b/contrib/win32/openssh/paths.targets
new file mode 100644
index 000000000..5aa3d0025
--- /dev/null
+++ b/contrib/win32/openssh/paths.targets
@@ -0,0 +1,14 @@
+
+
+
+ $(SolutionDir)..\..\..\
+ $(SolutionDir)..\..\..\bin\
+ $(SolutionDir)lib\
+ $(SolutionDir)\OpenSSLSDK\1.0.2d
+ $(SolutionDir)\OpenSSLSDK\1.0.2d\Win32\Release\
+ $(SolutionDir)\OpenSSLSDK\1.0.2d\Win32\Debug\
+ $(SolutionDir)\OpenSSLSDK\1.0.2d\x64\Release\
+ $(SolutionDir)\OpenSSLSDK\1.0.2d\x64\Debug\
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/resource.h b/contrib/win32/openssh/resource.h
new file mode 100644
index 000000000..3c7d7cdea
Binary files /dev/null and b/contrib/win32/openssh/resource.h differ
diff --git a/contrib/win32/openssh/scp.vcxproj b/contrib/win32/openssh/scp.vcxproj
new file mode 100644
index 000000000..2d331044b
--- /dev/null
+++ b/contrib/win32/openssh/scp.vcxproj
@@ -0,0 +1,192 @@
+
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+
+ {29B98ADF-1285-49CE-BF6C-AA92C5D2FB24}
+ Win32Proj
+ keygen
+ 8.1
+ scp
+
+
+
+ Application
+ true
+ v140
+ MultiByte
+
+
+ Application
+ false
+ v140
+ true
+ MultiByte
+
+
+ Application
+ true
+ v140
+ MultiByte
+
+
+ Application
+ false
+ v140
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ true
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ false
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ false
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+
+
+
+ Level1
+ Disabled
+ _WIN32_WINNT=0x501;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-Win32-Debug-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+
+
+ Console
+ true
+ Netapi32.lib;posix_compat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Debug-Path)lib;%(AdditionalLibraryDirectories)
+ wmainCRTStartup
+
+
+
+
+
+
+ Level1
+ Disabled
+ _WIN32_WINNT=0x501;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-x64-Debug-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+
+
+ Console
+ true
+ Netapi32.lib;posix_compat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Debug-Path)lib;%(AdditionalLibraryDirectories)
+ wmainCRTStartup
+
+
+
+
+ Level1
+
+
+ MaxSpeed
+ true
+ true
+ _WIN32_WINNT=0x501;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-Win32-Release-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ Netapi32.lib;posix_compat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Release-Path)lib;%(AdditionalLibraryDirectories)
+ wmainCRTStartup
+
+
+
+
+ Level1
+
+
+ MaxSpeed
+ true
+ true
+ _WIN32_WINNT=0x501;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-x64-Release-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ Netapi32.lib;posix_compat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Release-Path)lib;%(AdditionalLibraryDirectories)
+ wmainCRTStartup
+
+
+
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/scp.vcxproj.filters b/contrib/win32/openssh/scp.vcxproj.filters
new file mode 100644
index 000000000..fccf50e03
--- /dev/null
+++ b/contrib/win32/openssh/scp.vcxproj.filters
@@ -0,0 +1,30 @@
+
+
+
+
+ {C40EA84D-1664-404D-95C2-79A9E794A94D}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {E2570738-658F-4541-9487-90ECF5F26A93}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {464A0812-84B6-4B3D-B5FD-B3E7F0E0C10E}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Resource Files
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/sftp-server.vcxproj b/contrib/win32/openssh/sftp-server.vcxproj
new file mode 100644
index 000000000..29944bb0b
--- /dev/null
+++ b/contrib/win32/openssh/sftp-server.vcxproj
@@ -0,0 +1,196 @@
+
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+
+
+
+ {6657614F-7821-4D55-96EF-7C3C4B551880}
+ Win32Proj
+ keygen
+ 8.1
+ sftp-server
+
+
+
+ Application
+ true
+ v140
+ MultiByte
+
+
+ Application
+ false
+ v140
+ true
+ MultiByte
+
+
+ Application
+ true
+ v140
+ MultiByte
+
+
+ Application
+ false
+ v140
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ true
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ false
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ false
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+
+
+
+ Level1
+ Disabled
+ _WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-Win32-Debug-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+ ProgramDatabase
+
+
+ Console
+ true
+ Netapi32.lib;posix_compat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Debug-Path)lib;%(AdditionalLibraryDirectories)
+ wmainCRTStartup
+
+
+
+
+
+
+ Level1
+ Disabled
+ _WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-x64-Debug-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+ ProgramDatabase
+
+
+ Console
+ true
+ Netapi32.lib;posix_compat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Debug-Path)lib;%(AdditionalLibraryDirectories)
+ wmainCRTStartup
+
+
+
+
+ Level1
+
+
+ MaxSpeed
+ true
+ true
+ _WIN32_WINNT=0x600;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-Win32-Release-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ Netapi32.lib;posix_compat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Release-Path)lib;%(AdditionalLibraryDirectories)
+ wmainCRTStartup
+
+
+
+
+ Level1
+
+
+ MaxSpeed
+ true
+ true
+ _WIN32_WINNT=0x600;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-x64-Release-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ Netapi32.lib;posix_compat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Release-Path)lib;%(AdditionalLibraryDirectories)
+ wmainCRTStartup
+
+
+
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/sftp-server.vcxproj.filters b/contrib/win32/openssh/sftp-server.vcxproj.filters
new file mode 100644
index 000000000..7e84e8c2d
--- /dev/null
+++ b/contrib/win32/openssh/sftp-server.vcxproj.filters
@@ -0,0 +1,33 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Resource Files
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/sftp.vcxproj b/contrib/win32/openssh/sftp.vcxproj
new file mode 100644
index 000000000..f11a60a58
--- /dev/null
+++ b/contrib/win32/openssh/sftp.vcxproj
@@ -0,0 +1,198 @@
+
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {BBEFF9D7-0BC3-41D1-908B-8052158B5052}
+ Win32Proj
+ keygen
+ 8.1
+ sftp
+
+
+
+ Application
+ true
+ v140
+ MultiByte
+
+
+ Application
+ false
+ v140
+ true
+ MultiByte
+
+
+ Application
+ true
+ v140
+ MultiByte
+
+
+ Application
+ false
+ v140
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ true
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ false
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ false
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+
+
+
+ Level1
+ Disabled
+ _WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-Win32-Debug-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+ ProgramDatabase
+
+
+ Console
+ true
+ Netapi32.lib;posix_compat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Debug-Path)lib;%(AdditionalLibraryDirectories)
+ wmainCRTStartup
+
+
+
+
+
+
+ Level1
+ Disabled
+ _WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-x64-Debug-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+ ProgramDatabase
+
+
+ Console
+ true
+ Netapi32.lib;posix_compat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Debug-Path)lib;%(AdditionalLibraryDirectories)
+ wmainCRTStartup
+
+
+
+
+ Level1
+
+
+ MaxSpeed
+ true
+ true
+ _WIN32_WINNT=0x600;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-Win32-Release-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ Netapi32.lib;posix_compat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Release-Path)lib;%(AdditionalLibraryDirectories)
+ wmainCRTStartup
+
+
+
+
+ Level1
+
+
+ MaxSpeed
+ true
+ true
+ _WIN32_WINNT=0x600;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-x64-Release-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ Netapi32.lib;posix_compat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Release-Path)lib;%(AdditionalLibraryDirectories)
+ wmainCRTStartup
+
+
+
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/sftp.vcxproj.filters b/contrib/win32/openssh/sftp.vcxproj.filters
new file mode 100644
index 000000000..04bc65203
--- /dev/null
+++ b/contrib/win32/openssh/sftp.vcxproj.filters
@@ -0,0 +1,42 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Resource Files
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/ssh-add.vcxproj b/contrib/win32/openssh/ssh-add.vcxproj
new file mode 100644
index 000000000..2b95003e9
--- /dev/null
+++ b/contrib/win32/openssh/ssh-add.vcxproj
@@ -0,0 +1,197 @@
+
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {029797FF-C986-43DE-95CD-2E771E86AEBC}
+ Win32Proj
+ keygen
+ 8.1
+ ssh-add
+
+
+
+ Application
+ true
+ v140
+ MultiByte
+
+
+ Application
+ false
+ v140
+ true
+ MultiByte
+
+
+ Application
+ true
+ v140
+ MultiByte
+
+
+ Application
+ false
+ v140
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ true
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ false
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ false
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+
+
+
+ Level1
+ Disabled
+ _WIN32_WINNT=0x501;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-Win32-Debug-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+ ProgramDatabase
+
+
+ Console
+ true
+ posix_compat.lib;Netapi32.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Debug-Path)lib;%(AdditionalLibraryDirectories)
+ wmainCRTStartup
+
+
+
+
+
+
+ Level1
+ Disabled
+ _WIN32_WINNT=0x501;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-x64-Debug-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+ ProgramDatabase
+
+
+ Console
+ true
+ posix_compat.lib;Netapi32.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Debug-Path)lib;%(AdditionalLibraryDirectories)
+ wmainCRTStartup
+
+
+
+
+ Level1
+
+
+ MaxSpeed
+ true
+ true
+ _WIN32_WINNT=0x501;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-Win32-Release-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ posix_compat.lib;Netapi32.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Release-Path)lib;%(AdditionalLibraryDirectories)
+ wmainCRTStartup
+
+
+
+
+ Level1
+
+
+ MaxSpeed
+ true
+ true
+ _WIN32_WINNT=0x501;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-x64-Release-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ posix_compat.lib;Netapi32.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Release-Path)lib;%(AdditionalLibraryDirectories)
+ wmainCRTStartup
+
+
+
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/ssh-add.vcxproj.filters b/contrib/win32/openssh/ssh-add.vcxproj.filters
new file mode 100644
index 000000000..12e01f9c0
--- /dev/null
+++ b/contrib/win32/openssh/ssh-add.vcxproj.filters
@@ -0,0 +1,35 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Resource Files
+
+
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/ssh-agent.vcxproj b/contrib/win32/openssh/ssh-agent.vcxproj
new file mode 100644
index 000000000..376d6e11d
--- /dev/null
+++ b/contrib/win32/openssh/ssh-agent.vcxproj
@@ -0,0 +1,220 @@
+
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {F6644EC5-D6B6-42A1-828C-75E2977470E0}
+ Win32Proj
+ Win32OpenSSH
+ 8.1
+ ssh-agent
+
+
+
+ Application
+ true
+ v140
+ MultiByte
+
+
+ Application
+ true
+ v140
+ MultiByte
+
+
+ Application
+ false
+ v140
+ true
+ MultiByte
+
+
+ Application
+ false
+ v140
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+ $(Platform)\$(Configuration)\$(TargetName)\
+ ssh-agent
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ false
+ $(Platform)\$(Configuration)\$(TargetName)\
+ ssh-agent
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ false
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ ssh-agent
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ false
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ ssh-agent
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+
+ NotUsing
+ Level1
+ Disabled
+ _WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-Win32-Debug-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories);$(OpenSSH-Src-Path)contrib\win32\ssh-pubkey
+ CompileAsC
+ MultiThreadedDebug
+ Sync
+ ProgramDatabase
+
+
+ Console
+ true
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Debug-Path)lib;%(AdditionalLibraryDirectories)
+ Netapi32.lib;Crypt32.lib;posix_compat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ targetos.manifest
+
+
+
+
+ NotUsing
+ Level1
+ Disabled
+ _WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-x64-Debug-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories);$(OpenSSH-Src-Path)contrib\win32\ssh-pubkey
+ CompileAsC
+ MultiThreadedDebug
+ ProgramDatabase
+
+
+ Console
+ true
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Debug-Path)lib;%(AdditionalLibraryDirectories)
+ Netapi32.lib;Crypt32.lib;posix_compat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ targetos.manifest
+
+
+
+
+ Level1
+ NotUsing
+ MaxSpeed
+ true
+ true
+ _WIN32_WINNT=0x600;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-Win32-Release-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories);$(OpenSSH-Src-Path)contrib\win32\ssh-pubkey
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Release-Path)lib;%(AdditionalLibraryDirectories)
+ Netapi32.lib;Crypt32.lib;posix_compat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ targetos.manifest
+
+
+
+
+ Level1
+ NotUsing
+ MaxSpeed
+ true
+ true
+ _WIN32_WINNT=0x600;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-x64-Release-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories);$(OpenSSH-Src-Path)contrib\win32\ssh-pubkey
+ MultiThreaded
+ true
+
+
+ Console
+ true
+ true
+ true
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Release-Path)lib;%(AdditionalLibraryDirectories)
+ Netapi32.lib;Crypt32.lib;posix_compat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ targetos.manifest
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/ssh-lsa.def b/contrib/win32/openssh/ssh-lsa.def
new file mode 100644
index 000000000..b77cde063
--- /dev/null
+++ b/contrib/win32/openssh/ssh-lsa.def
@@ -0,0 +1,11 @@
+; ssh-lsa.def : Declares the module parameters.
+
+LIBRARY "ssh-lsa.DLL"
+
+EXPORTS
+ LsaApInitializePackage @1
+ LsaApLogonUser @2
+ LsaApLogonTerminated @3
+ LsaApCallPackagePassthrough @4
+ LsaApCallPackageUntrusted @5
+ LsaApCallPackage @6
\ No newline at end of file
diff --git a/contrib/win32/openssh/ssh-lsa.vcxproj b/contrib/win32/openssh/ssh-lsa.vcxproj
new file mode 100644
index 000000000..183ee8a4a
--- /dev/null
+++ b/contrib/win32/openssh/ssh-lsa.vcxproj
@@ -0,0 +1,189 @@
+
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+ {02FB3D98-6516-42C6-9762-98811A99960F}
+ Win32Proj
+ ssh-lsa
+ 8.1
+ ssh-lsa
+
+
+
+ DynamicLibrary
+ true
+ v140
+ MultiByte
+
+
+ DynamicLibrary
+ false
+ v140
+ true
+ MultiByte
+
+
+ DynamicLibrary
+ true
+ v140
+ MultiByte
+
+
+ DynamicLibrary
+ false
+ v140
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+
+
+ true
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+
+
+ false
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+
+
+ false
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+
+
+
+
+
+ Level3
+ Disabled
+ _WIN32_WINNT=0x600;__VS_BUILD__=1;__VS_BUILD__WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ true
+ $(OpenSSL-Win32-Debug-Path)include;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+ ProgramDatabase
+
+
+ Console
+ true
+ advapi32.lib
+ $(OpenSSL-Win32-Debug-Path)lib;%(AdditionalLibraryDirectories)
+ ssh-lsa.def
+
+
+
+
+
+
+ Level3
+ Disabled
+ _WIN32_WINNT=0x600;__VS_BUILD__=1;__VS_BUILD__WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ true
+ $(OpenSSL-x64-Debug-Path)include;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+ ProgramDatabase
+
+
+ Console
+ true
+ advapi32.lib
+ $(OpenSSL-x64-Debug-Path)lib;%(AdditionalLibraryDirectories)
+ ssh-lsa.def
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _WIN32_WINNT=0x600;__VS_BUILD__=1;__VS_BUILD___LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(OpenSSL-Win32-Release-Path)include;%(AdditionalIncludeDirectories)
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ advapi32.lib
+ $(OpenSSL-Win32-Release-Path)lib;%(AdditionalLibraryDirectories)
+ ssh-lsa.def
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ _WIN32_WINNT=0x600;__VS_BUILD__=1;__VS_BUILD___LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(OpenSSL-x64-Release-Path)include;%(AdditionalIncludeDirectories)
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ advapi32.lib
+ $(OpenSSL-x64-Release-Path)lib;%(AdditionalLibraryDirectories)
+ ssh-lsa.def
+
+
+
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/ssh-lsa.vcxproj.filters b/contrib/win32/openssh/ssh-lsa.vcxproj.filters
new file mode 100644
index 000000000..44c766469
--- /dev/null
+++ b/contrib/win32/openssh/ssh-lsa.vcxproj.filters
@@ -0,0 +1,27 @@
+
+
+
+
+ {6CB7C14F-01AD-4B45-B64B-7CA809717A41}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {E208189E-89FC-415D-B803-9FE16836833A}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {A4657585-A2AC-4675-8657-EE71F3E97A4D}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+
+
+ Resource Files
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/ssh-shellhost.vcxproj b/contrib/win32/openssh/ssh-shellhost.vcxproj
new file mode 100644
index 000000000..d2cd41580
--- /dev/null
+++ b/contrib/win32/openssh/ssh-shellhost.vcxproj
@@ -0,0 +1,188 @@
+
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+ {C0AE8A30-E4FA-49CE-A2B5-0C072C77EC64}
+ Win32Proj
+ shellhost
+ 8.1
+ ssh-shellhost
+
+
+
+ Application
+ true
+ v140
+ Unicode
+
+
+ Application
+ false
+ v140
+ true
+ Unicode
+
+
+ Application
+ true
+ v140
+ Unicode
+
+
+ Application
+ false
+ v140
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+
+
+ true
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+
+
+ false
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+
+
+ false
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+
+
+
+
+
+ Level1
+ Disabled
+ _WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+
+
+ MultiThreadedDebug
+ ProgramDatabase
+
+
+ Console
+ true
+ kernel32.lib;user32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Debug-Path)lib;%(AdditionalLibraryDirectories)
+
+
+
+
+
+
+ Level1
+ Disabled
+ _WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+
+
+ MultiThreadedDebug
+ ProgramDatabase
+
+
+ Console
+ true
+ kernel32.lib;user32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Debug-Path)lib;%(AdditionalLibraryDirectories)
+
+
+
+
+ Level1
+
+
+ MaxSpeed
+ true
+ true
+ _WIN32_WINNT=0x600;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+
+
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ kernel32.lib;user32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Release-Path)lib;%(AdditionalLibraryDirectories)
+
+
+
+
+ Level1
+
+
+ MaxSpeed
+ true
+ true
+ _WIN32_WINNT=0x600;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+
+
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ kernel32.lib;user32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/ssh.vcxproj b/contrib/win32/openssh/ssh.vcxproj
new file mode 100644
index 000000000..571b3519a
--- /dev/null
+++ b/contrib/win32/openssh/ssh.vcxproj
@@ -0,0 +1,308 @@
+
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {74E69D5E-A1EF-46EA-9173-19A412774104}
+ Win32Proj
+ Win32OpenSSH
+ 8.1
+ ssh
+
+
+
+ Application
+ true
+ v140
+ MultiByte
+
+
+ Application
+ true
+ v140
+ MultiByte
+
+
+ Application
+ false
+ v140
+ true
+ MultiByte
+
+
+ Application
+ false
+ v140
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+ $(Platform)\$(Configuration)\$(TargetName)\
+ ssh
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ false
+ $(Platform)\$(Configuration)\$(TargetName)\
+ ssh
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ false
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ ssh
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ false
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ ssh
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+
+ NotUsing
+ Level1
+ Disabled
+ _WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-Win32-Debug-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ CompileAsC
+ MultiThreadedDebug
+ Sync
+ ProgramDatabase
+
+
+ Console
+ true
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Debug-Path)lib;%(AdditionalLibraryDirectories)
+ Netapi32.lib;posix_compat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ wmainCRTStartup
+
+
+ targetos.manifest
+
+
+
+
+ NotUsing
+ Level1
+ Disabled
+ _WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-x64-Debug-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ CompileAsC
+ MultiThreadedDebug
+ ProgramDatabase
+
+
+ Console
+ true
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Debug-Path)lib;%(AdditionalLibraryDirectories)
+ Netapi32.lib;posix_compat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ wmainCRTStartup
+
+
+ targetos.manifest
+
+
+
+
+ Level1
+ NotUsing
+ MaxSpeed
+ true
+ true
+ _WIN32_WINNT=0x600;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-Win32-Release-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Release-Path)lib;%(AdditionalLibraryDirectories)
+ Netapi32.lib;posix_compat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ wmainCRTStartup
+
+
+ targetos.manifest
+
+
+
+
+ Level1
+ NotUsing
+ MaxSpeed
+ true
+ true
+ _WIN32_WINNT=0x600;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-x64-Release-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreaded
+ true
+
+
+ Console
+ true
+ true
+ true
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Release-Path)lib;%(AdditionalLibraryDirectories)
+ Netapi32.lib;posix_compat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ wmainCRTStartup
+
+
+ targetos.manifest
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/ssh.vcxproj.filters b/contrib/win32/openssh/ssh.vcxproj.filters
new file mode 100644
index 000000000..56187a3e8
--- /dev/null
+++ b/contrib/win32/openssh/ssh.vcxproj.filters
@@ -0,0 +1,320 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Resource Files
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/sshd.vcxproj b/contrib/win32/openssh/sshd.vcxproj
new file mode 100644
index 000000000..e2da8f938
--- /dev/null
+++ b/contrib/win32/openssh/sshd.vcxproj
@@ -0,0 +1,254 @@
+
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ {F58FF6BA-098B-4DB9-9609-A030DFB4D03F}
+ Win32Proj
+ keygen
+ 8.1
+ sshd
+
+
+
+ Application
+ true
+ v140
+ MultiByte
+
+
+ Application
+ false
+ v140
+ true
+ MultiByte
+
+
+ Application
+ true
+ v140
+ MultiByte
+
+
+ Application
+ false
+ v140
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ true
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ false
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+ false
+ $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)\$(TargetName)\
+ $(OpenSSH-Src-Path)contrib\win32\win32compat\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath);
+
+
+
+
+
+ Level1
+ Disabled
+ _WIN32_WINNT=0x600;WIN32_ZLIB_NO;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-Win32-Debug-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+ ProgramDatabase
+
+
+ Console
+ true
+ Netapi32.lib;posix_compat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;Netapi32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Debug-Path)lib;%(AdditionalLibraryDirectories)
+ MultiplyDefinedSymbolOnly
+ wmainCRTStartup
+
+
+ targetos.manifest
+
+
+
+
+
+
+ Level1
+ Disabled
+ _WIN32_WINNT=0x600;WIN32_ZLIB_NO;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-x64-Debug-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+ ProgramDatabase
+
+
+ Console
+ true
+ Netapi32.lib;posix_compat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;Netapi32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Debug-Path)lib;%(AdditionalLibraryDirectories)
+ MultiplyDefinedSymbolOnly
+ wmainCRTStartup
+
+
+ targetos.manifest
+
+
+
+
+ Level1
+
+
+ MaxSpeed
+ true
+ true
+ _WIN32_WINNT=0x600;WIN32_ZLIB_NO;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-Win32-Release-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+ Netapi32.lib;posix_compat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;Netapi32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Release-Path)lib;%(AdditionalLibraryDirectories)
+ MultiplyDefinedSymbolOnly
+ wmainCRTStartup
+
+
+ targetos.manifest
+
+
+
+
+ Level1
+
+
+ Disabled
+ true
+ true
+ _WIN32_WINNT=0x600;WIN32_ZLIB_NO;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ false
+ $(SolutionDir);$(OpenSSL-x64-Release-Path)include;$(OpenSSH-Src-Path)includes;$(OpenSSH-Src-Path);$(OpenSSH-Src-Path)contrib\win32\win32compat;$(OpenSSH-Src-Path)libkrb;$(OpenSSH-Src-Path)libkrb\libKrb5;%(AdditionalIncludeDirectories)
+ MultiThreaded
+ false
+
+
+ Console
+ true
+ true
+ true
+ Netapi32.lib;posix_compat.lib;bcrypt.lib;Userenv.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;openbsd_compat.lib;libssh.lib;libeay32.lib;Netapi32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Release-Path)lib;%(AdditionalLibraryDirectories)
+ MultiplyDefinedSymbolOnly
+ wmainCRTStartup
+
+
+ targetos.manifest
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/sshd.vcxproj.filters b/contrib/win32/openssh/sshd.vcxproj.filters
new file mode 100644
index 000000000..cd2c9120e
--- /dev/null
+++ b/contrib/win32/openssh/sshd.vcxproj.filters
@@ -0,0 +1,159 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Resource Files
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/sshd_config b/contrib/win32/openssh/sshd_config
new file mode 100644
index 000000000..78ce20a7f
--- /dev/null
+++ b/contrib/win32/openssh/sshd_config
@@ -0,0 +1,122 @@
+# $OpenBSD: sshd_config,v 1.84 2011/05/23 03:30:07 djm Exp $
+
+# This is the sshd server system-wide configuration file. See
+# sshd_config(5) for more information.
+
+# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
+
+# The strategy used for options in the default sshd_config shipped with
+# OpenSSH is to specify options with their default value where
+# possible, but leave them commented. Uncommented options override the
+# default value.
+
+#Port 22
+#AddressFamily any
+#ListenAddress 0.0.0.0
+#ListenAddress ::
+
+# The default requires explicit activation of protocol 1
+#Protocol 2
+
+# HostKey for protocol version 1
+#HostKey /etc/ssh/ssh_host_key
+# HostKeys for protocol version 2
+#HostKey /etc/ssh/ssh_host_rsa_key
+#HostKey /etc/ssh/ssh_host_dsa_key
+#HostKey /etc/ssh/ssh_host_ecdsa_key
+
+# Lifetime and size of ephemeral version 1 server key
+#KeyRegenerationInterval 1h
+#ServerKeyBits 1024
+
+# Logging
+# obsoletes QuietMode and FascistLogging
+#SyslogFacility AUTH
+#LogLevel INFO
+
+# Authentication:
+
+#LoginGraceTime 2m
+#PermitRootLogin yes
+#StrictModes yes
+#MaxAuthTries 6
+#MaxSessions 10
+
+#RSAAuthentication yes
+#PubkeyAuthentication yes
+
+# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
+# but this is overridden so installations will only check .ssh/authorized_keys
+AuthorizedKeysFile .ssh/authorized_keys
+
+# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
+#RhostsRSAAuthentication no
+# similar for protocol version 2
+#HostbasedAuthentication no
+# Change to yes if you don't trust ~/.ssh/known_hosts for
+# RhostsRSAAuthentication and HostbasedAuthentication
+#IgnoreUserKnownHosts no
+# Don't read the user's ~/.rhosts and ~/.shosts files
+#IgnoreRhosts yes
+
+# To disable tunneled clear text passwords, change to no here!
+#PasswordAuthentication yes
+#PermitEmptyPasswords no
+
+# Change to no to disable s/key passwords
+#ChallengeResponseAuthentication yes
+
+# Kerberos options
+#KerberosAuthentication no
+#KerberosOrLocalPasswd yes
+#KerberosTicketCleanup yes
+#KerberosGetAFSToken no
+
+# GSSAPI options
+#GSSAPIAuthentication no
+#GSSAPICleanupCredentials yes
+
+# Set this to 'yes' to enable PAM authentication, account processing,
+# and session processing. If this is enabled, PAM authentication will
+# be allowed through the ChallengeResponseAuthentication and
+# PasswordAuthentication. Depending on your PAM configuration,
+# PAM authentication via ChallengeResponseAuthentication may bypass
+# the setting of "PermitRootLogin without-password".
+# If you just want the PAM account and session checks to run without
+# PAM authentication, then enable this but set PasswordAuthentication
+# and ChallengeResponseAuthentication to 'no'.
+#UsePAM no
+
+#AllowAgentForwarding yes
+#AllowTcpForwarding yes
+#GatewayPorts no
+#X11Forwarding no
+#X11DisplayOffset 10
+#X11UseLocalhost yes
+#PrintMotd yes
+#PrintLastLog yes
+#TCPKeepAlive yes
+#UseLogin no
+#UsePrivilegeSeparation yes
+#PermitUserEnvironment no
+#Compression delayed
+#ClientAliveInterval 0
+#ClientAliveCountMax 3
+#UseDNS yes
+#PidFile /var/run/sshd.pid
+#MaxStartups 10
+#PermitTunnel no
+#ChrootDirectory none
+
+# no default banner path
+#Banner none
+
+# override default of no subsystems
+Subsystem sftp C:/Program Files/OpenSSH/sftp-server.exe
+
+# Example of overriding settings on a per-user basis
+#Match User anoncvs
+# X11Forwarding no
+# AllowTcpForwarding no
+# ForceCommand cvs server
+PubkeyAcceptedKeyTypes ssh-ed25519*
\ No newline at end of file
diff --git a/contrib/win32/openssh/targetos.manifest b/contrib/win32/openssh/targetos.manifest
new file mode 100644
index 000000000..44b37135f
--- /dev/null
+++ b/contrib/win32/openssh/targetos.manifest
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+ *
+ *
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/contrib/win32/openssh/uninstall-sshd.ps1 b/contrib/win32/openssh/uninstall-sshd.ps1
new file mode 100644
index 000000000..8f0cd90f4
--- /dev/null
+++ b/contrib/win32/openssh/uninstall-sshd.ps1
@@ -0,0 +1,22 @@
+if (Get-Service sshd -ErrorAction SilentlyContinue)
+{
+ Stop-Service sshd
+ sc.exe delete sshd 1> null
+ Write-Host -ForegroundColor Green "sshd successfully uninstalled"
+}
+else {
+ Write-Host -ForegroundColor Yellow "sshd service is not installed"
+}
+
+if (Get-Service ssh-agent -ErrorAction SilentlyContinue)
+{
+ Stop-Service ssh-agent
+ sc.exe delete ssh-agent 1>null
+ Write-Host -ForegroundColor Green "ssh-agent successfully uninstalled"
+}
+else {
+ Write-Host -ForegroundColor Yellow "ssh-agent service is not installed"
+}
+
+
+
diff --git a/contrib/win32/openssh/uninstall-sshlsa.ps1 b/contrib/win32/openssh/uninstall-sshlsa.ps1
new file mode 100644
index 000000000..c99390ca8
--- /dev/null
+++ b/contrib/win32/openssh/uninstall-sshlsa.ps1
@@ -0,0 +1,10 @@
+$subkey = 'SYSTEM\CurrentControlSet\Control\Lsa'
+$value = 'Authentication Packages'
+$reg = [Microsoft.Win32.RegistryKey]::OpenBaseKey('LocalMachine', 0)
+$key = $reg.OpenSubKey($subkey, $true)
+$arr = $key.GetValue($value)
+if ($arr -contains 'ssh-lsa') {
+ $tempArryList = New-Object System.Collections.Arraylist(,$arr)
+ $tempArryList.Remove('ssh-lsa')
+ $key.SetValue($value, [string[]]$tempArryList, 'MultiString')
+}
diff --git a/contrib/win32/openssh/version.rc b/contrib/win32/openssh/version.rc
new file mode 100644
index 000000000..6242ddcbf
Binary files /dev/null and b/contrib/win32/openssh/version.rc differ
diff --git a/contrib/win32/win32compat/Debug.h b/contrib/win32/win32compat/Debug.h
new file mode 100644
index 000000000..8da03fa1a
--- /dev/null
+++ b/contrib/win32/win32compat/Debug.h
@@ -0,0 +1,39 @@
+/*
+ * Author: NoMachine
+ *
+ * Copyright (c) 2009, 2011 NoMachine
+ * All rights reserved
+ *
+ * Support functions and system calls' replacements needed to let the
+ * software run on Win32 based operating systems.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Debug_H
+#define Debug_H
+
+#define FAIL(CONDITION) if (CONDITION) goto fail
+
+#define NTFAIL(NTFUNC) if((ntStat = (NTFUNC))) goto fail
+
+#endif
diff --git a/contrib/win32/win32compat/ansiprsr.c b/contrib/win32/win32compat/ansiprsr.c
new file mode 100644
index 000000000..9ebd12d01
--- /dev/null
+++ b/contrib/win32/win32compat/ansiprsr.c
@@ -0,0 +1,1000 @@
+/*
+ * Author: Microsoft Corp.
+ *
+ * Copyright (c) 2015 Microsoft Corp.
+ * All rights reserved
+ *
+ * Microsoft openssh win32 port
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ansiprsr.c
+ *
+ * ANSI Parser to run on Win32 based operating systems.
+ *
+ */
+
+#include
+#include
+#include
+#include
+
+
+#include
+
+#include "ansiprsr.h"
+#include "tncon.h"
+#include "tnnet.h"
+
+#define TS_IS 0
+#define TS_SEND 1
+
+// items used from other modules
+TelParams Parameters;
+
+extern int ScreenX;
+extern int ScreenY;
+extern int ScrollTop;
+extern int ScrollBottom;
+
+// end of imports from outside module
+
+bool gbVTAppMode = false;
+
+// private message for port printing to
+unsigned char VT_ST[] = { 0x1b, '/', '\0' };
+
+static int AutoWrap = 1;
+
+BOOL bAtEOLN = FALSE;
+
+static int term_mode;
+
+// ParseANSI globals - these need to be here, because sometimes blocks are sent
+// in mid ANSI sequence
+int iParam[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+int iCurrentParam = 0;
+int bDelimiter = 0;
+int bMode = 0;
+int fcompletion = 1;
+int bExtMode = 0;
+int bCS0 = 0;
+int bCS1 = 0;
+int bBkMode = 0;
+int bCharMode = 0;
+int ReportedX = 0;
+int ReportedY = 0;
+
+BOOL fShiftOut = FALSE;
+BOOL InPrintMode = FALSE;
+BOOL fPcMode = FALSE;
+
+char printErr[] = "Unable to Print: Printer not assigned. Press any key to continue...";
+char cursor_report[255];
+
+#define MODE_CURSORAPP 0x0001
+#define MODE_ANSIVT52 0x0002
+#define MODE_COL132 0x0004
+#define MODE_SMOOTHSCROLL 0x0008
+#define MODE_REVERSESCREEN 0x0010
+#define MODE_ORIGINREL 0x0020
+#define MODE_WRAPAROUND 0x0040
+#define MODE_AUTOREPEAT 0x0080
+#define MODE_APPMODE 0x0100
+#define MODE_LNM 0x0200
+#define MODE_IRM_INSERT 0x0400
+
+int VTMode = 0;
+
+#define MODE_CURSORAPP 0x0001
+#define MODE_ANSIVT52 0x0002
+#define MODE_COL132 0x0004
+#define MODE_SMOOTHSCROLL 0x0008
+#define MODE_REVERSESCREEN 0x0010
+#define MODE_ORIGINREL 0x0020
+#define MODE_WRAPAROUND 0x0040
+#define MODE_AUTOREPEAT 0x0080
+#define MODE_APPMODE 0x0100
+#define MODE_LNM 0x0200
+
+char *GetTerminalId()
+{
+ return TERMINAL_ID;
+}
+
+char * GetStatusReport()
+{
+ return STATUS_REPORT;
+}
+
+char * GetCursorPositionReport()
+{
+ DWORD wr = 0;
+ DWORD out = 0;
+
+ out = _snprintf_s(cursor_report, sizeof(cursor_report), _TRUNCATE,
+ CURSOR_REPORT_FORMAT_STRING, ConGetCursorY() + 1, ConGetCursorX() + 1);
+
+ if (out > 0) {
+ return cursor_report;
+ }
+
+ return NULL;
+}
+
+void BufConvertToG2(char * pszBuffer, int length)
+{
+ int i;
+
+ for (i=0;i= (ConWindowSizeY()-1))
+ {
+ ConScrollDown(ScrollTop,ScrollBottom);
+ ConMoveCursorPosition(-ConGetCursorX(),0);
+ }
+ else
+ ConMoveCursorPosition(-ConGetCursorX(),1);
+ bAtEOLN = FALSE;
+}
+
+unsigned char* ParseBuffer(unsigned char* pszBuffer, unsigned char* pszBufferEnd, unsigned char **respbuf, size_t *resplen)
+{
+ int CurrentX;
+ int CurrentY;
+ int bufLen, cmpLen, i;
+
+ if (!fcompletion)
+ {
+ if (pszBuffer < pszBufferEnd - 1)
+ {
+ unsigned char * pszCurrent = pszBuffer+1;
+ unsigned char * pszNewCurrent = pszCurrent;
+
+ if (term_mode == TERM_ANSI)
+ {
+ pszNewCurrent = ParseANSI(pszCurrent, pszBufferEnd, respbuf, resplen);
+ }
+ else if (term_mode == TERM_VT52)
+ {
+ pszNewCurrent = ParseVT52(pszCurrent, pszBufferEnd, respbuf, resplen);
+ }
+
+ if (pszCurrent == pszNewCurrent) // Pointer didn't move inside Parse function
+ {
+ pszNewCurrent += ConWriteString( (char *)pszCurrent, 1);
+ return pszNewCurrent;
+ }
+ if (pszNewCurrent > pszCurrent)
+ pszBuffer = pszNewCurrent;
+ }
+ }
+
+ // This is handling special characters including locating the ESC which starts a
+ // terminal control sequence.
+ switch ((unsigned char) (*pszBuffer))
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 11:
+ pszBuffer++;
+ break;
+
+ case 7:
+ Beep(1000, 400);
+ pszBuffer++;
+ break;
+
+ case 8:
+ pszBuffer++;
+ if (!bAtEOLN)
+ {
+ CurrentX = ConGetCursorX();
+ if (CurrentX == 0)
+ {
+ ConMoveCursorPosition(ScreenX-1,-1);
+ ConWriteString(" ",1);
+ }
+ else
+ {
+ ConClearNFromCursorLeft(1);
+ ConMoveCursorPosition(-1, 0);
+ }
+ }
+ bAtEOLN = FALSE;
+ break;
+
+ case 9:
+ {
+ if (bAtEOLN) GoToNextLine();
+ int i, MoveRight = 8 - (ConGetCursorX() % 8);
+
+ for ( i = 0; i < MoveRight; i++ )
+ ConWriteString( " ", 1 );
+ pszBuffer++;
+ AutoWrap = 1;
+ bAtEOLN = FALSE;
+ }
+ break;
+
+ case 10:
+ pszBuffer++;
+ AutoWrap = 1;
+ bAtEOLN = FALSE;
+ break;
+
+ case 12:
+ pszBuffer++;
+ ConSetCursorPosition(0, 0);
+ ConClearScreen();
+ AutoWrap = 1;
+ bAtEOLN = FALSE;
+ break;
+
+ case 13:
+ pszBuffer++;
+ AutoWrap = 1;
+ GoToNextLine();
+ break;
+
+ case 14:
+ pszBuffer++;
+ fShiftOut = TRUE;
+ break;
+
+ case 15:
+ fShiftOut = FALSE;
+ pszBuffer++;
+ break;
+
+ case 27:
+ if (pszBuffer < pszBufferEnd -1)
+ {
+ unsigned char * pszCurrent = pszBuffer + 1;
+ unsigned char * pszNewCurrent = pszCurrent;
+
+ if (*pszCurrent == 27)
+ {
+ pszNewCurrent += ConWriteString( (char *)pszCurrent, 1);
+ return pszBuffer + 1;
+ }
+ else
+ {
+ if (term_mode == TERM_ANSI)
+ {
+ pszNewCurrent = ParseANSI(pszCurrent, pszBufferEnd, respbuf, resplen);
+ }
+ else if (term_mode == TERM_VT52)
+ {
+ pszNewCurrent = ParseVT52(pszCurrent, pszBufferEnd, respbuf, resplen);
+ }
+ }
+ if (pszNewCurrent > pszCurrent)
+ pszBuffer = pszNewCurrent;
+ }
+ break;
+
+ default:
+ {
+ if (bAtEOLN) GoToNextLine();
+
+ unsigned char* pszCurrent = pszBuffer;
+ CurrentX = ConGetCursorX();
+ int nCharCount = 0;
+
+ while ((pszCurrent < pszBufferEnd) && (*pszCurrent != (unsigned char)27)
+ && (*pszCurrent > (unsigned char)15) && (*pszCurrent != (unsigned char)255)
+ && (CurrentX++ < ScreenX)) {
+ if (*pszCurrent > 127) {
+ unsigned char nLead = *pszCurrent;
+ nCharCount++;
+ if ((nLead & 128) == 128) {
+ pszCurrent++;
+ }
+ if ((nLead & 192) == 192) {
+ pszCurrent++;
+ }
+ if ((nLead & 224) == 224) {
+ pszCurrent++;
+ }
+ if ((nLead & 240) == 240) {
+ pszCurrent++;
+ }
+ }
+ else
+ pszCurrent++;
+ }
+
+ if (fShiftOut)
+ memset(pszBuffer, '|', pszCurrent - pszBuffer);
+
+ pszBuffer += ConWriteString((char *)pszBuffer, (int)(pszCurrent - pszBuffer));
+
+ if ((CurrentX >= ScreenX) && AutoWrap && !(VTMode & MODE_CURSORAPP))
+ {
+ bAtEOLN = TRUE;
+ }
+ }
+ break;
+ }
+
+ return pszBuffer;
+}
+
+
+unsigned char * GetNextChar(unsigned char *pszBuffer, unsigned char *pszBufferEnd)
+{
+ if (++pszBuffer > pszBufferEnd)
+ return NULL;
+ else
+ return pszBuffer;
+}
+
+void ConSetExtendedMode(int iFunction, BOOL bEnable)
+{
+ switch(iFunction)
+ {
+ case 1:
+ if (bEnable){
+ VTMode |= MODE_CURSORAPP;
+ gbVTAppMode = true;
+ }else{
+ VTMode &= ~MODE_CURSORAPP;
+ gbVTAppMode = false;
+ }
+ break;
+ case 2:
+ if (!bEnable)
+ VTMode |= MODE_ANSIVT52;
+ break;
+ case 3:
+ if (bEnable)
+ VTMode |= MODE_COL132;
+ else
+ VTMode &= ~MODE_COL132;
+ break;
+ case 4:
+ if (bEnable)
+ VTMode |= MODE_SMOOTHSCROLL;
+ else
+ VTMode &= ~MODE_SMOOTHSCROLL;
+ break;
+ case 5:
+ if (bEnable)
+ VTMode |= MODE_REVERSESCREEN;
+ else
+ VTMode &= ~MODE_REVERSESCREEN;
+ break;
+ case 6:
+ if (bEnable)
+ VTMode |= MODE_ORIGINREL;
+ else
+ VTMode &= ~MODE_ORIGINREL;
+ break;
+ case 7:
+ if (bEnable)
+ VTMode |= MODE_WRAPAROUND;
+ else
+ VTMode &= ~MODE_WRAPAROUND;
+ break;
+ case 8:
+ if (bEnable)
+ VTMode |= MODE_AUTOREPEAT;
+ else
+ VTMode &= ~MODE_AUTOREPEAT;
+ break;
+ case 20: // LNM Mode CSI 20h
+ if (bEnable){
+ VTMode |= MODE_LNM;
+ Parameters.nReceiveCRLF = ENUM_CRLF;
+ }else{
+ VTMode &= ~MODE_LNM;
+ Parameters.nReceiveCRLF = ENUM_LF;
+ }
+ break;
+ case 25:
+ ConDisplayCursor(bEnable);
+ break;
+
+ }
+
+ if ((iFunction == 2) && (bEnable))
+ {
+ term_mode = TERM_VT52;
+ }
+}
+
+#define MODE_EXT 0x00000001
+#define MODE_CS0 0x00000002
+#define MODE_CS1 0x00000004
+#define MODE_CS2 0x00000008
+#define MODE_CS3 0x00000010
+#define MODE_BRK 0x00000020
+#define MODE_CHAR 0x00000040
+#define MODE_K 0x00000080
+
+#define DIGI_MASK (MODE_CS0 | MODE_CS1 | MODE_CS2 | MODE_CS3 | MODE_CHAR)
+
+unsigned char * ParseANSI(unsigned char * pszBuffer, unsigned char * pszBufferEnd, unsigned char **respbuf, size_t *resplen)
+{
+ const int nParam = 10; // Maximum number of parameters
+
+ static int SavedX = 0;
+ static int SavedY = 0;
+
+ unsigned char * pszCurrent = pszBuffer;
+
+ if (pszCurrent == NULL || pszBufferEnd == NULL)
+ return NULL;
+
+ fcompletion = 0;
+ do
+ {
+ switch ((unsigned char) *pszCurrent)
+ {
+// Delimiter
+ case ';':
+ bDelimiter = TRUE;
+ break;
+// Modifiers
+ case '?': // Extended Mode
+ bMode |= MODE_EXT;
+ break;
+ case '(':
+ bMode |= MODE_CS0;
+ break;
+ case ')':
+ bMode |= MODE_CS1;
+ break;
+ case '*':
+ bMode |= MODE_CS2;
+ break;
+ case '+':
+ bMode |= MODE_CS3;
+ break;
+ case '[':
+ bMode |= MODE_BRK;
+ break;
+ case '#':
+ bMode |= MODE_CHAR;
+ break;
+
+// Termination Options
+ case 0:
+ fcompletion = 1;
+ break;
+
+ case '}':
+ fcompletion = 1;
+ break;
+
+ case '<': // Character set
+ fcompletion = 1;
+ break;
+
+ case '\\':
+ fcompletion = 1;
+ break;
+
+ case '~':
+ fcompletion = 1;
+ break;
+
+ case '^': // Private message
+ while (pszCurrent && pszCurrent < pszBufferEnd &&
+ _strnicmp((const char *)pszCurrent, (const char *)VT_ST, strlen((const char *)VT_ST) ) ) // while not stop
+ {
+ if (pszCurrent && pszCurrent < pszBufferEnd &&
+ _strnicmp((const char *)pszCurrent, (const char *)VT_ST, strlen((const char *)VT_ST) ) )
+ pszCurrent++;
+ }
+ pszCurrent += strlen((const char *)VT_ST) - 1;
+ fcompletion = 1;
+ break;
+
+ case 'A': // Character Set change or Cursor Up
+ if (bMode & MODE_CHAR)
+ {
+ }
+ else if (bMode & MODE_BRK)
+ {
+ // Cursor UP
+ if (iParam[0] == 0)
+ iParam[0] = 1;
+ ConMoveCursorPosition(0, -iParam[0]);
+ }
+ fcompletion = 1;
+ break;
+
+ case 'B': // Character set change or Cursor down
+ if (bMode & MODE_CHAR)
+ {
+ // Character Set
+ }
+ else if (bMode & MODE_BRK)
+ {
+ // Cursor DOWN
+ if (iParam[0] == 0)
+ iParam[0] = 1;
+ ConMoveCursorPosition(0, iParam[0]);
+ }
+ fcompletion = 1;
+ break;
+
+ case 'C': // Character Set change or Cursor right
+ if (bMode & MODE_CHAR)
+ {
+ // Character Set
+ }
+ else if (bMode & MODE_BRK)
+ {
+ // Cursor right
+ if (iParam[0] == 0)
+ iParam[0] = 1;
+ ConMoveCursorPosition(iParam[0], 0);
+
+ }
+ fcompletion = 1;
+ break;
+
+ case 'D': // Cursor left
+ if (bMode & MODE_BRK)
+ {
+ // Cursor left
+ if (iParam[0] == 0)
+ iParam[0] = 1;
+ ConMoveCursorPosition(-iParam[0], 0);
+ }
+ else if (bMode == 0)
+ {
+ // Index
+ ConScrollDown(ScrollTop,ScrollBottom);
+ }
+ fcompletion = 1;
+ bAtEOLN = FALSE;
+ break;
+
+ case '=': // Application mode
+ VTMode |= MODE_APPMODE;
+ fcompletion = 1;
+ break;
+
+ case '>': // Numeric mode
+ VTMode &= ~MODE_APPMODE;
+ fcompletion = 1;
+ break;
+
+ case '%': // Character set definitions
+ fcompletion = 1;
+ break;
+
+ case 'h':
+ if (bMode & MODE_EXT)
+ {
+ if (iParam[0] == 4 && iParam[1] == 7) {
+ ConSaveScreen();
+ }
+ }
+ case 'l': // ^[?25h
+ if (bMode & MODE_EXT)
+ {
+ if (iParam[0] == 4 && iParam[1] == 7) {
+ ConRestoreScreen();
+ }
+ else
+ {
+ if (iParam[0] == 4) {
+ VTMode |= MODE_IRM_INSERT;
+ }
+ int i;
+ for (i = 0; i < iCurrentParam; i++)
+ ConSetExtendedMode(iParam[i], *pszCurrent == 'h' ? 1 : 0);
+ }
+ }
+ else if (bMode & MODE_BRK)
+ {
+ // Possible set Line feed (option 20)
+ if (iParam[0] == 20)
+ ConSetExtendedMode(iParam[0], *pszCurrent=='h' ? 1 : 0);
+ if (iParam[0] == 4){
+ VTMode &= ~MODE_IRM_INSERT;
+ }
+ }
+ fcompletion = 1;
+ break;
+
+ case 'L':
+ if (iParam[0])
+ {
+ int i;
+ for (i=0; i 0) ? iParam[1] - 1 : 0, (iParam[0] > 0) ? iParam[0] - 1 : 0);
+ }
+ else if (bMode == 0)
+ {
+ //Set tab
+ }
+ fcompletion = 1;
+ bAtEOLN = FALSE;
+ break;
+
+ case 'M':
+ if (iParam[0])
+ {
+ int i ;
+ for (i=0; i': // Exit Alt Keypad mode
+ case '1': // Graphics processor on
+ case '2': // Graphics processor off
+ pszCurrent++;
+ break;
+
+ case '<': // Enter ANSI mode
+ term_mode = TERM_ANSI;
+ pszCurrent++;
+ break;
+
+ default:
+ pszCurrent++;
+ break;
+ }
+
+ return pszCurrent;
+
+}
diff --git a/contrib/win32/win32compat/ansiprsr.h b/contrib/win32/win32compat/ansiprsr.h
new file mode 100644
index 000000000..c1cbfc45c
--- /dev/null
+++ b/contrib/win32/win32compat/ansiprsr.h
@@ -0,0 +1,81 @@
+/*
+ * Author: Microsoft Corp.
+ *
+ * Copyright (c) 2015 Microsoft Corp.
+ * All rights reserved
+ *
+ * Microsoft openssh win32 port
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ansiprsr.h
+ *
+ * ANSI Parser header file to run on Win32 based operating systems.
+ *
+ */
+
+#ifndef __ANSIPRSR_H
+#define __ANSIPRSR_H
+
+#define TERM_ANSI 0
+#define TERM_VT52 1
+
+unsigned char * ParseBuffer(unsigned char* pszBuffer, unsigned char* pszBufferEnd, unsigned char **respbuf, size_t *resplen);
+unsigned char * GetNextChar(unsigned char * pszBuffer, unsigned char *pszBufferEnd);
+unsigned char * ParseANSI(unsigned char * pszBuffer, unsigned char * pszBufferEnd, unsigned char **respbuf, size_t *resplen);
+unsigned char * ParseVT52(unsigned char * pszBuffer, unsigned char * pszBufferEnd, unsigned char **respbuf, size_t *resplen);
+
+#define true TRUE
+#define false FALSE
+#define bool BOOL
+
+#define ENUM_CRLF 0
+#define ENUM_LF 1
+#define ENUM_CR 2
+
+typedef struct _TelParams
+{
+ int fLogging;
+ FILE *fplogfile;
+
+ char *pInputFile;
+
+ char *szDebugInputFile;
+ BOOL fDebugWait;
+
+ int timeOut;
+ int fLocalEcho;
+ int fTreatLFasCRLF;
+ int fSendCROnly;
+ int nReceiveCRLF;
+
+ char sleepChar;
+ char menuChar;
+
+ SOCKET Socket;
+ BOOL bVT100Mode;
+
+ char *pAltKey;
+
+} TelParams;
+
+#endif
\ No newline at end of file
diff --git a/contrib/win32/win32compat/conio.c b/contrib/win32/win32compat/conio.c
new file mode 100644
index 000000000..4e406fa5a
--- /dev/null
+++ b/contrib/win32/win32compat/conio.c
@@ -0,0 +1,183 @@
+/*
+ * Author: Microsoft Corp.
+ *
+ * Copyright (c) 2015 Microsoft Corp.
+ * All rights reserved
+ *
+ * Microsoft openssh win32 port
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/* conio.c
+ *
+ * Inserts data into Windows Console Input. Needed WriteToConsole() API implemented.
+ *
+ */
+
+#include
+#include
+#include
+
+#include
+
+#include "console.h"
+#include
+
+COORD lastCursorLoc = { 0, 0 };
+BYTE KeyboardState[256];
+INPUT_RECORD srec;
+DWORD dwGlobalConsoleMode ;
+
+int WriteToConsole(HANDLE fd, unsigned char *buf, size_t len, size_t *dwWritten, void *flag)
+{
+ static KEY_EVENT_RECORD *pkey;
+ static KEY_EVENT_RECORD *pkey2;
+ static INPUT_RECORD irec[2];
+ static BOOL bInitKeyboard = TRUE;
+ size_t ctr;
+ int rc;
+ DWORD dwRecords;
+ DWORD vkey;
+ BOOL bNeedToWait = TRUE;
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+
+ int scr_width = 80; /* screen horizontal width, e.g. 80 */
+ int scr_height = 25; /* screen vertical length, e.g. 25 */
+ char tmpbuf[2];
+ int local_echo = 0;
+
+ /*
+ * Need to set pkey and pkey2 which we use below. Initialize the keyboard state table.
+ */
+ if (bInitKeyboard)
+ {
+ GetKeyboardState(KeyboardState);
+ bInitKeyboard = FALSE;
+ srec.EventType = KEY_EVENT;
+ srec.Event.KeyEvent.bKeyDown = TRUE;
+ srec.Event.KeyEvent.wRepeatCount = 1;
+ srec.Event.KeyEvent.wVirtualKeyCode = 0x10;
+ srec.Event.KeyEvent.wVirtualScanCode = 0x2a;
+ srec.Event.KeyEvent.uChar.AsciiChar = 0;
+ srec.Event.KeyEvent.uChar.UnicodeChar = 0;
+ srec.Event.KeyEvent.dwControlKeyState = 0x10;
+
+ irec[0].EventType = KEY_EVENT; /* init key down message */
+ pkey = &(irec[0].Event.KeyEvent);
+ pkey->wRepeatCount = 1;
+ pkey->bKeyDown = TRUE;
+
+ irec[1].EventType = KEY_EVENT; /* init key up message */
+ pkey2 = &(irec[1].Event.KeyEvent);
+ pkey2->wRepeatCount = 1;
+ pkey2->bKeyDown = FALSE;
+ }
+
+ // Stream mode processing
+ if (local_echo)
+ {
+ GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
+ }
+
+ GetConsoleMode(fd, &dwGlobalConsoleMode);
+
+ ctr = 0;
+ while (ctr < len)
+ {
+ if (local_echo)
+ {
+ GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
+ lastCursorLoc.Y = csbi.dwCursorPosition.Y;
+ lastCursorLoc.X = csbi.dwCursorPosition.X;
+ }
+ {
+ pkey->dwControlKeyState = 0x00000000;
+ pkey->uChar.AsciiChar = buf[ctr]; /* next char in ascii */
+
+ mbtowc(&(pkey->uChar.UnicodeChar), (const char *)&(buf[ctr]), 1);
+ vkey = VkKeyScan(pkey->uChar.AsciiChar);
+
+ if ((BYTE)(vkey >> 8) != 0xFF) // high order word
+ {
+ if (vkey & 0x0100 || (KeyboardState[VK_LSHIFT] & 0x80)) /* high word gives shift, ctrl, alt status */
+ pkey->dwControlKeyState |= SHIFT_PRESSED; /* shift key presssed*/
+ if (vkey & 0x0200 || (KeyboardState[VK_LCONTROL] & 0x80))
+ pkey->dwControlKeyState |= LEFT_CTRL_PRESSED; /* any ctrl really*/
+ if ((vkey & 0x0400) || (KeyboardState[VK_LMENU] & 0x80))
+ pkey->dwControlKeyState |= LEFT_ALT_PRESSED; /* any ALT really*/
+ }
+ if ((BYTE)vkey != 0xFF) // low order word
+ {
+ pkey->wVirtualKeyCode = (BYTE)vkey;
+ pkey->wVirtualScanCode = MapVirtualKey(pkey->wVirtualKeyCode, 0);
+ if (pkey->uChar.UnicodeChar == 0x1b) // stream mode fix for Admark ESC sequences
+ pkey->wVirtualKeyCode = 0x00db;
+
+
+ }
+
+ /* we need to mimic key up and key down */
+ if (pkey->dwControlKeyState & 0x0100)
+ {
+ srec.Event.KeyEvent.bKeyDown = TRUE;
+ srec.Event.KeyEvent.dwControlKeyState = 0x10;
+ WriteConsoleInput(fd, &srec, 1, &dwRecords); /* write shift down */
+ tmpbuf[0] = irec[0].Event.KeyEvent.uChar.AsciiChar;
+ tmpbuf[1] = '\0';
+ }
+
+ pkey->bKeyDown = TRUE; /*since pkey is mucked by others we do it again*/
+
+ /* dup these into key up message structure from key down message */
+ pkey2->wVirtualKeyCode = pkey->wVirtualKeyCode;
+ pkey2->wVirtualScanCode = pkey->wVirtualScanCode;
+ pkey2->uChar.AsciiChar = pkey->uChar.AsciiChar;
+ pkey2->uChar.UnicodeChar = pkey->uChar.UnicodeChar;
+ pkey2->dwControlKeyState = pkey->dwControlKeyState;
+
+ WriteConsoleInput(fd, irec, 2, &dwRecords); /* key down,up msgs */
+ tmpbuf[0] = irec[0].Event.KeyEvent.uChar.AsciiChar;
+ tmpbuf[1] = '\0';
+ if (pkey->dwControlKeyState & 0x0100)
+ {
+ srec.Event.KeyEvent.bKeyDown = FALSE;
+ srec.Event.KeyEvent.dwControlKeyState = 0x0;
+ WriteConsoleInput(fd, &srec, 1, &dwRecords); /* write shift up */
+
+ }
+ //if ((local_echo))
+ //{
+ // bNeedToWait = EchoInputCharacter(buf[ctr], &csbi.dwCursorPosition, dwGlobalConsoleMode);
+ //}
+ }
+ ctr++;
+ Sleep(0);
+ }
+
+ *dwWritten = len;
+
+ //netflush();
+
+ return 0;
+}
+
+
diff --git a/contrib/win32/win32compat/console.c b/contrib/win32/win32compat/console.c
new file mode 100644
index 000000000..9e2a71ca4
--- /dev/null
+++ b/contrib/win32/win32compat/console.c
@@ -0,0 +1,1590 @@
+/*
+ * Author: Microsoft Corp.
+ *
+ * Copyright (c) 2015 Microsoft Corp.
+ * All rights reserved
+ *
+ * Microsoft openssh win32 port
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/* console.c
+ *
+ * Common library for Windows Console Screen IO.
+ * Contains Windows console related definition so that emulation code can draw
+ * on Windows console screen surface.
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include "console.h"
+#include
+
+#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
+#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x4
+#endif
+
+HANDLE hOutputConsole = NULL;
+DWORD dwSavedAttributes = 0;
+WORD wStartingAttributes = 0;
+
+int ScreenX;
+int ScreenY;
+int ScrollTop;
+int ScrollBottom;
+int LastCursorX;
+int LastCursorY;
+
+char *pSavedScreen = NULL;
+static COORD ZeroCoord = {0,0};
+COORD SavedScreenSize = {0,0};
+COORD SavedScreenCursor = {0, 0 };
+SMALL_RECT SavedViewRect = {0,0,0,0};
+CONSOLE_SCREEN_BUFFER_INFOEX SavedWindowState;
+
+typedef struct _SCREEN_RECORD{
+ PCHAR_INFO pScreenBuf;
+ COORD ScreenSize;
+ COORD ScreenCursor;
+ SMALL_RECT srWindowRect;
+}SCREEN_RECORD,*PSCREEN_RECORD;
+
+PSCREEN_RECORD pSavedScreenRec = NULL;
+
+/* ************************************************************ */
+/* Function: ConInit */
+/* Used to Initialize the Console for output */
+/* ************************************************************ */
+int ConInit( DWORD OutputHandle, BOOL fSmartInit )
+{
+ OSVERSIONINFO os;
+ DWORD dwAttributes = 0;
+ DWORD dwRet = 0;
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ static bool bFirstConInit = true;
+
+ os.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
+ GetVersionEx( &os );
+
+ hOutputConsole = GetStdHandle(OutputHandle);
+ if (hOutputConsole == INVALID_HANDLE_VALUE) {
+ dwRet = GetLastError();
+ printf("GetStdHandle failed with %d\n", dwRet);
+ return dwRet;
+ }
+
+ if (!GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &dwSavedAttributes)) {
+ dwRet = GetLastError();
+ printf("GetConsoleMode failed with %d\n", GetLastError());
+ return dwRet;
+ }
+
+ dwAttributes = dwSavedAttributes;
+ dwAttributes &= ~(ENABLE_LINE_INPUT |
+ ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT);
+ dwAttributes |= ENABLE_WINDOW_INPUT;
+
+ char *term = getenv("TERM");
+
+ if (term != NULL && (_stricmp(term, "ansi") == 0 || _stricmp(term, "passthru") == 0))
+ dwAttributes |= (DWORD)ENABLE_VIRTUAL_TERMINAL_PROCESSING;
+
+ SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), dwAttributes); // Windows NT
+
+ ConSetScreenX();
+ ConSetScreenY();
+ ScrollTop = 0;
+ ScrollBottom = ConWindowSizeY();
+
+ if (GetConsoleScreenBufferInfo(hOutputConsole, &csbi))
+ SavedViewRect = csbi.srWindow;
+
+ return 0;
+}
+
+
+/* ************************************************************ */
+/* Function: ConUnInit */
+/* Used to Uninitialize the Console */
+/* ************************************************************ */
+int ConUnInit( void )
+{
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+
+ if ( hOutputConsole == NULL )
+ return 0;
+
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ return 0;
+
+ SetConsoleMode(hOutputConsole, dwSavedAttributes);
+
+ return 0;
+}
+
+/* ************************************************************ */
+/* Function: ConUnInit */
+/* Used to Uninitialize the Console */
+/* ************************************************************ */
+int ConUnInitWithRestore( void )
+{
+ DWORD dwWritten;
+ COORD Coord ;
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+
+ if ( hOutputConsole == NULL )
+ return 0;
+
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ return 0;
+
+ SetConsoleMode(hOutputConsole, dwSavedAttributes);
+
+ Coord = ConsoleInfo.dwCursorPosition;
+ Coord.X = 0;
+
+ DWORD dwNumChar = (ConsoleInfo.dwSize.Y - ConsoleInfo.dwCursorPosition.Y) *
+ ConsoleInfo.dwSize.X;
+
+ FillConsoleOutputCharacter(hOutputConsole, ' ', dwNumChar,
+ Coord, &dwWritten);
+ FillConsoleOutputAttribute(hOutputConsole, wStartingAttributes, dwNumChar,
+ Coord, &dwWritten);
+
+ SetConsoleTextAttribute(hOutputConsole, wStartingAttributes);
+
+ return 0;
+}
+
+BOOL ConSetScreenRect( int xSize, int ySize )
+{
+ BOOL bSuccess = TRUE;
+
+ CONSOLE_SCREEN_BUFFER_INFO csbi; /* hold current console buffer info */
+ SMALL_RECT srWindowRect; /* hold the new console size */
+ COORD coordScreen;
+
+ bSuccess = GetConsoleScreenBufferInfo(hOutputConsole, &csbi);
+ if (!bSuccess) {
+ return bSuccess;
+ }
+
+ /* get the largest size we can size the console window to */
+ coordScreen = GetLargestConsoleWindowSize(hOutputConsole);
+
+ /* define the new console window size and scroll position */
+ srWindowRect.Top = csbi.srWindow.Top;
+ srWindowRect.Left = csbi.srWindow.Left;
+ srWindowRect.Right = xSize - 1 + srWindowRect.Left;
+ srWindowRect.Bottom = ySize - 1 + srWindowRect.Top;
+
+ /* define the new console buffer size */
+ coordScreen.X = max(csbi.dwSize.X, xSize);
+ coordScreen.Y = max(csbi.dwSize.Y, ySize);
+
+ /* if the current buffer is larger than what we want, resize the */
+ /* console window first, then the buffer */
+ if (csbi.dwSize.X < coordScreen.X ||
+ csbi.dwSize.Y < coordScreen.Y)
+ {
+ bSuccess = SetConsoleScreenBufferSize(hOutputConsole, coordScreen);
+ if (bSuccess)
+ bSuccess = SetConsoleWindowInfo(hOutputConsole, TRUE, &srWindowRect);
+ }
+ else
+ {
+ bSuccess = SetConsoleWindowInfo(hOutputConsole, TRUE, &srWindowRect);
+ if (bSuccess)
+ bSuccess = SetConsoleScreenBufferSize(hOutputConsole, coordScreen);
+ }
+
+ if (bSuccess)
+ ConSaveViewRect();
+
+ /* if the current buffer *is* the size we want, don't do anything! */
+ return bSuccess;
+}
+
+BOOL ConSetScreenSize( int xSize, int ySize )
+{
+ BOOL bSuccess = TRUE;
+
+ CONSOLE_SCREEN_BUFFER_INFO csbi; /* hold current console buffer info */
+ SMALL_RECT srWindowRect; /* hold the new console size */
+ COORD coordScreen;
+
+ bSuccess = GetConsoleScreenBufferInfo(hOutputConsole, &csbi);
+ if (!bSuccess) {
+ return bSuccess;
+ }
+
+ /* get the largest size we can size the console window to */
+ coordScreen = GetLargestConsoleWindowSize(hOutputConsole);
+
+ /* define the new console window size and scroll position */
+ srWindowRect.Right = (SHORT) (min(xSize, coordScreen.X) - 1);
+ srWindowRect.Bottom = (SHORT) (min(ySize, coordScreen.Y) - 1);
+ srWindowRect.Left = srWindowRect.Top = (SHORT) 0;
+
+ /* define the new console buffer size */
+ coordScreen.X = xSize;
+ coordScreen.Y = ySize;
+
+ /* if the current buffer is larger than what we want, resize the */
+ /* console window first, then the buffer */
+ if ((DWORD) csbi.dwSize.X * csbi.dwSize.Y > (DWORD) xSize * ySize)
+ {
+ bSuccess = SetConsoleWindowInfo(hOutputConsole, TRUE, &srWindowRect);
+ if (bSuccess)
+ {
+ bSuccess = SetConsoleScreenBufferSize(hOutputConsole, coordScreen);
+ }
+ }
+
+ /* if the current buffer is smaller than what we want, resize the */
+ /* buffer first, then the console window */
+ if ((DWORD) csbi.dwSize.X * csbi.dwSize.Y < (DWORD) xSize * ySize)
+ {
+ bSuccess = SetConsoleScreenBufferSize(hOutputConsole, coordScreen);
+ if (bSuccess)
+ bSuccess = SetConsoleWindowInfo(hOutputConsole, TRUE, &srWindowRect);
+ }
+
+ if (bSuccess)
+ ConSaveViewRect();
+
+ /* if the current buffer *is* the size we want, don't do anything! */
+ return bSuccess;
+}
+
+/* ************************************************************ */
+/* Function: ConSetAttributes */
+/* Used to set the Color of the console and other attributes */
+/* ************************************************************ */
+void ConSetAttribute(int *iParam, int iParamCount)
+{
+ static int iAttr = 0;
+ int i = 0;
+ BOOL bRet = TRUE;
+
+ if (iParamCount < 1)
+ {
+ iAttr |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
+
+ iAttr = iAttr & ~BACKGROUND_INTENSITY;
+ iAttr = iAttr & ~FOREGROUND_INTENSITY;
+ iAttr = iAttr & ~COMMON_LVB_UNDERSCORE;
+ iAttr = iAttr & ~COMMON_LVB_REVERSE_VIDEO;
+
+ SetConsoleTextAttribute(hOutputConsole, (WORD)iAttr);
+ }
+ else
+ {
+ for (i=0;i ScrollBottom-1)
+ {
+ ConScrollDown( ScrollTop, ScrollBottom );
+ ConSetCursorPosition( 0, ScrollBottom );
+ }
+ else
+ ConSetCursorPosition( 0, Y );
+ break;
+
+ default:
+
+ fOkay = (BOOL)WriteConsole( hOutputConsole, &ch, 1, (LPDWORD)&Result, 0 );
+
+ if ( X >= ScreenX-1 ) // last coord
+ {
+ if (Y >= ScrollBottom-1) // last coord
+ {
+ ConScrollDown(ScrollTop,ScrollBottom);
+ ConMoveCursorPosition(-ConGetCursorX(),0);
+ }
+ else
+ {
+ ConMoveCursorPosition(-ConGetCursorX(),1);
+ }
+ }
+ break;
+ }
+
+ return fOkay;
+}
+
+
+BOOL ConWriteCharW(WCHAR ch)
+{
+ int X, Y, Result;
+ BOOL fOkay = TRUE;
+
+ Y = ConGetCursorY();
+ X = ConGetCursorX();
+
+ switch ( ch )
+ {
+ case 0x8: // BackSpace
+ if ( X == 0 )
+ {
+ ConSetCursorPosition( ScreenX - 1, --Y );
+ WriteConsole( hOutputConsole, " ", 1, (LPDWORD)&Result, 0 );
+ ConSetCursorPosition( ScreenX - 1, Y );
+ }
+ else
+ {
+ ConSetCursorPosition( X - 1, Y );
+ WriteConsole( hOutputConsole, " ", 1, (LPDWORD)&Result, 0 );
+ ConSetCursorPosition( X - 1, Y );
+ }
+
+ break;
+ case L'\r':
+ ConSetCursorPosition( 0, Y );
+ break;
+
+ case L'\n':
+ Y++;
+ if ( Y > ScrollBottom-1)
+ {
+ ConScrollDown( ScrollTop, ScrollBottom );
+ ConSetCursorPosition( 0, ScrollBottom );
+ }
+ else
+ ConSetCursorPosition( 0, Y );
+ break;
+
+ default:
+ fOkay = (BOOL)WriteConsoleW( hOutputConsole, &ch, 1, (LPDWORD)&Result, 0 );
+
+ if ( X >= ScreenX-1 ) // last coord
+ {
+ if (Y >= ScrollBottom-1) // last coord
+ {
+ ConScrollDown(ScrollTop,ScrollBottom);
+ ConMoveCursorPosition(-ConGetCursorX(),0);
+ }
+ else
+ {
+ ConMoveCursorPosition(-ConGetCursorX(),1);
+ }
+ }
+ break;
+ }
+
+ return fOkay;
+}
+
+
+/* Special Function for handling TABS and other bad control chars */
+int ConWriteConsole( char *pData, int NumChars )
+{
+ int X, CurrentY, CurrentX, Result;
+
+ for( X = 0; (X < NumChars) && (pData[X] != '\0') ; X++ )
+ {
+ switch (pData[X])
+ {
+
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 11:
+ break;
+
+ case 7:
+ Beep( 1000, 400);
+ break;
+
+ case 8:
+ ConMoveCursorPosition( -1, 0 );
+ WriteConsole(hOutputConsole, " ", 1, (LPDWORD)&Result, 0);
+ ConMoveCursorPosition( -1, 0 );
+ break;
+
+ case 9:
+ {
+ int i, MoveRight = TAB_LENGTH - (ConGetCursorX() % TAB_LENGTH);
+
+ for ( i = 0; i < MoveRight; i++ )
+ WriteConsole(hOutputConsole, " ", 1, (LPDWORD)&Result, 0);
+ }
+ break;
+
+ case 10:
+ CurrentY = ConGetCursorY()+1;
+ if (CurrentY >= ScrollBottom)
+ {
+ ConScrollDown(ScrollTop,ScrollBottom);
+ ConMoveCursorPosition(-ConGetCursorX(),0);
+ }
+ else
+ {
+ ConMoveCursorPosition(0,1);
+ }
+ break;
+
+ case 12:
+ ConClearScreen();
+ ConSetCursorPosition(0, 0);
+ break;
+
+ case 13:
+ ConMoveCursorPosition(-ConGetCursorX(),0);
+ break;
+
+ case 14:
+ break;
+
+ case 15:
+ break;
+
+ default:
+ {
+
+ CurrentY = ConGetCursorY();
+ CurrentX = ConGetCursorX();
+
+ WriteConsole(hOutputConsole, &pData[X], 1, (LPDWORD)&Result, 0);
+
+ if ( CurrentX >= ScreenX-1) // last coord
+ {
+ if (CurrentY >= ScrollBottom-1) // last coord
+ {
+ ConScrollDown(ScrollTop,ScrollBottom);
+ ConMoveCursorPosition(-ConGetCursorX(),0);
+ }
+ else
+ {
+ ConMoveCursorPosition(-ConGetCursorX(),1);
+ }
+ }
+ }
+ }
+ }
+
+ return X;
+}
+
+PCHAR ConWriteLine(char* pData)
+{
+ PCHAR pCurrent, pNext, pTab;
+ DWORD Result;
+ size_t distance, tabCount, pos;
+ size_t tabLength, charCount;
+
+ pCurrent = pData;
+
+ pNext = strchr( pCurrent, '\r' );
+ if ( pNext != NULL )
+ {
+ distance = pNext - pCurrent;
+
+ if ( distance > (size_t)ScreenX )
+ distance = (size_t)ScreenX;
+
+ pos = 0;
+ tabCount = 0;
+ pTab = strchr( pCurrent, TAB_CHAR );
+ if ( (pTab != NULL) && (pTab < pNext) )
+ {
+ // Tab exists in string
+ // So we use our WriteString
+ while ( (pTab != NULL) && (pTab < pNext) && (pos < (size_t)ScreenX) )
+ {
+ tabCount++;
+ charCount = (pTab - pCurrent) - 1; // Ignore actual TAB since we add 8 for it
+ pos = charCount + (tabCount * TAB_LENGTH);
+ pTab++; // increment past last tab
+ pTab = strchr( pTab, TAB_CHAR );
+ }
+
+ tabLength = (tabCount * TAB_LENGTH);
+
+// if ( pos >= ScreenX )
+ distance = ConWriteConsole( pCurrent, (int)distance );// Special routine for handling TABS
+
+ }
+ else
+ WriteConsole( hOutputConsole,pCurrent, (DWORD)distance, &Result, 0 );
+
+ ConSetCursorPosition( 0, ConGetCursorY() + 1 );
+
+ pCurrent+= (distance + 2); // Add one to always skip last char printed
+ }
+ else
+ {
+ distance = strlen( pCurrent );
+ if ( distance > (size_t)ScreenX )
+ distance = (size_t)ScreenX;
+ WriteConsole( hOutputConsole, pCurrent, (DWORD)distance, &Result, 0 );
+ pCurrent += distance;
+ }
+
+ return pCurrent;
+}
+
+PCHAR ConDisplayData(char* pData, int NumLines)
+{
+ PCHAR pCurrent, pNext, pTab;
+ DWORD Result;
+ size_t Y, distance, pos, add;
+ int linecnt = 0;
+
+ pCurrent = pData;
+
+ for ( ;(pCurrent) &&
+ ((Y = (size_t)ConGetCursorY()) <= (size_t)ScrollBottom) &&
+ (*pCurrent != '\0'); )
+ {
+ pNext = strchr( pCurrent, '\n' );
+ if ( pNext != NULL )
+ {
+ --pNext;
+ if ( *pNext != '\r' )
+ {
+ pNext++;
+ add = 1;
+ }
+ else
+ add = 2;
+ distance = pNext - pCurrent;
+
+ if ( distance > 0 && linecnt < NumLines)
+ {
+ pos = 0;
+ pTab = strchr( pCurrent, TAB_CHAR );
+ if ( (distance > (size_t)ScreenX) || ((pTab != NULL) && (pTab < pNext)) )
+ {
+ ConWriteConsole( pCurrent, (int)distance ); // Special routine for handling TABS
+ }
+ else
+ {
+ WriteConsole( hOutputConsole, pCurrent, (DWORD)distance, &Result, 0 );
+ }
+ }
+ ConMoveCursorPosition(-ConGetCursorX(),1);
+ pCurrent += (distance + add); // Add one to always skip last char printed
+ linecnt++;
+ }
+ else
+ {
+ distance = strlen( pCurrent );
+ if ( distance > (size_t)ScreenX )
+ distance = ScreenX;
+ if (linecnt < NumLines)
+ WriteConsole( hOutputConsole, pCurrent, (DWORD)distance, &Result, 0 );
+ return pCurrent + distance;
+ }
+ }
+ return pCurrent;
+}
+
+int Con_printf( const char *Format, ... )
+{
+ va_list va_data;
+ int len;
+ char Temp[4096];
+
+ memset( Temp, '\0', sizeof( Temp ) );
+
+ va_start( va_data, Format );
+
+ len = vsnprintf( Temp, sizeof(Temp), Format, va_data );
+
+ ConWriteConsole(Temp, len);
+
+ va_end( va_data );
+
+ return len;
+}
+
+BOOL ConDisplayCursor( BOOL bVisible )
+{
+ CONSOLE_CURSOR_INFO ConsoleCursorInfo;
+
+ if (GetConsoleCursorInfo(hOutputConsole, &ConsoleCursorInfo)) {
+
+ ConsoleCursorInfo.bVisible = bVisible;
+
+ return SetConsoleCursorInfo(hOutputConsole, &ConsoleCursorInfo);
+ }
+
+ return FALSE;
+}
+
+void ConClearScreen(void)
+{
+ DWORD dwWritten;
+ COORD Coord ;
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+ SMALL_RECT srcWindow;
+
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ return;
+
+ Coord.X = 0;
+ Coord.Y = 0;
+
+ DWORD dwNumChar = (ConsoleInfo.srWindow.Bottom + 1) *
+ (ConsoleInfo.srWindow.Right + 1);
+
+ FillConsoleOutputCharacter(hOutputConsole, ' ',
+ dwNumChar,
+ Coord, &dwWritten);
+ FillConsoleOutputAttribute(hOutputConsole, ConsoleInfo.wAttributes,
+ dwNumChar,
+ Coord, &dwWritten);
+
+ srcWindow = ConsoleInfo.srWindow;
+
+ ConSetCursorPosition(0, 0);
+}
+
+void ConClearScrollRegion()
+{
+ DWORD dwWritten;
+ COORD Coord ;
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ return;
+
+ Coord.X = 0;
+ Coord.Y = ScrollTop+ConsoleInfo.srWindow.Top;
+ FillConsoleOutputCharacter(hOutputConsole, ' ', (DWORD)ConsoleInfo.dwSize.X * (DWORD)ScrollBottom,
+ Coord, &dwWritten);
+
+ FillConsoleOutputAttribute(hOutputConsole, ConsoleInfo.wAttributes,
+ (DWORD)ConsoleInfo.dwSize.X * (DWORD)ScrollBottom,
+ Coord, &dwWritten);
+
+ ConSetCursorPosition( 0, ScrollTop );
+}
+
+void ConClearEOScreen()
+{
+ DWORD dwWritten;
+ COORD Coord ;
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ return;
+
+ Coord.X = 0;
+ Coord.Y = (short)(ConGetCursorY() + 1) + ConsoleInfo.srWindow.Top;
+ FillConsoleOutputCharacter(hOutputConsole, ' ',
+ (DWORD)(ConsoleInfo.dwSize.X)*
+ (DWORD)(ConsoleInfo.srWindow.Bottom - Coord.Y + 1),
+ Coord, &dwWritten);
+ FillConsoleOutputAttribute(hOutputConsole, ConsoleInfo.wAttributes,
+ (DWORD)(ConsoleInfo.dwSize.X)*
+ (DWORD)(ConsoleInfo.srWindow.Bottom - Coord.Y + 1),
+ Coord, &dwWritten);
+
+ ConClearEOLine();
+}
+
+void ConClearBOScreen()
+{
+ DWORD dwWritten;
+ COORD Coord;
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ return;
+
+ Coord.X = 0;
+ Coord.Y = 0;
+ FillConsoleOutputCharacter(hOutputConsole, ' ',
+ (DWORD)(ConsoleInfo.dwSize.X)*
+ (DWORD)(ConsoleInfo.dwSize.Y - ConGetCursorY() - 1),
+ Coord, &dwWritten);
+ FillConsoleOutputAttribute(hOutputConsole, ConsoleInfo.wAttributes,
+ (DWORD)(ConsoleInfo.dwSize.X)*
+ (DWORD)(ConsoleInfo.dwSize.Y - ConGetCursorY() - 1),
+ Coord, &dwWritten);
+
+ ConClearBOLine();
+}
+
+void ConClearLine()
+{
+ DWORD dwWritten;
+ COORD Coord;
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ return;
+
+ Coord.X = 0;
+ Coord.Y = ConGetCursorY();
+
+ FillConsoleOutputAttribute(hOutputConsole, ConsoleInfo.wAttributes, ScreenX,
+ Coord, &dwWritten);
+ FillConsoleOutputCharacter(hOutputConsole, ' ',ScreenX,
+ Coord, &dwWritten);
+}
+
+void ConClearEOLine()
+{
+ DWORD dwWritten;
+ COORD Coord;
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ return;;
+
+ Coord.X = ConGetCursorX()+ConsoleInfo.srWindow.Left;
+ Coord.Y = ConGetCursorY()+ConsoleInfo.srWindow.Top;
+
+ FillConsoleOutputCharacter(hOutputConsole, ' ',
+ (DWORD)(ScreenX - ConGetCursorX()),
+ Coord, &dwWritten);
+ FillConsoleOutputAttribute(hOutputConsole, ConsoleInfo.wAttributes,
+ (DWORD)(ScreenX - ConGetCursorX()),
+ Coord, &dwWritten);
+}
+
+void ConClearNFromCursorRight(int n)
+{
+ DWORD dwWritten;
+ COORD Coord;
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ return;
+
+
+ Coord.X = ConGetCursorX()+ConsoleInfo.srWindow.Left;
+ Coord.Y = ConGetCursorY()+ConsoleInfo.srWindow.Top;
+ FillConsoleOutputCharacter(hOutputConsole, ' ',
+ (DWORD)n,
+ Coord, &dwWritten);
+ FillConsoleOutputAttribute(hOutputConsole, ConsoleInfo.wAttributes,
+ (DWORD)n,
+ Coord, &dwWritten);
+}
+
+void ConClearNFromCursorLeft(int n)
+{
+ DWORD dwWritten;
+ COORD Coord;
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ return;
+
+ Coord.X = ConGetCursorX()+ConsoleInfo.srWindow.Left-n;
+ Coord.Y = ConGetCursorY()+ConsoleInfo.srWindow.Top;
+ FillConsoleOutputCharacter(hOutputConsole, ' ',
+ (DWORD)n,
+ Coord, &dwWritten);
+ FillConsoleOutputAttribute(hOutputConsole, ConsoleInfo.wAttributes,
+ (DWORD)n,
+ Coord, &dwWritten);
+}
+
+void ConScrollDownEntireBuffer()
+{
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ return;
+ ConScrollDown(0, ConsoleInfo.dwSize.Y - 1);
+ return;
+}
+
+void ConScrollUpEntireBuffer()
+{
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ return;
+ ConScrollUp(0, ConsoleInfo.dwSize.Y - 1);
+ return;
+}
+
+void ConScrollUp(int topline,int botline)
+{
+ SMALL_RECT ScrollRect;
+ SMALL_RECT ClipRect;
+ COORD destination;
+ CHAR_INFO Fill;
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ return;
+
+ if ((botline - topline) == ConsoleInfo.dwSize.Y-1) // scrolling whole buffer
+ {
+ ScrollRect.Top = topline;
+ ScrollRect.Bottom = botline;
+ }
+ else
+ {
+ ScrollRect.Top = topline + ConsoleInfo.srWindow.Top;
+ ScrollRect.Bottom = botline + ConsoleInfo.srWindow.Top;
+ }
+ ScrollRect.Left = 0;
+ ScrollRect.Right = ConScreenSizeX() -1;
+
+ ClipRect.Top = ScrollRect.Top;
+ ClipRect.Bottom = ScrollRect.Bottom;
+ ClipRect.Left = ScrollRect.Left;
+ ClipRect.Right = ScrollRect.Right;
+
+ destination.X = 0;
+ destination.Y = ScrollRect.Top+1;
+
+ Fill.Attributes = ConsoleInfo.wAttributes;
+ Fill.Char.AsciiChar = ' ';
+
+ BOOL bRet = ScrollConsoleScreenBuffer( hOutputConsole,
+ &ScrollRect,
+ &ClipRect,
+ destination,
+ &Fill
+ );
+}
+
+void ConScrollDown(int topline, int botline)
+{
+ SMALL_RECT ScrollRect;
+ SMALL_RECT ClipRect;
+ COORD destination;
+ CHAR_INFO Fill;
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ return;
+
+ if ((botline - topline) == ConsoleInfo.dwSize.Y - 1) // scrolling whole buffer
+ {
+ ScrollRect.Top = topline;
+ ScrollRect.Bottom = botline;
+ }
+ else
+ {
+ ScrollRect.Top = topline + ConsoleInfo.srWindow.Top + 1;
+ ScrollRect.Bottom = botline + ConsoleInfo.srWindow.Top;
+ }
+
+ ScrollRect.Left = 0;
+ ScrollRect.Right = ConScreenSizeX() - 1;
+
+ ClipRect.Top = ScrollRect.Top;
+ ClipRect.Bottom = ScrollRect.Bottom;
+ ClipRect.Left = ScrollRect.Left;
+ ClipRect.Right = ScrollRect.Right;
+
+ destination.X = 0;
+ destination.Y = ScrollRect.Top - 1;
+
+ Fill.Attributes = ConsoleInfo.wAttributes;
+ Fill.Char.AsciiChar = ' ';
+
+ BOOL bRet = ScrollConsoleScreenBuffer( hOutputConsole,
+ &ScrollRect,
+ NULL,
+ destination,
+ &Fill
+ );
+}
+
+void ConClearBOLine()
+{
+ DWORD dwWritten;
+ COORD Coord ;
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ return;
+
+ Coord.X = 0;
+ Coord.Y = (short)(ConGetCursorY());
+ FillConsoleOutputAttribute(hOutputConsole, ConsoleInfo.wAttributes,
+ (DWORD)(ConGetCursorX()),
+ Coord, &dwWritten);
+ FillConsoleOutputCharacter(hOutputConsole, ' ',
+ (DWORD)(ConGetCursorX()),
+ Coord, &dwWritten);
+}
+
+void ConSetCursorPosition(int x, int y)
+{
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+ COORD Coord;
+ int rc;
+
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ return;
+
+ Coord.X = (short)(x);
+ Coord.Y = (short)(y);
+
+ if ((y > ConsoleInfo.dwSize.Y - 1) && y > LastCursorY) {
+ for(int n = LastCursorY; n < y; n++)
+ GoToNextLine();
+ }
+
+ if (y >= ConsoleInfo.dwSize.Y) {
+ Coord.Y = ConsoleInfo.dwSize.Y - 1;
+ }
+
+ if (!SetConsoleCursorPosition(hOutputConsole, Coord))
+ rc = GetLastError();
+
+ LastCursorX = x;
+ LastCursorY = y;
+}
+
+BOOL ConChangeCursor( CONSOLE_CURSOR_INFO *pCursorInfo )
+{
+ return SetConsoleCursorInfo( hOutputConsole, pCursorInfo );
+}
+
+int ConGetCursorX()
+{
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ return 0;
+
+ return ConsoleInfo.dwCursorPosition.X;
+}
+
+int ConGetCursorY()
+{
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ {
+ return 0;
+ }
+
+ return (ConsoleInfo.dwCursorPosition.Y - ConsoleInfo.srWindow.Top);
+}
+
+int ConGetCursorInBufferY()
+{
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ {
+ return 0;
+ }
+
+ return (ConsoleInfo.dwCursorPosition.Y);
+}
+
+void ConMoveCursorPosition(int x, int y)
+{
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+ COORD Coord;
+
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ return;
+
+ Coord.X = (short)(ConsoleInfo.dwCursorPosition.X + x);
+ Coord.Y = (short)(ConsoleInfo.dwCursorPosition.Y + y);
+
+ SetConsoleCursorPosition(hOutputConsole, Coord);
+}
+
+void ConGetRelativeCursorPosition(int *x, int *y)
+{
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ return;
+
+ *x -= ConsoleInfo.srWindow.Left;
+ *y -= ConsoleInfo.srWindow.Top;
+}
+
+void ConDeleteChars(int n)
+{
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+ COORD Coord;
+ CHAR_INFO chiBuffer[256]; // 1 row, 256 characters
+ SMALL_RECT sr;
+ COORD Temp;
+ int result;
+
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ return;
+
+ Coord.X = (short)(ConsoleInfo.dwCursorPosition.X);
+ Coord.Y = (short)(ConsoleInfo.dwCursorPosition.Y);
+
+ sr.Left = Coord.X + n;
+ sr.Top = Coord.Y;
+ sr.Bottom = Coord.Y;
+ sr.Right = ConsoleInfo.srWindow.Right;
+
+ Temp.X = 256;
+ Temp.Y = 1;
+ result = ReadConsoleOutput( hOutputConsole, // handle of a console screen buffer
+ (PCHAR_INFO)chiBuffer, // address of buffer that receives data
+ Temp, // column-row size of destination buffer
+ ZeroCoord, // upper-left cell to write to
+ &sr // address of rectangle to read from
+ );
+ ConClearEOLine();
+
+ sr.Left = Coord.X;
+ Temp.X = 256;
+ Temp.Y = 1;
+
+ sr.Right -= n;
+ result = WriteConsoleOutput(hOutputConsole,(PCHAR_INFO)chiBuffer,Temp, ZeroCoord, &sr);
+}
+
+
+SCREEN_HANDLE ConSaveScreenHandle( SCREEN_HANDLE hScreen )
+{
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+
+ PSCREEN_RECORD pScreenRec = (PSCREEN_RECORD)hScreen;
+
+ int result, width,height;
+
+ if ( hOutputConsole == NULL )
+ return NULL;
+
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ return (NULL);
+
+ if (pScreenRec == NULL){
+ pScreenRec = (PSCREEN_RECORD)malloc(sizeof(SCREEN_RECORD));
+ pScreenRec->pScreenBuf = NULL;
+ }
+
+ pScreenRec->srWindowRect = ConsoleInfo.srWindow;
+ width = ConsoleInfo.srWindow.Right - ConsoleInfo.srWindow.Left + 1;
+ height = ConsoleInfo.srWindow.Bottom - ConsoleInfo.srWindow.Top + 1;
+ pScreenRec->ScreenSize.X = width;
+ pScreenRec->ScreenSize.Y = height;
+ pScreenRec->ScreenCursor.X = ConsoleInfo.dwCursorPosition.X-ConsoleInfo.srWindow.Left;
+ pScreenRec->ScreenCursor.Y = ConsoleInfo.dwCursorPosition.Y-ConsoleInfo.srWindow.Top;
+
+ if (pScreenRec->pScreenBuf == NULL){
+ pScreenRec->pScreenBuf = (PCHAR_INFO)malloc( sizeof(CHAR_INFO) * width * height );
+ }
+
+ if ( !pScreenRec->pScreenBuf )
+ {
+ if ( pScreenRec != (PSCREEN_RECORD)hScreen ) {
+ free(pScreenRec);
+ }
+ return NULL;
+ }
+
+ result = ReadConsoleOutput( hOutputConsole, // handle of a console screen buffer
+ (PCHAR_INFO)(pScreenRec->pScreenBuf), // address of buffer that receives data
+ pScreenRec->ScreenSize, // column-row size of destination buffer
+ ZeroCoord, // upper-left cell to write to
+ &ConsoleInfo.srWindow // address of rectangle to read from
+ );
+
+ return((SCREEN_HANDLE)pScreenRec);
+}
+
+
+BOOL ConRestoreScreenHandle( SCREEN_HANDLE hScreen )
+{
+ BOOL fOkay = FALSE;
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+ COORD beginOfScreen = { 0, 0 };
+ PCHAR_INFO pSavedCharInfo;
+ DWORD dwWritten;
+ PSCREEN_RECORD pScreenRec = (PSCREEN_RECORD)hScreen;
+ int width, height;
+
+ if ( hOutputConsole == NULL )
+ return FALSE;
+
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ return (FALSE);
+
+ width = ConsoleInfo.srWindow.Right - ConsoleInfo.srWindow.Left + 1;
+ height = ConsoleInfo.srWindow.Bottom - ConsoleInfo.srWindow.Top + 1;
+
+ beginOfScreen.X = ConsoleInfo.srWindow.Left;
+ beginOfScreen.Y = ConsoleInfo.srWindow.Top;
+ FillConsoleOutputCharacter(hOutputConsole, ' ', (DWORD)width*height,
+ beginOfScreen, &dwWritten);
+
+ pSavedCharInfo = (PCHAR_INFO)(pScreenRec->pScreenBuf);
+ SetConsoleTextAttribute(hOutputConsole, pSavedCharInfo->Attributes);
+
+ FillConsoleOutputAttribute(hOutputConsole, pSavedCharInfo->Attributes,
+ (DWORD)width*height,
+ beginOfScreen, &dwWritten);
+
+ fOkay = WriteConsoleOutput( hOutputConsole, // handle to a console screen buffer
+ (PCHAR_INFO)(pScreenRec->pScreenBuf), // pointer to buffer with data to write
+ pScreenRec->ScreenSize, // column-row size of source buffer
+ ZeroCoord, // upper-left cell to write from
+ &ConsoleInfo.srWindow // pointer to rectangle to write to
+ );
+
+ SetConsoleWindowInfo(hOutputConsole,TRUE,&pScreenRec->srWindowRect);
+
+ ConSetCursorPosition( pScreenRec->ScreenCursor.X, pScreenRec->ScreenCursor.Y );
+
+ return fOkay;
+}
+
+BOOL ConRestoreScreenColors( )
+{
+ SCREEN_HANDLE hScreen = pSavedScreenRec;
+ BOOL fOkay = FALSE;
+ CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
+ COORD beginOfScreen = { 0, 0 };
+ PCHAR_INFO pSavedCharInfo;
+ DWORD dwWritten;
+ PSCREEN_RECORD pScreenRec = (PSCREEN_RECORD)hScreen;
+
+ if ( hOutputConsole == NULL )
+ return FALSE;
+
+ if ( pSavedScreen == NULL )
+ return FALSE;
+
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &ConsoleInfo))
+ return (FALSE);
+
+ beginOfScreen.X = ConsoleInfo.srWindow.Left;
+ beginOfScreen.Y = ConsoleInfo.srWindow.Top;
+
+ FillConsoleOutputCharacter(hOutputConsole, ' ',
+ (DWORD)pScreenRec->ScreenSize.X*pScreenRec->ScreenSize.Y,
+ beginOfScreen, &dwWritten);
+
+ pSavedCharInfo = (PCHAR_INFO)(pScreenRec->pScreenBuf);
+ SetConsoleTextAttribute(hOutputConsole, pSavedCharInfo->Attributes);
+
+ FillConsoleOutputAttribute(hOutputConsole, pSavedCharInfo->Attributes,
+ (DWORD)pScreenRec->ScreenSize.X*pScreenRec->ScreenSize.Y,
+ beginOfScreen, &dwWritten);
+
+ return fOkay;
+}
+
+void ConDeleteScreenHandle( SCREEN_HANDLE hScreen )
+{
+ PSCREEN_RECORD pScreenRec = (PSCREEN_RECORD)hScreen;
+
+ free(pScreenRec->pScreenBuf);
+ free(pScreenRec);
+
+}
+
+/* ************************************************************ */
+/* Function: ConRestoreScreen */
+/* Restores Previous Saved screen info and buffer */
+/* ************************************************************ */
+BOOL ConRestoreScreen( void )
+{
+ return ConRestoreScreenHandle(pSavedScreenRec);
+}
+
+void ConRestoreViewRect( void )
+{
+ //SetConsoleWindowInfo(hOutputConsole,TRUE,&SavedViewRect);
+}
+
+/* ************************************************************ */
+/* Function: ConSaveScreen */
+/* Saves current screen info and buffer */
+/* ************************************************************ */
+BOOL ConSaveScreen( void )
+{
+ pSavedScreenRec = (PSCREEN_RECORD)ConSaveScreenHandle(pSavedScreenRec);
+ return TRUE;
+}
+
+void ConSaveViewRect( void )
+{
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+
+ if (!GetConsoleScreenBufferInfo(hOutputConsole, &csbi))
+ return;
+
+ SavedViewRect = csbi.srWindow;
+
+}
+
+BOOL ConIsRedirected(HANDLE hInput)
+{
+ DWORD dwMode;
+
+ return !GetConsoleMode(hInput, &dwMode);
+}
+
+HANDLE GetConsoleOutputHandle()
+{
+ SECURITY_ATTRIBUTES sa;
+
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa.lpSecurityDescriptor = NULL;
+ sa.bInheritHandle = TRUE;
+
+ HANDLE hTemp = GetStdHandle(STD_OUTPUT_HANDLE);
+
+ if (ConIsRedirected(hTemp))
+ {
+ hTemp = CreateFile(TEXT("CONOUT$"), GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_WRITE | FILE_SHARE_READ,
+ &sa, OPEN_EXISTING, 0, NULL);
+ }
+
+ return hTemp;
+}
+
+HANDLE GetConsoleInputHandle()
+{
+ SECURITY_ATTRIBUTES sa;
+
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa.lpSecurityDescriptor = NULL;
+ sa.bInheritHandle = TRUE;
+
+ HANDLE hTemp = GetStdHandle(STD_INPUT_HANDLE);
+
+ if (ConIsRedirected(hTemp))
+ {
+ hTemp = CreateFile(TEXT("CONIN$"), GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_WRITE | FILE_SHARE_READ,
+ &sa, OPEN_EXISTING, 0, NULL);
+ }
+
+ return hTemp;
+}
+
+void ConSaveWindowsState(void)
+{
+ CONSOLE_SCREEN_BUFFER_INFOEX csbiex;
+ csbiex.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
+
+ if (!GetConsoleScreenBufferInfoEx(hOutputConsole, &csbiex))
+ return;
+
+ SavedWindowState = csbiex;
+}
diff --git a/contrib/win32/win32compat/console.h b/contrib/win32/win32compat/console.h
new file mode 100644
index 000000000..f06143e26
--- /dev/null
+++ b/contrib/win32/win32compat/console.h
@@ -0,0 +1,139 @@
+/*
+ * Author: Microsoft Corp.
+ *
+ * Copyright (c) 2015 Microsoft Corp.
+ * All rights reserved
+ *
+ * Microsoft openssh win32 port
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/* console.h
+ *
+ * Common library for Windows Console Screen IO.
+ * Contains Windows console related definition so that emulation code can draw
+ * on Windows console screen surface.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ */
+
+#ifndef __PRAGMA_CONSOLE_h
+#define __PRAGMA_CONSOLE_h
+
+#define ANSI_ATTR_RESET 0
+#define ANSI_BRIGHT 1
+#define ANSI_DIM 2
+#define ANSI_UNDERSCORE 4
+#define ANSI_BLINK 5
+#define ANSI_REVERSE 7
+#define ANSI_HIDDEN 8
+#define ANSI_NOUNDERSCORE 24
+#define ANSI_NOREVERSE 27
+
+#define ANSI_FOREGROUND_BLACK 30
+#define ANSI_FOREGROUND_RED 31
+#define ANSI_FOREGROUND_GREEN 32
+#define ANSI_FOREGROUND_YELLOW 33
+#define ANSI_FOREGROUND_BLUE 34
+#define ANSI_FOREGROUND_MAGENTA 35
+#define ANSI_FOREGROUND_CYAN 36
+#define ANSI_FOREGROUND_WHITE 37
+#define ANSI_DEFAULT_FOREGROUND 39
+#define ANSI_BACKGROUND_BLACK 40
+#define ANSI_BACKGROUND_RED 41
+#define ANSI_BACKGROUND_GREEN 42
+#define ANSI_BACKGROUND_YELLOW 43
+#define ANSI_BACKGROUND_BLUE 44
+#define ANSI_BACKGROUND_MAGENTA 45
+#define ANSI_BACKGROUND_CYAN 46
+#define ANSI_BACKGROUND_WHITE 47
+#define ANSI_DEFAULT_BACKGROUND 49
+#define ANSI_BACKGROUND_BRIGHT 128
+
+#define TAB_LENGTH 4
+#define TAB_CHAR '\t'
+#define TAB_SPACE " "
+
+#define true TRUE
+#define false FALSE
+#define bool BOOL
+
+typedef void * SCREEN_HANDLE;
+
+int ConInit( DWORD OutputHandle, BOOL fSmartInit);
+int ConUnInitWithRestore( void );
+int ConUnInit( void );
+BOOL ConIsRedirected(HANDLE hInput);
+HANDLE GetConsoleOutputHandle();
+HANDLE GetConsoleInputHandle();
+BOOL ConSetScreenRect( int xSize, int ySize );
+BOOL ConSetScreenSize( int X, int Y );
+BOOL ConRestoreScreen( void );
+BOOL ConSaveScreen( void );
+void ConSetAttribute( int *iParam, int iParamCount );
+int ConScreenSizeX();
+int ConSetScreenX();
+int ConScreenSizeY();
+int ConWindowSizeX();
+int ConWindowSizeY();
+int ConSetScreenY();
+void ConFillToEndOfLine();
+int ConWriteString(char* pszString, int cbString);
+BOOL ConWriteChar( CHAR ch );
+int ConWriteConsole( char *pData, int NumChars );
+PCHAR ConDisplayData(char* pData, int NumLines);
+PCHAR ConWriteLine(char* pData);
+int Con_printf( const char *Format, ... );
+void ConClearScrollRegion();
+void ConClearScreen();
+void ConClearEOScreen();
+void ConClearBOScreen();
+void ConClearLine();
+void ConClearEOLine();
+void ConClearNFromCursorRight(int n);
+void ConClearNFromCursorLeft(int n);
+void ConScrollUpEntireBuffer();
+void ConScrollDownEntireBuffer();
+void ConScrollUp(int topline,int botline);
+void ConScrollDown(int topline,int botline);
+void ConClearBOLine();
+BOOL ConChangeCursor( CONSOLE_CURSOR_INFO *pCursorInfo );
+void ConSetCursorPosition(int x, int y);
+int ConGetCursorX();
+int ConGetCursorY();
+int ConGetCursorInBufferY(void);
+BOOL ConDisplayCursor( BOOL bVisible );
+void ConMoveCursorPosition(int x, int y);
+void ConGetRelativeCursorPosition(int *x, int *y);
+BOOL ConRestoreScreenHandle( SCREEN_HANDLE hScreen );
+BOOL ConRestoreScreenColors( void );
+SCREEN_HANDLE ConSaveScreenHandle( SCREEN_HANDLE);
+void ConDeleteScreenHandle( SCREEN_HANDLE hScreen );
+void ConSaveViewRect( void );
+void ConRestoreViewRect( void );
+void ConDeleteChars(int n);
+void ConSaveWindowsState(void);
+
+
+#endif
diff --git a/contrib/win32/win32compat/fileio.c b/contrib/win32/win32compat/fileio.c
new file mode 100644
index 000000000..8d7ed26d5
--- /dev/null
+++ b/contrib/win32/win32compat/fileio.c
@@ -0,0 +1,694 @@
+/*
+* Author: Manoj Ampalam
+*
+* Copyright (c) 2015 Microsoft Corp.
+* All rights reserved
+*
+* Microsoft openssh win32 port
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* 1. Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include
+#include
+#include
+#include
+#include "w32fd.h"
+#include "inc/defs.h"
+#include
+#include
+#include "inc\utf.h"
+
+/* internal read buffer size */
+#define READ_BUFFER_SIZE 100*1024
+/* internal write buffer size */
+#define WRITE_BUFFER_SIZE 100*1024
+#define errno_from_Win32LastError() errno_from_Win32Error(GetLastError())
+
+int termio_initiate_read(struct w32_io* pio);
+int termio_initiate_write(struct w32_io* pio, DWORD num_bytes);
+
+/* maps Win32 error to errno */
+int
+errno_from_Win32Error(int win32_error)
+{
+ switch (win32_error) {
+ case ERROR_ACCESS_DENIED:
+ return EACCES;
+ case ERROR_OUTOFMEMORY:
+ return ENOMEM;
+ case ERROR_FILE_EXISTS:
+ return EEXIST;
+ case ERROR_FILE_NOT_FOUND:
+ return ENOENT;
+ default:
+ return win32_error;
+ }
+}
+
+/* used to name named pipes used to implement pipe() */
+static int pipe_counter = 0;
+
+/*
+ * pipe() implementation. Creates an inbound named pipe, uses CreateFile to connect
+ * to it. These handles are associated with read end and write end of the pipe
+ */
+int
+fileio_pipe(struct w32_io* pio[2]) {
+ HANDLE read_handle = INVALID_HANDLE_VALUE, write_handle = INVALID_HANDLE_VALUE;
+ struct w32_io *pio_read = NULL, *pio_write = NULL;
+ char pipe_name[MAX_PATH];
+ SECURITY_ATTRIBUTES sec_attributes;
+
+ if (pio == NULL) {
+ errno = EINVAL;
+ debug("pipe - ERROR invalid parameter");
+ return -1;
+ }
+
+ /* create name for named pipe */
+ if (-1 == sprintf_s(pipe_name, MAX_PATH, "\\\\.\\Pipe\\W32PosixPipe.%08x.%08x",
+ GetCurrentProcessId(), pipe_counter++)) {
+ errno = EOTHER;
+ debug("pipe - ERROR sprintf_s %d", errno);
+ goto error;
+ }
+
+ sec_attributes.bInheritHandle = TRUE;
+ sec_attributes.lpSecurityDescriptor = NULL;
+ sec_attributes.nLength = 0;
+
+ /* create named pipe */
+ read_handle = CreateNamedPipeA(pipe_name,
+ PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
+ PIPE_TYPE_BYTE | PIPE_WAIT,
+ 1,
+ 4096,
+ 4096,
+ 0,
+ &sec_attributes);
+ if (read_handle == INVALID_HANDLE_VALUE) {
+ errno = errno_from_Win32LastError();
+ debug("pipe - CreateNamedPipe() ERROR:%d", errno);
+ goto error;
+ }
+
+ /* connect to named pipe */
+ write_handle = CreateFileA(pipe_name,
+ GENERIC_WRITE,
+ 0,
+ &sec_attributes,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
+ NULL);
+ if (write_handle == INVALID_HANDLE_VALUE) {
+ errno = errno_from_Win32LastError();
+ debug("pipe - ERROR CreateFile() :%d", errno);
+ goto error;
+ }
+
+ /* create w32_io objects encapsulating above handles */
+ pio_read = (struct w32_io*)malloc(sizeof(struct w32_io));
+ pio_write = (struct w32_io*)malloc(sizeof(struct w32_io));
+
+ if (!pio_read || !pio_write) {
+ errno = ENOMEM;
+ debug("pip - ERROR:%d", errno);
+ goto error;
+ }
+
+ memset(pio_read, 0, sizeof(struct w32_io));
+ memset(pio_write, 0, sizeof(struct w32_io));
+
+ pio_read->handle = read_handle;
+ pio_write->handle = write_handle;
+
+ pio[0] = pio_read;
+ pio[1] = pio_write;
+ return 0;
+
+error:
+ if (read_handle)
+ CloseHandle(read_handle);
+ if (write_handle)
+ CloseHandle(write_handle);
+ if (pio_read)
+ free(pio_read);
+ if (pio_write)
+ free(pio_write);
+ return -1;
+}
+
+struct createFile_flags {
+ DWORD dwDesiredAccess;
+ DWORD dwShareMode;
+ SECURITY_ATTRIBUTES securityAttributes;
+ DWORD dwCreationDisposition;
+ DWORD dwFlagsAndAttributes;
+};
+
+/* maps open() file modes and flags to ones needed by CreateFile */
+static int
+createFile_flags_setup(int flags, int mode, struct createFile_flags* cf_flags) {
+
+ /* check flags */
+ int rwflags = flags & 0x3;
+ int c_s_flags = flags & 0xfffffff0;
+
+ /*
+ * should be one of one of the following access modes:
+ * O_RDONLY, O_WRONLY, or O_RDWR
+ */
+ if ((rwflags != O_RDONLY) && (rwflags != O_WRONLY) && (rwflags != O_RDWR)) {
+ debug("open - flags ERROR: wrong rw flags: %d", flags);
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*only following create and status flags currently supported*/
+ if (c_s_flags & ~(O_NONBLOCK | O_APPEND | O_CREAT | O_TRUNC
+ | O_EXCL | O_BINARY)) {
+ debug("open - ERROR: Unsupported flags: %d", flags);
+ errno = ENOTSUP;
+ return -1;
+ }
+
+ /*validate mode*/
+ if (mode &~(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) {
+ debug("open - ERROR: unsupported mode: %d", mode);
+ errno = ENOTSUP;
+ return -1;
+ }
+
+ cf_flags->dwShareMode = 0;
+
+ switch (rwflags) {
+ case O_RDONLY:
+ cf_flags->dwDesiredAccess = GENERIC_READ;
+ /*todo: need to review to make sure all flags are correct*/
+ if (flags & O_NONBLOCK)
+ cf_flags->dwShareMode = FILE_SHARE_READ;
+ break;
+ case O_WRONLY:
+ cf_flags->dwDesiredAccess = GENERIC_WRITE;
+ break;
+ case O_RDWR:
+ cf_flags->dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
+ break;
+ }
+
+ cf_flags->securityAttributes.lpSecurityDescriptor = NULL;
+ cf_flags->securityAttributes.bInheritHandle = TRUE;
+ cf_flags->securityAttributes.nLength = 0;
+
+ cf_flags->dwCreationDisposition = OPEN_EXISTING;
+ if (c_s_flags & O_TRUNC)
+ cf_flags->dwCreationDisposition = TRUNCATE_EXISTING;
+ if (c_s_flags & O_CREAT) {
+ if (c_s_flags & O_EXCL)
+ cf_flags->dwCreationDisposition = CREATE_NEW;
+ else
+ cf_flags->dwCreationDisposition = CREATE_ALWAYS;
+ }
+
+ if (c_s_flags & O_APPEND)
+ cf_flags->dwDesiredAccess = FILE_APPEND_DATA;
+
+ cf_flags->dwFlagsAndAttributes = FILE_FLAG_OVERLAPPED | SECURITY_IMPERSONATION | FILE_FLAG_BACKUP_SEMANTICS;
+
+ /*TODO - map mode */
+
+ return 0;
+}
+
+/* open() implementation. Uses CreateFile to open file, console, device, etc */
+struct w32_io*
+ fileio_open(const char *path_utf8, int flags, int mode) {
+ struct w32_io* pio = NULL;
+ struct createFile_flags cf_flags;
+ HANDLE handle;
+ wchar_t *path_utf16 = NULL;
+
+ debug2("open - pathname:%s, flags:%d, mode:%d", path_utf8, flags, mode);
+ /* check input params*/
+ if (path_utf8 == NULL) {
+ errno = EINVAL;
+ debug("open - ERROR:%d", errno);
+ return NULL;
+ }
+
+ if ((path_utf16 = utf8_to_utf16(path_utf8)) == NULL) {
+ errno = ENOMEM;
+ debug("utf8_to_utf16 failed - ERROR:%d", GetLastError());
+ return NULL;
+ }
+
+ if (createFile_flags_setup(flags, mode, &cf_flags) == -1)
+ return NULL;
+
+ handle = CreateFileW(path_utf16, cf_flags.dwDesiredAccess, cf_flags.dwShareMode,
+ &cf_flags.securityAttributes, cf_flags.dwCreationDisposition,
+ cf_flags.dwFlagsAndAttributes, NULL);
+
+ if (handle == INVALID_HANDLE_VALUE) {
+ errno = errno_from_Win32LastError();
+ debug("open - CreateFile ERROR:%d", GetLastError());
+ free(path_utf16);
+ return NULL;
+ }
+
+ free(path_utf16);
+ pio = (struct w32_io*)malloc(sizeof(struct w32_io));
+ if (pio == NULL) {
+ CloseHandle(handle);
+ errno = ENOMEM;
+ debug("open - ERROR:%d", errno);
+ return NULL;
+ }
+
+ memset(pio, 0, sizeof(struct w32_io));
+
+ if (flags & O_NONBLOCK)
+ pio->fd_status_flags = O_NONBLOCK;
+
+ pio->handle = handle;
+ return pio;
+}
+
+VOID CALLBACK ReadCompletionRoutine(
+ _In_ DWORD dwErrorCode,
+ _In_ DWORD dwNumberOfBytesTransfered,
+ _Inout_ LPOVERLAPPED lpOverlapped
+ ) {
+ struct w32_io* pio =
+ (struct w32_io*)((char*)lpOverlapped - offsetof(struct w32_io, read_overlapped));
+ debug2("ReadCB pio:%p, pending_state:%d, error:%d, received:%d",
+ pio, pio->read_details.pending, dwErrorCode, dwNumberOfBytesTransfered);
+ pio->read_details.error = dwErrorCode;
+ pio->read_details.remaining = dwNumberOfBytesTransfered;
+ pio->read_details.completed = 0;
+ pio->read_details.pending = FALSE;
+ *((__int64*)&lpOverlapped->Offset) += dwNumberOfBytesTransfered;
+}
+
+/* initiate an async read */
+/* TODO: make this a void func, store error in context */
+int
+fileio_ReadFileEx(struct w32_io* pio, unsigned int bytes_requested) {
+ debug2("ReadFileEx io:%p", pio);
+
+ if (pio->read_details.buf == NULL) {
+ pio->read_details.buf = malloc(READ_BUFFER_SIZE);
+ if (!pio->read_details.buf) {
+ errno = ENOMEM;
+ debug2("ReadFileEx - ERROR: %d, io:%p", errno, pio);
+ return -1;
+ }
+ }
+
+ if (FILETYPE(pio) == FILE_TYPE_DISK)
+ pio->read_details.buf_size = min(bytes_requested, READ_BUFFER_SIZE);
+ else
+ pio->read_details.buf_size = READ_BUFFER_SIZE;
+
+ if (ReadFileEx(WINHANDLE(pio), pio->read_details.buf, pio->read_details.buf_size,
+ &pio->read_overlapped, &ReadCompletionRoutine))
+ pio->read_details.pending = TRUE;
+ else {
+ errno = errno_from_Win32LastError();
+ debug("ReadFileEx() ERROR:%d, io:%p", GetLastError(), pio);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* read() implementation */
+int
+fileio_read(struct w32_io* pio, void *dst, unsigned int max) {
+ int bytes_copied;
+
+ debug3("read - io:%p remaining:%d", pio, pio->read_details.remaining);
+
+ /* if read is pending */
+ if (pio->read_details.pending) {
+ if (w32_io_is_blocking(pio)) {
+ debug2("read - io is pending, blocking call made, io:%p", pio);
+ while (fileio_is_io_available(pio, TRUE) == FALSE) {
+ if (-1 == wait_for_any_event(NULL, 0, INFINITE))
+ return -1;
+ }
+ }
+ errno = EAGAIN;
+ debug2("read - io is already pending, io:%p", pio);
+ return -1;
+ }
+
+ if (fileio_is_io_available(pio, TRUE) == FALSE) {
+ if (FILETYPE(pio) == FILE_TYPE_CHAR) {
+ if (-1 == termio_initiate_read(pio))
+ return -1;
+ }
+ else {
+ if (-1 == fileio_ReadFileEx(pio, max)) {
+ if ((FILETYPE(pio) == FILE_TYPE_PIPE)
+ && (errno == ERROR_BROKEN_PIPE)) {
+ /* write end of the pipe closed */
+ debug("read - no more data, io:%p", pio);
+ errno = 0;
+ return 0;
+ }
+ /* on W2012, ReadFileEx on file throws a synchronous EOF error*/
+ else if ((FILETYPE(pio) == FILE_TYPE_DISK)
+ && (errno == ERROR_HANDLE_EOF)) {
+ debug("read - no more data, io:%p", pio);
+ errno = 0;
+ return 0;
+ }
+ return -1;
+ }
+ }
+
+ /* pick up APC if IO has completed */
+ SleepEx(0, TRUE);
+
+ if (w32_io_is_blocking(pio)) {
+ while (fileio_is_io_available(pio, TRUE) == FALSE) {
+ if (-1 == wait_for_any_event(NULL, 0, INFINITE))
+ return -1;
+ }
+ }
+ else if (pio->read_details.pending) {
+ errno = EAGAIN;
+ debug2("read - IO is pending, io:%p", pio);
+ return -1;
+ }
+ }
+
+ if (pio->read_details.error) {
+ errno = errno_from_Win32Error(pio->read_details.error);
+ /*write end of the pipe is closed or pipe broken or eof reached*/
+ if ((pio->read_details.error == ERROR_BROKEN_PIPE) ||
+ (pio->read_details.error == ERROR_HANDLE_EOF)) {
+ debug2("read - (2) no more data, io:%p", pio);
+ errno = 0;
+ pio->read_details.error = 0;
+ return 0;
+ }
+ debug("read - ERROR from cb :%d, io:%p", errno, pio);
+ pio->read_details.error = 0;
+ return -1;
+ }
+
+ bytes_copied = min(max, pio->read_details.remaining);
+ memcpy(dst, pio->read_details.buf + pio->read_details.completed, bytes_copied);
+ pio->read_details.remaining -= bytes_copied;
+ pio->read_details.completed += bytes_copied;
+ debug2("read - io:%p read: %d remaining: %d", pio, bytes_copied,
+ pio->read_details.remaining);
+ return bytes_copied;
+}
+
+VOID CALLBACK WriteCompletionRoutine(
+ _In_ DWORD dwErrorCode,
+ _In_ DWORD dwNumberOfBytesTransfered,
+ _Inout_ LPOVERLAPPED lpOverlapped
+ ) {
+ struct w32_io* pio =
+ (struct w32_io*)((char*)lpOverlapped - offsetof(struct w32_io, write_overlapped));
+ debug2("WriteCB - pio:%p, pending_state:%d, error:%d, transferred:%d of remaining: %d",
+ pio, pio->write_details.pending, dwErrorCode, dwNumberOfBytesTransfered,
+ pio->write_details.remaining);
+ pio->write_details.error = dwErrorCode;
+ /* TODO - assert that remaining == dwNumberOfBytesTransfered */
+ if ((dwErrorCode == 0) && (pio->write_details.remaining != dwNumberOfBytesTransfered)) {
+ debug("WriteCB - ERROR: broken assumption, io:%p, wrote:%d, remaining:%d", pio,
+ dwNumberOfBytesTransfered, pio->write_details.remaining);
+ DebugBreak();
+ }
+ pio->write_details.remaining -= dwNumberOfBytesTransfered;
+ pio->write_details.pending = FALSE;
+ *((__int64*)&lpOverlapped->Offset) += dwNumberOfBytesTransfered;
+}
+
+/* write() implementation */
+int
+fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
+ int bytes_copied;
+
+ debug2("write - io:%p", pio);
+
+ if (pio->write_details.pending) {
+ if (w32_io_is_blocking(pio))
+ {
+ debug2("write - io pending, blocking call made, io:%p", pio);
+ while (pio->write_details.pending) {
+ if (wait_for_any_event(NULL, 0, INFINITE) == -1)
+ return -1;
+ }
+ }
+ else {
+ errno = EAGAIN;
+ debug2("write - IO is already pending, io:%p", pio);
+ return -1;
+ }
+ }
+
+ if (pio->write_details.error) {
+ errno = errno_from_Win32Error(pio->write_details.error);
+ debug("write - ERROR:%d on prior unblocking write, io:%p", errno, pio);
+ pio->write_details.error = 0;
+ if ((FILETYPE(pio) == FILE_TYPE_PIPE) && (errno == ERROR_BROKEN_PIPE)) {
+ debug("write - ERROR:read end of the pipe closed, io:%p", pio);
+ errno = EPIPE;
+ }
+ return -1;
+ }
+
+ if (pio->write_details.buf == NULL) {
+ pio->write_details.buf = malloc(WRITE_BUFFER_SIZE);
+ if (pio->write_details.buf == NULL) {
+ errno = ENOMEM;
+ debug("write - ERROR:%d, io:%p", errno, pio);
+ return -1;
+ }
+ pio->write_details.buf_size = WRITE_BUFFER_SIZE;
+ }
+
+ bytes_copied = min(max, pio->write_details.buf_size);
+ memcpy(pio->write_details.buf, buf, bytes_copied);
+
+ if (FILETYPE(pio) == FILE_TYPE_CHAR) {
+ if (termio_initiate_write(pio, bytes_copied) == 0) {
+ pio->write_details.pending = TRUE;
+ pio->write_details.remaining = bytes_copied;
+ }
+ else
+ return -1;
+ }
+ else {
+ if (WriteFileEx(WINHANDLE(pio), pio->write_details.buf, bytes_copied,
+ &pio->write_overlapped, &WriteCompletionRoutine)) {
+ pio->write_details.pending = TRUE;
+ pio->write_details.remaining = bytes_copied;
+ }
+ else {
+ errno = errno_from_Win32LastError();
+ /* read end of the pipe closed ? */
+ if ((FILETYPE(pio) == FILE_TYPE_PIPE) && (errno == ERROR_BROKEN_PIPE)) {
+ debug("write - ERROR:read end of the pipe closed, io:%p", pio);
+ errno = EPIPE;
+ }
+ debug("write ERROR from cb(2):%d, io:%p", errno, pio);
+ return -1;
+ }
+ }
+
+ if (w32_io_is_blocking(pio)) {
+ while (pio->write_details.pending) {
+ if (wait_for_any_event(NULL, 0, INFINITE) == -1) {
+ /* if interrupted but write has completed, we are good*/
+ if ((errno != EINTR) || (pio->write_details.pending))
+ return -1;
+ errno = 0;
+ }
+ }
+ }
+ /* execute APC to give a chance for write to complete */
+ SleepEx(0, TRUE);
+
+ /* if write has completed, pick up any error reported*/
+ if (!pio->write_details.pending && pio->write_details.error) {
+ errno = errno_from_Win32Error(pio->write_details.error);
+ debug("write - ERROR from cb:%d, io:%p", pio->write_details.error, pio);
+ pio->write_details.error = 0;
+ return -1;
+ }
+ debug2("write - reporting %d bytes written, io:%p", bytes_copied, pio);
+ return bytes_copied;
+
+}
+
+/* fstat() implemetation */
+int
+fileio_fstat(struct w32_io* pio, struct _stat64 *buf) {
+
+ int fd = _open_osfhandle((intptr_t)pio->handle, 0);
+ debug2("fstat - pio:%p", pio);
+ if (fd == -1) {
+ errno = EOTHER;
+ return -1;
+ }
+
+ return _fstat64(fd, buf);
+}
+
+int
+fileio_stat(const char *path, struct _stat64 *buf) {
+ wchar_t wpath[MAX_PATH];
+ wchar_t* wtmp = NULL;
+
+ if ((wtmp = utf8_to_utf16(path)) == NULL)
+ fatal("failed to covert input arguments");
+ wcscpy(&wpath[0], wtmp);
+ free(wtmp);
+
+ return _wstat64(wpath, buf);
+}
+
+long
+fileio_lseek(struct w32_io* pio, long offset, int origin) {
+ debug2("lseek - pio:%p", pio);
+ if (origin != SEEK_SET) {
+ debug("lseek - ERROR, origin is not supported %d", origin);
+ errno = ENOTSUP;
+ return -1;
+ }
+
+ pio->read_overlapped.Offset = offset;
+ pio->write_overlapped.Offset = offset;
+ return 0;
+}
+
+/* fdopen implementation */
+FILE*
+fileio_fdopen(struct w32_io* pio, const char *mode) {
+
+ int fd_flags = 0;
+ debug2("fdopen - io:%p", pio);
+
+ /* logic below doesn't work with overlapped file HANDLES */
+ errno = ENOTSUP;
+ return NULL;
+
+ if (mode[1] == '\0') {
+ switch (*mode) {
+ case 'r':
+ fd_flags = _O_RDONLY;
+ break;
+ case 'w':
+ break;
+ case 'a':
+ fd_flags = _O_APPEND;
+ break;
+ default:
+ errno = ENOTSUP;
+ debug("fdopen - ERROR unsupported mode %s", mode);
+ return NULL;
+ }
+ }
+ else {
+ errno = ENOTSUP;
+ debug("fdopen - ERROR unsupported mode %s", mode);
+ return NULL;
+ }
+
+ int fd = _open_osfhandle((intptr_t)pio->handle, fd_flags);
+
+ if (fd == -1) {
+ errno = EOTHER;
+ debug("fdopen - ERROR:%d _open_osfhandle()", errno);
+ return NULL;
+ }
+
+ return _fdopen(fd, mode);
+}
+
+void
+fileio_on_select(struct w32_io* pio, BOOL rd) {
+
+ if (!rd)
+ return;
+
+ if (!pio->read_details.pending && !fileio_is_io_available(pio, rd))
+ /* initiate read, record any error so read() will pick up */
+ if (FILETYPE(pio) == FILE_TYPE_CHAR) {
+ if (termio_initiate_read(pio) != 0) {
+ pio->read_details.error = errno;
+ errno = 0;
+ return;
+ }
+ }
+ else {
+ if (fileio_ReadFileEx(pio, INT_MAX) != 0) {
+ pio->read_details.error = errno;
+ errno = 0;
+ return;
+ }
+ }
+}
+
+
+int
+fileio_close(struct w32_io* pio) {
+
+ debug2("fileclose - pio:%p", pio);
+
+ CancelIo(WINHANDLE(pio));
+ //let queued APCs (if any) drain
+ SleepEx(0, TRUE);
+ if (pio->type != STD_IO_FD) {//STD handles are never explicitly closed
+ CloseHandle(WINHANDLE(pio));
+
+ if (pio->read_details.buf)
+ free(pio->read_details.buf);
+
+ if (pio->write_details.buf)
+ free(pio->write_details.buf);
+
+ free(pio);
+ }
+ return 0;
+}
+
+BOOL
+fileio_is_io_available(struct w32_io* pio, BOOL rd) {
+ if (rd) {
+ if (pio->read_details.remaining || pio->read_details.error)
+ return TRUE;
+ else
+ return FALSE;
+ }
+ else { //write
+ return (pio->write_details.pending == FALSE) ? TRUE : FALSE;
+ }
+}
\ No newline at end of file
diff --git a/contrib/win32/win32compat/inc/arpa/inet.h b/contrib/win32/win32compat/inc/arpa/inet.h
new file mode 100644
index 000000000..d522ea827
--- /dev/null
+++ b/contrib/win32/win32compat/inc/arpa/inet.h
@@ -0,0 +1,6 @@
+#ifndef COMPAT_INET_H
+#define COMPAT_INET_H 1
+
+/* Compatibility header to avoid lots of #ifdef _WIN32's in includes.h */
+
+#endif
diff --git a/contrib/win32/win32compat/inc/arpa/nameser.h b/contrib/win32/win32compat/inc/arpa/nameser.h
new file mode 100644
index 000000000..a9ecc0c34
--- /dev/null
+++ b/contrib/win32/win32compat/inc/arpa/nameser.h
@@ -0,0 +1,6 @@
+#ifndef COMPAT_NAMESER_H
+#define COMPAT_NAMESER_H 1
+
+/* Compatibility header to avoid lots of #ifdef _WIN32's in includes.h */
+
+#endif
diff --git a/contrib/win32/win32compat/inc/crypto-wrap.h b/contrib/win32/win32compat/inc/crypto-wrap.h
new file mode 100644
index 000000000..6ed12df54
--- /dev/null
+++ b/contrib/win32/win32compat/inc/crypto-wrap.h
@@ -0,0 +1,76 @@
+
+#ifndef _OPENSSL_WRAP_H
+#define _OPENSSL_WRAP_H
+
+struct sshdh;
+struct sshbn;
+struct sshbuf;
+struct ssh;
+struct sshedh;
+struct sshepoint;
+struct sshecurve;
+
+
+struct sshdh *sshdh_new(void);
+void sshdh_free(struct sshdh *dh);
+struct sshbn *sshdh_pubkey(struct sshdh *dh);
+struct sshbn *sshdh_p(struct sshdh *dh);
+struct sshbn *sshdh_g(struct sshdh *dh);
+void sshdh_dump(struct sshdh *dh);
+size_t sshdh_shared_key_size(struct sshdh *dh);
+int sshdh_compute_key(struct sshdh *dh, struct sshbn *pubkey,
+struct sshbn **shared_secretp);
+int sshdh_generate(struct sshdh *dh, size_t len);
+int sshdh_new_group_hex(const char *gen, const char *modulus,
+struct sshdh **dhp);
+struct sshdh *sshdh_new_group(struct sshbn *gen, struct sshbn *modulus);
+
+struct sshedh *sshedh_new(void);
+void sshedh_free(struct sshdh *dh);
+struct sshepoint *sshedh_pubkey(struct sshedh *dh);
+void sshedh_dump(struct sshedh *dh);
+size_t sshedh_shared_key_size(struct sshedh *dh);
+int sshedh_compute_key(struct sshedh *dh, struct sshepoint *pubkey,
+struct sshbn **shared_secretp);
+int sshedh_generate(struct sshedh *dh, size_t len);
+struct sshedh *sshedh_new_curve(int nid);
+
+struct sshepoint * sshepoint_new(void);
+int sshepoint_from(struct sshbn * x, struct sshbn * y, struct sshecurve * sshecurve, struct sshepoint **retp);
+int sshepoint_to(struct sshepoint * pt, struct sshbn **retx, struct sshbn **rety, struct sshecurve ** retcurve);
+void sshepoint_free(struct sshepoint * pt);
+
+struct sshecurve * sshecurve_new(void);
+void sshecurve_free(struct sshecurve * curve);
+struct sshecurve * sshecurve_new_curve(int nid);
+
+
+
+struct sshbn *sshbn_new(void);
+void sshbn_free(struct sshbn *bn);
+int sshbn_from(const void *d, size_t l, struct sshbn **retp);
+int sshbn_from_hex(const char *hex, struct sshbn **retp);
+size_t sshbn_bits(const struct sshbn *bn);
+const struct sshbn *sshbn_value_0(void);
+const struct sshbn *sshbn_value_1(void);
+int sshbn_cmp(const struct sshbn *a, const struct sshbn *b);
+int sshbn_sub(struct sshbn *r, const struct sshbn *a, const struct sshbn *b);
+int sshbn_is_bit_set(const struct sshbn *bn, size_t i);
+int sshbn_to(const struct sshbn *a, unsigned char *to);
+size_t sshbn_bytes(const struct sshbn *bn);
+
+/* XXX move to sshbuf.h; rename s/_wrap$// */
+int sshbuf_get_bignum2_wrap(struct sshbuf *buf, struct sshbn *bn);
+int sshbuf_get_bignum1_wrap(struct sshbuf *buf, struct sshbn *bn);
+int sshbuf_put_bignum2_wrap(struct sshbuf *buf, const struct sshbn *bn);
+int sshbuf_put_bignum1_wrap(struct sshbuf *buf, const struct sshbn *bn);
+int sshpkt_get_bignum2_wrap(struct ssh *ssh, struct sshbn *bn);
+int sshpkt_put_bignum2_wrap(struct ssh *ssh, const struct sshbn *bn);
+
+/* bridge to unwrapped OpenSSL APIs; XXX remove later */
+struct sshbn *sshbn_from_bignum(BIGNUM *bn);
+BIGNUM *sshbn_bignum(struct sshbn *bn);
+DH *sshdh_dh(struct sshdh *dh);
+
+
+#endif /* _OPENSSL_WRAP_H */
\ No newline at end of file
diff --git a/contrib/win32/win32compat/inc/defs.h b/contrib/win32/win32compat/inc/defs.h
new file mode 100644
index 000000000..0bd0a966b
--- /dev/null
+++ b/contrib/win32/win32compat/inc/defs.h
@@ -0,0 +1,97 @@
+/*
+* Author: Manoj Ampalam
+*
+* Redefined and missing POSIX macros
+*/
+#pragma once
+
+#include
+
+/* total fds that can be allotted */
+#define MAX_FDS 256 /* a 2^n number */
+
+#undef FD_ZERO
+#define FD_ZERO(set) (memset( (set), 0, sizeof(w32_fd_set)))
+#undef FD_SET
+#define FD_SET(fd,set) ( (set)->bitmap[(fd) >> 3] |= (0x80 >> ((fd) % 8)))
+#undef FD_ISSET
+#define FD_ISSET(fd, set) (( (set)->bitmap[(fd) >> 3] & (0x80 >> ((fd) % 8)))?1:0)
+#undef FD_CLR
+#define FD_CLR(fd, set) ((set)->bitmap[(fd) >> 3] &= (~(0x80 >> ((fd) % 8))))
+
+#define STDIN_FILENO 0
+#define STDOUT_FILENO 1
+#define STDERR_FILENO 2
+
+/*fcntl commands*/
+#define F_GETFL 0x1
+#define F_SETFL 0x2
+#define F_GETFD 0x4
+#define F_SETFD 0x8
+
+/*fd flags*/
+#define FD_CLOEXEC 0x1
+
+/* signal related defs*/
+/* supported signal types */
+#define W32_SIGINT 0
+#define W32_SIGSEGV 1
+
+#define W32_SIGPIPE 2
+#define W32_SIGCHLD 3
+#define W32_SIGALRM 4
+#define W32_SIGTSTP 5
+
+#define W32_SIGHUP 6
+#define W32_SIGQUIT 7
+#define W32_SIGTERM 8
+#define W32_SIGTTIN 9
+#define W32_SIGTTOU 10
+#define W32_SIGWINCH 11
+
+#define W32_SIGMAX 12
+/* these signals are not supposed to be raised on Windows*/
+#define W32_SIGSTOP 13
+#define W32_SIGABRT 14
+#define W32_SIGFPE 15
+#define W32_SIGILL 16
+#define W32_SIGKILL 17
+#define W32_SIGUSR1 18
+#define W32_SIGUSR2 19
+
+/* singprocmask "how" codes*/
+#define SIG_BLOCK 0
+#define SIG_UNBLOCK 1
+#define SIG_SETMASK 2
+
+typedef void(*sighandler_t)(int);
+typedef int sigset_t;
+#define sigemptyset(set) (memset( (set), 0, sizeof(sigset_t)))
+#define sigaddset(set, sig) ( (*(set)) |= (0x80000000 >> (sig)))
+#define sigismember(set, sig) ( (*(set) & (0x80000000 >> (sig)))?1:0 )
+#define sigdelset(set, sig) ( (*(set)) &= (~( 0x80000000 >> (sig)) ) )
+
+/* signal action codes*/
+#define W32_SIG_ERR ((sighandler_t)-1)
+#define W32_SIG_DFL ((sighandler_t)0)
+#define W32_SIG_IGN ((sighandler_t)1)
+
+typedef unsigned short _mode_t;
+typedef _mode_t mode_t;
+typedef int ssize_t;
+/* TODO - investigate if it makes sense to make pid_t a DWORD_PTR.
+ * Double check usage of pid_t as int */
+typedef int pid_t;
+
+/* wait pid options */
+#define WNOHANG 1
+
+/*ioctl macros and structs*/
+#define TIOCGWINSZ 1
+struct winsize {
+ unsigned short ws_row; /* rows, in characters */
+ unsigned short ws_col; /* columns, in character */
+ unsigned short ws_xpixel; /* horizontal size, pixels */
+ unsigned short ws_ypixel; /* vertical size, pixels */
+};
+
diff --git a/contrib/win32/win32compat/inc/dirent.h b/contrib/win32/win32compat/inc/dirent.h
new file mode 100644
index 000000000..a74081518
--- /dev/null
+++ b/contrib/win32/win32compat/inc/dirent.h
@@ -0,0 +1,25 @@
+// direntry functions in Windows platform like Ubix/Linux
+// opendir(), readdir(), closedir().
+// NT_DIR * nt_opendir(char *name) ;
+// struct nt_dirent *nt_readdir(NT_DIR *dirp);
+// int nt_closedir(NT_DIR *dirp) ;
+
+#ifndef __DIRENT_H__
+#define __DIRENT_H__
+
+#include
+#include
+#include
+
+struct dirent {
+ int d_ino; /* Inode number */
+ char d_name[256]; /* Null-terminated filename */
+};
+
+typedef struct DIR_ DIR;
+
+DIR * opendir(const char *name);
+int closedir(DIR *dirp);
+struct dirent *readdir(void *avp);
+
+#endif
\ No newline at end of file
diff --git a/contrib/win32/win32compat/inc/dlfcn.h b/contrib/win32/win32compat/inc/dlfcn.h
new file mode 100644
index 000000000..653604146
--- /dev/null
+++ b/contrib/win32/win32compat/inc/dlfcn.h
@@ -0,0 +1,11 @@
+#pragma once
+#include
+#define RTLD_NOW 0
+
+#define dlerror() GetLastError()
+
+HMODULE dlopen(const char *filename, int flags);
+
+int dlclose(HMODULE handle);
+
+FARPROC dlsym(HMODULE handle, const char *symbol);
\ No newline at end of file
diff --git a/contrib/win32/win32compat/inc/fcntl.h b/contrib/win32/win32compat/inc/fcntl.h
new file mode 100644
index 000000000..1891a13ae
--- /dev/null
+++ b/contrib/win32/win32compat/inc/fcntl.h
@@ -0,0 +1,23 @@
+
+
+#pragma once
+
+#define O_RDONLY 0x0000 // open for reading only
+#define O_WRONLY 0x0001 // open for writing only
+#define O_RDWR 0x0002 // open for reading and writing
+#define O_ACCMODE 0x0003
+#define O_APPEND 0x0008 // writes done at eof
+
+#define O_CREAT 0x0100 // create and open file
+#define O_TRUNC 0x0200 // open and truncate
+#define O_EXCL 0x0400 // open only if file doesn't already exist
+
+#define O_TEXT 0x4000 /* file mode is text (translated) */
+#define O_BINARY 0x8000 /* file mode is binary (untranslated) */
+#define O_WTEXT 0x10000 /* file mode is UTF16 (translated) */
+#define O_U16TEXT 0x20000 /* file mode is UTF16 no BOM (translated) */
+#define O_U8TEXT 0x40000 /* file mode is UTF8 no BOM (translated) */
+
+#define O_NOCTTY 0x80000 /* TODO - implement this if it makes sense on Windows*/
+
+#define F_OK 0
\ No newline at end of file
diff --git a/contrib/win32/win32compat/inc/grp.h b/contrib/win32/win32compat/inc/grp.h
new file mode 100644
index 000000000..3e4db7504
--- /dev/null
+++ b/contrib/win32/win32compat/inc/grp.h
@@ -0,0 +1,6 @@
+#ifndef COMPAT_GRP_H
+#define COMPAT_GRP_H 1
+
+char *group_from_gid(gid_t gid, int nogroup);
+
+#endif
diff --git a/contrib/win32/win32compat/inc/libgen.h b/contrib/win32/win32compat/inc/libgen.h
new file mode 100644
index 000000000..b83e65db3
--- /dev/null
+++ b/contrib/win32/win32compat/inc/libgen.h
@@ -0,0 +1,3 @@
+
+
+char *basename(char *path);
\ No newline at end of file
diff --git a/contrib/win32/win32compat/inc/netdb.h b/contrib/win32/win32compat/inc/netdb.h
new file mode 100644
index 000000000..65ea0c408
--- /dev/null
+++ b/contrib/win32/win32compat/inc/netdb.h
@@ -0,0 +1,6 @@
+#ifndef COMPAT_NETDB_H
+#define COMPAT_NETDB_H 1
+
+/* Compatibility header to avoid lots of #ifdef _WIN32's in includes.h */
+
+#endif
diff --git a/contrib/win32/win32compat/inc/netinet/in.h b/contrib/win32/win32compat/inc/netinet/in.h
new file mode 100644
index 000000000..929218138
--- /dev/null
+++ b/contrib/win32/win32compat/inc/netinet/in.h
@@ -0,0 +1,6 @@
+#ifndef COMPAT_IN_H
+#define COMPAT_IN_H 1
+
+/* Compatibility header to avoid lots of #ifdef _WIN32's in includes.h */
+
+#endif
diff --git a/contrib/win32/win32compat/inc/netinet/in_systm.h b/contrib/win32/win32compat/inc/netinet/in_systm.h
new file mode 100644
index 000000000..e8cca1056
--- /dev/null
+++ b/contrib/win32/win32compat/inc/netinet/in_systm.h
@@ -0,0 +1,6 @@
+#ifndef COMPAT_IN_SYSTM_H
+#define COMPAT_IN_SYSTM_H 1
+
+/* Compatibility header to avoid lots of #ifdef _WIN32's in includes.h */
+
+#endif
diff --git a/contrib/win32/win32compat/inc/netinet/ip.h b/contrib/win32/win32compat/inc/netinet/ip.h
new file mode 100644
index 000000000..7b39a3bf2
--- /dev/null
+++ b/contrib/win32/win32compat/inc/netinet/ip.h
@@ -0,0 +1,6 @@
+#ifndef COMPAT_IP_H
+#define COMPAT_IP_H 1
+
+/* Compatibility header to avoid lots of #ifdef _WIN32's in includes.h */
+
+#endif
diff --git a/contrib/win32/win32compat/inc/netinet/tcp.h b/contrib/win32/win32compat/inc/netinet/tcp.h
new file mode 100644
index 000000000..ac933f100
--- /dev/null
+++ b/contrib/win32/win32compat/inc/netinet/tcp.h
@@ -0,0 +1,7 @@
+#ifndef COMPAT_TCP_H
+#define COMPAT_TCP_H 1
+
+
+/* Compatibility header to avoid lots of #ifdef _WIN32's in includes.h */
+
+#endif
diff --git a/contrib/win32/win32compat/inc/poll.h b/contrib/win32/win32compat/inc/poll.h
new file mode 100644
index 000000000..d7d35b9cd
--- /dev/null
+++ b/contrib/win32/win32compat/inc/poll.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "w32posix.h"
+
+/* created to #def out decarations in open-bsd.h (that are defined in winsock2.h) */
+
+int poll(struct pollfd *, nfds_t, int);
\ No newline at end of file
diff --git a/contrib/win32/win32compat/inc/process.h b/contrib/win32/win32compat/inc/process.h
new file mode 100644
index 000000000..691a96b98
--- /dev/null
+++ b/contrib/win32/win32compat/inc/process.h
@@ -0,0 +1,6 @@
+#ifndef Process_H
+#define Process_H
+
+/* Compatibility header to avoid lots of #ifdef _WIN32's in includes.h */
+
+#endif
diff --git a/contrib/win32/win32compat/inc/pwd.h b/contrib/win32/win32compat/inc/pwd.h
new file mode 100644
index 000000000..b44ed738b
--- /dev/null
+++ b/contrib/win32/win32compat/inc/pwd.h
@@ -0,0 +1,45 @@
+/*
+* Author: Manoj Ampalam
+*
+* Compatibility header to give us pwd-like functionality on Win32
+* A lot of passwd fields are not applicable in Windows, neither are some API calls based on this structure
+* Ideally, usage of this structure needs to be replaced in core SSH code to an ssh_user interface,
+* that each platform can extend and implement.
+*/
+
+#ifndef COMPAT_PWD_H
+#define COMPAT_PWD_H 1
+
+#include "sys\param.h"
+
+struct passwd {
+ char *pw_name; /* user's login name */
+ char *pw_passwd; /* password? */
+ char *pw_gecos; /* ??? */
+ uid_t pw_uid; /* numerical user ID */
+ gid_t pw_gid; /* numerical group ID */
+ char *pw_dir; /* initial working directory */
+ char *pw_shell; /* path to shell */
+};
+
+/*start - declarations not applicable in Windows */
+uid_t getuid(void);
+gid_t getgid(void);
+uid_t geteuid(void);
+gid_t getegid(void);
+int setuid(uid_t uid);
+int setgid(gid_t gid);
+int seteuid(uid_t uid);
+int setegid(gid_t gid);
+char *user_from_uid(uid_t uid, int nouser);
+
+/*end - declarations not applicable in Windows */
+
+struct passwd *w32_getpwuid(uid_t uid);
+struct passwd *w32_getpwnam(const char *username);
+struct passwd *getpwent(void);
+
+#define getpwuid w32_getpwuid
+#define getpwnam w32_getpwnam
+
+#endif
diff --git a/contrib/win32/win32compat/inc/resolv.h b/contrib/win32/win32compat/inc/resolv.h
new file mode 100644
index 000000000..0b449b6b5
--- /dev/null
+++ b/contrib/win32/win32compat/inc/resolv.h
@@ -0,0 +1,6 @@
+#ifndef COMPAT_RESOLV_H
+#define COMPAT_RESOLV_H 1
+
+/* Compatibility header to avoid lots of #ifdef _WIN32's in includes.h */
+
+#endif
diff --git a/contrib/win32/win32compat/inc/signal.h b/contrib/win32/win32compat/inc/signal.h
new file mode 100644
index 000000000..c514a722d
--- /dev/null
+++ b/contrib/win32/win32compat/inc/signal.h
@@ -0,0 +1,43 @@
+/*
+* Author: Manoj Ampalam
+*
+* POSIX header and needed function definitions
+*/
+#ifndef COMPAT_SIGNAL_H
+#define COMPAT_SIGNAL_H 1
+
+#include "w32posix.h"
+
+#define signal(a,b) w32_signal((a), (b))
+#define mysignal(a,b) w32_signal((a), (b))
+#define raise(a) w32_raise(a)
+#define kill(a,b) w32_kill((a), (b))
+#define ftruncate(a, b) w32_ftruncate((a), (b))
+#define sigprocmask(a,b,c) w32_sigprocmask((a), (b), (c))
+
+#define SIGINT W32_SIGINT
+#define SIGSEGV W32_SIGSEGV
+#define SIGPIPE W32_SIGPIPE
+#define SIGCHLD W32_SIGCHLD
+#define SIGALRM W32_SIGALRM
+#define SIGTSTP W32_SIGTSTP
+#define SIGHUP W32_SIGHUP
+#define SIGQUIT W32_SIGQUIT
+#define SIGTERM W32_SIGTERM
+#define SIGTTIN W32_SIGTTIN
+#define SIGTTOU W32_SIGTTOU
+#define SIGWINCH W32_SIGWINCH
+#define SIGSTOP W32_SIGSTOP
+#define SIGSTOP W32_SIGSTOP
+#define SIGABRT W32_SIGABRT
+#define SIGFPE W32_SIGFPE
+#define SIGILL W32_SIGILL
+#define SIGKILL W32_SIGKILL
+#define SIGUSR1 W32_SIGUSR1
+#define SIGUSR2 W32_SIGUSR2
+
+#define SIG_DFL W32_SIG_DFL
+#define SIG_IGN W32_SIG_IGN
+#define SIG_ERR W32_SIG_ERR
+
+#endif
\ No newline at end of file
diff --git a/contrib/win32/win32compat/inc/sys/ioctl.h b/contrib/win32/win32compat/inc/sys/ioctl.h
new file mode 100644
index 000000000..1043e6118
--- /dev/null
+++ b/contrib/win32/win32compat/inc/sys/ioctl.h
@@ -0,0 +1,8 @@
+#ifndef COMPAT_IOCTL_H
+#define COMPAT_IOCTL_H 1
+
+#include "..\w32posix.h"
+
+#define ioctl w32_ioctl
+
+#endif
diff --git a/contrib/win32/win32compat/inc/sys/param.h b/contrib/win32/win32compat/inc/sys/param.h
new file mode 100644
index 000000000..071f11a9a
--- /dev/null
+++ b/contrib/win32/win32compat/inc/sys/param.h
@@ -0,0 +1,10 @@
+#ifndef COMPAT_PARAM_H
+#define COMPAT_PARAM_H 1
+
+typedef unsigned int uid_t;
+typedef unsigned int gid_t;
+typedef long long off_t;
+typedef unsigned int dev_t;
+
+
+#endif
diff --git a/contrib/win32/win32compat/inc/sys/resource.h b/contrib/win32/win32compat/inc/sys/resource.h
new file mode 100644
index 000000000..68799dea4
--- /dev/null
+++ b/contrib/win32/win32compat/inc/sys/resource.h
@@ -0,0 +1,6 @@
+#ifndef COMPAT_RESOURCE_H
+#define COMPAT_RESOURCE_H 1
+
+/* Compatibility header to avoid lots of #ifdef _WIN32's in includes.h */
+
+#endif
diff --git a/contrib/win32/win32compat/inc/sys/select.h b/contrib/win32/win32compat/inc/sys/select.h
new file mode 100644
index 000000000..03b4d67c6
--- /dev/null
+++ b/contrib/win32/win32compat/inc/sys/select.h
@@ -0,0 +1,13 @@
+/*
+* Author: Manoj Ampalam
+*
+* POSIX header and needed function definitions
+*/
+#pragma once
+
+#include "..\w32posix.h"
+
+#undef FD_SETSIZE
+#define FD_SETSIZE MAX_FDS
+
+
diff --git a/contrib/win32/win32compat/inc/sys/socket.h b/contrib/win32/win32compat/inc/sys/socket.h
new file mode 100644
index 000000000..a7924383f
--- /dev/null
+++ b/contrib/win32/win32compat/inc/sys/socket.h
@@ -0,0 +1,24 @@
+/*
+* Author: Manoj Ampalam
+*
+* POSIX header and needed function definitions
+*/
+#pragma once
+
+#include "..\w32posix.h"
+
+#define socket(a,b,c) w32_socket((a), (b), (c))
+#define accept(a,b,c) w32_accept((a), (b), (c))
+#define setsockopt(a,b,c,d,e) w32_setsockopt((a), (b), (c), (d), (e))
+#define getsockopt(a,b,c,d,e) w32_getsockopt((a), (b), (c), (d), (e))
+#define getsockname(a,b,c) w32_getsockname((a), (b), (c))
+#define getpeername(a,b,c) w32_getpeername((a), (b), (c))
+#define listen(a,b) w32_listen((a), (b))
+#define bind(a,b,c) w32_bind((a), (b), (c))
+#define connect(a,b,c) w32_connect((a), (b), (c))
+#define recv(a,b,c,d) w32_recv((a), (b), (c), (d))
+#define send(a,b,c,d) w32_send((a), (b), (c), (d))
+#define shutdown(a,b) w32_shutdown((a), (b))
+#define socketpair(a,b,c,d) w32_socketpair((a), (b), (c), (d))
+#define freeaddrinfo w32_freeaddrinfo
+#define getaddrinfo w32_getaddrinfo
diff --git a/contrib/win32/win32compat/inc/sys/stat.h b/contrib/win32/win32compat/inc/sys/stat.h
new file mode 100644
index 000000000..0b0e0a30e
--- /dev/null
+++ b/contrib/win32/win32compat/inc/sys/stat.h
@@ -0,0 +1,64 @@
+/*
+* Author: Manoj Ampalam
+*
+* private stat.h (all code relying on POSIX wrapper should include this version
+* instead of the one in Windows SDK.
+*/
+#pragma once
+#include "..\fcntl.h"
+#include "param.h"
+
+/* flags COPIED FROM STAT.H
+ */
+#define _S_IFMT 0xF000 // File type mask
+#define _S_IFDIR 0x4000 // Directory
+#define _S_IFCHR 0x2000 // Character special
+#define _S_IFIFO 0x1000 // Pipe
+#define _S_IFREG 0x8000 // Regular
+#define _S_IREAD 0x0100 // Read permission, owner
+#define _S_IWRITE 0x0080 // Write permission, owner
+#define _S_IEXEC 0x0040 // Execute/search permission, owner
+#define _S_IFLNK 0xA000 // symbolic link
+#define _S_IFSOCK 0xC000 // socket
+
+#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
+
+#define S_IFMT _S_IFMT
+#define S_IFDIR _S_IFDIR
+#define S_IFCHR _S_IFCHR
+#define S_IFREG _S_IFREG
+#define S_IREAD _S_IREAD
+#define S_IWRITE _S_IWRITE
+#define S_IEXEC _S_IEXEC
+#define S_IFLNK _S_IFLNK
+#define S_IFSOCK _S_IFSOCK
+
+ /* TODO - is this the right place for these defs ?*/
+# define S_ISUID 0x800
+# define S_ISGID 0x400
+
+#define stat w32_stat
+#define lstat w32_stat
+#define mkdir w32_mkdir
+#define chmod w32_chmod
+
+struct w32_stat {
+ dev_t st_dev; /* ID of device containing file */
+ unsigned short st_ino; /* inode number */
+ unsigned short st_mode; /* protection */
+ short st_nlink; /* number of hard links */
+ short st_uid; /* user ID of owner */
+ short st_gid; /* group ID of owner */
+ dev_t st_rdev; /* device ID (if special file) */
+ __int64 st_size; /* total size, in bytes */
+ __int64 st_atime; /* time of last access */
+ __int64 st_mtime; /* time of last modification */
+ __int64 st_ctime; /* time of last status change */
+};
+
+typedef unsigned short _mode_t;
+typedef _mode_t mode_t;
+
+void strmode(mode_t mode, char *p);
+int w32_chmod(const char *, mode_t);
+int w32_mkdir(const char *pathname, unsigned short mode);
\ No newline at end of file
diff --git a/contrib/win32/win32compat/inc/sys/statvfs.h b/contrib/win32/win32compat/inc/sys/statvfs.h
new file mode 100644
index 000000000..8f14361a9
--- /dev/null
+++ b/contrib/win32/win32compat/inc/sys/statvfs.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#define ST_RDONLY 1
+#define ST_NOSUID 2
+typedef unsigned long fsblkcnt_t;
+typedef unsigned long fsfilcnt_t;
+
+struct statvfs {
+ unsigned long f_bsize; /* File system block size. */
+ unsigned long f_frsize; /* Fundamental file system block size. */
+ fsblkcnt_t f_blocks; /* Total number of blocks on file system in */
+ /* units of f_frsize. */
+ fsblkcnt_t f_bfree; /* Total number of free blocks. */
+ fsblkcnt_t f_bavail; /* Number of free blocks available to */
+ /* non-privileged process. */
+ fsfilcnt_t f_files; /* Total number of file serial numbers. */
+ fsfilcnt_t f_ffree; /* Total number of free file serial numbers. */
+ fsfilcnt_t f_favail; /* Number of file serial numbers available to */
+ /* non-privileged process. */
+ unsigned long f_fsid; /* File system ID. */
+ unsigned long f_flag; /* BBit mask of f_flag values. */
+ unsigned long f_namemax;/* Maximum filename length. */
+};
+
+int statvfs(const char *, struct statvfs *);
+int fstatvfs(int, struct statvfs *);
\ No newline at end of file
diff --git a/contrib/win32/win32compat/inc/sys/time.h b/contrib/win32/win32compat/inc/sys/time.h
new file mode 100644
index 000000000..27b08c34b
--- /dev/null
+++ b/contrib/win32/win32compat/inc/sys/time.h
@@ -0,0 +1,9 @@
+#include
+
+#define utimbuf _utimbuf
+#define utimes w32_utimes
+
+int usleep(unsigned int);
+int gettimeofday(struct timeval *tv, void *tz);
+int nanosleep(const struct timespec *req, struct timespec *rem);
+int w32_utimes(const char *filename, struct timeval *tvp);
\ No newline at end of file
diff --git a/contrib/win32/win32compat/inc/sys/uio.h b/contrib/win32/win32compat/inc/sys/uio.h
new file mode 100644
index 000000000..dd51934c6
--- /dev/null
+++ b/contrib/win32/win32compat/inc/sys/uio.h
@@ -0,0 +1,7 @@
+#ifndef COMPAT_UIO_H
+#define COMPAT_UIO_H 1
+
+
+/* Compatibility header to avoid #ifdefs on Win32 */
+
+#endif
diff --git a/contrib/win32/win32compat/inc/sys/un.h b/contrib/win32/win32compat/inc/sys/un.h
new file mode 100644
index 000000000..fff9d7891
--- /dev/null
+++ b/contrib/win32/win32compat/inc/sys/un.h
@@ -0,0 +1,7 @@
+#ifndef COMPAT_UN_H
+#define COMPAT_UN_H 1
+
+
+/* Compatibility header to avoid lots of #ifdef _WIN32's in includes.h */
+
+#endif
diff --git a/contrib/win32/win32compat/inc/sys/wait.h b/contrib/win32/win32compat/inc/sys/wait.h
new file mode 100644
index 000000000..312486b9c
--- /dev/null
+++ b/contrib/win32/win32compat/inc/sys/wait.h
@@ -0,0 +1,19 @@
+#pragma once
+#include "..\w32posix.h"
+
+//#define _W_INT(w) (*(int*)&(w)) /* convert union wait to int */
+//#define WIFEXITED(w) (!((_W_INT(w)) & 0377))
+//#define WIFSTOPPED(w) ((_W_INT(w)) & 0100)
+//#define WIFSIGNALED(w) (!WIFEXITED(w) && !WIFSTOPPED(w))
+//#define WEXITSTATUS(w) (int)(WIFEXITED(w) ? ((_W_INT(w) >> 8) & 0377) : -1)
+//#define WTERMSIG(w) (int)(WIFSIGNALED(w) ? (_W_INT(w) & 0177) : -1)
+
+#define WIFEXITED(w) TRUE
+#define WIFSTOPPED(w) TRUE
+#define WIFSIGNALED(w) FALSE
+#define WEXITSTATUS(w) w
+#define WTERMSIG(w) -1
+#define WNOHANG 1
+#define WUNTRACED 2
+
+int waitpid(int pid, int *status, int options);
\ No newline at end of file
diff --git a/contrib/win32/win32compat/inc/syslog.h b/contrib/win32/win32compat/inc/syslog.h
new file mode 100644
index 000000000..28e67fbed
--- /dev/null
+++ b/contrib/win32/win32compat/inc/syslog.h
@@ -0,0 +1,28 @@
+#pragma once
+
+
+/* Compatibility header to give us some syslog-like functionality on Win32 */
+
+#define LOG_CRIT (2) /* critical */
+#define LOG_ERR (3) /* errors */
+#define LOG_WARNING (4) /* warnings */
+#define LOG_INFO (6) /* informational */
+#define LOG_DEBUG (7) /* debug messages */
+#define LOG_USER (1 << 3) /* user level messages */
+#define LOG_DAEMON (3 << 3) /* daemons/servers */
+#define LOG_AUTH (4 << 3) /* security messages */
+#define LOG_LOCAL0 (16 << 3) /* reserved for local use */
+#define LOG_LOCAL1 (17 << 3) /* reserved for local use */
+#define LOG_LOCAL2 (18 << 3) /* reserved for local use */
+#define LOG_LOCAL3 (19 << 3) /* reserved for local use */
+#define LOG_LOCAL4 (20 << 3) /* reserved for local use */
+#define LOG_LOCAL5 (21 << 3) /* reserved for local use */
+#define LOG_LOCAL6 (22 << 3) /* reserved for local use */
+#define LOG_LOCAL7 (23 << 3) /* reserved for local use */
+
+#define LOG_PID 0x01 /* log the pid */
+
+void openlog (char *, unsigned int, int);
+void closelog (void);
+void syslog (int, const char *, const char *);
+
diff --git a/contrib/win32/win32compat/inc/termios.h b/contrib/win32/win32compat/inc/termios.h
new file mode 100644
index 000000000..9d961dbd8
--- /dev/null
+++ b/contrib/win32/win32compat/inc/termios.h
@@ -0,0 +1,110 @@
+#ifndef COMPAT_TERMIOS_H
+#define COMPAT_TERMIOS_H 1
+
+#define B0 0x00000000
+#define B50 0x00000001
+#define B75 0x00000002
+#define B110 0x00000003
+#define B134 0x00000004
+#define B150 0x00000005
+#define B200 0x00000006
+#define B300 0x00000007
+#define B600 0x00000008
+#define B1200 0x00000009
+#define B1800 0x0000000a
+#define B2400 0x0000000b
+#define B4800 0x0000000c
+#define B9600 0x0000000d
+#define B19200 0x0000000e
+#define B38400 0x0000000f
+
+#define BRKINT 0x00000100
+#define ICRNL 0x00000200
+#define IGNBRK 0x00000400
+#define IGNCR 0x00000800
+#define IGNPAR 0x00001000
+#define INLCR 0x00002000
+#define INPCK 0x00004000
+#define ISTRIP 0x00008000
+#define IXOFF 0x00010000
+#define IXON 0x00020000
+#define PARMRK 0x00040000
+#ifndef _POSIX_SOURCE
+#define IXANY 0x00000800 /* any char will restart after stop */
+#define IMAXBEL 0x00002000 /* ring bell on input queue full */
+#endif /*_POSIX_SOURCE */
+
+#define OPOST 0x00000100
+
+#define CLOCAL 0x00000100
+#define CREAD 0x00000200
+#define CS5 0x00000000
+#define CS6 0x00000400
+#define CS7 0x00000800
+#define CS8 0x00000c00
+#define CSIZE 0x00000c00
+#define CSTOPB 0x00001000
+#define HUPCL 0x00002000
+#define PARENB 0x00004000
+#define PARODD 0x00008000
+
+#define ECHO 0x00000100
+#define ECHOE 0x00000200
+#define ECHOK 0x00000400
+#define ECHONL 0x00000800
+#define ICANON 0x00001000
+#define IEXTEN 0x00002000
+#define ISIG 0x00004000
+#define NOFLSH 0x00008000
+#define TOSTOP 0x00010000
+
+#define TCIFLUSH 1
+#define TCOFLUSH 2
+#define TCIOFLUSH 3
+#define TCOOFF 1
+#define TCOON 2
+#define TCIOFF 3
+#define TCION 4
+
+#define TCSADRAIN 1
+#define TCSAFLUSH 2
+#define TCSANOW 3
+
+/* Compatibility header to allow some termios functionality to compile without #ifdefs */
+
+#define VDISCARD 1
+#define VEOL 2
+#define VEOL2 3
+#define VEOF 4
+#define VERASE 5
+#define VINTR 6
+#define VKILL 7
+#define VLNEXT 8
+#define VMIN 9
+#define VQUIT 10
+#define VREPRINT 11
+#define VSTART 12
+#define VSTOP 13
+#define VSUSP 14
+#define VSWTC 15
+#define VTIME 16
+#define VWERASE 17
+#define NCCS 18
+
+typedef unsigned char cc_t;
+typedef unsigned int tcflag_t;
+typedef unsigned int speed_t;
+
+struct termios
+{
+ tcflag_t c_iflag;
+ tcflag_t c_oflag;
+ tcflag_t c_cflag;
+ tcflag_t c_lflag;
+ char c_line;
+ cc_t c_cc[NCCS];
+ speed_t c_ispeed;
+ speed_t c_ospeed;
+};
+
+#endif
diff --git a/contrib/win32/win32compat/inc/unistd.h b/contrib/win32/win32compat/inc/unistd.h
new file mode 100644
index 000000000..5e4ca6804
--- /dev/null
+++ b/contrib/win32/win32compat/inc/unistd.h
@@ -0,0 +1,50 @@
+/*
+* Author: Manoj Ampalam
+*
+* POSIX header and needed function definitions
+*/
+#ifndef COMPAT_UNISTD_H
+#define COMPAT_UNISTD_H 1
+
+#include "w32posix.h"
+
+#define pipe w32_pipe
+#define open w32_open
+#define read w32_read
+#define write w32_write
+#define writev w32_writev
+/* can't do this #define isatty w32_isatty
+* as there is a variable in code named isatty*/
+#define isatty(a) w32_isatty((a))
+#define close w32_close
+#define dup w32_dup
+#define dup2 w32_dup2
+
+#define sleep(sec) Sleep(1000 * sec)
+#define alarm w32_alarm
+#define lseek w32_lseek
+
+#define getdtablesize() MAX_FDS
+#define gethostname w32_gethostname
+
+#define fsync(a) w32_fsync((a))
+#define ftruncate(a, b) w32_ftruncate((a), (b))
+
+#define symlink w32_symlink
+#define chown w32_chown
+#define unlink w32_unlink
+#define rmdir w32_rmdir
+#define chdir w32_chdir
+#define getcwd w32_getcwd
+
+int daemon(int nochdir, int noclose);
+char *crypt(const char *key, const char *salt);
+int link(const char *oldpath, const char *newpath);
+int w32_symlink(const char *target, const char *linkpath);
+int w32_chown(const char *pathname, unsigned int owner, unsigned int group);
+int w32_unlink(const char *path);
+int w32_rmdir(const char *pathname);
+int w32_chdir(const char *dirname);
+char *w32_getcwd(char *buffer, int maxlen);
+int readlink(const char *path, char *link, int linklen);
+#endif
diff --git a/contrib/win32/win32compat/inc/utf.h b/contrib/win32/win32compat/inc/utf.h
new file mode 100644
index 000000000..1e959b566
--- /dev/null
+++ b/contrib/win32/win32compat/inc/utf.h
@@ -0,0 +1,12 @@
+/*
+* Author: Manoj Ampalam
+*
+* UTF-16 <--> UTF-8 definitions
+*/
+#ifndef UTF_H
+#define UTF_H 1
+
+wchar_t* utf8_to_utf16(const char *);
+char* utf16_to_utf8(const wchar_t*);
+
+#endif
\ No newline at end of file
diff --git a/contrib/win32/win32compat/inc/w32posix.h b/contrib/win32/win32compat/inc/w32posix.h
new file mode 100644
index 000000000..0236b3c7a
--- /dev/null
+++ b/contrib/win32/win32compat/inc/w32posix.h
@@ -0,0 +1,161 @@
+/*
+* Author: Manoj Ampalam
+*
+* Win32 renamed POSIX APIs
+*/
+#pragma once
+#include
+#include
+#include
+#include "defs.h"
+#include "utf.h"
+#include "sys\param.h"
+
+typedef struct w32_fd_set_ {
+ unsigned char bitmap[MAX_FDS >> 3];
+}w32_fd_set;
+
+#define fd_set w32_fd_set
+
+void w32posix_initialize();
+void w32posix_done();
+
+/*network i/o*/
+int w32_socket(int domain, int type, int protocol);
+int w32_accept(int fd, struct sockaddr* addr, int* addrlen);
+int w32_setsockopt(int fd, int level, int optname, const void* optval, int optlen);
+int w32_getsockopt(int fd, int level, int optname, void* optval, int* optlen);
+int w32_getsockname(int fd, struct sockaddr* name, int* namelen);
+int w32_getpeername(int fd, struct sockaddr* name, int* namelen);
+int w32_listen(int fd, int backlog);
+int w32_bind(int fd, const struct sockaddr *name, int namelen);
+int w32_connect(int fd, const struct sockaddr* name, int namelen);
+int w32_recv(int fd, void *buf, size_t len, int flags);
+int w32_send(int fd, const void *buf, size_t len, int flags);
+int w32_shutdown(int fd, int how);
+int w32_socketpair(int domain, int type, int protocol, int sv[2]);
+
+/*non-network (file) i/o*/
+#undef fdopen
+#define fdopen(a,b) w32_fdopen((a), (b))
+#define fstat(a,b) w32_fstat((a), (b))
+
+#define rename w32_rename
+
+struct w32_stat;
+int w32_pipe(int *pfds);
+int w32_open(const char *pathname, int flags, ...);
+int w32_read(int fd, void *dst, size_t max);
+int w32_write(int fd, const void *buf, unsigned int max);
+int w32_writev(int fd, const struct iovec *iov, int iovcnt);
+int w32_fstat(int fd, struct w32_stat *buf);
+int w32_stat(const char *path, struct w32_stat *buf);
+long w32_lseek( int fd, long offset, int origin);
+int w32_isatty(int fd);
+FILE* w32_fdopen(int fd, const char *mode);
+int w32_rename(const char *old_name, const char *new_name);
+
+/*common i/o*/
+#define fcntl(a,b,...) w32_fcntl((a), (b), __VA_ARGS__)
+#define select(a,b,c,d,e) w32_select((a), (b), (c), (d), (e))
+int w32_close(int fd);
+int w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* exceptfds,
+ const struct timeval *timeout);
+int w32_fcntl(int fd, int cmd, ... /* arg */);
+int w32_dup(int oldfd);
+int w32_dup2(int oldfd, int newfd);
+
+
+/* misc */
+unsigned int w32_alarm(unsigned int seconds);
+sighandler_t w32_signal(int signum, sighandler_t handler);
+int w32_sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
+int w32_raise(int sig);
+int w32_kill(int pid, int sig);
+int w32_gethostname(char *, size_t);
+void w32_freeaddrinfo(struct addrinfo *);
+int w32_getaddrinfo(const char *, const char *,
+ const struct addrinfo *, struct addrinfo **);
+FILE* w32_fopen_utf8(const char *, const char *);
+int w32_ftruncate(int fd, off_t length);
+char* w32_programdir();
+int w32_fsync(int fd);
+int w32_ioctl(int d, int request, ...);
+
+/* Shutdown constants */
+#define SHUT_WR SD_SEND
+#define SHUT_RD SD_RECEIVE
+#define SHUT_RDWR SD_BOTH
+
+/* Other constants */
+#define IN_LOOPBACKNET 127 /* 127.* is the loopback network */
+#define MAXHOSTNAMELEN 64
+
+
+/* Errno helpers */
+#ifndef EXX
+#define EXX WSAEMFILE
+#endif
+#ifndef EXX1
+#define EXX1 WSAENOBUFS
+#endif
+#ifndef ESOCKTNOSUPPORT
+#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
+#endif
+#ifndef ENOTUNREACH
+#define ENOTUNREACH WSAENOTUNREACH
+#endif
+#ifndef EPFNOSUPPORT
+#define EPFNOSUPPORT WSAEPFNOSUPPORT
+#endif
+
+int spawn_child(char* cmd, int in, int out, int err, DWORD flags);
+
+
+/*
+ * these routines are temporarily defined here to allow transition
+ * from older POSIX wrapper to the newer one. After complete transition
+ * these should be gone or moved to a internal header.
+ */
+HANDLE w32_fd_to_handle(int fd);
+int w32_allocate_fd_for_handle(HANDLE h, BOOL is_sock);
+int sw_add_child(HANDLE child, DWORD pid);
+
+/* temporary definitions to aid in transition */
+#define sfd_to_handle(a) w32_fd_to_handle((a))
+
+/* TODO - These defs need to revisited and positioned appropriately */
+#define environ _environ
+
+typedef unsigned int nfds_t;
+
+struct w32_pollfd {
+
+ int fd;
+ SHORT events;
+ SHORT revents;
+
+};
+
+#define pollfd w32_pollfd
+
+struct iovec
+{
+ void *iov_base;
+ size_t iov_len;
+};
+
+
+#define bzero(p,l) memset((void *)(p),0,(size_t)(l))
+
+void
+explicit_bzero(void *b, size_t len);
+
+/* string.h overrides */
+#define strcasecmp _stricmp
+#define strncasecmp _strnicmp
+
+/* stdio.h overrides */
+#define fopen w32_fopen_utf8
+#define popen _popen
+#define pclose _pclose
diff --git a/contrib/win32/win32compat/inc/zlib.h b/contrib/win32/win32compat/inc/zlib.h
new file mode 100644
index 000000000..62d77ff7a
--- /dev/null
+++ b/contrib/win32/win32compat/inc/zlib.h
@@ -0,0 +1,76 @@
+/*
+ * Temporary zlib.h header for Windows
+ * TODO - decide on a compression solution for Windows
+ */
+#pragma once
+#include
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+
+#define Z_PARTIAL_FLUSH 1
+
+#define voidpf void*
+typedef voidpf(*alloc_func)(voidpf opaque, unsigned int items, unsigned int size);
+typedef void(*free_func)(voidpf opaque, voidpf address);
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ char *next_in; /* next input byte */
+ unsigned int avail_in; /* number of bytes available at next_in */
+ unsigned long total_in; /* total number of input bytes read so far */
+
+ char *next_out; /* next output byte should be put there */
+ unsigned int avail_out; /* remaining free space at next_out */
+ unsigned long total_out; /* total number of bytes output so far */
+
+ char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: binary or text */
+ unsigned long adler; /* adler32 value of the uncompressed data */
+ unsigned long reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+int
+deflateEnd(z_streamp strm);
+
+int
+inflateEnd(z_streamp strm);
+
+int
+deflateInit(z_streamp strm, int level);
+
+int
+inflateInit(z_streamp strm);
+
+int
+deflate(z_streamp strm, int flush);
+
+int
+inflate(z_streamp strm, int flush);
+
+
+
+
+
+
+
+
+
+
+
diff --git a/contrib/win32/win32compat/libwin32compat.q b/contrib/win32/win32compat/libwin32compat.q
new file mode 100644
index 000000000..8b277f0dd
--- /dev/null
+++ b/contrib/win32/win32compat/libwin32compat.q
@@ -0,0 +1 @@
+!
diff --git a/contrib/win32/win32compat/lsa/Ssh-lsa.c b/contrib/win32/win32compat/lsa/Ssh-lsa.c
new file mode 100644
index 000000000..26a69c6f7
--- /dev/null
+++ b/contrib/win32/win32compat/lsa/Ssh-lsa.c
@@ -0,0 +1,357 @@
+/*
+ * Author: NoMachine
+ * Copyright (c) 2009, 2013 NoMachine
+ * All rights reserved
+ *
+ * Author: Manoj Ampalam
+ * Simplified code to just perform local user logon
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS intERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define WINVER 0x501
+
+#define UMDF_USING_NTSTATUS
+#include
+#define SECURITY_WIN32
+#include
+#include
+#include
+#include
+#include
+
+#define Unsigned unsigned
+#define Char char
+#define Int int
+#define Long long
+#define Not(value) ((value) == 0)
+#define PKG_NAME "SSH-LSA"
+#define PKG_NAME_SIZE sizeof(PKG_NAME)
+#define MAX_ACCOUNT_NAME_SIZE (256 * 2)
+#define VERSION "4.0.346"
+
+
+typedef VOID(WINAPI *RtlInitUnicodeStringPtr)
+(PUNICODE_STRING, PCWSTR SourceString);
+#define FAIL(CONDITION) if(CONDITION) goto fail
+
+#define NTFAIL(NTFUNC) if((ntStat = (NTFUNC))) goto fail
+
+RtlInitUnicodeStringPtr RtlInitUnicodeString = NULL;
+HMODULE NtDll = NULL;
+LSA_SECPKG_FUNCTION_TABLE LsaApi;
+
+NTSTATUS LsaAllocUnicodeString(PUNICODE_STRING *lsaStr, USHORT maxLen)
+{
+ NTSTATUS ntStat = STATUS_NO_MEMORY;
+ FAIL(lsaStr == NULL);
+ *lsaStr = (PUNICODE_STRING)LsaApi.AllocateLsaHeap(sizeof(UNICODE_STRING));
+ FAIL((*lsaStr) == NULL);
+ (*lsaStr)->Buffer = (WCHAR *)LsaApi.AllocateLsaHeap(sizeof(maxLen));
+ (*lsaStr)->Length = 0;
+ (*lsaStr)->MaximumLength = maxLen;
+ FAIL((*lsaStr)->Buffer == NULL);
+
+ ntStat = 0;
+fail:
+
+ if (ntStat) {
+ if (lsaStr && (*lsaStr)) {
+ LsaApi.FreeLsaHeap((*lsaStr)->Buffer);
+ LsaApi.FreeLsaHeap((*lsaStr));
+ }
+ }
+
+ return ntStat;
+}
+
+void LsaFreeUnicodeString(PUNICODE_STRING lsaStr)
+{
+ if (lsaStr) {
+ if (lsaStr->Buffer)
+ LsaApi.FreeLsaHeap(lsaStr->Buffer);
+ LsaApi.FreeLsaHeap(lsaStr);
+ }
+}
+
+NTSTATUS FillUnicodeString(UNICODE_STRING *lsaStr, const Char *str)
+{
+ NTSTATUS ntStat = STATUS_NO_MEMORY;
+ size_t cbSize = 0;
+ FAIL(lsaStr == NULL);
+ FAIL(lsaStr->Buffer == NULL);
+ FAIL(str == NULL);
+ cbSize = strlen(str);
+ FAIL(cbSize >= lsaStr->MaximumLength);
+ _swprintf(lsaStr->Buffer, L"%hs", str);
+ lsaStr->Length = (USHORT)(cbSize * 2);
+ lsaStr->Buffer[cbSize * 2] = 0x0000;
+ ntStat = STATUS_SUCCESS;
+
+fail:
+ return ntStat;
+}
+
+
+NTSTATUS NTAPI LsaApCallPackagePassthrough(PLSA_CLIENT_REQUEST request,
+ PVOID submitBuf,
+ PVOID clientBufBase,
+ ULONG submitBufSize,
+ PVOID *outBuf,
+ PULONG outBufSize,
+ PNTSTATUS status) {
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS NTAPI LsaApCallPackageUntrusted(PLSA_CLIENT_REQUEST request,
+ PVOID submitBuf,
+ PVOID clientBufBase,
+ ULONG submitBufSize,
+ PVOID *outBuf,
+ PULONG outBufSize,
+ PNTSTATUS status) {
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS NTAPI LsaApCallPackage(PLSA_CLIENT_REQUEST request, PVOID submitBuf,
+ PVOID clientBufBase, ULONG submitBufSize,
+ PVOID *outBuf, PULONG outBufSize,
+ PNTSTATUS status) {
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS NTAPI LsaApInitializePackage(ULONG pkgId,
+ PLSA_SECPKG_FUNCTION_TABLE func,
+ PLSA_STRING database,
+ PLSA_STRING confident,
+ PLSA_STRING *pkgName)
+{
+ memcpy(&LsaApi, func, sizeof(LsaApi));
+
+ *pkgName = (PLSA_STRING)LsaApi.AllocateLsaHeap(sizeof(LSA_STRING));
+ (*pkgName)->Buffer = (PCHAR)LsaApi.AllocateLsaHeap(PKG_NAME_SIZE);
+
+ /* fill buffer with package name */
+ memcpy((*pkgName)->Buffer, PKG_NAME, PKG_NAME_SIZE);
+ (*pkgName)->Length = PKG_NAME_SIZE - 1;
+ (*pkgName)->MaximumLength = PKG_NAME_SIZE;
+
+ return STATUS_SUCCESS;
+}
+
+int LsaCopySid(PSID *dst, PSID src)
+{
+ int exitCode = 1;
+ DWORD size = 0;
+
+ FAIL(IsValidSid(src) == FALSE);
+ size = GetLengthSid(src);
+ *dst = LsaApi.AllocateLsaHeap(size);
+ memcpy(*dst, src, size);
+ exitCode = 0;
+fail:
+ return exitCode;
+}
+
+int LsaAllocTokenInfo(PLSA_TOKEN_INFORMATION_V1 *info, HANDLE token)
+{
+
+ int exitCode = 1;
+ DWORD cbSize = 0;
+ DWORD i = 0;
+
+ PTOKEN_USER pUserToken = NULL;
+ PTOKEN_GROUPS pGroupsToken = NULL;
+ PTOKEN_OWNER pOwnerToken = NULL;
+ PTOKEN_PRIMARY_GROUP pPrimaryGroupToken = NULL;
+ PLSA_TOKEN_INFORMATION_V1 tokenInfo;
+
+ *info = (PLSA_TOKEN_INFORMATION_V1)
+ LsaApi.AllocateLsaHeap(sizeof(LSA_TOKEN_INFORMATION_V1));
+
+ FAIL(*info == NULL);
+ tokenInfo = *info;
+ GetTokenInformation(token, TokenUser, NULL, 0, &cbSize);
+ pUserToken = (PTOKEN_USER)LocalAlloc(LPTR, cbSize);
+ FAIL(GetTokenInformation(token, TokenUser,
+ pUserToken, cbSize, &cbSize) == FALSE);
+ tokenInfo->User.User.Attributes = pUserToken->User.Attributes;
+ FAIL(LsaCopySid(&tokenInfo->User.User.Sid, pUserToken->User.Sid));
+
+ GetTokenInformation(token, TokenGroups, NULL, 0, &cbSize);
+ pGroupsToken = (PTOKEN_GROUPS)LocalAlloc(LPTR, cbSize);
+ FAIL(GetTokenInformation(token, TokenGroups,
+ pGroupsToken, cbSize, &cbSize) == FALSE);
+ cbSize = pGroupsToken->GroupCount * sizeof(SID_AND_ATTRIBUTES) + sizeof(DWORD);
+ tokenInfo->Groups = (PTOKEN_GROUPS)LsaApi.AllocateLsaHeap(cbSize);
+ tokenInfo->Groups->GroupCount = pGroupsToken->GroupCount;
+
+ for (i = 0; i < pGroupsToken->GroupCount; i++)
+ {
+ FAIL(LsaCopySid(&tokenInfo->Groups->Groups[i].Sid,
+ pGroupsToken->Groups[i].Sid));
+
+ tokenInfo->Groups->Groups[i].Attributes = pGroupsToken->Groups[i].Attributes;
+ }
+
+ GetTokenInformation(token, TokenPrivileges, NULL, 0, &cbSize);
+ tokenInfo->Privileges = (PTOKEN_PRIVILEGES)LsaApi.AllocateLsaHeap(cbSize);
+ FAIL(GetTokenInformation(token, TokenPrivileges,
+ tokenInfo->Privileges, cbSize, &cbSize) == FALSE);
+ GetTokenInformation(token, TokenOwner, NULL, 0, &cbSize);
+ pOwnerToken = (PTOKEN_OWNER)LocalAlloc(LPTR, cbSize);
+ FAIL(GetTokenInformation(token, TokenOwner,
+ pOwnerToken, cbSize, &cbSize) == FALSE);
+ FAIL(LsaCopySid(&tokenInfo->Owner.Owner, pOwnerToken->Owner));
+
+ GetTokenInformation(token, TokenPrimaryGroup, NULL, 0, &cbSize);
+ pPrimaryGroupToken = (PTOKEN_PRIMARY_GROUP)LocalAlloc(LPTR, cbSize);
+ FAIL(GetTokenInformation(token, TokenPrimaryGroup,
+ pPrimaryGroupToken, cbSize, &cbSize) == FALSE);
+ FAIL(LsaCopySid(&tokenInfo->PrimaryGroup.PrimaryGroup,
+ pPrimaryGroupToken->PrimaryGroup));
+
+ tokenInfo->DefaultDacl.DefaultDacl = NULL;
+ tokenInfo->ExpirationTime.HighPart = 0x7fffffff;
+ tokenInfo->ExpirationTime.LowPart = 0xffffffff;
+ exitCode = 0;
+
+fail:
+ LsaApi.FreeLsaHeap(pUserToken);
+ LsaApi.FreeLsaHeap(pGroupsToken);
+ LsaApi.FreeLsaHeap(pOwnerToken);
+ LsaApi.FreeLsaHeap(pPrimaryGroupToken);
+
+ return exitCode;
+}
+
+
+NTSTATUS NTAPI
+LsaApLogonUser(PLSA_CLIENT_REQUEST request, SECURITY_LOGON_TYPE logonType,
+ PVOID authData, PVOID clientAuthData, ULONG authDataSize,
+ PVOID *profile, PULONG profileSize, PLUID logonId,
+ PNTSTATUS subStat,
+ PLSA_TOKEN_INFORMATION_TYPE tokenInfoType,
+ PVOID *tokenInfo,
+ PLSA_UNICODE_STRING *accountName,
+ PLSA_UNICODE_STRING *authority)
+{
+
+ NTSTATUS ntStat = STATUS_LOGON_FAILURE;
+ int exitCode = 1;
+ wchar_t *inUserName = NULL;
+ WCHAR samUserBuf[MAX_ACCOUNT_NAME_SIZE + 1];
+ SECURITY_STRING samUser;
+ UNICODE_STRING *flatName = NULL;
+ UCHAR *userAuth = NULL;
+ ULONG userAuthSize;
+ wchar_t homeDir[MAX_PATH];
+ TOKEN_SOURCE tokenSource;
+
+ HANDLE token = NULL;
+ HANDLE clientToken = NULL;
+ SECPKG_CLIENT_INFO clientInfo;
+ inUserName = (wchar_t *)authData;
+
+ NTFAIL(LsaApi.GetClientInfo(&clientInfo));
+ FAIL(Not(clientInfo.HasTcbPrivilege));
+ NTFAIL(LsaAllocUnicodeString(authority, MAX_ACCOUNT_NAME_SIZE));
+ NTFAIL(LsaAllocUnicodeString(accountName, MAX_ACCOUNT_NAME_SIZE));
+ NTFAIL(LsaAllocUnicodeString(&flatName, MAX_ACCOUNT_NAME_SIZE));
+
+ lstrcpyW(samUserBuf, inUserName);
+ samUserBuf[MAX_ACCOUNT_NAME_SIZE] = 0x00;
+ RtlInitUnicodeString((PUNICODE_STRING)&samUser, samUserBuf);
+ NTFAIL(LsaApi.GetAuthDataForUser(&samUser, SecNameFlat, NULL,
+ &userAuth, &userAuthSize, flatName));
+
+ memcpy(tokenSource.SourceName, "_sshlsa_", 8);
+ AllocateLocallyUniqueId(&tokenSource.SourceIdentifier);
+ NTFAIL(LsaApi.ConvertAuthDataToToken(userAuth, userAuthSize,
+ SecurityDelegation,
+ &tokenSource, Network,
+ *authority, &token, logonId,
+ *accountName, subStat));
+
+ NTFAIL(LsaApi.AllocateClientBuffer(request, MAX_PATH * sizeof(wchar_t), profile));
+ *profileSize = MAX_PATH;
+ NTFAIL(LsaApi.CopyToClientBuffer(request, MAX_PATH * sizeof(wchar_t),
+ *profile, homeDir));
+
+ PLSA_TOKEN_INFORMATION_V1 outTokenInfo;
+ FAIL(LsaAllocTokenInfo(&outTokenInfo, token));
+ *tokenInfoType = LsaTokenInformationV1;
+ *tokenInfo = outTokenInfo;
+
+ NTFAIL(LsaApi.DuplicateHandle(token, &clientToken));
+ ntStat = STATUS_SUCCESS;
+ exitCode = 0;
+
+fail:
+ if (exitCode)
+ {
+ ntStat = STATUS_LOGON_FAILURE;
+ CloseHandle(clientToken);
+ LsaApi.DeleteLogonSession(logonId);
+ *profileSize = 0;
+ }
+
+ CloseHandle(token);
+ LsaFreeUnicodeString(flatName);
+ return ntStat;
+}
+
+
+VOID NTAPI LsaApLogonTerminated(PLUID logonId)
+{
+}
+
+BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpRes)
+{
+ BOOL exitCode = FALSE;
+
+ switch (dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+ NtDll = GetModuleHandle("ntdll.dll");
+
+ FAIL(NtDll == NULL);
+ RtlInitUnicodeString = (RtlInitUnicodeStringPtr)
+ GetProcAddress(NtDll, "RtlInitUnicodeString");
+ FAIL(RtlInitUnicodeString == NULL);
+ break;
+ }
+
+ case DLL_PROCESS_DETACH:
+ FreeModule(NtDll);
+ }
+
+ exitCode = TRUE;
+
+fail:
+
+ if (exitCode == FALSE)
+ FreeModule(NtDll);
+
+ return exitCode;
+}
diff --git a/contrib/win32/win32compat/lsastring.c b/contrib/win32/win32compat/lsastring.c
new file mode 100644
index 000000000..7543b5454
--- /dev/null
+++ b/contrib/win32/win32compat/lsastring.c
@@ -0,0 +1,152 @@
+/*
+ * Author: NoMachine
+ *
+ * Copyright (c) 2009, 2011 NoMachine
+ * All rights reserved
+ *
+ * Support functions and system calls' replacements needed to let the
+ * software run on Win32 based operating systems.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "LsaString.h"
+
+/*
+ * Allocate UNICODE_STRING's buffer and initializes it with
+ * given string.
+ *
+ * lsaStr - UNICODE_STRING to initialize (IN/OUT)
+ * wstr - string, which will be copied to lsaStr (IN)
+ *
+ * RETURNS: 0 if OK.
+ */
+
+int InitUnicodeString(UNICODE_STRING *lsaStr, const wchar_t *wstr)
+{
+ int exitCode = 1;
+
+ int size = (wstr) ? wcslen(wstr) * 2 : 0;
+
+ lsaStr -> Length = size;
+ lsaStr -> MaximumLength = size + 2;
+ lsaStr -> Buffer = (wchar_t *) malloc(size + 2);
+
+ FAIL(lsaStr -> Buffer == NULL);
+
+ memcpy(lsaStr -> Buffer, wstr, size);
+
+ lsaStr -> Buffer[size / 2] = 0;
+
+ exitCode = 0;
+
+fail:
+
+ if (exitCode)
+ {
+ printf("ERROR. Cannot initialize UNICODE_STRING...");
+ }
+
+ return exitCode;
+}
+
+
+/*
+ * Allocate LSA_STRING's buffer and initializes it with
+ * given string.
+ *
+ * lsaStr - LSA_STRING to initialize (IN/OUT)
+ * str - string, which will be copied to lsaStr (IN)
+ *
+ * RETURNS: 0 if OK.
+ */
+
+int InitLsaString(LSA_STRING *lsaStr, const char *str)
+{
+ int exitCode = 1;
+
+ int len = (str) ? strlen(str) : 0;
+
+ lsaStr -> Length = len;
+ lsaStr -> MaximumLength = len + 1;
+ lsaStr -> Buffer = (char *) malloc(len + 1);
+
+ FAIL(lsaStr -> Buffer == NULL);
+
+ memcpy(lsaStr -> Buffer, str, len);
+
+ lsaStr -> Buffer[len] = 0;
+
+ exitCode = 0;
+
+fail:
+
+ if (exitCode)
+ {
+ printf("ERROR. Cannot initialize LSA_STRING...");
+ }
+
+ return exitCode;
+}
+
+
+/*
+ * Clear LSA_STRING's buffer.
+ *
+ * lsaStr - LSA_STRING to clear (IN/OUT)
+ */
+
+void ClearLsaString(LSA_STRING *lsaStr)
+{
+ if (lsaStr)
+ {
+ if (lsaStr -> Buffer)
+ {
+ free(lsaStr -> Buffer);
+
+ lsaStr -> Buffer = NULL;
+ }
+ lsaStr -> MaximumLength = 0;
+ lsaStr -> Length = 0;
+ }
+}
+
+/*
+ * Clear UNICODE_STRING's buffer.
+ *
+ * lsaStr - UNICODE_STRING to clear (IN/OUT)
+ */
+
+void ClearUnicodeString(UNICODE_STRING *lsaStr)
+{
+ if (lsaStr)
+ {
+ if (lsaStr -> Buffer)
+ {
+ free(lsaStr -> Buffer);
+
+ lsaStr -> Buffer = NULL;
+ }
+ lsaStr -> MaximumLength = 0;
+ lsaStr -> Length = 0;
+ }
+}
diff --git a/contrib/win32/win32compat/lsastring.h b/contrib/win32/win32compat/lsastring.h
new file mode 100644
index 000000000..5f7a7fc5a
--- /dev/null
+++ b/contrib/win32/win32compat/lsastring.h
@@ -0,0 +1,50 @@
+/*
+ * Author: NoMachine
+ *
+ * Copyright (c) 2009, 2011 NoMachine
+ * All rights reserved
+ *
+ * Support functions and system calls' replacements needed to let the
+ * software run on Win32 based operating systems.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LsaString_H
+#define LsaString_H
+
+
+#include
+#include
+#include
+
+#include "Debug.h"
+
+int InitUnicodeString(UNICODE_STRING *lsaStr, const wchar_t *wstr);
+
+void ClearUnicodeString(UNICODE_STRING *lsaStr);
+
+int InitLsaString(LSA_STRING *lsaStr, const char *str);
+
+void ClearLsaString(LSA_STRING *lsaStr);
+
+#endif
diff --git a/contrib/win32/win32compat/misc.c b/contrib/win32/win32compat/misc.c
new file mode 100644
index 000000000..722a88158
--- /dev/null
+++ b/contrib/win32/win32compat/misc.c
@@ -0,0 +1,813 @@
+/*
+* Author: Manoj Ampalam
+*
+* Copyright(c) 2016 Microsoft Corp.
+* All rights reserved
+*
+* Misc Unix POSIX routine implementations for Windows
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met :
+*
+* 1. Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and / or other materials provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT
+* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include
+#include
+#include "inc\defs.h"
+#include "sys\stat.h"
+#include "inc\sys\statvfs.h"
+#include "inc\sys\time.h"
+#include
+#include
+
+int usleep(unsigned int useconds)
+{
+ Sleep(useconds / 1000);
+ return 1;
+}
+
+int nanosleep(const struct timespec *req, struct timespec *rem) {
+ HANDLE timer;
+ LARGE_INTEGER li;
+
+ if (req->tv_sec < 0 || req->tv_nsec < 0 || req->tv_nsec > 999999999) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if ((timer = CreateWaitableTimerW(NULL, TRUE, NULL)) == NULL) {
+ errno = EFAULT;
+ return -1;
+ }
+
+ li.QuadPart = -req->tv_nsec;
+ if (!SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE)) {
+ CloseHandle(timer);
+ errno = EFAULT;
+ return -1;
+ }
+
+ /* TODO - use wait_for_any_event, since we want to wake up on interrupts*/
+ switch (WaitForSingleObject(timer, INFINITE)) {
+ case WAIT_OBJECT_0:
+ CloseHandle(timer);
+ return 0;
+ default:
+ errno = EFAULT;
+ return -1;
+ }
+}
+
+/* Difference in us between UNIX Epoch and Win32 Epoch */
+#define EPOCH_DELTA_US 11644473600000000ULL
+
+/* This routine is contributed by * Author: NoMachine
+* Copyright (c) 2009, 2010 NoMachine
+* All rights reserved
+*/
+int
+gettimeofday(struct timeval *tv, void *tz)
+{
+ union
+ {
+ FILETIME ft;
+ unsigned long long ns;
+ } timehelper;
+ unsigned long long us;
+
+ /* Fetch time since Jan 1, 1601 in 100ns increments */
+ GetSystemTimeAsFileTime(&timehelper.ft);
+
+ /* Convert to microseconds from 100 ns units */
+ us = timehelper.ns / 10;
+
+ /* Remove the epoch difference */
+ us -= EPOCH_DELTA_US;
+
+ /* Stuff result into the timeval */
+ tv->tv_sec = (long)(us / 1000000ULL);
+ tv->tv_usec = (long)(us % 1000000ULL);
+
+ return 0;
+}
+
+void
+explicit_bzero(void *b, size_t len) {
+ SecureZeroMemory(b, len);
+}
+
+int statvfs(const char *path, struct statvfs *buf) {
+ DWORD sectorsPerCluster;
+ DWORD bytesPerSector;
+ DWORD freeClusters;
+ DWORD totalClusters;
+
+ if (GetDiskFreeSpace(path, §orsPerCluster, &bytesPerSector,
+ &freeClusters, &totalClusters) == TRUE)
+ {
+ debug3("path : [%s]", path);
+ debug3("sectorsPerCluster : [%lu]", sectorsPerCluster);
+ debug3("bytesPerSector : [%lu]", bytesPerSector);
+ debug3("bytesPerCluster : [%lu]", sectorsPerCluster * bytesPerSector);
+ debug3("freeClusters : [%lu]", freeClusters);
+ debug3("totalClusters : [%lu]", totalClusters);
+
+ buf->f_bsize = sectorsPerCluster * bytesPerSector;
+ buf->f_frsize = sectorsPerCluster * bytesPerSector;
+ buf->f_blocks = totalClusters;
+ buf->f_bfree = freeClusters;
+ buf->f_bavail = freeClusters;
+ buf->f_files = -1;
+ buf->f_ffree = -1;
+ buf->f_favail = -1;
+ buf->f_fsid = 0;
+ buf->f_flag = 0;
+ buf->f_namemax = MAX_PATH - 1;
+
+ return 0;
+ }
+ else
+ {
+ debug3("ERROR: Cannot get free space for [%s]. Error code is : %d.\n",
+ path, GetLastError());
+
+ return -1;
+ }
+}
+
+int fstatvfs(int fd, struct statvfs *buf) {
+ errno = ENOTSUP;
+ return -1;
+}
+
+#include "inc\dlfcn.h"
+HMODULE dlopen(const char *filename, int flags) {
+ return LoadLibraryA(filename);
+}
+
+int dlclose(HMODULE handle) {
+ FreeLibrary(handle);
+ return 0;
+}
+
+FARPROC dlsym(HMODULE handle, const char *symbol) {
+ return GetProcAddress(handle, symbol);
+}
+
+
+/*fopen on Windows to mimic https://linux.die.net/man/3/fopen
+* only r, w, a are supported for now
+*/
+FILE*
+w32_fopen_utf8(const char *path, const char *mode) {
+ wchar_t wpath[MAX_PATH], wmode[5];
+ FILE* f;
+ char utf8_bom[] = { 0xEF,0xBB,0xBF };
+ char first3_bytes[3];
+
+ if (mode[1] != '\0') {
+ errno = ENOTSUP;
+ return NULL;
+ }
+
+ if (MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, MAX_PATH) == 0 ||
+ MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, 5) == 0) {
+ errno = EFAULT;
+ debug("WideCharToMultiByte failed for %c - ERROR:%d", path, GetLastError());
+ return NULL;
+ }
+
+ f = _wfopen(wpath, wmode);
+
+ if (f) {
+ /* BOM adjustments for file streams*/
+ if (mode[0] == 'w' && fseek(f, 0, SEEK_SET) != EBADF) {
+ /* write UTF-8 BOM - should we ?*/
+ /*if (fwrite(utf8_bom, sizeof(utf8_bom), 1, f) != 1) {
+ fclose(f);
+ return NULL;
+ }*/
+
+ }
+ else if (mode[0] == 'r' && fseek(f, 0, SEEK_SET) != EBADF) {
+ /* read out UTF-8 BOM if present*/
+ if (fread(first3_bytes, 3, 1, f) != 1 ||
+ memcmp(first3_bytes, utf8_bom, 3) != 0) {
+ fseek(f, 0, SEEK_SET);
+ }
+ }
+ }
+
+ return f;
+}
+
+
+wchar_t*
+utf8_to_utf16(const char *utf8) {
+ int needed = 0;
+ wchar_t* utf16 = NULL;
+ if ((needed = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0)) == 0 ||
+ (utf16 = malloc(needed * sizeof(wchar_t))) == NULL ||
+ MultiByteToWideChar(CP_UTF8, 0, utf8, -1, utf16, needed) == 0)
+ return NULL;
+ return utf16;
+}
+
+char*
+utf16_to_utf8(const wchar_t* utf16) {
+ int needed = 0;
+ char* utf8 = NULL;
+ if ((needed = WideCharToMultiByte(CP_UTF8, 0, utf16, -1, NULL, 0, NULL, NULL)) == 0 ||
+ (utf8 = malloc(needed)) == NULL ||
+ WideCharToMultiByte(CP_UTF8, 0, utf16, -1, utf8, needed, NULL, NULL) == 0)
+ return NULL;
+ return utf8;
+}
+
+static char* s_programdir = NULL;
+char* w32_programdir() {
+ if (s_programdir != NULL)
+ return s_programdir;
+
+ if ((s_programdir = utf16_to_utf8(_wpgmptr)) == NULL)
+ return NULL;
+
+ /* null terminate after directory path */
+ {
+ char* tail = s_programdir + strlen(s_programdir);
+ while (tail > s_programdir && *tail != '\\' && *tail != '/')
+ tail--;
+
+ if (tail > s_programdir)
+ *tail = '\0';
+ else
+ *tail = '.'; /* current directory */
+ }
+
+ return s_programdir;
+
+}
+
+int
+daemon(int nochdir, int noclose)
+{
+ FreeConsole();
+ return 0;
+}
+
+int w32_ioctl(int d, int request, ...) {
+ va_list valist;
+ va_start(valist, request);
+
+ switch (request){
+ case TIOCGWINSZ: {
+ struct winsize* wsize = va_arg(valist, struct winsize*);
+ CONSOLE_SCREEN_BUFFER_INFO c_info;
+ if (wsize == NULL || !GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &c_info)) {
+ errno = EINVAL;
+ return -1;
+ }
+ wsize->ws_col = c_info.dwSize.X - 5;
+ wsize->ws_row = c_info.dwSize.Y;
+ wsize->ws_xpixel = 640;
+ wsize->ws_ypixel = 480;
+ return 0;
+ }
+ default:
+ errno = ENOTSUP;
+ return -1;
+ }
+}
+
+HANDLE w32_fd_to_handle(int fd);
+int
+spawn_child(char* cmd, int in, int out, int err, DWORD flags) {
+ PROCESS_INFORMATION pi;
+ STARTUPINFOW si;
+ BOOL b;
+ char* abs_cmd;
+ wchar_t * cmd_utf16;
+
+ /* relative ? if so, add current module path to start */
+ if (!(cmd && cmd[0] != '\0' && (cmd[1] == ':' || cmd[0] == '\\' || cmd[0] == '.'))) {
+ char* ctr;
+ abs_cmd = malloc(strlen(w32_programdir()) + 1 + strlen(cmd) + 1);
+ if (abs_cmd == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ ctr = abs_cmd;
+ memcpy(ctr, w32_programdir(), strlen(w32_programdir()));
+ ctr += strlen(w32_programdir());
+ *ctr++ = '\\';
+ memcpy(ctr, cmd, strlen(cmd) + 1);
+ }
+ else
+ abs_cmd = cmd;
+
+ debug("spawning %s", abs_cmd);
+
+ if ((cmd_utf16 = utf8_to_utf16(abs_cmd)) == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ if(abs_cmd != cmd)
+ free(abs_cmd);
+
+ memset(&si, 0, sizeof(STARTUPINFOW));
+ si.cb = sizeof(STARTUPINFOW);
+ si.hStdInput = w32_fd_to_handle(in);
+ si.hStdOutput = w32_fd_to_handle(out);
+ si.hStdError = w32_fd_to_handle(err);
+ si.dwFlags = STARTF_USESTDHANDLES;
+
+ b = CreateProcessW(NULL, cmd_utf16, NULL, NULL, TRUE, flags, NULL, NULL, &si, &pi);
+
+ if (b) {
+ if (sw_add_child(pi.hProcess, pi.dwProcessId) == -1) {
+ TerminateProcess(pi.hProcess, 0);
+ CloseHandle(pi.hProcess);
+ pi.dwProcessId = -1;
+ }
+ CloseHandle(pi.hThread);
+ }
+ else {
+ errno = GetLastError();
+ pi.dwProcessId = -1;
+ }
+
+ free(cmd_utf16);
+ return pi.dwProcessId;
+}
+
+void
+strmode(mode_t mode, char *p)
+{
+ /* print type */
+ switch (mode & S_IFMT) {
+ case S_IFDIR: /* directory */
+ *p++ = 'd';
+ break;
+ case S_IFCHR: /* character special */
+ *p++ = 'c';
+ break;
+ //case S_IFBLK: /* block special */
+ // *p++ = 'b';
+ // break;
+ case S_IFREG: /* regular */
+ *p++ = '-';
+ break;
+ //case S_IFLNK: /* symbolic link */
+ // *p++ = 'l';
+ // break;
+#ifdef S_IFSOCK
+ case S_IFSOCK: /* socket */
+ *p++ = 's';
+ break;
+#endif
+ case _S_IFIFO: /* fifo */
+ *p++ = 'p';
+ break;
+ default: /* unknown */
+ *p++ = '?';
+ break;
+ }
+
+ // The below code is commented as the group, other is not applicable on the windows.
+ // This will be properly fixed in next releases.
+ // As of now we are keeping "*" for everything.
+ const char *permissions = "********* ";
+ strncpy(p, permissions, strlen(permissions) + 1);
+ p = p + strlen(p);
+ ///* usr */
+ //if (mode & S_IRUSR)
+ // *p++ = 'r';
+ //else
+ // *p++ = '-';
+ //if (mode & S_IWUSR)
+ // *p++ = 'w';
+ //else
+ // *p++ = '-';
+ //switch (mode & (S_IXUSR)) {
+ //case 0:
+ // *p++ = '-';
+ // break;
+ //case S_IXUSR:
+ // *p++ = 'x';
+ // break;
+ // //case S_ISUID:
+ // // *p++ = 'S';
+ // // break;
+ // //case S_IXUSR | S_ISUID:
+ // // *p++ = 's';
+ // // break;
+ //}
+ ///* group */
+ //if (mode & S_IRGRP)
+ // *p++ = 'r';
+ //else
+ // *p++ = '-';
+ //if (mode & S_IWGRP)
+ // *p++ = 'w';
+ //else
+ // *p++ = '-';
+ //switch (mode & (S_IXGRP)) {
+ //case 0:
+ // *p++ = '-';
+ // break;
+ //case S_IXGRP:
+ // *p++ = 'x';
+ // break;
+ // //case S_ISGID:
+ // // *p++ = 'S';
+ // // break;
+ // //case S_IXGRP | S_ISGID:
+ // // *p++ = 's';
+ // // break;
+ //}
+ ///* other */
+ //if (mode & S_IROTH)
+ // *p++ = 'r';
+ //else
+ // *p++ = '-';
+ //if (mode & S_IWOTH)
+ // *p++ = 'w';
+ //else
+ // *p++ = '-';
+ //switch (mode & (S_IXOTH)) {
+ //case 0:
+ // *p++ = '-';
+ // break;
+ //case S_IXOTH:
+ // *p++ = 'x';
+ // break;
+ //}
+ //*p++ = ' '; /* will be a '+' if ACL's implemented */
+ *p = '\0';
+}
+
+int
+w32_chmod(const char *pathname, mode_t mode) {
+ /* TODO - implement this */
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+int
+w32_chown(const char *pathname, unsigned int owner, unsigned int group) {
+ /* TODO - implement this */
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+char *realpath_win(const char *path, char resolved[MAX_PATH]);
+
+int
+w32_utimes(const char *filename, struct timeval *tvp) {
+ struct utimbuf ub;
+ ub.actime = tvp[0].tv_sec;
+ ub.modtime = tvp[1].tv_sec;
+ int ret;
+
+ // Skip the first '/' in the pathname
+ char resolvedPathName[MAX_PATH];
+ realpath_win(filename, resolvedPathName);
+ wchar_t *resolvedPathName_utf16 = utf8_to_utf16(resolvedPathName);
+ if (resolvedPathName_utf16 == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ ret = _wutime(resolvedPathName_utf16, &ub);
+ free(resolvedPathName_utf16);
+ return ret;
+}
+
+int
+w32_symlink(const char *target, const char *linkpath) {
+ // Not supported in windows
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+int
+link(const char *oldpath, const char *newpath) {
+ // Not supported in windows
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+int
+w32_rename(const char *old_name, const char *new_name) {
+ // Skip the first '/' in the pathname
+ char resolvedOldPathName[MAX_PATH];
+ realpath_win(old_name, resolvedOldPathName);
+
+ // Skip the first '/' in the pathname
+ char resolvedNewPathName[MAX_PATH];
+ realpath_win(new_name, resolvedNewPathName);
+
+ wchar_t *resolvedOldPathName_utf16 = utf8_to_utf16(resolvedOldPathName);
+ wchar_t *resolvedNewPathName_utf16 = utf8_to_utf16(resolvedNewPathName);
+ if (NULL == resolvedOldPathName_utf16 || NULL == resolvedNewPathName_utf16) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ int returnStatus = _wrename(resolvedOldPathName_utf16, resolvedNewPathName_utf16);
+ free(resolvedOldPathName_utf16);
+ free(resolvedNewPathName_utf16);
+
+ return returnStatus;
+}
+
+int
+w32_unlink(const char *path) {
+ // Skip the first '/' in the pathname
+ char resolvedPathName[MAX_PATH];
+ realpath_win(path, resolvedPathName);
+
+ wchar_t *resolvedPathName_utf16 = utf8_to_utf16(resolvedPathName);
+ if (NULL == resolvedPathName_utf16) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ int returnStatus = _wunlink(resolvedPathName_utf16);
+ free(resolvedPathName_utf16);
+
+ return returnStatus;
+}
+
+int
+w32_rmdir(const char *path) {
+ // Skip the first '/' in the pathname
+ char resolvedPathName[MAX_PATH];
+ realpath_win(path, resolvedPathName);
+
+ wchar_t *resolvedPathName_utf16 = utf8_to_utf16(resolvedPathName);
+ if (NULL == resolvedPathName_utf16) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ int returnStatus = _wrmdir(resolvedPathName_utf16);
+ free(resolvedPathName_utf16);
+
+ return returnStatus;
+}
+
+int
+w32_chdir(const char *dirname_utf8) {
+ wchar_t *dirname_utf16 = utf8_to_utf16(dirname_utf8);
+ if (dirname_utf16 == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ int returnStatus = _wchdir(dirname_utf16);
+ free(dirname_utf16);
+
+ return returnStatus;
+}
+
+char *
+w32_getcwd(char *buffer, int maxlen) {
+ wchar_t wdirname[MAX_PATH];
+ char* putf8 = NULL;
+
+ _wgetcwd(&wdirname[0], MAX_PATH);
+
+ if ((putf8 = utf16_to_utf8(&wdirname[0])) == NULL)
+ fatal("failed to convert input arguments");
+ strcpy(buffer, putf8);
+ free(putf8);
+
+ return buffer;
+}
+
+int
+w32_mkdir(const char *path_utf8, unsigned short mode) {
+ // Skip the first '/' in the pathname
+ char resolvedPathName[MAX_PATH];
+ realpath_win(path_utf8, resolvedPathName);
+
+ wchar_t *path_utf16 = utf8_to_utf16(resolvedPathName);
+ if (path_utf16 == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ int returnStatus = _wmkdir(path_utf16);
+ free(path_utf16);
+
+ return returnStatus;
+}
+
+void
+getrnd(u_char *s, size_t len) {
+ HCRYPTPROV hProvider;
+ if (CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT) == FALSE ||
+ CryptGenRandom(hProvider, len, s) == FALSE ||
+ CryptReleaseContext(hProvider, 0) == FALSE)
+ DebugBreak();
+}
+
+int
+w32_stat(const char *path, struct w32_stat *buf) {
+ // Skip the first '/' in the pathname
+ char resolvedPathName[MAX_PATH];
+ realpath_win(path, resolvedPathName);
+
+ return fileio_stat(resolvedPathName, (struct _stat64*)buf);
+}
+
+// if file is symbolic link, copy its link into "link" .
+int
+readlink(const char *path, char *link, int linklen)
+{
+ // Skip the first '/' in the pathname
+ char resolvedPathName[MAX_PATH];
+ realpath_win(path, resolvedPathName);
+
+ strcpy_s(link, linklen, resolvedPathName);
+ return 0;
+}
+
+/*
+* This method will expands all symbolic links and resolves references to /./,
+* /../ and extra '/' characters in the null-terminated string named by
+* path to produce a canonicalized absolute pathname.
+*/
+char *
+realpath(const char *path, char resolved[MAX_PATH])
+{
+ char tempPath[MAX_PATH];
+
+ if ((0 == strcmp(path, "./")) || (0 == strcmp(path, "."))) {
+ tempPath[0] = '/';
+ _getcwd(&tempPath[1], sizeof(tempPath) - 1);
+ slashconvert(tempPath);
+
+ strncpy(resolved, tempPath, strlen(tempPath) + 1);
+ return resolved;
+ }
+
+ if (path[0] != '/')
+ strlcpy(resolved, path, sizeof(tempPath));
+ else
+ strlcpy(resolved, path + 1, sizeof(tempPath));
+
+ backslashconvert(resolved);
+ PathCanonicalizeA(tempPath, resolved);
+ slashconvert(tempPath);
+
+ // Store terminating slash in 'X:/' on Windows.
+ if (tempPath[1] == ':' && tempPath[2] == 0) {
+ tempPath[2] = '/';
+ tempPath[3] = 0;
+ }
+
+ resolved[0] = '/'; // will be our first slash in /x:/users/test1 format
+ strncpy(resolved + 1, tempPath, sizeof(tempPath) - 1);
+ return resolved;
+}
+
+// like realpathWin32() but takes out the first slash so that windows systems can work on the actual file or directory
+char *
+realpath_win(const char *path, char resolved[MAX_PATH])
+{
+ char tempPath[MAX_PATH];
+ realpath(path, tempPath);
+
+ strncpy(resolved, &tempPath[1], sizeof(tempPath) - 1);
+ return resolved;
+}
+
+// Maximum reparse buffer info size. The max user defined reparse
+// data is 16KB, plus there's a header.
+#define MAX_REPARSE_SIZE 17000
+#define IO_REPARSE_TAG_SYMBOLIC_LINK IO_REPARSE_TAG_RESERVED_ZERO
+#define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) // winnt ntifs
+#define IO_REPARSE_TAG_HSM (0xC0000004L) // winnt ntifs
+#define IO_REPARSE_TAG_SIS (0x80000007L) // winnt ntifs
+#define REPARSE_MOUNTPOINT_HEADER_SIZE 8
+
+
+typedef struct _REPARSE_DATA_BUFFER {
+ ULONG ReparseTag;
+ USHORT ReparseDataLength;
+ USHORT Reserved;
+ union {
+ struct {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ WCHAR PathBuffer[1];
+ } SymbolicLinkReparseBuffer;
+ struct {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ WCHAR PathBuffer[1];
+ } MountPointReparseBuffer;
+ struct {
+ UCHAR DataBuffer[1];
+ } GenericReparseBuffer;
+ };
+} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
+
+BOOL
+ResolveLink(wchar_t * tLink, wchar_t *ret, DWORD * plen, DWORD Flags)
+{
+ HANDLE fileHandle;
+ BYTE reparseBuffer[MAX_REPARSE_SIZE];
+ PBYTE reparseData;
+ PREPARSE_GUID_DATA_BUFFER reparseInfo = (PREPARSE_GUID_DATA_BUFFER)reparseBuffer;
+ PREPARSE_DATA_BUFFER msReparseInfo = (PREPARSE_DATA_BUFFER)reparseBuffer;
+ DWORD returnedLength;
+
+ if (Flags & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ fileHandle = CreateFileW(tLink, 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
+
+ }
+ else {
+
+ //
+ // Open the file
+ //
+ fileHandle = CreateFileW(tLink, 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_OPEN_REPARSE_POINT, 0);
+ }
+ if (fileHandle == INVALID_HANDLE_VALUE)
+ {
+ swprintf_s(ret, *plen, L"%ls", tLink);
+ return TRUE;
+ }
+
+ if (GetFileAttributesW(tLink) & FILE_ATTRIBUTE_REPARSE_POINT) {
+
+ if (DeviceIoControl(fileHandle, FSCTL_GET_REPARSE_POINT,
+ NULL, 0, reparseInfo, sizeof(reparseBuffer),
+ &returnedLength, NULL)) {
+
+ if (IsReparseTagMicrosoft(reparseInfo->ReparseTag)) {
+
+ switch (reparseInfo->ReparseTag) {
+ case 0x80000000 | IO_REPARSE_TAG_SYMBOLIC_LINK:
+ case IO_REPARSE_TAG_MOUNT_POINT:
+ if (*plen >= msReparseInfo->MountPointReparseBuffer.SubstituteNameLength)
+ {
+ reparseData = (PBYTE)&msReparseInfo->SymbolicLinkReparseBuffer.PathBuffer;
+ WCHAR temp[1024];
+ wcsncpy_s(temp, 1024,
+ (PWCHAR)(reparseData + msReparseInfo->MountPointReparseBuffer.SubstituteNameOffset),
+ (size_t)msReparseInfo->MountPointReparseBuffer.SubstituteNameLength);
+ temp[msReparseInfo->MountPointReparseBuffer.SubstituteNameLength] = 0;
+ swprintf_s(ret, *plen, L"%ls", &temp[4]);
+ }
+ else
+ {
+ swprintf_s(ret, *plen, L"%ls", tLink);
+ return FALSE;
+ }
+
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ else {
+ swprintf_s(ret, *plen, L"%ls", tLink);
+ }
+
+ CloseHandle(fileHandle);
+ return TRUE;
+}
\ No newline at end of file
diff --git a/contrib/win32/win32compat/no-ops.c b/contrib/win32/win32compat/no-ops.c
new file mode 100644
index 000000000..6fa5b1c03
--- /dev/null
+++ b/contrib/win32/win32compat/no-ops.c
@@ -0,0 +1,129 @@
+/*
+* Author: Manoj Ampalam
+*
+* Copyright (c) 2015 Microsoft Corp.
+* All rights reserved
+*
+* Definitions of all SSH/POSIX calls that are otherwise no-ops in Windows
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* 1. Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "inc\sys\param.h"
+
+/* uuidswap.c defs */
+void temporarily_use_uid(struct passwd *pw){
+ return;
+}
+
+void
+permanently_drop_suid(uid_t uid) {
+ return;
+}
+
+void
+restore_uid(void) {
+ return;
+}
+
+void
+permanently_set_uid(struct passwd *pw) {
+ return;
+}
+
+
+/* mux.c defs */
+int muxserver_sock = -1;
+typedef struct Channel Channel;
+unsigned int muxclient_command = 0;
+void
+muxserver_listen(void){
+ return;
+}
+
+void
+mux_exit_message(Channel *c, int exitval) {
+ return;
+}
+
+void
+mux_tty_alloc_failed(Channel *c) {
+ return;
+}
+
+void
+muxclient(const char *path) {
+ return;
+}
+
+
+int
+innetgr(const char *netgroup, const char *host,
+ const char *user, const char *domain) {
+ return -1;
+}
+
+
+/* groupaccess.c*/
+int
+ga_init(const char *user, gid_t base) {
+ return -1;
+}
+
+int
+ga_match(char * const *groups, int n) {
+ return -1;
+}
+
+int
+ga_match_pattern_list(const char *group_pattern) {
+ return -1;
+}
+
+void
+ga_free(void) {
+ return;
+}
+
+int chroot(const char *path) {
+ return -1;
+}
+
+int initgroups(const char *user, gid_t group) {
+ return -1;
+}
+
+
+/* sshd.c */
+int
+setgroups(gid_t group, char* name) {
+ return 0;
+}
+
+int
+setsid(void) {
+ return 0;
+}
+
+int startup_handler(void) {
+ return 0;
+}
diff --git a/contrib/win32/win32compat/pwd.c b/contrib/win32/win32compat/pwd.c
new file mode 100644
index 000000000..b779f554b
--- /dev/null
+++ b/contrib/win32/win32compat/pwd.c
@@ -0,0 +1,298 @@
+/*
+ * Author: NoMachine
+ *
+ * Copyright (c) 2009, 2011 NoMachine
+ * All rights reserved
+ *
+ * Support functions and system calls' replacements needed to let the
+ * software run on Win32 based operating systems.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#define SECURITY_WIN32
+#include
+#include "inc\pwd.h"
+#include "inc\grp.h"
+#include "inc\utf.h"
+
+static struct passwd pw;
+static char* pw_shellpath = NULL;
+#define SHELL_HOST "\\ssh-shellhost.exe"
+
+char* w32_programdir();
+
+int
+initialize_pw() {
+ if (pw_shellpath == NULL) {
+ if ((pw_shellpath = malloc(strlen(w32_programdir()) + strlen(SHELL_HOST) + 1)) == NULL)
+ fatal("initialize_pw - out of memory");
+ else {
+ char* head = pw_shellpath;
+ memcpy(head, w32_programdir(), strlen(w32_programdir()));
+ head += strlen(w32_programdir());
+ memcpy(head, SHELL_HOST, strlen(SHELL_HOST));
+ head += strlen(SHELL_HOST);
+ *head = '\0';
+ }
+ }
+ if (pw.pw_shell != pw_shellpath) {
+ memset(&pw, 0, sizeof(pw));
+ pw.pw_shell = pw_shellpath;
+ pw.pw_passwd = "\0";
+ /* pw_uid = 0 for root on Unix and SSH code has specific restrictions for root
+ * that are not applicable in Windows */
+ pw.pw_uid = 1;
+ }
+ return 0;
+}
+
+void
+reset_pw() {
+ initialize_pw();
+ if (pw.pw_name)
+ free(pw.pw_name);
+ if (pw.pw_dir)
+ free(pw.pw_dir);
+}
+
+static struct passwd*
+get_passwd(const char *user_utf8, LPWSTR user_sid) {
+ struct passwd *ret = NULL;
+ wchar_t *user_utf16 = NULL, *uname_utf16, *udom_utf16, *tmp;
+ char *uname_utf8 = NULL, *pw_home_utf8 = NULL;
+ LPBYTE user_info = NULL;
+ LPWSTR user_sid_local = NULL;
+ wchar_t reg_path[MAX_PATH], profile_home[MAX_PATH];
+ HKEY reg_key = 0;
+ int tmp_len = MAX_PATH;
+ PDOMAIN_CONTROLLER_INFOW pdc = NULL;
+
+ errno = 0;
+
+ reset_pw();
+
+ if ((user_utf16 = utf8_to_utf16(user_utf8) ) == NULL) {
+ errno = ENOMEM;
+ goto done;
+ }
+
+ /*find domain part if any*/
+ if ((tmp = wcschr(user_utf16, L'\\')) != NULL) {
+ udom_utf16 = user_utf16;
+ uname_utf16 = tmp + 1;
+ *tmp = L'\0';
+
+ }
+ else if ((tmp = wcschr(user_utf16, L'@')) != NULL) {
+ udom_utf16 = tmp + 1;
+ uname_utf16 = user_utf16;
+ *tmp = L'\0';
+ }
+ else {
+ uname_utf16 = user_utf16;
+ udom_utf16 = NULL;
+ }
+
+ if (user_sid == NULL) {
+ if (NetUserGetInfo(udom_utf16, uname_utf16, 23, &user_info) != NERR_Success) {
+ if (DsGetDcNameW(NULL, udom_utf16, NULL, NULL, DS_DIRECTORY_SERVICE_PREFERRED, &pdc) == ERROR_SUCCESS) {
+ if (NetUserGetInfo(pdc->DomainControllerName, uname_utf16, 23, &user_info) != NERR_Success ||
+ ConvertSidToStringSidW(((LPUSER_INFO_23)user_info)->usri23_user_sid, &user_sid_local) == FALSE) {
+ errno = ENOMEM; //??
+ goto done;
+ }
+ }
+ else {
+ errno = ENOMEM; //??
+ goto done;
+ }
+ }
+ else {
+ if (ConvertSidToStringSidW(((LPUSER_INFO_23)user_info)->usri23_user_sid, &user_sid_local) == FALSE) {
+ errno = ENOMEM; //??
+ goto done;
+ }
+ }
+ user_sid = user_sid_local;
+ }
+
+ if (swprintf(reg_path, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\%ls", user_sid) == MAX_PATH ||
+ RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_WOW64_64KEY, ®_key) != 0 ||
+ RegQueryValueExW(reg_key, L"ProfileImagePath", 0, NULL, (LPBYTE)profile_home, &tmp_len) != 0)
+ GetWindowsDirectoryW(profile_home, MAX_PATH);
+
+ if ((uname_utf8 = _strdup(user_utf8)) == NULL ||
+ (pw_home_utf8 = utf16_to_utf8(profile_home)) == NULL) {
+ errno = ENOMEM;
+ goto done;
+ }
+
+ pw.pw_name = uname_utf8;
+ uname_utf8 = NULL;
+ pw.pw_dir = pw_home_utf8;
+ pw_home_utf8 = NULL;
+ ret = &pw;
+done:
+ if (user_utf16)
+ free(user_utf16);
+ if (uname_utf8)
+ free(uname_utf8);
+ if (pw_home_utf8)
+ free(pw_home_utf8);
+ if (user_info)
+ NetApiBufferFree(user_info);
+ if (user_sid_local)
+ LocalFree(user_sid_local);
+ if (reg_key)
+ RegCloseKey(reg_key);
+ if (pdc)
+ NetApiBufferFree(pdc);
+ return ret;
+}
+
+struct passwd*
+w32_getpwnam(const char *user_utf8) {
+ return get_passwd(user_utf8, NULL);
+}
+
+struct passwd*
+w32_getpwuid(uid_t uid) {
+ wchar_t* wuser = NULL;
+ char* user_utf8 = NULL;
+ ULONG needed = 0;
+ struct passwd *ret = NULL;
+ HANDLE token = 0;
+ DWORD info_len = 0;
+ TOKEN_USER* info = NULL;
+ LPWSTR user_sid = NULL;
+
+ errno = 0;
+
+ if (GetUserNameExW(NameSamCompatible, NULL, &needed) != 0 ||
+ (wuser = malloc(needed * sizeof(wchar_t))) == NULL ||
+ GetUserNameExW(NameSamCompatible, wuser, &needed) == 0 ||
+ (user_utf8 = utf16_to_utf8(wuser)) == NULL ||
+ OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) == FALSE ||
+ GetTokenInformation(token, TokenUser, NULL, 0, &info_len) == TRUE ||
+ (info = (TOKEN_USER*)malloc(info_len)) == NULL ||
+ GetTokenInformation(token, TokenUser, info, info_len, &info_len) == FALSE ||
+ ConvertSidToStringSidW(info->User.Sid, &user_sid) == FALSE){
+ errno = ENOMEM;
+ goto done;
+ }
+ ret = get_passwd(user_utf8, user_sid);
+
+done:
+ if (wuser)
+ free(wuser);
+ if (user_utf8)
+ free(user_utf8);
+ if (token)
+ CloseHandle(token);
+ if (info)
+ free(info);
+ if (user_sid)
+ LocalFree(user_sid);
+ return ret;
+}
+
+
+
+char *group_from_gid(gid_t gid, int nogroup) {
+ return "-";
+}
+
+char *user_from_uid(uid_t uid, int nouser) {
+ return "-";
+}
+
+
+/* TODO - this is moved from realpath.c in openbsdcompat. Review and finalize its position*/
+
+#include
+
+void backslashconvert(char *str)
+{
+ while (*str) {
+ if (*str == '/')
+ *str = '\\'; // convert forward slash to back slash
+ str++;
+ }
+
+}
+
+// convert back slash to forward slash
+void slashconvert(char *str)
+{
+ while (*str) {
+ if (*str == '\\')
+ *str = '/'; // convert back slash to forward slash
+ str++;
+ }
+}
+
+
+uid_t
+getuid(void) {
+ return 0;
+}
+
+gid_t
+getgid(void) {
+ return 0;
+}
+
+uid_t
+geteuid(void) {
+ return 0;
+}
+
+gid_t
+getegid(void) {
+ return 0;
+}
+
+int
+setuid(uid_t uid) {
+ return 0;
+}
+
+int
+setgid(gid_t gid) {
+ return 0;
+}
+
+int
+seteuid(uid_t uid) {
+ return 0;
+}
+
+int
+setegid(gid_t gid) {
+ return 0;
+}
diff --git a/contrib/win32/win32compat/shell-host.c b/contrib/win32/win32compat/shell-host.c
new file mode 100644
index 000000000..dfd052951
--- /dev/null
+++ b/contrib/win32/win32compat/shell-host.c
@@ -0,0 +1,1307 @@
+/*
+* Author: Manoj Ampalam
+* Primitive shell-host to support parsing of cmd.exe input and async IO redirection
+*
+* Author: Ray Heyes
+* PTY with ANSI emulation wrapper
+*
+* Copyright (c) 2015 Microsoft Corp.
+* All rights reserved
+*
+* Microsoft openssh win32 port
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* 1. Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include
+#include
+#include
+#include
+
+#define MAX_CONSOLE_COLUMNS 9999
+#define MAX_CONSOLE_ROWS 9999
+#define MAX_CMD_LEN 8191 // msdn
+#define WM_APPEXIT WM_USER+1
+#define MAX_EXPECTED_BUFFER_SIZE 1024
+
+#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
+#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x4
+#endif
+
+#ifndef ENABLE_VIRTUAL_TERMINAL_INPUT
+#define ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200
+#endif
+
+typedef BOOL (WINAPI *__t_SetCurrentConsoleFontEx)(
+ _In_ HANDLE hConsoleOutput,
+ _In_ BOOL bMaximumWindow,
+ _In_ PCONSOLE_FONT_INFOEX lpConsoleCurrentFontEx
+ );
+__t_SetCurrentConsoleFontEx __SetCurrentConsoleFontEx;
+
+typedef BOOL (WINAPI *__t_UnhookWinEvent)(
+ _In_ HWINEVENTHOOK hWinEventHook
+ );
+__t_UnhookWinEvent __UnhookWinEvent;
+
+typedef HWINEVENTHOOK (WINAPI *__t_SetWinEventHook)(
+ _In_ UINT eventMin,
+ _In_ UINT eventMax,
+ _In_ HMODULE hmodWinEventProc,
+ _In_ WINEVENTPROC lpfnWinEventProc,
+ _In_ DWORD idProcess,
+ _In_ DWORD idThread,
+ _In_ UINT dwflags
+ );
+__t_SetWinEventHook __SetWinEventHook;
+
+
+typedef struct consoleEvent {
+ DWORD event;
+ HWND hwnd;
+ LONG idObject;
+ LONG idChild;
+ void* prior;
+ void* next;
+} consoleEvent;
+
+struct key_translation
+{
+ char incoming[5];
+ int vk;
+ char outgoing[1];
+} key_translation;
+
+struct key_translation keys[] = {
+ { "\x1b", VK_ESCAPE, "\x1b" },
+ { "\r", VK_RETURN, "\r" },
+ { "\b", VK_BACK, "\b" },
+ { "\x7f", VK_BACK, "\x7f" },
+ { "\t", VK_TAB, "\t" },
+ { "\x1b[A", VK_UP, 0 },
+ { "\x1b[B", VK_DOWN, 0 },
+ { "\x1b[C", VK_RIGHT, 0 },
+ { "\x1b[D", VK_LEFT, 0 },
+ { "\x1b[1~", VK_HOME, 0 },
+ { "\x1b[2~", VK_INSERT, 0 },
+ { "\x1b[3~", VK_DELETE, 0 },
+ { "\x1b[4~", VK_END, 0 },
+ { "\x1b[5~", VK_PRIOR, 0 },
+ { "\x1b[6~", VK_NEXT, 0 },
+ { "\x1b[11~", VK_F1, 0 },
+ { "\x1b[12~", VK_F2, 0 },
+ { "\x1b[13~", VK_F3, 0 },
+ { "\x1b[14~", VK_F4, 0 },
+ { "\x1b[15~", VK_F5, 0 },
+ { "\x1b[17~", VK_F6, 0 },
+ { "\x1b[18~", VK_F7, 0 },
+ { "\x1b[19~", VK_F8, 0 },
+ { "\x1b[20~", VK_F9, 0 },
+ { "\x1b[21~", VK_F10, 0 },
+ { "\x1b[23~", VK_F11, 0 },
+ { "\x1b[24~", VK_F12, 0 }
+};
+
+consoleEvent* head = NULL;
+consoleEvent* tail = NULL;
+
+BOOL bRet = FALSE;
+BOOL bNoScrollRegion = FALSE;
+BOOL bStartup = TRUE;
+BOOL bAnsi = FALSE;
+BOOL bHookEvents = FALSE;
+
+HANDLE child_out = INVALID_HANDLE_VALUE;
+HANDLE child_in = INVALID_HANDLE_VALUE;
+HANDLE child_err = INVALID_HANDLE_VALUE;
+HANDLE pipe_in = INVALID_HANDLE_VALUE;
+HANDLE pipe_out = INVALID_HANDLE_VALUE;
+HANDLE pipe_err = INVALID_HANDLE_VALUE;
+HANDLE child = INVALID_HANDLE_VALUE;
+HANDLE hConsoleBuffer = INVALID_HANDLE_VALUE;
+
+HANDLE monitor_thread = INVALID_HANDLE_VALUE;
+HANDLE io_thread = INVALID_HANDLE_VALUE;
+HANDLE ux_thread = INVALID_HANDLE_VALUE;
+
+DWORD hostProcessId = 0;
+DWORD hostThreadId = 0;
+DWORD childProcessId = 0;
+DWORD dwStatus = 0;
+DWORD currentLine = 0;
+DWORD lastLineLength = 0;
+
+UINT cp = 0;
+
+UINT ViewPortY = 0;
+UINT lastViewPortY = 0;
+
+BOOL bFullScreen = FALSE;
+BOOL bUseAnsiEmulation = TRUE;
+
+UINT savedViewPortY = 0;
+UINT savedLastViewPortY = 0;
+
+DWORD in_cmd_len = 0;
+char in_cmd[MAX_CMD_LEN];
+
+CRITICAL_SECTION criticalSection;
+
+CONSOLE_SCREEN_BUFFER_INFOEX consoleInfo;
+CONSOLE_SCREEN_BUFFER_INFOEX nextConsoleInfo;
+STARTUPINFO inputSi;
+
+#define GOTO_CLEANUP_ON_FALSE(exp) do { \
+ ret = (exp); \
+ if (ret == FALSE) \
+ goto cleanup; \
+} while(0) \
+
+#define GOTO_CLEANUP_ON_ERR(exp) do { \
+ if ((exp) != 0) \
+ goto cleanup; \
+} while(0) \
+
+// Console keystroke handling
+void SendKeyStroke(HANDLE hInput, int keyStroke, char character)
+{
+ DWORD wr = 0;
+ INPUT_RECORD ir;
+
+ ir.EventType = KEY_EVENT;
+ ir.Event.KeyEvent.bKeyDown = TRUE;
+ ir.Event.KeyEvent.wRepeatCount = 1;
+ ir.Event.KeyEvent.wVirtualKeyCode = keyStroke;
+ ir.Event.KeyEvent.wVirtualScanCode = 0;
+ ir.Event.KeyEvent.dwControlKeyState = 0;
+ ir.Event.KeyEvent.uChar.UnicodeChar = 0;
+ if(character != 0)
+ ir.Event.KeyEvent.uChar.AsciiChar = character;
+
+ WriteConsoleInputA(hInput, &ir, 1, &wr);
+
+ ir.Event.KeyEvent.bKeyDown = FALSE;
+ WriteConsoleInputA(hInput, &ir, 1, &wr);
+}
+
+void ProcessIncomingKeys(char * ansikey) {
+ int nKey = 0;
+ int index = ARRAYSIZE(keys);
+
+ while (nKey < index) {
+ if (strcmp(ansikey, keys[nKey].incoming) == 0) {
+ SendKeyStroke(child_in, keys[nKey].vk, keys[nKey].outgoing[0]);
+ break;
+ }
+ else
+ nKey++;
+ }
+
+ if (nKey == index) {
+ SendKeyStroke(child_in, 0, ansikey[0]);
+ }
+}
+
+// VT output routines
+void SendLF(HANDLE hInput) {
+ DWORD wr = 0;
+
+ if (bUseAnsiEmulation)
+ WriteFile(hInput, "\n", 1, &wr, NULL);
+}
+
+void SendClearScreen(HANDLE hInput) {
+ DWORD wr = 0;
+
+ if (bUseAnsiEmulation)
+ WriteFile(hInput, "\033[2J", 4, &wr, NULL);
+}
+
+void SendClearScreenFromCursor(HANDLE hInput) {
+ DWORD wr = 0;
+
+ if (bUseAnsiEmulation)
+ WriteFile(hInput, "\033[1J", 4, &wr, NULL);
+}
+
+void SendHideCursor(HANDLE hInput) {
+ DWORD wr = 0;
+
+ if (bUseAnsiEmulation)
+ WriteFile(hInput, "\033[?25l", 6, &wr, NULL);
+}
+
+void SendShowCursor(HANDLE hInput) {
+ DWORD wr = 0;
+
+ if (bUseAnsiEmulation)
+ WriteFile(hInput, "\033[?25h", 6, &wr, NULL);
+}
+
+void SendCursorPositionRequest(HANDLE hInput) {
+ DWORD wr = 0;
+
+ if (bUseAnsiEmulation)
+ WriteFile(hInput, "\033[6n", 4, &wr, NULL);
+}
+
+void SendSetCursor(HANDLE hInput, int X, int Y) {
+
+ DWORD wr = 0;
+ DWORD out = 0;
+
+ char formatted_output[255];
+
+ out = _snprintf_s(formatted_output, sizeof(formatted_output), _TRUNCATE, "\033[%d;%dH", Y, X);
+ if (bUseAnsiEmulation)
+ WriteFile(hInput, formatted_output, out, &wr, NULL);
+}
+
+void SendVerticalScroll(HANDLE hInput, int lines) {
+
+ DWORD wr = 0;
+ DWORD out = 0;
+ char formatted_output[255];
+
+ LONG vn = abs(lines);
+
+ if (lines > 0) {
+
+ out = snprintf(formatted_output, sizeof(formatted_output), "\033[%dT", vn);
+
+ if (bUseAnsiEmulation)
+ WriteFile(hInput, formatted_output, out, &wr, NULL);
+ }
+ // Not supporting the [S at the moment.
+}
+
+void SendHorizontalScroll(HANDLE hInput, int cells) {
+
+ DWORD wr = 0;
+ DWORD out = 0;
+ char formatted_output[255];
+
+ out = snprintf(formatted_output, sizeof(formatted_output), "\033[%dG", cells);
+
+ if (bUseAnsiEmulation)
+ WriteFile(hInput, formatted_output, out, &wr, NULL);
+}
+
+void SendCharacter(HANDLE hInput, WORD attributes, wchar_t character) {
+
+ DWORD wr = 0;
+ DWORD out = 0;
+ DWORD current = 0;
+
+ char formatted_output[2048];
+
+ static WORD pattributes = 0;
+
+ USHORT Color = 0;
+ ULONG Status = 0;
+
+ PSTR Next;
+ size_t SizeLeft;
+
+ if (!character)
+ return;
+
+ Next = formatted_output;
+ SizeLeft = sizeof formatted_output;
+
+ //
+ // Handle the foreground intensity
+ //
+ if ((attributes & FOREGROUND_INTENSITY) != 0) {
+ Color = 1;
+ }
+ else {
+ Color = 0;
+ }
+
+ StringCbPrintfExA(Next, SizeLeft, &Next, &SizeLeft, 0, "\033[%u", Color);
+
+ //
+ // Handle the background intensity
+ //
+ if ((attributes & BACKGROUND_INTENSITY) != 0) {
+ Color = 1;
+ }
+ else {
+ Color = 39;
+ }
+
+ StringCbPrintfExA(Next, SizeLeft, &Next, &SizeLeft, 0, ";%u", Color);
+
+ //
+ // Handle the underline
+ //
+ if ((attributes & COMMON_LVB_UNDERSCORE) != 0) {
+ Color = 4;
+ }
+ else {
+ Color = 24;
+ }
+
+ StringCbPrintfExA(Next, SizeLeft, &Next, &SizeLeft, 0, ";%u", Color);
+
+ //
+ // Handle reverse video
+ //
+ if ((attributes & COMMON_LVB_REVERSE_VIDEO) != 0) {
+ Color = 7;
+ }
+ else {
+ Color = 27;
+ }
+
+ StringCbPrintfExA(Next, SizeLeft, &Next, &SizeLeft, 0, ";%u", Color);
+
+ //
+ // Add background and foreground colors to buffer.
+ //
+ Color = 30 +
+ 4 * ((attributes & FOREGROUND_BLUE) != 0) +
+ 2 * ((attributes & FOREGROUND_GREEN) != 0) +
+ 1 * ((attributes & FOREGROUND_RED) != 0);
+
+ StringCbPrintfExA(Next, SizeLeft, &Next, &SizeLeft, 0, ";%u", Color);
+
+ Color = 40 +
+ 4 * ((attributes & BACKGROUND_BLUE) != 0) +
+ 2 * ((attributes & BACKGROUND_GREEN) != 0) +
+ 1 * ((attributes & BACKGROUND_RED) != 0);
+
+ StringCbPrintfExA(Next, SizeLeft, &Next, &SizeLeft, 0, ";%u", Color);
+
+ StringCbPrintfExA(Next, SizeLeft, &Next, &SizeLeft, 0, "m", Color);
+
+ if (bUseAnsiEmulation && attributes != pattributes)
+ WriteFile(hInput, formatted_output, (Next - formatted_output), &wr, NULL);
+
+ // East asian languages have 2 bytes for each character, only use the first
+ if (!(attributes & COMMON_LVB_TRAILING_BYTE))
+ {
+ int nSize = WideCharToMultiByte(CP_UTF8,
+ 0,
+ &character,
+ 1,
+ Next,
+ 10,
+ NULL,
+ NULL);
+
+ if(nSize > 0)
+ WriteFile(hInput, Next, nSize, &wr, NULL);
+ }
+
+ pattributes = attributes;
+}
+
+void SendBuffer(HANDLE hInput, CHAR_INFO *buffer, DWORD bufferSize) {
+
+ if (bufferSize <= 0)
+ return;
+
+ for (DWORD i = 0; i < bufferSize; i++)
+ {
+ SendCharacter(hInput, buffer[i].Attributes, buffer[i].Char.UnicodeChar);
+ }
+}
+
+void CalculateAndSetCursor(HANDLE hInput, UINT aboveTopLine, UINT viewPortHeight, UINT x, UINT y) {
+
+ SendSetCursor(pipe_out, x + 1, y + 1);
+ currentLine = y;
+}
+
+void SizeWindow(HANDLE hInput) {
+
+ SMALL_RECT srWindowRect;
+ COORD coordScreen;
+ BOOL bSuccess = FALSE;
+
+ // The input window does not scroll currently to ease calculations
+ // on the paint/draw.
+ bNoScrollRegion = TRUE;
+
+ // Set the default font to Consolas
+ CONSOLE_FONT_INFOEX matchingFont;
+ matchingFont.cbSize = sizeof(matchingFont);
+ matchingFont.nFont = 0;
+ matchingFont.dwFontSize.X = 0;
+ matchingFont.dwFontSize.Y = 16;
+ matchingFont.FontFamily = FF_DONTCARE;
+ matchingFont.FontWeight = FW_NORMAL;
+ wcscpy(matchingFont.FaceName, L"Consolas");
+
+ bSuccess = __SetCurrentConsoleFontEx(child_out, FALSE, &matchingFont);
+
+ // This information is the live screen
+ ZeroMemory(&consoleInfo, sizeof(consoleInfo));
+ consoleInfo.cbSize = sizeof(consoleInfo);
+
+ bSuccess = GetConsoleScreenBufferInfoEx(child_out, &consoleInfo);
+
+ // Get the largest size we can size the console window to.
+ coordScreen = GetLargestConsoleWindowSize(child_out);
+
+ // Define the new console window size and scroll position.
+ if (inputSi.dwXCountChars == 0 || inputSi.dwYCountChars == 0) {
+ inputSi.dwXCountChars = 80;
+ inputSi.dwYCountChars = 25;
+ }
+
+ srWindowRect.Right = (SHORT)(min(inputSi.dwXCountChars, coordScreen.X) - 1);
+ srWindowRect.Bottom = (SHORT)(min(inputSi.dwYCountChars, coordScreen.Y) - 1);
+ srWindowRect.Left = srWindowRect.Top = (SHORT)0;
+
+ /// Define the new console buffer size to be the maximum possible.
+ coordScreen.X = 100;
+ coordScreen.Y = 9999;
+
+ if (SetConsoleWindowInfo(child_out, TRUE, &srWindowRect)) {
+
+ bSuccess = SetConsoleScreenBufferSize(child_out, coordScreen);
+ }
+ else {
+ if (SetConsoleScreenBufferSize(child_out, coordScreen)) {
+
+ bSuccess = SetConsoleWindowInfo(child_out, TRUE, &srWindowRect);
+ }
+
+ }
+
+ bSuccess = GetConsoleScreenBufferInfoEx(child_out, &consoleInfo);
+}
+
+// End of VT output routines
+
+DWORD WINAPI MonitorChild(_In_ LPVOID lpParameter) {
+ WaitForSingleObject(child, INFINITE);
+ PostThreadMessage(hostThreadId, WM_APPEXIT, 0, 0);
+ return 0;
+}
+
+DWORD ProcessEvent(void *p) {
+
+ char f[255];
+ wchar_t chUpdate;
+
+ WORD wAttributes;
+ WORD wX;
+ WORD wY;
+
+ DWORD dwProcessId;
+ DWORD wr = 0;
+ DWORD dwMode;
+
+ DWORD event;
+ HWND hwnd;
+ LONG idObject;
+ LONG idChild;
+
+ if (!p)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ consoleEvent* current = (consoleEvent *)p;
+
+ if(current) {
+ event = current->event;
+ hwnd = current->hwnd;
+ idObject = current->idObject;
+ idChild = current->idChild;
+ }
+ else {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ if (event < EVENT_CONSOLE_CARET || event > EVENT_CONSOLE_LAYOUT)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ if (child_out == INVALID_HANDLE_VALUE || child_out == NULL)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ GetWindowThreadProcessId(hwnd, &dwProcessId);
+
+ if (childProcessId != dwProcessId)
+ {
+ return ERROR_SUCCESS;
+ }
+
+ ZeroMemory(&consoleInfo, sizeof(consoleInfo));
+ consoleInfo.cbSize = sizeof(consoleInfo);
+
+ GetConsoleScreenBufferInfoEx(child_out, &consoleInfo);
+
+ UINT viewPortHeight = consoleInfo.srWindow.Bottom - consoleInfo.srWindow.Top + 1;
+ UINT viewPortWidth = consoleInfo.srWindow.Right - consoleInfo.srWindow.Left + 1;
+
+ switch (event) {
+ case EVENT_CONSOLE_CARET:
+ {
+ COORD co;
+
+ if (idObject == CONSOLE_CARET_SELECTION) {
+ co.X = HIWORD(idChild);
+ co.Y = LOWORD(idChild);
+ }
+ else {
+ co.X = HIWORD(idChild);
+ co.Y = LOWORD(idChild);
+ }
+
+ break;
+ }
+ case EVENT_CONSOLE_UPDATE_REGION:
+ {
+ SMALL_RECT readRect;
+
+ readRect.Top = HIWORD(idObject);
+ readRect.Left = LOWORD(idObject);
+ readRect.Bottom = HIWORD(idChild);
+ readRect.Right = LOWORD(idChild);
+
+ // Detect a "cls" (Windows).
+ if (!bStartup &&
+ (readRect.Top == consoleInfo.srWindow.Top || readRect.Top == nextConsoleInfo.srWindow.Top))
+ {
+ BOOL isClearCommand = FALSE;
+ isClearCommand = (consoleInfo.dwSize.X == readRect.Right + 1) && (consoleInfo.dwSize.Y == readRect.Bottom + 1);
+
+ // If cls then inform app to clear its buffers and return.
+ if (isClearCommand)
+ {
+ SendClearScreen(pipe_out);
+ ViewPortY = 0;
+ lastViewPortY = 0;
+
+ return ERROR_SUCCESS;
+ }
+ }
+
+ // Figure out the buffer size
+ COORD coordBufSize;
+ coordBufSize.Y = readRect.Bottom - readRect.Top + 1;
+ coordBufSize.X = readRect.Right - readRect.Left + 1;
+
+ // Security check: the maximum screen buffer size is 9999 columns x 9999 lines so check
+ // the computed buffer size for overflow. since the X and Y in the COORD structure
+ // are shorts they could be negative.
+ if (coordBufSize.X < 0 || coordBufSize.X > MAX_CONSOLE_COLUMNS ||
+ coordBufSize.Y < 0 || coordBufSize.Y > MAX_CONSOLE_ROWS)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ // Compute buffer size
+ DWORD bufferSize = coordBufSize.X * coordBufSize.Y;
+
+ if (bufferSize > MAX_EXPECTED_BUFFER_SIZE) {
+
+ if (!bStartup) {
+ SendClearScreen(pipe_out);
+ ViewPortY = 0;
+ lastViewPortY = 0;
+ }
+
+ return ERROR_SUCCESS;
+ }
+
+ // Create the screen scrape buffer
+ CHAR_INFO *pBuffer = (PCHAR_INFO)malloc(sizeof(CHAR_INFO) * bufferSize);
+
+ if (!pBuffer)
+ {
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ // The top left destination cell of the temporary buffer is row 0, col 0.
+ COORD coordBufCoord;
+ coordBufCoord.X = 0;
+ coordBufCoord.Y = 0;
+
+ // Copy the block from the screen buffer to the temp. buffer.
+ if (!ReadConsoleOutput(child_out, pBuffer, coordBufSize, coordBufCoord, &readRect))
+ {
+ DWORD dwError = GetLastError();
+
+ free(pBuffer);
+ return dwError;
+ }
+
+ if (readRect.Top > currentLine)
+ for(SHORT n = currentLine; n < readRect.Top; n++)
+ SendLF(pipe_out);
+
+ // Set cursor location based on the reported location from the message.
+ CalculateAndSetCursor(pipe_out, ViewPortY, viewPortHeight, readRect.Left,
+ readRect.Top);
+
+ // Send the entire block.
+ SendBuffer(pipe_out, pBuffer, bufferSize);
+
+ lastViewPortY = ViewPortY;
+ lastLineLength = readRect.Left;
+
+ free(pBuffer);
+
+ break;
+ }
+ case EVENT_CONSOLE_UPDATE_SIMPLE:
+ {
+ chUpdate = LOWORD(idChild);
+ wAttributes = HIWORD(idChild);
+ wX = LOWORD(idObject);
+ wY = HIWORD(idObject);
+
+ // Set cursor location based on the reported location from the message.
+ CalculateAndSetCursor(pipe_out, ViewPortY, viewPortHeight, wX, wY);
+
+ // Send the one character. Note that a CR doesn't end up here.
+ SendCharacter(pipe_out, wAttributes, chUpdate);
+
+ break;
+ }
+ case EVENT_CONSOLE_UPDATE_SCROLL:
+ {
+ DWORD out = 0;
+ LONG vd = idChild;
+ LONG hd = idObject;
+
+ LONG vn = abs(vd);
+
+ if (vd > 0) {
+ if(ViewPortY > 0)
+ ViewPortY -= vn;
+ }
+ else {
+ ViewPortY += vn;
+ }
+
+ break;
+ }
+ case EVENT_CONSOLE_LAYOUT:
+ {
+ if (consoleInfo.dwMaximumWindowSize.X == consoleInfo.dwSize.X &&
+ consoleInfo.dwMaximumWindowSize.Y == consoleInfo.dwSize.Y &&
+ (consoleInfo.dwCursorPosition.X == 0 && consoleInfo.dwCursorPosition.Y == 0))
+ {
+ // Screen has switched to fullscreen mode
+ SendClearScreen(pipe_out);
+
+ savedViewPortY = ViewPortY;
+ savedLastViewPortY = lastViewPortY;
+
+ ViewPortY = 0;
+ lastViewPortY = 0;;
+
+ bFullScreen = TRUE;
+ }
+ else
+ {
+ // Leave full screen mode if applicable
+ if (bFullScreen) {
+ SendClearScreen(pipe_out);
+
+ ViewPortY = savedViewPortY;
+ lastViewPortY = savedLastViewPortY;
+ bFullScreen = FALSE;
+ }
+ }
+
+ break;
+ }
+ }
+
+ ZeroMemory(&consoleInfo, sizeof(consoleInfo));
+ consoleInfo.cbSize = sizeof(consoleInfo);
+
+ GetConsoleScreenBufferInfoEx(child_out, &consoleInfo);
+
+ return ERROR_SUCCESS;
+}
+
+DWORD WINAPI ProcessEventQueue(LPVOID p) {
+
+ static SHORT lastX = 0;
+ static SHORT lastY = 0;
+
+ while (1) {
+
+ while (head) {
+
+ EnterCriticalSection(&criticalSection);
+
+ consoleEvent* current = head;
+
+ if (current) {
+ if (current->next)
+ {
+ head = current->next;
+ head->prior = NULL;
+ }
+ else
+ {
+ head = NULL;
+ tail = NULL;
+ }
+ }
+
+ LeaveCriticalSection(&criticalSection);
+
+ if (current)
+ {
+ ProcessEvent(current);
+ free(current);
+ }
+ }
+
+ if (child_in != INVALID_HANDLE_VALUE && child_in != NULL &&
+ child_out != INVALID_HANDLE_VALUE && child_out != NULL)
+ {
+ DWORD dwInputMode;
+ DWORD dwOutputMode;
+
+ if (GetConsoleMode(child_in, &dwInputMode) && GetConsoleMode(child_out, &dwOutputMode)) {
+ if (((dwOutputMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) == ENABLE_VIRTUAL_TERMINAL_PROCESSING) &&
+ ((dwInputMode & ENABLE_VIRTUAL_TERMINAL_INPUT) == ENABLE_VIRTUAL_TERMINAL_INPUT))
+ {
+ bAnsi = TRUE;
+ }
+ else {
+ bAnsi = FALSE;
+ }
+ }
+
+ ZeroMemory(&consoleInfo, sizeof(consoleInfo));
+ consoleInfo.cbSize = sizeof(consoleInfo);
+
+ // This information is the live buffer that's currently in use.
+ GetConsoleScreenBufferInfoEx(child_out, &consoleInfo);
+
+ // Set the cursor to the last known good location according to the live buffer.
+ if (lastX != consoleInfo.dwCursorPosition.X ||
+ lastY != consoleInfo.dwCursorPosition.Y) {
+
+ SendSetCursor(pipe_out, consoleInfo.dwCursorPosition.X + 1,
+ consoleInfo.dwCursorPosition.Y + 1);
+ }
+
+ lastX = consoleInfo.dwCursorPosition.X;
+ lastY = consoleInfo.dwCursorPosition.Y;
+ }
+
+ Sleep(100);
+ }
+
+ return 0;
+}
+
+void QueueEvent(
+ DWORD event,
+ HWND hwnd,
+ LONG idObject,
+ LONG idChild) {
+
+ consoleEvent* current = NULL;
+
+ EnterCriticalSection(&criticalSection);
+
+ current = malloc(sizeof(consoleEvent));
+
+ if (current) {
+ if (!head) {
+ current->event = event;
+ current->hwnd = hwnd;
+ current->idChild = idChild;
+ current->idObject = idObject;
+
+ // No links head == tail
+ current->next = NULL;
+ current->prior = NULL;
+
+ head = current;
+ tail = current;
+ }
+ else {
+ current->event = event;
+ current->hwnd = hwnd;
+ current->idChild = idChild;
+ current->idObject = idObject;
+
+ // Current tail points to new tail
+ tail->next = current;
+
+ // New tail points to old tail
+ current->prior = tail;
+ current->next = NULL;
+
+ // Update the tail pointer to the new
+ // last event
+ tail = current;
+ }
+ }
+
+ LeaveCriticalSection(&criticalSection);
+
+ return;
+}
+
+DWORD WINAPI ProcessPipes(LPVOID p) {
+
+ BOOL ret;
+ DWORD dwStatus;
+
+ /* process data from pipe_in and route appropriately */
+ while (1) {
+ char buf[128];
+ ZeroMemory(buf, 128);
+
+ DWORD rd = 0, wr = 0, i = -1;
+
+ GOTO_CLEANUP_ON_FALSE(ReadFile(pipe_in, buf, 128, &rd, NULL));
+
+ bStartup = FALSE;
+
+ while (++i < rd) {
+
+ INPUT_RECORD ir;
+
+ if (buf[i] == 3) {/*Ctrl+C - Raise Ctrl+C*/
+ GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
+ continue;
+ }
+
+ if (bAnsi) {
+ ir.EventType = KEY_EVENT;
+ ir.Event.KeyEvent.bKeyDown = TRUE;
+ ir.Event.KeyEvent.wRepeatCount = 1;
+ ir.Event.KeyEvent.wVirtualKeyCode = 0;
+ ir.Event.KeyEvent.wVirtualScanCode = 0;
+ ir.Event.KeyEvent.uChar.AsciiChar = buf[i];
+ ir.Event.KeyEvent.dwControlKeyState = 0;
+ WriteConsoleInputA(child_in, &ir, 1, &wr);
+
+ ir.Event.KeyEvent.bKeyDown = FALSE;
+ WriteConsoleInputA(child_in, &ir, 1, &wr);
+ }
+ else {
+ ProcessIncomingKeys(buf);
+ break;
+ }
+ }
+ }
+
+cleanup:
+ dwStatus = GetLastError();
+
+ return 0;
+}
+
+void CALLBACK ConsoleEventProc(HWINEVENTHOOK hWinEventHook,
+ DWORD event,
+ HWND hwnd,
+ LONG idObject,
+ LONG idChild,
+ DWORD dwEventThread,
+ DWORD dwmsEventTime)
+{
+ QueueEvent(event, hwnd, idObject, idChild);
+}
+
+DWORD ProcessMessages(void* p)
+{
+ BOOL ret;
+ DWORD dwMode;
+ DWORD dwStatus;
+ SECURITY_ATTRIBUTES sa;
+ MSG msg;
+
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa.lpSecurityDescriptor = NULL;
+ sa.bInheritHandle = TRUE;
+
+ while (child_in == (HANDLE)-1)
+ {
+ child_in = CreateFile(TEXT("CONIN$"), GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_WRITE | FILE_SHARE_READ,
+ &sa, OPEN_EXISTING, 0, NULL);
+ }
+
+ if (child_in == (HANDLE)-1)
+ goto cleanup;
+
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa.lpSecurityDescriptor = NULL;
+ sa.bInheritHandle = TRUE;
+
+ while (child_out == (HANDLE)-1)
+ {
+ child_out = CreateFile(TEXT("CONOUT$"), GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_WRITE | FILE_SHARE_READ,
+ &sa, OPEN_EXISTING, 0, NULL);
+ }
+
+ if (child_out == (HANDLE)-1)
+ goto cleanup;
+
+ child_err = child_out;
+
+ SizeWindow(child_out);
+
+ // Get the current buffer information after all the adjustments.
+ GetConsoleScreenBufferInfoEx(child_out, &consoleInfo);
+
+ // Loop for the console output events
+ while (GetMessage(&msg, NULL, 0, 0))
+ {
+ if (msg.message == WM_APPEXIT)
+ {
+ break;
+ }
+ else
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+
+cleanup:
+ dwStatus = GetLastError();
+
+ if (child_in != INVALID_HANDLE_VALUE)
+ CloseHandle(child_in);
+ if (child_out != INVALID_HANDLE_VALUE)
+ CloseHandle(child_out);
+ return 0;
+}
+
+int start_with_pty(int ac, wchar_t **av) {
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ wchar_t cmd[MAX_CMD_LEN];
+ SECURITY_ATTRIBUTES sa;
+ BOOL ret;
+ DWORD dwThreadId;
+ DWORD dwMode;
+ DWORD dwStatus;
+ HANDLE hEventHook = NULL;
+ HMODULE hm_kernel32 = NULL, hm_user32 = NULL;
+
+ if ((hm_kernel32 = LoadLibraryW(L"kernel32.dll")) == NULL ||
+ (hm_user32 = LoadLibraryW(L"user32.dll")) == NULL ||
+ (__SetCurrentConsoleFontEx = (__t_SetCurrentConsoleFontEx)GetProcAddress(hm_kernel32, "SetCurrentConsoleFontEx")) == NULL ||
+ (__UnhookWinEvent = (__t_UnhookWinEvent)GetProcAddress(hm_user32, "UnhookWinEvent")) == NULL ||
+ (__SetWinEventHook = (__t_SetWinEventHook)GetProcAddress(hm_user32, "SetWinEventHook")) == NULL) {
+ printf("cannot support a pseudo terminal. \n");
+ return -1;
+ }
+
+ pipe_in = GetStdHandle(STD_INPUT_HANDLE);
+ pipe_out = GetStdHandle(STD_OUTPUT_HANDLE);
+ pipe_err = GetStdHandle(STD_ERROR_HANDLE);
+
+ /* copy pipe handles passed through std io*/
+ if ((pipe_in == INVALID_HANDLE_VALUE)
+ || (pipe_out == INVALID_HANDLE_VALUE)
+ || (pipe_err == INVALID_HANDLE_VALUE))
+ return -1;
+
+ cp = GetConsoleCP();
+
+ /* Windows PTY sends cursor positions in absolute coordinates starting from <0,0>
+ * We send a clear screen upfront to simplify client */
+ SendClearScreen(pipe_out);
+
+ ZeroMemory(&inputSi, sizeof(STARTUPINFO));
+ GetStartupInfo(&inputSi);
+
+ memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
+ sa.bInheritHandle = TRUE;
+
+ /* WM_APPEXIT */
+ hostThreadId = GetCurrentThreadId();
+ hostProcessId = GetCurrentProcessId();
+
+ InitializeCriticalSection(&criticalSection);
+
+ hEventHook = __SetWinEventHook(EVENT_CONSOLE_CARET, EVENT_CONSOLE_LAYOUT, NULL,
+ ConsoleEventProc, 0, 0, WINEVENT_OUTOFCONTEXT);
+
+ memset(&si, 0, sizeof(STARTUPINFO));
+ memset(&pi, 0, sizeof(PROCESS_INFORMATION));
+
+ // Copy our parent buffer sizes
+ si.cb = sizeof(STARTUPINFO);
+ si.dwFlags = 0;
+
+ /* disable inheritance on pipe_in*/
+ GOTO_CLEANUP_ON_FALSE(SetHandleInformation(pipe_in, HANDLE_FLAG_INHERIT, 0));
+
+ /*TODO - pick this up from system32*/
+ cmd[0] = L'\0';
+ if (ac)
+ GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_PATH, L"cmd.exe"));
+
+ ac--;
+ av++;
+ if (ac)
+ GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_PATH, L" /c"));
+ while (ac) {
+ GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_PATH, L" "));
+ GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_PATH, *av));
+ ac--;
+ av++;
+ }
+
+ SetConsoleCtrlHandler(NULL, FALSE);
+ GOTO_CLEANUP_ON_FALSE(CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NEW_CONSOLE,
+ NULL, NULL, &si, &pi));
+ childProcessId = pi.dwProcessId;
+
+ FreeConsole();
+ Sleep(20);
+ while (!AttachConsole(pi.dwProcessId))
+ {
+ DWORD exit_code;
+ if (GetExitCodeProcess(pi.hProcess, &exit_code) && exit_code != STILL_ACTIVE)
+ break;
+ Sleep(100);
+ }
+
+ /* monitor child exist */
+ child = pi.hProcess;
+ monitor_thread = CreateThread(NULL, 0, MonitorChild, NULL, 0, NULL);
+ if (monitor_thread == INVALID_HANDLE_VALUE)
+ goto cleanup;
+
+ /* disable Ctrl+C hander in this process*/
+ SetConsoleCtrlHandler(NULL, TRUE);
+
+ io_thread = CreateThread(NULL, 0, ProcessPipes, NULL, 0, NULL);
+ if (io_thread == INVALID_HANDLE_VALUE)
+ goto cleanup;
+
+ ux_thread = CreateThread(NULL, 0, ProcessEventQueue, NULL, 0, NULL);
+ if (ux_thread == INVALID_HANDLE_VALUE)
+ goto cleanup;
+
+ ProcessMessages(NULL);
+
+cleanup:
+ dwStatus = GetLastError();
+
+ DeleteCriticalSection(&criticalSection);
+
+ if (child != INVALID_HANDLE_VALUE)
+ TerminateProcess(child, 0);
+ if (monitor_thread != INVALID_HANDLE_VALUE)
+ WaitForSingleObject(monitor_thread, INFINITE);
+ if (ux_thread != INVALID_HANDLE_VALUE)
+ TerminateThread(ux_thread, S_OK);
+ if (hEventHook)
+ __UnhookWinEvent(hEventHook);
+
+ FreeConsole();
+
+ return 0;
+}
+
+HANDLE child_pipe_read;
+HANDLE child_pipe_write;
+DWORD WINAPI MonitorChild_nopty(
+ _In_ LPVOID lpParameter
+ ) {
+ WaitForSingleObject(child, INFINITE);
+ CloseHandle(pipe_in);
+ //printf("XXXX CHILD PROCESS DEAD XXXXX");
+ return 0;
+}
+
+int start_withno_pty(int ac, wchar_t **av) {
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ wchar_t cmd[MAX_CMD_LEN];
+ SECURITY_ATTRIBUTES sa;
+ BOOL ret;
+
+ pipe_in = GetStdHandle(STD_INPUT_HANDLE);
+ pipe_out = GetStdHandle(STD_OUTPUT_HANDLE);
+ pipe_err = GetStdHandle(STD_ERROR_HANDLE);
+
+ /* copy pipe handles passed through std io*/
+ if ((pipe_in == INVALID_HANDLE_VALUE)
+ || (pipe_out == INVALID_HANDLE_VALUE)
+ || (pipe_err == INVALID_HANDLE_VALUE))
+ return -1;
+
+ memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
+ sa.bInheritHandle = TRUE;
+ if (!CreatePipe(&child_pipe_read, &child_pipe_write, &sa, 128))
+ return -1;
+
+ memset(&si, 0, sizeof(STARTUPINFO));
+ memset(&pi, 0, sizeof(PROCESS_INFORMATION));
+
+ si.cb = sizeof(STARTUPINFO);
+ si.dwFlags = STARTF_USESTDHANDLES;
+ si.hStdInput = child_pipe_read;
+ si.hStdOutput = pipe_out;
+ si.hStdError = pipe_err;
+
+ /* disable inheritance on child_pipe_write and pipe_in*/
+ GOTO_CLEANUP_ON_FALSE(SetHandleInformation(pipe_in, HANDLE_FLAG_INHERIT, 0));
+ GOTO_CLEANUP_ON_FALSE(SetHandleInformation(child_pipe_write, HANDLE_FLAG_INHERIT, 0));
+
+ /*TODO - pick this up from system32*/
+ cmd[0] = L'\0';
+ GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_PATH, L"cmd.exe"));
+ ac -= 2;
+ av += 2;
+ if (ac)
+ GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_PATH, L" /c"));
+ while (ac) {
+ GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_PATH, L" "));
+ GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_PATH, *av));
+ ac--;
+ av++;
+ }
+
+ GOTO_CLEANUP_ON_FALSE(CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi));
+
+ /* close unwanted handles*/
+ CloseHandle(child_pipe_read);
+ child_pipe_read = INVALID_HANDLE_VALUE;
+
+ child = pi.hProcess;
+ /* monitor child exist */
+ monitor_thread = CreateThread(NULL, 0, MonitorChild_nopty, NULL, 0, NULL);
+ if (monitor_thread == INVALID_HANDLE_VALUE)
+ goto cleanup;
+
+ /* disable Ctrl+C hander in this process*/
+ SetConsoleCtrlHandler(NULL, TRUE);
+
+ /* process data from pipe_in and route appropriately */
+ while (1) {
+ char buf[128];
+ DWORD rd = 0, wr = 0, i = 0;
+ GOTO_CLEANUP_ON_FALSE(ReadFile(pipe_in, buf, 128, &rd, NULL));
+
+ while (i < rd) {
+
+ /* skip arrow keys */
+ if ((rd - i >= 3) && (buf[i] == '\033') && (buf[i + 1] == '[')
+ && (buf[i + 2] >= 'A') && (buf[i + 2] <= 'D')) {
+ i += 3;
+ continue;
+ }
+
+ /* skip tab */
+ if (buf[i] == '\t') {
+ i++;
+ continue;
+ }
+
+ // Ctrl +C
+ if (buf[i] == '\003') {
+ GOTO_CLEANUP_ON_FALSE(GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0));
+ in_cmd_len = 0;
+ i++;
+ continue;
+ }
+
+ // for backspace, we need to send space and another backspace for visual erase
+ if (buf[i] == '\b') {
+ if (in_cmd_len > 0) {
+ GOTO_CLEANUP_ON_FALSE(WriteFile(pipe_out, "\b \b", 3, &wr, NULL));
+ in_cmd_len--;
+ }
+ i++;
+ continue;
+ }
+
+ //for CR and LF
+ if ((buf[i] == '\r') || (buf[i] == '\n')) {
+
+ /* TODO - do a much accurate mapping */
+ GOTO_CLEANUP_ON_FALSE(WriteFile(pipe_out, buf + i, 1, &wr, NULL));
+ if ((buf[i] == '\r') && ((i == rd - 1) || (buf[i + 1] != '\n'))) {
+ buf[i] = '\n';
+ GOTO_CLEANUP_ON_FALSE(WriteFile(pipe_out, buf + i, 1, &wr, NULL));
+ }
+ in_cmd[in_cmd_len] = buf[i];
+ in_cmd_len++;
+ GOTO_CLEANUP_ON_FALSE(WriteFile(child_pipe_write, in_cmd, in_cmd_len, &wr, NULL));
+ in_cmd_len = 0;
+ i++;
+ continue;
+ }
+
+
+ GOTO_CLEANUP_ON_FALSE(WriteFile(pipe_out, buf + i, 1, &wr, NULL));
+ in_cmd[in_cmd_len] = buf[i];
+ in_cmd_len++;
+ if (in_cmd_len == MAX_CMD_LEN - 1) {
+ GOTO_CLEANUP_ON_FALSE(WriteFile(child_pipe_write, in_cmd, in_cmd_len, &wr, NULL));
+ in_cmd_len = 0;
+ }
+
+ i++;
+ }
+ }
+
+cleanup:
+
+ if (child != INVALID_HANDLE_VALUE)
+ TerminateProcess(child, 0);
+ if (monitor_thread != INVALID_HANDLE_VALUE)
+ WaitForSingleObject(monitor_thread, INFINITE);
+ return 0;
+}
+
+int wmain(int ac, wchar_t **av) {
+
+
+ /* create job to hold all child processes */
+ {
+ /* TODO - this does not work as expected*/
+ HANDLE job = CreateJobObject(NULL, NULL);
+ JOBOBJECT_EXTENDED_LIMIT_INFORMATION job_info;
+ memset(&job_info, 0, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
+ job_info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
+ if (!SetInformationJobObject(job, JobObjectExtendedLimitInformation, &job_info, sizeof(job_info)))
+ return -1;
+ CloseHandle(job);
+ }
+
+ if ((ac == 1) || wcscmp(av[1], L"-nopty"))
+ return start_with_pty(ac, av);
+ else
+ return start_withno_pty(ac, av);
+}
\ No newline at end of file
diff --git a/contrib/win32/win32compat/signal.c b/contrib/win32/win32compat/signal.c
new file mode 100644
index 000000000..8a74da9a3
--- /dev/null
+++ b/contrib/win32/win32compat/signal.c
@@ -0,0 +1,310 @@
+/*
+* Author: Manoj Ampalam
+*
+* Copyright (c) 2015 Microsoft Corp.
+* All rights reserved
+*
+* Microsoft openssh win32 port
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* 1. Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "w32fd.h"
+#include
+#include
+#include "signal_internal.h"
+
+/* pending signals to be processed */
+sigset_t pending_signals;
+
+/* signal handler table*/
+sighandler_t sig_handlers[W32_SIGMAX];
+
+static VOID CALLBACK
+sigint_APCProc(
+ _In_ ULONG_PTR dwParam
+ ) {
+ debug3("SIGINT APCProc()");
+ sigaddset(&pending_signals, W32_SIGINT);
+}
+
+static VOID CALLBACK
+sigterm_APCProc(
+ _In_ ULONG_PTR dwParam
+ ) {
+ debug3("SIGTERM APCProc()");
+ sigaddset(&pending_signals, W32_SIGTERM);
+}
+
+static VOID CALLBACK
+sigtstp_APCProc(
+ _In_ ULONG_PTR dwParam
+ ) {
+ debug3("SIGTSTP APCProc()");
+ sigaddset(&pending_signals, W32_SIGTSTP);
+}
+
+BOOL WINAPI
+native_sig_handler(DWORD dwCtrlType)
+{
+ debug("Native Ctrl+C handler, CtrlType %d", dwCtrlType);
+ switch (dwCtrlType) {
+ case CTRL_C_EVENT:
+ QueueUserAPC(sigint_APCProc, main_thread, (ULONG_PTR)NULL);
+ return TRUE;
+ case CTRL_BREAK_EVENT:
+ QueueUserAPC(sigtstp_APCProc, main_thread, (ULONG_PTR)NULL);
+ return TRUE;
+ case CTRL_CLOSE_EVENT:
+ case CTRL_LOGOFF_EVENT:
+ case CTRL_SHUTDOWN_EVENT:
+ QueueUserAPC(sigterm_APCProc, main_thread, (ULONG_PTR)NULL);
+ /* wait for main thread to terminate */
+ WaitForSingleObject(main_thread, INFINITE);
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+static VOID CALLBACK
+sigwinch_APCProc(
+ _In_ ULONG_PTR dwParam
+ ) {
+ debug3("SIGTERM APCProc()");
+ sigaddset(&pending_signals, W32_SIGWINCH);
+}
+
+
+void
+queue_terminal_window_change_event() {
+ QueueUserAPC(sigwinch_APCProc, main_thread, (ULONG_PTR)NULL);
+}
+
+void
+sw_init_signal_handler_table() {
+ int i;
+
+ SetConsoleCtrlHandler(native_sig_handler, TRUE);
+ sigemptyset(&pending_signals);
+ /* this automatically sets all to SIG_DFL (0)*/
+ memset(sig_handlers, 0, sizeof(sig_handlers));
+}
+
+extern struct _children children;
+
+sighandler_t
+sw_signal(int signum, sighandler_t handler) {
+ sighandler_t prev;
+
+ debug2("signal() sig:%d, handler:%p", signum, handler);
+ if (signum >= W32_SIGMAX) {
+ errno = EINVAL;
+ return W32_SIG_ERR;
+ }
+
+ prev = sig_handlers[signum];
+ sig_handlers[signum] = handler;
+ return prev;
+}
+
+int
+sw_sigprocmask(int how, const sigset_t *set, sigset_t *oldset) {
+ /* this is only used by sshd to block SIGCHLD while doing waitpid() */
+ /* our implementation of waidpid() is never interrupted, so no need to implement this for now*/
+ debug3("sigprocmask() how:%d");
+ return 0;
+}
+
+
+
+int
+sw_raise(int sig) {
+ debug("raise sig:%d", sig);
+ if (sig == W32_SIGSEGV)
+ return raise(SIGSEGV); /* raise native exception handler*/
+
+ if (sig >= W32_SIGMAX) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* execute user specified disposition */
+ if (sig_handlers[sig] > W32_SIG_IGN) {
+ sig_handlers[sig](sig);
+ return 0;
+ }
+
+ /* if set to ignore, nothing to do */
+ if (sig_handlers[sig] == W32_SIG_IGN)
+ return 0;
+
+ /* execute any default handlers */
+ switch (sig) {
+ case W32_SIGCHLD:
+ sw_cleanup_child_zombies();
+ break;
+ default: /* exit process */
+ exit(0);
+ }
+
+ return 0;
+}
+
+/* processes pending signals, return -1 and errno=EINTR if any are processed*/
+static int
+sw_process_pending_signals() {
+ sigset_t pending_tmp = pending_signals;
+ BOOL sig_int = FALSE; /* has any signal actually interrupted */
+
+ debug3("process_signals()");
+ int i, exp[] = { W32_SIGCHLD , W32_SIGINT , W32_SIGALRM, W32_SIGTERM, W32_SIGTSTP, W32_SIGWINCH };
+
+ /* check for expected signals*/
+ for (i = 0; i < (sizeof(exp) / sizeof(exp[0])); i++)
+ sigdelset(&pending_tmp, exp[i]);
+ if (pending_tmp) {
+ /* unexpected signals queued up */
+ debug("process_signals() - ERROR unexpected signals in queue: %d", pending_tmp);
+ errno = ENOTSUP;
+ DebugBreak();
+ return -1;
+ }
+
+ /* take pending_signals local to prevent recursion in wait_for_any* loop */
+ pending_tmp = pending_signals;
+ pending_signals = 0;
+ for (i = 0; i < (sizeof(exp) / sizeof(exp[0])); i++) {
+ if (sigismember(&pending_tmp, exp[i])) {
+ if (sig_handlers[exp[i]] != W32_SIG_IGN) {
+ sw_raise(exp[i]);
+ /* dont error EINTR for SIG_ALRM, */
+ /* sftp client is not expecting it */
+ if (exp[i] != W32_SIGALRM)
+ sig_int = TRUE;
+ }
+
+ sigdelset(&pending_tmp, exp[i]);
+ }
+ }
+
+
+ /* by now all pending signals should have been taken care of*/
+ if (pending_tmp)
+ DebugBreak();
+
+ if (sig_int) {
+ debug("process_queued_signals: WARNING - A signal has interrupted and was processed");
+ errno = EINTR;
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Main wait routine used by all blocking calls.
+ * It wakes up on
+ * - any signals (errno = EINTR )
+ * - any of the supplied events set
+ * - any APCs caused by IO completions
+ * - time out
+ * - Returns 0 on IO completion and timeout, -1 on rest
+ * if milli_seconds is 0, this function returns 0, its called with 0
+ * to execute any scheduled APCs
+*/
+int
+wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
+{
+ HANDLE all_events[MAXIMUM_WAIT_OBJECTS];
+ DWORD num_all_events;
+ DWORD live_children = children.num_children - children.num_zombies;
+
+ num_all_events = num_events + live_children;
+
+ if (num_all_events > MAXIMUM_WAIT_OBJECTS) {
+ debug("wait() - ERROR max events reached");
+ errno = ENOTSUP;
+ return -1;
+ }
+
+ memcpy(all_events, children.handles, live_children * sizeof(HANDLE));
+ memcpy(all_events + live_children, events, num_events * sizeof(HANDLE));
+
+ debug3("wait() on %d events and %d children", num_events, live_children);
+ /* TODO - implement signal catching and handling */
+ if (num_all_events) {
+ DWORD ret = WaitForMultipleObjectsEx(num_all_events, all_events, FALSE,
+ milli_seconds, TRUE);
+ if ((ret >= WAIT_OBJECT_0) && (ret <= WAIT_OBJECT_0 + num_all_events - 1)) {
+ //woken up by event signalled
+ /* is this due to a child process going down*/
+ if (children.num_children && ((ret - WAIT_OBJECT_0) < children.num_children)) {
+ sigaddset(&pending_signals, W32_SIGCHLD);
+ sw_child_to_zombie(ret - WAIT_OBJECT_0);
+ }
+ }
+ else if (ret == WAIT_IO_COMPLETION) {
+ /* APC processed due to IO or signal*/
+ }
+ else if (ret == WAIT_TIMEOUT) {
+ /* timed out */
+ return 0;
+ }
+ /* some other error*/
+ else {
+ errno = EOTHER;
+ debug("ERROR: unxpected wait end: %d", ret);
+ return -1;
+ }
+ }
+ else {
+ DWORD ret = SleepEx(milli_seconds, TRUE);
+ if (ret == WAIT_IO_COMPLETION) {
+ /* APC processed due to IO or signal*/
+ }
+ else if (ret == 0) {
+ /* timed out */
+ return 0;
+ }
+ else { //some other error
+ errno = EOTHER;
+ debug("ERROR: unxpected SleepEx error: %d", ret);
+ return -1;
+ }
+ }
+
+ if (pending_signals) {
+ return sw_process_pending_signals();
+ }
+ return 0;
+}
+
+
+int
+sw_initialize() {
+ memset(&children, 0, sizeof(children));
+ sw_init_signal_handler_table();
+ if (sw_init_timer() != 0)
+ return -1;
+ return 0;
+}
diff --git a/contrib/win32/win32compat/signal_internal.h b/contrib/win32/win32compat/signal_internal.h
new file mode 100644
index 000000000..826ca9574
--- /dev/null
+++ b/contrib/win32/win32compat/signal_internal.h
@@ -0,0 +1,34 @@
+#include
+#include "inc\defs.h"
+
+
+int sw_initialize();
+sighandler_t sw_signal(int signum, sighandler_t handler);
+int sw_sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
+int sw_raise(int sig);
+int sw_kill(int pid, int sig);
+
+/* child processes */
+#define MAX_CHILDREN 50
+struct _children {
+ HANDLE handles[MAX_CHILDREN];
+ DWORD process_id[MAX_CHILDREN];
+ /* total children */
+ DWORD num_children;
+ /* #zombies */
+ /* (num_chileren - zombies) are live children */
+ DWORD num_zombies;
+};
+
+int sw_add_child(HANDLE child, DWORD pid);
+int sw_remove_child_at_index(DWORD index);
+int sw_child_to_zombie(DWORD index);
+void sw_cleanup_child_zombies();
+
+struct _timer_info {
+ HANDLE timer;
+ ULONGLONG ticks_at_start; /* 0 if timer is not live */
+ __int64 run_time_sec; /* time in seconds, timer is set to go off from ticks_at_start */
+};
+int sw_init_timer();
+unsigned int sw_alarm(unsigned int seconds);
\ No newline at end of file
diff --git a/contrib/win32/win32compat/signal_sigalrm.c b/contrib/win32/win32compat/signal_sigalrm.c
new file mode 100644
index 000000000..e068c48b4
--- /dev/null
+++ b/contrib/win32/win32compat/signal_sigalrm.c
@@ -0,0 +1,89 @@
+/*
+* Author: Manoj Ampalam
+*
+* Copyright(c) 2015 Microsoft Corp.
+* All rights reserved
+*
+* Helper routines to support SIGALRM
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met :
+*
+* 1. Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and / or other materials provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT
+* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "signal_internal.h"
+
+struct _timer_info timer_info;
+extern sigset_t pending_signals;
+
+static VOID CALLBACK
+sigalrm_APC(
+ _In_opt_ LPVOID lpArgToCompletionRoutine,
+ _In_ DWORD dwTimerLowValue,
+ _In_ DWORD dwTimerHighValue
+ ) {
+ sigaddset(&pending_signals, W32_SIGALRM);
+}
+
+unsigned int
+sw_alarm(unsigned int sec) {
+ LARGE_INTEGER due;
+ ULONGLONG sec_passed;
+ int ret = 0;
+
+ debug3("alarm() %d secs", sec);
+ errno = 0;
+ /* cancel any live timer if seconds is 0*/
+ if (sec == 0) {
+ CancelWaitableTimer(timer_info.timer);
+ timer_info.ticks_at_start = 0;
+ timer_info.run_time_sec = 0;
+ return 0;
+ }
+
+ due.QuadPart = -10000000LL; //1 sec in 100 nanosec intervals
+ due.QuadPart *= sec;
+ /* this call resets the timer if it is already active */
+ if (!SetWaitableTimer(timer_info.timer, &due, 0, sigalrm_APC, NULL, FALSE)) {
+ debug("alram() - ERROR SetWaitableTimer() %d", GetLastError());
+ return 0;;
+ }
+
+ /* if timer was already ative, return when it was due */
+ if (timer_info.ticks_at_start) {
+ sec_passed = (GetTickCount64() - timer_info.ticks_at_start) / 1000;
+ if (sec_passed < timer_info.run_time_sec)
+ ret = timer_info.run_time_sec - sec_passed;
+ }
+ timer_info.ticks_at_start = GetTickCount64();
+ timer_info.run_time_sec = sec;
+ return ret;
+}
+
+int
+sw_init_timer() {
+ memset(&timer_info, 0, sizeof(timer_info));
+ timer_info.timer = CreateWaitableTimer(NULL, TRUE, NULL);
+ if (timer_info.timer == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ return 0;
+}
\ No newline at end of file
diff --git a/contrib/win32/win32compat/signal_sigchld.c b/contrib/win32/win32compat/signal_sigchld.c
new file mode 100644
index 000000000..afd0242f4
--- /dev/null
+++ b/contrib/win32/win32compat/signal_sigchld.c
@@ -0,0 +1,233 @@
+/*
+* Author: Manoj Ampalam
+*
+* Copyright(c) 2015 Microsoft Corp.
+* All rights reserved
+*
+* Helper routines to support SIGCLD and related routines implementation
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met :
+*
+* 1. Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and / or other materials provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT
+* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "signal_internal.h"
+
+struct _children children;
+
+int
+sw_add_child(HANDLE child, DWORD pid) {
+ DWORD first_zombie_index;
+
+ debug("Register child %p pid %d, %d zombies of %d", child, pid,
+ children.num_zombies, children.num_children);
+ if (children.num_children == MAX_CHILDREN) {
+ errno = ENOMEM;
+ return -1;
+ }
+ if (children.num_zombies) {
+ first_zombie_index = children.num_children - children.num_zombies;
+ children.handles[children.num_children] = children.handles[first_zombie_index];
+ children.process_id[children.num_children] = children.process_id[first_zombie_index];
+
+ children.handles[first_zombie_index] = child;
+ children.process_id[first_zombie_index] = pid;
+ }
+ else {
+ children.handles[children.num_children] = child;
+ children.process_id[children.num_children] = pid;
+ }
+
+
+ children.num_children++;
+ return 0;
+}
+
+int
+sw_remove_child_at_index(DWORD index) {
+ DWORD last_non_zombie;
+
+ debug("Unregister child at index %d, %d zombies of %d", index,
+ children.num_zombies, children.num_children);
+
+ if ((index >= children.num_children)
+ || (children.num_children == 0)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ CloseHandle(children.handles[index]);
+ if (children.num_zombies == 0) {
+ children.handles[index] = children.handles[children.num_children - 1];
+ children.process_id[index] = children.process_id[children.num_children - 1];
+ }
+ else {
+ /* if its a zombie */
+ if (index >= (children.num_children - children.num_zombies)) {
+ children.handles[index] = children.handles[children.num_children - 1];
+ children.process_id[index] = children.process_id[children.num_children - 1];
+ children.num_zombies--;
+ }
+ else {
+ last_non_zombie = children.num_children - children.num_zombies - 1;
+ children.handles[index] = children.handles[last_non_zombie];
+ children.process_id[index] = children.process_id[last_non_zombie];
+
+ children.handles[last_non_zombie] = children.handles[children.num_children - 1];
+ children.process_id[last_non_zombie] = children.process_id[children.num_children - 1];
+ }
+ }
+
+ children.num_children--;
+ return 0;
+}
+
+int
+sw_child_to_zombie(DWORD index) {
+ DWORD last_non_zombie, last_child, zombie_pid;
+ HANDLE zombie_handle;
+
+ debug("zombie'ing child at index %d, %d zombies of %d", index,
+ children.num_zombies, children.num_children);
+
+ if (index >= children.num_children) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ zombie_pid = children.process_id[index];
+ zombie_handle = children.handles[index];
+ last_non_zombie = children.num_children - children.num_zombies - 1;
+ last_child = children.num_children - 1;
+
+ children.handles[index] = children.handles[last_non_zombie];
+ children.process_id[index] = children.process_id[last_non_zombie];
+
+ children.handles[last_non_zombie] = children.handles[index];
+ children.process_id[last_non_zombie] = children.process_id[index];
+
+ children.num_zombies++;
+ return 0;
+}
+
+int
+sw_kill(int pid, int sig) {
+ int child_index, i;
+ if (pid == GetCurrentProcessId())
+ return sw_raise(sig);
+
+ /* for child processes - only SIGTERM supported*/
+ child_index = -1;
+ for (i = 0; i < children.num_children; i++)
+ if (children.process_id[i] == pid) {
+ child_index = i;
+ break;
+ }
+
+ if (child_index != -1)
+ TerminateProcess(children.handles[child_index], 0);
+ return 0;
+}
+
+
+int waitpid(int pid, int *status, int options) {
+ DWORD index, ret, ret_id, exit_code, timeout = 0;
+ HANDLE process = NULL;
+
+ debug3("waitpid - pid:%d, options:%d", pid, options);
+ if (options & (~WNOHANG)) {
+ errno = ENOTSUP;
+ DebugBreak();
+ return -1;
+ }
+
+ if ((pid < -1) || (pid == 0)) {
+ errno = ENOTSUP;
+ DebugBreak();
+ return -1;
+ }
+
+ if (children.num_children == 0) {
+ errno = ECHILD;
+ return -1;
+ }
+
+ if (pid > 0) {
+ if (options != 0) {
+ errno = ENOTSUP;
+ DebugBreak();
+ return -1;
+ }
+ /* find entry in table */
+ for (index = 0; index < children.num_children; index++)
+ if (children.process_id[index] == pid)
+ break;
+
+ if (index == children.num_children) {
+ errno = ECHILD;
+ return -1;
+ }
+
+ process = children.handles[index];
+ ret = WaitForSingleObject(process, INFINITE);
+ if (ret != WAIT_OBJECT_0)
+ DebugBreak();//fatal
+
+ ret_id = children.process_id[index];
+ GetExitCodeProcess(process, &exit_code);
+ /* process handle will be closed when its removed from list */
+ sw_remove_child_at_index(index);
+ if (status)
+ *status = exit_code;
+ return ret_id;
+ }
+
+ /* pid = -1*/
+ timeout = INFINITE;
+ if (options & WNOHANG)
+ timeout = 0;
+ ret = WaitForMultipleObjects(children.num_children, children.handles, FALSE, timeout);
+ if ((ret >= WAIT_OBJECT_0) && (ret < (WAIT_OBJECT_0 + children.num_children))) {
+ index = ret - WAIT_OBJECT_0;
+ process = children.handles[index];
+ ret_id = children.process_id[index];
+ GetExitCodeProcess(process, &exit_code);
+ /* process handle will be closed when its removed from list */
+ sw_remove_child_at_index(index);
+ if (status)
+ *status = exit_code;
+ return ret_id;
+ }
+ else if (ret == WAIT_TIMEOUT) {
+ /* TODO - assert that WNOHANG was specified*/
+ return 0;
+ }
+
+ DebugBreak();//fatal
+ return -1;
+}
+
+void
+sw_cleanup_child_zombies() {
+ int pid = 1;
+ while (pid > 0) {
+ pid = waitpid(-1, NULL, WNOHANG);
+ }
+}
\ No newline at end of file
diff --git a/contrib/win32/win32compat/socketio.c b/contrib/win32/win32compat/socketio.c
new file mode 100644
index 000000000..8e5bbc234
--- /dev/null
+++ b/contrib/win32/win32compat/socketio.c
@@ -0,0 +1,1082 @@
+/*
+* Author: Manoj Ampalam
+*
+* Copyright (c) 2015 Microsoft Corp.
+* All rights reserved
+*
+* Microsoft openssh win32 port
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* 1. Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include "w32fd.h"
+#include
+#include "inc\utf.h"
+
+#define INTERNAL_SEND_BUFFER_SIZE 70*1024 //70KB
+
+#define INTERNAL_RECV_BUFFER_SIZE 70*1024 //70KB
+
+#define errno_from_WSALastError() errno_from_WSAError(WSAGetLastError())
+
+/* maps WSAError to errno */
+static
+int errno_from_WSAError(int wsaerrno)
+{
+ switch (wsaerrno) {
+ case WSAEWOULDBLOCK:
+ return EAGAIN;
+ case WSAEFAULT:
+ return EFAULT;
+ case WSAEINVAL:
+ return EINVAL;
+ case WSAECONNABORTED:
+ return ECONNABORTED;
+ case WSAECONNREFUSED:
+ return ECONNREFUSED;
+ case WSAEINPROGRESS:
+ return EINPROGRESS;
+ case WSAESHUTDOWN:
+ return ECONNRESET;
+ case WSAENOTCONN:
+ return ENOTCONN;
+ default:
+ /* */
+ return wsaerrno - 10000;
+ }
+}
+
+/* called before any other calls to socketio_ functions */
+int
+socketio_initialize() {
+ WSADATA wsaData = { 0 };
+ return WSAStartup(MAKEWORD(2, 2), &wsaData);
+}
+
+/* cleanup */
+int
+socketio_done() {
+ WSACleanup();
+ return 0;
+}
+
+/* state info that needs to be persisted for an inprocess acceptEx call*/
+struct acceptEx_context {
+ char lpOutputBuf[1024];
+ SOCKET accept_socket;
+ LPFN_ACCEPTEX lpfnAcceptEx;
+ LPFN_GETACCEPTEXSOCKADDRS lpfnGuidGetAcceptExSockaddrs;
+ DWORD bytes_received;
+};
+
+/* initiate async acceptEx*/
+/* TODO - always return 0, set error in context, accept() will pick it up*/
+int
+socketio_acceptEx(struct w32_io* pio) {
+ struct acceptEx_context *context;
+
+ debug3("acceptEx - io:%p", pio);
+ context = (struct acceptEx_context *)pio->internal.context;
+
+ ResetEvent(pio->read_overlapped.hEvent);
+
+ /* create accepting socket */
+ context->accept_socket = socket(AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
+ if (context->accept_socket == INVALID_SOCKET) {
+ errno = errno_from_WSALastError();
+ debug("acceptEx - socket() ERROR:%d, io:%p", errno, pio);
+ return -1;
+ }
+
+ if (TRUE == context->lpfnAcceptEx(pio->sock,
+ context->accept_socket,
+ context->lpOutputBuf,
+ 0,
+ sizeof(SOCKADDR_STORAGE) + 16,
+ sizeof(SOCKADDR_STORAGE) + 16,
+ &context->bytes_received,
+ &pio->read_overlapped))
+ {
+ /* we are already connected. Set event so subsequent select will catch */
+ SetEvent(pio->read_overlapped.hEvent);
+ }
+ else {
+ /* if overlapped io is in progress, we are good */
+ if (WSAGetLastError() != ERROR_IO_PENDING) {
+ errno = errno_from_WSALastError();
+ debug("acceptEx - AcceptEx() ERROR:%d, io:%p", errno, pio);
+ return -1;
+ }
+ }
+
+ pio->read_details.pending = TRUE;
+ return 0;
+}
+
+void
+CALLBACK WSARecvCompletionRoutine(
+ IN DWORD dwError,
+ IN DWORD cbTransferred,
+ IN LPWSAOVERLAPPED lpOverlapped,
+ IN DWORD dwFlags
+ )
+{
+ struct w32_io* pio =
+ (struct w32_io*)((char*)lpOverlapped - offsetof(struct w32_io, read_overlapped));
+ debug2("WSARecvCompletionCB - io:%p, pending_state:%d, flags:%d, error:%d, received:%d",
+ pio, pio->read_details.pending, dwFlags, dwError, cbTransferred);
+ if (!dwError && !cbTransferred)
+ dwError = ERROR_GRACEFUL_DISCONNECT;
+ pio->read_details.error = dwError;
+ pio->read_details.remaining = cbTransferred;
+ pio->read_details.completed = 0;
+ pio->read_details.pending = FALSE;
+}
+
+/* initiates async receive operation*/
+/* TODO - always return 0, or make this a void func. any error should be put in context*/
+int
+socketio_WSARecv(struct w32_io* pio, BOOL* completed) {
+ int ret = 0;
+ WSABUF wsabuf;
+ DWORD recv_flags = 0;
+
+ debug3("WSARecv - pio: %p", pio);
+ if (completed)
+ *completed = FALSE;
+
+ /* initialize recv buffers if needed */
+ wsabuf.len = INTERNAL_RECV_BUFFER_SIZE;
+ if (pio->read_details.buf == NULL)
+ {
+ wsabuf.buf = malloc(wsabuf.len);
+
+ if (!wsabuf.buf)
+ {
+ errno = ENOMEM;
+ debug("WSARecv - ERROR:%d, io:%p", errno, pio);
+ return -1;
+ }
+
+ pio->read_details.buf = wsabuf.buf;
+ pio->read_details.buf_size = wsabuf.len;
+ }
+ else
+ wsabuf.buf = pio->read_details.buf;
+
+
+ ret = WSARecv(pio->sock, &wsabuf, 1, NULL, &recv_flags, &pio->read_overlapped,
+ &WSARecvCompletionRoutine);
+ if (ret == 0)
+ {
+ pio->read_details.pending = TRUE;
+ /* receive has completed but APC is pending to be scheduled */
+ debug2("WSARecv - WSARecv() returned 0, io:%p", pio);
+ if (completed)
+ *completed = TRUE;
+ }
+ else { /* (ret == SOCKET_ERROR) */
+ if (WSAGetLastError() == WSA_IO_PENDING)
+ {
+ /* io is initiated and pending */
+ debug2("WSARecv - reported IO pending");
+ pio->read_details.pending = TRUE;
+ }
+ else {
+ errno = errno_from_WSALastError();
+ debug("WSARecv - WSARecv() ERROR: io:%p %d", pio, errno);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/* implements socket() */
+struct w32_io*
+socketio_socket(int domain, int type, int protocol) {
+ struct w32_io *pio = (struct w32_io*)malloc(sizeof(struct w32_io));
+ if (!pio) {
+ errno = ENOMEM;
+ debug("socket - ERROR:%d, io:%p", errno, pio);
+ return NULL;
+ }
+
+ memset(pio, 0, sizeof(struct w32_io));
+ pio->sock = socket(domain, type, protocol);
+ if (pio->sock == INVALID_SOCKET) {
+ errno = errno_from_WSALastError();
+ free(pio);
+ debug("socket - socket() ERROR:%d, io:%p", errno, pio);
+ return NULL;
+ }
+
+ pio->internal.state = SOCK_INITIALIZED;
+ return pio;
+}
+
+#define SET_ERRNO_ON_ERROR(expr) do { \
+ int ret = (expr); \
+ if (ret == SOCKET_ERROR) { \
+ errno = errno_from_WSALastError(); \
+ debug("%s - ERROR:%d", __FUNCTION__, errno); \
+ } \
+ return ret; \
+} while (0)
+
+/* implements setsockopt() */
+int
+socketio_setsockopt(struct w32_io* pio, int level, int optname, const char* optval,
+ int optlen) {
+ if ((optname == SO_KEEPALIVE) || (optname == SO_REUSEADDR) ||
+ (optname == TCP_NODELAY) || (optname == IPV6_V6ONLY))
+ SET_ERRNO_ON_ERROR(setsockopt(pio->sock, level, optname, optval, optlen));
+ else {
+ debug("setsockop - ERROR: unsupported optname:%d io:%p", optname, pio);
+ errno = ENOTSUP;
+ return -1;
+ }
+}
+
+/* implements getsockopt() */
+int
+socketio_getsockopt(struct w32_io* pio, int level, int optname, char* optval, int* optlen) {
+ SET_ERRNO_ON_ERROR(getsockopt(pio->sock, level, optname, optval, optlen));
+}
+
+/* implements getsockname() */
+int
+socketio_getsockname(struct w32_io* pio, struct sockaddr* name, int* namelen) {
+ SET_ERRNO_ON_ERROR(getsockname(pio->sock, name, namelen));
+}
+
+/* implements getpeername */
+int
+socketio_getpeername(struct w32_io* pio, struct sockaddr* name, int* namelen) {
+ SET_ERRNO_ON_ERROR(getpeername(pio->sock, name, namelen));
+}
+
+/* implements listen() */
+int
+socketio_listen(struct w32_io* pio, int backlog) {
+ struct acceptEx_context* context;
+
+ if (SOCKET_ERROR == listen(pio->sock, backlog)) {
+ errno = errno_from_WSALastError();
+ debug("listen - listen() ERROR:%d io:%p", errno, pio);
+ return -1;
+ }
+
+ /* prep for accept*/
+ {
+ GUID GuidAcceptEx = WSAID_ACCEPTEX;
+ GUID GuidGetAcceptExSockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
+ DWORD dwBytes;
+
+ context = (struct acceptEx_context*)malloc(sizeof(struct acceptEx_context));
+ if (context == NULL) {
+ errno = ENOMEM;
+ debug("listen - ERROR:%d, io:%p", errno, pio);
+ return -1;
+ }
+ memset(context, 0, sizeof(struct acceptEx_context));
+ if (SOCKET_ERROR == WSAIoctl(pio->sock,
+ SIO_GET_EXTENSION_FUNCTION_POINTER,
+ &GuidAcceptEx, sizeof(GuidAcceptEx),
+ &context->lpfnAcceptEx, sizeof(context->lpfnAcceptEx),
+ &dwBytes, NULL, NULL))
+ {
+ free(context);
+ errno = errno_from_WSALastError();
+ debug("listen - Ioctl1 ERROR:%d, io:%p", errno, pio);
+ return -1;
+ }
+
+ if (SOCKET_ERROR == WSAIoctl(pio->sock,
+ SIO_GET_EXTENSION_FUNCTION_POINTER,
+ &GuidGetAcceptExSockaddrs, sizeof(GuidGetAcceptExSockaddrs),
+ &context->lpfnGuidGetAcceptExSockaddrs, sizeof(context->lpfnGuidGetAcceptExSockaddrs),
+ &dwBytes, NULL, NULL))
+ {
+ free(context);
+ errno = errno_from_WSALastError();
+ debug("listen - Ioctl2 ERROR:%d, io:%p", errno, pio);
+ return -1;
+ }
+
+ pio->read_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if ((pio->read_overlapped.hEvent) == NULL) {
+ free(context);
+ errno = ENOMEM;
+ debug("listen - CreateEvent() ERROR:%d, io:%p", errno, pio);
+ return -1;
+ }
+
+ context->accept_socket = INVALID_SOCKET;
+ pio->internal.context = context;
+ }
+
+ pio->internal.state = SOCK_LISTENING;
+ return 0;
+}
+
+/* implements bind() */
+int
+socketio_bind(struct w32_io* pio, const struct sockaddr *name, int namelen) {
+ SET_ERRNO_ON_ERROR(bind(pio->sock, name, namelen));
+}
+
+/* implements recv() */
+int
+socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags) {
+ BOOL completed = FALSE;
+
+ debug3("recv - io:%p", pio);
+
+ if ((buf == NULL) || (len == 0)) {
+ errno = EINVAL;
+ debug("recv - ERROR: invalid arguments, buf:%p, len:%d, io:%p", buf, len, pio);
+ return -1;
+ }
+
+ if (flags != 0) {
+ errno = ENOTSUP;
+ debug("recv - ERROR: flags are not currently supported, io:%p", pio);
+ return -1;
+ }
+
+ /* TODO - ensure socket is in accepted or connected state */
+
+ /* /io is initiated and pending */
+ if (pio->read_details.pending) {
+ /* if recv is now in blocking mode, wait for data to be available */
+ if (w32_io_is_blocking(pio)) {
+ debug2("recv - io is pending, call is blocking, io:%p", pio);
+ while (socketio_is_io_available(pio, TRUE) == FALSE) {
+ if (0 != wait_for_any_event(NULL, 0, INFINITE))
+ return -1;
+ }
+ }
+ else {
+ errno = EAGAIN;
+ debug2("recv - io is already pending, io:%p", pio);
+ return -1;
+ }
+ }
+
+ /* if we have some buffer copy it and return #bytes copied */
+ if (pio->read_details.remaining)
+ {
+ int num_bytes_copied = min((int)len, pio->read_details.remaining);
+ memcpy(buf, pio->read_details.buf + pio->read_details.completed,
+ num_bytes_copied);
+ pio->read_details.remaining -= num_bytes_copied;
+ pio->read_details.completed += num_bytes_copied;
+ debug2("recv - returning %d bytes from prior completed IO, remaining:%d, io:%p",
+ num_bytes_copied, pio->read_details.remaining, pio);
+ return num_bytes_copied;
+ }
+
+
+ /* if there was an error on async call, return */
+ if (pio->read_details.error) {
+ if (pio->read_details.error == ERROR_GRACEFUL_DISCONNECT) {
+ debug2("recv - connection closed, io:%p", pio);
+ /* connection is closed */
+ return 0;
+ }
+ else {
+ errno = errno_from_WSAError(pio->read_details.error);
+ debug("recv - from CB ERROR:%d, io:%p", pio->read_details.error, pio);
+ pio->read_details.error = 0;
+ return -1;
+ }
+ }
+
+ if (0 != socketio_WSARecv(pio, &completed))
+ return -1;
+
+ if (completed) {
+ /* Let APC be scheduled */
+ debug2("recv - Letting APC to execute, io:%p", pio);
+ SleepEx(0, TRUE);
+ if (pio->read_details.pending) {
+ /* this shouldn't be happening */
+ errno = EOTHER;
+ debug("recv - ERROR: Unexpected IO state, io:%p", pio);
+ return -1;
+ }
+ }
+
+ if (w32_io_is_blocking(pio))
+ {
+ /* wait until io is done */
+ debug3("recv - socket in blocking mode, io:%p", pio);
+ while (socketio_is_io_available(pio, TRUE) == FALSE) {
+ if (0 != wait_for_any_event(NULL, 0, INFINITE))
+ return -1;
+ }
+ }
+ else {
+ if (socketio_is_io_available(pio, TRUE) == FALSE) {
+ errno = EAGAIN;
+ debug2("recv - IO is pending, io:%p", pio);
+ return -1;
+ }
+ }
+
+ /*
+ * by this time we should have some bytes in internal buffer
+ * or an error from callback
+ */
+ if (pio->read_details.error)
+ {
+ if (pio->read_details.error == ERROR_GRACEFUL_DISCONNECT) {
+ /* connection is closed */
+ debug2("recv - connection closed(2), io:%p", pio);
+ return 0;
+ }
+ else {
+ errno = errno_from_WSAError(pio->read_details.error);
+ pio->read_details.error = 0;
+ debug("recv - from CB(2) ERROR:%d, io:%p", errno, pio);
+ return -1;
+ }
+ }
+
+ if (pio->read_details.remaining) {
+ int num_bytes_copied = min((int)len, pio->read_details.remaining);
+ memcpy(buf, pio->read_details.buf, num_bytes_copied);
+ pio->read_details.remaining -= num_bytes_copied;
+ pio->read_details.completed = num_bytes_copied;
+ debug2("recv - (2) returning %d bytes from completed IO, remaining:%d, io:%p",
+ num_bytes_copied, pio->read_details.remaining, pio);
+ return num_bytes_copied;
+ }
+ else {
+ /* this should not happen */
+ errno = EOTHER;
+ debug("recv - (2) ERROR:Unexpected IO state, io:%p", pio);
+ return -1;
+ }
+
+}
+
+void
+CALLBACK WSASendCompletionRoutine(
+ IN DWORD dwError,
+ IN DWORD cbTransferred,
+ IN LPWSAOVERLAPPED lpOverlapped,
+ IN DWORD dwFlags
+ )
+{
+ struct w32_io* pio =
+ (struct w32_io*)((char*)lpOverlapped - offsetof(struct w32_io, write_overlapped));
+ debug2("WSASendCB - io:%p, pending_state:%d, error:%d, sent:%d of remaining:%d",
+ pio, pio->write_details.pending, dwError, cbTransferred,
+ pio->write_details.remaining);
+ pio->write_details.error = dwError;
+ /* TODO - assert that remaining == cbTransferred */
+ if ((dwError == 0) && (pio->write_details.remaining != cbTransferred)) {
+ debug("WSASendCB - ERROR: broken assumption, io:%p, sent:%d, remaining:%d", pio,
+ cbTransferred, pio->write_details.remaining);
+ DebugBreak();
+ }
+ pio->write_details.remaining -= cbTransferred;
+ pio->write_details.pending = FALSE;
+}
+
+/* implementation of send() */
+int
+socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags) {
+ int ret = 0;
+ WSABUF wsabuf;
+
+ debug2("send - io:%p", pio);
+
+ if ((buf == NULL) || (len == 0)) {
+ errno = EINVAL;
+ debug("send - ERROR invalid arguments, buf:%p, len:%d, io:%p", buf, len, pio);
+ return -1;
+ }
+
+ if (flags != 0) {
+ errno = ENOTSUP;
+ debug("send - ERROR: flags are not currently supported, io:%p", pio);
+ return -1;
+ }
+
+ /* TODO - ensure socket is in accepted or connected state */
+
+ /* if io is already pending */
+ if (pio->write_details.pending)
+ {
+ if (w32_io_is_blocking(pio))
+ {
+ debug2("send - io is pending, call is blocking, io:%p", pio);
+ while (pio->write_details.pending) {
+ if (wait_for_any_event(NULL, 0, INFINITE) == -1)
+ return -1;
+ }
+ }
+ else {
+ errno = EAGAIN;
+ debug2("send - IO currently pending, EAGAIN, io:%p", pio);
+ return -1;
+ }
+ }
+
+
+ if (pio->write_details.error) {
+ errno = errno_from_WSAError(pio->write_details.error);
+ debug("ERROR:%d, io:%p", errno, pio);
+ return -1;
+ }
+
+ /* initialize buffers if needed */
+ wsabuf.len = INTERNAL_SEND_BUFFER_SIZE;
+ if (pio->write_details.buf == NULL)
+ {
+ wsabuf.buf = malloc(wsabuf.len);
+ if (!wsabuf.buf)
+ {
+ errno = ENOMEM;
+ debug("send - ERROR:%d, io:%p", errno, pio);
+ return -1;
+ }
+
+ pio->write_details.buf = wsabuf.buf;
+ pio->write_details.buf_size = wsabuf.len;
+ }
+ else {
+ wsabuf.buf = pio->write_details.buf;
+ }
+
+ wsabuf.len = min(wsabuf.len, (int)len);
+ memcpy(wsabuf.buf, buf, wsabuf.len);
+
+ /* TODO - implement flags support if needed */
+ ret = WSASend(pio->sock, &wsabuf, 1, NULL, 0, &pio->write_overlapped,
+ &WSASendCompletionRoutine);
+
+ if (ret == 0)
+ {
+ /* send has completed and APC is scheduled, let it run */
+ debug2("send - WSASend() returned 0, APC scheduled io:%p", pio);
+ pio->write_details.pending = TRUE;
+ pio->write_details.remaining = wsabuf.len;
+ SleepEx(0, TRUE);
+ if ((pio->write_details.pending) || (pio->write_details.remaining != 0)) {
+ errno = EOTHER;
+ debug("send - ERROR: Unexpected IO state, io:%p", pio);
+ return -1;
+ }
+
+ /* return num of bytes written */
+ return wsabuf.len;
+ }
+ else {
+ if (WSAGetLastError() == WSA_IO_PENDING)
+ {
+ /* io is initiated and pending */
+ debug2("send - WSASend reported IO pending, io:%p", pio);
+ pio->write_details.pending = TRUE;
+ pio->write_details.remaining = wsabuf.len;
+ if (w32_io_is_blocking(pio))
+ {
+ /* wait until io is done */
+ debug3("send - waiting as socket is in blocking mode, io:%p", pio);
+ while (pio->write_details.pending)
+ if (wait_for_any_event(NULL, 0, INFINITE) == -1) {
+ /* if interrupted but send has completed, we are good*/
+ if ((errno != EINTR) || (pio->write_details.pending))
+ return -1;
+ errno = 0;
+ }
+ }
+
+ debug3("send - returning %d, io:%p", wsabuf.len, pio);
+ return wsabuf.len;
+ }
+ else {
+ errno = errno_from_WSALastError();
+ debug("send - WSASend() ERROR:%d, io:%p", errno, pio);
+ return -1;
+ }
+ }
+}
+
+/* shutdown() implementation */
+int
+socketio_shutdown(struct w32_io* pio, int how) {
+ SET_ERRNO_ON_ERROR(shutdown(pio->sock, how));
+}
+
+/* socket close() implementation */
+int
+socketio_close(struct w32_io* pio) {
+ debug2("close - io:%p", pio);
+ closesocket(pio->sock);
+ /* wait for pending io to abort */
+ SleepEx(0, TRUE);
+ if ( ((pio->internal.state == SOCK_CONNECTED) || (pio->internal.state == SOCK_ACCEPTED))
+ && (pio->read_details.pending || pio->write_details.pending)) {
+ debug2("close - IO is still pending on closed socket. read:%d, write:%d, io:%p",
+ pio->read_details.pending, pio->write_details.pending, pio);
+ DebugBreak();
+ }
+ if (pio->internal.state == SOCK_LISTENING) {
+ if (pio->read_overlapped.hEvent)
+ CloseHandle(pio->read_overlapped.hEvent);
+ if (pio->internal.context)
+ {
+ struct acceptEx_context *ctx = (struct acceptEx_context*)pio->internal.context;
+ if (ctx->accept_socket != INVALID_SOCKET)
+ closesocket(ctx->accept_socket);
+ free(pio->internal.context);
+ }
+
+ }
+ else if (pio->internal.state == SOCK_CONNECTING) {
+ if (pio->write_overlapped.hEvent)
+ CloseHandle(pio->write_overlapped.hEvent);
+ }
+ else {
+ if (pio->read_details.buf)
+ free(pio->read_details.buf);
+
+ if (pio->write_details.buf)
+ free(pio->write_details.buf);
+ }
+
+ free(pio);
+ return 0;
+}
+
+/* accept() implementation */
+struct w32_io*
+socketio_accept(struct w32_io* pio, struct sockaddr* addr, int* addrlen) {
+ struct w32_io *accept_io = NULL;
+ int iResult = 0;
+ struct acceptEx_context* context;
+ struct sockaddr *local_address,*remote_address;
+ int local_address_len, remote_address_len;
+
+ debug3("accept - io:%p", pio);
+ /* start io if not already started */
+ if (pio->read_details.pending == FALSE) {
+ if (socketio_acceptEx(pio) != 0) {
+ return NULL;
+ }
+ }
+
+ if (w32_io_is_blocking(pio)) {
+ /* block until accept io is complete */
+ while (FALSE == socketio_is_io_available(pio, TRUE))
+ if (-1 == wait_for_any_event(&pio->read_overlapped.hEvent,
+ 1, INFINITE))
+ return NULL;
+ }
+ else {
+ /* if i/o is not ready */
+ if (FALSE == socketio_is_io_available(pio, TRUE)) {
+ errno = EAGAIN;
+ debug2("accept is pending, io:%p", pio);
+ return NULL;
+ }
+
+ }
+
+ context = (struct acceptEx_context*)pio->internal.context;
+ pio->read_details.pending = FALSE;
+ ResetEvent(pio->read_overlapped.hEvent);
+
+ if (pio->read_details.error) {
+ errno = errno_from_WSAError(pio->read_details.error);
+ debug("accept - ERROR: async io completed with error: %d, io:%p", errno, pio);
+ goto on_error;
+ }
+
+ if (0 != setsockopt(context->accept_socket, SOL_SOCKET,
+ SO_UPDATE_ACCEPT_CONTEXT, (char*)&pio->sock, sizeof(pio->sock))) {
+ errno = errno_from_WSALastError();
+ debug("accept - ERROR: setsockopt failed:%d, io:%p", errno, pio);
+ goto on_error;
+ }
+
+ accept_io = (struct w32_io*)malloc(sizeof(struct w32_io));
+ if (!accept_io) {
+ errno = ENOMEM;
+ debug("accept - ERROR:%d, io:%p", errno, pio);
+ goto on_error;
+ }
+ memset(accept_io, 0, sizeof(struct w32_io));
+
+ accept_io->sock = context->accept_socket;
+ accept_io->internal.state = SOCK_ACCEPTED;
+ context->accept_socket = INVALID_SOCKET;
+ debug2("accept io:%p", accept_io);
+
+ if ((addr != NULL) && (addrlen != NULL)) {
+ context->lpfnGuidGetAcceptExSockaddrs(context->lpOutputBuf, 0,
+ sizeof(SOCKADDR_STORAGE) + 16,
+ sizeof(SOCKADDR_STORAGE) + 16, &local_address,
+ &local_address_len, &remote_address, &remote_address_len);
+ if (remote_address_len) {
+ memcpy(addr, remote_address, remote_address_len);
+ *addrlen = remote_address_len;
+ }
+ }
+ return accept_io;
+
+on_error:
+ if (context->accept_socket != INVALID_SOCKET) {
+ closesocket(context->accept_socket);
+ context->accept_socket = INVALID_SOCKET;
+ }
+
+ return NULL;
+}
+
+/* initiates an async connect*/
+int
+socketio_connectex(struct w32_io* pio, const struct sockaddr* name, int namelen) {
+
+ struct sockaddr_in tmp_addr4;
+ struct sockaddr_in6 tmp_addr6;
+ SOCKADDR* tmp_addr;
+ size_t tmp_addr_len;
+ DWORD tmp_bytes;
+ GUID connectex_guid = WSAID_CONNECTEX;
+ LPFN_CONNECTEX ConnectEx;
+
+ debug3("connectex - io:%p", pio);
+ if (name->sa_family == AF_INET6) {
+ ZeroMemory(&tmp_addr6, sizeof(tmp_addr6));
+ tmp_addr6.sin6_family = AF_INET6;
+ tmp_addr6.sin6_port = 0;
+ tmp_addr = (SOCKADDR*)&tmp_addr6;
+ tmp_addr_len = sizeof(tmp_addr6);
+ }
+ else if (name->sa_family == AF_INET) {
+ ZeroMemory(&tmp_addr4, sizeof(tmp_addr4));
+ tmp_addr4.sin_family = AF_INET;
+ tmp_addr4.sin_port = 0;
+ tmp_addr = (SOCKADDR*)&tmp_addr4;
+ tmp_addr_len = sizeof(tmp_addr4);
+ }
+ else {
+ errno = ENOTSUP;
+ debug("connectex - ERROR: unsuppored address family:%d, io:%p", name->sa_family, pio);
+ return -1;
+ }
+
+ if (SOCKET_ERROR == bind(pio->sock, tmp_addr, (int)tmp_addr_len))
+ {
+ errno = errno_from_WSALastError();
+ debug("connectex - ERROR: bind failed :%d, io:%p", WSAGetLastError(), pio);
+ return -1;
+ }
+
+ if (SOCKET_ERROR == WSAIoctl(pio->sock, SIO_GET_EXTENSION_FUNCTION_POINTER,
+ &connectex_guid, sizeof(connectex_guid),
+ &ConnectEx, sizeof(ConnectEx),
+ &tmp_bytes, NULL, NULL))
+ {
+ errno = errno_from_WSALastError();
+ debug("connectex - ioctl ERROR:%d, io:%p", WSAGetLastError(), pio);
+ return -1;
+ }
+
+ if ((!pio->write_overlapped.hEvent)
+ && ((pio->write_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)) {
+ errno = ENOMEM;
+ debug("connectex - ERROR CreateEvent failed:%d, io:%p", errno, pio);
+ return -1;
+ }
+
+ ResetEvent(pio->write_overlapped.hEvent);
+ if (TRUE == ConnectEx(pio->sock, name, namelen, NULL, 0, NULL,
+ &pio->write_overlapped)) {
+ /* set completion event to indicates that async connect has completed */
+ SetEvent(pio->write_overlapped.hEvent);
+ }
+ else {
+ if (WSAGetLastError() != ERROR_IO_PENDING) {
+ CloseHandle(pio->write_overlapped.hEvent);
+ pio->write_overlapped.hEvent = 0;
+ errno = errno_from_WSALastError();
+ debug("connectex - ERROR ConnectEx() :%d, io:%p", errno, pio);
+ return -1;
+ }
+ }
+
+ pio->write_details.pending = TRUE;
+ pio->internal.state = SOCK_CONNECTING;
+ return 0;
+}
+
+/* connect implementation */
+int
+socketio_connect(struct w32_io* pio, const struct sockaddr* name, int namelen) {
+
+ debug3("connect - io:%p", pio);
+ if (pio->write_details.pending == FALSE) {
+ if (-1 == socketio_connectex(pio, name, namelen))
+ return -1;
+ }
+
+ if (w32_io_is_blocking(pio)) {
+ /* block until connect io is complete */
+ while (FALSE == socketio_is_io_available(pio, TRUE)) {
+ if (-1 == wait_for_any_event(&pio->write_overlapped.hEvent,
+ 1, INFINITE))
+ return -1;
+ }
+ }
+ else {
+ /* if i/o is not ready */
+ if (FALSE == socketio_is_io_available(pio, TRUE)) {
+ errno = EINPROGRESS;
+ debug2("connect - in progress, io:%p", pio);
+ return -1;
+ }
+
+ }
+
+ return socketio_finish_connect(pio);
+}
+
+int
+socketio_finish_connect(struct w32_io* pio) {
+
+ debug3("finish_connect, io:%p", pio);
+
+ if (pio->write_details.error) {
+ errno = errno_from_WSAError(pio->write_details.error);
+ debug("finish_connect - ERROR: async io completed with error: %d, io:%p", errno, pio);
+ return -1;
+ }
+
+ if (0 != setsockopt(pio->sock, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0)) {
+ errno = errno_from_WSALastError();
+ debug("finish_connect - ERROR: setsockopt failed:%d, io:%p", errno, pio);
+ return -1;
+ }
+
+ /* Reset any state used during connect */
+ /* close event handle */
+ CloseHandle(pio->write_overlapped.hEvent);
+ ZeroMemory(&pio->write_details, sizeof(pio->write_details));
+ pio->internal.state = SOCK_CONNECTED;
+ return 0;
+}
+
+/* checks if a given io is ready/available */
+BOOL
+socketio_is_io_available(struct w32_io* pio, BOOL rd) {
+
+ if ((pio->internal.state == SOCK_LISTENING) ||
+ (pio->internal.state == SOCK_CONNECTING)) {
+ DWORD numBytes = 0;
+ DWORD flags;
+ BOOL sock_listening = (pio->internal.state == SOCK_LISTENING);
+ OVERLAPPED *overlapped =
+ sock_listening ? &pio->read_overlapped : &pio->write_overlapped;
+ BOOL pending =
+ sock_listening ? pio->read_details.pending : pio->write_details.pending;
+
+ if (pending)
+ /* if there is an error to be picked up */
+ if (sock_listening) {
+ if (pio->read_details.error)
+ return TRUE;
+ }
+ else {
+ if (pio->write_details.error)
+ return TRUE;
+ }
+
+ if (WSAGetOverlappedResult(pio->sock, overlapped,
+ &numBytes, FALSE, &flags))
+ return TRUE;
+ else if (WSAGetLastError() != WSA_IO_INCOMPLETE) {
+ if (sock_listening)
+ pio->read_details.error = WSAGetLastError();
+ else
+ pio->write_details.error = WSAGetLastError();
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+ else if (rd) {
+ if (pio->read_details.remaining || pio->read_details.error)
+ return TRUE;
+ else
+ return FALSE;
+ }
+ else {
+ return (pio->write_details.pending == FALSE) ? TRUE : FALSE;
+ }
+
+}
+/*start async io (if needed) for accept and recv*/
+void
+socketio_on_select(struct w32_io* pio, BOOL rd) {
+
+ enum w32_io_sock_state sock_state = pio->internal.state;
+
+ debug2("on_select - io:%p type:%d rd:%d", pio, pio->type, rd);
+
+ //nothing to do for writes (that includes connect)
+ if (!rd)
+ return;
+
+ //listening socket - acceptEx if needed
+ if (sock_state == SOCK_LISTENING) {
+ if (pio->read_details.pending == FALSE)
+ if (socketio_acceptEx(pio) != 0) {
+ /* set error, accept will pick it*/
+ pio->read_details.error = errno;
+ errno = 0;
+ pio->read_details.pending = TRUE;
+ SetEvent(pio->read_overlapped.hEvent);
+ return;
+ }
+ }
+ else {
+ //connected socket - WSARecv if needed
+ if ((!pio->read_details.pending) && (!socketio_is_io_available(pio, rd)))
+ if (socketio_WSARecv(pio, NULL) != 0) {
+ /* set error, recv() will pick it */
+ pio->read_details.error = errno;
+ errno = 0;
+ return;
+ }
+ }
+
+}
+
+int
+w32_gethostname(char *name_utf8, size_t len) {
+ wchar_t name_utf16[256];
+ char* tmp_name_utf8 = NULL;
+
+ if (IsWindows8OrGreater()) {
+ /* TODO - GetHostNameW not present in Win7, do GetProcAddr on Win8+*/
+ // if (GetHostNameW(name_utf16, 256) == SOCKET_ERROR) {
+ // errno = errno_from_WSALastError();
+ // return -1;
+ // }
+
+ // if ((tmp_name_utf8 = utf16_to_utf8(name_utf16)) == NULL ||
+ // strlen(tmp_name_utf8) >= len) {
+ // errno = EFAULT; //??
+ // return -1;
+ // }
+
+ // memcpy(name_utf8, tmp_name_utf8, strlen(tmp_name_utf8) + 1);
+ // free(tmp_name_utf8);
+ // return 0;
+ return gethostname(name_utf8, len);
+ }
+ else
+ return gethostname(name_utf8, len);
+}
+
+void
+w32_freeaddrinfo(struct addrinfo *ai) {
+ struct addrinfo *cur;
+ while (ai) {
+ cur = ai;
+ ai = ai->ai_next;
+ if (cur->ai_addr)
+ free(cur->ai_addr);
+ if (cur->ai_canonname)
+ free(cur->ai_canonname);
+ free(cur);
+ }
+}
+
+int
+w32_getaddrinfo(const char *node_utf8, const char *service_utf8,
+ const struct addrinfo *hints, struct addrinfo **res) {
+ int ret = 0;
+ wchar_t *node_utf16 = NULL, *service_utf16 = NULL;
+ struct addrinfoW *info_w = NULL;
+ *res = NULL;
+
+ if ((node_utf8 && (node_utf16 = utf8_to_utf16(node_utf8)) == NULL) ||
+ (service_utf8 && (service_utf16 = utf8_to_utf16(service_utf8)) == NULL)) {
+ ret = EAI_MEMORY;
+ goto done;
+ }
+
+ if ((ret = GetAddrInfoW(node_utf16, service_utf16, (ADDRINFOW*)hints, &info_w)) != 0)
+ goto done;
+
+ /* copy info_w to res */
+ {
+ struct addrinfoW **cur_w = &info_w;
+ struct addrinfo **cur = res;
+
+ while (*cur_w) {
+ if ((*cur = malloc(sizeof(struct addrinfo))) == NULL) {
+ ret = EAI_MEMORY;
+ goto done;
+ }
+ memcpy(*cur, *cur_w, sizeof(struct addrinfo));
+ (*cur)->ai_next = NULL;
+ if (((*cur_w)->ai_canonname && ((*cur)->ai_canonname = utf16_to_utf8((*cur_w)->ai_canonname)) == NULL) ||
+ ((*cur_w)->ai_addrlen && ((*cur)->ai_addr = malloc((*cur_w)->ai_addrlen)) == NULL) ) {
+ ret = EAI_MEMORY;
+ goto done;
+
+ }
+ if ((*cur_w)->ai_addrlen)
+ memcpy((*cur)->ai_addr, (*cur_w)->ai_addr, (*cur_w)->ai_addrlen);
+ cur_w = &(*cur_w)->ai_next;
+ cur = &(*cur)->ai_next;
+ }
+ }
+
+done:
+ if (node_utf16)
+ free(node_utf16);
+ if (service_utf16)
+ free(service_utf16);
+ if (info_w)
+ FreeAddrInfoW(info_w);
+ if (ret != 0 && *res) {
+ w32_freeaddrinfo(*res);
+ *res = NULL;
+ }
+ return ret;
+}
+
+
diff --git a/contrib/win32/win32compat/ssh-agent/agent-main.c b/contrib/win32/win32compat/ssh-agent/agent-main.c
new file mode 100644
index 000000000..e7634bfa8
--- /dev/null
+++ b/contrib/win32/win32compat/ssh-agent/agent-main.c
@@ -0,0 +1,159 @@
+/*
+ * Author: Manoj Ampalam
+ * ssh-agent implementation on Windows
+ *
+ * Copyright (c) 2015 Microsoft Corp.
+ * All rights reserved
+ *
+ * Microsoft openssh win32 port
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "agent.h"
+
+
+int scm_start_service(DWORD, LPWSTR*);
+
+SERVICE_TABLE_ENTRYW dispatch_table[] =
+{
+ { L"ssh-agent", (LPSERVICE_MAIN_FUNCTIONW)scm_start_service },
+ { NULL, NULL }
+};
+static SERVICE_STATUS_HANDLE service_status_handle;
+static SERVICE_STATUS service_status;
+
+
+static VOID ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
+{
+ service_status.dwCurrentState = dwCurrentState;
+ service_status.dwWin32ExitCode = dwWin32ExitCode;
+ service_status.dwWaitHint = dwWaitHint;
+
+ if (dwCurrentState == SERVICE_START_PENDING)
+ service_status.dwControlsAccepted = 0;
+ else
+ service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
+
+ if ((dwCurrentState == SERVICE_RUNNING) || (dwCurrentState == SERVICE_STOPPED))
+ service_status.dwCheckPoint = 0;
+ else
+ service_status.dwCheckPoint = 1;
+
+ SetServiceStatus(service_status_handle, &service_status);
+}
+
+static VOID WINAPI service_handler(DWORD dwControl)
+{
+ switch (dwControl)
+ {
+ case SERVICE_CONTROL_STOP: {
+ ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 500);
+ agent_shutdown();
+ ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
+ return;
+ }
+ case SERVICE_CONTROL_INTERROGATE:
+ break;
+ default:
+ break;
+ }
+
+ ReportSvcStatus(service_status.dwCurrentState, NO_ERROR, 0);
+}
+
+BOOL WINAPI ctrl_c_handler(
+ _In_ DWORD dwCtrlType
+) {
+ /* for any Ctrl type, shutdown agent*/
+ debug("Ctrl+C received");
+ agent_shutdown();
+ return TRUE;
+}
+
+int wmain(int argc, wchar_t **argv) {
+
+ w32posix_initialize();
+ load_config();
+ if (!StartServiceCtrlDispatcherW(dispatch_table)) {
+ if (GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {
+
+ if (argc == 2) {
+ if (wcsncmp(argv[1], L"-ddd", 4) == 0)
+ log_init("ssh-agent", 7, 1, 1);
+ else if (wcsncmp(argv[1], L"-dd", 3) == 0)
+ log_init("ssh-agent", 6, 1, 1);
+ else if (wcsncmp(argv[1], L"-d", 2) == 0)
+ log_init("ssh-agent", 5, 1, 1);
+
+ if (wcsncmp(argv[1], L"-d", 2) == 0) {
+ SetConsoleCtrlHandler(ctrl_c_handler, TRUE);
+ agent_start(TRUE, FALSE, 0);
+ return 0;
+ }
+
+ /*agent process is likely a spawned child*/
+ char* h = 0;
+ h += _wtoi(*(argv + 1));
+ if (h != 0) {
+ log_init("ssh-agent", config_log_level(), 1, 0);
+ agent_start(FALSE, TRUE, h);
+ return 0;
+ }
+ }
+ /* to support linux compat scenarios where ssh-agent.exe is typically launched per session*/
+ /* - just start ssh-agent service if needed */
+ {
+ SC_HANDLE sc_handle, svc_handle;
+ DWORD err;
+
+ if ((sc_handle = OpenSCManagerW(NULL, NULL, SERVICE_START)) == NULL ||
+ (svc_handle = OpenServiceW(sc_handle, L"ssh-agent", SERVICE_START)) == NULL) {
+ fatal("unable to open service handle");
+ return -1;
+ }
+
+ if (StartService(svc_handle, 0, NULL) == FALSE && GetLastError() != ERROR_SERVICE_ALREADY_RUNNING) {
+ fatal("unable to start ssh-agent service, error :%d", GetLastError());
+ return -1;
+ }
+
+ return 0;
+ }
+ }
+ else
+ return -1;
+ }
+ return 0;
+}
+
+int scm_start_service(DWORD num, LPWSTR* args) {
+ service_status_handle = RegisterServiceCtrlHandlerW(L"ssh-agent", service_handler);
+ ZeroMemory(&service_status, sizeof(service_status));
+ service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+ ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 300);
+ ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
+ log_init("ssh-agent", config_log_level(), 1, 0);
+ agent_start(FALSE, FALSE, 0);
+ return 0;
+}
+
diff --git a/contrib/win32/win32compat/ssh-agent/agent-request.h b/contrib/win32/win32compat/ssh-agent/agent-request.h
new file mode 100644
index 000000000..3d7c3df9f
--- /dev/null
+++ b/contrib/win32/win32compat/ssh-agent/agent-request.h
@@ -0,0 +1,21 @@
+typedef unsigned char u_int8_t;
+typedef unsigned short u_int16_t;
+typedef unsigned int u_int32_t;
+typedef unsigned __int64 u_int64_t;
+#define __attribute__(a)
+#include "rsa.h"
+#include "sshbuf.h"
+#include "sshkey.h"
+#include "authfd.h"
+#include "digest.h"
+
+
+/* key management */
+int process_add_identity(struct sshbuf*, struct sshbuf*, struct agent_connection*);
+int process_request_identities(struct sshbuf*, struct sshbuf*, struct agent_connection*);
+int process_sign_request(struct sshbuf*, struct sshbuf*, struct agent_connection*);
+int process_remove_key(struct sshbuf*, struct sshbuf*, struct agent_connection*);
+int process_remove_all(struct sshbuf*, struct sshbuf*, struct agent_connection*);
+int process_authagent_request(struct sshbuf*, struct sshbuf*, struct agent_connection*);
+
+/* auth */
diff --git a/contrib/win32/win32compat/ssh-agent/agent.c b/contrib/win32/win32compat/ssh-agent/agent.c
new file mode 100644
index 000000000..62e625d98
--- /dev/null
+++ b/contrib/win32/win32compat/ssh-agent/agent.c
@@ -0,0 +1,266 @@
+/*
+ * Author: Manoj Ampalam
+ * ssh-agent implementation on Windows
+ *
+ * Copyright (c) 2015 Microsoft Corp.
+ * All rights reserved
+ *
+ * Microsoft openssh win32 port
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "agent.h"
+#include
+#include
+#define BUFSIZE 5 * 1024
+
+static HANDLE ioc_port = NULL;
+static BOOL debug_mode = FALSE;
+
+#define AGENT_PIPE_ID L"\\\\.\\pipe\\ssh-agent"
+
+static HANDLE event_stop_agent;
+static OVERLAPPED ol;
+static HANDLE pipe;
+static SECURITY_ATTRIBUTES sa;
+
+static int
+init_listener() {
+ {
+ if ((ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL) {
+ debug("cannot create event ERROR:%d", GetLastError());
+ return GetLastError();
+ }
+ pipe = INVALID_HANDLE_VALUE;
+ sa.bInheritHandle = FALSE;
+ if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(L"D:P(A;; GA;;; AU)", SDDL_REVISION_1,
+ &sa.lpSecurityDescriptor, &sa.nLength)) {
+ debug("cannot convert sddl ERROR:%d", GetLastError());
+ return GetLastError();
+ }
+ }
+
+ return 0;
+}
+
+static void
+agent_cleanup() {
+ {
+ if (ol.hEvent != NULL)
+ CloseHandle(ol.hEvent);
+ if (pipe != INVALID_HANDLE_VALUE)
+ CloseHandle(pipe);
+ }
+ if (ioc_port)
+ CloseHandle(ioc_port);
+ return;
+}
+
+static DWORD WINAPI
+iocp_work(LPVOID lpParam) {
+ DWORD bytes;
+ struct agent_connection* con = NULL;
+ OVERLAPPED *p_ol;
+ while (1) {
+ con = NULL;
+ p_ol = NULL;
+ if (GetQueuedCompletionStatus(ioc_port, &bytes, &(ULONG_PTR)con, &p_ol, INFINITE) == FALSE) {
+ debug("iocp error: %d on %p \n", GetLastError(), con);
+ if (con)
+ agent_connection_on_error(con, GetLastError());
+ else
+ return 0;
+ }
+ else
+ agent_connection_on_io(con, bytes, p_ol);
+
+ }
+}
+
+static void
+process_connection(HANDLE pipe) {
+ struct agent_connection* con;
+
+ if ((con = malloc(sizeof(struct agent_connection))) == NULL)
+ fatal("failed to alloc");
+
+ memset(con, 0, sizeof(struct agent_connection));
+ con->connection = pipe;
+ if (CreateIoCompletionPort(pipe, ioc_port, (ULONG_PTR)con, 0) != ioc_port)
+ fatal("failed to assign pipe to ioc_port");
+
+ agent_connection_on_io(con, 0, &con->ol);
+ iocp_work(NULL);
+}
+
+static void
+agent_listen_loop() {
+ DWORD r;
+ HANDLE wait_events[2];
+
+ wait_events[0] = event_stop_agent;
+
+ wait_events[1] = ol.hEvent;
+
+ while (1) {
+ {
+ {
+ pipe = CreateNamedPipeW(
+ AGENT_PIPE_ID, // pipe name
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
+ PIPE_TYPE_BYTE | // message type pipe
+ PIPE_READMODE_BYTE | // message-read mode
+ PIPE_WAIT, // blocking mode
+ PIPE_UNLIMITED_INSTANCES, // max. instances
+ BUFSIZE, // output buffer size
+ BUFSIZE, // input buffer size
+ 0, // client time-out
+ &sa);
+
+ if (pipe == INVALID_HANDLE_VALUE) {
+ verbose("cannot create listener pipe ERROR:%d", GetLastError());
+ SetEvent(event_stop_agent);
+ }
+ else if (ConnectNamedPipe(pipe, &ol) != FALSE) {
+ verbose("ConnectNamedPipe returned TRUE unexpectedly ");
+ SetEvent(event_stop_agent);
+ }
+
+ if (GetLastError() == ERROR_PIPE_CONNECTED) {
+ debug("Client has already connected");
+ SetEvent(ol.hEvent);
+ }
+
+ if (GetLastError() != ERROR_IO_PENDING) {
+ debug("ConnectNamedPipe failed ERROR: %d", GetLastError());
+ SetEvent(event_stop_agent);
+ }
+
+ }
+ }
+
+ r = WaitForMultipleObjects(2, wait_events, FALSE, INFINITE);
+ if (r == WAIT_OBJECT_0) {
+ //received signal to shutdown
+ debug("shutting down");
+ agent_cleanup();
+ return;
+ }
+ else if ((r > WAIT_OBJECT_0) && (r <= (WAIT_OBJECT_0 + 1))) {
+ /* process incoming connection */
+ HANDLE con = pipe;
+ DWORD client_pid = 0;
+ pipe = INVALID_HANDLE_VALUE;
+ GetNamedPipeClientProcessId(con, &client_pid);
+ verbose("client pid %d connected", client_pid);
+ if (debug_mode) {
+ process_connection(con);
+ agent_cleanup();
+ return;
+ }
+ else {
+ /* spawn a child to take care of this*/
+ wchar_t path[MAX_PATH], module_path[MAX_PATH];
+ PROCESS_INFORMATION pi;
+ STARTUPINFOW si;
+
+ si.cb = sizeof(STARTUPINFOW);
+ memset(&si, 0, sizeof(STARTUPINFOW));
+ GetModuleFileNameW(NULL, module_path, MAX_PATH);
+ SetHandleInformation(con, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
+ if ((swprintf_s(path, MAX_PATH, L"%s %d", module_path, (int)(intptr_t)con) == -1 ) ||
+ (CreateProcessW(NULL, path, NULL, NULL, TRUE,
+ DETACHED_PROCESS, NULL, NULL,
+ &si, &pi) == FALSE)) {
+ verbose("Failed to create child process %ls ERROR:%d", module_path, GetLastError());
+ }
+ else {
+ debug("spawned worker %d for agent client pid %d ", pi.dwProcessId, client_pid);
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ }
+ SetHandleInformation(con, HANDLE_FLAG_INHERIT, 0);
+ CloseHandle(con);
+ }
+
+ }
+ else {
+ fatal("wait on events ended with %d ERROR:%d", r, GetLastError());
+ }
+
+ }
+}
+
+void agent_cleanup_connection(struct agent_connection* con) {
+ debug("connection %p clean up", con);
+ CloseHandle(con->connection);
+ if (con->hProfile)
+ UnloadUserProfile(con->auth_token, con->hProfile);
+ if (con->auth_token)
+ CloseHandle(con->auth_token);
+ free(con);
+ CloseHandle(ioc_port);
+ ioc_port = NULL;
+}
+
+void agent_shutdown() {
+ verbose("shutdown");
+ SetEvent(event_stop_agent);
+}
+
+#define REG_AGENT_SDDL L"D:P(A;; GR;;; AU)(A;; GA;;; SY)(A;; GA;;; BA)"
+
+void
+agent_start(BOOL dbg_mode, BOOL child, HANDLE pipe) {
+ int r;
+ HKEY agent_root = NULL;
+ DWORD process_id = GetCurrentProcessId();
+
+ verbose("agent_start pid:%d, dbg:%d, child:%d, pipe:%d", process_id, dbg_mode, child, pipe);
+ debug_mode = dbg_mode;
+
+ if ((ioc_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, (ULONG_PTR)NULL, 0)) == NULL)
+ fatal("cannot create ioc port ERROR:%d", GetLastError());
+
+
+ if (child == FALSE) {
+ SECURITY_ATTRIBUTES sa;
+ memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
+ sa.nLength = sizeof(sa);
+ if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(REG_AGENT_SDDL, SDDL_REVISION_1, &sa.lpSecurityDescriptor, &sa.nLength))
+ fatal("ConvertStringSecurityDescriptorToSecurityDescriptorW failed");
+ if ((r = RegCreateKeyExW(HKEY_LOCAL_MACHINE, SSH_AGENT_ROOT, 0, 0, 0, KEY_WRITE, &sa, &agent_root, 0)) != ERROR_SUCCESS)
+ fatal("cannot create agent root reg key, ERROR:%d", r);
+ if ((r = RegSetValueExW(agent_root, L"ProcessID", 0, REG_DWORD, (BYTE*)&process_id, 4)) != ERROR_SUCCESS)
+ fatal("cannot publish agent master process id ERROR:%d", r);
+ if ((event_stop_agent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)
+ fatal("cannot create global stop event ERROR:%d", GetLastError());
+ if ((r = init_listener()) != 0)
+ fatal("failed to create server pipes ERROR:%d", r);
+ agent_listen_loop();
+ }
+ else { /* this is a child process that processes one connection */
+ process_connection(pipe);
+ }
+
+}
+
diff --git a/contrib/win32/win32compat/ssh-agent/agent.h b/contrib/win32/win32compat/ssh-agent/agent.h
new file mode 100644
index 000000000..36686ffea
--- /dev/null
+++ b/contrib/win32/win32compat/ssh-agent/agent.h
@@ -0,0 +1,48 @@
+#include
+#include
+#define MAX_MESSAGE_SIZE 256 * 1024
+
+#define SSH_ROOT L"SOFTWARE\\SSH"
+#define SSH_AGENT_ROOT SSH_ROOT L"\\Agent"
+#define SSH_KEYS_KEY L"Keys"
+#define SSH_KEYS_ROOT SSH_ROOT L"\\" SSH_KEYS_KEY
+
+#define HEADER_SIZE 4
+
+struct agent_connection {
+ OVERLAPPED ol;
+ HANDLE connection;
+ struct {
+ DWORD num_bytes;
+ DWORD transferred;
+ char buf[MAX_MESSAGE_SIZE];
+ DWORD buf_size;
+ } io_buf;
+ enum {
+ LISTENING = 0,
+ READING_HEADER,
+ READING,
+ WRITING,
+ DONE
+ } state;
+ enum {
+ UNKNOWN = 0,
+ OTHER,
+ LOCAL_SYSTEM,
+ SSHD,
+ NETWORK_SERVICE
+ } client_process;
+ HANDLE auth_token;
+ HANDLE hProfile;
+};
+
+void agent_connection_on_io(struct agent_connection*, DWORD, OVERLAPPED*);
+void agent_connection_on_error(struct agent_connection* , DWORD );
+void agent_connection_disconnect(struct agent_connection*);
+
+void agent_start(BOOL, BOOL, HANDLE);
+void agent_shutdown();
+void agent_cleanup_connection(struct agent_connection*);
+
+int load_config();
+int config_log_level();
\ No newline at end of file
diff --git a/contrib/win32/win32compat/ssh-agent/agentconfig.c b/contrib/win32/win32compat/ssh-agent/agentconfig.c
new file mode 100644
index 000000000..ec261be72
--- /dev/null
+++ b/contrib/win32/win32compat/ssh-agent/agentconfig.c
@@ -0,0 +1,132 @@
+#include "includes.h"
+
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#ifdef HAVE_UTIL_H
+#include
+#endif
+
+#include "openbsd-compat/sys-queue.h"
+#include "xmalloc.h"
+#include "ssh.h"
+#include "log.h"
+#include "buffer.h"
+#include "misc.h"
+#include "servconf.h"
+#include "compat.h"
+#include "pathnames.h"
+#include "cipher.h"
+#include "key.h"
+#include "kex.h"
+#include "mac.h"
+#include "match.h"
+#include "channels.h"
+#include "groupaccess.h"
+#include "canohost.h"
+#include "packet.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "myproposal.h"
+#include "digest.h"
+#include "agent.h"
+
+#include
+
+Buffer cfg;
+ServerOptions options;
+struct passwd *privsep_pw = NULL;
+static char *config_file_name = _PATH_SERVER_CONFIG_FILE;
+int auth_sock = -1;
+
+int auth2_methods_valid(const char * c, int i) {
+ return 1;
+}
+
+int
+mm_is_monitor(void) {
+ return 0;
+}
+
+int kexgex_server(struct ssh * sh) {
+ return -1;
+}
+
+static
+int GetCurrentModulePath(wchar_t *path, int pathSize)
+{
+ if (GetModuleFileNameW(NULL, path, pathSize)) {
+ int i;
+ int lastSlashPos = 0;
+
+ for (i = 0; path[i]; i++) {
+ if (path[i] == L'/' || path[i] == L'\\') {
+ lastSlashPos = i;
+ }
+ }
+
+ path[lastSlashPos] = 0;
+ return 0;
+ }
+ return -1;
+}
+
+int load_config() {
+ wchar_t basePath[MAX_PATH] = { 0 };
+ wchar_t path[MAX_PATH] = { 0 };
+
+ /* TODO - account for UNICODE paths*/
+ if (GetCurrentModulePath(basePath, MAX_PATH) == -1)
+ return -1;
+
+ wcsncpy(path, basePath, MAX_PATH);
+ wcsncat(path, L"/sshd_config", MAX_PATH);
+
+ if ((config_file_name = utf16_to_utf8(path)) == NULL)
+ return -1;
+
+ buffer_init(&cfg);
+ initialize_server_options(&options);
+ load_server_config(config_file_name, &cfg);
+ parse_server_config(&options, config_file_name, &cfg, NULL);
+ fill_default_server_options(&options);
+
+ return 0;
+}
+
+int config_log_level() {
+ return options.log_level;
+}
+
+int pubkey_allowed(struct sshkey* pubkey, wchar_t* wuser, wchar_t* wuser_home) {
+ struct passwd pw;
+ int ret;
+ char *user = NULL, *user_home = NULL;
+ memset(&pw, 0, sizeof(pw));
+
+ if ((user_home = utf16_to_utf8(wuser_home)) == NULL ||
+ (user = utf16_to_utf8(wuser)) == NULL)
+ return 0;
+
+ pw.pw_dir = user_home;
+ pw.pw_name = user;
+ ret = user_key_allowed(&pw, pubkey, 1);
+ free(user);
+ free(user_home);
+ return ret;
+}
\ No newline at end of file
diff --git a/contrib/win32/win32compat/ssh-agent/authagent-request.c b/contrib/win32/win32compat/ssh-agent/authagent-request.c
new file mode 100644
index 000000000..0cacbe602
--- /dev/null
+++ b/contrib/win32/win32compat/ssh-agent/authagent-request.c
@@ -0,0 +1,389 @@
+/*
+* Author: Manoj Ampalam
+* ssh-agent implementation on Windows
+*
+* Copyright (c) 2015 Microsoft Corp.
+* All rights reserved
+*
+* Microsoft openssh win32 port
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* 1. Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#define UMDF_USING_NTSTATUS
+#include
+#include
+#include
+#include
+#include
+#include "agent.h"
+#include "agent-request.h"
+#include "key.h"
+
+static void
+InitLsaString(LSA_STRING *lsa_string, const char *str)
+{
+ if (str == NULL)
+ memset(lsa_string, 0, sizeof(LSA_STRING));
+ else {
+ lsa_string->Buffer = (char *)str;
+ lsa_string->Length = strlen(str);
+ lsa_string->MaximumLength = lsa_string->Length + 1;
+ }
+}
+
+static void
+EnablePrivilege(const char *privName, int enabled)
+{
+ TOKEN_PRIVILEGES tp;
+ HANDLE hProcToken = NULL;
+ LUID luid;
+
+ int exitCode = 1;
+
+ if (LookupPrivilegeValueA(NULL, privName, &luid) == FALSE ||
+ OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hProcToken) == FALSE)
+ goto done;
+
+ tp.PrivilegeCount = 1;
+ tp.Privileges[0].Luid = luid;
+ tp.Privileges[0].Attributes = enabled ? SE_PRIVILEGE_ENABLED : 0;
+
+ AdjustTokenPrivileges(hProcToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
+
+done:
+ if (hProcToken)
+ CloseHandle(hProcToken);
+
+ return;
+}
+
+
+void
+LoadProfile(struct agent_connection* con, wchar_t* user, wchar_t* domain) {
+ PROFILEINFOW profileInfo;
+ profileInfo.dwFlags = PI_NOUI;
+ profileInfo.lpProfilePath = NULL;
+ profileInfo.lpUserName = user;
+ profileInfo.lpDefaultPath = NULL;
+ profileInfo.lpServerName = domain;
+ profileInfo.lpPolicyPath = NULL;
+ profileInfo.hProfile = NULL;
+ profileInfo.dwSize = sizeof(profileInfo);
+ EnablePrivilege("SeBackupPrivilege", 1);
+ EnablePrivilege("SeRestorePrivilege", 1);
+ if (LoadUserProfileW(con->auth_token, &profileInfo) == FALSE)
+ debug("Loading user (%ls,%ls) profile failed ERROR: %d", user, domain, GetLastError());
+ else
+ con->hProfile = profileInfo.hProfile;
+ EnablePrivilege("SeBackupPrivilege", 0);
+ EnablePrivilege("SeRestorePrivilege", 0);
+}
+
+#define MAX_USER_LEN 256
+static HANDLE
+generate_user_token(wchar_t* user) {
+ HANDLE lsa_handle = 0, token = 0;
+ LSA_OPERATIONAL_MODE mode;
+ ULONG auth_package_id;
+ NTSTATUS ret, subStatus;
+ void * logon_info = NULL;
+ size_t logon_info_size;
+ LSA_STRING logon_process_name, auth_package_name, originName;
+ TOKEN_SOURCE sourceContext;
+ PKERB_INTERACTIVE_PROFILE pProfile = NULL;
+ LUID logonId;
+ QUOTA_LIMITS quotas;
+ DWORD cbProfile;
+ BOOL domain_user;
+ wchar_t user_copy[MAX_USER_LEN];
+
+ /* prep user name - TODO: implment an accurate check if user is domain account*/
+ if (wcsnlen(user, MAX_USER_LEN) == MAX_USER_LEN) {
+ debug("user length is not supported");
+ goto done;
+ }
+
+ if (wcschr(user, L'\\') != NULL) {
+ wchar_t *un = NULL, *dn = NULL;
+ DWORD un_len = 0, dn_len = 0;
+ dn = user;
+ dn_len = wcschr(user, L'\\') - user;
+ un = wcschr(user, L'\\') + 1;
+ un_len = wcsnlen(user, MAX_USER_LEN) - dn_len - 1;
+ if (dn_len == 0 || un_len == 0) {
+ debug("cannot get user token - bad user name");
+ goto done;
+ }
+ memcpy(user_copy, un, un_len * sizeof(wchar_t));
+ user_copy[un_len] = L'@';
+ memcpy(user_copy + un_len + 1, dn, dn_len * sizeof(wchar_t));
+ user_copy[dn_len + 1 + un_len] = L'\0';
+ user = user_copy;
+ }
+
+ domain_user = (wcschr(user, L'@') != NULL) ? TRUE : FALSE;
+
+ InitLsaString(&logon_process_name, "ssh-agent");
+ if (domain_user)
+ InitLsaString(&auth_package_name, MICROSOFT_KERBEROS_NAME_A);
+ else
+ InitLsaString(&auth_package_name, "SSH-LSA");
+
+ InitLsaString(&originName, "sshd");
+ if (ret = LsaRegisterLogonProcess(&logon_process_name, &lsa_handle, &mode) != STATUS_SUCCESS)
+ goto done;
+
+ if (ret = LsaLookupAuthenticationPackage(lsa_handle, &auth_package_name, &auth_package_id) != STATUS_SUCCESS)
+ goto done;
+
+ if (domain_user) {
+ KERB_S4U_LOGON *s4u_logon;
+ logon_info_size = sizeof(KERB_S4U_LOGON);
+ logon_info_size += (wcslen(user) * 2 + 2);
+ logon_info = malloc(logon_info_size);
+ if (logon_info == NULL)
+ goto done;
+ s4u_logon = (KERB_S4U_LOGON*)logon_info;
+ s4u_logon->MessageType = KerbS4ULogon;
+ s4u_logon->Flags = 0;
+ s4u_logon->ClientUpn.Length = wcslen(user) * 2;
+ s4u_logon->ClientUpn.MaximumLength = s4u_logon->ClientUpn.Length;
+ s4u_logon->ClientUpn.Buffer = (WCHAR*)(s4u_logon + 1);
+ memcpy(s4u_logon->ClientUpn.Buffer, user, s4u_logon->ClientUpn.Length + 2);
+ s4u_logon->ClientRealm.Length = 0;
+ s4u_logon->ClientRealm.MaximumLength = 0;
+ s4u_logon->ClientRealm.Buffer = 0;
+ }
+ else {
+ logon_info_size = (wcslen(user) + 1)*sizeof(wchar_t);
+ logon_info = malloc(logon_info_size);
+ if (logon_info == NULL)
+ goto done;
+ memcpy(logon_info, user, logon_info_size);
+ }
+
+ memcpy(sourceContext.SourceName,"sshagent", sizeof(sourceContext.SourceName));
+
+ if (AllocateLocallyUniqueId(&sourceContext.SourceIdentifier) != TRUE)
+ goto done;
+
+ if (ret = LsaLogonUser(lsa_handle,
+ &originName,
+ Network,
+ auth_package_id,
+ logon_info,
+ logon_info_size,
+ NULL,
+ &sourceContext,
+ (PVOID*)&pProfile,
+ &cbProfile,
+ &logonId,
+ &token,
+ "as,
+ &subStatus) != STATUS_SUCCESS) {
+ debug("LsaLogonUser failed %d", ret);
+ goto done;
+ }
+ debug3("LsaLogonUser succeeded");
+done:
+ if (lsa_handle)
+ LsaDeregisterLogonProcess(lsa_handle);
+ if (logon_info)
+ free(logon_info);
+ if (pProfile)
+ LsaFreeReturnBuffer(pProfile);
+
+ return token;
+}
+
+#define PUBKEY_AUTH_REQUEST "pubkey"
+#define PASSWD_AUTH_REQUEST "password"
+#define MAX_USER_NAME_LEN 256
+#define MAX_PW_LEN 128
+
+int process_passwordauth_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
+ char *user = NULL, *pwd = NULL;
+ wchar_t userW_buf[MAX_USER_NAME_LEN], pwdW_buf[MAX_PW_LEN];
+ wchar_t *userW = userW_buf, *domW = NULL, *pwdW = pwdW_buf, *tmp;
+ size_t user_len = 0, pwd_len = 0, dom_len = 0;
+ int r = -1;
+ HANDLE token = 0, dup_token, client_proc = 0;
+ ULONG client_pid;
+
+ if (sshbuf_get_cstring(request, &user, &user_len) != 0 ||
+ sshbuf_get_cstring(request, &pwd, &pwd_len) != 0 ||
+ user_len == 0 ||
+ pwd_len == 0 ){
+ debug("bad password auth request");
+ goto done;
+ }
+
+ userW[0] = L'\0';
+ if (MultiByteToWideChar(CP_UTF8, 0, user, user_len + 1, userW, MAX_USER_NAME_LEN) == 0 ||
+ MultiByteToWideChar(CP_UTF8, 0, pwd, pwd_len + 1, pwdW, MAX_PW_LEN) == 0) {
+ debug("unable to convert user (%s) or password to UTF-16", user);
+ goto done;
+ }
+
+ if ((tmp = wcschr(userW, L'\\')) != NULL) {
+ domW = userW;
+ userW = tmp + 1;
+ *tmp = L'\0';
+
+ }
+ else if ((tmp = wcschr(userW, L'@')) != NULL) {
+ domW = tmp + 1;
+ *tmp = L'\0';
+ }
+
+ if (LogonUserW(userW, domW, pwdW, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &token) == FALSE) {
+ debug("failed to logon user");
+ goto done;
+ }
+
+ if ((FALSE == GetNamedPipeClientProcessId(con->connection, &client_pid)) ||
+ ((client_proc = OpenProcess(PROCESS_DUP_HANDLE, FALSE, client_pid)) == NULL) ||
+ (FALSE == DuplicateHandle(GetCurrentProcess(), token, client_proc, &dup_token, TOKEN_QUERY | TOKEN_IMPERSONATE, FALSE, DUPLICATE_SAME_ACCESS)) ||
+ (sshbuf_put_u32(response, (int)(intptr_t)dup_token) != 0)) {
+ debug("failed to duplicate user token");
+ goto done;
+ }
+
+ con->auth_token = token;
+ LoadProfile(con, userW, domW);
+ r = 0;
+done:
+ /* TODO Fix this hacky protocol*/
+ if ((r == -1) && (sshbuf_put_u8(response, SSH_AGENT_FAILURE) == 0))
+ r = 0;
+
+ if (user)
+ free(user);
+ if (pwd)
+ free(pwd);
+ if (client_proc)
+ CloseHandle(client_proc);
+
+ return r;
+}
+
+int process_pubkeyauth_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
+ int r = -1;
+ char *key_blob, *user, *sig, *blob;
+ size_t key_blob_len, user_len, sig_len, blob_len;
+ struct sshkey *key = NULL;
+ HANDLE token = NULL, dup_token = NULL, client_proc = NULL;
+ wchar_t wuser[MAX_USER_NAME_LEN];
+ PWSTR wuser_home = NULL;
+ ULONG client_pid;
+
+ user = NULL;
+ if (sshbuf_get_string_direct(request, &key_blob, &key_blob_len) != 0 ||
+ sshbuf_get_cstring(request, &user, &user_len) != 0 ||
+ sshbuf_get_string_direct(request, &sig, &sig_len) != 0 ||
+ sshbuf_get_string_direct(request, &blob, &blob_len) != 0 ||
+ sshkey_from_blob(key_blob, key_blob_len, &key) != 0) {
+ debug("invalid pubkey auth request");
+ goto done;
+ }
+
+ wuser[0] = L'\0';
+ if (MultiByteToWideChar(CP_UTF8, 0, user, user_len + 1, wuser, MAX_USER_NAME_LEN) == 0 ||
+ (token = generate_user_token(wuser)) == 0) {
+ debug("unable to generate token for user %ls", wuser);
+ goto done;
+ }
+
+ con->auth_token = token;
+
+ if (SHGetKnownFolderPath(&FOLDERID_Profile, 0, token, &wuser_home) != S_OK ||
+ pubkey_allowed(key, wuser, wuser_home) != 1) {
+ debug("given public key is not mapped to user %ls (profile:%ls)", wuser, wuser_home);
+ goto done;
+ }
+
+ if (key_verify(key, sig, sig_len, blob, blob_len) != 1) {
+ debug("signature verification failed");
+ goto done;
+ }
+
+ if ((FALSE == GetNamedPipeClientProcessId(con->connection, &client_pid)) ||
+ ( (client_proc = OpenProcess(PROCESS_DUP_HANDLE, FALSE, client_pid)) == NULL) ||
+ (FALSE == DuplicateHandle(GetCurrentProcess(), token, client_proc, &dup_token, TOKEN_QUERY | TOKEN_IMPERSONATE, FALSE, DUPLICATE_SAME_ACCESS)) ||
+ (sshbuf_put_u32(response, (int)(intptr_t)dup_token) != 0) ) {
+ debug("failed to authorize user");
+ goto done;
+ }
+
+ {
+ wchar_t *tmp, *userW, *domW;
+ userW = wuser;
+ domW = NULL;
+ if ((tmp = wcschr(userW, L'\\')) != NULL) {
+ domW = userW;
+ userW = tmp + 1;
+ *tmp = L'\0';
+
+ }
+ else if ((tmp = wcschr(userW, L'@')) != NULL) {
+ domW = tmp + 1;
+ *tmp = L'\0';
+ }
+ LoadProfile(con, userW, domW);
+ }
+
+ r = 0;
+done:
+ /* TODO Fix this hacky protocol*/
+ if ((r == -1) && (sshbuf_put_u8(response, SSH_AGENT_FAILURE) == 0))
+ r = 0;
+
+ if (user)
+ free(user);
+ if (key)
+ sshkey_free(key);
+ if (wuser_home)
+ CoTaskMemFree(wuser_home);
+ if (client_proc)
+ CloseHandle(client_proc);
+ return r;
+}
+
+int process_authagent_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
+ char *opn;
+ size_t opn_len;
+ if (sshbuf_get_string_direct(request, &opn, &opn_len) != 0) {
+ debug("invalid auth request");
+ return -1;
+ }
+
+ if (opn_len == strlen(PUBKEY_AUTH_REQUEST) && memcmp(opn, PUBKEY_AUTH_REQUEST, opn_len) == 0)
+ return process_pubkeyauth_request(request, response, con);
+ else if (opn_len == strlen(PASSWD_AUTH_REQUEST) && memcmp(opn, PASSWD_AUTH_REQUEST, opn_len) == 0)
+ return process_passwordauth_request(request, response, con);
+ else {
+ debug("unknown auth request: %s", opn);
+ return -1;
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/win32/win32compat/ssh-agent/connection.c b/contrib/win32/win32compat/ssh-agent/connection.c
new file mode 100644
index 000000000..b45a00522
--- /dev/null
+++ b/contrib/win32/win32compat/ssh-agent/connection.c
@@ -0,0 +1,236 @@
+/*
+ * Author: Manoj Ampalam
+ * ssh-agent implementation on Windows
+ *
+ * Copyright (c) 2015 Microsoft Corp.
+ * All rights reserved
+ *
+ * Microsoft openssh win32 port
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "agent.h"
+#include "agent-request.h"
+
+int process_request(struct agent_connection*);
+
+#define ABORT_CONNECTION_RETURN(c) do { \
+ c->state = DONE; \
+ agent_cleanup_connection(c); \
+ return; \
+} while (0)
+
+void agent_connection_on_error(struct agent_connection* con, DWORD error) {
+ ABORT_CONNECTION_RETURN(con);
+}
+
+void agent_connection_on_io(struct agent_connection* con, DWORD bytes, OVERLAPPED* ol) {
+
+ /* process error */
+ debug3("connection io %p #bytes:%d state:%d", con, bytes, con->state);
+ if ((bytes == 0) && (GetOverlappedResult(con->connection, ol, &bytes, FALSE) == FALSE))
+ ABORT_CONNECTION_RETURN(con);
+
+ if (con->state == DONE)
+ DebugBreak();
+
+ {
+ switch (con->state) {
+ case LISTENING:
+ case WRITING:
+ /* Writing is done, read next request */
+ /* assert on assumption that write always completes on sending all bytes*/
+ if (bytes != con->io_buf.num_bytes)
+ DebugBreak();
+ con->state = READING_HEADER;
+ ZeroMemory(&con->io_buf, sizeof(con->io_buf));
+ if (!ReadFile(con->connection, con->io_buf.buf,
+ HEADER_SIZE, NULL, &con->ol) && (GetLastError() != ERROR_IO_PENDING))
+ ABORT_CONNECTION_RETURN(con);
+ break;
+ case READING_HEADER:
+ con->io_buf.transferred += bytes;
+ if (con->io_buf.transferred == HEADER_SIZE) {
+ con->io_buf.num_bytes = PEEK_U32(con->io_buf.buf);
+ con->io_buf.transferred = 0;
+ if (con->io_buf.num_bytes > MAX_MESSAGE_SIZE)
+ ABORT_CONNECTION_RETURN(con);
+
+ con->state = READING;
+ if (!ReadFile(con->connection, con->io_buf.buf,
+ con->io_buf.num_bytes, NULL, &con->ol)&&(GetLastError() != ERROR_IO_PENDING))
+ ABORT_CONNECTION_RETURN(con);
+ }
+ else {
+ if (!ReadFile(con->connection, con->io_buf.buf + con->io_buf.num_bytes,
+ HEADER_SIZE - con->io_buf.num_bytes, NULL, &con->ol)&& (GetLastError() != ERROR_IO_PENDING))
+ ABORT_CONNECTION_RETURN(con);
+ }
+ break;
+ case READING:
+ con->io_buf.transferred += bytes;
+ if (con->io_buf.transferred == con->io_buf.num_bytes) {
+ if (process_request(con) != 0) {
+ ABORT_CONNECTION_RETURN(con);
+ }
+ con->state = WRITING;
+ if (!WriteFile(con->connection, con->io_buf.buf,
+ con->io_buf.num_bytes, NULL, &con->ol)&& (GetLastError() != ERROR_IO_PENDING) )
+ ABORT_CONNECTION_RETURN(con);
+ }
+ else {
+ if (!ReadFile(con->connection, con->io_buf.buf + con->io_buf.transferred,
+ con->io_buf.num_bytes - con->io_buf.transferred, NULL, &con->ol)&& (GetLastError() != ERROR_IO_PENDING))
+ ABORT_CONNECTION_RETURN(con);
+ }
+ break;
+ default:
+ DebugBreak();
+ }
+ }
+}
+
+void agent_connection_disconnect(struct agent_connection* con) {
+ CancelIoEx(con->connection, NULL);
+ DisconnectNamedPipe(con->connection);
+}
+
+static int
+get_con_client_type(HANDLE pipe) {
+ int r = -1;
+ wchar_t *sshd_act = L"NT SERVICE\\SSHD", *ref_dom = NULL;
+ PSID sshd_sid = NULL;
+ char system_sid[SECURITY_MAX_SID_SIZE];
+ char ns_sid[SECURITY_MAX_SID_SIZE];
+ DWORD sshd_sid_len = 0, reg_dom_len = 0, info_len = 0, sid_size;
+ SID_NAME_USE nuse;
+ HANDLE token;
+ TOKEN_USER* info = NULL;
+
+ if (ImpersonateNamedPipeClient(pipe) == FALSE)
+ return -1;
+
+ if (LookupAccountNameW(NULL, sshd_act, NULL, &sshd_sid_len, NULL, ®_dom_len, &nuse) == TRUE ||
+ (sshd_sid = malloc(sshd_sid_len)) == NULL ||
+ (ref_dom = (wchar_t*)malloc(reg_dom_len * 2)) == NULL ||
+ LookupAccountNameW(NULL, sshd_act, sshd_sid, &sshd_sid_len, ref_dom, ®_dom_len, &nuse) == FALSE ||
+ OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &token) == FALSE ||
+ GetTokenInformation(token, TokenUser, NULL, 0, &info_len) == TRUE ||
+ (info = (TOKEN_USER*)malloc(info_len)) == NULL ||
+ GetTokenInformation(token, TokenUser, info, info_len, &info_len) == FALSE)
+ goto done;
+
+ sid_size = SECURITY_MAX_SID_SIZE;
+ if (CreateWellKnownSid(WinLocalSystemSid, NULL, system_sid, &sid_size) == FALSE)
+ goto done;
+ sid_size = SECURITY_MAX_SID_SIZE;
+ if (CreateWellKnownSid(WinNetworkServiceSid, NULL, ns_sid, &sid_size) == FALSE)
+ goto done;
+
+ if (EqualSid(info->User.Sid, system_sid))
+ r = LOCAL_SYSTEM;
+ else if (EqualSid(info->User.Sid, sshd_sid))
+ r = SSHD;
+ else if (EqualSid(info->User.Sid, ns_sid))
+ r = NETWORK_SERVICE;
+ else
+ r = OTHER;
+
+ debug2("client type: %d", r);
+done:
+ if (sshd_sid)
+ free(sshd_sid);
+ if (ref_dom)
+ free(ref_dom);
+ if (info)
+ free(info);
+ RevertToSelf();
+ return r;
+}
+
+/* TODO - move this to common header*/
+#define SSH_AGENT_AUTHENTICATE 100
+
+static int
+process_request(struct agent_connection* con) {
+ int r = -1;
+ struct sshbuf *request = NULL, *response = NULL;
+
+ if (con->client_process == UNKNOWN)
+ if ((con->client_process = get_con_client_type(con->connection)) == -1)
+ goto done;
+
+
+ request = sshbuf_from(con->io_buf.buf, con->io_buf.num_bytes);
+ response = sshbuf_new();
+ if ((request == NULL) || (response == NULL))
+ goto done;
+
+ {
+ u_char type;
+
+ if (sshbuf_get_u8(request, &type) != 0)
+ return -1;
+ debug("process agent request type %d", type);
+
+ switch (type) {
+ case SSH2_AGENTC_ADD_IDENTITY:
+ r = process_add_identity(request, response, con);
+ break;
+ case SSH2_AGENTC_REQUEST_IDENTITIES:
+ r = process_request_identities(request, response, con);
+ break;
+ case SSH2_AGENTC_SIGN_REQUEST:
+ r = process_sign_request(request, response, con);
+ break;
+ case SSH2_AGENTC_REMOVE_IDENTITY:
+ r = process_remove_key(request, response, con);
+ break;
+ case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
+ r = process_remove_all(request, response, con);
+ break;
+ case SSH_AGENT_AUTHENTICATE:
+ r = process_authagent_request(request, response, con);
+ break;
+ default:
+ debug("unknown agent request %d", type);
+ r = -1;
+ break;
+ }
+ }
+
+done:
+ if (request)
+ sshbuf_free(request);
+
+ ZeroMemory(&con->io_buf, sizeof(con->io_buf));
+ if (r == 0) {
+ POKE_U32(con->io_buf.buf, sshbuf_len(response));
+ memcpy(con->io_buf.buf + 4, sshbuf_ptr(response), sshbuf_len(response));
+ con->io_buf.num_bytes = sshbuf_len(response) + 4;
+ }
+
+ if (response)
+ sshbuf_free(response);
+
+ return r;
+}
\ No newline at end of file
diff --git a/contrib/win32/win32compat/ssh-agent/keyagent-request.c b/contrib/win32/win32compat/ssh-agent/keyagent-request.c
new file mode 100644
index 000000000..08225ac27
--- /dev/null
+++ b/contrib/win32/win32compat/ssh-agent/keyagent-request.c
@@ -0,0 +1,438 @@
+/*
+ * Author: Manoj Ampalam
+ * ssh-agent implementation on Windows
+ *
+ * Copyright (c) 2015 Microsoft Corp.
+ * All rights reserved
+ *
+ * Microsoft openssh win32 port
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "agent.h"
+#include "agent-request.h"
+#include
+
+#define MAX_KEY_LENGTH 255
+#define MAX_VALUE_NAME 16383
+
+static int
+get_user_root(struct agent_connection* con, HKEY *root){
+ int r = 0;
+ *root = NULL;
+ if (ImpersonateNamedPipeClient(con->connection) == FALSE)
+ return -1;
+
+ if (con->client_process > OTHER)
+ *root = HKEY_LOCAL_MACHINE;
+ else if (RegOpenCurrentUser(KEY_ALL_ACCESS, root) != ERROR_SUCCESS)
+ r = -1;
+
+ if (*root == NULL)
+ debug("cannot connect to user's registry root");
+ RevertToSelf();
+ return r;
+}
+
+static int
+convert_blob(struct agent_connection* con, const char *blob, DWORD blen, char **eblob, DWORD *eblen, int encrypt) {
+ int success = 0;
+ DATA_BLOB in, out;
+
+ if (con->client_process == OTHER)
+ if (ImpersonateNamedPipeClient(con->connection) == FALSE)
+ return -1;
+
+ in.cbData = blen;
+ in.pbData = (char*)blob;
+ out.cbData = 0;
+ out.pbData = NULL;
+
+ if (encrypt) {
+ if (!CryptProtectData(&in, NULL, NULL, 0, NULL, 0, &out)) {
+ debug("cannot encrypt data");
+ goto done;
+ }
+ }
+ else {
+ if (!CryptUnprotectData(&in, NULL, NULL, 0, NULL, 0, &out)) {
+ debug("cannot decrypt data");
+ goto done;
+ }
+ }
+
+ *eblob = malloc(out.cbData);
+ if (*eblob == NULL)
+ goto done;
+
+ memcpy(*eblob, out.pbData, out.cbData);
+ *eblen = out.cbData;
+ success = 1;
+done:
+ if (out.pbData)
+ LocalFree(out.pbData);
+ if (con->client_process == OTHER)
+ RevertToSelf();
+ return success? 0: -1;
+}
+
+#define REG_KEY_SDDL L"D:P(A;; GA;;; SY)(A;; GA;;; BA)"
+
+int
+process_add_identity(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
+ struct sshkey* key = NULL;
+ int r = 0, blob_len, eblob_len, request_invalid = 0, success = 0;
+ size_t comment_len, pubkey_blob_len;
+ u_char *pubkey_blob = NULL;
+ char *thumbprint = NULL, *comment;
+ const char *blob;
+ char* eblob = NULL;
+ HKEY reg = 0, sub = 0, user_root = 0;
+ SECURITY_ATTRIBUTES sa;
+
+ /* parse input request */
+ blob = sshbuf_ptr(request);
+ if (sshkey_private_deserialize(request, &key) != 0 ||
+ (blob_len = (sshbuf_ptr(request) - blob) & 0xffffffff) == 0 ||
+ sshbuf_peek_string_direct(request, &comment, &comment_len) != 0) {
+ debug("key add request is invalid");
+ request_invalid = 1;
+ goto done;
+ }
+
+ memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
+ sa.nLength = sizeof(sa);
+ if ((!ConvertStringSecurityDescriptorToSecurityDescriptorW(REG_KEY_SDDL, SDDL_REVISION_1, &sa.lpSecurityDescriptor, &sa.nLength)) ||
+ sshkey_to_blob(key, &pubkey_blob, &pubkey_blob_len) != 0 ||
+ convert_blob(con, blob, blob_len, &eblob, &eblob_len, 1) != 0 ||
+ ((thumbprint = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) ||
+ get_user_root(con, &user_root) != 0 ||
+ RegCreateKeyExW(user_root, SSH_KEYS_ROOT, 0, 0, 0, KEY_WRITE | KEY_WOW64_64KEY, &sa, ®, NULL) != 0 ||
+ RegCreateKeyExA(reg, thumbprint, 0, 0, 0, KEY_WRITE | KEY_WOW64_64KEY, &sa, &sub, NULL) != 0 ||
+ RegSetValueExW(sub, NULL, 0, REG_BINARY, eblob, eblob_len) != 0 ||
+ RegSetValueExW(sub, L"pub", 0, REG_BINARY, pubkey_blob, pubkey_blob_len) != 0 ||
+ RegSetValueExW(sub, L"type", 0, REG_DWORD, (BYTE*)&key->type, 4) != 0 ||
+ RegSetValueExW(sub, L"comment", 0, REG_BINARY, comment, comment_len) != 0 ) {
+ debug("failed to add key to store");
+ goto done;
+ }
+
+ debug("added key to store");
+ success = 1;
+done:
+ r = 0;
+ if (request_invalid)
+ r = -1;
+ else if (sshbuf_put_u8(response, success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE) != 0)
+ r = -1;
+
+ /* delete created reg key if not succeeded*/
+ if ((success == 0) && reg && thumbprint)
+ RegDeleteKeyExA(reg, thumbprint, KEY_WOW64_64KEY, 0);
+
+ if (eblob)
+ free(eblob);
+ if (sa.lpSecurityDescriptor)
+ LocalFree(sa.lpSecurityDescriptor);
+ if (key)
+ sshkey_free(key);
+ if (thumbprint)
+ free(thumbprint);
+ if (user_root)
+ RegCloseKey(user_root);
+ if (reg)
+ RegCloseKey(reg);
+ if (sub)
+ RegCloseKey(sub);
+ if (pubkey_blob)
+ free(pubkey_blob);
+ return r;
+}
+
+static int sign_blob(const struct sshkey *pubkey, u_char ** sig, size_t *siglen,
+ const u_char *blob, size_t blen, u_int flags, struct agent_connection* con) {
+ HKEY reg = 0, sub = 0, user_root = 0;
+ int r = 0, success = 0;
+ struct sshkey* prikey = NULL;
+ char *thumbprint = NULL, *regdata = NULL;
+ DWORD regdatalen = 0, keyblob_len = 0;
+ struct sshbuf* tmpbuf = NULL;
+ char *keyblob = NULL;
+
+ *sig = NULL;
+ *siglen = 0;
+
+ if ((thumbprint = sshkey_fingerprint(pubkey, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL ||
+ get_user_root(con, &user_root) != 0 ||
+ RegOpenKeyExW(user_root, SSH_KEYS_ROOT,
+ 0, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_WOW64_64KEY | KEY_ENUMERATE_SUB_KEYS, ®) != 0 ||
+ RegOpenKeyExA(reg, thumbprint, 0,
+ STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY, &sub) != 0 ||
+ RegQueryValueExW(sub, NULL, 0, NULL, NULL, ®datalen) != ERROR_SUCCESS ||
+ (regdata = malloc(regdatalen)) == NULL ||
+ RegQueryValueExW(sub, NULL, 0, NULL, regdata, ®datalen) != ERROR_SUCCESS ||
+ convert_blob(con, regdata, regdatalen, &keyblob, &keyblob_len, FALSE) != 0 ||
+ (tmpbuf = sshbuf_from(keyblob, keyblob_len)) == NULL)
+ goto done;
+
+ if (sshkey_private_deserialize(tmpbuf, &prikey) != 0 ||
+ sshkey_sign(prikey, sig, siglen, blob, blen, NULL, 0) != 0) {
+ debug("cannot sign using retrieved key");
+ goto done;
+ }
+
+ success = 1;
+
+done:
+ if (keyblob)
+ free(keyblob);
+ if (regdata)
+ free(regdata);
+ if (tmpbuf)
+ sshbuf_free(tmpbuf);
+ if (prikey)
+ sshkey_free(prikey);
+ if (thumbprint)
+ free(thumbprint);
+ if (user_root)
+ RegCloseKey(user_root);
+ if (reg)
+ RegCloseKey(reg);
+ if (sub)
+ RegCloseKey(sub);
+
+ return success ? 0 : -1;
+}
+
+int
+process_sign_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
+ u_char *blob, *data, *signature = NULL;
+ size_t blen, dlen, slen = 0;
+ u_int flags = 0;
+ int r, request_invalid = 0, success = 0;
+ struct sshkey *key = NULL;
+
+ if (sshbuf_get_string_direct(request, &blob, &blen) != 0 ||
+ sshbuf_get_string_direct(request, &data, &dlen) != 0 ||
+ sshbuf_get_u32(request, &flags) != 0 ||
+ sshkey_from_blob(blob, blen, &key) != 0) {
+ debug("sign request is invalid");
+ request_invalid = 1;
+ goto done;
+ }
+
+ /* TODO - flags?*/
+
+ if (sign_blob(key, &signature, &slen, data, dlen, 0, con) != 0)
+ goto done;
+
+ success = 1;
+done:
+ r = 0;
+ if (request_invalid)
+ r = -1;
+ else {
+ if (success) {
+ if (sshbuf_put_u8(response, SSH2_AGENT_SIGN_RESPONSE) != 0 ||
+ sshbuf_put_string(response, signature, slen) != 0) {
+ r = -1;
+ }
+ }
+ else
+ if (sshbuf_put_u8(response, SSH_AGENT_FAILURE) != 0)
+ r = -1;
+ }
+
+ if (key)
+ sshkey_free(key);
+ if (signature)
+ free(signature);
+ return r;
+}
+
+int
+process_remove_key(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
+ HKEY user_root = 0, root = 0;
+ char *blob, *thumbprint = NULL;
+ size_t blen;
+ int r = 0, success = 0, request_invalid = 0;
+ struct sshkey *key = NULL;
+
+ if (sshbuf_get_string_direct(request, &blob, &blen) != 0 ||
+ sshkey_from_blob(blob, blen, &key) != 0) {
+ request_invalid = 1;
+ goto done;
+ }
+
+ if ((thumbprint = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL ||
+ get_user_root(con, &user_root) != 0 ||
+ RegOpenKeyExW(user_root, SSH_KEYS_ROOT, 0,
+ DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE | KEY_WOW64_64KEY, &root) != 0 ||
+ RegDeleteTreeA(root, thumbprint) != 0)
+ goto done;
+ success = 1;
+done:
+ r = 0;
+ if (request_invalid)
+ r = -1;
+ else if (sshbuf_put_u8(response, success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE) != 0)
+ r = -1;
+
+ if (key)
+ sshkey_free(key);
+ if (user_root)
+ RegCloseKey(user_root);
+ if (root)
+ RegCloseKey(root);
+ if (thumbprint)
+ free(thumbprint);
+ return r;
+}
+int
+process_remove_all(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
+ HKEY user_root = 0, root = 0;
+ int r = 0;
+
+ if (get_user_root(con, &user_root) != 0 ||
+ RegOpenKeyExW(user_root, SSH_ROOT, 0,
+ DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE | KEY_WOW64_64KEY, &root) != 0) {
+ goto done;
+ }
+
+ RegDeleteTreeW(root, SSH_KEYS_KEY);
+done:
+ r = 0;
+ if (sshbuf_put_u8(response, SSH_AGENT_SUCCESS) != 0)
+ r = -1;
+
+ if (user_root)
+ RegCloseKey(user_root);
+ if (root)
+ RegCloseKey(root);
+ return r;
+}
+
+int
+process_request_identities(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
+ int count = 0, index = 0, success = 0, r = 0;
+ HKEY root = NULL, sub = NULL, user_root = 0;
+ char* count_ptr = NULL;
+ wchar_t sub_name[MAX_KEY_LENGTH];
+ DWORD sub_name_len = MAX_KEY_LENGTH;
+ char *pkblob = NULL, *comment = NULL;
+ DWORD regdatalen = 0, commentlen = 0, key_count = 0;
+ struct sshbuf* identities;
+
+ if ((identities = sshbuf_new()) == NULL)
+ goto done;
+
+ if ( get_user_root(con, &user_root) != 0 ||
+ RegOpenKeyExW(user_root, SSH_KEYS_ROOT, 0, STANDARD_RIGHTS_READ | KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY, &root) != 0) {
+ success = 1;
+ goto done;
+ }
+
+ while (1) {
+ sub_name_len = MAX_KEY_LENGTH;
+ if (sub) {
+ RegCloseKey(sub);
+ sub = NULL;
+ }
+ if (RegEnumKeyExW(root, index++, sub_name, &sub_name_len, NULL, NULL, NULL, NULL) == 0) {
+ if (RegOpenKeyExW(root, sub_name, 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &sub) == 0 &&
+ RegQueryValueExW(sub, L"pub", 0, NULL, NULL, ®datalen) == 0 &&
+ RegQueryValueExW(sub, L"comment", 0, NULL, NULL, &commentlen) == 0) {
+ if (pkblob)
+ free(pkblob);
+ if (comment)
+ free(comment);
+ pkblob = NULL;
+ comment = NULL;
+
+ if ((pkblob = malloc(regdatalen)) == NULL ||
+ (comment = malloc(commentlen)) == NULL ||
+ RegQueryValueExW(sub, L"pub", 0, NULL, pkblob, ®datalen) != 0 ||
+ RegQueryValueExW(sub, L"comment", 0, NULL, comment, &commentlen) != 0 ||
+ sshbuf_put_string(identities, pkblob, regdatalen) != 0 ||
+ sshbuf_put_string(identities, comment, commentlen) != 0)
+ goto done;
+
+ key_count++;
+ }
+ }
+ else
+ break;
+
+ }
+
+ success = 1;
+done:
+ r = 0;
+ if (success) {
+ if (sshbuf_put_u8(response, SSH2_AGENT_IDENTITIES_ANSWER) != 0 ||
+ sshbuf_put_u32(response, key_count) != 0 ||
+ sshbuf_putb(response, identities) != 0)
+ goto done;
+ }
+ else
+ r = -1;
+
+ if (pkblob)
+ free(pkblob);
+ if (comment)
+ free(comment);
+ if (identities)
+ sshbuf_free(identities);
+ if (user_root)
+ RegCloseKey(user_root);
+ if (root)
+ RegCloseKey(root);
+ if (sub)
+ RegCloseKey(sub);
+ return r;
+}
+
+
+int process_keyagent_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
+ u_char type;
+
+ if (sshbuf_get_u8(request, &type) != 0)
+ return -1;
+ debug2("process key agent request type %d", type);
+
+ switch (type) {
+ case SSH2_AGENTC_ADD_IDENTITY:
+ return process_add_identity(request, response, con);
+ case SSH2_AGENTC_REQUEST_IDENTITIES:
+ return process_request_identities(request, response, con);
+ case SSH2_AGENTC_SIGN_REQUEST:
+ return process_sign_request(request, response, con);
+ case SSH2_AGENTC_REMOVE_IDENTITY:
+ return process_remove_key(request, response, con);
+ case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
+ return process_remove_all(request, response, con);
+ default:
+ debug("unknown key agent request %d", type);
+ return -1;
+ }
+}
\ No newline at end of file
diff --git a/contrib/win32/win32compat/ssh_config/ssh_config b/contrib/win32/win32compat/ssh_config/ssh_config
new file mode 100644
index 000000000..42d6699b1
--- /dev/null
+++ b/contrib/win32/win32compat/ssh_config/ssh_config
@@ -0,0 +1,50 @@
+# $OpenBSD: ssh_config,v 1.26 2010/01/11 01:39:46 dtucker Exp $
+
+# This is the ssh client system-wide configuration file. See
+# ssh_config(5) for more information. This file provides defaults for
+# users, and the values can be changed in per-user configuration files
+# or on the command line.
+
+# Configuration data is parsed as follows:
+# 1. command line options
+# 2. user-specific file
+# 3. system-wide file
+# Any configuration value is only changed the first time it is set.
+# Thus, host-specific definitions should be at the beginning of the
+# configuration file, and defaults at the end.
+
+# Site-wide defaults for some commonly used options. For a comprehensive
+# list of available options, their meanings and defaults, please see the
+# ssh_config(5) man page.
+
+# Host *
+# ForwardAgent no
+# ForwardX11 no
+# RhostsRSAAuthentication no
+# RSAAuthentication yes
+# PasswordAuthentication yes
+# HostbasedAuthentication no
+# GSSAPIAuthentication no
+# GSSAPIDelegateCredentials no
+# BatchMode no
+# CheckHostIP yes
+# AddressFamily any
+# ConnectTimeout 0
+# StrictHostKeyChecking ask
+# IdentityFile ~/.ssh/identity
+# IdentityFile ~/.ssh/id_rsa
+# IdentityFile ~/.ssh/id_dsa
+# Port 22
+# Protocol 2,1
+# Cipher 3des
+# Ciphers aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc
+# MACs hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160
+# EscapeChar ~
+# Tunnel no
+# TunnelDevice any:any
+# PermitLocalCommand no
+# VisualHostKey no
+# ProxyCommand ssh -q -W %h:%p gateway.example.com
+#UsePrivilegeSeparation no
+PubkeyAcceptedKeyTypes ssh-ed25519*,ssh-rsa*,ssh-dss*,ecdsa-sha2*
+
diff --git a/contrib/win32/win32compat/ssh_config/sshd_config b/contrib/win32/win32compat/ssh_config/sshd_config
new file mode 100644
index 000000000..5b9152606
--- /dev/null
+++ b/contrib/win32/win32compat/ssh_config/sshd_config
@@ -0,0 +1,122 @@
+# $OpenBSD: sshd_config,v 1.84 2011/05/23 03:30:07 djm Exp $
+
+# This is the sshd server system-wide configuration file. See
+# sshd_config(5) for more information.
+
+# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
+
+# The strategy used for options in the default sshd_config shipped with
+# OpenSSH is to specify options with their default value where
+# possible, but leave them commented. Uncommented options override the
+# default value.
+
+#Port 22
+#AddressFamily any
+#ListenAddress 0.0.0.0
+#ListenAddress ::
+
+# The default requires explicit activation of protocol 1
+#Protocol 2
+
+# HostKey for protocol version 1
+#HostKey /etc/ssh/ssh_host_key
+# HostKeys for protocol version 2
+#HostKey /etc/ssh/ssh_host_rsa_key
+#HostKey /etc/ssh/ssh_host_dsa_key
+#HostKey /etc/ssh/ssh_host_ecdsa_key
+
+# Lifetime and size of ephemeral version 1 server key
+#KeyRegenerationInterval 1h
+#ServerKeyBits 1024
+
+# Logging
+# obsoletes QuietMode and FascistLogging
+#SyslogFacility AUTH
+#LogLevel INFO
+
+# Authentication:
+
+#LoginGraceTime 2m
+#PermitRootLogin yes
+#StrictModes yes
+#MaxAuthTries 6
+#MaxSessions 10
+
+#RSAAuthentication yes
+#PubkeyAuthentication yes
+
+# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
+# but this is overridden so installations will only check .ssh/authorized_keys
+AuthorizedKeysFile .ssh/authorized_keys
+
+# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
+#RhostsRSAAuthentication no
+# similar for protocol version 2
+#HostbasedAuthentication no
+# Change to yes if you don't trust ~/.ssh/known_hosts for
+# RhostsRSAAuthentication and HostbasedAuthentication
+#IgnoreUserKnownHosts no
+# Don't read the user's ~/.rhosts and ~/.shosts files
+#IgnoreRhosts yes
+
+# To disable tunneled clear text passwords, change to no here!
+#PasswordAuthentication yes
+#PermitEmptyPasswords no
+
+# Change to no to disable s/key passwords
+#ChallengeResponseAuthentication yes
+
+# Kerberos options
+#KerberosAuthentication no
+#KerberosOrLocalPasswd yes
+#KerberosTicketCleanup yes
+#KerberosGetAFSToken no
+
+# GSSAPI options
+#GSSAPIAuthentication no
+#GSSAPICleanupCredentials yes
+
+# Set this to 'yes' to enable PAM authentication, account processing,
+# and session processing. If this is enabled, PAM authentication will
+# be allowed through the ChallengeResponseAuthentication and
+# PasswordAuthentication. Depending on your PAM configuration,
+# PAM authentication via ChallengeResponseAuthentication may bypass
+# the setting of "PermitRootLogin without-password".
+# If you just want the PAM account and session checks to run without
+# PAM authentication, then enable this but set PasswordAuthentication
+# and ChallengeResponseAuthentication to 'no'.
+#UsePAM no
+
+#AllowAgentForwarding yes
+#AllowTcpForwarding yes
+#GatewayPorts no
+#X11Forwarding no
+#X11DisplayOffset 10
+#X11UseLocalhost yes
+#PrintMotd yes
+#PrintLastLog yes
+#TCPKeepAlive yes
+#UseLogin no
+#UsePrivilegeSeparation yes
+#PermitUserEnvironment no
+#Compression delayed
+#ClientAliveInterval 0
+#ClientAliveCountMax 3
+#UseDNS yes
+#PidFile /var/run/sshd.pid
+#MaxStartups 10
+#PermitTunnel no
+#ChrootDirectory none
+
+# no default banner path
+#Banner none
+
+# override default of no subsystems
+#Subsystem sftp /usr/libexec/sftp-server
+Subsystem sftp /win32openssh/bin/sftp-server.exe
+
+# Example of overriding settings on a per-user basis
+#Match User anoncvs
+# X11Forwarding no
+# AllowTcpForwarding no
+# ForceCommand cvs server
diff --git a/contrib/win32/win32compat/termio.c b/contrib/win32/win32compat/termio.c
new file mode 100644
index 000000000..4ae3be65e
--- /dev/null
+++ b/contrib/win32/win32compat/termio.c
@@ -0,0 +1,205 @@
+#include
+#include "w32fd.h"
+#include "tncon.h"
+#include "inc\defs.h"
+#include "inc\utf.h"
+
+#define TERM_IO_BUF_SIZE 2048
+
+struct io_status {
+ DWORD to_transfer;
+ DWORD transferred;
+ DWORD error;
+};
+
+static struct io_status read_status, write_status;
+
+static VOID CALLBACK ReadAPCProc(
+ _In_ ULONG_PTR dwParam
+ ) {
+ struct w32_io* pio = (struct w32_io*)dwParam;
+ debug3("TermRead CB - io:%p, bytes: %d, pending: %d, error: %d", pio, read_status.transferred,
+ pio->read_details.pending, read_status.error);
+ pio->read_details.error = read_status.error;
+ pio->read_details.remaining = read_status.transferred;
+ pio->read_details.completed = 0;
+ pio->read_details.pending = FALSE;
+ WaitForSingleObject(pio->read_overlapped.hEvent, INFINITE);
+ CloseHandle(pio->read_overlapped.hEvent);
+ pio->read_overlapped.hEvent = 0;
+}
+
+static DWORD WINAPI ReadThread(
+ _In_ LPVOID lpParameter
+ ) {
+ struct w32_io* pio = (struct w32_io*)lpParameter;
+ debug3("TermRead thread, io:%p", pio);
+ memset(&read_status, 0, sizeof(read_status));
+ if (!ReadFile(WINHANDLE(pio), pio->read_details.buf,
+ pio->read_details.buf_size, &read_status.transferred, NULL)) {
+ read_status.error = GetLastError();
+ debug("TermRead thread - ReadFile failed %d, io:%p", GetLastError(), pio);
+ }
+
+ if (0 == QueueUserAPC(ReadAPCProc, main_thread, (ULONG_PTR)pio)) {
+ debug("TermRead thread - ERROR QueueUserAPC failed %d, io:%p", GetLastError(), pio);
+ pio->read_details.pending = FALSE;
+ pio->read_details.error = GetLastError();
+ DebugBreak();
+ }
+ return 0;
+}
+
+static DWORD WINAPI ReadConsoleThread(
+ _In_ LPVOID lpParameter
+) {
+ int nBytesReturned = 0;
+
+ struct w32_io* pio = (struct w32_io*)lpParameter;
+
+ debug3("TermRead thread, io:%p", pio);
+ memset(&read_status, 0, sizeof(read_status));
+
+ while (nBytesReturned == 0) {
+ nBytesReturned = ReadConsoleForTermEmul(WINHANDLE(pio),
+ pio->read_details.buf, pio->read_details.buf_size);
+ }
+
+ read_status.transferred = nBytesReturned;
+
+ if (0 == QueueUserAPC(ReadAPCProc, main_thread, (ULONG_PTR)pio)) {
+ debug("TermRead thread - ERROR QueueUserAPC failed %d, io:%p", GetLastError(), pio);
+ pio->read_details.pending = FALSE;
+ pio->read_details.error = GetLastError();
+ DebugBreak();
+ }
+
+ return 0;
+}
+
+int
+termio_initiate_read(struct w32_io* pio) {
+ HANDLE read_thread;
+
+ debug3("TermRead initiate io:%p", pio);
+
+ if (pio->read_details.buf_size == 0) {
+ pio->read_details.buf = malloc(TERM_IO_BUF_SIZE);
+ if (pio->read_details.buf == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ pio->read_details.buf_size = TERM_IO_BUF_SIZE;
+ }
+
+ read_thread = CreateThread(NULL, 0, ReadConsoleThread, pio, 0, NULL);
+ if (read_thread == NULL) {
+ errno = errno_from_Win32Error(GetLastError());
+ debug("TermRead initiate - ERROR CreateThread %d, io:%p", GetLastError(), pio);
+ return -1;
+ }
+
+ pio->read_overlapped.hEvent = read_thread;
+ pio->read_details.pending = TRUE;
+ return 0;
+}
+
+static VOID CALLBACK WriteAPCProc(
+ _In_ ULONG_PTR dwParam
+ ) {
+ struct w32_io* pio = (struct w32_io*)dwParam;
+ debug3("TermWrite CB - io:%p, bytes: %d, pending: %d, error: %d", pio, write_status.transferred,
+ pio->write_details.pending, write_status.error);
+ pio->write_details.error = write_status.error;
+ pio->write_details.remaining -= write_status.transferred;
+ /*TODO- assert that reamining is 0 by now*/
+ pio->write_details.completed = 0;
+ pio->write_details.pending = FALSE;
+ WaitForSingleObject(pio->write_overlapped.hEvent, INFINITE);
+ CloseHandle(pio->write_overlapped.hEvent);
+ pio->write_overlapped.hEvent = 0;
+}
+
+static DWORD WINAPI WriteThread(
+ _In_ LPVOID lpParameter
+ ) {
+ struct w32_io* pio = (struct w32_io*)lpParameter;
+ char *respbuf = NULL;
+ size_t resplen = 0;
+ DWORD dwSavedAttributes = ENABLE_PROCESSED_INPUT;
+ debug3("TermWrite thread, io:%p", pio);
+
+ /* decide to call parsing engine or directly write to console
+ * doing the following trick to decide -
+ * if console in handle is set to process Ctrl+C, then it is likely
+ * serving a PTY enabled session
+ */
+ GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &dwSavedAttributes);
+ if (dwSavedAttributes & ENABLE_PROCESSED_INPUT) {
+ /* convert stream to utf16 and dump on console */
+ pio->write_details.buf[write_status.to_transfer] = '\0';
+ wchar_t* t = utf8_to_utf16(pio->write_details.buf);
+ WriteConsoleW(WINHANDLE(pio), t, wcslen(t), 0, 0);
+ free(t);
+ write_status.transferred = write_status.to_transfer;
+ } else {
+
+ telProcessNetwork(pio->write_details.buf, write_status.to_transfer, &respbuf, &resplen);
+ /*TODO - respbuf is not null in some cases, this needs to be returned back via read stream*/
+ write_status.transferred = write_status.to_transfer;
+ }
+
+ if (0 == QueueUserAPC(WriteAPCProc, main_thread, (ULONG_PTR)pio)) {
+ debug("TermWrite thread - ERROR QueueUserAPC failed %d, io:%p", GetLastError(), pio);
+ pio->write_details.pending = FALSE;
+ pio->write_details.error = GetLastError();
+ DebugBreak();
+ }
+ return 0;
+}
+
+int
+termio_initiate_write(struct w32_io* pio, DWORD num_bytes) {
+ HANDLE write_thread;
+
+ debug3("TermWrite initiate io:%p", pio);
+ memset(&write_status, 0, sizeof(write_status));
+ write_status.to_transfer = num_bytes;
+ write_thread = CreateThread(NULL, 0, WriteThread, pio, 0, NULL);
+ if (write_thread == NULL) {
+ errno = errno_from_Win32Error(GetLastError());
+ debug("TermWrite initiate - ERROR CreateThread %d, io:%p", GetLastError(), pio);
+ return -1;
+ }
+
+ pio->write_overlapped.hEvent = write_thread;
+ pio->write_details.pending = TRUE;
+ return 0;
+}
+
+
+int termio_close(struct w32_io* pio) {
+ debug2("termio_close - pio:%p", pio);
+ HANDLE h;
+
+ CancelIoEx(WINHANDLE(pio), NULL);
+ /* If io is pending, let write worker threads exit. The read thread is blocked so terminate it.*/
+ if (pio->read_details.pending)
+ TerminateThread(pio->read_overlapped.hEvent, 0);
+ if (pio->write_details.pending)
+ WaitForSingleObject(pio->write_overlapped.hEvent, INFINITE);
+ /* drain queued APCs */
+ SleepEx(0, TRUE);
+ if (pio->type != STD_IO_FD) {//STD handles are never explicitly closed
+ CloseHandle(WINHANDLE(pio));
+
+ if (pio->read_details.buf)
+ free(pio->read_details.buf);
+
+ if (pio->write_details.buf)
+ free(pio->write_details.buf);
+
+ free(pio);
+ }
+ return 0;
+}
diff --git a/contrib/win32/win32compat/tncon.c b/contrib/win32/win32compat/tncon.c
new file mode 100644
index 000000000..7df7eb24c
--- /dev/null
+++ b/contrib/win32/win32compat/tncon.c
@@ -0,0 +1,626 @@
+/*
+ * Author: Microsoft Corp.
+ *
+ * Copyright (c) 2015 Microsoft Corp.
+ * All rights reserved
+ *
+ * Microsoft openssh win32 port
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/* tncon.c
+ *
+ * Console reading calls for building an emulator over Windows Console. MS win32 port of ssh.exe client uses it.
+ *
+*/
+#include
+#include
+#include
+#include
+
+
+#include
+
+#include "ansiprsr.h"
+#include "tncon.h"
+#include "tnnet.h"
+
+extern bool gbVTAppMode;
+
+char *glob_out = NULL ;
+int glob_outlen = 0;
+int glob_space = 0;
+
+unsigned char NAWSSTR[] = { "\xff\xfa\x1f\x00\x00\x00\x00\xff\xf0" };
+
+extern int ScreenY;
+extern int ScreenX;
+
+extern int ScrollTop;
+extern int ScrollBottom;
+
+/* terminal global switches*/
+TelParams Parameters = {
+ 0, // int fLogging;
+ NULL, //FILE *fplogfile;
+ NULL, //char *pInputFile;
+ NULL, // char *szDebugInputFile;
+ FALSE, //BOOL fDebugWait;
+ 0, //int timeOut;
+ 0, //int fLocalEcho;
+ 0, //int fTreatLFasCRLF;
+ 0, //int fSendCROnly;
+ ENUM_LF, //int nReceiveCRLF;
+ '`', //char sleepChar;
+ '\035', //char menuChar; // CTRL-]
+ 0, //SOCKET Socket;
+ FALSE, //BOOL bVT100Mode;
+ "\x01", //char *pAltKey;
+};
+TelParams* pParams = &Parameters;
+
+// For our case, in NetWriteString2(), we do not use socket, but write the out going data to
+// a global buffer setup by ReadConsoleForTermEmul() function below
+int NetWriteString2(SOCKET sock, char* source, size_t len, int options)
+{
+ while (len > 0) {
+ if (glob_outlen >= glob_space)
+ return glob_outlen;
+ *glob_out++ = *source++ ;
+ len--;
+ glob_outlen++;
+ }
+
+ return glob_outlen;
+}
+
+BOOL DataAvailable(HANDLE h)
+{
+ DWORD dwRet = WaitForSingleObject(h, INFINITE);
+ if(dwRet == WAIT_OBJECT_0)
+ return TRUE;
+
+ if(dwRet == WAIT_FAILED)
+ return FALSE;
+
+ return FALSE;
+}
+
+void queue_terminal_window_change_event();
+
+int ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen)
+{
+ HANDLE hHandle[] = { hInput, NULL };
+ DWORD nHandle = 1;
+ DWORD dwInput = 0;
+ DWORD dwControlKeyState = 0;
+ DWORD rc = 0;
+
+ unsigned char szResponse[50];
+ unsigned char octets[20];
+
+ char aChar = 0;
+
+ INPUT_RECORD InputRecord;
+
+ BOOL bCapsOn = FALSE;
+ BOOL bShift = FALSE;
+
+ glob_out = destin;
+ glob_space = destinlen;
+ glob_outlen = 0;
+
+ while (DataAvailable(hInput))
+ {
+ if (glob_outlen >= destinlen)
+ return glob_outlen;
+
+ ReadConsoleInput(hInput, &InputRecord, 1, &dwInput);
+
+ switch (InputRecord.EventType)
+ {
+ case WINDOW_BUFFER_SIZE_EVENT:
+ queue_terminal_window_change_event();
+ break;
+
+ case FOCUS_EVENT:
+ case MENU_EVENT:
+ break;
+
+ case KEY_EVENT:
+ bCapsOn = (InputRecord.Event.KeyEvent.dwControlKeyState & CAPSLOCK_ON);
+ bShift = (InputRecord.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED);
+ dwControlKeyState = InputRecord.Event.KeyEvent.dwControlKeyState &
+ ~(CAPSLOCK_ON | ENHANCED_KEY | NUMLOCK_ON | SCROLLLOCK_ON);
+
+ if (InputRecord.Event.KeyEvent.bKeyDown)
+ {
+ int n = WideCharToMultiByte(
+ CP_UTF8,
+ 0,
+ &(InputRecord.Event.KeyEvent.uChar.UnicodeChar),
+ 1,
+ (LPSTR)octets,
+ 20,
+ NULL,
+ NULL);
+
+ if (pParams->fLocalEcho) {
+ ConWriteString((char *)octets, n);
+ }
+
+ switch (InputRecord.Event.KeyEvent.uChar.UnicodeChar)
+ {
+ case 0xd:
+ if (pParams->nReceiveCRLF == ENUM_LF)
+ NetWriteString2(pParams->Socket, "\r", 1, 0);
+ else
+ NetWriteString2(pParams->Socket, "\r\n", 2, 0);
+ break;
+
+ case VK_ESCAPE:
+ NetWriteString2(pParams->Socket, (char *)ESCAPE_KEY, 1, 0);
+ break;
+
+ default:
+ switch (InputRecord.Event.KeyEvent.wVirtualKeyCode)
+ {
+ case VK_UP:
+ NetWriteString2(pParams->Socket, (char *)(gbVTAppMode ? APP_UP_ARROW : UP_ARROW), 3, 0);
+ break;
+ case VK_DOWN:
+ NetWriteString2(pParams->Socket, (char *)(gbVTAppMode ? APP_DOWN_ARROW : DOWN_ARROW), 3, 0);
+ break;
+ case VK_RIGHT:
+ NetWriteString2(pParams->Socket, (char *)(gbVTAppMode ? APP_RIGHT_ARROW : RIGHT_ARROW), 3, 0);
+ break;
+ case VK_LEFT:
+ NetWriteString2(pParams->Socket, (char *)(gbVTAppMode ? APP_LEFT_ARROW : LEFT_ARROW), 3, 0);
+ break;
+ case VK_END:
+ NetWriteString2(pParams->Socket, (char *)SELECT_KEY, 4, 0);
+ break;
+ case VK_HOME:
+ NetWriteString2(pParams->Socket, (char *)FIND_KEY, 4, 0);
+ break;
+ case VK_INSERT:
+ NetWriteString2(pParams->Socket, (char *)INSERT_KEY, 4, 0);
+ break;
+ case VK_DELETE:
+ NetWriteString2(pParams->Socket, (char *)REMOVE_KEY, 4, 0);
+ break;
+ case VK_BACK:
+ NetWriteString2(pParams->Socket, (char *)BACKSPACE_KEY, 1, 0);
+ break;
+ case VK_TAB:
+ if (dwControlKeyState == SHIFT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)SHIFT_TAB_KEY, 3, 0);
+ else
+ NetWriteString2(pParams->Socket, (char *)octets, n, 0);
+ break;
+ case VK_ESCAPE:
+ NetWriteString2(pParams->Socket, (char *)ESCAPE_KEY, 1, 0);
+ break;
+ case VK_SHIFT:
+ case VK_CONTROL:
+ case VK_CAPITAL:
+ // NOP on these
+ break;
+ case VK_F1:
+ if (dwControlKeyState == 0)
+ {
+ NetWriteString2(pParams->Socket, (char *)PF1_KEY, strlen(PF1_KEY), 0);
+ }
+ else if (dwControlKeyState == SHIFT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)SHIFT_PF1_KEY, strlen(SHIFT_PF1_KEY), 0);
+ else if (dwControlKeyState == LEFT_CTRL_PRESSED ||
+ dwControlKeyState == RIGHT_CTRL_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)CTRL_PF1_KEY, strlen(CTRL_PF1_KEY), 0);
+ else if (dwControlKeyState == LEFT_ALT_PRESSED ||
+ dwControlKeyState == RIGHT_ALT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)ALT_PF1_KEY, strlen(ALT_PF1_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED)) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF1_KEY, strlen(SHIFT_ALT_CTRL_PF1_KEY), 0);
+ else if ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF1_KEY, strlen(ALT_CTRL_PF1_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF1_KEY, strlen(SHIFT_ALT_PF1_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF1_KEY, strlen(SHIFT_CTRL_PF1_KEY), 0);
+ break;
+ case VK_F2:
+ if (dwControlKeyState == 0)
+ {
+ NetWriteString2(pParams->Socket, (char *)PF2_KEY, strlen(PF2_KEY), 0);
+ }
+ else if (dwControlKeyState == SHIFT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)SHIFT_PF2_KEY, strlen(SHIFT_PF2_KEY), 0);
+ else if (dwControlKeyState == LEFT_CTRL_PRESSED ||
+ dwControlKeyState == RIGHT_CTRL_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)CTRL_PF2_KEY, strlen(CTRL_PF2_KEY), 0);
+ else if (dwControlKeyState == LEFT_ALT_PRESSED ||
+ dwControlKeyState == RIGHT_ALT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)ALT_PF2_KEY, strlen(ALT_PF2_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED)) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF2_KEY, strlen(SHIFT_ALT_CTRL_PF2_KEY), 0);
+ else if ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF2_KEY, strlen(ALT_CTRL_PF2_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF2_KEY, strlen(SHIFT_ALT_PF2_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF2_KEY, strlen(SHIFT_CTRL_PF2_KEY), 0);
+ break;
+ case VK_F3:
+ if (dwControlKeyState == 0)
+ {
+ NetWriteString2(pParams->Socket, (char *)PF3_KEY, strlen(PF3_KEY), 0);
+ }
+ else if (dwControlKeyState == SHIFT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)SHIFT_PF3_KEY, strlen(SHIFT_PF3_KEY), 0);
+ else if (dwControlKeyState == LEFT_CTRL_PRESSED ||
+ dwControlKeyState == RIGHT_CTRL_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)CTRL_PF3_KEY, strlen(CTRL_PF3_KEY), 0);
+ else if (dwControlKeyState == LEFT_ALT_PRESSED ||
+ dwControlKeyState == RIGHT_ALT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)ALT_PF3_KEY, strlen(ALT_PF3_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED)) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF3_KEY, strlen(SHIFT_ALT_CTRL_PF3_KEY), 0);
+ else if ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF3_KEY, strlen(ALT_CTRL_PF3_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF3_KEY, strlen(SHIFT_ALT_PF3_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF3_KEY, strlen(SHIFT_CTRL_PF3_KEY), 0);
+ break;
+ case VK_F4:
+ if (dwControlKeyState == 0)
+ {
+ NetWriteString2(pParams->Socket, (char *)PF4_KEY, strlen(PF4_KEY), 0);
+ }
+ else if (dwControlKeyState == SHIFT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)SHIFT_PF4_KEY, strlen(SHIFT_PF4_KEY), 0);
+ else if (dwControlKeyState == LEFT_CTRL_PRESSED ||
+ dwControlKeyState == RIGHT_CTRL_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)CTRL_PF4_KEY, strlen(CTRL_PF4_KEY), 0);
+ else if (dwControlKeyState == LEFT_ALT_PRESSED ||
+ dwControlKeyState == RIGHT_ALT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)ALT_PF4_KEY, strlen(ALT_PF4_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED)) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF4_KEY, strlen(SHIFT_ALT_CTRL_PF4_KEY), 0);
+ else if ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF4_KEY, strlen(ALT_CTRL_PF4_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF4_KEY, strlen(SHIFT_ALT_PF4_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF4_KEY, strlen(SHIFT_CTRL_PF4_KEY), 0);
+ break;
+ case VK_F5:
+ if (dwControlKeyState == 0)
+ {
+ NetWriteString2(pParams->Socket, (char *)PF5_KEY, strlen(PF5_KEY), 0);
+ }
+ else if (dwControlKeyState == SHIFT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)SHIFT_PF5_KEY, strlen(SHIFT_PF5_KEY), 0);
+ else if (dwControlKeyState == LEFT_CTRL_PRESSED ||
+ dwControlKeyState == RIGHT_CTRL_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)CTRL_PF5_KEY, strlen(CTRL_PF5_KEY), 0);
+ else if (dwControlKeyState == LEFT_ALT_PRESSED ||
+ dwControlKeyState == RIGHT_ALT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)ALT_PF5_KEY, strlen(ALT_PF5_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED)) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF5_KEY, strlen(SHIFT_ALT_CTRL_PF5_KEY), 0);
+ else if ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF5_KEY, strlen(ALT_CTRL_PF5_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF5_KEY, strlen(SHIFT_ALT_PF5_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF5_KEY, strlen(SHIFT_CTRL_PF5_KEY), 0);
+ break;
+ case VK_F6:
+ if (dwControlKeyState == 0)
+ NetWriteString2(pParams->Socket, (char *)PF6_KEY, strlen(PF6_KEY), 0);
+ else if (dwControlKeyState == SHIFT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)SHIFT_PF6_KEY, strlen(SHIFT_PF6_KEY), 0);
+ else if (dwControlKeyState == LEFT_CTRL_PRESSED ||
+ dwControlKeyState == RIGHT_CTRL_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)CTRL_PF6_KEY, strlen(CTRL_PF6_KEY), 0);
+ else if (dwControlKeyState == LEFT_ALT_PRESSED ||
+ dwControlKeyState == RIGHT_ALT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)ALT_PF6_KEY, strlen(ALT_PF6_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED)) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF6_KEY, strlen(SHIFT_ALT_CTRL_PF6_KEY), 0);
+ else if ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF6_KEY, strlen(ALT_CTRL_PF6_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF6_KEY, strlen(SHIFT_ALT_PF6_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF6_KEY, strlen(SHIFT_CTRL_PF6_KEY), 0);
+ break;
+ case VK_F7:
+ if (dwControlKeyState == 0)
+ NetWriteString2(pParams->Socket, (char *)PF7_KEY, strlen(PF7_KEY), 0);
+ else if (dwControlKeyState == SHIFT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)SHIFT_PF7_KEY, strlen(SHIFT_PF7_KEY), 0);
+ else if (dwControlKeyState == LEFT_CTRL_PRESSED ||
+ dwControlKeyState == RIGHT_CTRL_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)CTRL_PF7_KEY, strlen(CTRL_PF7_KEY), 0);
+ else if (dwControlKeyState == LEFT_ALT_PRESSED ||
+ dwControlKeyState == RIGHT_ALT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)ALT_PF7_KEY, strlen(ALT_PF7_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED)) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF7_KEY, strlen(SHIFT_ALT_CTRL_PF7_KEY), 0);
+ else if ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF7_KEY, strlen(ALT_CTRL_PF7_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF7_KEY, strlen(SHIFT_ALT_PF7_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF7_KEY, strlen(SHIFT_CTRL_PF7_KEY), 0);
+ break;
+ case VK_F8:
+ if (dwControlKeyState == 0)
+ NetWriteString2(pParams->Socket, (char *)PF8_KEY, strlen(PF8_KEY), 0);
+ else if (dwControlKeyState == SHIFT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)SHIFT_PF8_KEY, strlen(SHIFT_PF8_KEY), 0);
+ else if (dwControlKeyState == LEFT_CTRL_PRESSED ||
+ dwControlKeyState == RIGHT_CTRL_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)CTRL_PF8_KEY, strlen(CTRL_PF8_KEY), 0);
+ else if (dwControlKeyState == LEFT_ALT_PRESSED ||
+ dwControlKeyState == RIGHT_ALT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)ALT_PF8_KEY, strlen(ALT_PF8_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED)) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF8_KEY, strlen(SHIFT_ALT_CTRL_PF8_KEY), 0);
+ else if ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF8_KEY, strlen(ALT_CTRL_PF8_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF8_KEY, strlen(SHIFT_ALT_PF8_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF8_KEY, strlen(SHIFT_CTRL_PF8_KEY), 0);
+ break;
+ case VK_F9:
+ if (dwControlKeyState == 0)
+ NetWriteString2(pParams->Socket, (char *)PF9_KEY, strlen(PF9_KEY), 0);
+ else if (dwControlKeyState == SHIFT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)SHIFT_PF9_KEY, strlen(SHIFT_PF9_KEY), 0);
+ else if (dwControlKeyState == LEFT_CTRL_PRESSED ||
+ dwControlKeyState == RIGHT_CTRL_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)CTRL_PF9_KEY, strlen(CTRL_PF9_KEY), 0);
+ else if (dwControlKeyState == LEFT_ALT_PRESSED ||
+ dwControlKeyState == RIGHT_ALT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)ALT_PF9_KEY, strlen(ALT_PF9_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED)) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF9_KEY, strlen(SHIFT_ALT_CTRL_PF9_KEY), 0);
+ else if ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF9_KEY, strlen(ALT_CTRL_PF9_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF9_KEY, strlen(SHIFT_ALT_PF9_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF9_KEY, strlen(SHIFT_CTRL_PF9_KEY), 0);
+ break;
+ case VK_F10:
+ if (dwControlKeyState == 0)
+ NetWriteString2(pParams->Socket, (char *)PF10_KEY, strlen(PF10_KEY), 0);
+ else if (dwControlKeyState == SHIFT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)SHIFT_PF10_KEY, strlen(SHIFT_PF10_KEY), 0);
+ else if (dwControlKeyState == LEFT_CTRL_PRESSED ||
+ dwControlKeyState == RIGHT_CTRL_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)CTRL_PF10_KEY, strlen(CTRL_PF10_KEY), 0);
+ else if (dwControlKeyState == LEFT_ALT_PRESSED ||
+ dwControlKeyState == RIGHT_ALT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)ALT_PF10_KEY, strlen(ALT_PF10_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED)) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF10_KEY, strlen(SHIFT_ALT_CTRL_PF10_KEY), 0);
+ else if ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF10_KEY, strlen(ALT_CTRL_PF10_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF10_KEY, strlen(SHIFT_ALT_PF10_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF10_KEY, strlen(SHIFT_CTRL_PF10_KEY), 0);
+ break;
+ case VK_F11:
+ if (dwControlKeyState == 0)
+ NetWriteString2(pParams->Socket, (char *)PF11_KEY, strlen(PF11_KEY), 0);
+ else if (dwControlKeyState == SHIFT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)SHIFT_PF11_KEY, strlen(SHIFT_PF11_KEY), 0);
+ else if (dwControlKeyState == LEFT_CTRL_PRESSED ||
+ dwControlKeyState == RIGHT_CTRL_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)CTRL_PF11_KEY, strlen(CTRL_PF11_KEY), 0);
+ else if (dwControlKeyState == LEFT_ALT_PRESSED ||
+ dwControlKeyState == RIGHT_ALT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)ALT_PF11_KEY, strlen(ALT_PF11_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED)) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF11_KEY, strlen(SHIFT_ALT_CTRL_PF11_KEY), 0);
+ else if ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF11_KEY, strlen(ALT_CTRL_PF11_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF11_KEY, strlen(SHIFT_ALT_PF11_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF11_KEY, strlen(SHIFT_CTRL_PF11_KEY), 0);
+ break;
+ case VK_F12:
+ if (dwControlKeyState == 0)
+ NetWriteString2(pParams->Socket, (char *)PF12_KEY, strlen(PF12_KEY), 0);
+ else if (dwControlKeyState == SHIFT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)SHIFT_PF12_KEY, strlen(SHIFT_PF12_KEY), 0);
+ else if (dwControlKeyState == LEFT_CTRL_PRESSED ||
+ dwControlKeyState == RIGHT_CTRL_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)CTRL_PF12_KEY, strlen(CTRL_PF12_KEY), 0);
+ else if (dwControlKeyState == LEFT_ALT_PRESSED ||
+ dwControlKeyState == RIGHT_ALT_PRESSED)
+ NetWriteString2(pParams->Socket, (char *)ALT_PF12_KEY, strlen(ALT_PF12_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED)) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_CTRL_PF12_KEY, strlen(SHIFT_ALT_CTRL_PF12_KEY), 0);
+ else if ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)ALT_CTRL_PF12_KEY, strlen(ALT_CTRL_PF12_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & RIGHT_ALT_PRESSED) ||
+ (dwControlKeyState & LEFT_ALT_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_ALT_PF12_KEY, strlen(SHIFT_ALT_PF12_KEY), 0);
+ else if ((dwControlKeyState & SHIFT_PRESSED) &&
+ ((dwControlKeyState & LEFT_CTRL_PRESSED) ||
+ (dwControlKeyState & RIGHT_CTRL_PRESSED)))
+ NetWriteString2(pParams->Socket, (char *)SHIFT_CTRL_PF12_KEY, strlen(SHIFT_CTRL_PF12_KEY), 0);
+ break;
+ default:
+ {
+ NetWriteString2(pParams->Socket, (char *)octets, n, 0);
+ break;
+ }
+ }
+ }
+ }
+ break;
+ }
+ break;
+ }
+
+ return glob_outlen ;
+}
+
+
diff --git a/contrib/win32/win32compat/tncon.h b/contrib/win32/win32compat/tncon.h
new file mode 100644
index 000000000..c36c02b4b
--- /dev/null
+++ b/contrib/win32/win32compat/tncon.h
@@ -0,0 +1,184 @@
+/*
+ * Author: Microsoft Corp.
+ *
+ * Copyright (c) 2015 Microsoft Corp.
+ * All rights reserved
+ *
+ * Microsoft openssh win32 port
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/* tncon.h
+ *
+ * Contains terminal emulation console related key definition
+ *
+ */
+#ifndef __TNCON_H
+#define __TNCON_H
+
+#include "console.h"
+
+#define UP_ARROW "\x1b[A"
+#define DOWN_ARROW "\x1b[B"
+#define RIGHT_ARROW "\x1b[C"
+#define LEFT_ARROW "\x1b[D"
+
+#define APP_UP_ARROW "\x1bOA"
+#define APP_DOWN_ARROW "\x1bOB"
+#define APP_RIGHT_ARROW "\x1bOC"
+#define APP_LEFT_ARROW "\x1bOD"
+
+#define FIND_KEY "\x1b[1~"
+#define INSERT_KEY "\x1b[2~"
+#define REMOVE_KEY "\x1b[3~"
+#define SELECT_KEY "\x1b[4~"
+#define PREV_KEY "\x1b[5~"
+#define NEXT_KEY "\x1b[6~"
+#define SHIFT_TAB_KEY "\x1b[~"
+#define ESCAPE_KEY "\x1b"
+#define BACKSPACE_KEY "\b"
+
+// VT100 Function Key's
+#define VT100_PF1_KEY "\x1bO2"
+#define VT100_PF2_KEY "\x1bO3"
+#define VT100_PF3_KEY "\x1bO4"
+#define VT100_PF4_KEY "\x1bO5"
+#define VT100_PF5_KEY "\x1bO6"
+#define VT100_PF6_KEY "\x1bO7"
+#define VT100_PF7_KEY "\x1bO8"
+#define VT100_PF8_KEY "\x1bO9"
+#define VT100_PF9_KEY "\x1bO:"
+#define VT100_PF10_KEY "\x1bO;"
+
+// VT420 Key's
+#define PF1_KEY "\x1b[11~"
+#define PF2_KEY "\x1b[12~"
+#define PF3_KEY "\x1b[13~"
+#define PF4_KEY "\x1b[14~"
+#define PF5_KEY "\x1b[15~"
+#define PF6_KEY "\x1b[17~"
+#define PF7_KEY "\x1b[18~"
+#define PF8_KEY "\x1b[19~"
+#define PF9_KEY "\x1b[20~"
+#define PF10_KEY "\x1b[21~"
+#define PF11_KEY "\x1b[23~"
+#define PF12_KEY "\x1b[24~"
+
+#define SHIFT_PF1_KEY "\x1b[11;2~"
+#define SHIFT_PF2_KEY "\x1b[12;2~"
+#define SHIFT_PF3_KEY "\x1b[13;2~"
+#define SHIFT_PF4_KEY "\x1b[14;2~"
+#define SHIFT_PF5_KEY "\x1b[15;2~"
+#define SHIFT_PF6_KEY "\x1b[17;2~"
+#define SHIFT_PF7_KEY "\x1b[18;2~"
+#define SHIFT_PF8_KEY "\x1b[19;2~"
+#define SHIFT_PF9_KEY "\x1b[20;2~"
+#define SHIFT_PF10_KEY "\x1b[21;2~"
+#define SHIFT_PF11_KEY "\x1b[24;2~"
+#define SHIFT_PF12_KEY "\x1b[25;2~"
+
+#define ALT_PF1_KEY "\x1b[11;3~"
+#define ALT_PF2_KEY "\x1b[12;3~"
+#define ALT_PF3_KEY "\x1b[13;3~"
+#define ALT_PF4_KEY "\x1b[14;3~"
+#define ALT_PF5_KEY "\x1b[15;3~"
+#define ALT_PF6_KEY "\x1b[17;3~"
+#define ALT_PF7_KEY "\x1b[18;3~"
+#define ALT_PF8_KEY "\x1b[19;3~"
+#define ALT_PF9_KEY "\x1b[20;3~"
+#define ALT_PF10_KEY "\x1b[21;3~"
+#define ALT_PF11_KEY "\x1b[24;3~"
+#define ALT_PF12_KEY "\x1b[25;3~"
+
+#define CTRL_PF1_KEY "\x1b[11;4~"
+#define CTRL_PF2_KEY "\x1b[12;4~"
+#define CTRL_PF3_KEY "\x1b[13;4~"
+#define CTRL_PF4_KEY "\x1b[14;4~"
+#define CTRL_PF5_KEY "\x1b[15;4~"
+#define CTRL_PF6_KEY "\x1b[17;4~"
+#define CTRL_PF7_KEY "\x1b[18;4~"
+#define CTRL_PF8_KEY "\x1b[19;4~"
+#define CTRL_PF9_KEY "\x1b[20;4~"
+#define CTRL_PF10_KEY "\x1b[21;4~"
+#define CTRL_PF11_KEY "\x1b[24;4~"
+#define CTRL_PF12_KEY "\x1b[25;4~"
+
+#define SHIFT_CTRL_PF1_KEY "\x1b[11;6~"
+#define SHIFT_CTRL_PF2_KEY "\x1b[12;6~"
+#define SHIFT_CTRL_PF3_KEY "\x1b[13;6~"
+#define SHIFT_CTRL_PF4_KEY "\x1b[14;6~"
+#define SHIFT_CTRL_PF5_KEY "\x1b[15;6~"
+#define SHIFT_CTRL_PF6_KEY "\x1b[17;6~"
+#define SHIFT_CTRL_PF7_KEY "\x1b[18;6~"
+#define SHIFT_CTRL_PF8_KEY "\x1b[19;6~"
+#define SHIFT_CTRL_PF9_KEY "\x1b[20;6~"
+#define SHIFT_CTRL_PF10_KEY "\x1b[21;6~"
+#define SHIFT_CTRL_PF11_KEY "\x1b[24;6~"
+#define SHIFT_CTRL_PF12_KEY "\x1b[25;6~"
+
+#define SHIFT_ALT_PF1_KEY "\x1b[11;5~"
+#define SHIFT_ALT_PF2_KEY "\x1b[12;5~"
+#define SHIFT_ALT_PF3_KEY "\x1b[13;5~"
+#define SHIFT_ALT_PF4_KEY "\x1b[14;5~"
+#define SHIFT_ALT_PF5_KEY "\x1b[15;5~"
+#define SHIFT_ALT_PF6_KEY "\x1b[17;5~"
+#define SHIFT_ALT_PF7_KEY "\x1b[18;5~"
+#define SHIFT_ALT_PF8_KEY "\x1b[19;5~"
+#define SHIFT_ALT_PF9_KEY "\x1b[20;5~"
+#define SHIFT_ALT_PF10_KEY "\x1b[21;5~"
+#define SHIFT_ALT_PF11_KEY "\x1b[24;5~"
+#define SHIFT_ALT_PF12_KEY "\x1b[25;5~"
+
+#define ALT_CTRL_PF1_KEY "\x1b[11;7~"
+#define ALT_CTRL_PF2_KEY "\x1b[12;7~"
+#define ALT_CTRL_PF3_KEY "\x1b[13;7~"
+#define ALT_CTRL_PF4_KEY "\x1b[14;7~"
+#define ALT_CTRL_PF5_KEY "\x1b[15;7~"
+#define ALT_CTRL_PF6_KEY "\x1b[17;7~"
+#define ALT_CTRL_PF7_KEY "\x1b[18;7~"
+#define ALT_CTRL_PF8_KEY "\x1b[19;7~"
+#define ALT_CTRL_PF9_KEY "\x1b[20;7~"
+#define ALT_CTRL_PF10_KEY "\x1b[21;7~"
+#define ALT_CTRL_PF11_KEY "\x1b[24;7~"
+#define ALT_CTRL_PF12_KEY "\x1b[25;7~"
+
+#define SHIFT_ALT_CTRL_PF1_KEY "\x1b[11;8~"
+#define SHIFT_ALT_CTRL_PF2_KEY "\x1b[12;8~"
+#define SHIFT_ALT_CTRL_PF3_KEY "\x1b[13;8~"
+#define SHIFT_ALT_CTRL_PF4_KEY "\x1b[14;8~"
+#define SHIFT_ALT_CTRL_PF5_KEY "\x1b[15;8~"
+#define SHIFT_ALT_CTRL_PF6_KEY "\x1b[17;8~"
+#define SHIFT_ALT_CTRL_PF7_KEY "\x1b[18;8~"
+#define SHIFT_ALT_CTRL_PF8_KEY "\x1b[19;8~"
+#define SHIFT_ALT_CTRL_PF9_KEY "\x1b[20;8~"
+#define SHIFT_ALT_CTRL_PF10_KEY "\x1b[21;8~"
+#define SHIFT_ALT_CTRL_PF11_KEY "\x1b[24;8~"
+#define SHIFT_ALT_CTRL_PF12_KEY "\x1b[25;8~"
+
+#define TERMINAL_ID "\x1b[?1;2c"
+#define STATUS_REPORT "\x1b[2;5R"
+#define CURSOR_REPORT_FORMAT_STRING "\x1b[%d;%dR"
+#define VT52_TERMINAL_ID "\x1b/Z"
+
+int ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen);
+
+#endif
\ No newline at end of file
diff --git a/contrib/win32/win32compat/tnnet.c b/contrib/win32/win32compat/tnnet.c
new file mode 100644
index 000000000..a5ee3e2e3
--- /dev/null
+++ b/contrib/win32/win32compat/tnnet.c
@@ -0,0 +1,94 @@
+/*
+ * Author: Microsoft Corp.
+ *
+ * Copyright (c) 2015 Microsoft Corp.
+ * All rights reserved
+ *
+ * Microsoft openssh win32 port
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/* tnnet.c
+ *
+ * Contains terminal emulation related network calls to invoke ANSI parsing engine
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#include "ansiprsr.h"
+
+#define dwBuffer 4096
+
+// Server will always be returning a sequence of ANSI control characters which the client
+// protocol can either passthru directly to the console or transform based on an output terminal
+// type. We're not using termcap so we're only supporting the ANSI (vt100) sequences that
+// are hardcoded in the server and will be transformed to Windows Console commands.
+
+size_t telProcessNetwork(char *buf, size_t len, unsigned char **respbuf, size_t *resplen)
+{
+ unsigned char szBuffer[dwBuffer + 8];
+
+ unsigned char* pszNewHead = NULL;
+
+ unsigned char* pszHead = NULL;
+ unsigned char* pszTail = NULL;
+
+ char *term = NULL;
+
+ if (len == 0)
+ return len;
+
+ term = getenv("TERM");
+
+ if (term != NULL && _stricmp(term, "passthru") == 0)
+ return len;
+
+ // Transform a single carriage return into a single linefeed before
+ // continuing.
+ if ((len == 1) && (buf[0] == 13))
+ buf[0] = 10;
+
+ pszTail = (unsigned char *)buf;
+ pszHead = (unsigned char *)buf;
+
+ pszTail += len;
+
+ pszNewHead = pszHead;
+
+ // Loop through the network buffer transforming characters as necessary.
+ // The buffer will be empty after the transformation
+ // process since the buffer will contain only commands that are handled by the console API.
+ do {
+ pszHead = pszNewHead;
+ pszNewHead = ParseBuffer(pszHead, pszTail, respbuf, resplen);
+
+ } while ((pszNewHead != pszHead) && (pszNewHead < pszTail) && (resplen == NULL || (resplen != NULL && *resplen == 0)));
+
+ len = 0;
+
+ return len;
+}
diff --git a/contrib/win32/win32compat/tnnet.h b/contrib/win32/win32compat/tnnet.h
new file mode 100644
index 000000000..d2fb54b67
--- /dev/null
+++ b/contrib/win32/win32compat/tnnet.h
@@ -0,0 +1,42 @@
+/*
+ * Author: Microsoft Corp.
+ *
+ * Copyright (c) 2015 Microsoft Corp.
+ * All rights reserved
+ *
+ * Microsoft openssh win32 port
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/* tnnet.h
+ *
+ * Contains terminal emulation related network calls to invoke ANSI parsing engine
+ *
+ */
+
+#ifndef __TNNET_H
+#define __TNNET_H
+
+ size_t telProcessNetwork (char *buf, size_t len, unsigned char **respbuf, size_t *resplen);
+
+#endif
+
\ No newline at end of file
diff --git a/contrib/win32/win32compat/ttymodes_windows.c b/contrib/win32/win32compat/ttymodes_windows.c
new file mode 100644
index 000000000..6d8db1fd5
--- /dev/null
+++ b/contrib/win32/win32compat/ttymodes_windows.c
@@ -0,0 +1,230 @@
+/*
+ * SSH2 tty modes for Windows
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include
+
+#include
+#include
+#include
+#include
+
+#include "packet.h"
+#include "log.h"
+#include "compat.h"
+#include "buffer.h"
+
+#define TTY_OP_END 0
+/*
+ * uint32 (u_int) follows speed in SSH1 and SSH2
+ */
+#define TTY_OP_ISPEED_PROTO1 192
+#define TTY_OP_OSPEED_PROTO1 193
+#define TTY_OP_ISPEED_PROTO2 128
+#define TTY_OP_OSPEED_PROTO2 129
+
+/*
+ * Encodes terminal modes for the terminal referenced by fd
+ * or tiop in a portable manner, and appends the modes to a packet
+ * being constructed.
+ */
+void
+tty_make_modes(int fd, struct termios *tiop)
+{
+ int baud;
+ Buffer buf;
+ int tty_op_ospeed, tty_op_ispeed;
+ void (*put_arg)(Buffer *, u_int);
+
+ buffer_init(&buf);
+ if (compat20) {
+ tty_op_ospeed = TTY_OP_OSPEED_PROTO2;
+ tty_op_ispeed = TTY_OP_ISPEED_PROTO2;
+ put_arg = buffer_put_int;
+ } else {
+ tty_op_ospeed = TTY_OP_OSPEED_PROTO1;
+ tty_op_ispeed = TTY_OP_ISPEED_PROTO1;
+ put_arg = (void (*)(Buffer *, u_int)) buffer_put_char;
+ }
+
+ /* Store input and output baud rates. */
+ baud = 9600;
+
+ buffer_put_char(&buf, tty_op_ospeed);
+ buffer_put_int(&buf, baud);
+ baud = 9600;
+ buffer_put_char(&buf, tty_op_ispeed);
+ buffer_put_int(&buf, baud);
+
+ /* Store values of mode flags. */
+#define TTYCHAR(NAME, OP) \
+ buffer_put_char(&buf, OP); \
+ put_arg(&buf, special_char_encode(tio.c_cc[NAME]));
+
+#define TTYMODE(NAME, FIELD, OP) \
+ buffer_put_char(&buf, OP); \
+ put_arg(&buf, ((tio.FIELD & NAME) != 0));
+
+#undef TTYCHAR
+#undef TTYMODE
+
+end:
+ /* Mark end of mode data. */
+ buffer_put_char(&buf, TTY_OP_END);
+ if (compat20)
+ packet_put_string(buffer_ptr(&buf), buffer_len(&buf));
+ else
+ packet_put_raw(buffer_ptr(&buf), buffer_len(&buf));
+ buffer_free(&buf);
+}
+
+/*
+ * Decodes terminal modes for the terminal referenced by fd in a portable
+ * manner from a packet being read.
+ */
+void
+tty_parse_modes(int fd, int *n_bytes_ptr)
+{
+
+ u_int tio[255]; // win32 dummy
+ u_int tioFIELD ;
+ int opcode, baud;
+ int n_bytes = 0;
+ int failure = 0;
+ u_int (*get_arg)(void);
+ int arg_size;
+
+ if (compat20) {
+ *n_bytes_ptr = packet_get_int();
+ if (*n_bytes_ptr == 0)
+ return;
+ get_arg = packet_get_int;
+ arg_size = 4;
+ } else {
+ get_arg = packet_get_char;
+ arg_size = 1;
+ }
+
+ for (;;) {
+ n_bytes += 1;
+ opcode = packet_get_char();
+ switch (opcode) {
+ case TTY_OP_END:
+ goto set;
+
+ /* XXX: future conflict possible */
+ case TTY_OP_ISPEED_PROTO1:
+ case TTY_OP_ISPEED_PROTO2:
+ n_bytes += 4;
+ baud = packet_get_int();
+ break;
+
+ /* XXX: future conflict possible */
+ case TTY_OP_OSPEED_PROTO1:
+ case TTY_OP_OSPEED_PROTO2:
+ n_bytes += 4;
+ baud = packet_get_int();
+ break;
+
+#define TTYCHAR(NAME, OP) \
+ case OP: \
+ n_bytes += arg_size; \
+ tio[NAME] = special_char_decode(get_arg()); \
+ break;
+#define TTYMODE(NAME, FIELD, OP) \
+ case OP: \
+ n_bytes += arg_size; \
+ if (get_arg()) \
+ tioFIELD |= NAME; \
+ else \
+ tioFIELD &= ~NAME; \
+ break;
+
+#undef TTYCHAR
+#undef TTYMODE
+
+ default:
+ debug("Ignoring unsupported tty mode opcode %d (0x%x)",
+ opcode, opcode);
+ if (!compat20) {
+ /*
+ * SSH1:
+ * Opcodes 1 to 127 are defined to have
+ * a one-byte argument.
+ * Opcodes 128 to 159 are defined to have
+ * an integer argument.
+ */
+ if (opcode > 0 && opcode < 128) {
+ n_bytes += 1;
+ (void) packet_get_char();
+ break;
+ } else if (opcode >= 128 && opcode < 160) {
+ n_bytes += 4;
+ (void) packet_get_int();
+ break;
+ } else {
+ /*
+ * It is a truly undefined opcode (160 to 255).
+ * We have no idea about its arguments. So we
+ * must stop parsing. Note that some data
+ * may be left in the packet; hopefully there
+ * is nothing more coming after the mode data.
+ */
+ logit("parse_tty_modes: unknown opcode %d",
+ opcode);
+ goto set;
+ }
+ } else {
+ /*
+ * SSH2:
+ * Opcodes 1 to 159 are defined to have
+ * a uint32 argument.
+ * Opcodes 160 to 255 are undefined and
+ * cause parsing to stop.
+ */
+ if (opcode > 0 && opcode < 160) {
+ n_bytes += 4;
+ (void) packet_get_int();
+ break;
+ } else {
+ logit("parse_tty_modes: unknown opcode %d",
+ opcode);
+ goto set;
+ }
+ }
+ }
+ }
+
+set:
+ if (*n_bytes_ptr != n_bytes) {
+ *n_bytes_ptr = n_bytes;
+ logit("parse_tty_modes: n_bytes_ptr != n_bytes: %d %d",
+ *n_bytes_ptr, n_bytes);
+ return; /* Don't process bytes passed */
+ }
+ if (failure == -1)
+ return; /* Packet parsed ok but tcgetattr() failed */
+
+}
diff --git a/contrib/win32/win32compat/w32fd.c b/contrib/win32/win32compat/w32fd.c
new file mode 100644
index 000000000..9353f8cc2
--- /dev/null
+++ b/contrib/win32/win32compat/w32fd.c
@@ -0,0 +1,851 @@
+/*
+* Author: Manoj Ampalam
+*
+* Implementation of POSIX APIs
+*
+* Copyright (c) 2015 Microsoft Corp.
+* All rights reserved
+*
+* Microsoft openssh win32 port
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* 1. Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "inc\w32posix.h"
+#include "w32fd.h"
+#include "signal_internal.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include "Shlwapi.h"
+#include
+
+/* internal table that stores the fd to w32_io mapping*/
+struct w32fd_table {
+ w32_fd_set occupied; /*bit map for tracking occipied table entries*/
+ struct w32_io* w32_ios[MAX_FDS];/*array of references to mapped w32_io objects*/
+};
+
+/* mapping table*/
+static struct w32fd_table fd_table;
+
+/* static table entries representing std in, out and error*/
+static struct w32_io w32_io_stdin, w32_io_stdout, w32_io_stderr;
+
+/* main thread handle*/
+HANDLE main_thread;
+
+void fd_table_set(struct w32_io* pio, int index);
+
+/* initializes mapping table*/
+static int
+fd_table_initialize() {
+ memset(&fd_table, 0, sizeof(fd_table));
+ memset(&w32_io_stdin, 0, sizeof(w32_io_stdin));
+ w32_io_stdin.std_handle = STD_INPUT_HANDLE;
+ w32_io_stdin.type = STD_IO_FD;
+ fd_table_set(&w32_io_stdin, STDIN_FILENO);
+ memset(&w32_io_stdout, 0, sizeof(w32_io_stdout));
+ w32_io_stdout.std_handle = STD_OUTPUT_HANDLE;
+ w32_io_stdout.type = STD_IO_FD;
+ fd_table_set(&w32_io_stdout, STDOUT_FILENO);
+ memset(&w32_io_stderr, 0, sizeof(w32_io_stderr));
+ w32_io_stderr.std_handle = STD_ERROR_HANDLE;
+ w32_io_stderr.type = STD_IO_FD;
+ fd_table_set(&w32_io_stderr, STDERR_FILENO);
+ return 0;
+}
+
+/* get a free slot in mapping table with least index*/
+static int
+fd_table_get_min_index() {
+ int min_index = 0;
+ unsigned char* bitmap = fd_table.occupied.bitmap;
+ unsigned char tmp;
+
+ while (*bitmap == 0xff) {
+ bitmap++;
+ min_index += 8;
+ if (min_index >= MAX_FDS) {
+ errno = EMFILE;
+ debug("ERROR: MAX_FDS limit reached");
+ return -1;
+ }
+ }
+
+ tmp = *bitmap;
+
+ while (tmp & 0x80)
+ {
+ tmp <<= 1;
+ min_index++;
+ }
+
+ return min_index;
+}
+
+/* maps pio to fd (specified by index)*/
+static void
+fd_table_set(struct w32_io* pio, int index) {
+ fd_table.w32_ios[index] = pio;
+ pio->table_index = index;
+ assert(pio->type != UNKNOWN_FD);
+ FD_SET(index, &(fd_table.occupied));
+}
+
+/* removes entry at index from mapping table*/
+static void
+fd_table_clear(int index)
+{
+ fd_table.w32_ios[index]->table_index = -1;
+ fd_table.w32_ios[index] = NULL;
+ FD_CLR(index, &(fd_table.occupied));
+}
+
+void
+w32posix_initialize() {
+ if ((fd_table_initialize() != 0)
+ || (socketio_initialize() != 0))
+ DebugBreak();
+ main_thread = OpenThread(THREAD_SET_CONTEXT | SYNCHRONIZE, FALSE, GetCurrentThreadId());
+ if ((main_thread == NULL) || (sw_initialize() != 0) || w32_programdir() == NULL) {
+ DebugBreak();
+ fatal("failed to initialize w32posix wrapper");
+ }
+}
+
+void
+w32posix_done() {
+ socketio_done();
+}
+
+/* Check if the corresponding fd is set blocking */
+BOOL
+w32_io_is_blocking(struct w32_io* pio)
+{
+ return (pio->fd_status_flags & O_NONBLOCK) ? FALSE : TRUE;
+}
+
+/*
+* Check if io is ready/available. This function is primarily used by select()
+* as it decides on what fds can be set.
+*/
+BOOL
+w32_io_is_io_available(struct w32_io* pio, BOOL rd) {
+ if (pio->type == SOCK_FD)
+ return socketio_is_io_available(pio, rd);
+ else
+ return fileio_is_io_available(pio, rd);
+}
+
+void
+w32_io_on_select(struct w32_io* pio, BOOL rd)
+{
+ if ((pio->type == SOCK_FD))
+ socketio_on_select(pio, rd);
+ else
+ fileio_on_select(pio, rd);
+}
+
+#define CHECK_FD(fd) do { \
+ debug3("%s fd:%d", __FUNCTION__, fd); \
+ errno = 0; \
+ if ((fd < 0) || (fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) { \
+ errno = EBADF; \
+ debug("%s ERROR: bad fd: %d", __FUNCTION__, fd); \
+ return -1; \
+ } \
+} while (0)
+
+#define CHECK_SOCK_IO(pio) do { \
+ errno = 0; \
+ if (pio->type != SOCK_FD) { \
+ errno = ENOTSOCK; \
+ debug("%s ERROR: not sock :%d", __FUNCTION__, pio->type); \
+ return -1; \
+ } \
+} while (0)
+
+int
+w32_socket(int domain, int type, int protocol) {
+ int min_index = fd_table_get_min_index();
+ struct w32_io* pio = NULL;
+
+ errno = 0;
+ if (min_index == -1)
+ return -1;
+
+ pio = socketio_socket(domain, type, protocol);
+ if (pio == NULL)
+ return -1;
+
+ pio->type = SOCK_FD;
+ fd_table_set(pio, min_index);
+ debug("socket:%d, io:%p, fd:%d ", pio->sock, pio, min_index);
+ return min_index;
+}
+
+int
+w32_accept(int fd, struct sockaddr* addr, int* addrlen)
+{
+
+ CHECK_FD(fd);
+ CHECK_SOCK_IO(fd_table.w32_ios[fd]);
+ int min_index = fd_table_get_min_index();
+ struct w32_io* pio = NULL;
+
+ if (min_index == -1)
+ return -1;
+
+ pio = socketio_accept(fd_table.w32_ios[fd], addr, addrlen);
+ if (!pio)
+ return -1;
+
+ pio->type = SOCK_FD;
+ fd_table_set(pio, min_index);
+ debug("socket:%d, io:%p, fd:%d ", pio->sock, pio, min_index);
+ return min_index;
+}
+
+int
+w32_setsockopt(int fd, int level, int optname, const void* optval, int optlen) {
+
+ CHECK_FD(fd);
+ CHECK_SOCK_IO(fd_table.w32_ios[fd]);
+ return socketio_setsockopt(fd_table.w32_ios[fd], level, optname, (const char*)optval, optlen);
+}
+
+int
+w32_getsockopt(int fd, int level, int optname, void* optval, int* optlen) {
+
+ CHECK_FD(fd);
+ CHECK_SOCK_IO(fd_table.w32_ios[fd]);
+ return socketio_getsockopt(fd_table.w32_ios[fd], level, optname, (char*)optval, optlen);
+}
+
+int
+w32_getsockname(int fd, struct sockaddr* name, int* namelen) {
+
+ CHECK_FD(fd);
+ CHECK_SOCK_IO(fd_table.w32_ios[fd]);
+ return socketio_getsockname(fd_table.w32_ios[fd], name, namelen);
+}
+
+int
+w32_getpeername(int fd, struct sockaddr* name, int* namelen) {
+
+ CHECK_FD(fd);
+ CHECK_SOCK_IO(fd_table.w32_ios[fd]);
+ return socketio_getpeername(fd_table.w32_ios[fd], name, namelen);
+}
+
+int
+w32_listen(int fd, int backlog) {
+
+ CHECK_FD(fd);
+ CHECK_SOCK_IO(fd_table.w32_ios[fd]);
+ return socketio_listen(fd_table.w32_ios[fd], backlog);
+}
+
+int
+w32_bind(int fd, const struct sockaddr *name, int namelen) {
+
+ CHECK_FD(fd);
+ CHECK_SOCK_IO(fd_table.w32_ios[fd]);
+ return socketio_bind(fd_table.w32_ios[fd], name, namelen);
+}
+
+int
+w32_connect(int fd, const struct sockaddr* name, int namelen) {
+
+ CHECK_FD(fd);
+ CHECK_SOCK_IO(fd_table.w32_ios[fd]);
+ return socketio_connect(fd_table.w32_ios[fd], name, namelen);
+}
+
+int
+w32_recv(int fd, void *buf, size_t len, int flags) {
+
+ CHECK_FD(fd);
+ CHECK_SOCK_IO(fd_table.w32_ios[fd]);
+ return socketio_recv(fd_table.w32_ios[fd], buf, len, flags);
+}
+
+int
+w32_send(int fd, const void *buf, size_t len, int flags) {
+
+ CHECK_FD(fd);
+ CHECK_SOCK_IO(fd_table.w32_ios[fd]);
+ return socketio_send(fd_table.w32_ios[fd], buf, len, flags);
+}
+
+
+int
+w32_shutdown(int fd, int how) {
+ debug2("shutdown - fd:%d how:%d", fd, how);
+ CHECK_FD(fd);
+ CHECK_SOCK_IO(fd_table.w32_ios[fd]);
+ return socketio_shutdown(fd_table.w32_ios[fd], how);
+}
+
+int
+w32_socketpair(int domain, int type, int protocol, int sv[2]) {
+ errno = ENOTSUP;
+ debug("socketpair - ERROR not supported");
+ return -1;
+}
+
+
+int
+w32_pipe(int *pfds) {
+ int read_index, write_index;
+ struct w32_io* pio[2];
+
+ errno = 0;
+ read_index = fd_table_get_min_index();
+ if (read_index == -1)
+ return -1;
+
+ /*temporarily set occupied bit*/
+ FD_SET(read_index, &fd_table.occupied);
+ write_index = fd_table_get_min_index();
+ FD_CLR(read_index, &fd_table.occupied);
+ if (write_index == -1)
+ return -1;
+
+ if (-1 == fileio_pipe(pio))
+ return -1;
+
+ pio[0]->type = NONSOCK_FD;
+ pio[1]->type = NONSOCK_FD;
+ fd_table_set(pio[0], read_index);
+ fd_table_set(pio[1], write_index);
+ pfds[0] = read_index;
+ pfds[1] = write_index;
+ debug("pipe - r-h:%d,io:%p,fd:%d w-h:%d,io:%p,fd:%d",
+ pio[0]->handle, pio[0], read_index, pio[1]->handle, pio[1], write_index);
+ return 0;
+}
+char *realpath_win(const char *path, char resolved[MAX_PATH]);
+int
+w32_open(const char *pathname, int flags, ...) {
+ int min_index = fd_table_get_min_index();
+ struct w32_io* pio;
+
+ errno = 0;
+ if (min_index == -1)
+ return -1;
+
+ // Skip the first '/' in the pathname
+ char resolvedPathName[MAX_PATH];
+ realpath_win(pathname, resolvedPathName);
+
+ pio = fileio_open(resolvedPathName, flags, 0);
+ if (pio == NULL)
+ return -1;
+
+ pio->type = NONSOCK_FD;
+ fd_table_set(pio, min_index);
+ debug("open - handle:%p, io:%p, fd:%d", pio->handle, pio, min_index);
+ debug3("open - path:%s", resolvedPathName);
+ return min_index;
+}
+
+int
+w32_read(int fd, void *dst, size_t max) {
+ CHECK_FD(fd);
+
+ if (fd_table.w32_ios[fd]->type == SOCK_FD)
+ return socketio_recv(fd_table.w32_ios[fd], dst, max, 0);
+
+ return fileio_read(fd_table.w32_ios[fd], dst, max);
+}
+
+int
+w32_write(int fd, const void *buf, unsigned int max) {
+ CHECK_FD(fd);
+
+ if (fd_table.w32_ios[fd]->type == SOCK_FD)
+ return socketio_send(fd_table.w32_ios[fd], buf, max, 0);
+
+ return fileio_write(fd_table.w32_ios[fd], buf, max);
+}
+
+int w32_writev(int fd, const struct iovec *iov, int iovcnt) {
+ int written = 0;
+ int i = 0;
+
+ CHECK_FD(fd);
+
+ for (i = 0; i < iovcnt; i++) {
+ int ret = w32_write(fd, iov[i].iov_base, iov[i].iov_len);
+
+ if (ret > 0) {
+ written += ret;
+ }
+ }
+
+ return written;
+}
+
+int
+w32_fstat(int fd, struct w32_stat *buf) {
+ CHECK_FD(fd);
+ return fileio_fstat(fd_table.w32_ios[fd], (struct _stat64*)buf);
+}
+
+long
+w32_lseek(int fd, long offset, int origin) {
+ CHECK_FD(fd);
+ return fileio_lseek(fd_table.w32_ios[fd], offset, origin);
+}
+
+int
+w32_isatty(int fd) {
+ struct w32_io* pio;
+ if ((fd < 0) || (fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) {
+ errno = EBADF;
+ return 0;
+ }
+
+ pio = fd_table.w32_ios[fd];
+
+ if (FILETYPE(pio) == FILE_TYPE_CHAR)
+ return 1;
+ else {
+ errno = EINVAL;
+ return 0;
+ }
+}
+
+FILE*
+w32_fdopen(int fd, const char *mode) {
+ errno = 0;
+ if ((fd < 0) || (fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) {
+ errno = EBADF;
+ debug("fdopen - ERROR bad fd: %d", fd);
+ return NULL;
+ }
+ return fileio_fdopen(fd_table.w32_ios[fd], mode);
+}
+
+int
+w32_close(int fd) {
+ struct w32_io* pio;
+
+ if ((fd < 0) || (fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ pio = fd_table.w32_ios[fd];
+
+ debug("close - io:%p, type:%d, fd:%d, table_index:%d", pio, pio->type, fd,
+ pio->table_index);
+ fd_table_clear(pio->table_index);
+
+ if (pio->type == SOCK_FD)
+ return socketio_close(pio);
+ else
+ switch (FILETYPE(pio)) {
+ case FILE_TYPE_CHAR:
+ return termio_close(pio);
+ default:
+ return fileio_close(pio);
+ }
+}
+
+static int
+w32_io_process_fd_flags(struct w32_io* pio, int flags) {
+ DWORD shi_flags;
+ if (flags & ~FD_CLOEXEC) {
+ debug("fcntl - ERROR unsupported flags %d, io:%p", flags, pio);
+ errno = ENOTSUP;
+ return -1;
+ }
+
+ shi_flags = (flags & FD_CLOEXEC) ? 0 : HANDLE_FLAG_INHERIT;
+
+ if (SetHandleInformation(WINHANDLE(pio), HANDLE_FLAG_INHERIT, shi_flags) == FALSE) {
+ debug("fcntl - SetHandleInformation failed %d, io:%p",
+ GetLastError(), pio);
+ errno = EOTHER;
+ return -1;
+ }
+
+ pio->fd_flags = flags;
+ return 0;
+}
+
+int
+w32_fcntl(int fd, int cmd, ... /* arg */) {
+ va_list valist;
+ va_start(valist, cmd);
+ int ret = 0;
+
+ CHECK_FD(fd);
+
+ switch (cmd) {
+ case F_GETFL:
+ ret = fd_table.w32_ios[fd]->fd_status_flags;
+ break;
+ case F_SETFL:
+ fd_table.w32_ios[fd]->fd_status_flags = va_arg(valist, int);
+ ret = 0;
+ break;
+ case F_GETFD:
+ ret = fd_table.w32_ios[fd]->fd_flags;
+ break;
+ case F_SETFD:
+ ret = w32_io_process_fd_flags(fd_table.w32_ios[fd], va_arg(valist, int));
+ break;
+ default:
+ errno = EINVAL;
+ debug("fcntl - ERROR not supported cmd:%d", cmd);
+ ret = -1;
+ break;
+ }
+
+ va_end(valist);
+ return ret;
+}
+
+#define SELECT_EVENT_LIMIT 32
+int
+w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* exceptfds,
+ const struct timeval *timeout) {
+ ULONGLONG ticks_start = GetTickCount64(), ticks_spent;
+ w32_fd_set read_ready_fds, write_ready_fds;
+ HANDLE events[SELECT_EVENT_LIMIT];
+ int num_events = 0;
+ int in_set_fds = 0, out_ready_fds = 0, i;
+ unsigned int timeout_ms = 0, time_rem = 0;
+
+ errno = 0;
+ /* TODO - the size of these can be reduced based on fds */
+ memset(&read_ready_fds, 0, sizeof(w32_fd_set));
+ memset(&write_ready_fds, 0, sizeof(w32_fd_set));
+
+ if (timeout)
+ timeout_ms = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
+
+ if (fds > MAX_FDS) {
+ errno = EINVAL;
+ debug("select - ERROR: invalid fds: %d", fds);
+ return -1;
+ }
+
+ if (!readfds && !writefds) {
+ errno = EINVAL;
+ debug("select - ERROR: null fd_sets");
+ return -1;
+ }
+
+ /* TODO - see if this needs to be supported */
+ //if (exceptfds) {
+ // errno = EOPNOTSUPP;
+ // debug("select - ERROR: exceptfds not supported");
+ // DebugBreak();
+ // return -1;
+ //}
+
+ if (readfds) {
+ for (i = 0; i < fds; i++)
+ if (FD_ISSET(i, readfds)) {
+ CHECK_FD(i);
+ in_set_fds++;
+ }
+ }
+
+ if (writefds) {
+ for (i = 0; i < fds; i++)
+ if (FD_ISSET(i, writefds)) {
+ CHECK_FD(i);
+ in_set_fds++;
+ }
+ }
+
+ /* if none of input fds are set return error */
+ if (in_set_fds == 0) {
+ errno = EINVAL;
+ debug("select - ERROR: empty fd_sets");
+ return -1;
+ }
+
+ debug3("Total in fds:%d", in_set_fds);
+ /*
+ * start async io on selected fds if needed and pick up any events
+ * that select needs to listen on
+ */
+ for (int i = 0; i < fds; i++) {
+
+ if (readfds && FD_ISSET(i, readfds)) {
+ w32_io_on_select(fd_table.w32_ios[i], TRUE);
+ if ((fd_table.w32_ios[i]->type == SOCK_FD)
+ && (fd_table.w32_ios[i]->internal.state == SOCK_LISTENING)) {
+ if (num_events == SELECT_EVENT_LIMIT) {
+ debug("select - ERROR: max #events breach");
+ errno = ENOMEM;
+ return -1;
+ }
+ events[num_events++] = fd_table.w32_ios[i]->read_overlapped.hEvent;
+ }
+ }
+
+ if (writefds && FD_ISSET(i, writefds)) {
+ w32_io_on_select(fd_table.w32_ios[i], FALSE);
+ if ((fd_table.w32_ios[i]->type == SOCK_FD)
+ && (fd_table.w32_ios[i]->internal.state == SOCK_CONNECTING)) {
+ if (num_events == SELECT_EVENT_LIMIT) {
+ debug("select - ERROR: max #events reached for select");
+ errno = ENOMEM;
+ return -1;
+ }
+ events[num_events++] = fd_table.w32_ios[i]->write_overlapped.hEvent;
+ }
+ }
+ }
+
+ /* excute any scheduled APCs */
+ if (0 != wait_for_any_event(NULL, 0, 0))
+ return -1;
+
+ /* see if any io is ready */
+ for (i = 0; i < fds; i++) {
+
+ if (readfds && FD_ISSET(i, readfds)) {
+ if (w32_io_is_io_available(fd_table.w32_ios[i], TRUE)) {
+ FD_SET(i, &read_ready_fds);
+ out_ready_fds++;
+ }
+ }
+
+ if (writefds && FD_ISSET(i, writefds)) {
+ if (w32_io_is_io_available(fd_table.w32_ios[i], FALSE)) {
+ FD_SET(i, &write_ready_fds);
+ out_ready_fds++;
+ }
+ }
+ }
+
+
+ /* timeout specified and both fields are 0 - polling mode*/
+ /* proceed with further wait if not in polling mode*/
+ if ((timeout == NULL) || (timeout_ms != 0))
+ /* wait for io until any is ready */
+ while (out_ready_fds == 0) {
+ ticks_spent = GetTickCount64() - ticks_start;
+ time_rem = 0;
+
+ if (timeout != NULL) {
+ if (timeout_ms < ticks_spent) {
+ debug("select - timing out");
+ break;
+ }
+ time_rem = timeout_ms - (ticks_spent & 0xffffffff);
+ }
+ else
+ time_rem = INFINITE;
+
+ if (0 != wait_for_any_event(events, num_events, time_rem))
+ return -1;
+
+ /* check on fd status */
+ out_ready_fds = 0;
+ for (int i = 0; i < fds; i++) {
+
+ if (readfds && FD_ISSET(i, readfds)) {
+ if (w32_io_is_io_available(fd_table.w32_ios[i], TRUE)) {
+ FD_SET(i, &read_ready_fds);
+ out_ready_fds++;
+ }
+ }
+
+ if (writefds && FD_ISSET(i, writefds)) {
+ if (w32_io_is_io_available(fd_table.w32_ios[i], FALSE)) {
+ FD_SET(i, &write_ready_fds);
+ out_ready_fds++;
+ }
+ }
+ }
+
+ if (out_ready_fds == 0)
+ debug3("select - wait ended without any IO completion, looping again");
+
+ }
+
+ /* clear out fds that are not ready yet */
+ if (readfds)
+ for (i = 0; i < fds; i++)
+ if (FD_ISSET(i, readfds) && (!FD_ISSET(i, &read_ready_fds)))
+ FD_CLR(i, readfds);
+
+ if (writefds)
+ for (i = 0; i < fds; i++)
+ if (FD_ISSET(i, writefds)) {
+ if (FD_ISSET(i, &write_ready_fds)) {
+ /* for connect() completed sockets finish WSA connect process*/
+ if ((fd_table.w32_ios[i]->type == SOCK_FD)
+ && ((fd_table.w32_ios[i]->internal.state == SOCK_CONNECTING)))
+ if (socketio_finish_connect(fd_table.w32_ios[i]) != 0) {
+ /* finalizeing connect failed - recored error */
+ /* error gets picked up later recv and/or send*/
+ fd_table.w32_ios[i]->read_details.error = errno;
+ fd_table.w32_ios[i]->write_details.error = errno;
+ fd_table.w32_ios[i]->internal.state = SOCK_CONNECTED;
+ errno = 0;
+ }
+ }
+ else
+ FD_CLR(i, writefds);
+ }
+
+ debug3("select - returning %d", out_ready_fds);
+ return out_ready_fds;
+
+}
+
+int
+w32_dup(int oldfd) {
+ int min_index;
+ struct w32_io* pio;
+ HANDLE src, target;
+ CHECK_FD(oldfd);
+ if (oldfd > STDERR_FILENO) {
+ errno = EOPNOTSUPP;
+ debug("dup - ERROR: supports only std io, fd:%d", oldfd);
+ return -1;
+ }
+
+ if ((min_index = fd_table_get_min_index()) == -1)
+ return -1;
+
+ src = GetStdHandle(fd_table.w32_ios[oldfd]->std_handle);
+ if (src == INVALID_HANDLE_VALUE) {
+ errno = EINVAL;
+ debug("dup - ERROR: unable to get underlying handle for std fd:%d", oldfd);
+ return -1;
+ }
+
+ if (!DuplicateHandle(GetCurrentProcess(), src, GetCurrentProcess(), &target, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
+ errno = EOTHER;
+ debug("dup - ERROR: DuplicatedHandle() :%d", GetLastError());
+ return -1;
+ }
+
+ pio = (struct w32_io*) malloc(sizeof(struct w32_io));
+ if (pio == NULL) {
+ CloseHandle(target);
+ errno = ENOMEM;
+ debug("dup - ERROR: %d", errno);
+ return -1;
+ }
+
+ memset(pio, 0, sizeof(struct w32_io));
+ pio->handle = target;
+ pio->type = NONSOCK_FD;
+ fd_table_set(pio, min_index);
+ return min_index;
+}
+
+int
+w32_dup2(int oldfd, int newfd) {
+ CHECK_FD(oldfd);
+ errno = EOPNOTSUPP;
+ debug("dup2 - ERROR: not implemented yet");
+ return -1;
+}
+
+HANDLE
+w32_fd_to_handle(int fd) {
+ HANDLE h = fd_table.w32_ios[fd]->handle;
+ if (fd <= STDERR_FILENO)
+ h = GetStdHandle(fd_table.w32_ios[fd]->std_handle);
+ return h;
+}
+
+int w32_allocate_fd_for_handle(HANDLE h, BOOL is_sock) {
+ int min_index = fd_table_get_min_index();
+ struct w32_io* pio;
+
+ if (min_index == -1) {
+ return -1;
+ }
+
+ pio = malloc(sizeof(struct w32_io));
+ if (pio == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ memset(pio, 0, sizeof(struct w32_io));
+
+ pio->type = is_sock? SOCK_FD : NONSOCK_FD;
+ pio->handle = h;
+ fd_table_set(pio, min_index);
+ return min_index;
+}
+
+
+unsigned int
+w32_alarm(unsigned int seconds) {
+ return sw_alarm(seconds);;
+}
+sighandler_t
+w32_signal(int signum, sighandler_t handler) {
+ return sw_signal(signum, handler);
+}
+
+int
+w32_sigprocmask(int how, const sigset_t *set, sigset_t *oldset) {
+ return sw_sigprocmask(how, set, oldset);
+}
+
+int
+w32_raise(int sig) {
+ return sw_raise(sig);
+}
+
+int
+w32_kill(int pid, int sig) {
+ return sw_kill(pid, sig);
+}
+
+int
+w32_ftruncate(int fd, off_t length) {
+ CHECK_FD(fd);
+
+ if (!SetFilePointer(w32_fd_to_handle(fd), length, 0, FILE_BEGIN))
+ return -1;
+ if (!SetEndOfFile(w32_fd_to_handle(fd)))
+ return -1;
+
+ return 0;
+}
+
+int
+w32_fsync(int fd) {
+ CHECK_FD(fd);
+
+ return FlushFileBuffers(w32_fd_to_handle(fd));
+}
diff --git a/contrib/win32/win32compat/w32fd.h b/contrib/win32/win32compat/w32fd.h
new file mode 100644
index 000000000..0cb3a3453
--- /dev/null
+++ b/contrib/win32/win32compat/w32fd.h
@@ -0,0 +1,161 @@
+/*
+ * Author: Manoj Ampalam
+ *
+ * Definitions for Win32 wrapper functions with POSIX like signatures
+*/
+
+#pragma once
+
+#include
+#include
+#include "inc\defs.h"
+
+enum w32_io_type {
+ UNKNOWN_FD = 0,
+ SOCK_FD = 1, /*maps a socket fd*/
+ NONSOCK_FD = 2, /*maps a file fd, pipe fd or a tty fd*/
+ STD_IO_FD = 5 /*maps a std fd - ex. STDIN_FILE*/
+};
+
+enum w32_io_sock_state {
+ SOCK_INITIALIZED = 0,
+ SOCK_LISTENING = 1, /*listen called on socket*/
+ SOCK_ACCEPTED = 2, /*socket returned from accept()*/
+ SOCK_CONNECTING = 3, /*connect called on socket, connect is in progress*/
+ SOCK_CONNECTED = 4 /*connect completed on socket*/
+};
+
+/*
+* This structure encapsulates the state info needed to map a File Descriptor
+* to Win32 Handle
+*/
+struct w32_io {
+ OVERLAPPED read_overlapped;
+ OVERLAPPED write_overlapped;
+ struct {
+ /*internal read buffer*/
+ char *buf;
+ DWORD buf_size;
+ /*bytes in internal buffer remaining to be read by application*/
+ DWORD remaining;
+ /*bytes in internal buffer already read by application*/
+ DWORD completed;
+ BOOL pending; /*waiting on a read operation to complete*/
+ DWORD error; /*error reported on async read or accept completion*/
+ }read_details;
+ struct {
+ /*internal write buffer*/
+ char *buf;
+ DWORD buf_size;
+ /*bytes in internal buffer remaining to be written to network*/
+ DWORD remaining;
+ /*bytes in internal buffer already written to network*/
+ DWORD completed;
+ BOOL pending; /*waiting on a write operation to complete*/
+ DWORD error; /*error reported on async write or connect completion*/
+ }write_details;
+
+ /*index at which this object is stored in fd_table*/
+ int table_index;
+ enum w32_io_type type; /*hanldle type*/
+ DWORD fd_flags; /*fd flags from POSIX*/
+ DWORD fd_status_flags; /*fd status flags from POSIX*/
+
+ /*underlying w32 handle*/
+ union {
+ SOCKET sock;
+ HANDLE handle;
+ DWORD std_handle; /* ex. STD_INPUT_HANDLE */
+ };
+
+ /*handle specific internal state context, used by sockets and pipes*/
+ struct {
+ enum w32_io_sock_state state;
+ void* context;
+ }internal;
+};
+
+#define WINHANDLE(pio) (((pio)->type == STD_IO_FD)? GetStdHandle((pio)->std_handle):(pio)->handle)
+#define FILETYPE(pio) (GetFileType(WINHANDLE(pio)))
+extern HANDLE main_thread;
+
+BOOL w32_io_is_blocking(struct w32_io*);
+BOOL w32_io_is_io_available(struct w32_io* pio, BOOL rd);
+int wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds);
+
+/*POSIX mimic'ing socket API*/
+int socketio_initialize();
+int socketio_done();
+BOOL socketio_is_io_available(struct w32_io* pio, BOOL rd);
+void socketio_on_select(struct w32_io* pio, BOOL rd);
+struct w32_io* socketio_socket(int domain, int type, int protocol);
+struct w32_io* socketio_accept(struct w32_io* pio, struct sockaddr* addr, int* addrlen);
+int socketio_setsockopt(struct w32_io* pio, int level, int optname,
+ const char* optval, int optlen);
+int socketio_getsockopt(struct w32_io* pio, int level, int optname,
+ char* optval, int* optlen);
+int socketio_getsockname(struct w32_io* pio, struct sockaddr* name, int* namelen);
+int socketio_getpeername(struct w32_io* pio, struct sockaddr* name, int* namelen);
+int socketio_listen(struct w32_io* pio, int backlog);
+int socketio_bind(struct w32_io* pio, const struct sockaddr *name, int namelen);
+int socketio_connect(struct w32_io* pio, const struct sockaddr* name, int namelen);
+int socketio_finish_connect(struct w32_io* pio);
+int socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags);
+int socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags);
+int socketio_shutdown(struct w32_io* pio, int how);
+int socketio_close(struct w32_io* pio);
+
+/*POSIX mimic'ing file API*/
+BOOL fileio_is_io_available(struct w32_io* pio, BOOL rd);
+void fileio_on_select(struct w32_io* pio, BOOL rd);
+int fileio_close(struct w32_io* pio);
+int fileio_pipe(struct w32_io* pio[2]);
+struct w32_io* fileio_open(const char *pathname, int flags, int mode);
+int fileio_read(struct w32_io* pio, void *dst, unsigned int max);
+int fileio_write(struct w32_io* pio, const void *buf, unsigned int max);
+int fileio_fstat(struct w32_io* pio, struct _stat64 *buf);
+int fileio_stat(const char *path, struct _stat64 *buf);
+long fileio_lseek(struct w32_io* pio, long offset, int origin);
+FILE* fileio_fdopen(struct w32_io* pio, const char *mode);
+
+/* terminal io specific versions */
+int termio_close(struct w32_io* pio);
+
+/*
+* open() flags and modes
+* all commented out macros are defined in fcntl.h
+* they are listed here so as to cross check any conflicts with macros explicitly
+* defined below.
+*/
+/*open access modes. only one of these can be specified*/
+/* #define O_RDONLY 0x0 */
+/* #define O_WRONLY 0x1 */
+/* #define O_RDWR 0x2 */
+/* open file creation and file status flags can be bitwise-or'd*/
+/* #define O_APPEND 0x8 /*file is opened in append mode*/
+#ifndef O_NONBLOCK
+#define O_NONBLOCK 0x0004 /*io operations wont block*/
+#endif
+/* #define O_CREAT 0x100 /*If the file does not exist it will be created*/
+/*
+* If the file exists and is a regular file, and the file is successfully
+* opened O_RDWR or O_WRONLY, its length shall be truncated to 0, and the mode
+* and owner shall be unchanged
+*/
+/* #define O_TRUNC 0x200 */
+/* If O_CREAT and O_EXCL are set, open() shall fail if the file exists */
+/* #define O_EXCL 0x400 */
+/* #define O_BINARY 0x8000 //Gives raw data (while O_TEXT normalises line endings */
+// open modes
+#ifndef S_IRUSR
+#define S_IRUSR 00400 //user has read permission
+#endif // ! S_IRUSR
+#ifndef S_IWUSR
+#define S_IWUSR 00200 //user has write permission
+#endif
+#ifndef S_IRGRP
+#define S_IRGRP 00040 //group has read permission
+#endif
+#ifndef S_IROTH
+#define S_IROTH 00004 //others have read permission
+#endif
\ No newline at end of file
diff --git a/contrib/win32/win32compat/w32log.c b/contrib/win32/win32compat/w32log.c
new file mode 100644
index 000000000..06f2f4b41
--- /dev/null
+++ b/contrib/win32/win32compat/w32log.c
@@ -0,0 +1,56 @@
+
+#include
+#include
+#include
+#include
+#include "inc\syslog.h"
+
+#define MSGBUFSIZ 1024
+static int logfd = -1;
+
+void openlog(char *ident, unsigned int option, int facility) {
+ if ((logfd == -1) && (ident != NULL)) {
+ wchar_t path[MAX_PATH], log_file[MAX_PATH + 12];
+ if (GetModuleFileNameW(NULL, path, MAX_PATH) == 0)
+ return;
+ path[MAX_PATH - 1] = '\0';
+ /* split path root and module */
+ {
+ wchar_t* tail = path + wcslen(path), *p;
+ while (tail > path && *tail != L'\\' && *tail != L'/')
+ tail--;
+
+ memcpy(log_file, path, (tail - path) * sizeof(wchar_t));
+ p = log_file + (tail - path);
+ memcpy(p, L"\\logs\\", 12);
+ p += 6;
+ memcpy(p, tail + 1, (wcslen(tail + 1) - 3) * sizeof(wchar_t));
+ p += wcslen(tail + 1) - 3;
+ memcpy(p, L"log\0", 8);
+ }
+ logfd = _wopen(log_file, O_WRONLY | O_CREAT | O_APPEND,
+ S_IREAD | S_IWRITE);
+ if (logfd != -1)
+ SetHandleInformation((HANDLE)_get_osfhandle(logfd),
+ HANDLE_FLAG_INHERIT, 0);
+ }
+}
+
+void closelog(void) {
+ //NOOP
+}
+
+void
+syslog(int priority, const char *format, const char *formatBuffer) {
+ char msgbufTimestamp[MSGBUFSIZ];
+ SYSTEMTIME st;
+
+ if (logfd == -1)
+ return;
+
+ GetLocalTime(&st);
+ snprintf(msgbufTimestamp, sizeof msgbufTimestamp, "%d %02d:%02d:%02d %03d %s\n",
+ GetCurrentProcessId(), st.wHour, st.wMinute, st.wSecond,
+ st.wMilliseconds, formatBuffer);
+ _write(logfd, msgbufTimestamp, strlen(msgbufTimestamp));
+}
\ No newline at end of file
diff --git a/contrib/win32/win32compat/win32_dirent.c b/contrib/win32/win32compat/win32_dirent.c
new file mode 100644
index 000000000..e00937533
--- /dev/null
+++ b/contrib/win32/win32compat/win32_dirent.c
@@ -0,0 +1,131 @@
+// win32_dirent.c
+// directory entry functions in Windows platform like Ubix/Linux
+// opendir(), readdir(), closedir().
+
+#include
+#include
+#include
+#include
+#include
+#include "inc\utf.h"
+
+#include "inc\dirent.h"
+#include "inc\libgen.h"
+
+
+struct DIR_ {
+ intptr_t hFile;
+ struct _wfinddata_t c_file;
+ int first;
+};
+
+char * realpath_win(const char *path, char resolved[MAX_PATH]);
+
+/* Open a directory stream on NAME.
+ Return a DIR stream on the directory, or NULL if it could not be opened. */
+DIR * opendir(const char *name)
+{
+ struct _wfinddata_t c_file;
+ intptr_t hFile;
+ DIR *pdir;
+ wchar_t searchstr[MAX_PATH];
+ wchar_t* wname = NULL;
+ int needed;
+
+ // Skip the first '/' in the pathname
+ char resolvedPathName[MAX_PATH];
+ realpath_win(name, resolvedPathName);
+
+ if ((wname = utf8_to_utf16(resolvedPathName)) == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ // add *.* for Windows _findfirst() search pattern
+ swprintf_s(searchstr, MAX_PATH, L"%s\\*.*", wname);
+ free(wname);
+
+ if ((hFile = _wfindfirst(searchstr, &c_file)) == -1L)
+ return NULL; /* errno is set by _wfindfirst */
+ else {
+ if ((pdir = malloc(sizeof(DIR))) == NULL) {
+ _findclose(hFile);
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ memset(pdir, 0, sizeof(DIR));
+ pdir->hFile = hFile;
+ memcpy(&pdir->c_file, &c_file, sizeof(c_file));
+ pdir->first = 1;
+
+ return pdir ;
+ }
+}
+
+/* Close the directory stream DIRP.
+ Return 0 if successful, -1 if not. */
+int closedir(DIR *dirp)
+{
+ if ( dirp && (dirp->hFile) ) {
+ _findclose( dirp->hFile );
+ dirp->hFile = 0;
+ free (dirp);
+ }
+
+ return 0;
+}
+
+/* Read a directory entry from DIRP.
+ Return a pointer to a `struct dirent' describing the entry,
+ or NULL for EOF or error. The storage returned may be overwritten
+ by a later readdir call on the same DIR stream. */
+struct dirent *readdir(void *avp)
+{
+ struct dirent *pdirentry;
+ struct _wfinddata_t c_file;
+ DIR *dirp = (DIR *)avp;
+ char *tmp = NULL;
+
+ for (;;) {
+ if (dirp->first) {
+ memcpy(&c_file, &dirp->c_file, sizeof(c_file));
+ dirp->first = 0;
+ }
+ else if (_wfindnext(dirp->hFile, &c_file) != 0)
+ return NULL;
+
+ if (wcscmp(c_file.name, L".") == 0 || wcscmp(c_file.name, L"..") == 0 )
+ continue;
+
+ if ((pdirentry = malloc(sizeof(struct dirent))) == NULL ||
+ (tmp = utf16_to_utf8(c_file.name)) == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ strncpy(pdirentry->d_name, tmp, strlen(tmp) + 1);
+ free(tmp);
+
+ pdirentry->d_ino = 1; // a fictious one like UNIX to say it is nonzero
+ return pdirentry ;
+ }
+}
+
+// return last part of a path. The last path being a filename.
+char *basename(char *path)
+{
+ char *pdest;
+
+ if (!path)
+ return ".";
+ pdest = strrchr(path, '/');
+ if (pdest)
+ return (pdest+1);
+ pdest = strrchr(path, '\\');
+ if (pdest)
+ return (pdest+1);
+
+ return path; // path does not have a slash
+}
+// end of dirent functions in Windows
diff --git a/contrib/win32/win32compat/win32_zlib.c b/contrib/win32/win32compat/win32_zlib.c
new file mode 100644
index 000000000..0302ff815
--- /dev/null
+++ b/contrib/win32/win32compat/win32_zlib.c
@@ -0,0 +1,64 @@
+/*
+* Author: Manoj Ampalam
+*
+* Implementation of POSIX APIs
+*
+* Copyright (c) 2016 Microsoft Corp.
+* All rights reserved
+*
+* Dummy implementations of zlib routines used by OpenSSH
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* 1. Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "inc\zlib.h"
+
+
+int
+deflateEnd(z_streamp strm) {
+ return Z_DATA_ERROR;
+}
+
+int
+inflateEnd(z_streamp strm) {
+ return Z_DATA_ERROR;
+}
+
+int
+deflateInit(z_streamp strm, int level) {
+ return Z_DATA_ERROR;
+}
+
+int
+inflateInit(z_streamp strm) {
+ return Z_DATA_ERROR;
+}
+
+int
+deflate(z_streamp strm, int flush) {
+ return Z_DATA_ERROR;
+}
+
+int
+inflate(z_streamp strm, int flush) {
+ return Z_DATA_ERROR;
+}
diff --git a/contrib/win32/win32compat/win32compat.vcproj b/contrib/win32/win32compat/win32compat.vcproj
new file mode 100644
index 000000000..1de0f2545
--- /dev/null
+++ b/contrib/win32/win32compat/win32compat.vcproj
@@ -0,0 +1,311 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+