--- /dev/null
+#!python -u
+
+import os, sys
+import datetime
+import re
+import glob
+import tarfile
+import subprocess
+import shutil
+import time
+
+def get_configuration(release, debug):
+ configuration = release
+
+ if debug:
+ configuration += ' Debug'
+ else:
+ configuration += ' Release'
+
+ return configuration
+
+
+def get_target_path(release, arch, debug, vs):
+ configuration = get_configuration(release, debug)
+ name = ''.join(configuration.split(' '))
+ target = { 'x86': os.sep.join([name, 'Win32']), 'x64': os.sep.join([name, 'x64']) }
+ target_path = os.sep.join([vs, target[arch]])
+
+ return target_path
+
+
+def shell(command, dir):
+ print(dir)
+ print(command)
+ sys.stdout.flush()
+
+ sub = subprocess.Popen(' '.join(command), cwd=dir,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+
+ for line in sub.stdout:
+ print(line.decode(sys.getdefaultencoding()).rstrip())
+
+ sub.wait()
+
+ return sub.returncode
+
+
+class msbuild_failure(Exception):
+ def __init__(self, value):
+ self.value = value
+ def __str__(self):
+ return repr(self.value)
+
+def msbuild(platform, configuration, target, file, args, dir):
+ os.environ['PLATFORM'] = platform
+ os.environ['CONFIGURATION'] = configuration
+ os.environ['TARGET'] = target
+ os.environ['FILE'] = file
+ os.environ['EXTRA'] = args
+
+ bin = os.path.join(os.getcwd(), 'msbuild.bat')
+
+ status = shell([bin], dir)
+
+ if (status != 0):
+ raise msbuild_failure(configuration)
+
+
+def build_sln(name, release, arch, debug, vs):
+ configuration = get_configuration(release, debug)
+
+ if arch == 'x86':
+ platform = 'Win32'
+ elif arch == 'x64':
+ platform = 'x64'
+
+ cwd = os.getcwd()
+
+ msbuild(platform, configuration, 'Build', name + '.sln', '', vs)
+
+
+def copy_output(name, release, arch, debug, vs):
+ configuration = get_configuration(release, debug)
+ dst = os.path.join(name, arch)
+
+ if arch == 'x86':
+ src = vs
+ elif arch == 'x64':
+ src = os.path.join(vs, arch)
+
+ src = os.path.join(src, ''.join(configuration.split(' ')))
+
+ os.makedirs(dst, exist_ok=True)
+
+ files = glob.glob(os.path.join(src, '*.exe'))
+ files += glob.glob(os.path.join(src, '*.pdb'))
+
+ for file in files:
+ shutil.copy(file, dst)
+
+
+def archive(filename, files, tgz=False):
+ print(filename)
+ access='w'
+ if tgz:
+ access='w:gz'
+ tar = tarfile.open(filename, access)
+ for name in files :
+ try:
+ tar.add(name)
+ except:
+ pass
+ tar.close()
+
+
+def getVsVersion():
+ vsenv ={}
+ vars = subprocess.check_output([os.environ['VS']+'\\VC\\vcvarsall.bat', '&&', 'set'], shell=True)
+ for var in vars.splitlines():
+ k, _, v = map(str.strip, var.strip().decode('utf-8').partition('='))
+ if k.startswith('?'):
+ continue
+ vsenv[k] = v
+
+ mapping = { '11.0':'vs2012',
+ '12.0':'vs2013',
+ '14.0':'vs2015' }
+
+ return mapping[vsenv['VisualStudioVersion']]
+
+
+if __name__ == '__main__':
+ debug = { 'checked': True, 'free': False }
+ util = 'sockpipe'
+ vs = getVsVersion()
+ release = { 'vs2012':'Windows Vista',
+ 'vs2013':'Windows 7',
+ 'vs2015':'Windows 8' }
+
+ build_sln(util, release[vs], 'x86', debug[sys.argv[1]], vs)
+ build_sln(util, release[vs], 'x64', debug[sys.argv[1]], vs)
+
+ copy_output(util, release[vs], 'x86', debug[sys.argv[1]], vs)
+ copy_output(util, release[vs], 'x64', debug[sys.argv[1]], vs)
+
+ archive(util + '.tar', [util])
--- /dev/null
+#!/usr/bin/env python
+
+import os, sys, shutil
+
+if __name__ == '__main__':
+ file = os.popen('git status -u --porcelain')
+
+ for line in file:
+ item = line.split(' ')
+ if item[0] == '??':
+ path = ' '.join(item[1:]).rstrip()
+ print(path)
+ try:
+ if os.path.isfile(path):
+ os.remove(path)
+ if os.path.isdir(path):
+ shutil.rmtree(path)
+ except OSError:
+ None
+
+ file.close()
--- /dev/null
+call "%VS%\VC\vcvarsall.bat" x86
+@echo on
+msbuild.exe /m:1 /p:Configuration="%CONFIGURATION%" /p:Platform="%PLATFORM%" /t:"%TARGET%" %EXTRA% %FILE%
+if errorlevel 1 goto error
+exit 0
+
+:error
+exit 1
--- /dev/null
+//
+// Circular buffer.
+//
+// This class implements a circular buffer for data movement. The buffer
+// utilizes a pair of pointers, in and out, that chase each other.
+//
+// in is the offset of the next byte in the buffer where data can be inserted.
+// out is the offset of the next byte in the buffer to be removed.
+//
+// in == out means the buffer is empty. in one behind out means the buffer is
+// full.
+//
+// in is only ever updated by producers, out is only updated by consumers. If
+// there are multiple producers, in must be protected by a lock, if there are
+// multiple consumers, out must be protected by a lock.
+//
+// In the following, in > out, new data can be inserted at in and in can wrap
+// around to but not catch up out. Data from out to in is available.
+//
+// +------------------------------------------------------------+
+// | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX |
+// +------------------------------------------------------------+
+// ^out ^in
+//
+// When in < out, the already inserted data wraps around the buffer.
+//
+// +------------------------------------------------------------+
+// |XXXX XXXXXXXXXXXXXXXXXXXX|
+// +------------------------------------------------------------+
+// ^in ^out
+//
+
+#include "stdafx.h"
+#include <windows.h>
+#include "plj_utils.h"
+#include "circle.h"
+
+Circle::Circle()
+{
+ buffer = NULL;
+ in = 0;
+ out = 0;
+ length = 0;
+
+ waitEvent = INVALID_HANDLE_VALUE;
+ waitCount = 0;
+}
+
+Circle::~Circle()
+{
+ if (buffer != NULL)
+ {
+ delete buffer;
+ }
+}
+
+bool Circle::Initialize(int size)
+{
+ buffer = new char[size];
+ if (buffer == NULL)
+ {
+ die("failed to allocate circular buffer of %d bytes.", size);
+ }
+ length = size;
+
+ waitEvent = CreateEvent(NULL, false, false, NULL);
+
+ if (waitEvent == INVALID_HANDLE_VALUE)
+ {
+ // I don't think this can happen, but, ...
+ die("failed to create wait handle for circular buffer.");
+ }
+ return true;
+}
+
+void Circle::WaitUntilNotFull()
+{
+ if (QueryInsertable() == 0)
+ {
+ InterlockedIncrement(&waitCount);
+ WaitForSingleObject(waitEvent, INFINITE);
+ }
+}
+
+int Circle::QueryInsertable()
+{
+ //
+ // Calculate and return the number of bytes that can be inserted into the
+ // buffer.
+ //
+ // Note: The number of bytes that can be inserted is one less than the
+ // number of free bytes. This is so the 'in' pointer doesn't colide with
+ // the 'out' pointer, in == out is buffer empty, not buffer full.
+ //
+
+ int tin = in;
+ int tout = out;
+
+ if (tin == tout)
+ {
+ //
+ // buffer is empty.
+ //
+
+ return length - 1;
+ }
+ if (tin > tout)
+ {
+ return tout + (length - tin) - 1;
+ }
+
+ // else (in < out)
+
+ return tout - tin - 1;
+}
+
+int Circle::QueryRetrievable()
+{
+ int tin = in;
+ int tout = out;
+
+ if (tin >= tout)
+ {
+ return tin - tout;
+ }
+
+ // else (in < out)
+
+ return tin + (length - tout);
+}
+
+int Circle::Insert(char * data, int len)
+{
+ //
+ // Add data to the circular buffer. This routine is non-blocking.
+ // The amount of data added to the buffer is returned, that amount
+ // can be less than provided.
+ //
+ // If multiple providers, 'in' must be protected by a lock.
+ //
+
+ int insert = QueryInsertable();
+ int tin = in;
+ char * to = buffer + tin;
+
+ if (len < insert)
+ {
+ insert = len;
+ }
+ int inserted = insert;
+
+ if (in >= out)
+ {
+ //
+ // Determine if the insertion wraps around the end of the buffer in
+ // which case we'll need to do two copies.
+ //
+
+ int here = length - tin;
+
+ if (here < insert)
+ {
+ //
+ // Need to split the insertion into two parts, the copy to the
+ // top part of the buffer and the copy to the low. Do the top
+ // copy here and set things up to fall thru and do the bottom
+ // part.
+ //
+
+ RtlCopyMemory(to, data, here);
+ insert -= here;
+ data += here;
+ tin = 0;
+ to = buffer;
+ }
+ else if (here == insert)
+ {
+ //
+ // This insertion fits in the top of the buffer .. exactly ..
+ // need to wrap the in pointer as the next time the insertion
+ // will go to the start of the buffer. Fall thru and do the
+ // single copy below.
+ //
+
+ tin = -insert;
+ }
+ }
+ tin += insert;
+ ASSERT(tin < length);
+ RtlCopyMemory(to, data, insert);
+ in = tin;
+ return inserted;
+}
+
+int Circle::Retrieve(char * bp, int len)
+{
+ int tin = in;
+ int tout = out;
+ int tlen;
+
+ if (tin == tout)
+ {
+ return 0;
+ }
+
+ if (tin > tout)
+ {
+ //
+ // +------------------------------------------------------------+
+ // | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX |
+ // +------------------------------------------------------------+
+ // ^out ^in
+ //
+
+ tlen = tin - out;
+
+ if (tlen > len)
+ {
+ tlen = len;
+ }
+
+ RtlCopyMemory(bp, buffer + tout, tlen);
+
+ tout += tlen;
+ if (tout == length) // can't happen
+ {
+ // N.B. This can't actually happen unless we change the algorithm
+ // to allow in == length, currently that will always wrap to 0.
+ // I want to actually check and see if the algorithm becomes cleaner
+ // if we do that.
+ tout = 0;
+ }
+ }
+ else
+ {
+ //
+ // +------------------------------------------------------------+
+ // |XXXX XXXXXXXXXXXXXXXXXXXX|
+ // +------------------------------------------------------------+
+ // ^in ^out
+ //
+
+ tlen = length - tout + tin;
+ if (tlen > len)
+ {
+ tlen = len;
+ }
+ tout += tlen;
+
+ if (tout > length)
+ {
+ tout -= length;
+ }
+ }
+ out = tout;
+ if ((tlen != 0) && (waitCount != 0))
+ {
+ InterlockedDecrement(&waitCount);
+ SetEvent(waitEvent);
+ }
+ return tlen;
+}
+
+int Circle::QueryContiguousRetrievable(char ** datap)
+{
+ //
+ // Non-copy optimization, return the number of bytes we can retrieve in a
+ // straight line. If the available buffer wraps, return from the current
+ // position to the buffer end, the caller will call again for the stuff
+ // at the front.
+ //
+
+ int tout = out;
+ int tin = in;
+ int len = 0;
+
+ if (tout <= tin)
+ {
+ len = tin - tout;
+ }
+ else
+ {
+ len = length - tout;
+ }
+ *datap = buffer + tout;
+ return len;
+}
+
+int Circle::CommitRetrieved(int len)
+{
+ int tout = out;
+ int tin = in;
+
+ // Make sure out won't overtake in.
+ ASSERT((tin < tout) || ((tout + len) <= tin));
+
+ tout += len;
+
+ ASSERT(tout <= length);
+
+ if (tout == length)
+ {
+ tout = 0;
+ }
+ out = tout;
+
+ if ((len != 0) && (waitCount != 0))
+ {
+ InterlockedDecrement(&waitCount);
+ SetEvent(waitEvent);
+ }
+
+ return len;
+}
+
+void Circle::Drain()
+{
+ //
+ // Discard any data already in the buffer.
+ //
+ // Note: This is a Consumer function, that is, we pretend to have retrieved
+ // all the data in the buffer.
+ //
+
+ int tout = out;
+ int tin = in;
+
+ if (tin != tout)
+ {
+ in = tout;
+
+ if (waitCount != 0)
+ {
+ InterlockedDecrement(&waitCount);
+ SetEvent(waitEvent);
+ }
+ }
+}
+
+void Circle::TestPattern(HANDLE Writer)
+{
+ char pattern[80];
+
+ for (int i = 0; i < sizeof(pattern); i++)
+ {
+ pattern[i] = 0x30 + (i % 10);
+ }
+
+ for (;;)
+ {
+ for (int i = 0; i < sizeof(pattern); i++)
+ {
+ int j = i + 1;
+ char old = pattern[i];
+ pattern[i] = '\n';
+ char * s = pattern;
+ for (int n = 0; n < j; )
+ {
+ int d = Insert(s, i - n + 1);
+ n += d;
+ s += d;
+ if (n < j)
+ {
+ SetEvent(Writer);
+ WaitUntilNotFull();
+ continue;
+ }
+ ASSERT(n == j);
+ }
+ pattern[i] = old;
+ if (QueryRetrievable() == j)
+ {
+ SetEvent(Writer);
+ }
+ }
+ for (int i = sizeof(pattern) - 2; i > 0; i--)
+ {
+ int j = i + 1;
+ char old = pattern[i];
+ pattern[i] = '\n';
+ char * s = pattern;
+ for (int n = 0; n < j; )
+ {
+ int d = Insert(s, i - n + 1);
+ n += d;
+ s += d;
+ if (n < j)
+ {
+ SetEvent(Writer);
+ WaitUntilNotFull();
+ continue;
+ }
+ ASSERT(n == j);
+ }
+ pattern[i] = old;
+ if (QueryRetrievable() == j)
+ {
+ SetEvent(Writer);
+ }
+ }
+ }
+}
--- /dev/null
+#if !defined(CIRCLE_H)
+#define CIRCLE_H
+
+class Circle
+{
+public:
+ Circle();
+ ~Circle();
+ bool Initialize(int size);
+ int Insert(char * data, int len);
+ int Retrieve(char *, int len);
+ int QueryRetrievable();
+ int QueryInsertable();
+ void WaitUntilNotFull();
+ int QueryContiguousRetrievable(char ** datap);
+ int CommitRetrieved(int len);
+ void Drain();
+ void TestPattern(HANDLE);
+
+private:
+ char * buffer;
+ volatile int in;
+ volatile int out;
+ int length;
+ HANDLE waitEvent;
+ volatile LONG waitCount;
+};
+
+#endif
--- /dev/null
+#include "stdafx.h"
+#include <windows.h>
+#include "plj_utils.h"
+#include "spinlock.h"
+#include "circle.h"
+#include "threadcontrol.h"
+#include "logger.h"
+#include "connectoid.h"
+
+#define MANUAL_RESET_EVENT 1
+
+Channel::Channel()
+{
+ pended = false;
+
+ RtlZeroMemory(Overlapped(), sizeof(overlap));
+ overlap.hEvent = CreateEvent(NULL, MANUAL_RESET_EVENT, false, NULL);
+ if (overlap.hEvent == INVALID_HANDLE_VALUE)
+ {
+ // Really, this can't possibly have happened.
+ die("CreateEvent failed for OVERLAPPED structure for Channel constructor.");
+ }
+}
+
+Channel::~Channel()
+{
+}
+
+void Channel::SetOverlappedEvent()
+{
+ SetEvent(overlap.hEvent);
+}
+
+Connectoid::Connectoid()
+{
+ sender = NULL;
+ log = NULL;
+ tag[0] = tag[1] = tag[2] = 0;
+ resetPacketIndex = 0;
+
+#ifdef OUTBOUND_DROP_UNTIL_RESET_ONLY
+ // N.B. resetAckExpected true will cause data from either end to be ignored.
+ // We use this to silence the debugger until we've seen something from the
+ // target.
+ resetAckExpected = true;
+#else
+ // resetAckExpected starts false but will be set true by the first outbound
+ // data seen on the pipe (from the debugger). At that point, all data in
+ // either direction will be dropped until a reset ack is seen from the
+ // target.
+ resetAckExpected = false;
+#endif
+ receiveDataSeen = false;
+ connected = false;
+}
+
+Connectoid::~Connectoid()
+{
+}
+
+bool Connectoid::Initialize(Logger * Logger, class Connectoid * Sender, char * Tag)
+{
+ log = Logger;
+ sender = Sender;
+
+ // Grr! I'd have used strncpy to copy my 3 bytes here and allowing for
+ // the possibility that the source string might be short ... but strncpy
+ // is considered dangerous and strncpy_s whines if it can't fit the trailing
+ // null.
+ //
+
+ for (int i = 0; i < sizeof(tag); i++)
+ {
+ if ((tag[i] = Tag[i]) == 0)
+ {
+ break;
+ }
+ }
+
+ //
+ // Copy this, er, pipe's read handle and the other one's write handle
+ // into the array used by WaitForMultipleObjects for this thread.
+ //
+
+ waitHandles[0] = read.GetHandle();
+ waitHandles[1] = sender->write.GetHandle();
+ blocked[0] = blocked[1] = 0;
+
+ return true;
+}
+
+void Connectoid::Wait()
+{
+ int wake;
+
+ // The following need to be done directly when Pending is set.
+ //blocked[0] = read.Pending();
+ //blocked[1] = sender->write.Pending();
+
+ if (blocked[0] == blocked[1])
+ {
+ //
+ // we have zero or two waiters.
+ //
+
+ if (blocked[0])
+ {
+ //
+ // two waiters.
+ //
+
+ log->Log(0, tag, "Wait multiple");
+ wake = WaitForMultipleObjects(2, waitHandles, false, INFINITE);
+ wake -= WAIT_OBJECT_0;
+
+ ASSERT((wake >= 0) && (wake < 2));
+ log->Log(0, tag, "Wait multiple woke %d (%s) %x", wake, wake ? "sender" : "reader", waitHandles[wake]);
+ blocked[wake] = false;
+#if MANUAL_RESET_EVENT
+ ResetEvent(waitHandles[wake]);
+#endif
+ }
+ }
+ else
+ {
+ //
+ // blocked[0] != blocked[1]
+ //
+ // One waiter. This (should) mean the other side has nothing to do.
+ // for example, we're waiting on a read and all writes have completed.
+ //
+
+ int which = blocked[1]; // if blocked[1] = 0 then blocked[0] must be 1.
+ // (overloading true/false as an index)
+ HANDLE handle = waitHandles[which];
+ log->Log(0, tag, "Wait single %d (%s) %x", which, which ? "sender" : "reader", waitHandles[which]);
+ WaitForSingleObject(handle, INFINITE);
+ log->Log(0, tag, "Wait single woke %d (%s) %x", which, which ? "sender" : "reader", waitHandles[which]);
+#if MANUAL_RESET_EVENT
+ ResetEvent(handle);
+#endif
+ blocked[which] = false;
+
+#if 0
+ if (blocked[0])
+ {
+ WaitForSingleObject(waitHandles[0], INFINITE);
+ blocked[0] = false;
+ }
+ else
+ {
+ //
+ // Reader has nothing to do but write side is blocked? This seems
+ // odd.
+ //
+
+ fprintf(stderr, "%.3s write side (alone) blocked .. seems odd.\n");
+ WaitForSingleObject(waitHandles[1], INFINITE);
+ blocked[1] = false;
+ }
+#endif
+ }
+}
+
+int Connectoid::Send(Circle *)
+{
+ die("default Connectoid::Send called. This should be overridden.");
+}
+
+//
+// This really doesn't have anything to do with the communications but,
+// we need to do a little bit of stateful control when reset (aka resync)
+// packets are being sent. Specifically, we need to notice them outbound
+// then discard anything inbound until we see the ack inbound.
+//
+// We *could* also ignore inbound acks if we haven't seen an outbound one
+// because there's a bug in the protocol which makes an unexpected inbound
+// ack send us into a reset loop forever.
+//
+// Note: This will fail to catch a reset packet that's preceeded by some random
+// number of leader bytes 0x69. So far that hasn't been a problem. We could
+// fix it by keeping a sliding window of the last 8 bytes received.
+//
+// This function returns the number of bytes consumed on this call before the
+// packet was complete, zero otherwise.
+//
+
+char ResetPacket[8] =
+{
+ 0x69, 0x69, 0x69, 0x69, 0x06, 0x00, 0x00, 0x00
+};
+
+int Connectoid::CheckForResetPacket(char * Buffer, int Length)
+{
+ for (int count = 1; Length; count++, Length--)
+ {
+ if (*Buffer++ != ResetPacket[resetPacketIndex++])
+ {
+ resetPacketIndex = 0;
+ }
+ if (resetPacketIndex == sizeof(ResetPacket))
+ {
+ resetPacketIndex = 0;
+ return count;
+ }
+ }
+ return 0;
+}
+
+#if 0
+int Connectoid::FetchResetPacket(char * Buffer)
+{
+ RtlCopyMemory(Buffer, ResetPacket, sizeof(ResetPacket));
+ return sizeof(ResetPacket);
+}
+#endif
+
+void Connectoid::InsertResetPacket(Circle * Buffer)
+{
+ Buffer->Insert(ResetPacket, sizeof(ResetPacket));
+}
--- /dev/null
+#if !defined(CONNECTOID_H)
+#define CONNECTOID_H
+
+extern char resetPacket[8];
+
+class Channel
+{
+public:
+ Channel();
+ ~Channel();
+ void Wait();
+ LPOVERLAPPED Overlapped();
+// LPWSAOVERLAPPED WSAOverlapped();
+ bool Pending();
+ void SetPending(bool);
+ void SetOverlappedEvent();
+ HANDLE GetHandle();
+private:
+
+ //
+ // Currently OVERLAPPED and WSAOVERLAPPED are the same structure, what a
+ // pity they're different types.
+ //
+ OVERLAPPED overlap;
+// WSAOVERLAPPED wsaoverlap;
+ bool pended;
+};
+
+inline void Channel::Wait()
+{
+ DWORD result = WaitForSingleObject(overlap.hEvent, INFINITE);
+ ASSERT(result != WAIT_FAILED);
+ return;
+}
+
+inline LPOVERLAPPED Channel::Overlapped()
+{
+ return &overlap;
+}
+
+#if 0
+inline LPWSAOVERLAPPED Channel::WSAOverlapped()
+{
+ return &wsaoverlap;
+}
+#endif
+
+inline bool Channel::Pending()
+{
+ return pended;
+}
+
+inline void Channel::SetPending(bool Pend)
+{
+ pended = Pend;
+}
+
+inline HANDLE Channel::GetHandle()
+{
+ return overlap.hEvent;
+}
+
+
+class Connectoid
+{
+public:
+ Connectoid();
+ ~Connectoid();
+ bool Initialize(Logger * Logger, class Connectoid * Connector, char * Tag);
+// virtual void Send(char * buffer, int length);
+ virtual int Send(Circle *);
+// void Receive(char * buffer, int length);
+ void Wait();
+ void SetReadWait(bool);
+ void SetWriteWait(bool);
+ void SetResetAckExpected(bool);
+ bool Connected();
+
+protected:
+ class Connectoid * sender;
+ class Logger * log;
+ Channel read;
+ Channel write;
+ HANDLE waitHandles[2];
+ union
+ {
+ char blocked[2];
+ struct
+ {
+ char read;
+ char write;
+ } wait;
+ };
+ char tag[3];
+ Circle receiveBuffer;
+ int resetPacketIndex;
+ bool resetAckExpected;
+ bool receiveDataSeen;
+ bool connected;
+ int CheckForResetPacket(char *, int);
+ void ClearResetPacketIndex();
+ void InsertResetPacket(Circle *);
+};
+
+inline void Connectoid::SetReadWait(bool value)
+{
+ wait.read = value;
+}
+
+inline void Connectoid::SetWriteWait(bool value)
+{
+ wait.write = value;
+}
+
+inline void Connectoid::ClearResetPacketIndex()
+{
+ resetPacketIndex = 0;
+}
+
+inline void Connectoid::SetResetAckExpected(bool value)
+{
+ resetAckExpected = value;
+ sender->resetAckExpected = value;
+}
+
+inline bool Connectoid::Connected()
+{
+ return connected;
+}
+
+#endif
+
--- /dev/null
+#include "stdafx.h"
+#include <windows.h>
+#include "plj_utils.h"
+#include "spinlock.h"
+#include "circle.h"
+#include "threadcontrol.h"
+#include "logger.h"
+
+#if 0
+static char * asciiTable[0x20] =
+{
+ "<NUL>",
+ "<SOH>",
+ "<STX>",
+ "<ETX>",
+ "<EOT>",
+ "<ENQ>",
+ "<ACK>",
+ "<BEL>",
+ "<BS>",
+ "<TAB>",
+ "<LF>",
+ "<VT>",
+ "<FF>",
+ "<CR>",
+ "<SO>",
+ "<SI>",
+ "<DLE>",
+ "<DC1>",
+ "<DC2>",
+ "<DC3>",
+ "<DC4>",
+ "<NAK>",
+ "<SYN>",
+ "<ETB>",
+ "<CAN>",
+ "<EM>",
+ "<SUB>",
+ "<ESC>",
+ "<FS>",
+ "<GS>",
+ "<RS>",
+ "<US>"
+}
+
+void
+ToAcsii(char c, char * buf)
+{
+ if ((c & 0x80) != 0)
+ {
+ buf[0] = 0;
+ }
+ else if (c < 0x20)
+ {
+ strcpy(buf, asciiTable[c]);
+ }
+ else if (c < 0x7f)
+ {
+ buf[0] = c;
+ buf[1] = 0;
+ }
+ else
+ {
+ strcpy(buf, "<DEL>");
+ }
+}
+#endif
+
+Logger::Logger()
+{
+ fileHandle = INVALID_HANDLE_VALUE;
+#pragma prefast(suppress:28159)
+ originalTime = GetTickCount();
+}
+
+Logger::~Logger()
+{
+
+#if LOGGING_ENABLED
+
+ if (fileHandle != INVALID_HANDLE_VALUE)
+ {
+ int retries = 0;
+ while (buffer.QueryRetrievable() != 0)
+ {
+ if (++retries > 10)
+ {
+ break;
+ }
+ SetEvent(writerEvent);
+ Sleep(100);
+ }
+ CloseHandle(fileHandle);
+ fileHandle = INVALID_HANDLE_VALUE;
+ }
+
+#endif
+
+}
+
+void Logger::ThreadEntry(void * inContext)
+{
+ UNREFERENCED_PARAMETER(inContext);
+
+ printf("hello from Logger's thread entry!\n");
+
+#if defined(SOCKPIPE_LOGGING)
+
+ for (;;)
+ {
+ int bytes;
+ char * data;
+ DWORD written;
+
+ while ((bytes = buffer.QueryContiguousRetrievable(&data)) != 0)
+ {
+ WriteFile(fileHandle, data, bytes, &written, NULL);
+ //
+ // Error handling? What error handling?
+ //
+
+ buffer.CommitRetrieved(bytes);
+ }
+ WaitForSingleObject(writerEvent, INFINITE);
+ }
+
+#endif
+
+}
+
+bool Logger::Initialize()
+{
+
+#if LOGGING_ENABLED
+
+ fileHandle = CreateFile(_T("sockpipe.log"), GENERIC_WRITE, FILE_SHARE_READ,
+ NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (fileHandle == INVALID_HANDLE_VALUE)
+ {
+ die("failed to open log file \"sockpipe.log\".");
+ }
+
+ writerEvent = CreateEvent(NULL, false, false, NULL);
+
+ if (writerEvent == INVALID_HANDLE_VALUE)
+ {
+ // I don't think this can happen, but, ...
+ die("failed to create a writerEvent handle for the logger.");
+ }
+
+ threadHandle = CreateEvent(NULL, false, false, NULL);
+
+ if (threadHandle == INVALID_HANDLE_VALUE)
+ {
+ die("failed to create threadHandle for the logger thread.");
+ }
+
+ lock.Initialize();
+
+ if (!buffer.Initialize(4096))
+ {
+ die("failed to initialize circular buffer for logging.");
+ }
+
+ if (!Start())
+ {
+ die("failed to initialize/start log writer thread.");
+ }
+
+#if 0
+ //
+ // Unit test the Circular Buffer code. Never returns.
+ //
+
+ buffer.TestPattern(writerEvent);
+#endif
+#endif
+
+ return true;
+}
+
+char LogTags[] =
+{
+ '.',
+ 'R',
+ 'X',
+ 'S',
+ 'r',
+ 'x',
+ 'u'
+};
+
+void Logger::htoa(char * in, char * out, int lengthIn)
+{
+ char * t = out;
+
+ for (int i = 0; i < lengthIn; i++)
+ {
+ char c = ((in[i] >> 4) & 0xf) + '0';
+ if (c > '9') c += ('a' - '0') - 10;
+ *t = c;
+
+ c = (in[i] & 0xf) + '0';
+ if (c > '9') c += ('a' - '0')- 10;
+ *(t + 1) = c;
+ t += 2;
+ }
+}
+
+
+void Logger::InsertToLogBuffer(char * buff, int len)
+{
+
+#if defined(SOCKPIPE_LOGGING)
+
+ //
+ // Log activity. Could be receive of either type, or other
+ // interesting things (like a close).
+ //
+
+ for (int remaining = len; remaining; )
+ {
+ lock.Acquire();
+
+ int done = buffer.Insert(buff, remaining);
+
+ lock.Release();
+
+ remaining -= done;
+
+ if (remaining)
+ {
+ SetEvent(writerEvent);
+ buffer.WaitUntilNotFull();
+ }
+ }
+
+ //
+ // Kick off the writer thread. If there are more bytes in the buffer than
+ // we just inserted, the thread will have been kicked already, less than or
+ // equal and we can't tell.
+ //
+
+ if (buffer.QueryRetrievable() <= len)
+ {
+ SetEvent(writerEvent);
+ }
+
+#endif
+
+}
+
+void Logger::Flush()
+{
+ if (fileHandle == INVALID_HANDLE_VALUE)
+ {
+ return;
+ }
+
+ if (buffer.QueryRetrievable())
+ {
+ SetEvent(writerEvent);
+ }
+
+ //
+ // Wait up to 3 seconds for the flush to complete.
+ //
+
+ for (int i = 0; (buffer.QueryRetrievable()) && (i < 30); i++)
+ {
+ Sleep(100);
+ }
+}
+
+
+void Logger::Log(int direction, char * tag, int len, char * buff)
+{
+ ASSERT(len < (PUMP_BUFFER_SIZE * 2));
+ ASSERT(direction < TAG_COUNT);
+
+#if LOGGING_ENABLED
+
+ if (fileHandle == INVALID_HANDLE_VALUE)
+ {
+ return;
+ }
+
+ char tmpbuf[PUMP_BUFFER_SIZE * 4];
+ char * t = tmpbuf;
+
+#if defined(SAFESTR)
+ t += sprintf_s(tmpbuf, sizeof(tmpbuf), "%08x %05d %c%.3s ", logTime(), len, LogTags[direction], tag);
+#else
+ t += sprintf(tmpbuf, "%08x %05d %c%.3s ", logTime(), len, LogTags[direction], tag);
+#endif
+
+// if (buff && (direction <= TAG_READ)) // only dump buffer on read side (for the moment)
+ if (buff && ((direction <= TAG_READ) || ((direction == TAG_SENT) && !strncmp(tag, "pip", 3))))
+ {
+ htoa(buff, t, len);
+ }
+ else
+ {
+ len = 0;
+ }
+ t += len * 2;
+ *t = '\n';
+ *(t + 1) = 0;
+// printf(tmpbuf);
+ InsertToLogBuffer(tmpbuf, (int)(t - tmpbuf) + 1);
+
+#endif
+
+}
+
+
+void Logger::Log(int direction, char * tag, char * buff, ...)
+{
+ ASSERT(direction < TAG_COUNT);
+
+#if LOGGING_ENABLED
+
+ if (fileHandle == INVALID_HANDLE_VALUE)
+ {
+ return;
+ }
+
+ char tmpbuf[1024];
+ va_list args;
+ int l;
+ int n;
+
+ va_start(args, buff);
+#if defined(SAFESTR)
+ l = sprintf_s(tmpbuf, sizeof(tmpbuf), "%08x %c%.3s ", logTime(), LogTags[direction], tag);
+ n = vsnprintf_s(tmpbuf + l, sizeof(tmpbuf) - l - 1, sizeof(tmpbuf) - 1 - 2, buff, args);
+#else
+ l = sprintf(tmpbuf, "%08x %c%.3s ", logTime(), LogTags[direction], tag);
+ n = _vsnprintf(tmpbuf + l, sizeof(tmpbuf) - l - 1, buff, args);
+#endif
+ l += n;
+ if (n < 0)
+ {
+ l = sizeof(tmpbuf) - 1;
+ }
+
+ tmpbuf[l] = '\n';
+ InsertToLogBuffer(tmpbuf, l + 1);
+
+#endif
+
+}
+
+void Logger::LogPrint(char * format, ...)
+{
+
+#if LOGGING_ENABLED
+
+ if (fileHandle == INVALID_HANDLE_VALUE)
+ {
+ return;
+ }
+
+ char tmpbuf[1024];
+ va_list args;
+ int l;
+
+ va_start(args, format);
+#if defined(SAFESTR)
+ l = vsnprintf_s(tmpbuf, sizeof(tmpbuf), sizeof(tmpbuf) - 1, format, args);
+#else
+ l = _vsnprintf(tmpbuf, sizeof(tmpbuf), format, args);
+#endif
+
+ if (l < 0)
+ {
+ tmpbuf[sizeof(tmpbuf)-1] = '\n';
+ l = sizeof(tmpbuf);
+ }
+ InsertToLogBuffer(tmpbuf, l);
+
+#endif
+
+}
--- /dev/null
+#if !defined(LOGGER_H)
+#define LOGGER_H
+
+#if !defined LOGGING_ENABLED
+#define LOGGING_ENABLED 0
+#endif
+
+typedef enum
+{
+ TAG_INVALID,
+ TAG_READ,
+ TAG_SEND,
+ TAG_SENT,
+ TAG_READ_DBG,
+ TAG_XMIT_DBG,
+ TAG_COUNT
+} TAG_TYPE;
+
+#define SOCKPIPE_LOGGING 1
+#define PUMP_BUFFER_SIZE 2048
+
+class Logger : ThreadControl
+{
+public:
+ Logger();
+ ~Logger();
+ bool Initialize();
+ void Log(int direction, char * tag, int len, char * buff);
+ void Log(int direction, char * tag, char * buff, ...);
+ void LogPrint(char * format, ...);
+ void Flush();
+
+protected:
+ virtual void ThreadEntry(void * inContext);
+
+private:
+ void InsertToLogBuffer(char * buff, int len);
+ void htoa(char * in, char * out, int lengthIn);
+ DWORD logTime();
+ HANDLE fileHandle;
+ SpinLock lock;
+ Circle buffer;
+ HANDLE writerEvent;
+ HANDLE threadHandle;
+ DWORD originalTime;
+};
+
+inline DWORD Logger::logTime()
+{
+#pragma prefast(suppress:28159)
+ return GetTickCount() - originalTime;
+}
+
+#endif
--- /dev/null
+#include "stdafx.h"
+#include <winsock2.h>
+#include <windows.h>
+#include "plj_utils.h"
+#include "spinlock.h"
+#include "circle.h"
+#include "threadcontrol.h"
+#include "logger.h"
+#include "pipereader.h"
+
+
+PipeReader::PipeReader()
+{
+ pipe = INVALID_HANDLE_VALUE;
+}
+
+PipeReader::~PipeReader()
+{
+ if (pipe != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(pipe);
+ pipe = INVALID_HANDLE_VALUE;
+ }
+}
+
+bool PipeReader::Initialize(char * PipeName, Logger * Logger, class Connectoid * Sock, bool StartThread, bool Client, char * Tag)
+{
+ Connectoid::Initialize(Logger, Sock, Tag);
+ client = Client;
+ pipeName = PipeName;
+
+ receiveBuffer.Initialize(PUMP_BUFFER_SIZE);
+
+ //
+ // If we are spinning a thread for this pipe, spin it.
+ //
+
+ if (StartThread != false)
+ {
+ if (!Start())
+ {
+ die("failed to initialize/start pipe reader thread.");
+ }
+ }
+ return true;
+}
+
+int PipeReader::Send(Circle * buffer)
+{
+ BOOL success;
+ DWORD written;
+ DWORD previouslyWritten = 0;
+
+ if (!receiveDataSeen)
+ {
+ //
+ // Drop incoming data on floor.
+ //
+
+ buffer->Drain();
+ return 0;
+ }
+
+ int lastError = 0;
+
+ if (write.Pending())
+ {
+ //
+ // Check result from previous write.
+ //
+
+ success = GetOverlappedResult(pipe, write.Overlapped(), &previouslyWritten, false);
+ log->Log(TAG_XMIT_DBG, tag, "write: GetOverlapResult returned %d, oh = %p", success, write.GetHandle());
+
+ if (!success)
+ {
+ lastError = GetLastError();
+
+ if (lastError == ERROR_IO_PENDING)
+ {
+ //
+ // The previous write is not yet complete. We can't
+ // initiate another until it is.
+ //
+
+ log->Log(TAG_XMIT_DBG, tag, "write: GetOverlapResult returned ERROR_IO_PENDING, we shouldn't have come here!!!");
+ return 0;
+ }
+ else
+ {
+ die("pipe write failed, error %d\n", lastError);
+ }
+ }
+ write.SetPending(false);
+// log->Log(TAG_SENT, tag, previouslyWritten, NULL);
+ {
+ char * bufftmp;
+ DWORD lentmp;
+ lentmp = buffer->QueryContiguousRetrievable(&bufftmp);
+ ASSERT(lentmp >= previouslyWritten);
+ log->Log(TAG_SENT, tag, previouslyWritten, bufftmp);
+ }
+ buffer->CommitRetrieved(previouslyWritten);
+ }
+
+ //
+ // Initiate a write.
+ //
+
+ char * buff;
+ int length = buffer->QueryContiguousRetrievable(&buff);
+
+ if (length == 0)
+ {
+ //
+ // Nothing available to be written just yet.
+ //
+
+ log->Log(TAG_XMIT_DBG, tag, "write: nothing to write");
+ return 0;
+ }
+
+ log->Log(TAG_SEND, tag, length, NULL);
+ log->Log(TAG_XMIT_DBG, tag, "initiate %d byte write oh = %p", length, write.GetHandle());
+
+ success = WriteFile(pipe, buff, length, &written, write.Overlapped());
+ if (success)
+ {
+// log->Log(TAG_SENT, tag, written, NULL);
+ log->Log(TAG_SENT, tag, written, buff);
+ log->Log(TAG_XMIT_DBG, tag, "write: instant gratification %d bytes on oh = %p", written, write.GetHandle());
+ return buffer->CommitRetrieved(written) + previouslyWritten;
+ }
+
+ lastError = GetLastError();
+
+ if (lastError == ERROR_IO_PENDING)
+ {
+ write.SetPending(true);
+ sender->SetWriteWait(true);
+ log->Log(TAG_XMIT_DBG, tag, "write: initiated send %d bytes, new state == pending, oh = %p", length, write.GetHandle());
+ return previouslyWritten;
+ }
+ g_shutdown = true;
+ die("pipe write failed, error %d\n", lastError);
+}
+
+int PipeReader::Receive(char * buffer, int length)
+{
+ BOOL success;
+ DWORD received = 0;
+
+ if (read.Pending())
+ {
+ //
+ // Check result from previous read.
+ //
+
+ success = GetOverlappedResult(pipe, read.Overlapped(), &received, false);
+ log->Log(TAG_READ_DBG, tag, "read: GetOverlappedResult status %d, count %d, oh = %p", success, received, read.GetHandle());
+ if (!success)
+ {
+ int lastError = GetLastError();
+
+ if (lastError == ERROR_IO_PENDING)
+ {
+ //
+ // The previous read is not yet complete. We can't
+ // initiate another until it is.
+ //
+
+ log->Log(TAG_READ_DBG, tag, "read: still pending, this shouldn't have happpened *****************");
+ return 0;
+ }
+ if (lastError == ERROR_IO_INCOMPLETE)
+ {
+ log->Log(TAG_READ_DBG, tag, "read: ERROR_IO_INCOMPLETE, this shouldn't have happened ***************");
+ fprintf(stderr, "E_IO_INCOMPLETE read from %.3s -- this shouldn't happen, ignoring.\n", tag);
+ return 0;
+ }
+ else
+ {
+ die("pipe read failed, error %d\n", lastError);
+ }
+ }
+ read.SetPending(false);
+ log->Log(TAG_READ_DBG, tag, "read: delayed read complete, received %d bytes.", received);
+ return received;
+ }
+
+ log->Log(TAG_READ_DBG, tag, "read: initiating read %d bytes (max) oh %p", length, read.GetHandle());
+ success = ReadFile(pipe, buffer, length, &received, read.Overlapped());
+ if (!success)
+ {
+ int lastError = GetLastError();
+
+ if (lastError == ERROR_IO_PENDING)
+ {
+ log->Log(TAG_READ_DBG, tag, 0, "read: pending.");
+ read.SetPending(true);
+ SetReadWait(true); // ick, needs cleaning.
+ }
+ else if (lastError == ERROR_PIPE_LISTENING)
+ {
+ Sleep(500);
+ log->Log(TAG_READ_DBG, tag, "read: nobody is listening.");
+ read.SetOverlappedEvent(); // make sure the big wait will not wait for ever
+ }
+ else
+ {
+ fprintf(stderr, "read pipe failed %d\n", lastError);
+ // For now, get us out of here.
+ g_shutdown = true;
+ my_exit(0);
+ }
+ return 0;
+ }
+ log->Log(TAG_READ_DBG, tag, "read: instantly returning %d bytes", received);
+ return received;
+}
+
+void PipeReader::Pump()
+{
+ char buf[PUMP_BUFFER_SIZE];
+
+ connected = true;
+
+ while (g_shutdown == false)
+ {
+ int received = 0;
+ int sent = 0;
+
+ if (!wait.read)
+ {
+ //
+ // If there's room in the recieve buffer, attempt to receive
+ // some.
+
+ int receivable = receiveBuffer.QueryInsertable();
+
+ if (receivable != 0)
+ {
+ if ((received = Receive(buf, receivable)) != 0)
+ {
+ if (receiveDataSeen == false)
+ {
+ printf("pipe connected.\n");
+ log->Log(TAG_READ_DBG, tag, "Recieve data from debugger.\n");
+ receiveDataSeen = true;
+ }
+ log->Log(TAG_READ, tag, received, buf);
+ if (sender->Connected() == false)
+ {
+ // Ignore all incoming data until there is something
+ // connected to send it to.
+ printf("pipereader: dropping %d bytes because socket is not connected.\n",
+ received);
+ log->Log(TAG_READ_DBG, tag,
+ "dropping %d bytes because socket is not connected.\n",
+ received);
+ received = 0;
+ }
+ if (resetAckExpected)
+ {
+ // Ignore all incoming data until the other side tells
+ // us a reset ack has been seen.
+ log->Log(TAG_READ_DBG, tag,
+ "dropping %d bytes, waiting for reset ack from target.\n",
+ received);
+ received = 0;
+ }
+
+ int count = CheckForResetPacket(buf, received);
+ if (count != 0)
+ {
+ log->Log(TAG_READ_DBG, tag, "RESET packet received.\n");
+ if (!resetAckExpected)
+ {
+ printf("debugger sent RESET.\n");
+ }
+ // Truncate received data to end of reset packet. We
+ // discard all remaining data until we see a reset ack
+ // from the other end. Note: On send the reset packet
+ // is usually followed by 8 bytes of zero, the target
+ // seems to depend on it ... and being as we truncated
+ // and we don't know we got them all yet anyway and we
+ // will drop all further data until we see something,
+ // better send the zeros along.
+ receiveBuffer.Insert(buf, count);
+ int z = 0;
+ receiveBuffer.Insert((char *)&z, sizeof(z));
+ receiveBuffer.Insert((char *)&z, sizeof(z));
+ received = 0;
+ SetResetAckExpected(true);
+ }
+ receiveBuffer.Insert(buf, received);
+ }
+ }
+ }
+
+ if (!wait.write)
+ {
+ //
+ // Attempt to send.
+ //
+ // Note: The Send routine will take care of the no data case.
+ //
+
+ sent = sender->Send(&receiveBuffer);
+ }
+
+ if (!(sent | received))
+ {
+ //
+ // Nothing sent, nothing received, wait until something happens
+ // on one end or the other.
+ //
+
+ Wait();
+ }
+ }
+ connected = false;
+}
+
+void PipeReader::ThreadEntry(void * inContext)
+{
+ UNREFERENCED_PARAMETER(inContext);
+
+ if (client == false)
+ {
+ //
+ // Create pipe for server (that other end will connect to).
+ //
+
+ pipe = CreateNamedPipe(pipeName,
+ PIPE_ACCESS_DUPLEX
+// | FILE_FLAG_FIRST_PIPE_INSTANCE
+// | FILE_FLAG_WRITE_THROUGH
+ | FILE_FLAG_OVERLAPPED
+ ,
+ PIPE_TYPE_BYTE
+// | PIPE_WAIT
+ ,
+ 1,
+ 4096,
+ 4096,
+ INFINITE,
+ NULL);
+ if (pipe == INVALID_HANDLE_VALUE)
+ {
+ die("failed to open pipe, err = %d.", GetLastError());
+ }
+ }
+ else
+ {
+ //
+ // Create pipe for client. Use CreateFile because, oddly, CreateNamedPipe
+ // seems to fail if you use the \\servername\pipe\pipename format. Sadly,
+ // this too will fail if the other end doesn't exist so we need to do it
+ // in the spun thread. We did spin a thread right?
+ //
+
+ bool first = TRUE;
+
+ do
+ {
+ pipe = CreateFile(pipeName, // pipe name
+ GENERIC_READ | GENERIC_WRITE, // read and write access
+ 0, // no sharing
+ NULL, // default security
+ OPEN_ALWAYS, // sample says open existing
+ FILE_FLAG_WRITE_THROUGH // push the data to the other end
+ | FILE_FLAG_OVERLAPPED // don't wait
+ ,
+ NULL); // why would i want a template?
+ if (pipe == INVALID_HANDLE_VALUE)
+ {
+ DWORD err = GetLastError();
+
+ if (err != ERROR_FILE_NOT_FOUND)
+ {
+ die("failed to open pipe, err = %d.", err);
+ }
+
+ if (first)
+ {
+ printf("pipe client waiting for remote pipe to become available.\n");
+ first = false;
+ }
+ Sleep(1700);
+ }
+ } while (pipe == INVALID_HANDLE_VALUE);
+ }
+
+ printf("hello from the pipe reader.\n");
+
+ //
+ // Now pass data back and forth across the connections.
+ //
+
+ Pump();
+}
--- /dev/null
+#if !defined(PIPEREADER_H)
+#define PIPEREADER_H
+
+#include "connectoid.h"
+
+class PipeReader : public ThreadControl, public Connectoid
+{
+public:
+ PipeReader();
+ ~PipeReader();
+ bool Initialize(char * PipeName,
+ Logger * Logger,
+ class Connectoid * Sock,
+ bool StartThread,
+ bool Client,
+ char * Tag);
+ void ThreadEntry(void * inContext);
+// void Send(char * buffer, int length);
+ int Send(Circle *);
+ int Receive(char * buffer, int length);
+private:
+ void Pump();
+ bool client;
+ HANDLE pipe;
+ char * pipeName;
+};
+#endif
--- /dev/null
+#if !defined(PLJ_UTILS_H)
+#define PLJ_UTILS_H
+
+#define ASSERT(x) if (!(x)){fprintf(stderr, "assert failed %s %d:%s", __FILE__, __LINE__, #x);__debugbreak();}
+
+__declspec(noreturn) void die(char *,...);
+__declspec(noreturn) void my_exit(int code);
+
+extern bool g_shutdown;
+
+#endif
--- /dev/null
+
+#include "stdafx.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <winsock2.h>
+#include <windows.h>
+
+// plj specials
+
+#include "plj_utils.h"
+#include "spinlock.h"
+#include "threadcontrol.h"
+#include "circle.h"
+#include "logger.h"
+#include "connectoid.h"
+#include "pipereader.h"
+#include "sockreader.h"
+
+//
+// Globals.
+//
+
+bool g_shutdown = false;
+class Logger * g_log = NULL;
+_TCHAR g_progname[MAX_PATH];
+
+//
+// Define TWO_PIPE if you want to go pipe to pipe instead of pipe to
+// socket. This is useful for debugging (this proxy) against a known
+// working debuggee (eg a virtual machine under VPC).
+//
+//#define TWO_PIPE
+
+//
+// Generic (C style) support routines.
+//
+
+void my_exit(int code)
+{
+ if (g_log)
+ {
+ g_log->Flush();
+ }
+ exit(code);
+}
+
+void die(char * message,...)
+{
+ char buf[1024];
+ va_list args;
+
+ va_start(args, message);
+#if defined(SAFESTR)
+ vsnprintf_s(buf, sizeof(buf), sizeof(buf) - 1, message, args);
+#else
+ _vsnprintf(buf, sizeof(buf), message, args);
+#endif
+ fprintf(stderr, "%s\n", buf);
+ if (g_log)
+ {
+ g_log->Log(0, "die", buf);
+ }
+ my_exit(1);
+}
+
+void usage()
+{
+ _TCHAR * progname = g_progname;
+ _TCHAR * endName = _tcsrchr(g_progname, TCHAR('\\'));
+
+ if (endName)
+ {
+ progname = endName + 1;
+ }
+
+#if !defined(TWO_PIPE)
+ fprintf(stderr, "usage: %s [-l] pipe [address] port\n\n", progname);
+ fprintf(stderr, "where - pipe is the name of the local pipe which the\n"
+ " Microsoft Windows Debugger will try to connect to.\n"
+ " address [optional] is the address of the target\n"
+ " to connect to if Xen is listening.\n"
+ " port is the (decimal) number of the TCP port Xen\n"
+ " is configured to listen on or to connect to on\n"
+ " this machine.\n\n"
+ " Note: If sockpipe is listening then the port must\n"
+ " be open through this machine's firewall.\n\n"
+ " -l [optional] if specified, enable logging. N.B.\n"
+ " the log file can become quite large very quickly.\n"
+ "example: %s my_pipe 7001\n",
+ progname);
+#else
+ fprintf(stderr, "usage: %s [-l] pipe1 pipe2\n\n", progname);
+ fprintf(stderr, "where - pipe1 is the name of the local pipe which the\n"
+ " Microsoft Windows Debugger will try to connect to.\n"
+ " pipe2 is the full path pipe name to the pipe being\n"
+ " offered by a machine to be debugged.\n\n"
+ " -l [optional] if specified, enable logging. N.B.\n"
+ " the log file can become quite large very quickly.\n"
+ "example: %s my_pipe \\remotemachine\pipe\debugee_name\n",
+ progname);
+#endif
+ fprintf(stderr, "\n"
+ "This program (%s) needs to be started BEFORE either the\n"
+ "kernel debugger or the system to be debugged.\n"
+ "To configure the serial ports of a Xen guest to connect,\n"
+ "add a line to the guest configuration file of the form-\n\n"
+ "serial='tcp:proxy-machine:port_number'\n\n"
+ "where proxy-machine is the IP address or name of the machine where\n"
+ "this program is running and port_number is the TCP port number it\n"
+ "is listening on.\n\n"
+ "To configure the serial ports of a Xen guest to listen,\n"
+ "add a line to the guest configuration file of the form-\n\n"
+ "serial='tcp::port_number,server,nodelay'\n\n"
+ "where port_number is the TCP port number the program should\n"
+ "connect to.\n",
+ progname);
+ my_exit(1);
+}
+
+int __cdecl _tmain(int argc, _TCHAR* argv[])
+{
+
+#if defined(TWO_PIPE)
+ //
+ // Experiment with pipe to pipe so we can debug using VPC and capture
+ // a log of a working debug session.
+ //
+
+ PipeReader sock;
+
+#else
+
+ SockReader sock;
+
+#endif
+
+ PipeReader pipe;
+ Logger log;
+
+ //
+ // Save the name of the current running program. This is not presented
+ // in argv[0] as you might expect... but hey, this is Windows.
+ //
+
+ GetModuleFileName(NULL, g_progname, sizeof (g_progname));
+ g_progname[sizeof(g_progname) - 1] = _T('\0');
+ argv++;
+ --argc;
+
+ if (argc == 0)
+ usage();
+
+ //
+ // Three arguments if you count the program name, the pipe name and
+ // the port (or 2nd pipe).
+ //
+
+ if (_tcsncmp(*argv, _T("-l"), 2) == 0)
+ {
+ if (!log.Initialize())
+ {
+ die("couldn't initialize logger");
+ }
+ argv++;
+ --argc;
+
+ if (argc == 0)
+ usage();
+ }
+
+
+ bool passive = true;
+
+ if (argc == 3)
+ {
+ passive = false;
+ }
+ else if (argc < 2)
+ {
+ usage();
+ }
+
+ g_log = &log;
+
+ //
+ // Note: sock.Initialize will fire up the socket pump thread,
+ // pipe initialization needs to be completed before that.
+ //
+
+ _TCHAR * lpipename = *argv;
+
+#define whack_pipe _T("\\\\.\\pipe\\")
+
+ size_t whackPipeLen = (sizeof(whack_pipe) / sizeof(_TCHAR)) - 1;
+ if (_tcsnccmp(lpipename, whack_pipe, whackPipeLen) != 0)
+ {
+ size_t originalNameLen = _tcslen(lpipename);
+ size_t nameLen = whackPipeLen + originalNameLen + 1;
+ if (nameLen > 1024) // arbitary
+ {
+ die("pipe name is too long.");
+ }
+ lpipename = (_TCHAR *)malloc(nameLen * sizeof(_TCHAR));
+ if (lpipename == NULL)
+ {
+ die("failed to malloc space for local pipe name.");
+ }
+
+#pragma warning(push)
+#pragma warning(disable:6386)
+
+ memcpy(&lpipename[0], whack_pipe, whackPipeLen * sizeof(_TCHAR));
+ memcpy(&lpipename[whackPipeLen],
+ *argv,
+ originalNameLen * sizeof(_TCHAR));
+ lpipename[nameLen - 1] = 0;
+
+#pragma warning(pop)
+
+ }
+ argv++;
+
+ printf("gonna try pipe '%s'\n", lpipename);
+ if (!pipe.Initialize(lpipename, &log, &sock, false, false, "pip"))
+ {
+ die("couldn't open local named pipe, err %d", GetLastError());
+ }
+
+#if !defined(TWO_PIPE)
+ _TCHAR * address;
+ _TCHAR * portnumber;
+
+ if (passive) {
+ address = NULL;
+ portnumber = *argv;
+ } else {
+ address = *argv++;
+ portnumber = *argv;
+ }
+
+ if (!sock.Initialize(address, portnumber, &log, &pipe, true, "win"))
+ {
+ die("couldn't open socket.");
+ }
+#else
+ _TCHAR * rpipename = *argv;
+
+ if (!sock.Initialize(rpipename, &log, &pipe, true, true, "sok"))
+ {
+ die("couldn't open remote pipe.");
+ }
+#endif
+
+ //
+ // We run the pipe reader directly on this thread.
+ //
+
+ pipe.ThreadEntry(&pipe);
+
+ return 0;
+}
+
--- /dev/null
+#include "stdafx.h"
+#include <winsock2.h>
+#include <windows.h>
+#include <stdlib.h>
+#include "plj_utils.h"
+#include "spinlock.h"
+#include "circle.h"
+#include "threadcontrol.h"
+#include "logger.h"
+#include "sockreader.h"
+
+
+bool
+Printable(char c)
+{
+ if ((c >= 0x20) && (c <= 0x7e))
+ {
+ return true;
+ }
+
+ switch (c)
+ {
+ case 0x09: // tab
+ case 0x0a: // line feed
+ case 0x0d: // carriage return
+ return true;
+ default:
+ return false;
+ }
+}
+
+
+SockReader::SockReader()
+{
+ listenSocket = INVALID_SOCKET;
+ connection = INVALID_SOCKET;
+ doCleanup = false;
+ initialPacketHeaderIndex = 0;
+}
+
+SockReader::~SockReader()
+{
+ if (listenSocket != INVALID_SOCKET)
+ {
+ closesocket(listenSocket);
+ listenSocket = INVALID_SOCKET;
+ }
+ Close();
+ if (doCleanup)
+ {
+ WSACleanup();
+ }
+}
+
+void SockReader::Close()
+{
+ if (connection != INVALID_SOCKET)
+ {
+ closesocket(connection);
+ connection = INVALID_SOCKET;
+ }
+}
+
+
+bool SockReader::Initialize(_TCHAR * Address, _TCHAR * PortNumber, Logger * Logger, class Connectoid * Pipe, bool StartThread, char * Tag)
+{
+ u_long addr;
+ u_short port = htons((u_short)_tstol(PortNumber));
+
+ if (Address)
+ {
+ passive = false;
+
+ addr = inet_addr(Address);
+ if (addr == INADDR_ANY || addr == INADDR_NONE)
+ {
+ die("TCP: invalid address.");
+ }
+ }
+ else
+ {
+ addr = INADDR_ANY;
+ passive = true;
+ }
+
+ if (port == 0)
+ {
+ die("TCP: invalid port number.");
+ }
+
+ //
+ // The sockaddr_in structure specifies the address family, IP address and
+ // port number that will be bound.
+ //
+
+ RtlZeroMemory(&service, sizeof(service));
+ service.sin_family = AF_INET;
+ service.sin_port = port;
+ service.sin_addr.s_addr = addr;
+
+ Connectoid::Initialize(Logger, Pipe, Tag);
+ receiveBuffer.Initialize(PUMP_BUFFER_SIZE);
+
+ if (StartThread != false)
+ {
+ if (!Start())
+ {
+ die("failed to initialize/start socket reader thread.");
+ }
+ }
+
+ return true;
+}
+
+void SockReader::ThreadEntry(void * inContext)
+{
+ UNREFERENCED_PARAMETER(inContext);
+
+ while (g_shutdown == false)
+ {
+ //
+ // Initialize Winsock.
+ //
+ // Note; We could set this puppy up to handle multiple sessions, probably
+ // something we will want to do in the future.
+ //
+
+ printf("hello from the socket reader.\n");
+
+ if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR)
+ {
+ die("WINSOCK2: Winsock startup failed.");
+ }
+ doCleanup = true;
+
+ if (passive)
+ {
+ listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (listenSocket == INVALID_SOCKET)
+ {
+ // GetLastError would be useful here!
+ die("TCP: Socket creation error.");
+ }
+
+ //
+ // Bind it. The main loop will listen, accept and process it.
+ //
+
+ if (bind(listenSocket, (SOCKADDR *)&service, sizeof(service)) == SOCKET_ERROR)
+ {
+ die("WINSOCK2: bind failed.");
+ }
+
+ if (listen(listenSocket, 1) == SOCKET_ERROR)
+ {
+ die("WINSOCK2: listen failed.");
+ }
+
+ shutdown = false;
+
+ do
+ {
+ printf("socket accepting connections\n");
+ connection = accept(listenSocket, NULL, NULL);
+ if (connection == SOCKET_ERROR)
+ {
+ printf("accept failed (SOCKET_ERROR = %d)\n", WSAGetLastError());
+ }
+ } while (connection == SOCKET_ERROR);
+
+ printf("remote com emulator connected...\n");
+
+ closesocket(listenSocket);
+ listenSocket = INVALID_SOCKET;
+ }
+ else
+ {
+ shutdown = false;
+
+ connection = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (connection == INVALID_SOCKET)
+ {
+ // GetLastError would be useful here!
+ die("TCP: Socket creation error.");
+ }
+
+ do
+ {
+ printf("socket connecting...\n");
+ if (connect(connection, (SOCKADDR *)&service, sizeof(service)) == SOCKET_ERROR)
+ {
+ if (WSAGetLastError() != WSAECONNREFUSED &&
+ WSAGetLastError() != WSAENETUNREACH &&
+ WSAGetLastError() != WSAETIMEDOUT)
+ {
+ die("WINSOCK2: connect failed (SOCKET_ERROR = %d)\n", WSAGetLastError());
+ }
+
+ printf("connect failed (SOCKET_ERROR = %d)\n", WSAGetLastError());
+ }
+ else
+ {
+ break;
+ }
+ } while (true);
+ }
+
+ //
+ // We have no previously initiated read on this socket, clear up
+ // (potentially left over status). We should probably tear down
+ // and reestablish the read side of the world but ... I didn't
+ // write it in a way that makes that easy so, rudely, just fix it.
+ //
+
+ read.SetPending(false);
+
+ //
+ // Set TCP_NODELAY on the socket so TCP won't try to build bigger
+ // packets. On the target end this seems to be critical on this
+ // end it may not be so important but still may help.
+ //
+
+ int opt = 1;
+ setsockopt(connection, IPPROTO_TCP, TCP_NODELAY, (char *)&opt, sizeof(opt));
+
+ Pump();
+
+ Close();
+ WSACleanup();
+ doCleanup = false;
+
+ //
+ // Delay slightly before going around. This is to give the world
+ // time to clean up and shouldn't be needed at all ... but we'll
+ // see if it helps.
+ //
+
+ Sleep(314);
+ }
+}
+
+int SockReader::Send(Circle * buffer)
+{
+ int success;
+ DWORD sent;
+ DWORD previouslySent = 0;
+ int lastError = 0;
+ DWORD flags = 0;
+
+ if (write.Pending())
+ {
+ //
+ // Check the result from a previous send.
+ //
+
+ success = WSAGetOverlappedResult(connection, write.Overlapped(), &previouslySent, false, &flags);
+ log->Log(TAG_XMIT_DBG, tag, "write: WSAGetOverlappedResult %d, oh = %p", success, write.GetHandle());
+
+ if (!success)
+ {
+ lastError = WSAGetLastError();
+ die("write: WSAGetOverlappedResult failed, error = %d", lastError);
+ }
+ write.SetPending(false);
+ log->Log(TAG_SENT, tag, previouslySent, NULL);
+ buffer->CommitRetrieved(previouslySent);
+ }
+
+ //
+ // Initiate a write.
+ //
+
+ char * buff;
+ int length = buffer->QueryContiguousRetrievable(&buff);
+
+ if (length == 0)
+ {
+ //
+ // Nothing available to send.
+ //
+
+ log->Log(TAG_XMIT_DBG, tag, "write: nothing to write");
+ return 0;
+ }
+
+ log->Log(TAG_SEND, tag, length, NULL);
+ log->Log(TAG_XMIT_DBG, tag, "initiate %d write on socket oh = %p", length, write.GetHandle());
+
+ sent = 0;
+ WSABUF wsabuf;
+ wsabuf.buf = buff;
+ wsabuf.len = length;
+
+ success = WSASend(connection, &wsabuf, 1, &sent, flags, write.Overlapped(), NULL);
+
+ if (success == SOCKET_ERROR)
+ {
+ lastError = WSAGetLastError();
+
+ if (lastError == WSA_IO_PENDING)
+ {
+ write.SetPending(true);
+ sender->SetWriteWait(true);
+ log->Log(TAG_XMIT_DBG, tag, "write: initiated send on socket %d bytes, pending oh = %p.", length, write.GetHandle());
+ return previouslySent;
+ }
+
+ //
+ // Um ... Write failed, we don't know why. Assume the connection is probably
+ // gone and return to caller ... it should all come tumbling down shortly.
+ //
+
+ shutdown = true;
+ fprintf(stderr, "write socket failed %d\n", lastError);
+ return previouslySent;
+ }
+
+ log->Log(TAG_SENT, tag, sent, NULL);
+ buffer->CommitRetrieved(sent);
+
+ return previouslySent + sent;
+}
+
+
+int SockReader::Receive(char * buffer, int length)
+{
+
+ BOOL success;
+ DWORD received = 0;
+
+ if (read.Pending())
+ {
+ //
+ // Check result from previous read.
+ //
+
+ DWORD flags;
+
+ success = WSAGetOverlappedResult(connection, read.Overlapped(), &received, false, &flags);
+ log->Log(TAG_READ_DBG, tag, "read: WSAGetOverlappedResult returned %d for %d bytes\n", success, received);
+
+ if (!success)
+ {
+ int lastError = WSAGetLastError();
+
+ if (lastError == WSA_IO_INCOMPLETE)
+ {
+ log->Log(TAG_READ_DBG, tag, "read: WSA_IO_INCOMPLETE, this shouldn't happen, ignored.");
+ return 0;
+ }
+ //
+ // I've seen us die here with WSAECONNRESET when the socket goes away.
+ // Treat any unknown error here the same as if a read failed and cause
+ // socket closure and possible reset.
+ //
+
+ fprintf(stderr, "WSAGetOverlappedResult failed, err %d, closing pipe.\n", lastError);
+ shutdown = true;
+ return 0;
+ }
+ read.SetPending(false);
+ log->Log(TAG_READ_DBG, tag, "read: delayed read complete, received %d bytes.", received);
+ return received;
+ }
+
+ DWORD flags = 0;
+ WSABUF wsabuf;
+ wsabuf.buf = buffer;
+ wsabuf.len = length;
+ ASSERT(length);
+
+ log->Log(TAG_READ_DBG, tag, "read: initiating socket receive %d bytes (max) oh = %p", length, read.GetHandle());
+ success = WSARecv(connection, &wsabuf, 1, &received, &flags, read.Overlapped(), NULL);
+ if (success == SOCKET_ERROR)
+ {
+ int lastError = WSAGetLastError();
+
+ if (lastError == WSA_IO_PENDING)
+ {
+ log->Log(TAG_READ_DBG, tag, "read: pending.");
+ read.SetPending(true);
+ SetReadWait(true); // bleh
+ }
+ else
+ {
+ log->Log(TAG_READ, tag, "read failed, WSALastError == %d\n", lastError);
+ fprintf(stderr, "read socket failed %d\n", lastError);
+ shutdown = true;
+ }
+ return 0;
+ }
+ log->Log(TAG_READ_DBG, tag, "read: socket recv returned %d bytes immediately.", received);
+
+ if (!received)
+ {
+ log->Log(TAG_READ_DBG, tag, "read: successful read of 0 bytes, graceful shutdown.");
+ shutdown = true;
+ }
+ return received;
+}
+
+static char InitialPacketHeader[6] =
+{
+ 0x30, 0x30, 0x30, 0x30, 0x07, 0x00
+};
+
+int SockReader::CheckForInitialPacketHeader(char * Buffer, int Length)
+{
+ for (int count = 1; Length; count++, Length--)
+ {
+ if (*Buffer++ != InitialPacketHeader[initialPacketHeaderIndex++])
+ {
+ initialPacketHeaderIndex = 0;
+ }
+ if (initialPacketHeaderIndex == sizeof(InitialPacketHeader))
+ {
+ initialPacketHeaderIndex = 0;
+ return count;
+ }
+ }
+ return 0;
+}
+
+
+void SockReader::Pump()
+{
+ //
+ // We have a connection, pass data back and forth.
+ //
+
+ char buf[PUMP_BUFFER_SIZE];
+
+ log->Log(TAG_READ_DBG, tag, "Socket is up, beginning socket pump.");
+
+ //
+ // Crude. Push a reset packet onto the socket. Only the other side is
+ // supposed to write to the socket but until he sees the connected flag
+ // he isn't going to do any such thing, so, do it. Because we inserted
+ // this packet we need to stop the reset ack from getting thru to the
+ // debugger or it'll ack it and the loop is on forever.
+ //
+ // Trouble is, the easiest way to send something is to stick it in the
+ // send buffer and we're really not supposed to mess with the other side's
+ // buffer ... so ... really really gross, put it in our buffer!
+ //
+
+ receiveBuffer.Drain();
+ InsertResetPacket(&receiveBuffer);
+ int z = 0;
+ receiveBuffer.Insert((char *)&z, sizeof(z));
+ receiveBuffer.Insert((char *)&z, sizeof(z));
+ Send(&receiveBuffer);
+ receiveBuffer.Drain();
+ SetResetAckExpected(true);
+ bool killResetAck = true;
+
+ connected = true;
+ while (Shutdown() == false)
+ {
+ int received = 0;
+ int sent = 0;
+
+ if (!wait.read)
+ {
+ int receivable = receiveBuffer.QueryInsertable();
+
+ if (receivable != 0)
+ {
+ if ((received = Receive(buf, receivable)) != 0)
+ {
+ log->Log(TAG_READ, tag, received, buf);
+ if (receiveDataSeen == false)
+ {
+ //
+ // If some noisy piece of software (eg PXE) spews lots
+ // of data down the serial port we might think the
+ // target is talking to the debugger. Debugger packets
+ // always contain some unprintable characters soooooo ..
+ // use that and the probability that anything spewed by
+ // something verbose is all printable as a heuristic to
+ // indicate whether or not we think we're hearing from
+ // the debugger.
+ //
+
+ for (int i = 0; i < received; i++)
+ {
+ if (!Printable(buf[i]))
+ {
+ receiveDataSeen = true;
+ printf("receiving data from debug target.\n");
+ log->Log(TAG_READ_DBG, tag, "Receive data from debug target.");
+ break;
+ }
+#if 1
+ else
+ {
+ printf("%c", buf[i]);
+ }
+#endif
+ }
+ }
+ if (sender->Connected() == false)
+ {
+ // Ignore all incoming data until there is something
+ // connected to send it to.
+ printf("sockreader: dropping %d bytes because pipe is not connected (ERROR)\n",
+ received);
+ log->Log(TAG_READ_DBG, tag,
+ "dropping %d bytes because pipe is not connected.\n",
+ received);
+ received = 0;
+ }
+
+ int count;
+
+ if (resetAckExpected)
+ {
+ count = CheckForInitialPacketHeader(buf, received);
+
+ if (count != 0)
+ {
+ // Initial packet seen. This is as good as a reset.
+
+ log->Log(TAG_READ_DBG, tag, "Initial packet received from target.\n");
+ SetResetAckExpected(false);
+ receiveBuffer.Insert(InitialPacketHeader, sizeof(InitialPacketHeader));
+ receiveBuffer.Insert(buf + count, received - count);
+ received = 0;
+ }
+ }
+
+ count = CheckForResetPacket(buf, received);
+
+ if (count != 0)
+ {
+ // Reset packet seen, which is really a reset ack.
+ // Were we expecting one?
+
+ if (resetAckExpected)
+ {
+ log->Log(TAG_READ_DBG, tag, "Reset ACK received from target.\n");
+ printf("Reset ACK received from target.\n");
+ if (killResetAck == false)
+ {
+ InsertResetPacket(&receiveBuffer);
+ }
+ else
+ {
+ killResetAck = false;
+ }
+ SetResetAckExpected(false);
+ receiveBuffer.Insert(buf + count, received - count);
+ received = 0;
+ }
+ else
+ {
+ printf("unexpected reset-ack from debug target, probably a bad thing.\n");
+ log->Log(TAG_READ_DBG, tag, "unexpected reset ACK received from target, PROBABLY A BAD THING.\n");
+ }
+ }
+ else
+ {
+ if (resetAckExpected)
+ {
+ // Waiting for a reset packet, ignore (ie drop)
+ // anything else.
+ log->Log(TAG_READ_DBG, tag,
+ "dropping %d bytes, waiting for reset ack.\n",
+ received);
+ received = 0;
+ }
+ }
+ receiveBuffer.Insert(buf, received);
+ }
+ }
+ }
+
+ //
+ // We received some data, yay. Pass it along.
+ //
+
+ if (!wait.write)
+ {
+ sent = sender->Send(&receiveBuffer);
+ }
+
+ if (!(sent | received))
+ {
+ Wait();
+ }
+ }
+ log->Log(TAG_READ_DBG, tag, "Socket is down.");
+ receiveDataSeen = false;
+ connected = false;
+}
+
--- /dev/null
+#if !defined(SOCKREADER_H)
+#define SOCKREADER_H
+
+#include "connectoid.h"
+
+class SockReader : public ThreadControl, public Connectoid
+{
+public:
+ SockReader();
+ ~SockReader();
+ bool Initialize(_TCHAR * Address,
+ _TCHAR * PortNumber,
+ Logger * Logger,
+ class Connectoid * Pipe,
+ bool StartThread,
+ char * Tag);
+ void ThreadEntry(void * inContext);
+ int Send(Circle * buffer);
+ int Receive(char * buffer, int length);
+
+private:
+ void Close();
+ void Pump();
+ bool Shutdown();
+ int CheckForInitialPacketHeader(char *, int);
+ bool shutdown;
+ bool doCleanup;
+ int initialPacketHeaderIndex;
+ bool passive;
+
+ // winsock2 fields
+
+ WSADATA wsaData;
+ SOCKET listenSocket;
+ SOCKET connection;
+ sockaddr_in service;
+};
+
+inline
+bool
+SockReader::Shutdown()
+{
+ return shutdown || g_shutdown;
+}
+
+#endif
--- /dev/null
+//
+// SpinLock. Generic procedural.
+//
+
+#include "stdafx.h"
+#include <windows.h>
+#include "plj_utils.h"
+#include "spinlock.h"
+
+
+void SpinLock::Acquire()
+{
+ for(;;)
+ {
+ while (value != 0)
+ {
+ //
+ // Move to the back of the ready queue. If this process had more
+ // than two threads we might want to do something more interesting
+ // but with only two, if the lock is held the other guy has it,
+ // give him a turn on the processor.
+ //
+
+ Sleep(0);
+ }
+
+ //
+ // Might want to use something more interesting than 1 for the lock value.
+ // for example, the current thread id, or simply whether it's the reader
+ // or writer.
+ //
+
+ if (InterlockedExchange(&value, 1) == 0)
+ {
+ return;
+ }
+ }
+}
+
+void SpinLock::Release()
+{
+ ASSERT(value != 0);
+ value = 0;
+}
+
+bool SpinLock::TryToAcquire()
+{
+ if (value != 0)
+ {
+ return false;
+ }
+
+ if (InterlockedExchange(&value, 1) != 0)
+ {
+ return false;
+ }
+ return true;
+}
--- /dev/null
+#if !defined(SPINLOCK_H)
+#define SPINLOCK_H
+
+class SpinLock
+{
+public:
+ SpinLock();
+ ~SpinLock();
+ bool Initialize();
+
+ void Acquire();
+ void Release();
+ bool TryToAcquire();
+
+private:
+ volatile LONG value;
+};
+
+inline
+SpinLock::SpinLock()
+{
+ value = 0;
+}
+
+inline
+SpinLock::~SpinLock()
+{
+}
+
+inline
+bool SpinLock::Initialize()
+{
+ value = 0;
+ return true;
+}
+
+#endif
--- /dev/null
+// stdafx.cpp : source file that includes just the standard includes
+// sockpipe.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
--- /dev/null
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+
+#if !defined(WIN32_LEAN_AND_MEAN)
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#endif
+
+#include <stdio.h>
+#include <tchar.h>
+
+
--- /dev/null
+#include "stdafx.h"
+#include <windows.h>
+#include "plj_utils.h"
+#include "spinlock.h"
+#include "threadcontrol.h"
+
+DWORD WINAPI ThreadStart(void * inContext)
+{
+ UNREFERENCED_PARAMETER(inContext);
+
+ //
+ // Thunk from win32 C style entry to the containing C++ object's
+ // ThreadEntry routine.
+ //
+
+ ((class ThreadControl *)inContext)->ThreadEntry(inContext);
+ return 0;
+}
+
+bool ThreadControl::Start()
+{
+ //
+ // Create thread and let it run.
+ //
+ // Note: Anything that needs to be done for this thread before it starts
+ // needs to have been done before we get here. This includes things like
+ // initializing any events it might be supposed to wait on.
+ //
+
+ handle = CreateThread(NULL, 0, ThreadStart, this, 0, &id);
+ if (handle == INVALID_HANDLE_VALUE)
+ {
+ return false;
+ }
+ return true;
+}
+
+
+void ThreadControl::ThreadEntry(void * inContext)
+{
+ UNREFERENCED_PARAMETER(inContext);
+
+ die("default ThreadEntry called. This should be overridden.");
+}
+
--- /dev/null
+#if !defined(THREADCONTROL_H)
+#define THREADCONTROL_H
+
+class ThreadControl
+{
+public:
+ bool Start();
+ virtual void ThreadEntry(void * inContext);
+
+private:
+ HANDLE handle;
+ DWORD id;
+};
+
+#endif
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Windows 8 Debug|Win32">
+ <Configuration>Windows 8 Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows 7 Debug|Win32">
+ <Configuration>Windows 7 Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows Vista Debug|Win32">
+ <Configuration>Windows Vista Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows 8 Release|Win32">
+ <Configuration>Windows 8 Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows 7 Release|Win32">
+ <Configuration>Windows 7 Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows Vista Release|Win32">
+ <Configuration>Windows Vista Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows 8 Debug|x64">
+ <Configuration>Windows 8 Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows 7 Debug|x64">
+ <Configuration>Windows 7 Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows Vista Debug|x64">
+ <Configuration>Windows Vista Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows 8 Release|x64">
+ <Configuration>Windows 8 Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows 7 Release|x64">
+ <Configuration>Windows 7 Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows Vista Release|x64">
+ <Configuration>Windows Vista Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+</Project>
--- /dev/null
+\r
+Microsoft Visual Studio Solution File, Format Version 12.00\r
+# Visual Studio 2012\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sockpipe", "sockpipe\sockpipe.vcxproj", "{C7C6DFE5-847D-467B-AA0B-86770B042667}"\r
+EndProject\r
+Global\r
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
+ Windows 7 Debug|Win32 = Windows 7 Debug|Win32\r
+ Windows 7 Debug|x64 = Windows 7 Debug|x64\r
+ Windows 7 Release|Win32 = Windows 7 Release|Win32\r
+ Windows 7 Release|x64 = Windows 7 Release|x64\r
+ Windows 8 Debug|Win32 = Windows 8 Debug|Win32\r
+ Windows 8 Debug|x64 = Windows 8 Debug|x64\r
+ Windows 8 Release|Win32 = Windows 8 Release|Win32\r
+ Windows 8 Release|x64 = Windows 8 Release|x64\r
+ Windows Vista Debug|Win32 = Windows Vista Debug|Win32\r
+ Windows Vista Debug|x64 = Windows Vista Debug|x64\r
+ Windows Vista Release|Win32 = Windows Vista Release|Win32\r
+ Windows Vista Release|x64 = Windows Vista Release|x64\r
+ EndGlobalSection\r
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 7 Debug|Win32.ActiveCfg = Windows 7 Debug|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 7 Debug|Win32.Build.0 = Windows 7 Debug|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 7 Debug|Win32.Deploy.0 = Windows 7 Debug|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 7 Debug|x64.ActiveCfg = Windows 7 Debug|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 7 Debug|x64.Build.0 = Windows 7 Debug|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 7 Debug|x64.Deploy.0 = Windows 7 Debug|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 7 Release|Win32.ActiveCfg = Windows 7 Release|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 7 Release|Win32.Build.0 = Windows 7 Release|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 7 Release|Win32.Deploy.0 = Windows 7 Release|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 7 Release|x64.ActiveCfg = Windows 7 Release|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 7 Release|x64.Build.0 = Windows 7 Release|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 7 Release|x64.Deploy.0 = Windows 7 Release|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Debug|Win32.ActiveCfg = Windows 8 Debug|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Debug|Win32.Build.0 = Windows 8 Debug|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Debug|Win32.Deploy.0 = Windows 8 Debug|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Debug|x64.ActiveCfg = Windows 8 Debug|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Debug|x64.Build.0 = Windows 8 Debug|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Debug|x64.Deploy.0 = Windows 8 Debug|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Release|Win32.ActiveCfg = Windows 8 Release|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Release|Win32.Build.0 = Windows 8 Release|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Release|Win32.Deploy.0 = Windows 8 Release|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Release|x64.ActiveCfg = Windows 8 Release|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Release|x64.Build.0 = Windows 8 Release|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Release|x64.Deploy.0 = Windows 8 Release|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows Vista Debug|Win32.ActiveCfg = Windows Vista Debug|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows Vista Debug|Win32.Build.0 = Windows Vista Debug|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows Vista Debug|Win32.Deploy.0 = Windows Vista Debug|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows Vista Debug|x64.ActiveCfg = Windows Vista Debug|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows Vista Debug|x64.Build.0 = Windows Vista Debug|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows Vista Debug|x64.Deploy.0 = Windows Vista Debug|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows Vista Release|Win32.ActiveCfg = Windows Vista Release|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows Vista Release|Win32.Build.0 = Windows Vista Release|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows Vista Release|Win32.Deploy.0 = Windows Vista Release|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows Vista Release|x64.ActiveCfg = Windows Vista Release|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows Vista Release|x64.Build.0 = Windows Vista Release|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows Vista Release|x64.Deploy.0 = Windows Vista Release|x64\r
+ EndGlobalSection\r
+ GlobalSection(SolutionProperties) = preSolution\r
+ HideSolutionNode = FALSE\r
+ EndGlobalSection\r
+EndGlobal\r
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="..\configs.props" />
+ <PropertyGroup Label="PropertySheets">
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>WindowsApplicationForDrivers8.0</PlatformToolset>
+ <ConfigurationType>Application</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Globals">
+ <Configuration>Windows Vista Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{c7c6dfe5-847d-467b-aa0b-86770b042667}</ProjectGuid>
+ </PropertyGroup>
+ <Import Project="..\targets.props" />
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <PropertyGroup>
+ <IncludePath>$(IncludePath)</IncludePath>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ <EnableInf2cat>false</EnableInf2cat>
+ </PropertyGroup>
+ <PropertyGroup>
+ <CustomBuildAfterTargets>Link</CustomBuildAfterTargets>
+ </PropertyGroup>
+ <ItemDefinitionGroup>
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;_CRT_SECURE_NO_WARNINGS;LOGGING_ENABLED=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <WarningLevel>EnableAllWarnings</WarningLevel>
+ <DisableSpecificWarnings>4127;4265;4365;4711;4548;4820;4668;4255;6001;6054;28196;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <EnablePREfast>true</EnablePREfast>
+ <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary>
+ <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>kernel32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
+ <ClCompile>
+ <PreprocessorDefinitions>__i386__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Platform)'=='x64'">
+ <ClCompile>
+ <PreprocessorDefinitions>__x86_64__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <FilesToPackage Include="$(TargetPath)" />
+ <FilesToPackage Include="$(OutDir)$(TargetName).pdb" />
+ <FilesToPackage Include="$(OutDir)$(TargetName).dll" />
+ <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\sockpipe\sockpipe.cpp" />
+ <ClCompile Include="..\..\src\sockpipe\Circle.cpp" />
+ <ClCompile Include="..\..\src\sockpipe\connectoid.cpp" />
+ <ClCompile Include="..\..\src\sockpipe\logger.cpp" />
+ <ClCompile Include="..\..\src\sockpipe\pipereader.cpp" />
+ <ClCompile Include="..\..\src\sockpipe\sockreader.cpp" />
+ <ClCompile Include="..\..\src\sockpipe\spinlock.cpp" />
+ <ClCompile Include="..\..\src\sockpipe\stdafx.cpp" />
+ <ClCompile Include="..\..\src\sockpipe\threadcontrol.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows 8 Debug|Win32'">
+ <TargetVersion>Windows8</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows 8 Release|Win32'">
+ <TargetVersion>Windows8</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows 8 Debug|x64'">
+ <TargetVersion>Windows8</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows 8 Release|x64'">
+ <TargetVersion>Windows8</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows 7 Debug|Win32'">
+ <TargetVersion>Windows7</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows 7 Release|Win32'">
+ <TargetVersion>Windows7</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows 7 Debug|x64'">
+ <TargetVersion>Windows7</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows 7 Release|x64'">
+ <TargetVersion>Windows7</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows Vista Debug|Win32'">
+ <TargetVersion>Vista</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows Vista Release|Win32'">
+ <TargetVersion>Vista</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows Vista Debug|x64'">
+ <TargetVersion>Vista</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows Vista Release|x64'">
+ <TargetVersion>Vista</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+</Project>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Windows 8 Debug|Win32">
+ <Configuration>Windows 8 Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows 7 Debug|Win32">
+ <Configuration>Windows 7 Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows Vista Debug|Win32">
+ <Configuration>Windows Vista Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows 8 Release|Win32">
+ <Configuration>Windows 8 Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows 7 Release|Win32">
+ <Configuration>Windows 7 Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows Vista Release|Win32">
+ <Configuration>Windows Vista Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows 8 Debug|x64">
+ <Configuration>Windows 8 Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows 7 Debug|x64">
+ <Configuration>Windows 7 Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows Vista Debug|x64">
+ <Configuration>Windows Vista Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows 8 Release|x64">
+ <Configuration>Windows 8 Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows 7 Release|x64">
+ <Configuration>Windows 7 Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows Vista Release|x64">
+ <Configuration>Windows Vista Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+</Project>
--- /dev/null
+\r
+Microsoft Visual Studio Solution File, Format Version 12.00\r
+# Visual Studio 2013\r
+VisualStudioVersion = 12.0.40629.0\r
+MinimumVisualStudioVersion = 10.0.40219.1\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sockpipe", "sockpipe\sockpipe.vcxproj", "{C7C6DFE5-847D-467B-AA0B-86770B042667}"\r
+EndProject\r
+Global\r
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
+ Windows 7 Debug|Win32 = Windows 7 Debug|Win32\r
+ Windows 7 Debug|x64 = Windows 7 Debug|x64\r
+ Windows 7 Release|Win32 = Windows 7 Release|Win32\r
+ Windows 7 Release|x64 = Windows 7 Release|x64\r
+ Windows 8 Debug|Win32 = Windows 8 Debug|Win32\r
+ Windows 8 Debug|x64 = Windows 8 Debug|x64\r
+ Windows 8 Release|Win32 = Windows 8 Release|Win32\r
+ Windows 8 Release|x64 = Windows 8 Release|x64\r
+ Windows Vista Debug|Win32 = Windows Vista Debug|Win32\r
+ Windows Vista Debug|x64 = Windows Vista Debug|x64\r
+ Windows Vista Release|Win32 = Windows Vista Release|Win32\r
+ Windows Vista Release|x64 = Windows Vista Release|x64\r
+ EndGlobalSection\r
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 7 Debug|Win32.ActiveCfg = Windows 7 Debug|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 7 Debug|Win32.Build.0 = Windows 7 Debug|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 7 Debug|Win32.Deploy.0 = Windows 7 Debug|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 7 Debug|x64.ActiveCfg = Windows 7 Debug|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 7 Debug|x64.Build.0 = Windows 7 Debug|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 7 Debug|x64.Deploy.0 = Windows 7 Debug|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 7 Release|Win32.ActiveCfg = Windows 7 Release|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 7 Release|Win32.Build.0 = Windows 7 Release|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 7 Release|Win32.Deploy.0 = Windows 7 Release|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 7 Release|x64.ActiveCfg = Windows 7 Release|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 7 Release|x64.Build.0 = Windows 7 Release|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 7 Release|x64.Deploy.0 = Windows 7 Release|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Debug|Win32.ActiveCfg = Windows 8 Debug|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Debug|Win32.Build.0 = Windows 8 Debug|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Debug|Win32.Deploy.0 = Windows 8 Debug|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Debug|x64.ActiveCfg = Windows 8 Debug|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Debug|x64.Build.0 = Windows 8 Debug|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Debug|x64.Deploy.0 = Windows 8 Debug|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Release|Win32.ActiveCfg = Windows 8 Release|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Release|Win32.Build.0 = Windows 8 Release|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Release|Win32.Deploy.0 = Windows 8 Release|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Release|x64.ActiveCfg = Windows 8 Release|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Release|x64.Build.0 = Windows 8 Release|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Release|x64.Deploy.0 = Windows 8 Release|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows Vista Debug|Win32.ActiveCfg = Windows Vista Debug|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows Vista Debug|Win32.Build.0 = Windows Vista Debug|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows Vista Debug|Win32.Deploy.0 = Windows Vista Debug|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows Vista Debug|x64.ActiveCfg = Windows Vista Debug|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows Vista Debug|x64.Build.0 = Windows Vista Debug|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows Vista Debug|x64.Deploy.0 = Windows Vista Debug|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows Vista Release|Win32.ActiveCfg = Windows Vista Release|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows Vista Release|Win32.Build.0 = Windows Vista Release|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows Vista Release|Win32.Deploy.0 = Windows Vista Release|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows Vista Release|x64.ActiveCfg = Windows Vista Release|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows Vista Release|x64.Build.0 = Windows Vista Release|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows Vista Release|x64.Deploy.0 = Windows Vista Release|x64\r
+ EndGlobalSection\r
+ GlobalSection(SolutionProperties) = preSolution\r
+ HideSolutionNode = FALSE\r
+ EndGlobalSection\r
+EndGlobal\r
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="..\configs.props" />
+ <PropertyGroup Label="Globals">
+ <Configuration>Windows Vista Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets">
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>WindowsApplicationForDrivers8.1</PlatformToolset>
+ <ConfigurationType>Application</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{c7c6dfe5-847d-467b-aa0b-86770b042667}</ProjectGuid>
+ </PropertyGroup>
+ <Import Project="..\targets.props" />
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <PropertyGroup>
+ <IncludePath>$(IncludePath)</IncludePath>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ <EnableInf2cat>false</EnableInf2cat>
+ </PropertyGroup>
+ <PropertyGroup>
+ <CustomBuildAfterTargets>Link</CustomBuildAfterTargets>
+ </PropertyGroup>
+ <ItemDefinitionGroup>
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;_CRT_SECURE_NO_WARNINGS;LOGGING_ENABLED=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <WarningLevel>EnableAllWarnings</WarningLevel>
+ <DisableSpecificWarnings>4127;4265;4365;4711;4548;4820;4668;4255;6001;6054;28196;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <EnablePREfast>true</EnablePREfast>
+ <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary>
+ <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>kernel32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
+ <ClCompile>
+ <PreprocessorDefinitions>__i386__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Platform)'=='x64'">
+ <ClCompile>
+ <PreprocessorDefinitions>__x86_64__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <FilesToPackage Include="$(TargetPath)" />
+ <FilesToPackage Include="$(OutDir)$(TargetName).pdb" />
+ <FilesToPackage Include="$(OutDir)$(TargetName).dll" />
+ <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\sockpipe\sockpipe.cpp" />
+ <ClCompile Include="..\..\src\sockpipe\Circle.cpp" />
+ <ClCompile Include="..\..\src\sockpipe\connectoid.cpp" />
+ <ClCompile Include="..\..\src\sockpipe\logger.cpp" />
+ <ClCompile Include="..\..\src\sockpipe\pipereader.cpp" />
+ <ClCompile Include="..\..\src\sockpipe\sockreader.cpp" />
+ <ClCompile Include="..\..\src\sockpipe\spinlock.cpp" />
+ <ClCompile Include="..\..\src\sockpipe\stdafx.cpp" />
+ <ClCompile Include="..\..\src\sockpipe\threadcontrol.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows 8 Debug|Win32'">
+ <TargetVersion>Windows8</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows 8 Release|Win32'">
+ <TargetVersion>Windows8</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows 8 Debug|x64'">
+ <TargetVersion>Windows8</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows 8 Release|x64'">
+ <TargetVersion>Windows8</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows 7 Debug|Win32'">
+ <TargetVersion>Windows7</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows 7 Release|Win32'">
+ <TargetVersion>Windows7</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows 7 Debug|x64'">
+ <TargetVersion>Windows7</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows 7 Release|x64'">
+ <TargetVersion>Windows7</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows Vista Debug|Win32'">
+ <TargetVersion>Vista</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows Vista Release|Win32'">
+ <TargetVersion>Vista</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows Vista Debug|x64'">
+ <TargetVersion>Vista</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows Vista Release|x64'">
+ <TargetVersion>Vista</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+</Project>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Windows 10 Debug|Win32">
+ <Configuration>Windows 10 Debug</Configuration>
+ <Platform>Win32</Platform>
+ <WindowsTargetPlatformVersion>10</WindowsTargetPlatformVersion>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows 10 Release|Win32">
+ <Configuration>Windows 10 Release</Configuration>
+ <Platform>Win32</Platform>
+ <WindowsTargetPlatformVersion>10</WindowsTargetPlatformVersion>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows 10 Debug|x64">
+ <Configuration>Windows 10 Debug</Configuration>
+ <Platform>x64</Platform>
+ <WindowsTargetPlatformVersion>10</WindowsTargetPlatformVersion>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows 10 Release|x64">
+ <Configuration>Windows 10 Release</Configuration>
+ <Platform>x64</Platform>
+ <WindowsTargetPlatformVersion>10</WindowsTargetPlatformVersion>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows 8 Debug|Win32">
+ <Configuration>Windows 8 Debug</Configuration>
+ <Platform>Win32</Platform>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows 8 Release|Win32">
+ <Configuration>Windows 8 Release</Configuration>
+ <Platform>Win32</Platform>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows 8 Debug|x64">
+ <Configuration>Windows 8 Debug</Configuration>
+ <Platform>x64</Platform>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Windows 8 Release|x64">
+ <Configuration>Windows 8 Release</Configuration>
+ <Platform>x64</Platform>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ </ProjectConfiguration>
+ </ItemGroup>
+</Project>
--- /dev/null
+\r
+Microsoft Visual Studio Solution File, Format Version 12.00\r
+# Visual Studio 14\r
+VisualStudioVersion = 14.0.25420.1\r
+MinimumVisualStudioVersion = 10.0.40219.1\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sockpipe", "sockpipe\sockpipe.vcxproj", "{C7C6DFE5-847D-467B-AA0B-86770B042667}"\r
+EndProject\r
+Global\r
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
+ Windows 10 Debug|Win32 = Windows 10 Debug|Win32\r
+ Windows 10 Debug|x64 = Windows 10 Debug|x64\r
+ Windows 10 Release|Win32 = Windows 10 Release|Win32\r
+ Windows 10 Release|x64 = Windows 10 Release|x64\r
+ Windows 8 Debug|Win32 = Windows 8 Debug|Win32\r
+ Windows 8 Debug|x64 = Windows 8 Debug|x64\r
+ Windows 8 Release|Win32 = Windows 8 Release|Win32\r
+ Windows 8 Release|x64 = Windows 8 Release|x64\r
+ EndGlobalSection\r
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 10 Debug|Win32.ActiveCfg = Windows 10 Debug|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 10 Debug|Win32.Build.0 = Windows 10 Debug|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 10 Debug|x64.ActiveCfg = Windows 10 Debug|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 10 Debug|x64.Build.0 = Windows 10 Debug|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 10 Release|Win32.ActiveCfg = Windows 10 Release|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 10 Release|Win32.Build.0 = Windows 10 Release|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 10 Release|x64.ActiveCfg = Windows 10 Release|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 10 Release|x64.Build.0 = Windows 10 Release|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Debug|Win32.ActiveCfg = Windows 8 Debug|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Debug|Win32.Build.0 = Windows 8 Debug|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Debug|x64.ActiveCfg = Windows 8 Debug|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Debug|x64.Build.0 = Windows 8 Debug|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Release|Win32.ActiveCfg = Windows 8 Release|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Release|Win32.Build.0 = Windows 8 Release|Win32\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Release|x64.ActiveCfg = Windows 8 Release|x64\r
+ {C7C6DFE5-847D-467B-AA0B-86770B042667}.Windows 8 Release|x64.Build.0 = Windows 8 Release|x64\r
+ EndGlobalSection\r
+ GlobalSection(SolutionProperties) = preSolution\r
+ HideSolutionNode = FALSE\r
+ EndGlobalSection\r
+EndGlobal\r
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="..\configs.props" />
+ <PropertyGroup Label="PropertySheets">
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>Application</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{c7c6dfe5-847d-467b-aa0b-86770b042667}</ProjectGuid>
+ </PropertyGroup>
+ <Import Project="..\targets.props" />
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <PropertyGroup>
+ <IncludePath>$(IncludePath)</IncludePath>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ <EnableInf2cat>false</EnableInf2cat>
+ </PropertyGroup>
+ <PropertyGroup>
+ <CustomBuildAfterTargets>Link</CustomBuildAfterTargets>
+ </PropertyGroup>
+ <ItemDefinitionGroup>
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;_CRT_SECURE_NO_WARNINGS;LOGGING_ENABLED=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <WarningLevel>EnableAllWarnings</WarningLevel>
+ <DisableSpecificWarnings>4127;4265;4365;4548;4711;4777;4820;4668;4255;4996;6001;6054;28196;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <EnablePREfast>true</EnablePREfast>
+ <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary>
+ <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>kernel32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
+ <ClCompile>
+ <PreprocessorDefinitions>__i386__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Platform)'=='x64'">
+ <ClCompile>
+ <PreprocessorDefinitions>__x86_64__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <FilesToPackage Include="$(TargetPath)" />
+ <FilesToPackage Include="$(OutDir)$(TargetName).pdb" />
+ <FilesToPackage Include="$(OutDir)$(TargetName).dll" />
+ <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\sockpipe\sockpipe.cpp" />
+ <ClCompile Include="..\..\src\sockpipe\Circle.cpp" />
+ <ClCompile Include="..\..\src\sockpipe\connectoid.cpp" />
+ <ClCompile Include="..\..\src\sockpipe\logger.cpp" />
+ <ClCompile Include="..\..\src\sockpipe\pipereader.cpp" />
+ <ClCompile Include="..\..\src\sockpipe\sockreader.cpp" />
+ <ClCompile Include="..\..\src\sockpipe\spinlock.cpp" />
+ <ClCompile Include="..\..\src\sockpipe\stdafx.cpp" />
+ <ClCompile Include="..\..\src\sockpipe\threadcontrol.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows 10 Debug|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows 10 Release|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows 10 Debug|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows 10 Release|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows 8 Debug|Win32'">
+ <TargetVersion>Windows8</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows 8 Release|Win32'">
+ <TargetVersion>Windows8</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows 8 Debug|x64'">
+ <TargetVersion>Windows8</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Windows 8 Release|x64'">
+ <TargetVersion>Windows8</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+</Project>