summaryrefslogtreecommitdiffstats
path: root/src/ccapi/server/win
diff options
context:
space:
mode:
authorKevin Koch <kpkoch@mit.edu>2008-01-22 19:14:04 +0000
committerKevin Koch <kpkoch@mit.edu>2008-01-22 19:14:04 +0000
commit7bfff83859f4bfb254c659dc0caa529735fd2507 (patch)
tree0a9f78c9ae794e3f98616b7d7f9cc59825aef216 /src/ccapi/server/win
parentfaf9366d3111f171e157b1e45ba7b49d5a529903 (diff)
downloadkrb5-7bfff83859f4bfb254c659dc0caa529735fd2507.tar.gz
krb5-7bfff83859f4bfb254c659dc0caa529735fd2507.tar.xz
krb5-7bfff83859f4bfb254c659dc0caa529735fd2507.zip
Windows CCAPI snapshot. Should build & pass ping test
TargetVersion: 1.7 Component: krb5-libs Ticket: 5594 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@20203 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/ccapi/server/win')
-rw-r--r--src/ccapi/server/win/Makefile105
-rw-r--r--src/ccapi/server/win/Server.sln20
-rw-r--r--src/ccapi/server/win/Server.vcproj227
-rw-r--r--src/ccapi/server/win/WorkItem.cpp126
-rw-r--r--src/ccapi/server/win/WorkQueue.cpp61
-rw-r--r--src/ccapi/server/win/WorkQueue.h46
-rw-r--r--src/ccapi/server/win/ccs_os_pipe.c64
-rw-r--r--src/ccapi/server/win/ccs_os_server.cpp950
-rw-r--r--src/ccapi/server/win/ccs_request_proc.c116
-rw-r--r--src/ccapi/server/win/ccs_win_pipe.c163
-rw-r--r--src/ccapi/server/win/ccs_win_pipe.h69
-rw-r--r--src/ccapi/server/win/workitem.h48
12 files changed, 1995 insertions, 0 deletions
diff --git a/src/ccapi/server/win/Makefile b/src/ccapi/server/win/Makefile
new file mode 100644
index 000000000..deaebb2e0
--- /dev/null
+++ b/src/ccapi/server/win/Makefile
@@ -0,0 +1,105 @@
+!include <Win32.Mak>
+
+# . is ...\pismere\athena\auth\krb5\src\ccapi\server\win
+CCAPI = ..\..
+CO = $(CCAPI)\common
+COWIN = $(CCAPI)\common\win
+CCUTIL = $(CCAPI)\common\win\OldCC
+LIBDIR = $(CCAPI)\lib
+LIBWIN = $(CCAPI)\lib\win
+K5SRC = $(CCAPI)\..
+POSIX = $(K5SRC)\lib\krb5\posix
+
+INC = -I. -I.. -I$(CO) -I$(COWIN) -I$(K5SRC)\include -I..\..\..\util\et -I$(CCUTIL)
+
+!if "$(CPU)" == "i386"
+cflags = $(cflags) /EHsc -D_CRTAPI1=_cdecl -D_CRTAPI2=_cdecl -DWINVER=0x0501 -D_WIN32_WINNT=0x0501 \
+$(INC) -MTd
+!else
+cflags = $(cflags) /W3 -D_CRTAPI1= -D_CRTAPI2= $(INC)
+!endif
+
+all : server
+
+server : server.exe
+
+common = cci_array_internal.obj cci_cred_union.obj cci_debugging.obj cci_identifier.obj \
+ cci_message.obj cci_stream.obj
+
+commonwin = cci_os_debugging.obj \
+ cci_os_identifier.obj \
+ tls.obj \
+ win-utils.obj
+
+ccutils = ccutils.obj
+
+ccutilscxx = opts.obj util.obj secure.obj init.obj
+
+dll = ccapi_string.obj
+
+srv = ccs_array.obj ccs_cache_collection.obj ccs_callback.obj ccs_ccache.obj \
+ ccs_ccache_iterator.obj ccs_client.obj \
+ ccs_credentials.obj ccs_credentials_iterator.obj ccs_list.obj ccs_list_internal.obj \
+ ccs_lock.obj ccs_lock_state.obj ccs_pipe.obj ccs_server.obj
+
+srvwin = ccs_os_pipe.obj ccs_reply_c.obj \
+ ccs_request_proc.obj ccs_win_pipe.obj
+
+srvwincpp = ccs_os_server.obj ccs_request_s.obj WorkItem.obj WorkQueue.obj
+
+linkobjs = $(common) $(commonwin) $(ccutils) $(ccutilscxx) \
+ $(srv) $(srvwin) $(srvwincpp)
+
+includes = ccs_reply.h ccs_request.h
+
+# Main program:
+server.exe : $(linkobjs)
+# $(link) $(linkdebug) $(conflags) -MTd -out:ccapiserver.exe $(linkobjs) \
+ $(link) $(linkdebug) $(conflags) -out:ccapiserver.exe $(linkobjs) \
+ rpcrt4.lib advapi32.lib ws2_32.lib user32.lib
+
+
+ccs_request.h ccs_request_s.cpp : $(COWIN)\ccs_request.idl $(COWIN)\ccs_request.acf
+ midl $(MIDL_OPTIMIZATION) -oldnames -cpp_cmd $(cc) -cpp_opt "-E" -I. -I$(COWIN) -sstub \
+ ccs_request_s.cpp $(COWIN)\ccs_request.idl
+
+ccs_reply.h ccs_reply_c.c : $(COWIN)\ccs_reply.idl $(COWIN)\ccs_reply.acf
+ midl $(MIDL_OPTIMIZATION) -oldnames -cpp_cmd $(cc) -cpp_opt "-E" -I. -I$(COWIN) \
+ $(COWIN)\ccs_reply.idl
+
+$(common) : $(CO)\$*.c
+ $(cc) $(cdebug) $(cflags) $(CO)\$*.c
+
+$(commonwin) : $(COWIN)\$*.c
+ $(cc) $(cdebug) $(cflags) $(COWIN)\$*.c
+
+$(ccutils) : $(CCUTIL)\$*.c
+ $(cc) $(cdebug) $(cflags) $(CCUTIL)\$*.c
+
+$(ccutilscxx) : $(CCUTIL)\$*.cxx
+ $(cc) $(cdebug) $(cflags) $(CCUTIL)\$*.cxx
+
+$(srv) : ..\$*.c
+ $(cc) $(cdebug) $(cflags) ..\$*.c
+
+$(srvwin) : $*.c $(includes)
+ $(cc) $(cdebug) $(cflags) $*.c
+
+$(srvwincpp) : $*.cpp
+ $(cc) $(cdebug) $(cflags) $*.cpp
+
+
+# Clean up everything
+cleanall : clean
+ -del *.exe
+
+# Clean up everything but the .EXEs
+clean :
+ -del *.obj
+ -del *.map
+ -del ccs_request_s.c
+ -del ccs_request_c.c
+ -del ccs_request.h
+ -del ccs_reply_s.c
+ -del ccs_reply_c.c
+ -del ccs_reply.h
diff --git a/src/ccapi/server/win/Server.sln b/src/ccapi/server/win/Server.sln
new file mode 100644
index 000000000..64cc7f08c
--- /dev/null
+++ b/src/ccapi/server/win/Server.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Server", "Server.vcproj", "{114DCD80-6D13-4AAA-9510-B51CE6D94C1C}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {114DCD80-6D13-4AAA-9510-B51CE6D94C1C}.Debug|Win32.ActiveCfg = Debug|Win32
+ {114DCD80-6D13-4AAA-9510-B51CE6D94C1C}.Debug|Win32.Build.0 = Debug|Win32
+ {114DCD80-6D13-4AAA-9510-B51CE6D94C1C}.Release|Win32.ActiveCfg = Release|Win32
+ {114DCD80-6D13-4AAA-9510-B51CE6D94C1C}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/src/ccapi/server/win/Server.vcproj b/src/ccapi/server/win/Server.vcproj
new file mode 100644
index 000000000..39db361d8
--- /dev/null
+++ b/src/ccapi/server/win/Server.vcproj
@@ -0,0 +1,227 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="Server"
+ ProjectGUID="{114DCD80-6D13-4AAA-9510-B51CE6D94C1C}"
+ RootNamespace="Server"
+ Keyword="MakeFileProj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="0"
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake"
+ ReBuildCommandLine="nmake"
+ CleanCommandLine="nmake clean"
+ Output=""
+ PreprocessorDefinitions="WIN32;_DEBUG;"
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="0"
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="nmake"
+ ReBuildCommandLine="nmake"
+ CleanCommandLine="nmake clean"
+ Output=""
+ PreprocessorDefinitions="WIN32;NDEBUG;"
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\..\common\cci_debugging.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\cci_os_debugging.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\cci_stream.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ccs_reply.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ccs_request.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ccs_server.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\win\ccutil\ccutils.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\win\ccutil\init.hxx"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\include\k5-platform.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\win\ccutil\secure.hxx"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\win\ccutil\util.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\win\win-utils.h"
+ >
+ </File>
+ <File
+ RelativePath=".\workitem.h"
+ >
+ </File>
+ <File
+ RelativePath=".\WorkQueue.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\common\cci_debugging.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\win\cci_os_debugging.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\cci_stream.c"
+ >
+ </File>
+ <File
+ RelativePath="..\ccs_lock.c"
+ >
+ </File>
+ <File
+ RelativePath=".\ccs_os_pipe.c"
+ >
+ </File>
+ <File
+ RelativePath=".\ccs_os_server.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\win\ccs_reply.Idl"
+ >
+ </File>
+ <File
+ RelativePath=".\ccs_reply_c.c"
+ >
+ </File>
+ <File
+ RelativePath=".\ccs_reply_s.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\win\ccs_request.idl"
+ >
+ </File>
+ <File
+ RelativePath=".\ccs_request_c.c"
+ >
+ </File>
+ <File
+ RelativePath=".\ccs_request_proc.c"
+ >
+ </File>
+ <File
+ RelativePath=".\ccs_request_s.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\ccs_server.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\win\ccutil\ccutils.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\win\ccutil\init.cxx"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\win\ccutil\secure.cxx"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\win\ccutil\util.cxx"
+ >
+ </File>
+ <File
+ RelativePath="..\..\common\win\win-utils.c"
+ >
+ </File>
+ <File
+ RelativePath=".\WorkItem.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\WorkQueue.cpp"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="..\..\common\win\ccs_reply.Acf"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/ccapi/server/win/WorkItem.cpp b/src/ccapi/server/win/WorkItem.cpp
new file mode 100644
index 000000000..7e6aeb1cb
--- /dev/null
+++ b/src/ccapi/server/win/WorkItem.cpp
@@ -0,0 +1,126 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include <string.h>
+#include "assert.h"
+
+#pragma warning (disable : 4996)
+
+#include "win-utils.h"
+#include "WorkItem.h"
+
+extern "C" {
+#include "cci_debugging.h"
+ }
+
+// CountedBuffer makes a copy of the data. Each CountedBuffer must be deleted.
+
+void deleteBuffer(char** buf) {
+ if (*buf) {
+ delete [](*buf);
+ *buf = NULL;
+ }
+ }
+
+// WorkItem contains a CountedBuffer which must be deleted,
+// so each WorkItem must be deleted.
+WorkItem::WorkItem(cci_stream_t buf, WIN_PIPE* pipe, const long type, const long sst)
+: _buf(buf), _rpcmsg(type), _pipe(pipe), _sst(sst) { }
+
+WorkItem::WorkItem(const WorkItem& item) : _buf(NULL), _rpcmsg(0), _pipe(NULL), _sst(0) {
+
+ cci_stream_t _buf = NULL;
+ cci_stream_new(&_buf);
+ cci_stream_write(_buf,
+ cci_stream_data(item.payload()),
+ cci_stream_size(item.payload()) );
+ WorkItem(_buf, item._pipe, item._rpcmsg, item._sst);
+ }
+
+WorkItem::WorkItem() : _buf(NULL), _rpcmsg(CCMSG_INVALID), _pipe(NULL), _sst(0) { }
+
+WorkItem::~WorkItem() {
+ if (_buf) cci_stream_release(_buf);
+ if (_pipe) ccs_win_pipe_release(_pipe);
+ }
+
+const cci_stream_t WorkItem::take_payload() {
+ cci_stream_t temp = payload();
+ _buf = NULL;
+ return temp;
+ }
+
+WIN_PIPE* WorkItem::take_pipe() {
+ WIN_PIPE* temp = pipe();
+ _pipe = NULL;
+ return temp;
+ }
+
+WorkList::WorkList() {
+ assert(InitializeCriticalSectionAndSpinCount(&cs, 0x80000400));
+ }
+
+WorkList::~WorkList() {
+ // Delete any WorkItems in the queue:
+ WorkItem* item;
+ cci_debug_printf("%s", __FUNCTION__);
+ char buf[2048];
+ char* pbuf = (char*)buf;
+ while (remove(&item)) {
+ cci_debug_printf("WorkList::~WorkList() deleting %s", item->print(pbuf));
+ delete item;
+ }
+
+ DeleteCriticalSection(&cs);
+ }
+
+char* WorkItem::print(char* buf) {
+ sprintf(buf, "WorkItem msg#:%d sst:%ld pipe:<%s>/0x%X", _rpcmsg, _sst,
+ ccs_win_pipe_getUuid(_pipe), ccs_win_pipe_getHandle(_pipe));
+ return buf;
+ }
+
+int WorkList::add(WorkItem* item) {
+ EnterCriticalSection(&cs);
+ wl.push_front(item);
+ LeaveCriticalSection(&cs);
+ return 1;
+ }
+
+int WorkList::remove(WorkItem** item) {
+ bool bEmpty;
+
+ bEmpty = wl.empty() & 1;
+
+ if (!bEmpty) {
+ EnterCriticalSection(&cs);
+ *item = wl.back();
+ wl.pop_back();
+ LeaveCriticalSection(&cs);
+ }
+
+ return !bEmpty;
+ } \ No newline at end of file
diff --git a/src/ccapi/server/win/WorkQueue.cpp b/src/ccapi/server/win/WorkQueue.cpp
new file mode 100644
index 000000000..711ecc173
--- /dev/null
+++ b/src/ccapi/server/win/WorkQueue.cpp
@@ -0,0 +1,61 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+extern "C" {
+ #include "cci_debugging.h"
+ }
+
+#include "WorkItem.h"
+
+WorkList worklist;
+
+/* C interfaces: */
+EXTERN_C bool worklist_isEmpty() {
+ return worklist.isEmpty();
+ }
+
+EXTERN_C int worklist_add( const long rpcmsg,
+ const ccs_pipe_t pipe,
+ const cci_stream_t stream,
+ const time_t serverStartTime) {
+ return worklist.add(new WorkItem(stream, pipe, rpcmsg, serverStartTime) );
+ }
+
+EXTERN_C int worklist_remove(long* rpcmsg,
+ ccs_pipe_t* pipe,
+ cci_stream_t* stream,
+ time_t* sst) {
+ WorkItem* item = NULL;
+ cc_int32 err = worklist.remove(&item);
+
+ *rpcmsg = item->type();
+ *pipe = item->take_pipe();
+ *stream = item->take_payload();
+ *sst = item->sst();
+ delete item;
+ return err;
+ }
+
diff --git a/src/ccapi/server/win/WorkQueue.h b/src/ccapi/server/win/WorkQueue.h
new file mode 100644
index 000000000..106f9acb9
--- /dev/null
+++ b/src/ccapi/server/win/WorkQueue.h
@@ -0,0 +1,46 @@
+/*
+ * $Header$
+ *
+ * Copyright 2007 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef _work_queue_h
+#define _work_queue_h
+
+#include "windows.h"
+#include "cci_stream.h"
+#include "ccs_pipe.h"
+
+EXTERN_C BOOL worklist_isEmpty();
+
+EXTERN_C void worklist_add( const long rpcmsg,
+ const ccs_pipe_t pipe,
+ const cci_stream_t stream,
+ const time_t serverStartTime);
+
+EXTERN_C int worklist_remove(long* rpcmsg,
+ ccs_pipe_t* pipe,
+ cci_stream_t* stream,
+ time_t* serverStartTime);
+
+#endif // _work_queue_h \ No newline at end of file
diff --git a/src/ccapi/server/win/ccs_os_pipe.c b/src/ccapi/server/win/ccs_os_pipe.c
new file mode 100644
index 000000000..69dcec474
--- /dev/null
+++ b/src/ccapi/server/win/ccs_os_pipe.c
@@ -0,0 +1,64 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccs_common.h"
+#include "ccs_os_pipe.h"
+#include "ccs_win_pipe.h"
+
+/* ------------------------------------------------------------------------ */
+
+/* On Windows, a pipe is a struct. See ccs_win_pipe.h for details. */
+
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_os_pipe_valid (ccs_pipe_t in_pipe) {
+ return ccs_win_pipe_valid(in_pipe);
+ }
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_os_pipe_copy (ccs_pipe_t* out_pipe, ccs_pipe_t in_pipe) {
+ return ccs_win_pipe_copy(
+ out_pipe,
+ in_pipe);
+ }
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_os_pipe_release (ccs_pipe_t io_pipe) {
+ return ccs_win_pipe_release(io_pipe);
+ }
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_os_pipe_compare (ccs_pipe_t pipe_1,
+ ccs_pipe_t pipe_2,
+ cc_uint32 *out_equal) {
+
+ return ccs_win_pipe_compare(pipe_1, pipe_2, out_equal);
+ }
+
diff --git a/src/ccapi/server/win/ccs_os_server.cpp b/src/ccapi/server/win/ccs_os_server.cpp
new file mode 100644
index 000000000..0c3f7660e
--- /dev/null
+++ b/src/ccapi/server/win/ccs_os_server.cpp
@@ -0,0 +1,950 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "process.h"
+#include "windows.h"
+
+extern "C" {
+#include "ccs_common.h"
+#include "ccs_os_server.h"
+#include <syslog.h>
+#include "ccs_reply.h"
+#include "ccs_request.h"
+#include "win-utils.h"
+#include "ccutils.h"
+#include "cci_stream.h"
+ }
+
+#include "WorkQueue.h"
+#include "util.h"
+#include "opts.hxx"
+#include "init.hxx"
+
+#pragma warning (disable : 4996)
+
+BOOL bListen = TRUE; /* Why aren't bool and true defined? */
+const char* sessID = NULL; /* The logon session we are running on behalf of. */
+time_t _sst = 0;
+unsigned char* pszNetworkAddress = NULL;
+unsigned char* pszStringBinding = NULL;
+BOOL bRpcHandleInited = FALSE;
+_RPC_ASYNC_STATE* rpcState = NULL;
+
+/* Thread procedures can take only one void* argument. We put all the args we want
+ to pass into this struct and then pass a pointer to the struct: */
+struct RpcRcvArgs {
+ char* networkAddress;
+ unsigned char* protocolSequence;
+ unsigned char* sessID; /* Used for this server's endpoint */
+ unsigned char* uuid; /* Used for client's UUID */
+ ParseOpts::Opts* opts;
+ RPC_STATUS status;
+ } rpcargs = { NULL, /* pszNetworkAddress */
+ (unsigned char*)"ncalrpc", /* pszProtocolSequence */
+ NULL, /* sessID placeholder */
+ NULL, /* uuid placeholder */
+ NULL }; /* Opts placeholder */
+
+/* Command line format:
+ argv[0] Program name
+ argv[1] session ID to use
+ argv[2] "D" Debug: go into infinite loop in ccs_os_server_initialize so process
+ can be attached in debugger.
+ Any other value: continue
+ */
+#define N_FIXED_ARGS 3
+#define SERVER_REPLY_RPC_HANDLE ccs_reply_IfHandle
+
+/* Forward declarations: */
+void receiveLoop(void* rpcargs);
+void connectionListener(void* rpcargs);
+void Usage(const char* argv0);
+void printError(TCHAR* msg);
+void setMySST() {_sst = time(&_sst);}
+time_t getMySST() {return _sst;}
+RPC_STATUS send_connection_reply(ccs_pipe_t in_pipe);
+void RPC_ENTRY clientListener( _RPC_ASYNC_STATE*,
+ void* Context,
+ RPC_ASYNC_EVENT Event);
+RPC_STATUS RPC_ENTRY sec_callback( IN RPC_IF_ID *Interface,
+ IN void *Context);
+RPC_STATUS send_init(char* clientUUID);
+//DWORD alloc_name(LPSTR* pname, LPSTR postfix);
+
+
+/* The layout of the rest of this module:
+
+ The four entrypoints defined in ccs_os_server.h:
+ ccs_os_server_initialize
+ cc_int32 ccs_os_server_cleanup
+ cc_int32 ccs_os_server_listen_loop
+ cc_int32 ccs_os_server_send_reply
+
+ Other routines needed by those four.
+ */
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_os_server_initialize (int argc, const char *argv[]) {
+ cc_int32 err = 0;
+ ParseOpts::Opts opts = { 0 };
+ ParseOpts PO;
+ BOOL bAdjustedShutdown = FALSE;
+ HMODULE hKernel32 = GetModuleHandle("kernel32");
+
+ if (!err) {
+ sessID = argv[1];
+ setMySST();
+
+ opts.cMinCalls = 1;
+ opts.cMaxCalls = 20;
+ opts.fDontWait = TRUE;
+
+#ifdef CCAPI_TEST_OPTIONS
+ PO.SetValidOpts("kemnfubc");
+#else
+ PO.SetValidOpts("kc");
+#endif
+
+ PO.Parse(opts, argc, (char**)argv);
+
+// while(*argv[2] == 'D') {} /* Hang here to attach process with debugger. */
+
+ if (hKernel32) {
+ typedef BOOL (WINAPI *FP_SetProcessShutdownParameters)(DWORD, DWORD);
+ FP_SetProcessShutdownParameters pSetProcessShutdownParameters =
+ (FP_SetProcessShutdownParameters)
+ GetProcAddress(hKernel32, "SetProcessShutdownParameters");
+ if (pSetProcessShutdownParameters) {
+ bAdjustedShutdown = pSetProcessShutdownParameters(100, 0);
+ }
+ }
+ cci_debug_printf("%s Shutdown Parameters",
+ bAdjustedShutdown ? "Adjusted" : "Did not adjust");
+
+ err = Init::Initialize();
+ }
+
+// if (!err) {
+// if (opts.bShutdown) {
+// status = shutdown_server(opts.pszEndpoint);
+// }
+// }
+// else {
+// status = startup_server(opts);
+// }
+
+ if (err) {
+ Init::Cleanup();
+ fprintf( stderr, "An error occured while %s the server (%u)\n",
+ opts.bShutdown ? "shutting down" : "starting/running",
+ err);
+ exit(cci_check_error (err));
+ }
+
+ return cci_check_error (err);
+ }
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_os_server_cleanup (int argc, const char *argv[]) {
+ cc_int32 err = 0;
+
+ cci_debug_printf("%s for user <%s> shutting down.", argv[0], argv[1]);
+
+ return cci_check_error (err);
+ }
+
+/* ------------------------------------------------------------------------ */
+
+/* This function takes work items off the work queue and executes them.
+ * This is the one and only place where the multi-threaded Windows code
+ * calls into the single-threaded common code.
+ *
+ * The actual 'listening' for requests from clients happens after receiveloop
+ * establishes the RPC endpoint the clients will connect to and the RPC procedures
+ * put the work items into the work queue.
+ */
+cc_int32 ccs_os_server_listen_loop (int argc, const char *argv[]) {
+ cc_int32 err = 0;
+ uintptr_t threadStatus;
+ unsigned int loopCounter = 0;
+
+ ParseOpts::Opts opts = { 0 };
+ ParseOpts PO;
+
+ opts.cMinCalls = 1;
+ opts.cMaxCalls = 20;
+ opts.fDontWait = TRUE;
+
+#ifdef CCAPI_TEST_OPTIONS
+ PO.SetValidOpts("kemnfubc");
+#else
+ PO.SetValidOpts("kc");
+#endif
+ PO.Parse(opts, argc, (char**)argv);
+
+
+ //++ debug stuff
+ #define INFO_BUFFER_SIZE 32767
+ TCHAR infoBuf[INFO_BUFFER_SIZE];
+ DWORD bufCharCount = INFO_BUFFER_SIZE;
+ // Get and display the user name.
+ bufCharCount = INFO_BUFFER_SIZE;
+ if( !GetUserName( infoBuf, &bufCharCount ) ) printError( TEXT("GetUserName") );
+ //--
+
+ /* Sending the reply from within the request RPC handler doesn't seem to work.
+ So we listen for requests in a separate thread and put the requests in a
+ queue. */
+ rpcargs.sessID = (unsigned char*)sessID;
+ rpcargs.opts = &opts;
+ threadStatus = _beginthread(receiveLoop, 0, (void*)&rpcargs);
+
+ /* We handle the queue entries here. Work loop: */
+ while (TRUE) {
+ loopCounter++;
+ if (worklist_isEmpty() & 1) {
+ SleepEx(1000, TRUE);
+ }
+ else if (TRUE) { // Take next WorkItem from the queue:
+ cci_stream_t buf = NULL;
+ long rpcmsg = CCMSG_INVALID;
+ time_t serverStartTime = 0xDEADDEAD;
+ RPC_STATUS status = 0;
+ char* uuid = NULL;
+ cci_stream_t stream = NULL;
+ ccs_pipe_t pipe = NULL;
+ ccs_pipe_t pipe2 = NULL;
+
+ if (worklist_remove(&rpcmsg, &pipe, &buf, &serverStartTime)) {
+ uuid = ccs_win_pipe_getUuid(pipe);
+ cci_debug_printf("%s: processing WorkItem msg:%ld pipeUUID:<%s> pipeHandle:0x%X SST:%ld",
+ __FUNCTION__, rpcmsg, uuid, ccs_win_pipe_getHandle(pipe), serverStartTime);
+
+ if (serverStartTime <= getMySST()) {
+ switch (rpcmsg) {
+ case CCMSG_CONNECT: {
+ cci_debug_printf(" Processing CONNECT");
+ rpcargs.uuid = (unsigned char*)uuid;
+
+ // Even if a disconnect message is received before this code finishes,
+ // it won't be dequeued and processed until after this code finishes.
+ // So we can add the client after starting the connection listener.
+ connectionListener((void*)&rpcargs);
+ status = rpcargs.status;
+
+ if (!status) {
+ status = ccs_server_add_client(pipe);
+ }
+ if (!status) {status = send_connection_reply(pipe);}
+ break;
+ }
+ case CCMSG_DISCONNECT: {
+ cci_debug_printf(" Processing DISCONNECT");
+ if (!status) {
+ status = ccs_server_remove_client(pipe);
+ }
+ break;
+ }
+ case CCMSG_REQUEST:
+ cci_debug_printf(" Processing REQUEST");
+ ccs_pipe_copy(&pipe2, pipe);
+ // Dispatch message here, setting both pipes to the client UUID:
+ err = ccs_server_handle_request (pipe, pipe2, buf);
+ break;
+ case CCMSG_PING:
+ cci_debug_printf(" Processing PING");
+ err = cci_stream_new (&stream);
+ err = cci_stream_write(stream, "This is a test of the emergency broadcasting system", 52);
+ err = ccs_os_server_send_reply(pipe, stream);
+ break;
+ default:
+ cci_debug_printf("Huh? Received invalid message type %ld from UUID:<%s>",
+ rpcmsg, uuid);
+ break;
+ }
+ if (buf) cci_stream_release(buf);
+ /* Don't free uuid, which was allocated here. A pointer to it is in the
+ rpcargs struct which was passed to connectionListener which will be
+ received by ccapi_listen when the client exits. ccapi_listen needs
+ the uuid to know which client to disconnect.
+ */
+ }
+ // Server's start time is different from what the client thinks.
+ // That means the server has rebooted since the client connected.
+ else {
+ cci_debug_printf("Whoops! Server has rebooted since client established connection.");
+ }
+ }
+ else {cci_debug_printf("Huh? Queue not empty but no item to remove.");}
+ }
+ }
+
+ return cci_check_error (err);
+ }
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_os_server_send_reply (ccs_pipe_t in_pipe,
+ cci_stream_t in_reply_stream) {
+
+ /* ccs_pipe_t in_reply_pipe is a char* reply endpoint.
+ cci_stream_t in_reply_stream is the data to be sent.
+ */
+
+ cc_int32 err = 0;
+ char* uuid = ccs_win_pipe_getUuid(in_pipe);
+ HANDLE h = ccs_win_pipe_getHandle(in_pipe);
+
+ if (!err) {
+ err = send_init(uuid); // Sets RPC handle to be used.
+ }
+
+ if (!err) {
+ RpcTryExcept {
+ long status;
+ ccs_rpc_request_reply( // make call with user message
+ CCMSG_REQUEST_REPLY, /* Message type */
+ (unsigned char*)&h, /* client's tspdata* */
+ (unsigned char*)uuid,
+ getMySST(),
+ cci_stream_size(in_reply_stream), /* Length of buffer */
+ (const unsigned char*)cci_stream_data(in_reply_stream), /* Data buffer */
+ &status ); /* Return code */
+ }
+ RpcExcept(1) {
+ cci_check_error(RpcExceptionCode());
+ }
+ RpcEndExcept
+ }
+
+ /* The calls to the remote procedures are complete. */
+ /* Free whatever we allocated: */
+ err = RpcBindingFree(&SERVER_REPLY_RPC_HANDLE);
+
+ return cci_check_error (err);
+ }
+
+
+/* Windows-specific routines: */
+
+void Usage(const char* argv0) {
+ printf("Usage:\n");
+ printf("%s [m maxcalls] [n mincalls] [f dontwait] [h|?]]\n", argv0);
+ printf(" CCAPI server process.\n");
+ printf(" h|? whow usage message. <\n");
+ }
+
+/* ------------------------------------------------------------------------ */
+/* The receive thread repeatedly issues RpcServerListen.
+ When a message arrives, it is handled in the RPC procedure.
+ */
+void receiveLoop(void* rpcargs) {
+
+ struct RpcRcvArgs* rcvargs = (struct RpcRcvArgs*)rpcargs;
+ RPC_STATUS status = FALSE;
+ unsigned char* pszSecurity = NULL;
+ LPSTR endpoint = NULL;
+ LPSTR event_name = NULL;
+ PSECURITY_DESCRIPTOR psd = NULL;
+ HANDLE hEvent = 0;
+ Init::InitInfo info;
+
+ cci_debug_printf("THREAD BEGIN: %s", __FUNCTION__);
+
+ status = Init::Info(info);
+
+ /* Build complete RPC endpoint using previous CCAPI implementation: */
+ if (!status) {
+ if (!rcvargs->opts->pszEndpoint) {
+ if (!status) {
+ status = alloc_name(&endpoint, "ep", isNT());
+ }
+
+ if (!status) {
+ status = alloc_name(&event_name, "startup", isNT());
+ }
+
+ if (!status) {
+ hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, event_name);
+ // We ignore any error opening the event because we do not know who started us.
+ // [Comment paraphrased from previous implementation, whence it was copied.]
+ }
+ }
+ else {
+ endpoint = rcvargs->opts->pszEndpoint;
+ }
+ }
+
+ cci_debug_printf("%s Registering endpoint %s", __FUNCTION__, endpoint);
+
+ if (!status && isNT()) {
+ status = alloc_own_security_descriptor_NT(&psd);
+ }
+
+ if (!status) {
+ status = RpcServerUseProtseqEp(rcvargs->protocolSequence,
+ rcvargs->opts->cMaxCalls,
+ (RPC_CSTR)endpoint,
+ rcvargs->opts->bDontProtect ? 0 : psd); // SD
+ }
+
+ if (!status) {
+ status = RpcServerRegisterAuthInfo(0, // server principal
+ RPC_C_AUTHN_WINNT,
+ 0,
+ 0);
+ }
+
+ while (bListen && !status) {
+ cci_debug_printf("%s is listening ...", __FUNCTION__);
+
+ if (!info.isNT) {
+ status = RpcServerRegisterIf(ccs_request_ServerIfHandle, // interface
+ NULL, // MgrTypeUuid
+ NULL); // MgrEpv; null means use default
+ }
+ else {
+ status = info.fRpcServerRegisterIfEx(ccs_request_ServerIfHandle, // interface
+ NULL, // MgrTypeUuid
+ NULL, // MgrEpv; 0 means default
+ RPC_IF_ALLOW_SECURE_ONLY,
+ rcvargs->opts->cMaxCalls,
+ rcvargs->opts->bSecCallback ?
+ (RPC_IF_CALLBACK_FN*)sec_callback : 0 );
+ }
+
+ if (!status) {
+ status = RpcServerListen(rcvargs->opts->cMinCalls,
+ rcvargs->opts->cMaxCalls,
+ rcvargs->opts->fDontWait);
+ }
+
+ if (!status) {
+ if (rcvargs->opts->fDontWait) {
+ if (hEvent) SetEvent(hEvent); // Ignore any error -- SetEvent is an optimization.
+ status = RpcMgmtWaitServerListen();
+ }
+ }
+ }
+
+ if (status) { // Cleanup in case of errors:
+ if (hEvent) CloseHandle(hEvent);
+ free_alloc_p(&event_name);
+ free_alloc_p(&psd);
+ if (endpoint && (endpoint != rcvargs->opts->pszEndpoint))
+ free_alloc_p(&endpoint);
+ }
+
+ _endthread();
+ } // End receiveLoop
+
+
+#if 0
+
+ return status;
+}
+#endif
+
+
+
+/* ------------------------------------------------------------------------ */
+/* The connection listener thread waits forever for a call to the CCAPI_CLIENT_<UUID>
+ endpoint, ccapi_listen function to complete. If the call completes or gets an
+ RPC exception, it means the client has disappeared.
+
+ A separate connectionListener is started for each client that has connected to the server.
+ */
+
+void connectionListener(void* rpcargs) {
+
+ struct RpcRcvArgs* rcvargs = (struct RpcRcvArgs*)rpcargs;
+ RPC_STATUS status = FALSE;
+ char* endpoint;
+ unsigned char* pszOptions = NULL;
+ unsigned char * pszUuid = NULL;
+
+ endpoint = clientEndpoint((char*)rcvargs->uuid);
+ rpcState = (RPC_ASYNC_STATE*)malloc(sizeof(RPC_ASYNC_STATE));
+ status = RpcAsyncInitializeHandle(rpcState, sizeof(RPC_ASYNC_STATE));
+ cci_debug_printf("");
+ cci_debug_printf("%s About to LISTEN to <%s>", __FUNCTION__, endpoint);
+
+ rpcState->UserInfo = rcvargs->uuid;
+ rpcState->NotificationType = RpcNotificationTypeApc;
+ rpcState->u.APC.NotificationRoutine = clientListener;
+ rpcState->u.APC.hThread = 0;
+
+ /* [If in use] Free previous binding: */
+ if (bRpcHandleInited) {
+ // Free previous binding (could have been used to call ccapi_listen
+ // in a different client thread).
+ // Don't check result or update status.
+ RpcStringFree(&pszStringBinding);
+ RpcBindingFree(&SERVER_REPLY_RPC_HANDLE);
+ bRpcHandleInited = FALSE;
+ }
+
+ /* Set up binding to the client's endpoint: */
+ if (!status) {
+ status = RpcStringBindingCompose(
+ pszUuid,
+ pszProtocolSequence,
+ pszNetworkAddress,
+ (RPC_CSTR)endpoint,
+ pszOptions,
+ &pszStringBinding);
+ }
+
+ /* Set the binding handle that will be used to bind to the server. */
+ if (!status) {
+ status = RpcBindingFromStringBinding(pszStringBinding, &SERVER_REPLY_RPC_HANDLE);
+ }
+ if (!status) {bRpcHandleInited = TRUE;}
+
+ RpcTryExcept {
+ cci_debug_printf(" Calling remote procedure ccapi_listen");
+ ccapi_listen(rpcState, SERVER_REPLY_RPC_HANDLE, CCMSG_LISTEN, &status);
+ /* Asynchronous call will return immediately. */
+ }
+ RpcExcept(1) {
+ status = cci_check_error(RpcExceptionCode());
+ }
+ RpcEndExcept
+
+ rcvargs->status = status;
+ } // End connectionListener
+
+
+void RPC_ENTRY clientListener(
+ _RPC_ASYNC_STATE* pAsync,
+ void* Context,
+ RPC_ASYNC_EVENT Event
+ ) {
+
+ ccs_pipe_t pipe = ccs_win_pipe_new((char*)pAsync->UserInfo, NULL);
+
+ cci_debug_printf("%s(0x%X, ...) async routine for <0x%X:%s>!",
+ __FUNCTION__, pAsync, pAsync->UserInfo, pAsync->UserInfo);
+
+ worklist_add( CCMSG_DISCONNECT,
+ pipe,
+ NULL, /* No payload with connect request */
+ (const time_t)0 ); /* No server session number with connect request */
+ }
+
+
+void printError( TCHAR* msg ) {
+ DWORD eNum;
+ TCHAR sysMsg[256];
+ TCHAR* p;
+
+ eNum = GetLastError( );
+ FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, eNum,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ sysMsg, 256, NULL );
+
+ // Trim the end of the line and terminate it with a null
+ p = sysMsg;
+ while( ( *p > 31 ) || ( *p == 9 ) )
+ ++p;
+ do { *p-- = 0; } while( ( p >= sysMsg ) &&
+ ( ( *p == '.' ) || ( *p < 33 ) ) );
+
+ // Display the message
+ cci_debug_printf("%s failed with error %d (%s)", msg, eNum, sysMsg);
+ }
+
+
+RPC_STATUS send_init(char* clientUUID) {
+ RPC_STATUS status;
+ unsigned char * pszUuid = NULL;
+ unsigned char * pszOptions = NULL;
+
+ /* Use a convenience function to concatenate the elements of */
+ /* the string binding into the proper sequence. */
+ status = RpcStringBindingCompose(pszUuid,
+ pszProtocolSequence,
+ pszNetworkAddress,
+ (unsigned char*)clientEndpoint(clientUUID),
+ pszOptions,
+ &pszStringBinding);
+ if (status) {return (status);}
+
+ /* Set the binding handle that will be used to bind to the RPC server [the 'client']. */
+ status = RpcBindingFromStringBinding(pszStringBinding, &SERVER_REPLY_RPC_HANDLE);
+ return (status);
+ }
+
+RPC_STATUS send_finish() {
+ RPC_STATUS status;
+ /* Can't shut down client -- it runs listen function which */
+ /* server uses to detect the client going away. */
+
+ /* The calls to the remote procedures are complete. */
+ /* Free the string and the binding handle */
+ status = RpcStringFree(&pszStringBinding); // remote calls done; unbind
+ if (status) {return (status);}
+
+ status = RpcBindingFree(&SERVER_REPLY_RPC_HANDLE); // remote calls done; unbind
+
+ return (status);
+ }
+
+RPC_STATUS send_connection_reply(ccs_pipe_t in_pipe) {
+ char* uuid = ccs_win_pipe_getUuid (in_pipe);
+ HANDLE h = ccs_win_pipe_getHandle(in_pipe);
+ RPC_STATUS status = send_init(uuid);
+
+ RpcTryExcept {
+ ccs_rpc_connect_reply( // make call with user message
+ CCMSG_CONNECT_REPLY, /* Message type */
+ (unsigned char*)&h, /* client's tspdata* */
+ (unsigned char*)uuid,
+ getMySST(), /* Server's session number = it's start time */
+ &status ); /* Return code */
+ }
+ RpcExcept(1) {
+ cci_check_error(RpcExceptionCode());
+ }
+ RpcEndExcept
+
+ status = send_finish();
+ return (status);
+ }
+
+#if 0
+DWORD alloc_name(LPSTR* pname, LPSTR postfix) {
+ DWORD len = strlen(sessID) + 1 + strlen(postfix) + 1;
+
+ *pname = (LPSTR)malloc(len);
+ if (!*pname) return GetLastError();
+ _snprintf(*pname, len, "%s.%s", sessID, postfix);
+ return 0;
+ }
+#endif
+
+RPC_STATUS GetPeerName( RPC_BINDING_HANDLE hClient,
+ LPTSTR pszClientName,
+ int iMaxLen) {
+ RPC_STATUS Status = RPC_S_OK;
+ RPC_BINDING_HANDLE hServer = NULL;
+ PTBYTE pszStringBinding = NULL;
+ PTBYTE pszClientNetAddr = NULL;
+ PTBYTE pszProtSequence = NULL;
+
+ memset(pszClientName, 0, iMaxLen * sizeof(TCHAR));
+
+ __try {
+ // Create a partially bound server handle from the client handle.
+ Status = RpcBindingServerFromClient (hClient, &hServer);
+ if (Status != RPC_S_OK) __leave;
+
+ // Get the partially bound server string binding and parse it.
+ Status = RpcBindingToStringBinding (hServer,
+ &pszStringBinding);
+ if (Status != RPC_S_OK) __leave;
+
+ // String binding only contains protocol sequence and client
+ // address, and is not currently implemented for named pipes.
+ Status = RpcStringBindingParse (pszStringBinding, NULL,
+ &pszProtSequence, &pszClientNetAddr,
+ NULL, NULL);
+ if (Status != RPC_S_OK)
+ __leave;
+ int iLen = lstrlen(pszClientName) + 1;
+ if (iMaxLen < iLen)
+ Status = RPC_S_BUFFER_TOO_SMALL;
+ lstrcpyn(pszClientName, (LPCTSTR)pszClientNetAddr, iMaxLen);
+ }
+ __finally {
+ if (pszProtSequence)
+ RpcStringFree (&pszProtSequence);
+
+ if (pszClientNetAddr)
+ RpcStringFree (&pszClientNetAddr);
+
+ if (pszStringBinding)
+ RpcStringFree (&pszStringBinding);
+
+ if (hServer)
+ RpcBindingFree (&hServer);
+ }
+ return Status;
+}
+
+struct client_auth_info {
+ RPC_AUTHZ_HANDLE authz_handle;
+ unsigned char* server_principal; // need to RpcFreeString this
+ ULONG authn_level;
+ ULONG authn_svc;
+ ULONG authz_svc;
+};
+
+RPC_STATUS
+GetClientId(
+ RPC_BINDING_HANDLE hClient,
+ char* client_id,
+ int max_len,
+ client_auth_info* info
+ )
+{
+ RPC_AUTHZ_HANDLE authz_handle = 0;
+ unsigned char* server_principal = 0;
+ ULONG authn_level = 0;
+ ULONG authn_svc = 0;
+ ULONG authz_svc = 0;
+ RPC_STATUS status = 0;
+
+ memset(client_id, 0, max_len);
+
+ if (info) {
+ memset(info, 0, sizeof(client_auth_info));
+ }
+
+ status = RpcBindingInqAuthClient(hClient, &authz_handle,
+ info ? &server_principal : 0,
+ &authn_level, &authn_svc, &authz_svc);
+ if (status == RPC_S_OK)
+ {
+ if (info) {
+ info->server_principal = server_principal;
+ info->authz_handle = authz_handle;
+ info->authn_level = authn_level;
+ info->authn_svc = authn_svc;
+ info->authz_svc = authz_svc;
+ }
+
+ if (authn_svc == RPC_C_AUTHN_WINNT) {
+ WCHAR* username = (WCHAR*)authz_handle;
+ int len = lstrlenW(username) + 1;
+ if (max_len < len)
+ status = RPC_S_BUFFER_TOO_SMALL;
+ _snprintf(client_id, max_len, "%S", username);
+ } else {
+ status = RPC_S_UNKNOWN_AUTHN_SERVICE;
+ }
+ }
+ return status;
+}
+
+char*
+rpc_error_to_string(
+ RPC_STATUS status
+ )
+{
+ switch(status) {
+ case RPC_S_OK:
+ return "OK";
+ case RPC_S_INVALID_BINDING:
+ return "Invalid binding";
+ case RPC_S_WRONG_KIND_OF_BINDING:
+ return "Wrong binding";
+ case RPC_S_BINDING_HAS_NO_AUTH:
+ RpcRaiseException(RPC_S_BINDING_HAS_NO_AUTH);
+ return "Binding has no auth";
+ default:
+ return "BUG: I am confused";
+ }
+}
+
+void
+print_client_info(
+ RPC_STATUS peer_status,
+ const char* peer_name,
+ RPC_STATUS client_status,
+ const char* client_id,
+ client_auth_info* info
+ )
+{
+ if (peer_status == RPC_S_OK || peer_status == RPC_S_BUFFER_TOO_SMALL) {
+ cci_debug_printf("%s Peer Name is \"%s\"", __FUNCTION__, peer_name);
+ } else {
+ cci_debug_printf("%s Error %u getting Peer Name (%s)",
+ __FUNCTION__, peer_status, rpc_error_to_string(peer_status));
+ }
+
+ if (client_status == RPC_S_OK || client_status == RPC_S_BUFFER_TOO_SMALL) {
+ if (info) {
+ cci_debug_printf("%s Client Auth Info"
+ "\tServer Principal: %s\n"
+ "\tAuthentication Level: %d\n"
+ "\tAuthentication Service: %d\n"
+ "\tAuthorization Service: %d\n",
+ __FUNCTION__,
+ info->server_principal,
+ info->authn_level,
+ info->authn_svc,
+ info->authz_svc);
+ }
+ cci_debug_printf("%s Client ID is \"%s\"", __FUNCTION__, client_id);
+ } else {
+ cci_debug_printf("%s Error getting Client Info (%u = %s)",
+ __FUNCTION__, client_status, rpc_error_to_string(client_status));
+ }
+}
+
+DWORD sid_check() {
+ DWORD status = 0;
+ HANDLE hToken_c = 0;
+ HANDLE hToken_s = 0;
+ PTOKEN_USER ptu_c = 0;
+ PTOKEN_USER ptu_s = 0;
+ DWORD len = 0;
+ BOOL bImpersonate = FALSE;
+
+ // Note GetUserName will fail while impersonating at identify
+ // level. The workaround is to impersonate, OpenThreadToken,
+ // revert, call GetTokenInformation, and finally, call
+ // LookupAccountSid.
+
+ // XXX - Note: This workaround does not appear to work.
+ // OpenThreadToken fails with error 1346: "Either a requid
+ // impersonation level was not provided or the provided
+ // impersonation level is invalid".
+
+ status = RpcImpersonateClient(0);
+
+ if (!status) {
+ bImpersonate = TRUE;
+ if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken_c))
+ status = GetLastError();
+ }
+
+ if (!status) {
+ status = RpcRevertToSelf();
+ }
+
+ if (!status) {
+ bImpersonate = FALSE;
+
+ len = 0;
+ GetTokenInformation(hToken_c, TokenUser, ptu_c, 0, &len);
+ if (len == 0) status = 1;
+ }
+
+ if (!status) {
+ if (!(ptu_c = (PTOKEN_USER)LocalAlloc(0, len)))
+ status = GetLastError();
+ }
+
+ if (!status) {
+ if (!GetTokenInformation(hToken_c, TokenUser, ptu_c, len, &len))
+ status = GetLastError();
+ }
+
+ if (!status) {
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken_s))
+ status = GetLastError();
+ }
+
+ if (!status) {
+ len = 0;
+ GetTokenInformation(hToken_s, TokenUser, ptu_s, 0, &len);
+ if (len == 0) status = GetLastError();
+ }
+
+ if (!status) {
+ if (!(ptu_s = (PTOKEN_USER)LocalAlloc(0, len)))
+ status = GetLastError();
+ }
+
+ if (!status) {
+ if (!GetTokenInformation(hToken_s, TokenUser, ptu_s, len, &len))
+ status = GetLastError();
+ }
+
+ if (!EqualSid(ptu_s->User.Sid, ptu_c->User.Sid))
+ status = RPC_S_ACCESS_DENIED;
+
+/* Cleanup: */
+ if (!hToken_c && !bImpersonate)
+ cci_debug_printf("%s Cannot impersonate (%u)", __FUNCTION__, status);
+ else if (!hToken_c)
+ cci_debug_printf("%s Failed to open client token (%u)", __FUNCTION__, status);
+ else if (bImpersonate)
+ cci_debug_printf("%s Failed to revert (%u)", __FUNCTION__, status);
+ else if (!ptu_c)
+ cci_debug_printf("%s Failed to get client token user info (%u)",
+ __FUNCTION__, status);
+ else if (!hToken_s)
+ cci_debug_printf("%s Failed to open server token (%u)", __FUNCTION__, status);
+ else if (!ptu_s)
+ cci_debug_printf("%s Failed to get server token user info (%u)",
+ __FUNCTION__, status);
+ else if (status == RPC_S_ACCESS_DENIED)
+ cci_debug_printf("%s SID **does not** match!", __FUNCTION__);
+ else if (status == RPC_S_OK)
+ cci_debug_printf("%s SID matches!", __FUNCTION__);
+ else
+ if (status) {
+ cci_debug_printf("%s unrecognized error %u", __FUNCTION__, status);
+ abort();
+ }
+
+ if (bImpersonate) RpcRevertToSelf();
+ if (hToken_c && hToken_c != INVALID_HANDLE_VALUE)
+ CloseHandle(hToken_c);
+ if (ptu_c) LocalFree(ptu_c);
+ if (hToken_s && hToken_s != INVALID_HANDLE_VALUE)
+ CloseHandle(hToken_s);
+ if (ptu_s) LocalFree(ptu_s);
+ if (status) cci_debug_printf("%s returning %u", __FUNCTION__, status);
+ return status;
+ }
+
+RPC_STATUS RPC_ENTRY sec_callback( IN RPC_IF_ID *Interface,
+ IN void *Context) {
+ char peer_name[1024];
+ char client_name[1024];
+ RPC_STATUS peer_status;
+ RPC_STATUS client_status;
+
+ cci_debug_printf("%s", __FUNCTION__);
+ peer_status = GetPeerName(Context, peer_name, sizeof(peer_name));
+ client_status = GetClientId(Context, client_name, sizeof(client_name), 0);
+ print_client_info(peer_status, peer_name, client_status, client_name, 0);
+ DWORD sid_status = sid_check();
+ cci_debug_printf("%s returning (%u)", __FUNCTION__, sid_status);
+ return sid_status;
+ }
+
+
+
+/*********************************************************************/
+/* MIDL allocate and free */
+/*********************************************************************/
+
+void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len) {
+ return(malloc(len));
+ }
+
+void __RPC_USER midl_user_free(void __RPC_FAR * ptr) {
+ free(ptr);
+ }
diff --git a/src/ccapi/server/win/ccs_request_proc.c b/src/ccapi/server/win/ccs_request_proc.c
new file mode 100644
index 000000000..40713fb50
--- /dev/null
+++ b/src/ccapi/server/win/ccs_request_proc.c
@@ -0,0 +1,116 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "ccs_request.h" // header file generated by MIDL compiler
+#include "cci_debugging.h"
+#include "WorkQueue.h"
+#include "win-utils.h"
+#include "ccs_win_pipe.h"
+
+void ccs_rpc_request(
+ const long rpcmsg, /* Message type */
+ const char tspHandle[], /* Client's tspdata* */
+ const char* pszUUID, /* Where client will listen for the reply */
+ const long lenRequest, /* Length of buffer */
+ const char pbRequest[], /* Data buffer */
+ const long serverStartTime, /* Which server session we're talking to */
+ long* return_status ) { /* Return code */
+
+ cc_int32 status = 0;
+ cci_stream_t stream;
+ DWORD* p = (DWORD*)(tspHandle);
+ WIN_PIPE* pipe = NULL;
+
+ cci_debug_printf("%s rpcmsg:%d; UUID:<%s> SST:<%s>",
+ __FUNCTION__, rpcmsg, pszUUID, serverStartTime);
+
+ status = (rpcmsg != CCMSG_REQUEST) && (rpcmsg != CCMSG_PING);
+
+ if (!status) {
+ status = cci_stream_new (&stream); /* Create a stream for the request data */
+ }
+
+ if (!status) { /* Put the data into the stream */
+ status = cci_stream_write (stream, pbRequest, lenRequest);
+ }
+
+ pipe = ccs_win_pipe_new(pszUUID, *p);
+ worklist_add(rpcmsg, pipe, stream, serverStartTime);
+ *return_status = status;
+ }
+
+
+void ccs_rpc_connect(
+ const long rpcmsg, /* Message type */
+ const char tspHandle[], /* Client's tspdata* */
+ const char* pszUUID, /* Data buffer */
+ long* return_status ) { /* Return code */
+
+ DWORD* p = (DWORD*)(tspHandle);
+ WIN_PIPE* pipe = ccs_win_pipe_new(pszUUID, *p);
+
+ cci_debug_printf("%s; rpcmsg:%d; UUID: <%s>", __FUNCTION__, rpcmsg, pszUUID);
+
+ worklist_add( rpcmsg,
+ pipe,
+ NULL, /* No payload with connect request */
+ (const time_t)0 ); /* No server session number with connect request */
+ }
+
+
+// 'Authentication' is client setting a value in a file and the server
+// returning that value plus one.
+CC_UINT32 ccs_authenticate(const CC_CHAR* name) {
+ HANDLE hMap = 0;
+ PDWORD pvalue = 0;
+ CC_UINT32 result = 0;
+ DWORD status = 0;
+
+ cci_debug_printf("%s ( %s )", __FUNCTION__, name);
+
+ hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, (LPSTR)name);
+ status = !hMap;
+
+ if (!status) {
+ pvalue = (PDWORD)MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0);
+ status = !pvalue;
+ }
+
+ if (!status) {
+ *pvalue += 1;
+ result = *pvalue;
+ }
+
+ if (pvalue) {
+ UnmapViewOfFile(pvalue);
+ }
+
+ if (hMap) CloseHandle(hMap);
+ return result;
+ } \ No newline at end of file
diff --git a/src/ccapi/server/win/ccs_win_pipe.c b/src/ccapi/server/win/ccs_win_pipe.c
new file mode 100644
index 000000000..4d121aaea
--- /dev/null
+++ b/src/ccapi/server/win/ccs_win_pipe.c
@@ -0,0 +1,163 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "assert.h"
+
+#include "ccs_win_pipe.h"
+#include "cci_debugging.h"
+
+/* Ref:
+struct ccs_win_pipe_t {
+ char* uuid;
+ HANDLE clientHandle;
+ }
+ */
+
+/* ------------------------------------------------------------------------ */
+
+struct ccs_win_pipe_t* ccs_win_pipe_new (const char* uuid, const HANDLE h) {
+
+ cc_int32 err = ccNoError;
+ struct ccs_win_pipe_t* out_pipe = NULL;
+ char* uuidCopy = NULL;
+
+ if (!err) {
+ if (!uuid) {err = cci_check_error(ccErrBadParam);}
+ }
+
+ if (!err) {
+ uuidCopy = (char*)malloc(1+strlen(uuid));
+ if (!uuidCopy) {err = cci_check_error(ccErrBadParam);}
+ strcpy(uuidCopy, uuid);
+ }
+
+ if (!err) {
+ out_pipe = (struct ccs_win_pipe_t*)malloc(sizeof(struct ccs_win_pipe_t));
+ if (!out_pipe) {err = cci_check_error(ccErrBadParam);}
+ out_pipe->uuid = uuidCopy;
+ out_pipe->clientHandle = h;
+ }
+
+ cci_debug_printf("0x%X = %s(%s, 0x%X)", out_pipe, __FUNCTION__, uuid, h);
+
+ return out_pipe;
+ }
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_win_pipe_copy (WIN_PIPE** out_pipe,
+ const WIN_PIPE* in_pipe) {
+
+ *out_pipe =
+ ccs_win_pipe_new(
+ ccs_win_pipe_getUuid (in_pipe),
+ ccs_win_pipe_getHandle(in_pipe) );
+
+ return (*out_pipe) ? ccNoError : ccErrBadParam;
+ }
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_win_pipe_release(const WIN_PIPE* in_pipe) {
+
+ cc_int32 err = ccNoError;
+
+ if (!ccs_win_pipe_valid(in_pipe)) {err = cci_check_error(ccErrBadParam);}
+
+ if (!err) {
+ if (!in_pipe->uuid) free(in_pipe->uuid);
+ if (!in_pipe) free(in_pipe);
+ }
+
+ return err;
+ }
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_win_pipe_valid (const WIN_PIPE* in_pipe) {
+
+ if (!in_pipe) {
+ cci_check_error(ccErrBadParam);
+ return FALSE;
+ }
+
+ if (!in_pipe->uuid) {
+ cci_check_error(ccErrBadParam);
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_win_pipe_compare (const WIN_PIPE* in_pipe_1,
+ const WIN_PIPE* in_pipe_2,
+ cc_uint32 *out_equal) {
+
+ cc_int32 err = ccNoError;
+ int seq = 0;
+ *out_equal = FALSE;
+
+ if (!ccs_win_pipe_valid(in_pipe_1)) {err = cci_check_error(ccErrBadParam);}
+ if (!ccs_win_pipe_valid(in_pipe_2)) {err = cci_check_error(ccErrBadParam);}
+ if (!out_equal) {err = cci_check_error(ccErrBadParam);}
+
+ /* A disconnect doesn't have a tls* with it -- only the uuid. SO only
+ compare the uuids.
+ */
+ if (!err) {
+ seq = strcmp( ccs_win_pipe_getUuid(in_pipe_1),
+ ccs_win_pipe_getUuid(in_pipe_2) );
+ *out_equal = (seq == 0);
+ }
+
+ return err;
+ }
+
+/* ------------------------------------------------------------------------ */
+
+char* ccs_win_pipe_getUuid (const WIN_PIPE* in_pipe) {
+
+ char* result = NULL;
+
+ if (!ccs_win_pipe_valid(in_pipe)) {cci_check_error(ccErrBadParam);}
+ else {result = in_pipe->uuid;}
+
+ return result;
+ }
+
+/* ------------------------------------------------------------------------ */
+
+HANDLE ccs_win_pipe_getHandle (const WIN_PIPE* in_pipe) {
+
+ HANDLE result = NULL;
+
+ if (!ccs_win_pipe_valid(in_pipe)) {cci_check_error(ccErrBadParam);}
+ else {result = in_pipe->clientHandle;}
+
+ return result;
+ }
diff --git a/src/ccapi/server/win/ccs_win_pipe.h b/src/ccapi/server/win/ccs_win_pipe.h
new file mode 100644
index 000000000..afabe12fe
--- /dev/null
+++ b/src/ccapi/server/win/ccs_win_pipe.h
@@ -0,0 +1,69 @@
+/*
+ * $Header$
+ *
+ * Copyright 2008 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef _ccs_win_pipe_h_
+#define _ccs_win_pipe_h_
+
+#include "windows.h"
+
+#include "CredentialsCache.h"
+
+/* ------------------------------------------------------------------------ */
+
+/* On Windows, a pipe is a struct containing a UUID and a handle. Both the
+ UUID and handle are supplied by the client.
+
+ The UUID is used to build the client's reply endpoint.
+
+ The handle is to the requesting client thread's thread local storage struct,
+ so that the client's one and only reply handler can put reply data where
+ the requesting thread will be able to see it.
+ */
+
+struct ccs_win_pipe_t {
+ char* uuid;
+ HANDLE clientHandle;
+ };
+
+typedef struct ccs_win_pipe_t WIN_PIPE;
+
+struct ccs_win_pipe_t* ccs_win_pipe_new(const char* uuid, const HANDLE h);
+
+cc_int32 ccs_win_pipe_release (const WIN_PIPE* io_pipe);
+
+cc_int32 ccs_win_pipe_compare (const WIN_PIPE* win_pipe_1,
+ const WIN_PIPE* win_pipe_2,
+ cc_uint32 *out_equal);
+
+cc_int32 ccs_win_pipe_copy (WIN_PIPE** out_pipe,
+ const WIN_PIPE* in_pipe);
+
+cc_int32 ccs_win_pipe_valid (const WIN_PIPE* in_pipe);
+
+char* ccs_win_pipe_getUuid (const WIN_PIPE* in_pipe);
+HANDLE ccs_win_pipe_getHandle (const WIN_PIPE* in_pipe);
+
+#endif // _ccs_win_pipe_h_ \ No newline at end of file
diff --git a/src/ccapi/server/win/workitem.h b/src/ccapi/server/win/workitem.h
new file mode 100644
index 000000000..a9d1c0e29
--- /dev/null
+++ b/src/ccapi/server/win/workitem.h
@@ -0,0 +1,48 @@
+#ifndef __WorkItem
+#define __WorkItem
+
+#include <list>
+#include "windows.h"
+
+extern "C" {
+ #include "cci_stream.h"
+ #include "ccs_pipe.h"
+ }
+
+class WorkItem {
+private:
+ cci_stream_t _buf;
+ WIN_PIPE* _pipe;
+ const long _rpcmsg;
+ const long _sst;
+public:
+ WorkItem( cci_stream_t buf,
+ WIN_PIPE* pipe,
+ const long type,
+ const long serverStartTime);
+ WorkItem( const WorkItem&);
+ WorkItem();
+ ~WorkItem();
+
+ const cci_stream_t payload() const {return _buf;}
+ const cci_stream_t take_payload();
+ WIN_PIPE* take_pipe();
+ WIN_PIPE* pipe() const {return _pipe;}
+ const long type() const {return _rpcmsg;}
+ const long sst() const {return _sst;}
+ char* print(char* buf);
+ };
+
+class WorkList {
+private:
+ std::list <WorkItem*> wl;
+ CRITICAL_SECTION cs;
+public:
+ WorkList();
+ ~WorkList();
+ int add(WorkItem*);
+ int remove(WorkItem**);
+ bool isEmpty() {return wl.empty();}
+ };
+
+#endif // __WorkItem \ No newline at end of file