-/*\r
-\r
- Copyright (C) 1998 Danilo Almeida. All rights reserved.\r
-\r
- automatic stack-based locking object\r
-\r
- This file is part of FIFS (Framework for Implementing File Systems). \r
-\r
- This software is distributed with NO WARRANTY OF ANY KIND. No\r
- author or distributor accepts any responsibility for the\r
- consequences of using it, or for whether it serves any particular\r
- purpose or works at all, unless he or she says so in writing.\r
- Refer to the included modified Alladin Free Public License (the\r
- "License") for full details.\r
-\r
- Every copy of this software must include a copy of the License, in\r
- a plain ASCII text file named COPYING. The License grants you the\r
- right to copy, modify and redistribute this software, but only\r
- under certain conditions described in the License. Among other\r
- things, the License requires that the copyright notice and this\r
- notice be preserved on all copies.\r
-\r
-*/\r
-\r
-#ifndef __AUTOLOCK_HXX__\r
-#define __AUTOLOCK_HXX__\r
-\r
-#include <windows.h>\r
-\r
-class CcOsLock {\r
- CRITICAL_SECTION cs;\r
- bool valid;\r
-public:\r
- CcOsLock() {InitializeCriticalSection(&cs); valid = true; }\r
- ~CcOsLock() {DeleteCriticalSection(&cs); valid = false;}\r
- void lock() {if (valid) EnterCriticalSection(&cs);}\r
- void unlock() {if (valid) LeaveCriticalSection(&cs);}\r
-#if 0\r
- bool trylock() {return valid ? (TryEnterCriticalSection(&cs) ? true : false)\r
- : false; }\r
-#endif\r
-};\r
-\r
-class CcAutoLock {\r
- CcOsLock& m_lock;\r
-public:\r
- static void Start(CcAutoLock*& a, CcOsLock& lock) { a = new CcAutoLock(lock); };\r
- static void Stop (CcAutoLock*& a) { delete a; a = 0; };\r
- CcAutoLock(CcOsLock& lock):m_lock(lock) { m_lock.lock(); }\r
- ~CcAutoLock() { m_lock.unlock(); }\r
-};\r
-\r
-#endif /* __AUTOLOCK_HXX */\r
+/*
+
+ Copyright (C) 1998 Danilo Almeida. All rights reserved.
+
+ automatic stack-based locking object
+
+ This file is part of FIFS (Framework for Implementing File Systems).
+
+ This software is distributed with NO WARRANTY OF ANY KIND. No
+ author or distributor accepts any responsibility for the
+ consequences of using it, or for whether it serves any particular
+ purpose or works at all, unless he or she says so in writing.
+ Refer to the included modified Alladin Free Public License (the
+ "License") for full details.
+
+ Every copy of this software must include a copy of the License, in
+ a plain ASCII text file named COPYING. The License grants you the
+ right to copy, modify and redistribute this software, but only
+ under certain conditions described in the License. Among other
+ things, the License requires that the copyright notice and this
+ notice be preserved on all copies.
+
+*/
+
+#ifndef __AUTOLOCK_HXX__
+#define __AUTOLOCK_HXX__
+
+#include <windows.h>
+
+class CcOsLock {
+ CRITICAL_SECTION cs;
+ bool valid;
+public:
+ CcOsLock() {InitializeCriticalSection(&cs); valid = true; }
+ ~CcOsLock() {DeleteCriticalSection(&cs); valid = false;}
+ void lock() {if (valid) EnterCriticalSection(&cs);}
+ void unlock() {if (valid) LeaveCriticalSection(&cs);}
+#if 0
+ bool trylock() {return valid ? (TryEnterCriticalSection(&cs) ? true : false)
+ : false; }
+#endif
+};
+
+class CcAutoLock {
+ CcOsLock& m_lock;
+public:
+ static void Start(CcAutoLock*& a, CcOsLock& lock) { a = new CcAutoLock(lock); };
+ static void Stop (CcAutoLock*& a) { delete a; a = 0; };
+ CcAutoLock(CcOsLock& lock):m_lock(lock) { m_lock.lock(); }
+ ~CcAutoLock() { m_lock.unlock(); }
+};
+
+#endif /* __AUTOLOCK_HXX */
-/*\r
- * $Header$\r
- *\r
- * Copyright 2008 Massachusetts Institute of Technology.\r
- * All Rights Reserved.\r
- *\r
- * Export of this software from the United States of America may\r
- * require a specific license from the United States Government.\r
- * It is the responsibility of any person or organization contemplating\r
- * export to obtain such a license before exporting.\r
- *\r
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and\r
- * distribute this software and its documentation for any purpose and\r
- * without fee is hereby granted, provided that the above copyright\r
- * notice appear in all copies and that both that copyright notice and\r
- * this permission notice appear in supporting documentation, and that\r
- * the name of M.I.T. not be used in advertising or publicity pertaining\r
- * to distribution of the software without specific, written prior\r
- * permission. Furthermore if you modify this software you must label\r
- * your software as modified software and not distribute it in such a\r
- * fashion that it might be confused with the original M.I.T. software.\r
- * M.I.T. makes no representations about the suitability of\r
- * this software for any purpose. It is provided "as is" without express\r
- * or implied warranty.\r
- */\r
-\r
-#include <windows.h>\r
-#include "init.hxx"\r
-#include "secure.hxx"\r
-\r
-extern "C" {\r
-#include "cci_debugging.h"\r
- }\r
-\r
-\r
-CcOsLock Init::s_lock;\r
-DWORD Init::s_refcount = 0;\r
-DWORD Init::s_error = ERROR_INVALID_HANDLE;\r
-bool Init::s_init = false;\r
-Init::InitInfo Init::s_info = { 0 };\r
-HINSTANCE Init::s_hRpcDll = 0;\r
-\r
-#define INIT "INIT: "\r
-\r
-static\r
-void\r
-ShowInfo(\r
- Init::InitInfo& info\r
- );\r
-\r
-DWORD\r
-Init::Info(\r
- InitInfo& info\r
- )\r
-{\r
- // This funciton will not do automatic initialization.\r
- CcAutoLock AL(s_lock);\r
- if (!s_init) {\r
- memset(&info, 0, sizeof(info));\r
- return s_error ? s_error : ERROR_INVALID_HANDLE;\r
- } else {\r
- info = s_info;\r
- return 0;\r
- }\r
-}\r
-\r
-DWORD\r
-Init::Initialize() {\r
- CcAutoLock AL(s_lock);\r
- cci_debug_printf("%s s_init:%d", __FUNCTION__, s_init);\r
- if (s_init) {\r
- s_refcount++;\r
- return 0;\r
- }\r
- SecureClient s;\r
- DWORD status = 0;\r
- OSVERSIONINFO osvi;\r
- BOOL isSupportedVersion = FALSE;\r
- memset(&s_info, 0, sizeof(s_info));\r
- memset(&osvi, 0, sizeof(osvi));\r
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);\r
-\r
- status = !GetVersionEx(&osvi); // Returns a boolean. Invert to 0 is OK.\r
-\r
- if (!status) {\r
- switch(osvi.dwPlatformId) {\r
- case VER_PLATFORM_WIN32_WINDOWS:\r
- s_info.isNT = FALSE;\r
- isSupportedVersion = TRUE;\r
- break;\r
- case VER_PLATFORM_WIN32_NT:\r
- s_info.isNT = TRUE;\r
- isSupportedVersion = TRUE;\r
- break;\r
- case VER_PLATFORM_WIN32s:\r
- default:\r
- s_info.isNT = FALSE;\r
- break;\r
- }\r
- \r
- if (!isSupportedVersion) {\r
- cci_debug_printf("%s Trying to run on an unsupported version of Windows", __FUNCTION__);\r
- status = 1;\r
- }\r
- }\r
-\r
- if (!status) {status = !s_info.isNT;}\r
-\r
- if (!status) {status = !(s_hRpcDll = LoadLibrary(TEXT("rpcrt4.dll")));}\r
-\r
- if (!status) {\r
- s_info.fRpcBindingSetAuthInfoEx = (FP_RpcBindingSetAuthInfoEx)\r
- GetProcAddress(s_hRpcDll, TEXT(FN_RpcBindingSetAuthInfoEx));\r
- if (!s_info.fRpcBindingSetAuthInfoEx) {\r
- cci_debug_printf(" Running on NT but could not find RpcBindinSetAuthInfoEx");\r
- status = 1;\r
- }\r
- }\r
- \r
- if (!status) {\r
- s_info.fRpcServerRegisterIfEx = (FP_RpcServerRegisterIfEx)\r
- GetProcAddress(s_hRpcDll, TEXT(FN_RpcServerRegisterIfEx));\r
- if (!s_info.fRpcServerRegisterIfEx) {\r
- cci_debug_printf(" Running on NT but could not find RpcServerRegisterIfEx");\r
- status = 1;\r
- }\r
- }\r
-\r
- if (!status) {\r
- status = SecureClient::Attach();\r
- if (status) {\r
- cci_debug_printf(" SecureClient::Attach() failed (%u)", status);\r
- }\r
- }\r
-\r
- if (status) {\r
- memset(&s_info, 0, sizeof(s_info));\r
- if (s_hRpcDll) {\r
- FreeLibrary(s_hRpcDll);\r
- s_hRpcDll = 0;\r
- }\r
- cci_debug_printf(" Init::Attach() failed (%u)", status);\r
- } else {\r
- s_refcount++;\r
- s_init = true;\r
- ShowInfo(s_info);\r
- }\r
- s_error = status;\r
- return status;\r
-}\r
-\r
-DWORD\r
-Init::Cleanup(\r
- )\r
-{\r
- CcAutoLock AL(s_lock);\r
- s_refcount--;\r
- if (s_refcount) return 0;\r
- if (!s_init) return 0;\r
- DWORD error = 0;\r
- if (s_hRpcDll) {\r
- FreeLibrary(s_hRpcDll);\r
- s_hRpcDll = 0;\r
- }\r
- error = SecureClient::Detach();\r
- memset(&s_info, 0, sizeof(s_info));\r
- s_init = false;\r
- s_error = 0;\r
- if (error) {\r
- cci_debug_printf(" Init::Detach() had an error (%u)", error);\r
- }\r
- return error;\r
-}\r
-\r
-static\r
-void\r
-ShowInfo(\r
- Init::InitInfo& info\r
- )\r
-{\r
- if (info.isNT) {\r
- cci_debug_printf(" Running on Windows NT using secure mode");\r
- } else {\r
- cci_debug_printf(" Running insecurely on non-NT Windows");\r
- }\r
- return;\r
-}\r
+/*
+ * $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 <windows.h>
+#include "init.hxx"
+#include "secure.hxx"
+
+extern "C" {
+#include "cci_debugging.h"
+ }
+
+
+CcOsLock Init::s_lock;
+DWORD Init::s_refcount = 0;
+DWORD Init::s_error = ERROR_INVALID_HANDLE;
+bool Init::s_init = false;
+Init::InitInfo Init::s_info = { 0 };
+HINSTANCE Init::s_hRpcDll = 0;
+
+#define INIT "INIT: "
+
+static
+void
+ShowInfo(
+ Init::InitInfo& info
+ );
+
+DWORD
+Init::Info(
+ InitInfo& info
+ )
+{
+ // This funciton will not do automatic initialization.
+ CcAutoLock AL(s_lock);
+ if (!s_init) {
+ memset(&info, 0, sizeof(info));
+ return s_error ? s_error : ERROR_INVALID_HANDLE;
+ } else {
+ info = s_info;
+ return 0;
+ }
+}
+
+DWORD
+Init::Initialize() {
+ CcAutoLock AL(s_lock);
+ cci_debug_printf("%s s_init:%d", __FUNCTION__, s_init);
+ if (s_init) {
+ s_refcount++;
+ return 0;
+ }
+ SecureClient s;
+ DWORD status = 0;
+ OSVERSIONINFO osvi;
+ BOOL isSupportedVersion = FALSE;
+ memset(&s_info, 0, sizeof(s_info));
+ memset(&osvi, 0, sizeof(osvi));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+ status = !GetVersionEx(&osvi); // Returns a boolean. Invert to 0 is OK.
+
+ if (!status) {
+ switch(osvi.dwPlatformId) {
+ case VER_PLATFORM_WIN32_WINDOWS:
+ s_info.isNT = FALSE;
+ isSupportedVersion = TRUE;
+ break;
+ case VER_PLATFORM_WIN32_NT:
+ s_info.isNT = TRUE;
+ isSupportedVersion = TRUE;
+ break;
+ case VER_PLATFORM_WIN32s:
+ default:
+ s_info.isNT = FALSE;
+ break;
+ }
+
+ if (!isSupportedVersion) {
+ cci_debug_printf("%s Trying to run on an unsupported version of Windows", __FUNCTION__);
+ status = 1;
+ }
+ }
+
+ if (!status) {status = !s_info.isNT;}
+
+ if (!status) {status = !(s_hRpcDll = LoadLibrary(TEXT("rpcrt4.dll")));}
+
+ if (!status) {
+ s_info.fRpcBindingSetAuthInfoEx = (FP_RpcBindingSetAuthInfoEx)
+ GetProcAddress(s_hRpcDll, TEXT(FN_RpcBindingSetAuthInfoEx));
+ if (!s_info.fRpcBindingSetAuthInfoEx) {
+ cci_debug_printf(" Running on NT but could not find RpcBindinSetAuthInfoEx");
+ status = 1;
+ }
+ }
+
+ if (!status) {
+ s_info.fRpcServerRegisterIfEx = (FP_RpcServerRegisterIfEx)
+ GetProcAddress(s_hRpcDll, TEXT(FN_RpcServerRegisterIfEx));
+ if (!s_info.fRpcServerRegisterIfEx) {
+ cci_debug_printf(" Running on NT but could not find RpcServerRegisterIfEx");
+ status = 1;
+ }
+ }
+
+ if (!status) {
+ status = SecureClient::Attach();
+ if (status) {
+ cci_debug_printf(" SecureClient::Attach() failed (%u)", status);
+ }
+ }
+
+ if (status) {
+ memset(&s_info, 0, sizeof(s_info));
+ if (s_hRpcDll) {
+ FreeLibrary(s_hRpcDll);
+ s_hRpcDll = 0;
+ }
+ cci_debug_printf(" Init::Attach() failed (%u)", status);
+ } else {
+ s_refcount++;
+ s_init = true;
+ ShowInfo(s_info);
+ }
+ s_error = status;
+ return status;
+}
+
+DWORD
+Init::Cleanup(
+ )
+{
+ CcAutoLock AL(s_lock);
+ s_refcount--;
+ if (s_refcount) return 0;
+ if (!s_init) return 0;
+ DWORD error = 0;
+ if (s_hRpcDll) {
+ FreeLibrary(s_hRpcDll);
+ s_hRpcDll = 0;
+ }
+ error = SecureClient::Detach();
+ memset(&s_info, 0, sizeof(s_info));
+ s_init = false;
+ s_error = 0;
+ if (error) {
+ cci_debug_printf(" Init::Detach() had an error (%u)", error);
+ }
+ return error;
+}
+
+static
+void
+ShowInfo(
+ Init::InitInfo& info
+ )
+{
+ if (info.isNT) {
+ cci_debug_printf(" Running on Windows NT using secure mode");
+ } else {
+ cci_debug_printf(" Running insecurely on non-NT Windows");
+ }
+ return;
+}
-;LIBRARY COMERR32\r
-HEAPSIZE 8192\r
-\r
-EXPORTS\r
+;LIBRARY COMERR32
+HEAPSIZE 8192
+
+EXPORTS
\ No newline at end of file
-/*\r
- * $Header$\r
- *\r
- * Copyright 2008 Massachusetts Institute of Technology.\r
- * All Rights Reserved.\r
- *\r
- * Export of this software from the United States of America may\r
- * require a specific license from the United States Government.\r
- * It is the responsibility of any person or organization contemplating\r
- * export to obtain such a license before exporting.\r
- *\r
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and\r
- * distribute this software and its documentation for any purpose and\r
- * without fee is hereby granted, provided that the above copyright\r
- * notice appear in all copies and that both that copyright notice and\r
- * this permission notice appear in supporting documentation, and that\r
- * the name of M.I.T. not be used in advertising or publicity pertaining\r
- * to distribution of the software without specific, written prior\r
- * permission. Furthermore if you modify this software you must label\r
- * your software as modified software and not distribute it in such a\r
- * fashion that it might be confused with the original M.I.T. software.\r
- * M.I.T. makes no representations about the suitability of\r
- * this software for any purpose. It is provided "as is" without express\r
- * or implied warranty.\r
- */\r
-\r
-#include <windows.h>\r
-#include "init.hxx"\r
-#include "secure.hxx"\r
-\r
-extern "C" {\r
-#include "cci_debugging.h"\r
- }\r
-\r
-\r
-CcOsLock Init::s_lock;\r
-DWORD Init::s_refcount = 0;\r
-DWORD Init::s_error = ERROR_INVALID_HANDLE;\r
-bool Init::s_init = false;\r
-Init::InitInfo Init::s_info = { 0 };\r
-HINSTANCE Init::s_hRpcDll = 0;\r
-\r
-#define INIT "INIT: "\r
-\r
-static\r
-void\r
-ShowInfo(\r
- Init::InitInfo& info\r
- );\r
-\r
-DWORD\r
-Init::Info(\r
- InitInfo& info\r
- )\r
-{\r
- // This funciton will not do automatic initialization.\r
- CcAutoLock AL(s_lock);\r
- if (!s_init) {\r
- memset(&info, 0, sizeof(info));\r
- return s_error ? s_error : ERROR_INVALID_HANDLE;\r
- } else {\r
- info = s_info;\r
- return 0;\r
- }\r
-}\r
-\r
-DWORD\r
-Init::Initialize() {\r
- CcAutoLock AL(s_lock);\r
-// cci_debug_printf("%s s_init:%d", __FUNCTION__, s_init);\r
- if (s_init) {\r
- s_refcount++;\r
- return 0;\r
- }\r
- SecureClient s;\r
- DWORD status = 0;\r
- OSVERSIONINFO osvi;\r
- BOOL isSupportedVersion = FALSE;\r
- memset(&s_info, 0, sizeof(s_info));\r
- memset(&osvi, 0, sizeof(osvi));\r
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);\r
-\r
- status = !GetVersionEx(&osvi); // Returns a boolean. Invert to 0 is OK.\r
-\r
- if (!status) {\r
- switch(osvi.dwPlatformId) {\r
- case VER_PLATFORM_WIN32_WINDOWS:\r
- s_info.isNT = FALSE;\r
- isSupportedVersion = TRUE;\r
- break;\r
- case VER_PLATFORM_WIN32_NT:\r
- s_info.isNT = TRUE;\r
- isSupportedVersion = TRUE;\r
- break;\r
- case VER_PLATFORM_WIN32s:\r
- default:\r
- s_info.isNT = FALSE;\r
- break;\r
- }\r
- \r
- if (!isSupportedVersion) {\r
- cci_debug_printf("%s Trying to run on an unsupported version of Windows", __FUNCTION__);\r
- status = 1;\r
- }\r
- }\r
-\r
- if (!status) {status = !s_info.isNT;}\r
-\r
- if (!status) {status = !(s_hRpcDll = LoadLibrary(TEXT("rpcrt4.dll")));}\r
-\r
- if (!status) {\r
- s_info.fRpcBindingSetAuthInfoEx = (FP_RpcBindingSetAuthInfoEx)\r
- GetProcAddress(s_hRpcDll, TEXT(FN_RpcBindingSetAuthInfoEx));\r
- if (!s_info.fRpcBindingSetAuthInfoEx) {\r
- cci_debug_printf(" Running on NT but could not find RpcBindinSetAuthInfoEx");\r
- status = 1;\r
- }\r
- }\r
- \r
- if (!status) {\r
- s_info.fRpcServerRegisterIfEx = (FP_RpcServerRegisterIfEx)\r
- GetProcAddress(s_hRpcDll, TEXT(FN_RpcServerRegisterIfEx));\r
- if (!s_info.fRpcServerRegisterIfEx) {\r
- cci_debug_printf(" Running on NT but could not find RpcServerRegisterIfEx");\r
- status = 1;\r
- }\r
- }\r
-\r
- if (!status) {\r
- status = SecureClient::Attach();\r
- if (status) {\r
- cci_debug_printf(" SecureClient::Attach() failed (%u)", status);\r
- }\r
- }\r
-\r
- if (status) {\r
- memset(&s_info, 0, sizeof(s_info));\r
- if (s_hRpcDll) {\r
- FreeLibrary(s_hRpcDll);\r
- s_hRpcDll = 0;\r
- }\r
- cci_debug_printf(" Init::Attach() failed (%u)", status);\r
- } else {\r
- s_refcount++;\r
- s_init = true;\r
- ShowInfo(s_info);\r
- }\r
- s_error = status;\r
- return status;\r
-}\r
-\r
-DWORD\r
-Init::Cleanup(\r
- )\r
-{\r
- CcAutoLock AL(s_lock);\r
- s_refcount--;\r
- if (s_refcount) return 0;\r
- if (!s_init) return 0;\r
- DWORD error = 0;\r
- if (s_hRpcDll) {\r
- FreeLibrary(s_hRpcDll);\r
- s_hRpcDll = 0;\r
- }\r
- error = SecureClient::Detach();\r
- memset(&s_info, 0, sizeof(s_info));\r
- s_init = false;\r
- s_error = 0;\r
- if (error) {\r
- cci_debug_printf(" Init::Detach() had an error (%u)", error);\r
- }\r
- return error;\r
-}\r
-\r
-static\r
-void\r
-ShowInfo(\r
- Init::InitInfo& info\r
- )\r
-{\r
- if (info.isNT) {\r
- cci_debug_printf(" Running on Windows NT using secure mode");\r
- } else {\r
- cci_debug_printf(" Running insecurely on non-NT Windows");\r
- }\r
- return;\r
-}\r
+/*
+ * $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 <windows.h>
+#include "init.hxx"
+#include "secure.hxx"
+
+extern "C" {
+#include "cci_debugging.h"
+ }
+
+
+CcOsLock Init::s_lock;
+DWORD Init::s_refcount = 0;
+DWORD Init::s_error = ERROR_INVALID_HANDLE;
+bool Init::s_init = false;
+Init::InitInfo Init::s_info = { 0 };
+HINSTANCE Init::s_hRpcDll = 0;
+
+#define INIT "INIT: "
+
+static
+void
+ShowInfo(
+ Init::InitInfo& info
+ );
+
+DWORD
+Init::Info(
+ InitInfo& info
+ )
+{
+ // This funciton will not do automatic initialization.
+ CcAutoLock AL(s_lock);
+ if (!s_init) {
+ memset(&info, 0, sizeof(info));
+ return s_error ? s_error : ERROR_INVALID_HANDLE;
+ } else {
+ info = s_info;
+ return 0;
+ }
+}
+
+DWORD
+Init::Initialize() {
+ CcAutoLock AL(s_lock);
+// cci_debug_printf("%s s_init:%d", __FUNCTION__, s_init);
+ if (s_init) {
+ s_refcount++;
+ return 0;
+ }
+ SecureClient s;
+ DWORD status = 0;
+ OSVERSIONINFO osvi;
+ BOOL isSupportedVersion = FALSE;
+ memset(&s_info, 0, sizeof(s_info));
+ memset(&osvi, 0, sizeof(osvi));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+ status = !GetVersionEx(&osvi); // Returns a boolean. Invert to 0 is OK.
+
+ if (!status) {
+ switch(osvi.dwPlatformId) {
+ case VER_PLATFORM_WIN32_WINDOWS:
+ s_info.isNT = FALSE;
+ isSupportedVersion = TRUE;
+ break;
+ case VER_PLATFORM_WIN32_NT:
+ s_info.isNT = TRUE;
+ isSupportedVersion = TRUE;
+ break;
+ case VER_PLATFORM_WIN32s:
+ default:
+ s_info.isNT = FALSE;
+ break;
+ }
+
+ if (!isSupportedVersion) {
+ cci_debug_printf("%s Trying to run on an unsupported version of Windows", __FUNCTION__);
+ status = 1;
+ }
+ }
+
+ if (!status) {status = !s_info.isNT;}
+
+ if (!status) {status = !(s_hRpcDll = LoadLibrary(TEXT("rpcrt4.dll")));}
+
+ if (!status) {
+ s_info.fRpcBindingSetAuthInfoEx = (FP_RpcBindingSetAuthInfoEx)
+ GetProcAddress(s_hRpcDll, TEXT(FN_RpcBindingSetAuthInfoEx));
+ if (!s_info.fRpcBindingSetAuthInfoEx) {
+ cci_debug_printf(" Running on NT but could not find RpcBindinSetAuthInfoEx");
+ status = 1;
+ }
+ }
+
+ if (!status) {
+ s_info.fRpcServerRegisterIfEx = (FP_RpcServerRegisterIfEx)
+ GetProcAddress(s_hRpcDll, TEXT(FN_RpcServerRegisterIfEx));
+ if (!s_info.fRpcServerRegisterIfEx) {
+ cci_debug_printf(" Running on NT but could not find RpcServerRegisterIfEx");
+ status = 1;
+ }
+ }
+
+ if (!status) {
+ status = SecureClient::Attach();
+ if (status) {
+ cci_debug_printf(" SecureClient::Attach() failed (%u)", status);
+ }
+ }
+
+ if (status) {
+ memset(&s_info, 0, sizeof(s_info));
+ if (s_hRpcDll) {
+ FreeLibrary(s_hRpcDll);
+ s_hRpcDll = 0;
+ }
+ cci_debug_printf(" Init::Attach() failed (%u)", status);
+ } else {
+ s_refcount++;
+ s_init = true;
+ ShowInfo(s_info);
+ }
+ s_error = status;
+ return status;
+}
+
+DWORD
+Init::Cleanup(
+ )
+{
+ CcAutoLock AL(s_lock);
+ s_refcount--;
+ if (s_refcount) return 0;
+ if (!s_init) return 0;
+ DWORD error = 0;
+ if (s_hRpcDll) {
+ FreeLibrary(s_hRpcDll);
+ s_hRpcDll = 0;
+ }
+ error = SecureClient::Detach();
+ memset(&s_info, 0, sizeof(s_info));
+ s_init = false;
+ s_error = 0;
+ if (error) {
+ cci_debug_printf(" Init::Detach() had an error (%u)", error);
+ }
+ return error;
+}
+
+static
+void
+ShowInfo(
+ Init::InitInfo& info
+ )
+{
+ if (info.isNT) {
+ cci_debug_printf(" Running on Windows NT using secure mode");
+ } else {
+ cci_debug_printf(" Running insecurely on non-NT Windows");
+ }
+ return;
+}
-/*\r
- * $Header$\r
- *\r
- * Copyright 2008 Massachusetts Institute of Technology.\r
- * All Rights Reserved.\r
- *\r
- * Export of this software from the United States of America may\r
- * require a specific license from the United States Government.\r
- * It is the responsibility of any person or organization contemplating\r
- * export to obtain such a license before exporting.\r
- *\r
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and\r
- * distribute this software and its documentation for any purpose and\r
- * without fee is hereby granted, provided that the above copyright\r
- * notice appear in all copies and that both that copyright notice and\r
- * this permission notice appear in supporting documentation, and that\r
- * the name of M.I.T. not be used in advertising or publicity pertaining\r
- * to distribution of the software without specific, written prior\r
- * permission. Furthermore if you modify this software you must label\r
- * your software as modified software and not distribute it in such a\r
- * fashion that it might be confused with the original M.I.T. software.\r
- * M.I.T. makes no representations about the suitability of\r
- * this software for any purpose. It is provided "as is" without express\r
- * or implied warranty.\r
- */\r
-\r
-#pragma once\r
-#include "autolock.hxx"\r
-#include <rpc.h>\r
-\r
-typedef RPC_STATUS (RPC_ENTRY *FP_RpcBindingSetAuthInfoExA)(\r
- IN RPC_BINDING_HANDLE Binding,\r
- IN unsigned char __RPC_FAR * ServerPrincName,\r
- IN unsigned long AuthnLevel,\r
- IN unsigned long AuthnSvc,\r
- IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity, OPTIONAL\r
- IN unsigned long AuthzSvc,\r
- IN RPC_SECURITY_QOS *SecurityQos OPTIONAL\r
- );\r
-\r
-typedef RPC_STATUS (RPC_ENTRY *FP_RpcBindingSetAuthInfoExW)(\r
- IN RPC_BINDING_HANDLE Binding,\r
- IN unsigned short __RPC_FAR * ServerPrincName,\r
- IN unsigned long AuthnLevel,\r
- IN unsigned long AuthnSvc,\r
- IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity, OPTIONAL\r
- IN unsigned long AuthzSvc, OPTIONAL\r
- IN RPC_SECURITY_QOS *SecurityQOS\r
- );\r
-\r
-typedef RPC_STATUS (RPC_ENTRY *FP_RpcServerRegisterIfEx)(\r
- IN RPC_IF_HANDLE IfSpec,\r
- IN UUID __RPC_FAR * MgrTypeUuid,\r
- IN RPC_MGR_EPV __RPC_FAR * MgrEpv,\r
- IN unsigned int Flags,\r
- IN unsigned int MaxCalls,\r
- IN RPC_IF_CALLBACK_FN __RPC_FAR *IfCallback\r
- );\r
-\r
-#ifdef UNICODE\r
-#define FP_RpcBindingSetAuthInfoEx FP_RpcBindingSetAuthInfoExW\r
-#define FN_RpcBindingSetAuthInfoEx "RpcBindingSetAuthInfoExW"\r
-#else\r
-#define FP_RpcBindingSetAuthInfoEx FP_RpcBindingSetAuthInfoExA\r
-#define FN_RpcBindingSetAuthInfoEx "RpcBindingSetAuthInfoExA"\r
-#endif\r
-\r
-#define FN_RpcServerRegisterIfEx "RpcServerRegisterIfEx"\r
-\r
-class Init\r
-{\r
-public:\r
- struct InitInfo {\r
- BOOL isNT;\r
- FP_RpcBindingSetAuthInfoEx fRpcBindingSetAuthInfoEx;\r
- FP_RpcServerRegisterIfEx fRpcServerRegisterIfEx;\r
- };\r
-\r
- static DWORD Initialize();\r
- static DWORD Cleanup();\r
- static DWORD Info(InitInfo& info);\r
-\r
- static bool Initialized() { return s_init; }\r
-\r
-private:\r
- static CcOsLock s_lock;\r
- static DWORD s_refcount;\r
- static DWORD s_error;\r
- static bool s_init;\r
- static InitInfo s_info;\r
- static HINSTANCE s_hRpcDll;\r
-};\r
-\r
-#define INIT_INIT_EX(trap, error) \\r
-do \\r
-{ \\r
- if (!Init::Initialized()) \\r
- { \\r
- DWORD rc = Init::Initialize(); \\r
- if (rc) return (trap) ? (error) : rc; \\r
- } \\r
-} while(0)\r
+/*
+ * $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.
+ */
+
+#pragma once
+#include "autolock.hxx"
+#include <rpc.h>
+
+typedef RPC_STATUS (RPC_ENTRY *FP_RpcBindingSetAuthInfoExA)(
+ IN RPC_BINDING_HANDLE Binding,
+ IN unsigned char __RPC_FAR * ServerPrincName,
+ IN unsigned long AuthnLevel,
+ IN unsigned long AuthnSvc,
+ IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity, OPTIONAL
+ IN unsigned long AuthzSvc,
+ IN RPC_SECURITY_QOS *SecurityQos OPTIONAL
+ );
+
+typedef RPC_STATUS (RPC_ENTRY *FP_RpcBindingSetAuthInfoExW)(
+ IN RPC_BINDING_HANDLE Binding,
+ IN unsigned short __RPC_FAR * ServerPrincName,
+ IN unsigned long AuthnLevel,
+ IN unsigned long AuthnSvc,
+ IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity, OPTIONAL
+ IN unsigned long AuthzSvc, OPTIONAL
+ IN RPC_SECURITY_QOS *SecurityQOS
+ );
+
+typedef RPC_STATUS (RPC_ENTRY *FP_RpcServerRegisterIfEx)(
+ IN RPC_IF_HANDLE IfSpec,
+ IN UUID __RPC_FAR * MgrTypeUuid,
+ IN RPC_MGR_EPV __RPC_FAR * MgrEpv,
+ IN unsigned int Flags,
+ IN unsigned int MaxCalls,
+ IN RPC_IF_CALLBACK_FN __RPC_FAR *IfCallback
+ );
+
+#ifdef UNICODE
+#define FP_RpcBindingSetAuthInfoEx FP_RpcBindingSetAuthInfoExW
+#define FN_RpcBindingSetAuthInfoEx "RpcBindingSetAuthInfoExW"
+#else
+#define FP_RpcBindingSetAuthInfoEx FP_RpcBindingSetAuthInfoExA
+#define FN_RpcBindingSetAuthInfoEx "RpcBindingSetAuthInfoExA"
+#endif
+
+#define FN_RpcServerRegisterIfEx "RpcServerRegisterIfEx"
+
+class Init
+{
+public:
+ struct InitInfo {
+ BOOL isNT;
+ FP_RpcBindingSetAuthInfoEx fRpcBindingSetAuthInfoEx;
+ FP_RpcServerRegisterIfEx fRpcServerRegisterIfEx;
+ };
+
+ static DWORD Initialize();
+ static DWORD Cleanup();
+ static DWORD Info(InitInfo& info);
+
+ static bool Initialized() { return s_init; }
+
+private:
+ static CcOsLock s_lock;
+ static DWORD s_refcount;
+ static DWORD s_error;
+ static bool s_init;
+ static InitInfo s_info;
+ static HINSTANCE s_hRpcDll;
+};
+
+#define INIT_INIT_EX(trap, error) \
+do \
+{ \
+ if (!Init::Initialized()) \
+ { \
+ DWORD rc = Init::Initialize(); \
+ if (rc) return (trap) ? (error) : rc; \
+ } \
+} while(0)
-/*\r
- * $Header$\r
- *\r
- * Copyright 2008 Massachusetts Institute of Technology.\r
- * All Rights Reserved.\r
- *\r
- * Export of this software from the United States of America may\r
- * require a specific license from the United States Government.\r
- * It is the responsibility of any person or organization contemplating\r
- * export to obtain such a license before exporting.\r
- *\r
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and\r
- * distribute this software and its documentation for any purpose and\r
- * without fee is hereby granted, provided that the above copyright\r
- * notice appear in all copies and that both that copyright notice and\r
- * this permission notice appear in supporting documentation, and that\r
- * the name of M.I.T. not be used in advertising or publicity pertaining\r
- * to distribution of the software without specific, written prior\r
- * permission. Furthermore if you modify this software you must label\r
- * your software as modified software and not distribute it in such a\r
- * fashion that it might be confused with the original M.I.T. software.\r
- * M.I.T. makes no representations about the suitability of\r
- * this software for any purpose. It is provided "as is" without express\r
- * or implied warranty.\r
- */\r
-\r
-#include <windows.h>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <opts.hxx>\r
-\r
-#if 0\r
-const struct Opts*\r
-GetOpts(\r
- )\r
-{\r
- bool done = false;\r
- struct Opts* o;\r
- if (!(o = new Opts))\r
- goto cleanup;\r
- if (!(o->pszString = new char[lstrlenA(opts.pszString) + 1]))\r
- goto cleanup;\r
- if (!(o->pszEndpoint = new char[lstrlenA(opts.pszEndpoint) + 1]))\r
- goto cleanup;\r
- strcpy(o->pszString, opts.pszString);\r
- strcpy(o->pszEndpoint, opts.pszEndpoint);\r
- done = true;\r
- cleanup:\r
- if (!done) {\r
- FreeOpts(o);\r
- o = 0;\r
- }\r
- return o;\r
-}\r
-\r
-void\r
-FreeOpts(\r
- struct Opts* o\r
- )\r
-{\r
- if (o) {\r
- if (o->pszString)\r
- delete [] o->pszString;\r
- if (o->pszEndpoint)\r
- delete [] o->pszEndpoint;\r
- delete o;\r
- }\r
-}\r
-#endif\r
-\r
-bool\r
-ParseOpts::IsValidOpt(\r
- char ch\r
- )\r
-{\r
- return (m_ValidOpts[ch % 256] != 0);\r
-}\r
-\r
-void\r
-ParseOpts::PrintOpt(\r
- char ch,\r
- char* text\r
- )\r
-{\r
- if (IsValidOpt(ch))\r
- fprintf(stderr, " -%c %s\n", ch, text);\r
-}\r
-\r
-void\r
-ParseOpts::UsageOpts(\r
- char * program,\r
- int code\r
- )\r
-{\r
- fprintf(stderr, "Usage: %s [options]\n", program);\r
- PrintOpt('k', "stop server");\r
-#ifdef CCAPI_TEST_OPTIONS\r
- PrintOpt('s', "string");\r
- PrintOpt('e', "endpoint");\r
- PrintOpt('m', "maxcalls");\r
- PrintOpt('n', "mincalls");\r
- PrintOpt('f', "flag_wait_op");\r
- PrintOpt('u', "unprotected");\r
- PrintOpt('b', "use security callback");\r
-#endif\r
- PrintOpt('c', "output debug info to console");\r
- exit(code);\r
-}\r
-\r
-void\r
-ParseOpts::SetValidOpts(\r
- char* valid_opts\r
- )\r
-{\r
- memset(m_ValidOpts, 0, sizeof(m_ValidOpts));\r
- char *p = valid_opts;\r
- for (p = valid_opts; *p; p++) {\r
- m_ValidOpts[*p % sizeof(m_ValidOpts)] = 1;\r
- }\r
-}\r
-\r
-void\r
-ParseOpts::Parse(\r
- Opts& opts,\r
- int argc,\r
- char **argv\r
- )\r
-{\r
- int i;\r
- for (i = 1; i < argc; i++) {\r
- if ((*argv[i] == '-') || (*argv[i] == '/')) {\r
- char ch = tolower(*(argv[i]+1));\r
- if (!IsValidOpt(ch))\r
- UsageOpts(argv[0]);\r
- switch (ch) {\r
- case 'k':\r
- opts.bShutdown = TRUE;\r
- break;\r
-#ifdef CCAPI_TEST_OPTIONS\r
- case 's':\r
- opts.pszString = argv[++i];\r
- break;\r
- case 'e':\r
- opts.pszEndpoint = argv[++i];\r
- break;\r
- case 'm':\r
- opts.cMaxCalls = (unsigned int) atoi(argv[++i]);\r
- break;\r
- case 'n':\r
- opts.cMinCalls = (unsigned int) atoi(argv[++i]);\r
- break;\r
- case 'f':\r
- opts.fDontWait = (unsigned int) atoi(argv[++i]);\r
- break;\r
- case 'u':\r
- opts.bDontProtect = TRUE;\r
- break;\r
- case 'b':\r
- opts.bSecCallback = TRUE;\r
- break;\r
-#endif\r
- case 'c':\r
- opts.bConsole = TRUE;\r
- break;\r
- case 'h':\r
- case '?':\r
- default:\r
- UsageOpts(argv[0]);\r
- }\r
- }\r
- else\r
- UsageOpts(argv[0]);\r
- }\r
-\r
-}\r
-\r
-ParseOpts::ParseOpts(char* valid_opts)\r
-{\r
- SetValidOpts(valid_opts);\r
-}\r
-\r
-ParseOpts::ParseOpts()\r
-{\r
-}\r
-\r
-ParseOpts::~ParseOpts()\r
-{\r
-}\r
+/*
+ * $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 <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <opts.hxx>
+
+#if 0
+const struct Opts*
+GetOpts(
+ )
+{
+ bool done = false;
+ struct Opts* o;
+ if (!(o = new Opts))
+ goto cleanup;
+ if (!(o->pszString = new char[lstrlenA(opts.pszString) + 1]))
+ goto cleanup;
+ if (!(o->pszEndpoint = new char[lstrlenA(opts.pszEndpoint) + 1]))
+ goto cleanup;
+ strcpy(o->pszString, opts.pszString);
+ strcpy(o->pszEndpoint, opts.pszEndpoint);
+ done = true;
+ cleanup:
+ if (!done) {
+ FreeOpts(o);
+ o = 0;
+ }
+ return o;
+}
+
+void
+FreeOpts(
+ struct Opts* o
+ )
+{
+ if (o) {
+ if (o->pszString)
+ delete [] o->pszString;
+ if (o->pszEndpoint)
+ delete [] o->pszEndpoint;
+ delete o;
+ }
+}
+#endif
+
+bool
+ParseOpts::IsValidOpt(
+ char ch
+ )
+{
+ return (m_ValidOpts[ch % 256] != 0);
+}
+
+void
+ParseOpts::PrintOpt(
+ char ch,
+ char* text
+ )
+{
+ if (IsValidOpt(ch))
+ fprintf(stderr, " -%c %s\n", ch, text);
+}
+
+void
+ParseOpts::UsageOpts(
+ char * program,
+ int code
+ )
+{
+ fprintf(stderr, "Usage: %s [options]\n", program);
+ PrintOpt('k', "stop server");
+#ifdef CCAPI_TEST_OPTIONS
+ PrintOpt('s', "string");
+ PrintOpt('e', "endpoint");
+ PrintOpt('m', "maxcalls");
+ PrintOpt('n', "mincalls");
+ PrintOpt('f', "flag_wait_op");
+ PrintOpt('u', "unprotected");
+ PrintOpt('b', "use security callback");
+#endif
+ PrintOpt('c', "output debug info to console");
+ exit(code);
+}
+
+void
+ParseOpts::SetValidOpts(
+ char* valid_opts
+ )
+{
+ memset(m_ValidOpts, 0, sizeof(m_ValidOpts));
+ char *p = valid_opts;
+ for (p = valid_opts; *p; p++) {
+ m_ValidOpts[*p % sizeof(m_ValidOpts)] = 1;
+ }
+}
+
+void
+ParseOpts::Parse(
+ Opts& opts,
+ int argc,
+ char **argv
+ )
+{
+ int i;
+ for (i = 1; i < argc; i++) {
+ if ((*argv[i] == '-') || (*argv[i] == '/')) {
+ char ch = tolower(*(argv[i]+1));
+ if (!IsValidOpt(ch))
+ UsageOpts(argv[0]);
+ switch (ch) {
+ case 'k':
+ opts.bShutdown = TRUE;
+ break;
+#ifdef CCAPI_TEST_OPTIONS
+ case 's':
+ opts.pszString = argv[++i];
+ break;
+ case 'e':
+ opts.pszEndpoint = argv[++i];
+ break;
+ case 'm':
+ opts.cMaxCalls = (unsigned int) atoi(argv[++i]);
+ break;
+ case 'n':
+ opts.cMinCalls = (unsigned int) atoi(argv[++i]);
+ break;
+ case 'f':
+ opts.fDontWait = (unsigned int) atoi(argv[++i]);
+ break;
+ case 'u':
+ opts.bDontProtect = TRUE;
+ break;
+ case 'b':
+ opts.bSecCallback = TRUE;
+ break;
+#endif
+ case 'c':
+ opts.bConsole = TRUE;
+ break;
+ case 'h':
+ case '?':
+ default:
+ UsageOpts(argv[0]);
+ }
+ }
+ else
+ UsageOpts(argv[0]);
+ }
+
+}
+
+ParseOpts::ParseOpts(char* valid_opts)
+{
+ SetValidOpts(valid_opts);
+}
+
+ParseOpts::ParseOpts()
+{
+}
+
+ParseOpts::~ParseOpts()
+{
+}
-/*\r
- * $Header$\r
- *\r
- * Copyright 2008 Massachusetts Institute of Technology.\r
- * All Rights Reserved.\r
- *\r
- * Export of this software from the United States of America may\r
- * require a specific license from the United States Government.\r
- * It is the responsibility of any person or organization contemplating\r
- * export to obtain such a license before exporting.\r
- *\r
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and\r
- * distribute this software and its documentation for any purpose and\r
- * without fee is hereby granted, provided that the above copyright\r
- * notice appear in all copies and that both that copyright notice and\r
- * this permission notice appear in supporting documentation, and that\r
- * the name of M.I.T. not be used in advertising or publicity pertaining\r
- * to distribution of the software without specific, written prior\r
- * permission. Furthermore if you modify this software you must label\r
- * your software as modified software and not distribute it in such a\r
- * fashion that it might be confused with the original M.I.T. software.\r
- * M.I.T. makes no representations about the suitability of\r
- * this software for any purpose. It is provided "as is" without express\r
- * or implied warranty.\r
- */\r
-\r
-#pragma once\r
-\r
-class ParseOpts\r
-{\r
-public:\r
- struct Opts {\r
- char* pszString;\r
- char* pszEndpoint;\r
- unsigned int cMinCalls;\r
- unsigned int cMaxCalls;\r
- unsigned int fDontWait;\r
- bool bDontProtect;\r
- bool bShutdown;\r
- bool bSecCallback;\r
- bool bConsole;\r
- };\r
-\r
- ParseOpts(char* valid_opts);\r
- ParseOpts();\r
- ~ParseOpts();\r
- void SetValidOpts(char* valid_opts);\r
- void Parse(Opts& opts, int argc, char **argv);\r
-\r
-private:\r
- bool IsValidOpt(char ch);\r
- void PrintOpt(char ch, char* text);\r
- void UsageOpts(char* program, int code = 0);\r
-\r
- char m_ValidOpts[256];\r
-};\r
+/*
+ * $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.
+ */
+
+#pragma once
+
+class ParseOpts
+{
+public:
+ struct Opts {
+ char* pszString;
+ char* pszEndpoint;
+ unsigned int cMinCalls;
+ unsigned int cMaxCalls;
+ unsigned int fDontWait;
+ bool bDontProtect;
+ bool bShutdown;
+ bool bSecCallback;
+ bool bConsole;
+ };
+
+ ParseOpts(char* valid_opts);
+ ParseOpts();
+ ~ParseOpts();
+ void SetValidOpts(char* valid_opts);
+ void Parse(Opts& opts, int argc, char **argv);
+
+private:
+ bool IsValidOpt(char ch);
+ void PrintOpt(char ch, char* text);
+ void UsageOpts(char* program, int code = 0);
+
+ char m_ValidOpts[256];
+};
-/*\r
- * $Header$\r
- *\r
- * Copyright 2008 Massachusetts Institute of Technology.\r
- * All Rights Reserved.\r
- *\r
- * Export of this software from the United States of America may\r
- * require a specific license from the United States Government.\r
- * It is the responsibility of any person or organization contemplating\r
- * export to obtain such a license before exporting.\r
- *\r
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and\r
- * distribute this software and its documentation for any purpose and\r
- * without fee is hereby granted, provided that the above copyright\r
- * notice appear in all copies and that both that copyright notice and\r
- * this permission notice appear in supporting documentation, and that\r
- * the name of M.I.T. not be used in advertising or publicity pertaining\r
- * to distribution of the software without specific, written prior\r
- * permission. Furthermore if you modify this software you must label\r
- * your software as modified software and not distribute it in such a\r
- * fashion that it might be confused with the original M.I.T. software.\r
- * M.I.T. makes no representations about the suitability of\r
- * this software for any purpose. It is provided "as is" without express\r
- * or implied warranty.\r
- */\r
-\r
-#include <windows.h>\r
-#include "secure.hxx"\r
-\r
-extern "C" {\r
-#include "cci_debugging.h"\r
- }\r
-\r
-CcOsLock SecureClient::s_lock;\r
-DWORD SecureClient::s_refcount = 0;\r
-DWORD SecureClient::s_error = 0;\r
-HANDLE SecureClient::s_hToken = 0;\r
-\r
-#include "util.h"\r
-\r
-#define SC "SecureClient::"\r
-\r
-DWORD\r
-SecureClient::Attach(\r
- )\r
-{\r
- CcAutoLock AL(s_lock);\r
- if (s_hToken) {\r
- s_refcount++;\r
- return 0;\r
- }\r
- if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, \r
- &s_hToken)) {\r
- s_refcount++;\r
- s_error = 0;\r
- } else {\r
- s_hToken = 0;\r
- s_error = GetLastError();\r
- }\r
- return s_error;\r
-}\r
-\r
-DWORD\r
-SecureClient::Detach(\r
- )\r
-{\r
- CcAutoLock AL(s_lock);\r
- s_refcount--;\r
- if (s_refcount) return 0;\r
- if (!s_hToken) return 0;\r
- DWORD error = 0;\r
- if (!CloseHandle(s_hToken))\r
- error = GetLastError();\r
- s_hToken = 0;\r
- s_error = 0;\r
- return error;\r
-}\r
-\r
-DWORD SecureClient::Token(HANDLE& hToken) {\r
- // This function will not do automatic initialization.\r
- CcAutoLock AL(s_lock);\r
- hToken = 0;\r
- if (!s_hToken) {\r
- cci_debug_printf("%s no process token initialized (%u)", __FUNCTION__, s_error);\r
- return s_error ? s_error : ERROR_INVALID_HANDLE;\r
- } \r
- else {\r
- DWORD status = 0;\r
- if (!DuplicateHandle(GetCurrentProcess(), s_hToken, \r
- GetCurrentProcess(), &hToken, 0, FALSE, \r
- DUPLICATE_SAME_ACCESS)) {\r
- status = GetLastError();\r
- cci_debug_printf(" Could not duplicate handle (%u)", status);\r
- }\r
- return status;\r
- }\r
- }\r
-\r
-void\r
-SecureClient::Start(SecureClient*& s) {\r
- s = new SecureClient;\r
-}\r
-\r
-void\r
-SecureClient::Stop(SecureClient*& s) {\r
- delete s;\r
- s = 0;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-/* This constructor turns off impersonation.\r
- * It is OK for OpenThreadToken to return an error -- that just means impersonation\r
- * is off.\r
- */\r
-SecureClient::SecureClient():\r
- m_Error(0),\r
- m_hToken(0),\r
- m_NeedRestore(false) {\r
-\r
- HANDLE hThread = GetCurrentThread();\r
- HANDLE hThDuplicate;\r
- \r
- int status = DuplicateHandle( GetCurrentProcess(),\r
- hThread,\r
- GetCurrentProcess(),\r
- &hThDuplicate,\r
- TOKEN_ALL_ACCESS,\r
- FALSE,\r
- 0);\r
- if (!status) return;\r
-\r
- if (!OpenThreadToken(hThDuplicate, TOKEN_ALL_ACCESS, FALSE, &m_hToken)) {\r
- m_Error = GetLastError();\r
- return;\r
- }\r
- if (SetThreadToken(&hThDuplicate, NULL)) {\r
- m_NeedRestore = true;\r
- } else {\r
- m_Error = GetLastError();\r
- }\r
- CloseHandle(hThDuplicate);\r
- }\r
-\r
-SecureClient::~SecureClient() {\r
- if (m_NeedRestore) {\r
- HANDLE hThread = GetCurrentThread();\r
- if (!SetThreadToken(&hThread, m_hToken)) {\r
- m_Error = cci_check_error(GetLastError());\r
- }\r
- }\r
- if (m_hToken) {\r
- if (!CloseHandle(m_hToken)) {\r
- m_Error = cci_check_error(GetLastError());\r
- }\r
- }\r
- }\r
-\r
-DWORD SecureClient::Error() {\r
- return m_Error;\r
+/*
+ * $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 <windows.h>
+#include "secure.hxx"
+
+extern "C" {
+#include "cci_debugging.h"
+ }
+
+CcOsLock SecureClient::s_lock;
+DWORD SecureClient::s_refcount = 0;
+DWORD SecureClient::s_error = 0;
+HANDLE SecureClient::s_hToken = 0;
+
+#include "util.h"
+
+#define SC "SecureClient::"
+
+DWORD
+SecureClient::Attach(
+ )
+{
+ CcAutoLock AL(s_lock);
+ if (s_hToken) {
+ s_refcount++;
+ return 0;
+ }
+ if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY,
+ &s_hToken)) {
+ s_refcount++;
+ s_error = 0;
+ } else {
+ s_hToken = 0;
+ s_error = GetLastError();
+ }
+ return s_error;
+}
+
+DWORD
+SecureClient::Detach(
+ )
+{
+ CcAutoLock AL(s_lock);
+ s_refcount--;
+ if (s_refcount) return 0;
+ if (!s_hToken) return 0;
+ DWORD error = 0;
+ if (!CloseHandle(s_hToken))
+ error = GetLastError();
+ s_hToken = 0;
+ s_error = 0;
+ return error;
+}
+
+DWORD SecureClient::Token(HANDLE& hToken) {
+ // This function will not do automatic initialization.
+ CcAutoLock AL(s_lock);
+ hToken = 0;
+ if (!s_hToken) {
+ cci_debug_printf("%s no process token initialized (%u)", __FUNCTION__, s_error);
+ return s_error ? s_error : ERROR_INVALID_HANDLE;
+ }
+ else {
+ DWORD status = 0;
+ if (!DuplicateHandle(GetCurrentProcess(), s_hToken,
+ GetCurrentProcess(), &hToken, 0, FALSE,
+ DUPLICATE_SAME_ACCESS)) {
+ status = GetLastError();
+ cci_debug_printf(" Could not duplicate handle (%u)", status);
+ }
+ return status;
+ }
+ }
+
+void
+SecureClient::Start(SecureClient*& s) {
+ s = new SecureClient;
+}
+
+void
+SecureClient::Stop(SecureClient*& s) {
+ delete s;
+ s = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+/* This constructor turns off impersonation.
+ * It is OK for OpenThreadToken to return an error -- that just means impersonation
+ * is off.
+ */
+SecureClient::SecureClient():
+ m_Error(0),
+ m_hToken(0),
+ m_NeedRestore(false) {
+
+ HANDLE hThread = GetCurrentThread();
+ HANDLE hThDuplicate;
+
+ int status = DuplicateHandle( GetCurrentProcess(),
+ hThread,
+ GetCurrentProcess(),
+ &hThDuplicate,
+ TOKEN_ALL_ACCESS,
+ FALSE,
+ 0);
+ if (!status) return;
+
+ if (!OpenThreadToken(hThDuplicate, TOKEN_ALL_ACCESS, FALSE, &m_hToken)) {
+ m_Error = GetLastError();
+ return;
+ }
+ if (SetThreadToken(&hThDuplicate, NULL)) {
+ m_NeedRestore = true;
+ } else {
+ m_Error = GetLastError();
+ }
+ CloseHandle(hThDuplicate);
+ }
+
+SecureClient::~SecureClient() {
+ if (m_NeedRestore) {
+ HANDLE hThread = GetCurrentThread();
+ if (!SetThreadToken(&hThread, m_hToken)) {
+ m_Error = cci_check_error(GetLastError());
+ }
+ }
+ if (m_hToken) {
+ if (!CloseHandle(m_hToken)) {
+ m_Error = cci_check_error(GetLastError());
+ }
+ }
+ }
+
+DWORD SecureClient::Error() {
+ return m_Error;
}
\ No newline at end of file
-/*\r
- * $Header$\r
- *\r
- * Copyright 2008 Massachusetts Institute of Technology.\r
- * All Rights Reserved.\r
- *\r
- * Export of this software from the United States of America may\r
- * require a specific license from the United States Government.\r
- * It is the responsibility of any person or organization contemplating\r
- * export to obtain such a license before exporting.\r
- *\r
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and\r
- * distribute this software and its documentation for any purpose and\r
- * without fee is hereby granted, provided that the above copyright\r
- * notice appear in all copies and that both that copyright notice and\r
- * this permission notice appear in supporting documentation, and that\r
- * the name of M.I.T. not be used in advertising or publicity pertaining\r
- * to distribution of the software without specific, written prior\r
- * permission. Furthermore if you modify this software you must label\r
- * your software as modified software and not distribute it in such a\r
- * fashion that it might be confused with the original M.I.T. software.\r
- * M.I.T. makes no representations about the suitability of\r
- * this software for any purpose. It is provided "as is" without express\r
- * or implied warranty.\r
- */\r
-\r
-#pragma once\r
-\r
-#include <windows.h>\r
-#include "autolock.hxx"\r
-\r
-class SecureClient\r
-{\r
-public:\r
- static DWORD Attach();\r
- static DWORD Detach();\r
- static DWORD Token(HANDLE& hToken);\r
- static void Start(SecureClient*& s);\r
- static void Stop(SecureClient*& s);\r
-\r
-#if 0\r
- static DWORD CheckImpersonation();\r
- static bool IsImp();\r
- static DWORD DuplicateImpAsPrimary(HANDLE& hPrimary);\r
-#endif\r
-\r
- SecureClient();\r
- ~SecureClient();\r
- DWORD Error();\r
-\r
-private:\r
- static CcOsLock s_lock;\r
- static DWORD s_refcount;\r
- static DWORD s_error;\r
- static HANDLE s_hToken;\r
-\r
- DWORD m_Error;\r
- HANDLE m_hToken;\r
- bool m_NeedRestore;\r
-};\r
+/*
+ * $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.
+ */
+
+#pragma once
+
+#include <windows.h>
+#include "autolock.hxx"
+
+class SecureClient
+{
+public:
+ static DWORD Attach();
+ static DWORD Detach();
+ static DWORD Token(HANDLE& hToken);
+ static void Start(SecureClient*& s);
+ static void Stop(SecureClient*& s);
+
+#if 0
+ static DWORD CheckImpersonation();
+ static bool IsImp();
+ static DWORD DuplicateImpAsPrimary(HANDLE& hPrimary);
+#endif
+
+ SecureClient();
+ ~SecureClient();
+ DWORD Error();
+
+private:
+ static CcOsLock s_lock;
+ static DWORD s_refcount;
+ static DWORD s_error;
+ static HANDLE s_hToken;
+
+ DWORD m_Error;
+ HANDLE m_hToken;
+ bool m_NeedRestore;
+};
-/*\r
- * $Header$\r
- *\r
- * Copyright 2008 Massachusetts Institute of Technology.\r
- * All Rights Reserved.\r
- *\r
- * Export of this software from the United States of America may\r
- * require a specific license from the United States Government.\r
- * It is the responsibility of any person or organization contemplating\r
- * export to obtain such a license before exporting.\r
- *\r
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and\r
- * distribute this software and its documentation for any purpose and\r
- * without fee is hereby granted, provided that the above copyright\r
- * notice appear in all copies and that both that copyright notice and\r
- * this permission notice appear in supporting documentation, and that\r
- * the name of M.I.T. not be used in advertising or publicity pertaining\r
- * to distribution of the software without specific, written prior\r
- * permission. Furthermore if you modify this software you must label\r
- * your software as modified software and not distribute it in such a\r
- * fashion that it might be confused with the original M.I.T. software.\r
- * M.I.T. makes no representations about the suitability of\r
- * this software for any purpose. It is provided "as is" without express\r
- * or implied warranty.\r
- */\r
-\r
-#include <windows.h>\r
-#include <stdio.h> // for _snprintf\r
-\r
-#include "util.h"\r
-#include "secure.hxx"\r
-\r
-extern "C" {\r
-#include "cci_debugging.h"\r
-#include "ccutils.h"\r
- }\r
-\r
-\r
-\r
-void* malloc_alloc_p(size_t size) {\r
- return malloc(size);\r
- }\r
-\r
-void free_alloc_p(void *pptr) {\r
- void **real_pptr = (void**)pptr;\r
- if (*real_pptr) {\r
- free(*real_pptr);\r
- *real_pptr = 0;\r
- }\r
- }\r
-\r
-extern "C" DWORD alloc_textual_sid(\r
- PSID pSid, // binary Sid\r
- LPSTR *pTextualSid // buffer for Textual representaion of Sid\r
- ) {\r
- PSID_IDENTIFIER_AUTHORITY psia;\r
- DWORD dwSubAuthorities;\r
- DWORD dwSidRev = SID_REVISION;\r
- DWORD dwCounter;\r
- DWORD dwSidSize;\r
-\r
- *pTextualSid = 0;\r
-\r
- //\r
- // test if Sid passed in is valid\r
- //\r
- if(!IsValidSid(pSid)) return ERROR_INVALID_PARAMETER;\r
-\r
- // obtain SidIdentifierAuthority\r
- psia = GetSidIdentifierAuthority(pSid);\r
- \r
- // obtain sidsubauthority count\r
- dwSubAuthorities =* GetSidSubAuthorityCount(pSid);\r
- \r
- //\r
- // compute buffer length\r
- // S-SID_REVISION- + identifierauthority- + subauthorities- + NULL\r
- //\r
- dwSidSize = (15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);\r
- *pTextualSid = (LPSTR)malloc_alloc_p(dwSidSize);\r
- if (!*pTextualSid)\r
- return GetLastError();\r
-\r
- LPSTR TextualSid = *pTextualSid;\r
-\r
- //\r
- // prepare S-SID_REVISION-\r
- //\r
- wsprintf(TextualSid, TEXT("S-%lu-"), dwSidRev );\r
- \r
- //\r
- // prepare SidIdentifierAuthority\r
- //\r
- if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) )\r
- {\r
- wsprintf(TextualSid + lstrlen(TextualSid),\r
- TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),\r
- (USHORT)psia->Value[0],\r
- (USHORT)psia->Value[1],\r
- (USHORT)psia->Value[2],\r
- (USHORT)psia->Value[3],\r
- (USHORT)psia->Value[4],\r
- (USHORT)psia->Value[5]);\r
- }\r
- else\r
- {\r
- wsprintf(TextualSid + lstrlen(TextualSid), TEXT("%lu"),\r
- (ULONG)(psia->Value[5] ) +\r
- (ULONG)(psia->Value[4] << 8) +\r
- (ULONG)(psia->Value[3] << 16) +\r
- (ULONG)(psia->Value[2] << 24) );\r
- }\r
- \r
- //\r
- // loop through SidSubAuthorities\r
- //\r
- for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++)\r
- {\r
- wsprintf(TextualSid + lstrlen(TextualSid), TEXT("-%lu"),\r
- *GetSidSubAuthority(pSid, dwCounter) );\r
- }\r
- return 0;\r
-}\r
-\r
-DWORD alloc_token_user(HANDLE hToken, PTOKEN_USER *pptu) {\r
- DWORD status = 0;\r
- DWORD size = 0;\r
- *pptu = 0;\r
-\r
- GetTokenInformation(hToken, TokenUser, *pptu, 0, &size);\r
- if (size == 0) status = GetLastError();\r
-\r
- if (!status) {\r
- if (!(*pptu = (PTOKEN_USER)malloc_alloc_p(size)))\r
- status = GetLastError();\r
- }\r
-\r
- if (!status) {\r
- if (!GetTokenInformation(hToken, TokenUser, *pptu, size, &size))\r
- status = GetLastError();\r
- }\r
-\r
- if (status && *pptu) {\r
- free_alloc_p(pptu);\r
- }\r
- return status;\r
- }\r
-\r
-DWORD\r
-alloc_username(\r
- PSID Sid,\r
- LPSTR* pname,\r
- LPSTR* pdomain = 0\r
- )\r
-{\r
- DWORD status = 0;\r
- DWORD name_len = 0;\r
- DWORD domain_len = 0;\r
- SID_NAME_USE snu;\r
- LPSTR name = 0;\r
- LPSTR domain = 0;\r
-\r
- *pname = 0;\r
- if (pdomain) *pdomain = 0;\r
-\r
- LookupAccountSidA(NULL, Sid, 0, &name_len, 0, &domain_len, &snu);\r
- if ((name_len == 0) || (domain_len == 0)) status = GetLastError();\r
-\r
- if (!status) {\r
- if (!(name = (LPSTR)malloc_alloc_p(name_len))) status = GetLastError();\r
- }\r
-\r
- if (!status) {\r
- if (!(domain = (LPSTR)malloc_alloc_p(domain_len))) status = GetLastError();\r
- }\r
-\r
- if (!status) {\r
- if (!LookupAccountSidA(NULL, Sid, name, &name_len, domain, &domain_len, &snu)) status = GetLastError();\r
- }\r
-\r
- if (status) {\r
- if (name) free_alloc_p(&name);\r
- if (domain) free_alloc_p(&domain);\r
- } \r
- else {\r
- if (pdomain) {\r
- *pname = name;\r
- *pdomain = domain;\r
- } \r
- else {\r
- DWORD size = name_len + domain_len + 1;\r
- *pname = (LPSTR)malloc_alloc_p(size);\r
- if (!*pname) status = GetLastError();\r
- else _snprintf(*pname, size, "%s\\%s", name, domain);\r
- }\r
- }\r
- return status;\r
- }\r
-\r
-DWORD get_authentication_id(HANDLE hToken, LUID* pAuthId) {\r
- TOKEN_STATISTICS ts;\r
- DWORD len;\r
-\r
- if (!GetTokenInformation(hToken, TokenStatistics, &ts, sizeof(ts), &len))\r
- return GetLastError();\r
- *pAuthId = ts.AuthenticationId;\r
- return 0;\r
- }\r
-\r
-DWORD\r
-alloc_name_9x(\r
- LPSTR* pname,\r
- LPSTR postfix\r
- )\r
-{\r
- char prefix[] = "krbcc";\r
- DWORD len = (sizeof(prefix) - 1) + 1 + strlen(postfix) + 1;\r
-\r
- *pname = (LPSTR)malloc_alloc_p(len);\r
- if (!*pname) return GetLastError();\r
- _snprintf(*pname, len, "%s.%s", prefix, postfix);\r
- return 0;\r
-}\r
-\r
-DWORD alloc_name_NT(LPSTR* pname, LPSTR postfix) {\r
- DWORD status = 0;\r
- HANDLE hToken = 0;\r
- LUID auth_id;\r
-#ifdef _DEBUG\r
- PTOKEN_USER ptu = 0;\r
- LPSTR name = 0;\r
- LPSTR domain = 0;\r
- LPSTR sid = 0;\r
-#endif\r
- char prefix[] = "krbcc";\r
- // Play it safe and say 3 characters are needed per 8 bits (byte).\r
- // Note that 20 characters are needed for a 64-bit number in\r
- // decimal (plus one for the string termination.\r
- // and include room for sessionId.\r
- char lid[3*sizeof(LUID)+1+5];\r
- DWORD sessionId;\r
- DWORD len = 0;\r
-\r
- *pname = 0;\r
-\r
- status = SecureClient::Token(hToken);\r
-\r
- if (!status) {\r
- status = get_authentication_id(hToken, &auth_id);\r
- }\r
-\r
- if (!status) {\r
- if (!ProcessIdToSessionId(GetCurrentProcessId(), &sessionId))\r
- sessionId = 0;\r
- }\r
-\r
-#ifdef _DEBUG\r
- if (!status) {status = alloc_token_user(hToken, &ptu);}\r
- if (!status) {status = alloc_username(ptu->User.Sid, &name, &domain);}\r
- if (!status) {status = alloc_textual_sid(ptu->User.Sid, &sid);}\r
-#endif\r
-\r
- if (!status) {\r
- _snprintf(lid, sizeof(lid), "%I64u.%u", auth_id, sessionId);\r
- lid[sizeof(lid)-1] = 0; // be safe\r
-\r
- len = (sizeof(prefix) - 1) + 1 + strlen(lid) + 1 + strlen(postfix) + 1;\r
- *pname = (LPSTR)malloc_alloc_p(len);\r
- if (!*pname) status = GetLastError();\r
- }\r
-\r
- //\r
- // We used to allocate a name of the form:\r
- // "prefix.domain.name.sid.lid.postfix" (usually under 80\r
- // characters, depending on username). However, XP thought this\r
- // was "invalid" (too long?) for some reason.\r
- //\r
- // Therefore, we now use "prefix.lid.postfix"\r
- // and for Terminal server we use "prefix.lid.sessionId.postfix"\r
- //\r
-\r
- if (!status) {\r
- _snprintf(*pname, len, "%s.%s.%s", prefix, lid, postfix);\r
- }\r
-\r
-#ifdef _DEBUG\r
- if (sid)\r
- free_alloc_p(&sid);\r
- if (name)\r
- free_alloc_p(&name);\r
- if (domain)\r
- free_alloc_p(&domain);\r
- if (ptu)\r
- free_alloc_p(&ptu);\r
-#endif\r
- if (hToken && hToken != INVALID_HANDLE_VALUE)\r
- CloseHandle(hToken);\r
- if (status && *pname)\r
- free_alloc_p(pname);\r
- return status;\r
-}\r
-\r
-extern "C" DWORD alloc_name(LPSTR* pname, LPSTR postfix, BOOL isNT) {\r
- return isNT ? alloc_name_NT(pname, postfix) : \r
- alloc_name_9x(pname, postfix);\r
- }\r
-\r
-extern "C" DWORD alloc_own_security_descriptor_NT(PSECURITY_DESCRIPTOR* ppsd) {\r
- DWORD status = 0;\r
- HANDLE hToken = 0;\r
- PTOKEN_USER ptu = 0;\r
- PSID pSid = 0;\r
- PACL pAcl = 0;\r
- DWORD size = 0;\r
- SECURITY_DESCRIPTOR sd;\r
-\r
- *ppsd = 0;\r
-\r
- if (!status) {status = SecureClient::Token(hToken);}\r
-\r
- // Get SID:\r
- if (!status) {status = alloc_token_user(hToken, &ptu);}\r
-\r
- if (!status) {\r
- size = GetLengthSid(ptu->User.Sid);\r
- pSid = (PSID) malloc_alloc_p(size);\r
- if (!pSid) status = GetLastError();\r
- }\r
- if (!status) {\r
- if (!CopySid(size, pSid, ptu->User.Sid)) status = GetLastError();\r
- }\r
-\r
- if (!status) {\r
- // Prepare ACL:\r
- size = sizeof(ACL);\r
- // Add an ACE:\r
- size += sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(pSid);\r
- pAcl = (PACL) malloc_alloc_p(size);\r
- if (!pAcl) status = GetLastError();\r
- }\r
-\r
- if (!status) {\r
- if (!InitializeAcl(pAcl, size, ACL_REVISION)) status = GetLastError();\r
- }\r
-\r
- if (!status) {\r
- if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, pSid)) status = GetLastError();\r
- }\r
-\r
- if (!status) {\r
- // Prepare SD itself:\r
- if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) status = GetLastError();\r
- }\r
-\r
- if (!status) {\r
- if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) status = GetLastError();\r
- }\r
-\r
- if (!status) {\r
- if (!SetSecurityDescriptorOwner(&sd, pSid, FALSE)) status = GetLastError();\r
- }\r
-\r
- if (!status) {\r
- if (!IsValidSecurityDescriptor(&sd)) status = ERROR_INVALID_PARAMETER;\r
- }\r
-\r
- if (!status) {\r
- // We now have a SD. Let's copy it.\r
- {\r
- // This should not succeed. Instead it should give us the size.\r
- BOOL ok = MakeSelfRelativeSD(&sd, 0, &size);\r
- }\r
- if (size == 0) status = GetLastError();\r
- }\r
-\r
- if (!status) {\r
- *ppsd = (PSECURITY_DESCRIPTOR) malloc_alloc_p(size);\r
- if (!*ppsd) status = GetLastError();\r
- }\r
-\r
- if (!status) {\r
- if (!MakeSelfRelativeSD(&sd, *ppsd, &size)) status = GetLastError();\r
- }\r
-\r
- if (ptu) free_alloc_p(&ptu);\r
- if (pSid) free_alloc_p(&pSid);\r
- if (pAcl) free_alloc_p(&pAcl);\r
- if (hToken && hToken != INVALID_HANDLE_VALUE) CloseHandle(hToken);\r
- if (status && *ppsd) free_alloc_p(ppsd);\r
- return status;\r
-}\r
-\r
-DWORD\r
-alloc_module_file_name(\r
- char* module,\r
- char** pname\r
- )\r
-{\r
- const DWORD max = 8192;\r
- DWORD status = 0;\r
- DWORD got = 0;\r
- DWORD size = 512; // use low number to test...\r
- HMODULE h = 0;\r
- BOOL ok = FALSE;\r
- char* name = 0;\r
-\r
- if (!pname)\r
- return ERROR_INVALID_PARAMETER;\r
- *pname = 0;\r
-\r
- h = GetModuleHandle(module);\r
-\r
- if (!h) return GetLastError();\r
-\r
- // We assume size < max and size > 0\r
- while (!status && !ok) {\r
- if (size > max) {\r
- // XXX - Assert?\r
- status = ERROR_INVALID_DATA;\r
- continue;\r
- }\r
- if (name) free_alloc_p(&name);\r
- name = (char*)malloc_alloc_p(size + 1);\r
- if (!name) {\r
- status = ERROR_NOT_ENOUGH_MEMORY;\r
- continue;\r
- }\r
- name[size] = 0;\r
- got = GetModuleFileName(h, name, size);\r
- if (!got) {\r
- status = GetLastError();\r
- // sanity check:\r
- if (!status) {\r
- // XXX - print nasty message...assert?\r
- status = ERROR_INVALID_DATA;\r
- }\r
- continue;\r
- }\r
- // To know we're ok, we need to verify that what we got\r
- // was bigger than GetModuleSize thought it got.\r
- ok = got && (got < size) && !name[got];\r
- size *= 2;\r
- }\r
- if (status && name)\r
- free_alloc_p(&name);\r
- else\r
- *pname = name;\r
- return status;\r
-}\r
-\r
-DWORD\r
-alloc_module_dir_name(\r
- char* module,\r
- char** pname\r
- )\r
-{\r
- DWORD status = alloc_module_file_name(module, pname);\r
- if (!status) {\r
- char* name = *pname;\r
- char* p = name + strlen(name);\r
- while ((p >= name) && (*p != '\\') && (*p != '/')) p--;\r
- if (p < name) {\r
- free_alloc_p(pname);\r
- status = ERROR_INVALID_DATA;\r
- } else {\r
- *p = 0;\r
- }\r
- }\r
- return status;\r
-}\r
-\r
-DWORD\r
-alloc_module_dir_name_with_file(\r
- char* module,\r
- char* file,\r
- char** pname\r
- )\r
-{\r
- DWORD status = alloc_module_dir_name(module, pname);\r
- if (!status) {\r
- char* name = *pname;\r
- size_t name_size = strlen(name);\r
- size_t size = name_size + 1 + strlen(file) + 1;\r
- char* result = (char*)malloc_alloc_p(size);\r
- if (!result) {\r
- status = ERROR_NOT_ENOUGH_MEMORY;\r
- free_alloc_p(pname);\r
- } else {\r
- strcpy(result, name);\r
- result[name_size] = '\\';\r
- strcpy(result + name_size + 1, file);\r
- free_alloc_p(pname);\r
- *pname = result;\r
- }\r
- }\r
- return status;\r
-}\r
-\r
-DWORD alloc_cmdline_2_args(char* prog,\r
- char* arg1,\r
- char* arg2,\r
- char** pname) {\r
- DWORD status = 0;\r
- size_t size = strlen(prog) + strlen(arg1) + strlen(arg2) + 4;\r
- char* result = (char*)malloc_alloc_p(size);\r
- if (!result) {\r
- status = ERROR_NOT_ENOUGH_MEMORY;\r
- } \r
- else {\r
- strcpy(result, prog);\r
- strcat(result, " ");\r
- strcat(result, arg1);\r
- strcat(result, " ");\r
- strcat(result, arg2);\r
- *pname = result;\r
- }\r
- cci_debug_printf("%s made <%s>", __FUNCTION__, result);\r
- return status;\r
- }\r
+/*
+ * $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 <windows.h>
+#include <stdio.h> // for _snprintf
+
+#include "util.h"
+#include "secure.hxx"
+
+extern "C" {
+#include "cci_debugging.h"
+#include "ccutils.h"
+ }
+
+
+
+void* malloc_alloc_p(size_t size) {
+ return malloc(size);
+ }
+
+void free_alloc_p(void *pptr) {
+ void **real_pptr = (void**)pptr;
+ if (*real_pptr) {
+ free(*real_pptr);
+ *real_pptr = 0;
+ }
+ }
+
+extern "C" DWORD alloc_textual_sid(
+ PSID pSid, // binary Sid
+ LPSTR *pTextualSid // buffer for Textual representaion of Sid
+ ) {
+ PSID_IDENTIFIER_AUTHORITY psia;
+ DWORD dwSubAuthorities;
+ DWORD dwSidRev = SID_REVISION;
+ DWORD dwCounter;
+ DWORD dwSidSize;
+
+ *pTextualSid = 0;
+
+ //
+ // test if Sid passed in is valid
+ //
+ if(!IsValidSid(pSid)) return ERROR_INVALID_PARAMETER;
+
+ // obtain SidIdentifierAuthority
+ psia = GetSidIdentifierAuthority(pSid);
+
+ // obtain sidsubauthority count
+ dwSubAuthorities =* GetSidSubAuthorityCount(pSid);
+
+ //
+ // compute buffer length
+ // S-SID_REVISION- + identifierauthority- + subauthorities- + NULL
+ //
+ dwSidSize = (15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);
+ *pTextualSid = (LPSTR)malloc_alloc_p(dwSidSize);
+ if (!*pTextualSid)
+ return GetLastError();
+
+ LPSTR TextualSid = *pTextualSid;
+
+ //
+ // prepare S-SID_REVISION-
+ //
+ wsprintf(TextualSid, TEXT("S-%lu-"), dwSidRev );
+
+ //
+ // prepare SidIdentifierAuthority
+ //
+ if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) )
+ {
+ wsprintf(TextualSid + lstrlen(TextualSid),
+ TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
+ (USHORT)psia->Value[0],
+ (USHORT)psia->Value[1],
+ (USHORT)psia->Value[2],
+ (USHORT)psia->Value[3],
+ (USHORT)psia->Value[4],
+ (USHORT)psia->Value[5]);
+ }
+ else
+ {
+ wsprintf(TextualSid + lstrlen(TextualSid), TEXT("%lu"),
+ (ULONG)(psia->Value[5] ) +
+ (ULONG)(psia->Value[4] << 8) +
+ (ULONG)(psia->Value[3] << 16) +
+ (ULONG)(psia->Value[2] << 24) );
+ }
+
+ //
+ // loop through SidSubAuthorities
+ //
+ for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++)
+ {
+ wsprintf(TextualSid + lstrlen(TextualSid), TEXT("-%lu"),
+ *GetSidSubAuthority(pSid, dwCounter) );
+ }
+ return 0;
+}
+
+DWORD alloc_token_user(HANDLE hToken, PTOKEN_USER *pptu) {
+ DWORD status = 0;
+ DWORD size = 0;
+ *pptu = 0;
+
+ GetTokenInformation(hToken, TokenUser, *pptu, 0, &size);
+ if (size == 0) status = GetLastError();
+
+ if (!status) {
+ if (!(*pptu = (PTOKEN_USER)malloc_alloc_p(size)))
+ status = GetLastError();
+ }
+
+ if (!status) {
+ if (!GetTokenInformation(hToken, TokenUser, *pptu, size, &size))
+ status = GetLastError();
+ }
+
+ if (status && *pptu) {
+ free_alloc_p(pptu);
+ }
+ return status;
+ }
+
+DWORD
+alloc_username(
+ PSID Sid,
+ LPSTR* pname,
+ LPSTR* pdomain = 0
+ )
+{
+ DWORD status = 0;
+ DWORD name_len = 0;
+ DWORD domain_len = 0;
+ SID_NAME_USE snu;
+ LPSTR name = 0;
+ LPSTR domain = 0;
+
+ *pname = 0;
+ if (pdomain) *pdomain = 0;
+
+ LookupAccountSidA(NULL, Sid, 0, &name_len, 0, &domain_len, &snu);
+ if ((name_len == 0) || (domain_len == 0)) status = GetLastError();
+
+ if (!status) {
+ if (!(name = (LPSTR)malloc_alloc_p(name_len))) status = GetLastError();
+ }
+
+ if (!status) {
+ if (!(domain = (LPSTR)malloc_alloc_p(domain_len))) status = GetLastError();
+ }
+
+ if (!status) {
+ if (!LookupAccountSidA(NULL, Sid, name, &name_len, domain, &domain_len, &snu)) status = GetLastError();
+ }
+
+ if (status) {
+ if (name) free_alloc_p(&name);
+ if (domain) free_alloc_p(&domain);
+ }
+ else {
+ if (pdomain) {
+ *pname = name;
+ *pdomain = domain;
+ }
+ else {
+ DWORD size = name_len + domain_len + 1;
+ *pname = (LPSTR)malloc_alloc_p(size);
+ if (!*pname) status = GetLastError();
+ else _snprintf(*pname, size, "%s\\%s", name, domain);
+ }
+ }
+ return status;
+ }
+
+DWORD get_authentication_id(HANDLE hToken, LUID* pAuthId) {
+ TOKEN_STATISTICS ts;
+ DWORD len;
+
+ if (!GetTokenInformation(hToken, TokenStatistics, &ts, sizeof(ts), &len))
+ return GetLastError();
+ *pAuthId = ts.AuthenticationId;
+ return 0;
+ }
+
+DWORD
+alloc_name_9x(
+ LPSTR* pname,
+ LPSTR postfix
+ )
+{
+ char prefix[] = "krbcc";
+ DWORD len = (sizeof(prefix) - 1) + 1 + strlen(postfix) + 1;
+
+ *pname = (LPSTR)malloc_alloc_p(len);
+ if (!*pname) return GetLastError();
+ _snprintf(*pname, len, "%s.%s", prefix, postfix);
+ return 0;
+}
+
+DWORD alloc_name_NT(LPSTR* pname, LPSTR postfix) {
+ DWORD status = 0;
+ HANDLE hToken = 0;
+ LUID auth_id;
+#ifdef _DEBUG
+ PTOKEN_USER ptu = 0;
+ LPSTR name = 0;
+ LPSTR domain = 0;
+ LPSTR sid = 0;
+#endif
+ char prefix[] = "krbcc";
+ // Play it safe and say 3 characters are needed per 8 bits (byte).
+ // Note that 20 characters are needed for a 64-bit number in
+ // decimal (plus one for the string termination.
+ // and include room for sessionId.
+ char lid[3*sizeof(LUID)+1+5];
+ DWORD sessionId;
+ DWORD len = 0;
+
+ *pname = 0;
+
+ status = SecureClient::Token(hToken);
+
+ if (!status) {
+ status = get_authentication_id(hToken, &auth_id);
+ }
+
+ if (!status) {
+ if (!ProcessIdToSessionId(GetCurrentProcessId(), &sessionId))
+ sessionId = 0;
+ }
+
+#ifdef _DEBUG
+ if (!status) {status = alloc_token_user(hToken, &ptu);}
+ if (!status) {status = alloc_username(ptu->User.Sid, &name, &domain);}
+ if (!status) {status = alloc_textual_sid(ptu->User.Sid, &sid);}
+#endif
+
+ if (!status) {
+ _snprintf(lid, sizeof(lid), "%I64u.%u", auth_id, sessionId);
+ lid[sizeof(lid)-1] = 0; // be safe
+
+ len = (sizeof(prefix) - 1) + 1 + strlen(lid) + 1 + strlen(postfix) + 1;
+ *pname = (LPSTR)malloc_alloc_p(len);
+ if (!*pname) status = GetLastError();
+ }
+
+ //
+ // We used to allocate a name of the form:
+ // "prefix.domain.name.sid.lid.postfix" (usually under 80
+ // characters, depending on username). However, XP thought this
+ // was "invalid" (too long?) for some reason.
+ //
+ // Therefore, we now use "prefix.lid.postfix"
+ // and for Terminal server we use "prefix.lid.sessionId.postfix"
+ //
+
+ if (!status) {
+ _snprintf(*pname, len, "%s.%s.%s", prefix, lid, postfix);
+ }
+
+#ifdef _DEBUG
+ if (sid)
+ free_alloc_p(&sid);
+ if (name)
+ free_alloc_p(&name);
+ if (domain)
+ free_alloc_p(&domain);
+ if (ptu)
+ free_alloc_p(&ptu);
+#endif
+ if (hToken && hToken != INVALID_HANDLE_VALUE)
+ CloseHandle(hToken);
+ if (status && *pname)
+ free_alloc_p(pname);
+ return status;
+}
+
+extern "C" DWORD alloc_name(LPSTR* pname, LPSTR postfix, BOOL isNT) {
+ return isNT ? alloc_name_NT(pname, postfix) :
+ alloc_name_9x(pname, postfix);
+ }
+
+extern "C" DWORD alloc_own_security_descriptor_NT(PSECURITY_DESCRIPTOR* ppsd) {
+ DWORD status = 0;
+ HANDLE hToken = 0;
+ PTOKEN_USER ptu = 0;
+ PSID pSid = 0;
+ PACL pAcl = 0;
+ DWORD size = 0;
+ SECURITY_DESCRIPTOR sd;
+
+ *ppsd = 0;
+
+ if (!status) {status = SecureClient::Token(hToken);}
+
+ // Get SID:
+ if (!status) {status = alloc_token_user(hToken, &ptu);}
+
+ if (!status) {
+ size = GetLengthSid(ptu->User.Sid);
+ pSid = (PSID) malloc_alloc_p(size);
+ if (!pSid) status = GetLastError();
+ }
+ if (!status) {
+ if (!CopySid(size, pSid, ptu->User.Sid)) status = GetLastError();
+ }
+
+ if (!status) {
+ // Prepare ACL:
+ size = sizeof(ACL);
+ // Add an ACE:
+ size += sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(pSid);
+ pAcl = (PACL) malloc_alloc_p(size);
+ if (!pAcl) status = GetLastError();
+ }
+
+ if (!status) {
+ if (!InitializeAcl(pAcl, size, ACL_REVISION)) status = GetLastError();
+ }
+
+ if (!status) {
+ if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, pSid)) status = GetLastError();
+ }
+
+ if (!status) {
+ // Prepare SD itself:
+ if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) status = GetLastError();
+ }
+
+ if (!status) {
+ if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) status = GetLastError();
+ }
+
+ if (!status) {
+ if (!SetSecurityDescriptorOwner(&sd, pSid, FALSE)) status = GetLastError();
+ }
+
+ if (!status) {
+ if (!IsValidSecurityDescriptor(&sd)) status = ERROR_INVALID_PARAMETER;
+ }
+
+ if (!status) {
+ // We now have a SD. Let's copy it.
+ {
+ // This should not succeed. Instead it should give us the size.
+ BOOL ok = MakeSelfRelativeSD(&sd, 0, &size);
+ }
+ if (size == 0) status = GetLastError();
+ }
+
+ if (!status) {
+ *ppsd = (PSECURITY_DESCRIPTOR) malloc_alloc_p(size);
+ if (!*ppsd) status = GetLastError();
+ }
+
+ if (!status) {
+ if (!MakeSelfRelativeSD(&sd, *ppsd, &size)) status = GetLastError();
+ }
+
+ if (ptu) free_alloc_p(&ptu);
+ if (pSid) free_alloc_p(&pSid);
+ if (pAcl) free_alloc_p(&pAcl);
+ if (hToken && hToken != INVALID_HANDLE_VALUE) CloseHandle(hToken);
+ if (status && *ppsd) free_alloc_p(ppsd);
+ return status;
+}
+
+DWORD
+alloc_module_file_name(
+ char* module,
+ char** pname
+ )
+{
+ const DWORD max = 8192;
+ DWORD status = 0;
+ DWORD got = 0;
+ DWORD size = 512; // use low number to test...
+ HMODULE h = 0;
+ BOOL ok = FALSE;
+ char* name = 0;
+
+ if (!pname)
+ return ERROR_INVALID_PARAMETER;
+ *pname = 0;
+
+ h = GetModuleHandle(module);
+
+ if (!h) return GetLastError();
+
+ // We assume size < max and size > 0
+ while (!status && !ok) {
+ if (size > max) {
+ // XXX - Assert?
+ status = ERROR_INVALID_DATA;
+ continue;
+ }
+ if (name) free_alloc_p(&name);
+ name = (char*)malloc_alloc_p(size + 1);
+ if (!name) {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ continue;
+ }
+ name[size] = 0;
+ got = GetModuleFileName(h, name, size);
+ if (!got) {
+ status = GetLastError();
+ // sanity check:
+ if (!status) {
+ // XXX - print nasty message...assert?
+ status = ERROR_INVALID_DATA;
+ }
+ continue;
+ }
+ // To know we're ok, we need to verify that what we got
+ // was bigger than GetModuleSize thought it got.
+ ok = got && (got < size) && !name[got];
+ size *= 2;
+ }
+ if (status && name)
+ free_alloc_p(&name);
+ else
+ *pname = name;
+ return status;
+}
+
+DWORD
+alloc_module_dir_name(
+ char* module,
+ char** pname
+ )
+{
+ DWORD status = alloc_module_file_name(module, pname);
+ if (!status) {
+ char* name = *pname;
+ char* p = name + strlen(name);
+ while ((p >= name) && (*p != '\\') && (*p != '/')) p--;
+ if (p < name) {
+ free_alloc_p(pname);
+ status = ERROR_INVALID_DATA;
+ } else {
+ *p = 0;
+ }
+ }
+ return status;
+}
+
+DWORD
+alloc_module_dir_name_with_file(
+ char* module,
+ char* file,
+ char** pname
+ )
+{
+ DWORD status = alloc_module_dir_name(module, pname);
+ if (!status) {
+ char* name = *pname;
+ size_t name_size = strlen(name);
+ size_t size = name_size + 1 + strlen(file) + 1;
+ char* result = (char*)malloc_alloc_p(size);
+ if (!result) {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ free_alloc_p(pname);
+ } else {
+ strcpy(result, name);
+ result[name_size] = '\\';
+ strcpy(result + name_size + 1, file);
+ free_alloc_p(pname);
+ *pname = result;
+ }
+ }
+ return status;
+}
+
+DWORD alloc_cmdline_2_args(char* prog,
+ char* arg1,
+ char* arg2,
+ char** pname) {
+ DWORD status = 0;
+ size_t size = strlen(prog) + strlen(arg1) + strlen(arg2) + 4;
+ char* result = (char*)malloc_alloc_p(size);
+ if (!result) {
+ status = ERROR_NOT_ENOUGH_MEMORY;
+ }
+ else {
+ strcpy(result, prog);
+ strcat(result, " ");
+ strcat(result, arg1);
+ strcat(result, " ");
+ strcat(result, arg2);
+ *pname = result;
+ }
+ cci_debug_printf("%s made <%s>", __FUNCTION__, result);
+ return status;
+ }
-/*\r
- * $Header$\r
- *\r
- * Copyright 2008 Massachusetts Institute of Technology.\r
- * All Rights Reserved.\r
- *\r
- * Export of this software from the United States of America may\r
- * require a specific license from the United States Government.\r
- * It is the responsibility of any person or organization contemplating\r
- * export to obtain such a license before exporting.\r
- *\r
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and\r
- * distribute this software and its documentation for any purpose and\r
- * without fee is hereby granted, provided that the above copyright\r
- * notice appear in all copies and that both that copyright notice and\r
- * this permission notice appear in supporting documentation, and that\r
- * the name of M.I.T. not be used in advertising or publicity pertaining\r
- * to distribution of the software without specific, written prior\r
- * permission. Furthermore if you modify this software you must label\r
- * your software as modified software and not distribute it in such a\r
- * fashion that it might be confused with the original M.I.T. software.\r
- * M.I.T. makes no representations about the suitability of\r
- * this software for any purpose. It is provided "as is" without express\r
- * or implied warranty.\r
- */\r
-\r
-[implicit_handle(handle_t ccs_reply_IfHandle)]\r
-\r
-interface ccs_reply {\r
- [async] ccapi_listen();\r
- }\r
+/*
+ * $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.
+ */
+
+[implicit_handle(handle_t ccs_reply_IfHandle)]
+
+interface ccs_reply {
+ [async] ccapi_listen();
+ }
-/*\r
- * $Header$\r
- *\r
- * Copyright 2008 Massachusetts Institute of Technology.\r
- * All Rights Reserved.\r
- *\r
- * Export of this software from the United States of America may\r
- * require a specific license from the United States Government.\r
- * It is the responsibility of any person or organization contemplating\r
- * export to obtain such a license before exporting.\r
- *\r
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and\r
- * distribute this software and its documentation for any purpose and\r
- * without fee is hereby granted, provided that the above copyright\r
- * notice appear in all copies and that both that copyright notice and\r
- * this permission notice appear in supporting documentation, and that\r
- * the name of M.I.T. not be used in advertising or publicity pertaining\r
- * to distribution of the software without specific, written prior\r
- * permission. Furthermore if you modify this software you must label\r
- * your software as modified software and not distribute it in such a\r
- * fashion that it might be confused with the original M.I.T. software.\r
- * M.I.T. makes no representations about the suitability of\r
- * this software for any purpose. It is provided "as is" without express\r
- * or implied warranty.\r
- */\r
-\r
-[ uuid (6E3B5060-CA46-1067-B31A-00DD010662DA),\r
- version(1.0),\r
- pointer_default(unique)\r
-]\r
-\r
-/* This interface sends a cci_stream via rpc.\r
- */\r
-\r
-interface ccs_reply {\r
- const long HSIZE = sizeof(void*);\r
-\r
-/* The reply from the server to a request from the client: */\r
-void ccs_rpc_request_reply(\r
- [in] const long rpcmsg, /* Message type */\r
- [in, size_is(HSIZE)] const char tsphandle[],\r
- [in, string] const char* uuid,\r
- [in] const long srvStartTime, /* Server Start Time */\r
- [in] const long cbIn, /* Length of buffer */\r
- [in, size_is(cbIn)] const unsigned char chIn[], /* Data buffer */\r
- [out] long* status ); /* Return code */\r
-\r
-void ccs_rpc_connect_reply(\r
- [in] const long rpcmsg, /* Message type */\r
- [in, size_is(HSIZE)] const char tsphandle[],\r
- [in, string] const char* uuid,\r
- [in] const long srvStartTime, /* Server Start Time */\r
- [out] long* status ); /* Return code */\r
-\r
-void ccapi_listen(\r
- handle_t hBinding, \r
- [in] const long rpcmsg, /* Message type */\r
- [out] long* status ); /* Return code */\r
-\r
- }\r
+/*
+ * $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.
+ */
+
+[ uuid (6E3B5060-CA46-1067-B31A-00DD010662DA),
+ version(1.0),
+ pointer_default(unique)
+]
+
+/* This interface sends a cci_stream via rpc.
+ */
+
+interface ccs_reply {
+ const long HSIZE = sizeof(void*);
+
+/* The reply from the server to a request from the client: */
+void ccs_rpc_request_reply(
+ [in] const long rpcmsg, /* Message type */
+ [in, size_is(HSIZE)] const char tsphandle[],
+ [in, string] const char* uuid,
+ [in] const long srvStartTime, /* Server Start Time */
+ [in] const long cbIn, /* Length of buffer */
+ [in, size_is(cbIn)] const unsigned char chIn[], /* Data buffer */
+ [out] long* status ); /* Return code */
+
+void ccs_rpc_connect_reply(
+ [in] const long rpcmsg, /* Message type */
+ [in, size_is(HSIZE)] const char tsphandle[],
+ [in, string] const char* uuid,
+ [in] const long srvStartTime, /* Server Start Time */
+ [out] long* status ); /* Return code */
+
+void ccapi_listen(
+ handle_t hBinding,
+ [in] const long rpcmsg, /* Message type */
+ [out] long* status ); /* Return code */
+
+ }
-/*\r
- * $Header$\r
- *\r
- * Copyright 2008 Massachusetts Institute of Technology.\r
- * All Rights Reserved.\r
- *\r
- * Export of this software from the United States of America may\r
- * require a specific license from the United States Government.\r
- * It is the responsibility of any person or organization contemplating\r
- * export to obtain such a license before exporting.\r
- *\r
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and\r
- * distribute this software and its documentation for any purpose and\r
- * without fee is hereby granted, provided that the above copyright\r
- * notice appear in all copies and that both that copyright notice and\r
- * this permission notice appear in supporting documentation, and that\r
- * the name of M.I.T. not be used in advertising or publicity pertaining\r
- * to distribution of the software without specific, written prior\r
- * permission. Furthermore if you modify this software you must label\r
- * your software as modified software and not distribute it in such a\r
- * fashion that it might be confused with the original M.I.T. software.\r
- * M.I.T. makes no representations about the suitability of\r
- * this software for any purpose. It is provided "as is" without express\r
- * or implied warranty.\r
- */\r
-\r
-[implicit_handle(handle_t ccs_request_IfHandle)]\r
-interface ccs_request\r
-{\r
-\r
-}\r
+/*
+ * $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.
+ */
+
+[implicit_handle(handle_t ccs_request_IfHandle)]
+interface ccs_request
+{
+
+}
-/*\r
- * $Header$\r
- *\r
- * Copyright 2008 Massachusetts Institute of Technology.\r
- * All Rights Reserved.\r
- *\r
- * Export of this software from the United States of America may\r
- * require a specific license from the United States Government.\r
- * It is the responsibility of any person or organization contemplating\r
- * export to obtain such a license before exporting.\r
- *\r
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and\r
- * distribute this software and its documentation for any purpose and\r
- * without fee is hereby granted, provided that the above copyright\r
- * notice appear in all copies and that both that copyright notice and\r
- * this permission notice appear in supporting documentation, and that\r
- * the name of M.I.T. not be used in advertising or publicity pertaining\r
- * to distribution of the software without specific, written prior\r
- * permission. Furthermore if you modify this software you must label\r
- * your software as modified software and not distribute it in such a\r
- * fashion that it might be confused with the original M.I.T. software.\r
- * M.I.T. makes no representations about the suitability of\r
- * this software for any purpose. It is provided "as is" without express\r
- * or implied warranty.\r
- */\r
-\r
-[ uuid (906B0CE0-C70B-1067-B317-00DD010662DA),\r
- version(1.0),\r
- pointer_default(unique)\r
-]\r
-\r
-interface ccs_request {\r
-\r
-typedef char CC_CHAR;\r
-typedef unsigned char CC_UCHAR;\r
-typedef int CC_INT32;\r
-typedef unsigned int CC_UINT32;\r
-\r
-const long HSIZE = sizeof(void*);\r
-\r
-void ccs_rpc_request(\r
- [in] const long rpcmsg, /* Message type */\r
- [in, size_is(HSIZE)] const char tsphandle[],\r
- [in, string] const char* pszUUID, /* Requestor's UUID */\r
- [in] const long lenRequest, /* Length of buffer */\r
- [in, size_is(lenRequest)] const char* pszRequest, /* Data buffer */\r
- [in] const long serverStartTime,/* Which server session we're talking to */\r
- [out] long* status ); /* Return code */\r
-\r
-void ccs_rpc_connect(\r
- [in] const long rpcmsg, /* Message type */\r
- [in, size_is(HSIZE)] const char tsphandle[],\r
- [in, string] const char* pszUUID, /* Requestor's UUID */\r
- [out] long* status ); /* Return code */\r
-\r
-CC_UINT32 ccs_authenticate(\r
- [in, string] const CC_CHAR* name );\r
-}\r
+/*
+ * $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.
+ */
+
+[ uuid (906B0CE0-C70B-1067-B317-00DD010662DA),
+ version(1.0),
+ pointer_default(unique)
+]
+
+interface ccs_request {
+
+typedef char CC_CHAR;
+typedef unsigned char CC_UCHAR;
+typedef int CC_INT32;
+typedef unsigned int CC_UINT32;
+
+const long HSIZE = sizeof(void*);
+
+void ccs_rpc_request(
+ [in] const long rpcmsg, /* Message type */
+ [in, size_is(HSIZE)] const char tsphandle[],
+ [in, string] const char* pszUUID, /* Requestor's UUID */
+ [in] const long lenRequest, /* Length of buffer */
+ [in, size_is(lenRequest)] const char* pszRequest, /* Data buffer */
+ [in] const long serverStartTime,/* Which server session we're talking to */
+ [out] long* status ); /* Return code */
+
+void ccs_rpc_connect(
+ [in] const long rpcmsg, /* Message type */
+ [in, size_is(HSIZE)] const char tsphandle[],
+ [in, string] const char* pszUUID, /* Requestor's UUID */
+ [out] long* status ); /* Return code */
+
+CC_UINT32 ccs_authenticate(
+ [in, string] const CC_CHAR* name );
+}
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\r
-<html xmlns="http://www.w3.org/1999/xhtml">\r
-<head>\r
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />\r
-<title>Windows CCAPI RPC design</title>\r
-<style type="text/css">\r
-<!--\r
-.style2 {color: 0}\r
-.style3 {font-family: "Courier New", Courier, monospace}\r
-.style5 {color: #CC3300}\r
-.style6 {color: #999999}\r
-.style7 {color: #000099}\r
--->\r
-</style>\r
-</head>\r
-\r
-<body>\r
-<h2 class="style5">Proposed RPC design for Windows CCAPI clients and server</h2>\r
-<p>The proposal is for a single user; the solution is replicated for each user logged onto the PC.</p>\r
-<h2>Conventions & clarifications </h2>\r
-<p>"Client" and "server" refer to the CCAPI client and server. </p>\r
-<p>The CCAPI client acts as both an RPC client and RPC server and the CCAPI server acts as both an RPC client and RPC server. </p>\r
-<ul>\r
- <li class="style2">The RPC call from the CCAPI client to the CCAPI server is called the "request." In this mode, the CCAPI client is the RPC client and the CCAPI server is the RPC server.</li>\r
- <li class="style2">The RPC call from the CCAPI server to the CCAPI client is called the "reply." In this mode, the CCAPI client is the RPC server and the CCAPI server is the RPC client. </li>\r
-</ul>\r
-<p>The Windows username is referred to below as "<USER>." </p>\r
-<p>The Windows Logon Security Identifier is referred to as "<LSID>." </p>\r
-<p><UUID> means a thread-specific UUID.</p>\r
-<p><SST> means <strong>s</strong>erver <strong>s</strong>tart <strong>t</strong>ime, a time_t. </p>\r
-<p>A description of client and server authentication has not been added yet.</p>\r
-<h2>Design Requirements </h2>\r
-<ul>\r
- <li>The server's OS-independent code is single threaded, because it must operate on platforms that do not allow multiple threads. </li>\r
- <li>The client and server must be able to maintain connections, where state is maintained between individual messages.</li>\r
- <li>Individual messages must be handled in a single threaded server. </li>\r
- <li>The server must be able to detect when a client dies, so that any connection state can be cleaned up. </li>\r
-</ul>\r
-<h2>Design</h2>\r
-<p>The server and each client create an RPC endpoint. The server's endpoint is CCS_<LSID> and the client's endpoint is CCAPI_<UUID>, where each client geta a UUID. </p>\r
-<p>On Windows, the server's ccs_pipe_t type is a char* and is set to the client UUID.</p>\r
-<h3>How is the request handled in the server and the reply sent to the client? </h3>\r
-<p>One straightforward way is for the reply to be the returned data in the request RPC call (an [out] parameter). That is, data passed from the RPC server to the RPC client. The request handler calls <span class="style3">ccs_server_handle_request</span>. Eventually, the server code calls <span class="style3">ccs_os_server_send_reply, </span>which saves the reply somewhere. When the server eventually returns to the request handler, the handler returns the saved reply to the client.</p>\r
-<p>But this doesn't work. If two clients A and B ask for the same lock, A will acquire the lock and B will have to wait. But if the single threaded server waits for B's lock, it will never handle A's unlock message. Therefore the server must return to B's request handler and <em>not </em>send a reply to B. So this method will not work. </p>\r
-<p>Instead, there are listener and worker threads in Windows-specific code. </p>\r
-<p>The client's <span class="style3">cci_os_ipc </span>function waits for <span class="style3">ccs_reply</span>. The client sends the request, including <em>it's UUID, </em>from which the server can construct the endpoint on which to call <span class="style3">ccs_reply</span>. </p>\r
-<p>The server's listener thread listens for RPC requests. The request handler puts each request/<em>reply</em> endpoint in a queue and returns to the client.</p>\r
-<p>The server's worker thread removes items from the queue, calls <span class="style3">ccs_server_handle_request</span>. <span class="style3">ccs_server_handle_request</span> takes both the request data and the client UUID . Eventually <span class="style3">ccs_os_server_send_reply</span> is called, with the reply data and client UUID in the reply_pipe. <span class="style3">ccs_os_server_send_reply</span> calls <span class="style3">ccs_reply </span>on the client's endpoint, which sends the reply to the client. </p>\r
-<p>Is there any security issue with the client listening for RPC calls from the server?</p>\r
-<h3>Connections</h3>\r
-<p>If the client wants state to be maintained on the server, the client creates a connection. When the connection is closed, the server cleans up any state associated with the connection. </p>\r
-<p>Any given thread in an application process could want to create a connection. When cci_ipc_thread_init is called, the connection thread-local variables are initialized. New connections are created when cci_os_ipc() (via _cci_ipc_send) is called and no connection was previously established. Basically we lazily establish connections so the client doesn't talk to the server until it has to.</p>\r
-<h3>Detecting client exit</h3>\r
-<p>The server must be able to detect when clients disappear, so the server can free any resources that had been held for the client. </p>\r
-<p>The Windows RPC API does not appear to provide a notification for an endpoint disappearing. It does provide a way to ask if an endpoint is listening. This is useful for polling, but we want a better performing solution than that. </p>\r
-<p>The client has an <em>isAlive </em>function on its endpoint. </p>\r
-<p>To detect the client disappearing without using polling, the server makes an asynchronous call to the <em>isAlive </em>function on the client's endpoint. The <em>isAlive </em>function never returns. When the client exits for any reason, it's <em></em>endpoint will be closed and the server's function call will return an error. The asynchronous call on the server means no additional threads are used. </p>\r
-<p>Windows provides a number of notification methods to signal I/O completion. Among them are I/O completion ports and callback functions. I chose callback functions because they appear to consume fewer resources. </p>\r
-<h3>RPC Endpoint / Function summary</h3>\r
-<ul>\r
- <li>The server creates one CCS_<LSID> endpoint to listen for connection requests and client requests. \r
- It has the functions\r
- <ul>\r
- <li>ccs_rpc_connect(msgtype, UUIDlen, <UUID>, status)</li>\r
- <li>ccs_rpc_request(msgtype, UUIDlen, <UUID>, msglen, msg, SST, status) called by client. NB: The windows server sets the <span class="style3">in_client_pipe </span>to the <span class="style3">in_reply_pipe</span>.<br />\r
- </li>\r
- </ul>\r
- </li>\r
- <li>Each client thread creates a CCAPI_<UUID> endpoint. It has the functions\r
- <ul>\r
- <li>isAlive [function never returns.] </li>\r
- <li>ccs_rpc_request_reply(msgtype, SST, replylen, reply, status)</li>\r
- <li>ccs_rpc_connect_reply(msgtype, SST, status</li>\r
- </ul>\r
- </li>\r
-</ul>\r
-<h2>Windows-specific implementation details </h2>\r
-<h3>Client CCAPI library initialization:</h3>\r
-<p>This code runs when the CCAPI DLL is loaded. </p>\r
-<ul>\r
- <li>?</li>\r
-</ul>\r
-<h3>Client initialization: </h3>\r
-<p>This code runs when cci_os_ipc_thread_init is called: </p>\r
-<ul>\r
- <li>Generate <UUID> and save in thread-specific storage. This serves as the client ID / ccs_pipe_t. </li>\r
- <li>Create client endpoint.</li>\r
- <li>Listen on client <em></em>endpoint.</li>\r
- <li>Create canonical server connection endpoint from the <LSID>, which the client and server should have in common. </li>\r
- <li>Test if server is listening to the CCS_<LSID> endpoint.\r
- <ul>\r
- <li>If not, quit. (! Start it?) </li>\r
- </ul>\r
- </li>\r
- <li>Call ccs_connect(<UUID>) on the CCS_<LSID> endpoint.</li>\r
- <li>Save SST in thread-specific storage. </li>\r
-</ul>\r
-<h3>Server initialization:</h3>\r
-<p class="style6">[old]</p>\r
-<ul>\r
- <li class="style6">Server is initialized by client starting a new process. There should be only one server process per Windows username. </li>\r
-</ul>\r
-<p class="style7">[new]</p>\r
-<ul>\r
- <li class="style7">Server is started by kfwlogon (as is done currently). </li>\r
- <li>Capture <strong>s</strong>erver <strong>s</strong>tart <strong>t</strong>ime (SST). </li>\r
- <li>Start listener thread, create listener endpoint, listen on CCS_<LSID> endpoint. </li>\r
-</ul>\r
-<h3>Establishing a connection: </h3>\r
-<ul>\r
- <li>Client calls ccs_connect(<UUID>) on server's CCS_<LSID> endpoint.</li>\r
- <li>Client gets back and stores SST in thread-specific storage.</li>\r
- <li>If new connection, server ...\r
- <ul>\r
- <li>adds connection to connection table</li>\r
- <li>calls isAlive on CCAPI_<UUID>.\r
- <ul>\r
- <li>NB: isAlive never returns. </li>\r
- </ul>\r
- </li>\r
- </ul>\r
- </li>\r
-</ul>\r
-<h3>Client request:</h3>\r
-<p>The server's reply to the client's request is not synchronous.</p>\r
-<ul>\r
- <li>Client calls ccs_rpc_request(msglen, msg, msgtype, UUIDlen, <UUID>, SST, status) on server's endpoint.</li>\r
- <li>Server listen thread receives message, queues request.</li>\r
- <li>Server worker thread dequeues request, processes, calls ccs_rpc_reply(replylen, reply, msgtype, status) on CCAPI_<UUID>.</li>\r
- <li>Server checks SST. If server's SST is different, it means server has restarted since client created connection. </li>\r
- <li>Client receives reply. </li>\r
-</ul>\r
-<h3>Detecting client exit</h3>\r
-<ul>\r
- <li>When connection created, client created an endpoint.</li>\r
- <li>Server calls isAlive on client's endpoint. </li>\r
- <li>When isAlive returns, the server's notification callback will be called. Call back routine queues a DISCONNECT pseudo-message. When the server's worker thread handles the DISCONNECT, it will release connection resources.</li>\r
-</ul>\r
-<h3>Detecting server exit </h3>\r
-<ul>\r
- <li>Client's call to ccs_rpc_request will return an error if the server has gone away. </li>\r
-</ul>\r
-<p> </p>\r
-<p>------<br />\r
- Stop: <br />\r
-Start: </p>\r
-</body>\r
-</html>\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Windows CCAPI RPC design</title>
+<style type="text/css">
+<!--
+.style2 {color: 0}
+.style3 {font-family: "Courier New", Courier, monospace}
+.style5 {color: #CC3300}
+.style6 {color: #999999}
+.style7 {color: #000099}
+-->
+</style>
+</head>
+
+<body>
+<h2 class="style5">Proposed RPC design for Windows CCAPI clients and server</h2>
+<p>The proposal is for a single user; the solution is replicated for each user logged onto the PC.</p>
+<h2>Conventions & clarifications </h2>
+<p>"Client" and "server" refer to the CCAPI client and server. </p>
+<p>The CCAPI client acts as both an RPC client and RPC server and the CCAPI server acts as both an RPC client and RPC server. </p>
+<ul>
+ <li class="style2">The RPC call from the CCAPI client to the CCAPI server is called the "request." In this mode, the CCAPI client is the RPC client and the CCAPI server is the RPC server.</li>
+ <li class="style2">The RPC call from the CCAPI server to the CCAPI client is called the "reply." In this mode, the CCAPI client is the RPC server and the CCAPI server is the RPC client. </li>
+</ul>
+<p>The Windows username is referred to below as "<USER>." </p>
+<p>The Windows Logon Security Identifier is referred to as "<LSID>." </p>
+<p><UUID> means a thread-specific UUID.</p>
+<p><SST> means <strong>s</strong>erver <strong>s</strong>tart <strong>t</strong>ime, a time_t. </p>
+<p>A description of client and server authentication has not been added yet.</p>
+<h2>Design Requirements </h2>
+<ul>
+ <li>The server's OS-independent code is single threaded, because it must operate on platforms that do not allow multiple threads. </li>
+ <li>The client and server must be able to maintain connections, where state is maintained between individual messages.</li>
+ <li>Individual messages must be handled in a single threaded server. </li>
+ <li>The server must be able to detect when a client dies, so that any connection state can be cleaned up. </li>
+</ul>
+<h2>Design</h2>
+<p>The server and each client create an RPC endpoint. The server's endpoint is CCS_<LSID> and the client's endpoint is CCAPI_<UUID>, where each client geta a UUID. </p>
+<p>On Windows, the server's ccs_pipe_t type is a char* and is set to the client UUID.</p>
+<h3>How is the request handled in the server and the reply sent to the client? </h3>
+<p>One straightforward way is for the reply to be the returned data in the request RPC call (an [out] parameter). That is, data passed from the RPC server to the RPC client. The request handler calls <span class="style3">ccs_server_handle_request</span>. Eventually, the server code calls <span class="style3">ccs_os_server_send_reply, </span>which saves the reply somewhere. When the server eventually returns to the request handler, the handler returns the saved reply to the client.</p>
+<p>But this doesn't work. If two clients A and B ask for the same lock, A will acquire the lock and B will have to wait. But if the single threaded server waits for B's lock, it will never handle A's unlock message. Therefore the server must return to B's request handler and <em>not </em>send a reply to B. So this method will not work. </p>
+<p>Instead, there are listener and worker threads in Windows-specific code. </p>
+<p>The client's <span class="style3">cci_os_ipc </span>function waits for <span class="style3">ccs_reply</span>. The client sends the request, including <em>it's UUID, </em>from which the server can construct the endpoint on which to call <span class="style3">ccs_reply</span>. </p>
+<p>The server's listener thread listens for RPC requests. The request handler puts each request/<em>reply</em> endpoint in a queue and returns to the client.</p>
+<p>The server's worker thread removes items from the queue, calls <span class="style3">ccs_server_handle_request</span>. <span class="style3">ccs_server_handle_request</span> takes both the request data and the client UUID . Eventually <span class="style3">ccs_os_server_send_reply</span> is called, with the reply data and client UUID in the reply_pipe. <span class="style3">ccs_os_server_send_reply</span> calls <span class="style3">ccs_reply </span>on the client's endpoint, which sends the reply to the client. </p>
+<p>Is there any security issue with the client listening for RPC calls from the server?</p>
+<h3>Connections</h3>
+<p>If the client wants state to be maintained on the server, the client creates a connection. When the connection is closed, the server cleans up any state associated with the connection. </p>
+<p>Any given thread in an application process could want to create a connection. When cci_ipc_thread_init is called, the connection thread-local variables are initialized. New connections are created when cci_os_ipc() (via _cci_ipc_send) is called and no connection was previously established. Basically we lazily establish connections so the client doesn't talk to the server until it has to.</p>
+<h3>Detecting client exit</h3>
+<p>The server must be able to detect when clients disappear, so the server can free any resources that had been held for the client. </p>
+<p>The Windows RPC API does not appear to provide a notification for an endpoint disappearing. It does provide a way to ask if an endpoint is listening. This is useful for polling, but we want a better performing solution than that. </p>
+<p>The client has an <em>isAlive </em>function on its endpoint. </p>
+<p>To detect the client disappearing without using polling, the server makes an asynchronous call to the <em>isAlive </em>function on the client's endpoint. The <em>isAlive </em>function never returns. When the client exits for any reason, it's <em></em>endpoint will be closed and the server's function call will return an error. The asynchronous call on the server means no additional threads are used. </p>
+<p>Windows provides a number of notification methods to signal I/O completion. Among them are I/O completion ports and callback functions. I chose callback functions because they appear to consume fewer resources. </p>
+<h3>RPC Endpoint / Function summary</h3>
+<ul>
+ <li>The server creates one CCS_<LSID> endpoint to listen for connection requests and client requests.
+ It has the functions
+ <ul>
+ <li>ccs_rpc_connect(msgtype, UUIDlen, <UUID>, status)</li>
+ <li>ccs_rpc_request(msgtype, UUIDlen, <UUID>, msglen, msg, SST, status) called by client. NB: The windows server sets the <span class="style3">in_client_pipe </span>to the <span class="style3">in_reply_pipe</span>.<br />
+ </li>
+ </ul>
+ </li>
+ <li>Each client thread creates a CCAPI_<UUID> endpoint. It has the functions
+ <ul>
+ <li>isAlive [function never returns.] </li>
+ <li>ccs_rpc_request_reply(msgtype, SST, replylen, reply, status)</li>
+ <li>ccs_rpc_connect_reply(msgtype, SST, status</li>
+ </ul>
+ </li>
+</ul>
+<h2>Windows-specific implementation details </h2>
+<h3>Client CCAPI library initialization:</h3>
+<p>This code runs when the CCAPI DLL is loaded. </p>
+<ul>
+ <li>?</li>
+</ul>
+<h3>Client initialization: </h3>
+<p>This code runs when cci_os_ipc_thread_init is called: </p>
+<ul>
+ <li>Generate <UUID> and save in thread-specific storage. This serves as the client ID / ccs_pipe_t. </li>
+ <li>Create client endpoint.</li>
+ <li>Listen on client <em></em>endpoint.</li>
+ <li>Create canonical server connection endpoint from the <LSID>, which the client and server should have in common. </li>
+ <li>Test if server is listening to the CCS_<LSID> endpoint.
+ <ul>
+ <li>If not, quit. (! Start it?) </li>
+ </ul>
+ </li>
+ <li>Call ccs_connect(<UUID>) on the CCS_<LSID> endpoint.</li>
+ <li>Save SST in thread-specific storage. </li>
+</ul>
+<h3>Server initialization:</h3>
+<p class="style6">[old]</p>
+<ul>
+ <li class="style6">Server is initialized by client starting a new process. There should be only one server process per Windows username. </li>
+</ul>
+<p class="style7">[new]</p>
+<ul>
+ <li class="style7">Server is started by kfwlogon (as is done currently). </li>
+ <li>Capture <strong>s</strong>erver <strong>s</strong>tart <strong>t</strong>ime (SST). </li>
+ <li>Start listener thread, create listener endpoint, listen on CCS_<LSID> endpoint. </li>
+</ul>
+<h3>Establishing a connection: </h3>
+<ul>
+ <li>Client calls ccs_connect(<UUID>) on server's CCS_<LSID> endpoint.</li>
+ <li>Client gets back and stores SST in thread-specific storage.</li>
+ <li>If new connection, server ...
+ <ul>
+ <li>adds connection to connection table</li>
+ <li>calls isAlive on CCAPI_<UUID>.
+ <ul>
+ <li>NB: isAlive never returns. </li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+</ul>
+<h3>Client request:</h3>
+<p>The server's reply to the client's request is not synchronous.</p>
+<ul>
+ <li>Client calls ccs_rpc_request(msglen, msg, msgtype, UUIDlen, <UUID>, SST, status) on server's endpoint.</li>
+ <li>Server listen thread receives message, queues request.</li>
+ <li>Server worker thread dequeues request, processes, calls ccs_rpc_reply(replylen, reply, msgtype, status) on CCAPI_<UUID>.</li>
+ <li>Server checks SST. If server's SST is different, it means server has restarted since client created connection. </li>
+ <li>Client receives reply. </li>
+</ul>
+<h3>Detecting client exit</h3>
+<ul>
+ <li>When connection created, client created an endpoint.</li>
+ <li>Server calls isAlive on client's endpoint. </li>
+ <li>When isAlive returns, the server's notification callback will be called. Call back routine queues a DISCONNECT pseudo-message. When the server's worker thread handles the DISCONNECT, it will release connection resources.</li>
+</ul>
+<h3>Detecting server exit </h3>
+<ul>
+ <li>Client's call to ccs_rpc_request will return an error if the server has gone away. </li>
+</ul>
+<p> </p>
+<p>------<br />
+ Stop: <br />
+Start: </p>
+</body>
+</html>
-/*\r
- * $Header$\r
- *\r
- * Copyright 2008 Massachusetts Institute of Technology.\r
- * All Rights Reserved.\r
- *\r
- * Export of this software from the United States of America may\r
- * require a specific license from the United States Government.\r
- * It is the responsibility of any person or organization contemplating\r
- * export to obtain such a license before exporting.\r
- *\r
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and\r
- * distribute this software and its documentation for any purpose and\r
- * without fee is hereby granted, provided that the above copyright\r
- * notice appear in all copies and that both that copyright notice and\r
- * this permission notice appear in supporting documentation, and that\r
- * the name of M.I.T. not be used in advertising or publicity pertaining\r
- * to distribution of the software without specific, written prior\r
- * permission. Furthermore if you modify this software you must label\r
- * your software as modified software and not distribute it in such a\r
- * fashion that it might be confused with the original M.I.T. software.\r
- * M.I.T. makes no representations about the suitability of\r
- * this software for any purpose. It is provided "as is" without express\r
- * or implied warranty.\r
- */\r
-\r
-#include "stdio.h" // KPKDBG\r
-\r
-#include "ccs_request.h"\r
-\r
-#include "ccapi.h"\r
-#include "util.h"\r
-\r
-extern "C" {\r
-#include "cci_debugging.h"\r
-#include "tls.h" // KPKDBG\r
- }\r
-\r
-#include "client.h"\r
-#include "init.hxx"\r
-#include "name.h"\r
-#include "secure.hxx"\r
-\r
-#define SECONDS_TO_WAIT 10\r
-\r
-#define STARTUP "CLIENT STARTUP: "\r
-#define DISCONNECT "CLIENT DISCONNECT: "\r
-\r
-bool Client::s_init = false;\r
-CcOsLock Client::sLock;\r
-\r
-static DWORD bind_client(char* ep OPTIONAL, Init::InitInfo& info, LPSTR* endpoint) {\r
- DWORD status = 0;\r
- unsigned char * pszStringBinding = NULL;\r
-\r
- if (!ep) {\r
- status = alloc_name(endpoint, "ep", isNT());\r
- } \r
- else {\r
- *endpoint = ep;\r
- }\r
-\r
- if (!status) {\r
- /* Use a convenience function to concatenate the elements of */\r
- /* the string binding into the proper sequence. */\r
- status = RpcStringBindingCompose(0, // uuid\r
- (unsigned char*)"ncalrpc", // protseq\r
- 0, // address\r
- (unsigned char*)(*endpoint), // endpoint\r
- 0, // options\r
- &pszStringBinding);\r
- cci_check_error(status);\r
- }\r
- \r
- if (!status) {\r
- /* Set the binding handle that will be used to bind to the server. */\r
- status = RpcBindingFromStringBinding(pszStringBinding, &ccs_request_IfHandle);\r
- cci_check_error(status);\r
- }\r
-\r
- if (!status) {\r
- // Win9x might call RpcBindingSetAuthInfo (not Ex), but it does not\r
- // quite work on Win9x...\r
- if (isNT()) {\r
- RPC_SECURITY_QOS qos;\r
- qos.Version = RPC_C_SECURITY_QOS_VERSION;\r
- qos.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT;\r
- qos.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;\r
- qos.ImpersonationType = RPC_C_IMP_LEVEL_IDENTIFY;\r
-\r
- status = info.fRpcBindingSetAuthInfoEx(ccs_request_IfHandle,\r
- 0, // principal\r
- RPC_C_AUTHN_LEVEL_CONNECT,\r
- RPC_C_AUTHN_WINNT,\r
- 0, // current address space\r
- RPC_C_AUTHZ_NAME,\r
- &qos);\r
- cci_check_error(status);\r
- }\r
- }\r
-\r
- if (pszStringBinding) {\r
- DWORD status = RpcStringFree(&pszStringBinding); \r
- cci_check_error(status);\r
- }\r
- return cci_check_error(status);\r
- }\r
-\r
-DWORD find_server(Init::InitInfo& info, LPSTR endpoint) {\r
- DWORD status = 0;\r
- LPSTR event_name = 0;\r
- HANDLE hEvent = 0;\r
- SECURITY_ATTRIBUTES sa = { 0 };\r
- PSECURITY_ATTRIBUTES psa = 0;\r
- STARTUPINFO si = { 0 };\r
- PROCESS_INFORMATION pi = { 0 };\r
- char* szExe = 0;\r
- char* szDir = 0;\r
- BOOL bRes = FALSE;\r
- char* cmdline = NULL;\r
-#if 0\r
- HANDLE hToken = 0;\r
-#endif\r
-\r
- psa = isNT() ? &sa : 0;\r
-\r
-// cci_debug_printf("%s Looking for server; ccs_request_IfHandle:0x%X", __FUNCTION__, ccs_request_IfHandle);\r
- status = cci_check_error(RpcMgmtIsServerListening(ccs_request_IfHandle));\r
- if (status == RPC_S_NOT_LISTENING) {\r
-// cci_debug_printf(" Server *NOT* found!");\r
- si.cb = sizeof(si);\r
-\r
- status = alloc_module_dir_name(CCAPI_DLL, &szDir);\r
-\r
- if (!status) {\r
- status = alloc_module_dir_name_with_file(CCAPI_DLL, CCAPI_EXE, &szExe);\r
- }\r
-\r
- if (!status) {\r
- status = alloc_name(&event_name, "startup", isNT());\r
- cci_check_error(status);\r
- }\r
-\r
- if (!status) {\r
- if (isNT()) {\r
- sa.nLength = sizeof(sa);\r
- status = alloc_own_security_descriptor_NT(&sa.lpSecurityDescriptor);\r
- cci_check_error(status);\r
- }\r
- }\r
-\r
- if (!status) {\r
- hEvent = CreateEvent(psa, FALSE, FALSE, event_name);\r
- cci_debug_printf(" CreateEvent(... %s) returned hEvent 0x%X", event_name, hEvent);\r
- if (!hEvent) status = GetLastError();\r
- }\r
-\r
- if (!status) {\r
-\r
-#if 0\r
- if (SecureClient::IsImp()) {\r
- cci_debug_printf(STARTUP "Token is impersonation token"));\r
- SecureClient::DuplicateImpAsPrimary(hToken);\r
- } \r
- else {\r
- cci_debug_printf(STARTUP "Token is NOT impersonation token"));\r
- }\r
-#endif\r
-\r
-#if 0\r
- if (hToken)\r
- bRes = CreateProcessAsUser(hToken,\r
- szExe, // app name\r
- NULL, // cmd line\r
- psa, // SA\r
- psa, // SA\r
- FALSE, \r
- CREATE_NEW_PROCESS_GROUP | \r
- //CREATE_NEW_CONSOLE |\r
- NORMAL_PRIORITY_CLASS |\r
- // CREATE_NO_WINDOW |\r
- DETACHED_PROCESS |\r
- 0\r
- ,\r
- NULL, // environment\r
- szDir, // current dir\r
- &si,\r
- &pi);\r
- else\r
-#endif\r
- alloc_cmdline_2_args(szExe, endpoint, "-D", &cmdline);\r
- bRes = CreateProcess( szExe, // app name\r
- NULL, //cmdline, // cmd line is <server endpoint -[DC]>\r
- psa, // SA\r
- psa, // SA\r
- FALSE, \r
- CREATE_NEW_PROCESS_GROUP | \r
- CREATE_NEW_CONSOLE |\r
- NORMAL_PRIORITY_CLASS |\r
- // CREATE_NO_WINDOW |\r
- // DETACHED_PROCESS | /* KPK TODO: was set - restore */\r
- 0\r
- ,\r
- NULL, // environment\r
- szDir, // current dir\r
- &si,\r
- &pi);\r
- if (!bRes) {\r
- status = GetLastError();\r
- cci_debug_printf(" CreateProcess returned %d; LastError: %d", bRes, status);\r
- }\r
- cci_debug_printf(" Waiting...");\r
- }\r
- cci_check_error(status);\r
-\r
- if (!status) {\r
- status = WaitForSingleObject(hEvent, (SECONDS_TO_WAIT)*1000);\r
- status = RpcMgmtIsServerListening(ccs_request_IfHandle);\r
- }\r
- } \r
- else if (status) {\r
- cci_debug_printf(" unexpected error while looking for server: 0D%d / 0U%u / 0X%X", status, status, status);\r
- } \r
-\r
-#if 0\r
- if (hToken)\r
- CloseHandle(hToken);\r
-#endif\r
- if (szDir) free_alloc_p(&szDir);\r
- if (szExe) free_alloc_p(&szExe);\r
- if (hEvent) CloseHandle(hEvent);\r
- if (pi.hThread) CloseHandle(pi.hThread);\r
- if (pi.hProcess) CloseHandle(pi.hProcess);\r
- if (sa.lpSecurityDescriptor) free_alloc_p(&sa.lpSecurityDescriptor);\r
- return cci_check_error(status);\r
-\r
-}\r
-\r
-static\r
-DWORD\r
-authenticate_server(Init::InitInfo& info) {\r
- DWORD challenge = 17; // XXX - maybe use random number\r
- DWORD desired_response= challenge + 1;\r
- HANDLE hMap = 0;\r
- LPSTR mem_name = 0;\r
- PDWORD pvalue = 0;\r
- CC_UINT32 response = 0;\r
- SECURITY_ATTRIBUTES sa = { 0 };\r
- DWORD status = 0;\r
-\r
- cci_debug_printf("%s entry", __FUNCTION__);\r
-\r
- status = alloc_name(&mem_name, "auth", isNT());\r
- cci_check_error(status);\r
-\r
- if (!status) {\r
- if (isNT()) {\r
- sa.nLength = sizeof(sa);\r
- status = alloc_own_security_descriptor_NT(&sa.lpSecurityDescriptor);\r
- }\r
- }\r
- cci_check_error(status);\r
-\r
- if (!status) {\r
- hMap = CreateFileMapping(INVALID_HANDLE_VALUE, isNT() ? &sa : 0, \r
- PAGE_READWRITE, 0, sizeof(DWORD), mem_name);\r
- if (!hMap)\r
- status = GetLastError();\r
- }\r
- cci_check_error(status);\r
-\r
- if (!status) {\r
- pvalue = (PDWORD)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);\r
- if (!pvalue) status = GetLastError();\r
- }\r
- cci_check_error(status);\r
-\r
- if (!status) {\r
- *pvalue = challenge;\r
-\r
- RpcTryExcept {\r
- response = ccs_authenticate( (CC_CHAR*)mem_name );\r
- }\r
- RpcExcept(1) {\r
- status = RpcExceptionCode();\r
- cci_check_error(status);\r
- }\r
- RpcEndExcept;\r
- }\r
- cci_check_error(status);\r
-\r
- if (!status) {\r
- // Check response\r
- if ((response != desired_response) && (*pvalue != desired_response)) {\r
- cci_debug_printf(" Could not authenticate server.");\r
- status = ERROR_ACCESS_DENIED; // XXX - CO_E_NOMATCHINGSIDFOUND?\r
- } \r
- else {\r
- cci_debug_printf(" Server authenticated!");\r
- }\r
- cci_check_error(status);\r
- }\r
-\r
- free_alloc_p(&mem_name);\r
- free_alloc_p(&sa.lpSecurityDescriptor);\r
- if (pvalue) {\r
- BOOL ok = UnmapViewOfFile(pvalue);\r
-// DEBUG_ASSERT(ok);\r
- }\r
- if (hMap) CloseHandle(hMap);\r
- return status;\r
-}\r
-\r
-DWORD\r
-Client::Disconnect() {\r
- DWORD status = 0;\r
- if (ccs_request_IfHandle) {\r
- /* The calls to the remote procedures are complete. */\r
- /* Free the binding handle */\r
- status = RpcBindingFree(&ccs_request_IfHandle);\r
- }\r
- s_init = false;\r
- return status;\r
- }\r
-\r
-DWORD\r
-Client::Connect(char* ep OPTIONAL) {\r
- LPSTR endpoint = 0;\r
- DWORD status = 0;\r
-\r
- if (!ccs_request_IfHandle) {\r
- Init::InitInfo info;\r
-\r
- status = Init::Info(info);\r
- cci_check_error(status);\r
-\r
- if (!status) {\r
- status = bind_client(ep, info, &endpoint);\r
- cci_check_error(status);\r
- }\r
-\r
- if (!status) {\r
- status = find_server(info, endpoint);\r
- cci_check_error(status);\r
- }\r
-\r
- if (!status) {\r
- status = authenticate_server(info);\r
- cci_check_error(status);\r
- }\r
- }\r
-\r
-\r
- if (endpoint && (endpoint != ep)) free_alloc_p(&endpoint);\r
- \r
- if (status) Client::Disconnect();\r
- return status;\r
- }\r
-\r
-DWORD Client::Initialize(char* ep OPTIONAL) {\r
- CcAutoLock AL(Client::sLock);\r
- SecureClient s;\r
- ccs_request_IfHandle = NULL;\r
- if (s_init) return 0;\r
- DWORD status = Client::Connect(ep);\r
- if (!status) s_init = true;\r
- return status;\r
- }\r
-\r
-DWORD Client::Cleanup() {\r
- CcAutoLock AL(Client::sLock);\r
- SecureClient s;\r
- return Client::Disconnect();\r
- }\r
-\r
-DWORD Client::Reconnect(char* ep OPTIONAL) {\r
- CcAutoLock AL(Client::sLock);\r
- SecureClient s;\r
- DWORD status = 0;\r
-\r
- if (Initialized()) {\r
- DWORD status = Client::Cleanup();\r
- }\r
- if ( (!status) ) {\r
- status = Client::Initialize(ep);\r
- }\r
-\r
- return status;\r
- }\r
+/*
+ * $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 "stdio.h" // KPKDBG
+
+#include "ccs_request.h"
+
+#include "ccapi.h"
+#include "util.h"
+
+extern "C" {
+#include "cci_debugging.h"
+#include "tls.h" // KPKDBG
+ }
+
+#include "client.h"
+#include "init.hxx"
+#include "name.h"
+#include "secure.hxx"
+
+#define SECONDS_TO_WAIT 10
+
+#define STARTUP "CLIENT STARTUP: "
+#define DISCONNECT "CLIENT DISCONNECT: "
+
+bool Client::s_init = false;
+CcOsLock Client::sLock;
+
+static DWORD bind_client(char* ep OPTIONAL, Init::InitInfo& info, LPSTR* endpoint) {
+ DWORD status = 0;
+ unsigned char * pszStringBinding = NULL;
+
+ if (!ep) {
+ status = alloc_name(endpoint, "ep", isNT());
+ }
+ else {
+ *endpoint = ep;
+ }
+
+ if (!status) {
+ /* Use a convenience function to concatenate the elements of */
+ /* the string binding into the proper sequence. */
+ status = RpcStringBindingCompose(0, // uuid
+ (unsigned char*)"ncalrpc", // protseq
+ 0, // address
+ (unsigned char*)(*endpoint), // endpoint
+ 0, // options
+ &pszStringBinding);
+ cci_check_error(status);
+ }
+
+ if (!status) {
+ /* Set the binding handle that will be used to bind to the server. */
+ status = RpcBindingFromStringBinding(pszStringBinding, &ccs_request_IfHandle);
+ cci_check_error(status);
+ }
+
+ if (!status) {
+ // Win9x might call RpcBindingSetAuthInfo (not Ex), but it does not
+ // quite work on Win9x...
+ if (isNT()) {
+ RPC_SECURITY_QOS qos;
+ qos.Version = RPC_C_SECURITY_QOS_VERSION;
+ qos.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT;
+ qos.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
+ qos.ImpersonationType = RPC_C_IMP_LEVEL_IDENTIFY;
+
+ status = info.fRpcBindingSetAuthInfoEx(ccs_request_IfHandle,
+ 0, // principal
+ RPC_C_AUTHN_LEVEL_CONNECT,
+ RPC_C_AUTHN_WINNT,
+ 0, // current address space
+ RPC_C_AUTHZ_NAME,
+ &qos);
+ cci_check_error(status);
+ }
+ }
+
+ if (pszStringBinding) {
+ DWORD status = RpcStringFree(&pszStringBinding);
+ cci_check_error(status);
+ }
+ return cci_check_error(status);
+ }
+
+DWORD find_server(Init::InitInfo& info, LPSTR endpoint) {
+ DWORD status = 0;
+ LPSTR event_name = 0;
+ HANDLE hEvent = 0;
+ SECURITY_ATTRIBUTES sa = { 0 };
+ PSECURITY_ATTRIBUTES psa = 0;
+ STARTUPINFO si = { 0 };
+ PROCESS_INFORMATION pi = { 0 };
+ char* szExe = 0;
+ char* szDir = 0;
+ BOOL bRes = FALSE;
+ char* cmdline = NULL;
+#if 0
+ HANDLE hToken = 0;
+#endif
+
+ psa = isNT() ? &sa : 0;
+
+// cci_debug_printf("%s Looking for server; ccs_request_IfHandle:0x%X", __FUNCTION__, ccs_request_IfHandle);
+ status = cci_check_error(RpcMgmtIsServerListening(ccs_request_IfHandle));
+ if (status == RPC_S_NOT_LISTENING) {
+// cci_debug_printf(" Server *NOT* found!");
+ si.cb = sizeof(si);
+
+ status = alloc_module_dir_name(CCAPI_DLL, &szDir);
+
+ if (!status) {
+ status = alloc_module_dir_name_with_file(CCAPI_DLL, CCAPI_EXE, &szExe);
+ }
+
+ if (!status) {
+ status = alloc_name(&event_name, "startup", isNT());
+ cci_check_error(status);
+ }
+
+ if (!status) {
+ if (isNT()) {
+ sa.nLength = sizeof(sa);
+ status = alloc_own_security_descriptor_NT(&sa.lpSecurityDescriptor);
+ cci_check_error(status);
+ }
+ }
+
+ if (!status) {
+ hEvent = CreateEvent(psa, FALSE, FALSE, event_name);
+ cci_debug_printf(" CreateEvent(... %s) returned hEvent 0x%X", event_name, hEvent);
+ if (!hEvent) status = GetLastError();
+ }
+
+ if (!status) {
+
+#if 0
+ if (SecureClient::IsImp()) {
+ cci_debug_printf(STARTUP "Token is impersonation token"));
+ SecureClient::DuplicateImpAsPrimary(hToken);
+ }
+ else {
+ cci_debug_printf(STARTUP "Token is NOT impersonation token"));
+ }
+#endif
+
+#if 0
+ if (hToken)
+ bRes = CreateProcessAsUser(hToken,
+ szExe, // app name
+ NULL, // cmd line
+ psa, // SA
+ psa, // SA
+ FALSE,
+ CREATE_NEW_PROCESS_GROUP |
+ //CREATE_NEW_CONSOLE |
+ NORMAL_PRIORITY_CLASS |
+ // CREATE_NO_WINDOW |
+ DETACHED_PROCESS |
+ 0
+ ,
+ NULL, // environment
+ szDir, // current dir
+ &si,
+ &pi);
+ else
+#endif
+ alloc_cmdline_2_args(szExe, endpoint, "-D", &cmdline);
+ bRes = CreateProcess( szExe, // app name
+ NULL, //cmdline, // cmd line is <server endpoint -[DC]>
+ psa, // SA
+ psa, // SA
+ FALSE,
+ CREATE_NEW_PROCESS_GROUP |
+ CREATE_NEW_CONSOLE |
+ NORMAL_PRIORITY_CLASS |
+ // CREATE_NO_WINDOW |
+ // DETACHED_PROCESS | /* KPK TODO: was set - restore */
+ 0
+ ,
+ NULL, // environment
+ szDir, // current dir
+ &si,
+ &pi);
+ if (!bRes) {
+ status = GetLastError();
+ cci_debug_printf(" CreateProcess returned %d; LastError: %d", bRes, status);
+ }
+ cci_debug_printf(" Waiting...");
+ }
+ cci_check_error(status);
+
+ if (!status) {
+ status = WaitForSingleObject(hEvent, (SECONDS_TO_WAIT)*1000);
+ status = RpcMgmtIsServerListening(ccs_request_IfHandle);
+ }
+ }
+ else if (status) {
+ cci_debug_printf(" unexpected error while looking for server: 0D%d / 0U%u / 0X%X", status, status, status);
+ }
+
+#if 0
+ if (hToken)
+ CloseHandle(hToken);
+#endif
+ if (szDir) free_alloc_p(&szDir);
+ if (szExe) free_alloc_p(&szExe);
+ if (hEvent) CloseHandle(hEvent);
+ if (pi.hThread) CloseHandle(pi.hThread);
+ if (pi.hProcess) CloseHandle(pi.hProcess);
+ if (sa.lpSecurityDescriptor) free_alloc_p(&sa.lpSecurityDescriptor);
+ return cci_check_error(status);
+
+}
+
+static
+DWORD
+authenticate_server(Init::InitInfo& info) {
+ DWORD challenge = 17; // XXX - maybe use random number
+ DWORD desired_response= challenge + 1;
+ HANDLE hMap = 0;
+ LPSTR mem_name = 0;
+ PDWORD pvalue = 0;
+ CC_UINT32 response = 0;
+ SECURITY_ATTRIBUTES sa = { 0 };
+ DWORD status = 0;
+
+ cci_debug_printf("%s entry", __FUNCTION__);
+
+ status = alloc_name(&mem_name, "auth", isNT());
+ cci_check_error(status);
+
+ if (!status) {
+ if (isNT()) {
+ sa.nLength = sizeof(sa);
+ status = alloc_own_security_descriptor_NT(&sa.lpSecurityDescriptor);
+ }
+ }
+ cci_check_error(status);
+
+ if (!status) {
+ hMap = CreateFileMapping(INVALID_HANDLE_VALUE, isNT() ? &sa : 0,
+ PAGE_READWRITE, 0, sizeof(DWORD), mem_name);
+ if (!hMap)
+ status = GetLastError();
+ }
+ cci_check_error(status);
+
+ if (!status) {
+ pvalue = (PDWORD)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
+ if (!pvalue) status = GetLastError();
+ }
+ cci_check_error(status);
+
+ if (!status) {
+ *pvalue = challenge;
+
+ RpcTryExcept {
+ response = ccs_authenticate( (CC_CHAR*)mem_name );
+ }
+ RpcExcept(1) {
+ status = RpcExceptionCode();
+ cci_check_error(status);
+ }
+ RpcEndExcept;
+ }
+ cci_check_error(status);
+
+ if (!status) {
+ // Check response
+ if ((response != desired_response) && (*pvalue != desired_response)) {
+ cci_debug_printf(" Could not authenticate server.");
+ status = ERROR_ACCESS_DENIED; // XXX - CO_E_NOMATCHINGSIDFOUND?
+ }
+ else {
+ cci_debug_printf(" Server authenticated!");
+ }
+ cci_check_error(status);
+ }
+
+ free_alloc_p(&mem_name);
+ free_alloc_p(&sa.lpSecurityDescriptor);
+ if (pvalue) {
+ BOOL ok = UnmapViewOfFile(pvalue);
+// DEBUG_ASSERT(ok);
+ }
+ if (hMap) CloseHandle(hMap);
+ return status;
+}
+
+DWORD
+Client::Disconnect() {
+ DWORD status = 0;
+ if (ccs_request_IfHandle) {
+ /* The calls to the remote procedures are complete. */
+ /* Free the binding handle */
+ status = RpcBindingFree(&ccs_request_IfHandle);
+ }
+ s_init = false;
+ return status;
+ }
+
+DWORD
+Client::Connect(char* ep OPTIONAL) {
+ LPSTR endpoint = 0;
+ DWORD status = 0;
+
+ if (!ccs_request_IfHandle) {
+ Init::InitInfo info;
+
+ status = Init::Info(info);
+ cci_check_error(status);
+
+ if (!status) {
+ status = bind_client(ep, info, &endpoint);
+ cci_check_error(status);
+ }
+
+ if (!status) {
+ status = find_server(info, endpoint);
+ cci_check_error(status);
+ }
+
+ if (!status) {
+ status = authenticate_server(info);
+ cci_check_error(status);
+ }
+ }
+
+
+ if (endpoint && (endpoint != ep)) free_alloc_p(&endpoint);
+
+ if (status) Client::Disconnect();
+ return status;
+ }
+
+DWORD Client::Initialize(char* ep OPTIONAL) {
+ CcAutoLock AL(Client::sLock);
+ SecureClient s;
+ ccs_request_IfHandle = NULL;
+ if (s_init) return 0;
+ DWORD status = Client::Connect(ep);
+ if (!status) s_init = true;
+ return status;
+ }
+
+DWORD Client::Cleanup() {
+ CcAutoLock AL(Client::sLock);
+ SecureClient s;
+ return Client::Disconnect();
+ }
+
+DWORD Client::Reconnect(char* ep OPTIONAL) {
+ CcAutoLock AL(Client::sLock);
+ SecureClient s;
+ DWORD status = 0;
+
+ if (Initialized()) {
+ DWORD status = Client::Cleanup();
+ }
+ if ( (!status) ) {
+ status = Client::Initialize(ep);
+ }
+
+ return status;
+ }
-/*\r
- * $Header$\r
- *\r
- * Copyright 2008 Massachusetts Institute of Technology.\r
- * All Rights Reserved.\r
- *\r
- * Export of this software from the United States of America may\r
- * require a specific license from the United States Government.\r
- * It is the responsibility of any person or organization contemplating\r
- * export to obtain such a license before exporting.\r
- *\r
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and\r
- * distribute this software and its documentation for any purpose and\r
- * without fee is hereby granted, provided that the above copyright\r
- * notice appear in all copies and that both that copyright notice and\r
- * this permission notice appear in supporting documentation, and that\r
- * the name of M.I.T. not be used in advertising or publicity pertaining\r
- * to distribution of the software without specific, written prior\r
- * permission. Furthermore if you modify this software you must label\r
- * your software as modified software and not distribute it in such a\r
- * fashion that it might be confused with the original M.I.T. software.\r
- * M.I.T. makes no representations about the suitability of\r
- * this software for any purpose. It is provided "as is" without express\r
- * or implied warranty.\r
- */\r
-\r
-#include <stdlib.h>\r
-#include <stdio.h>\r
-\r
-extern "C" {\r
-#include "CredentialsCache.h"\r
-#include "secure.hxx"\r
-#include "client.h"\r
-#include "autolock.hxx"\r
-#include "cci_debugging.h"\r
- }\r
-\r
-extern HANDLE hCCAPIv2Mutex;\r
-\r
-#define MAKE_RPC_CALL(rc, x) \\r
-do { \\r
- WaitForSingleObject( hCCAPIv2Mutex, INFINITE ); \\r
- SecureClient* s = 0; \\r
- SecureClient::Start(s); \\r
- CcAutoLock* a = 0; \\r
- CcAutoLock::Start(a, Client::sLock); \\r
- RpcTryExcept { \\r
- cci_debug_printf("RpcTry: #x"); \\r
- x; \\r
- } \\r
- RpcExcept(1) { \\r
- rc = handle_exception(RpcExceptionCode()); \\r
- } \\r
- RpcEndExcept; \\r
- CcAutoLock::Stop(a); \\r
- SecureClient::Stop(s); \\r
- ReleaseMutex( hCCAPIv2Mutex ); \\r
-} while (0)\r
-\r
-static\r
-DWORD\r
-handle_exception(DWORD code) {\r
- cci_debug_printf("Runtime reported exception %u", code);\r
- if (code == RPC_S_SERVER_UNAVAILABLE) {\r
- Client::Reconnect(0);\r
- }\r
- return 4;\r
- }\r
-\r
-//////////////////////////////////////////////////////////////////////////////\r
-\r
-cc_int32 cc_initialize() {\r
-\r
- CLIENT_INIT_EX(true, 4);\r
- cc_int32 rc = ccNoError;\r
-\r
- MAKE_RPC_CALL(rc, rc = 5);\r
- return rc;\r
+/*
+ * $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>
+
+extern "C" {
+#include "CredentialsCache.h"
+#include "secure.hxx"
+#include "client.h"
+#include "autolock.hxx"
+#include "cci_debugging.h"
+ }
+
+extern HANDLE hCCAPIv2Mutex;
+
+#define MAKE_RPC_CALL(rc, x) \
+do { \
+ WaitForSingleObject( hCCAPIv2Mutex, INFINITE ); \
+ SecureClient* s = 0; \
+ SecureClient::Start(s); \
+ CcAutoLock* a = 0; \
+ CcAutoLock::Start(a, Client::sLock); \
+ RpcTryExcept { \
+ cci_debug_printf("RpcTry: #x"); \
+ x; \
+ } \
+ RpcExcept(1) { \
+ rc = handle_exception(RpcExceptionCode()); \
+ } \
+ RpcEndExcept; \
+ CcAutoLock::Stop(a); \
+ SecureClient::Stop(s); \
+ ReleaseMutex( hCCAPIv2Mutex ); \
+} while (0)
+
+static
+DWORD
+handle_exception(DWORD code) {
+ cci_debug_printf("Runtime reported exception %u", code);
+ if (code == RPC_S_SERVER_UNAVAILABLE) {
+ Client::Reconnect(0);
+ }
+ return 4;
+ }
+
+//////////////////////////////////////////////////////////////////////////////
+
+cc_int32 cc_initialize() {
+
+ CLIENT_INIT_EX(true, 4);
+ cc_int32 rc = ccNoError;
+
+ MAKE_RPC_CALL(rc, rc = 5);
+ return rc;
}
\ No newline at end of file
-;LIBRARY COMERR32\r
-HEAPSIZE 8192\r
-\r
-EXPORTS\r
- cci_debug_printf\r
- \r
- cc_initialize\r
-\r
- cci_string_new\r
- cci_string_d_initializer\r
- ccapi_string_release\r
-\r
- cci_credentials_iterator_new \r
- cci_credentials_iterator_write \r
-\r
- cci_ccache_iterator_new \r
- cci_ccache_iterator_write \r
-\r
- ccapi_ccache_iterator_release \r
- ccapi_ccache_iterator_next \r
- ccapi_ccache_iterator_clone \r
-\r
- ccapi_credentials_iterator_release \r
- ccapi_credentials_iterator_next \r
- ccapi_credentials_iterator_clone\r
- \r
-;debugging:\r
- _cci_check_error\r
- cci_os_ipc\r
- cci_os_ipc_msg\r
- cci_os_ipc_thread_init\r
- cci_stream_data\r
- cci_stream_write\r
- cci_stream_new\r
- \r
- ccs_authenticate\r
- \r
- \r
+;LIBRARY COMERR32
+HEAPSIZE 8192
+
+EXPORTS
+ cci_debug_printf
+
+ cc_initialize
+
+ cci_string_new
+ cci_string_d_initializer
+ ccapi_string_release
+
+ cci_credentials_iterator_new
+ cci_credentials_iterator_write
+
+ cci_ccache_iterator_new
+ cci_ccache_iterator_write
+
+ ccapi_ccache_iterator_release
+ ccapi_ccache_iterator_next
+ ccapi_ccache_iterator_clone
+
+ ccapi_credentials_iterator_release
+ ccapi_credentials_iterator_next
+ ccapi_credentials_iterator_clone
+
+;debugging:
+ _cci_check_error
+ cci_os_ipc
+ cci_os_ipc_msg
+ cci_os_ipc_thread_init
+ cci_stream_data
+ cci_stream_write
+ cci_stream_new
+
+ ccs_authenticate
+
+
\ No newline at end of file
-/*\r
- * $Header$\r
- *\r
- * Copyright 2008 Massachusetts Institute of Technology.\r
- * All Rights Reserved.\r
- *\r
- * Export of this software from the United States of America may\r
- * require a specific license from the United States Government.\r
- * It is the responsibility of any person or organization contemplating\r
- * export to obtain such a license before exporting.\r
- *\r
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and\r
- * distribute this software and its documentation for any purpose and\r
- * without fee is hereby granted, provided that the above copyright\r
- * notice appear in all copies and that both that copyright notice and\r
- * this permission notice appear in supporting documentation, and that\r
- * the name of M.I.T. not be used in advertising or publicity pertaining\r
- * to distribution of the software without specific, written prior\r
- * permission. Furthermore if you modify this software you must label\r
- * your software as modified software and not distribute it in such a\r
- * fashion that it might be confused with the original M.I.T. software.\r
- * M.I.T. makes no representations about the suitability of\r
- * this software for any purpose. It is provided "as is" without express\r
- * or implied warranty.\r
- */\r
-\r
-extern "C" {\r
-#include "k5-thread.h"\r
-#include "ccapi_os_ipc.h"\r
-#include "tls.h"\r
-#include "dllmain.h"\r
-#include "ccs_reply.h"\r
-#include "ccs_request.h"\r
-#include "win-utils.h"\r
-#include "ccutils.h"\r
-#include "util.h"\r
- }\r
-\r
-#include "CredentialsCache.h"\r
-#include "secure.hxx"\r
-#include "opts.hxx"\r
-#include "client.h"\r
-#include "autolock.hxx"\r
-#include "cci_debugging.h"\r
-\r
-#define SECONDS_TO_WAIT 10\r
-#define CLIENT_REQUEST_RPC_HANDLE ccs_request_IfHandle\r
-\r
-extern HANDLE hCCAPIv2Mutex;\r
-ParseOpts::Opts opts = { 0 };\r
-PSECURITY_ATTRIBUTES psa = 0;\r
-SECURITY_ATTRIBUTES sa = { 0 };\r
-\r
-/* The layout of the rest of this module: \r
-\r
- The entrypoints defined in ccs_os_ipc.h:\r
- cci_os_ipc_thread_init\r
- cci_os_ipc\r
-\r
- Other routines needed by those four.\r
- cci_os_connect\r
- handle_exception\r
- */\r
-\r
-cc_int32 ccapi_connect(const struct tspdata* tsp);\r
-static DWORD handle_exception(DWORD code);\r
-\r
-extern "C" {\r
-cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server,\r
- cci_stream_t in_request_stream,\r
- cc_int32 in_msg,\r
- cci_stream_t* out_reply_stream);\r
- }\r
-\r
-/* ------------------------------------------------------------------------ */\r
-\r
-extern "C" cc_int32 cci_os_ipc_thread_init (void) {\r
- cc_int32 err = ccNoError;\r
- struct tspdata* ptspdata;\r
- HANDLE replyEvent;\r
- UUID __RPC_FAR uuid;\r
- unsigned char __RPC_FAR* uuidString = NULL;\r
-\r
- if (!GetTspData(&ptspdata)) return ccErrNoMem;\r
-\r
- opts.cMinCalls = 1;\r
- opts.cMaxCalls = 20;\r
- opts.fDontWait = TRUE;\r
-\r
- err = cci_check_error(UuidCreate(&uuid)); // Get a UUID\r
- if (err == RPC_S_OK) { // Convert to string\r
- err = UuidToString(&uuid, &uuidString);\r
- }\r
- if (!err) { // Save in thread local storage\r
- tspdata_setUUID(ptspdata, uuidString);\r
- }\r
- cci_debug_printf("%s UUID:<%s>", __FUNCTION__, tspdata_getUUID(ptspdata));\r
-\r
- // Initialize old CCAPI if necessary:\r
- if (!err) if (!Init:: Initialized()) err = Init:: Initialize( );\r
- if (!err) if (!Client::Initialized()) err = Client::Initialize(0);\r
-\r
- if (!err) {\r
- /* Whenever a reply to an RPC request is received, the RPC caller needs to\r
- know when the reply has been received. It does that by waiting for a \r
- client-specific event to be set. Define the event name to be <UUID>_reply: */\r
- replyEvent = createThreadEvent((char*)uuidString, REPLY_SUFFIX);\r
- }\r
-\r
- if (replyEvent) tspdata_setReplyEvent(ptspdata, replyEvent);\r
- else err = cci_check_error(GetLastError());\r
-\r
- if (uuidString) RpcStringFree(&uuidString);\r
-\r
- return cci_check_error(err);\r
- }\r
-\r
-\r
-/* ------------------------------------------------------------------------ */\r
-\r
-cc_int32 cci_os_ipc (cc_int32 in_launch_server,\r
- cci_stream_t in_request_stream,\r
- cci_stream_t* out_reply_stream) {\r
- return cci_os_ipc_msg( in_launch_server, \r
- in_request_stream, \r
- CCMSG_REQUEST, \r
- out_reply_stream);\r
- }\r
-\r
-extern "C" cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server,\r
- cci_stream_t in_request_stream,\r
- cc_int32 in_msg,\r
- cci_stream_t* out_reply_stream) {\r
-\r
- cc_int32 err = ccNoError;\r
- cc_int32 done = FALSE;\r
- cc_int32 try_count = 0;\r
- cc_int32 server_died = FALSE;\r
- TCHAR* pszStringBinding= NULL;\r
- struct tspdata* ptspdata = NULL;\r
- char* uuid = NULL;\r
- int lenUUID = 0;\r
- unsigned int trycount = 0;\r
- time_t sst = 0;\r
- STARTUPINFO si = { 0 };\r
- PROCESS_INFORMATION pi = { 0 };\r
- HANDLE replyEvent = 0;\r
- BOOL bCCAPI_Connected= FALSE;\r
-\r
- if (!in_request_stream) { err = cci_check_error (ccErrBadParam); }\r
- if (!out_reply_stream ) { err = cci_check_error (ccErrBadParam); }\r
- \r
- if (!GetTspData(&ptspdata)) {return ccErrBadParam;}\r
- bCCAPI_Connected = tspdata_getConnected (ptspdata);\r
- replyEvent = tspdata_getReplyEvent (ptspdata);\r
- sst = tspdata_getSST (ptspdata);\r
- uuid = tspdata_getUUID(ptspdata);\r
-\r
- // The lazy connection to the server has been put off as long as possible!\r
- // ccapi_connect starts listening for replies as an RPC server and then\r
- // calls ccs_rpc_connect.\r
- if (!bCCAPI_Connected) {\r
- err = cci_check_error(ccapi_connect(ptspdata));\r
- bCCAPI_Connected = !err;\r
- tspdata_setConnected(ptspdata, bCCAPI_Connected);\r
- }\r
-\r
- // Clear replyEvent so we can detect when a reply to our request has been received:\r
- ResetEvent(replyEvent);\r
- \r
- //++ Use the old CCAPI implementation to try to talk to the server:\r
- // It has all the code to use the RPC in a thread-safe way, make the endpoint, \r
- // (re)connect and (re)start the server.\r
- // Note: the old implementation wrapped the thread-safety stuff in a macro.\r
- // Here it is expanded and thus duplicated for each RPC call. The new code has\r
- // a very limited number of RPC calls, unlike the older code.\r
- WaitForSingleObject( hCCAPIv2Mutex, INFINITE );\r
- SecureClient* s = 0;\r
- SecureClient::Start(s);\r
- CcAutoLock* a = 0;\r
- CcAutoLock::Start(a, Client::sLock);\r
-\r
- // Initialize old CCAPI if necessary:\r
- if (!err) if (!Init:: Initialized()) err = cci_check_error(Init:: Initialize( ));\r
- if (!err) if (!Client::Initialized()) err = cci_check_error(Client::Initialize(0));\r
-\r
- // New code using new RPC procedures for sending the data and receiving a reply:\r
- if (!err) {\r
- RpcTryExcept {\r
- if (!GetTspData(&ptspdata)) {return ccErrBadParam;}\r
- uuid = tspdata_getUUID(ptspdata);\r
- lenUUID = 1 + strlen(uuid); /* 1+ includes terminating \0. */\r
- cci_debug_printf("%s calling remote ccs_rpc_request tsp*:0x%X", __FUNCTION__, ptspdata);\r
- cci_debug_printf(" rpcmsg:%d; UUID[%d]:<%s> SST:%ld", in_msg, lenUUID, uuid, sst);\r
-\r
- ccs_rpc_request( /* make call with user message: */\r
- in_msg, /* Message type */\r
- (unsigned char*)&ptspdata, /* Our tspdata* will be sent back to the reply proc. */\r
- (unsigned char*)uuid,\r
- cci_stream_size(in_request_stream),\r
- (unsigned char*)cci_stream_data(in_request_stream), /* Data buffer */\r
- sst, /* session start time */\r
- (long*)(&err) ); /* Return code */\r
- }\r
- RpcExcept(1) {\r
- handle_exception(RpcExceptionCode());\r
- }\r
- RpcEndExcept;\r
- }\r
-\r
- cci_check_error(err);\r
- CcAutoLock::Stop(a);\r
- SecureClient::Stop(s);\r
- ReleaseMutex(hCCAPIv2Mutex); \r
- //-- Use the old CCAPI implementation to try to talk to the server.\r
-\r
- // Wait for reply handler to set event:\r
- if (!err) {\r
- cci_debug_printf(" Waiting for request reply.");\r
- err = cci_check_error(WaitForSingleObject(replyEvent, INFINITE));//(SECONDS_TO_WAIT)*1000));\r
- cci_debug_printf(" Request reply received!");\r
- }\r
-\r
- if (!err) {\r
- err = cci_check_error(RpcMgmtIsServerListening(CLIENT_REQUEST_RPC_HANDLE));\r
- }\r
-\r
- if (!err && server_died) {\r
- err = cci_check_error (ccErrServerUnavailable);\r
- }\r
-#if 0 \r
- if (err == BOOTSTRAP_UNKNOWN_SERVICE && !in_launch_server) {\r
- err = ccNoError; /* If the server is not running just return an empty stream. */\r
- }\r
-#endif\r
-\r
- if (!err) {\r
- *out_reply_stream = tspdata_getStream(ptspdata);\r
- }\r
- \r
- cci_debug_printf(" payload:<%s>", cci_stream_data(*out_reply_stream));\r
-\r
- return cci_check_error (err); \r
- }\r
-\r
-\r
-\r
-static DWORD handle_exception(DWORD code) {\r
- cci_debug_printf("%s code %u; ccs_request_IfHandle:0x%X", __FUNCTION__, code, ccs_request_IfHandle);\r
- if ( (code == RPC_S_SERVER_UNAVAILABLE) || (code == RPC_S_INVALID_BINDING) ) {\r
- Client::Reconnect(0);\r
- }\r
- return 4;\r
- }\r
-\r
-\r
-/* Establish a CCAPI connection with the server.\r
- * The connect logic here is identical to the logic in the send request code.\r
- * TODO: merge this connect code with that request code.\r
- */\r
-cc_int32 ccapi_connect(const struct tspdata* tsp) {\r
- BOOL bListen = TRUE;\r
- char* endpoint = NULL;\r
- HANDLE replyEvent = 0;\r
- RPC_STATUS status = FALSE;\r
- char* uuid = NULL;\r
-\r
- /* Start listening to our uuid before establishing the connection,\r
- * so that when the server tries to call ccapi_listen, we will be ready.\r
- */\r
-\r
- /* Build complete RPC uuid using previous CCAPI implementation: */\r
- replyEvent = tspdata_getReplyEvent(tsp);\r
- uuid = tspdata_getUUID(tsp);\r
- endpoint = clientEndpoint(uuid);\r
- cci_debug_printf("%s Registering endpoint %s", __FUNCTION__, endpoint);\r
-\r
- opts.cMinCalls = 1;\r
- opts.cMaxCalls = 20;\r
- opts.fDontWait = TRUE;\r
-\r
- if (!status) {\r
- status = RpcServerUseProtseqEp((RPC_CSTR)"ncalrpc",\r
- opts.cMaxCalls,\r
- (RPC_CSTR)endpoint,\r
- sa.lpSecurityDescriptor); // SD\r
- cci_check_error(status);\r
- }\r
-\r
- if (!status) {\r
- status = RpcServerRegisterAuthInfo(0, // server principal\r
- RPC_C_AUTHN_WINNT,\r
- 0,\r
- 0 );\r
- cci_check_error(status);\r
- }\r
-\r
- cci_debug_printf("%s is listening ...", __FUNCTION__);\r
-\r
- if (!status) {\r
- if (!isNT()) {\r
- status = RpcServerRegisterIf(ccs_reply_ServerIfHandle, // interface \r
- NULL, // MgrTypeUuid\r
- NULL); // MgrEpv; null means use default\r
- } \r
- else {\r
- status = RpcServerRegisterIfEx(ccs_reply_ServerIfHandle,// interface\r
- NULL, // MgrTypeUuid\r
- NULL, // MgrEpv; 0 means default\r
- RPC_IF_ALLOW_SECURE_ONLY,\r
- opts.cMaxCalls,\r
- NULL); // No security callback.\r
- }\r
-\r
- cci_check_error(status);\r
-\r
- if (!status) {\r
- status = RpcServerListen(opts.cMinCalls,\r
- opts.cMaxCalls,\r
- TRUE);\r
- cci_check_error(status);\r
- }\r
- }\r
-\r
- // Clear replyEvent so we can detect when a reply to our connect request has been received:\r
- ResetEvent(replyEvent);\r
-\r
- // We use the old CCAPI implementation to try to talk to the server. \r
- // It has all the code to make the uuid, (re)connect and (re)start the server.\r
- WaitForSingleObject( hCCAPIv2Mutex, INFINITE );\r
- SecureClient* s = 0;\r
- SecureClient::Start(s);\r
- CcAutoLock* a = 0;\r
- CcAutoLock::Start(a, Client::sLock);\r
-\r
- // Initialize old CCAPI if necessary:\r
- if (!status) if (!Init:: Initialized()) status = Init:: Initialize( );\r
- if (!status) if (!Client::Initialized()) status = Client::Initialize(0);\r
-\r
- // New code using new RPC procedures for sending the data and receiving a reply:\r
- if (!status) {\r
- RpcTryExcept {\r
- ccs_rpc_connect( /* make call with user message: */\r
- CCMSG_CONNECT, /* Message type */\r
- (unsigned char*)&tsp, /* Our tspdata* will be sent back to the reply proc. */\r
- (unsigned char*)uuid,\r
- (long*)(&status) ); /* Return code */\r
- }\r
- RpcExcept(1) {\r
- cci_check_error(RpcExceptionCode());\r
- status = ccErrBadInternalMessage;\r
- }\r
- RpcEndExcept;\r
- }\r
-\r
- CcAutoLock::Stop(a);\r
- SecureClient::Stop(s);\r
- ReleaseMutex(hCCAPIv2Mutex); \r
-\r
- if (!status) {\r
- cci_debug_printf("%s Waiting for replyEvent.", __FUNCTION__);\r
- status = WaitForSingleObject(replyEvent, INFINITE);//(SECONDS_TO_WAIT)*1000);\r
- status = cci_check_error(RpcMgmtIsServerListening(CLIENT_REQUEST_RPC_HANDLE));\r
- cci_debug_printf(" Server %sFOUND!", (status) ? "NOT " : "");\r
- }\r
- if (status) {\r
- cci_debug_printf(" unexpected error while looking for server... (%u)", status);\r
- } \r
- \r
- cci_debug_printf("%s TODO: check connect reply result.", __FUNCTION__);\r
- cci_debug_printf("%s TODO: merge this connect code with that request code.", __FUNCTION__);\r
- return status;\r
+/*
+ * $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 "k5-thread.h"
+#include "ccapi_os_ipc.h"
+#include "tls.h"
+#include "dllmain.h"
+#include "ccs_reply.h"
+#include "ccs_request.h"
+#include "win-utils.h"
+#include "ccutils.h"
+#include "util.h"
+ }
+
+#include "CredentialsCache.h"
+#include "secure.hxx"
+#include "opts.hxx"
+#include "client.h"
+#include "autolock.hxx"
+#include "cci_debugging.h"
+
+#define SECONDS_TO_WAIT 10
+#define CLIENT_REQUEST_RPC_HANDLE ccs_request_IfHandle
+
+extern HANDLE hCCAPIv2Mutex;
+ParseOpts::Opts opts = { 0 };
+PSECURITY_ATTRIBUTES psa = 0;
+SECURITY_ATTRIBUTES sa = { 0 };
+
+/* The layout of the rest of this module:
+
+ The entrypoints defined in ccs_os_ipc.h:
+ cci_os_ipc_thread_init
+ cci_os_ipc
+
+ Other routines needed by those four.
+ cci_os_connect
+ handle_exception
+ */
+
+cc_int32 ccapi_connect(const struct tspdata* tsp);
+static DWORD handle_exception(DWORD code);
+
+extern "C" {
+cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server,
+ cci_stream_t in_request_stream,
+ cc_int32 in_msg,
+ cci_stream_t* out_reply_stream);
+ }
+
+/* ------------------------------------------------------------------------ */
+
+extern "C" cc_int32 cci_os_ipc_thread_init (void) {
+ cc_int32 err = ccNoError;
+ struct tspdata* ptspdata;
+ HANDLE replyEvent;
+ UUID __RPC_FAR uuid;
+ unsigned char __RPC_FAR* uuidString = NULL;
+
+ if (!GetTspData(&ptspdata)) return ccErrNoMem;
+
+ opts.cMinCalls = 1;
+ opts.cMaxCalls = 20;
+ opts.fDontWait = TRUE;
+
+ err = cci_check_error(UuidCreate(&uuid)); // Get a UUID
+ if (err == RPC_S_OK) { // Convert to string
+ err = UuidToString(&uuid, &uuidString);
+ }
+ if (!err) { // Save in thread local storage
+ tspdata_setUUID(ptspdata, uuidString);
+ }
+ cci_debug_printf("%s UUID:<%s>", __FUNCTION__, tspdata_getUUID(ptspdata));
+
+ // Initialize old CCAPI if necessary:
+ if (!err) if (!Init:: Initialized()) err = Init:: Initialize( );
+ if (!err) if (!Client::Initialized()) err = Client::Initialize(0);
+
+ if (!err) {
+ /* Whenever a reply to an RPC request is received, the RPC caller needs to
+ know when the reply has been received. It does that by waiting for a
+ client-specific event to be set. Define the event name to be <UUID>_reply: */
+ replyEvent = createThreadEvent((char*)uuidString, REPLY_SUFFIX);
+ }
+
+ if (replyEvent) tspdata_setReplyEvent(ptspdata, replyEvent);
+ else err = cci_check_error(GetLastError());
+
+ if (uuidString) RpcStringFree(&uuidString);
+
+ return cci_check_error(err);
+ }
+
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 cci_os_ipc (cc_int32 in_launch_server,
+ cci_stream_t in_request_stream,
+ cci_stream_t* out_reply_stream) {
+ return cci_os_ipc_msg( in_launch_server,
+ in_request_stream,
+ CCMSG_REQUEST,
+ out_reply_stream);
+ }
+
+extern "C" cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server,
+ cci_stream_t in_request_stream,
+ cc_int32 in_msg,
+ cci_stream_t* out_reply_stream) {
+
+ cc_int32 err = ccNoError;
+ cc_int32 done = FALSE;
+ cc_int32 try_count = 0;
+ cc_int32 server_died = FALSE;
+ TCHAR* pszStringBinding= NULL;
+ struct tspdata* ptspdata = NULL;
+ char* uuid = NULL;
+ int lenUUID = 0;
+ unsigned int trycount = 0;
+ time_t sst = 0;
+ STARTUPINFO si = { 0 };
+ PROCESS_INFORMATION pi = { 0 };
+ HANDLE replyEvent = 0;
+ BOOL bCCAPI_Connected= FALSE;
+
+ if (!in_request_stream) { err = cci_check_error (ccErrBadParam); }
+ if (!out_reply_stream ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!GetTspData(&ptspdata)) {return ccErrBadParam;}
+ bCCAPI_Connected = tspdata_getConnected (ptspdata);
+ replyEvent = tspdata_getReplyEvent (ptspdata);
+ sst = tspdata_getSST (ptspdata);
+ uuid = tspdata_getUUID(ptspdata);
+
+ // The lazy connection to the server has been put off as long as possible!
+ // ccapi_connect starts listening for replies as an RPC server and then
+ // calls ccs_rpc_connect.
+ if (!bCCAPI_Connected) {
+ err = cci_check_error(ccapi_connect(ptspdata));
+ bCCAPI_Connected = !err;
+ tspdata_setConnected(ptspdata, bCCAPI_Connected);
+ }
+
+ // Clear replyEvent so we can detect when a reply to our request has been received:
+ ResetEvent(replyEvent);
+
+ //++ Use the old CCAPI implementation to try to talk to the server:
+ // It has all the code to use the RPC in a thread-safe way, make the endpoint,
+ // (re)connect and (re)start the server.
+ // Note: the old implementation wrapped the thread-safety stuff in a macro.
+ // Here it is expanded and thus duplicated for each RPC call. The new code has
+ // a very limited number of RPC calls, unlike the older code.
+ WaitForSingleObject( hCCAPIv2Mutex, INFINITE );
+ SecureClient* s = 0;
+ SecureClient::Start(s);
+ CcAutoLock* a = 0;
+ CcAutoLock::Start(a, Client::sLock);
+
+ // Initialize old CCAPI if necessary:
+ if (!err) if (!Init:: Initialized()) err = cci_check_error(Init:: Initialize( ));
+ if (!err) if (!Client::Initialized()) err = cci_check_error(Client::Initialize(0));
+
+ // New code using new RPC procedures for sending the data and receiving a reply:
+ if (!err) {
+ RpcTryExcept {
+ if (!GetTspData(&ptspdata)) {return ccErrBadParam;}
+ uuid = tspdata_getUUID(ptspdata);
+ lenUUID = 1 + strlen(uuid); /* 1+ includes terminating \0. */
+ cci_debug_printf("%s calling remote ccs_rpc_request tsp*:0x%X", __FUNCTION__, ptspdata);
+ cci_debug_printf(" rpcmsg:%d; UUID[%d]:<%s> SST:%ld", in_msg, lenUUID, uuid, sst);
+
+ ccs_rpc_request( /* make call with user message: */
+ in_msg, /* Message type */
+ (unsigned char*)&ptspdata, /* Our tspdata* will be sent back to the reply proc. */
+ (unsigned char*)uuid,
+ cci_stream_size(in_request_stream),
+ (unsigned char*)cci_stream_data(in_request_stream), /* Data buffer */
+ sst, /* session start time */
+ (long*)(&err) ); /* Return code */
+ }
+ RpcExcept(1) {
+ handle_exception(RpcExceptionCode());
+ }
+ RpcEndExcept;
+ }
+
+ cci_check_error(err);
+ CcAutoLock::Stop(a);
+ SecureClient::Stop(s);
+ ReleaseMutex(hCCAPIv2Mutex);
+ //-- Use the old CCAPI implementation to try to talk to the server.
+
+ // Wait for reply handler to set event:
+ if (!err) {
+ cci_debug_printf(" Waiting for request reply.");
+ err = cci_check_error(WaitForSingleObject(replyEvent, INFINITE));//(SECONDS_TO_WAIT)*1000));
+ cci_debug_printf(" Request reply received!");
+ }
+
+ if (!err) {
+ err = cci_check_error(RpcMgmtIsServerListening(CLIENT_REQUEST_RPC_HANDLE));
+ }
+
+ if (!err && server_died) {
+ err = cci_check_error (ccErrServerUnavailable);
+ }
+#if 0
+ if (err == BOOTSTRAP_UNKNOWN_SERVICE && !in_launch_server) {
+ err = ccNoError; /* If the server is not running just return an empty stream. */
+ }
+#endif
+
+ if (!err) {
+ *out_reply_stream = tspdata_getStream(ptspdata);
+ }
+
+ cci_debug_printf(" payload:<%s>", cci_stream_data(*out_reply_stream));
+
+ return cci_check_error (err);
+ }
+
+
+
+static DWORD handle_exception(DWORD code) {
+ cci_debug_printf("%s code %u; ccs_request_IfHandle:0x%X", __FUNCTION__, code, ccs_request_IfHandle);
+ if ( (code == RPC_S_SERVER_UNAVAILABLE) || (code == RPC_S_INVALID_BINDING) ) {
+ Client::Reconnect(0);
+ }
+ return 4;
+ }
+
+
+/* Establish a CCAPI connection with the server.
+ * The connect logic here is identical to the logic in the send request code.
+ * TODO: merge this connect code with that request code.
+ */
+cc_int32 ccapi_connect(const struct tspdata* tsp) {
+ BOOL bListen = TRUE;
+ char* endpoint = NULL;
+ HANDLE replyEvent = 0;
+ RPC_STATUS status = FALSE;
+ char* uuid = NULL;
+
+ /* Start listening to our uuid before establishing the connection,
+ * so that when the server tries to call ccapi_listen, we will be ready.
+ */
+
+ /* Build complete RPC uuid using previous CCAPI implementation: */
+ replyEvent = tspdata_getReplyEvent(tsp);
+ uuid = tspdata_getUUID(tsp);
+ endpoint = clientEndpoint(uuid);
+ cci_debug_printf("%s Registering endpoint %s", __FUNCTION__, endpoint);
+
+ opts.cMinCalls = 1;
+ opts.cMaxCalls = 20;
+ opts.fDontWait = TRUE;
+
+ if (!status) {
+ status = RpcServerUseProtseqEp((RPC_CSTR)"ncalrpc",
+ opts.cMaxCalls,
+ (RPC_CSTR)endpoint,
+ sa.lpSecurityDescriptor); // SD
+ cci_check_error(status);
+ }
+
+ if (!status) {
+ status = RpcServerRegisterAuthInfo(0, // server principal
+ RPC_C_AUTHN_WINNT,
+ 0,
+ 0 );
+ cci_check_error(status);
+ }
+
+ cci_debug_printf("%s is listening ...", __FUNCTION__);
+
+ if (!status) {
+ if (!isNT()) {
+ status = RpcServerRegisterIf(ccs_reply_ServerIfHandle, // interface
+ NULL, // MgrTypeUuid
+ NULL); // MgrEpv; null means use default
+ }
+ else {
+ status = RpcServerRegisterIfEx(ccs_reply_ServerIfHandle,// interface
+ NULL, // MgrTypeUuid
+ NULL, // MgrEpv; 0 means default
+ RPC_IF_ALLOW_SECURE_ONLY,
+ opts.cMaxCalls,
+ NULL); // No security callback.
+ }
+
+ cci_check_error(status);
+
+ if (!status) {
+ status = RpcServerListen(opts.cMinCalls,
+ opts.cMaxCalls,
+ TRUE);
+ cci_check_error(status);
+ }
+ }
+
+ // Clear replyEvent so we can detect when a reply to our connect request has been received:
+ ResetEvent(replyEvent);
+
+ // We use the old CCAPI implementation to try to talk to the server.
+ // It has all the code to make the uuid, (re)connect and (re)start the server.
+ WaitForSingleObject( hCCAPIv2Mutex, INFINITE );
+ SecureClient* s = 0;
+ SecureClient::Start(s);
+ CcAutoLock* a = 0;
+ CcAutoLock::Start(a, Client::sLock);
+
+ // Initialize old CCAPI if necessary:
+ if (!status) if (!Init:: Initialized()) status = Init:: Initialize( );
+ if (!status) if (!Client::Initialized()) status = Client::Initialize(0);
+
+ // New code using new RPC procedures for sending the data and receiving a reply:
+ if (!status) {
+ RpcTryExcept {
+ ccs_rpc_connect( /* make call with user message: */
+ CCMSG_CONNECT, /* Message type */
+ (unsigned char*)&tsp, /* Our tspdata* will be sent back to the reply proc. */
+ (unsigned char*)uuid,
+ (long*)(&status) ); /* Return code */
+ }
+ RpcExcept(1) {
+ cci_check_error(RpcExceptionCode());
+ status = ccErrBadInternalMessage;
+ }
+ RpcEndExcept;
+ }
+
+ CcAutoLock::Stop(a);
+ SecureClient::Stop(s);
+ ReleaseMutex(hCCAPIv2Mutex);
+
+ if (!status) {
+ cci_debug_printf("%s Waiting for replyEvent.", __FUNCTION__);
+ status = WaitForSingleObject(replyEvent, INFINITE);//(SECONDS_TO_WAIT)*1000);
+ status = cci_check_error(RpcMgmtIsServerListening(CLIENT_REQUEST_RPC_HANDLE));
+ cci_debug_printf(" Server %sFOUND!", (status) ? "NOT " : "");
+ }
+ if (status) {
+ cci_debug_printf(" unexpected error while looking for server... (%u)", status);
+ }
+
+ cci_debug_printf("%s TODO: check connect reply result.", __FUNCTION__);
+ cci_debug_printf("%s TODO: merge this connect code with that request code.", __FUNCTION__);
+ return status;
}
\ No newline at end of file
-/*\r
- * $Header$\r
- *\r
- * Copyright 2008 Massachusetts Institute of Technology.\r
- * All Rights Reserved.\r
- *\r
- * Export of this software from the United States of America may\r
- * require a specific license from the United States Government.\r
- * It is the responsibility of any person or organization contemplating\r
- * export to obtain such a license before exporting.\r
- *\r
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and\r
- * distribute this software and its documentation for any purpose and\r
- * without fee is hereby granted, provided that the above copyright\r
- * notice appear in all copies and that both that copyright notice and\r
- * this permission notice appear in supporting documentation, and that\r
- * the name of M.I.T. not be used in advertising or publicity pertaining\r
- * to distribution of the software without specific, written prior\r
- * permission. Furthermore if you modify this software you must label\r
- * your software as modified software and not distribute it in such a\r
- * fashion that it might be confused with the original M.I.T. software.\r
- * M.I.T. makes no representations about the suitability of\r
- * this software for any purpose. It is provided "as is" without express\r
- * or implied warranty.\r
- */\r
-\r
-#include <windows.h>\r
-#include <LMCons.h>\r
-\r
-extern "C" {\r
-#include "dllmain.h"\r
-#include "tls.h"\r
-#include "cci_debugging.h"\r
-#include "ccapi_context.h"\r
-#include "client.h"\r
-\r
-//void cci_thread_init__auxinit();\r
- }\r
-\r
-#define CCAPI_V2_MUTEX_NAME TEXT("MIT_CCAPI_V4_MUTEX")\r
-\r
-// Process-specific data:\r
-static DWORD dwTlsIndex;\r
-static char _user[UNLEN+1]; // Username is used as part of the server and client endpoints.\r
-static HANDLE sessionToken;\r
-static char* ep_prefices[] = {"CCS", "CCAPI"};\r
-HANDLE hCCAPIv2Mutex = NULL;\r
-DWORD firstThreadID = 0;\r
-\r
-// These data structures are used by the old CCAPI implementation \r
-// to keep track of the state of the RPC connection. All data is static.\r
-static Init init;\r
-static Client client;\r
-\r
-// DllMain() is the entry-point function for this DLL. \r
-BOOL WINAPI DllMain(HINSTANCE hinstDLL, // DLL module handle\r
- DWORD fdwReason, // reason called\r
- LPVOID lpvReserved) { // reserved \r
-\r
- struct tspdata* ptspdata;\r
- BOOL fIgnore;\r
- BOOL bStatus;\r
- DWORD status = 0; // 0 is success.\r
- DWORD maxUN = sizeof(_user);\r
- unsigned int i = 0;\r
- unsigned int j = 0;\r
- \r
- switch (fdwReason) { \r
- // The DLL is loading due to process initialization or a call to LoadLibrary:\r
- case DLL_PROCESS_ATTACH: \r
- cci_debug_printf("%s DLL_PROCESS_ATTACH", __FUNCTION__);\r
- // Process-wide mutex used to allow only one thread at a time into the RPC code:\r
- hCCAPIv2Mutex = CreateMutex(NULL, FALSE, CCAPI_V2_MUTEX_NAME);\r
-\r
- // Figure out our username; it's process-wide:\r
- bStatus = GetUserName(_user, &maxUN);\r
- if (!bStatus) return bStatus;\r
-\r
- // Remove any characters that aren't valid endpoint characters:\r
- while (_user[j] != 0) {\r
- if (isalnum(_user[j])) _user[i++] = _user[j];\r
- j++;\r
- }\r
- _user[i] = '\0';\r
-\r
- // Our logon session is determined in client.cxx, old CCAPI code carried\r
- // over to this implementation.\r
-\r
- // Allocate a TLS index:\r
- if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE; \r
- \r
- // Initialize CCAPI once per DLL load:\r
- firstThreadID = GetCurrentThreadId();\r
-\r
- // Don't break; fallthrough: Initialize the TLS index for first thread.\r
- \r
- // The attached process creates a new thread:\r
- case DLL_THREAD_ATTACH:\r
- // Initialize the TLS index for this thread:\r
- ptspdata = (struct tspdata*) LocalAlloc(LPTR, sizeof(struct tspdata)); \r
- cci_debug_printf("%s DLL_THREAD_ATTACH; tsp*:0x%X", __FUNCTION__, ptspdata);\r
- if (ptspdata == NULL) return FALSE;\r
- fIgnore = TlsSetValue(dwTlsIndex, ptspdata); \r
-\r
- memset(ptspdata, 0, sizeof(struct tspdata));\r
-\r
- // Initialize CCAPI once per DLL load:\r
- if (GetCurrentThreadId() == firstThreadID) cci_thread_init__auxinit();\r
-\r
- break; \r
- \r
- // The thread of the attached process terminates:\r
- case DLL_THREAD_DETACH: \r
- cci_debug_printf("%s DLL_THREAD_DETACH", __FUNCTION__);\r
- // Release the allocated memory for this thread:\r
- ptspdata = (struct tspdata*)TlsGetValue(dwTlsIndex); \r
- if (ptspdata != NULL) {\r
- LocalFree((HLOCAL) ptspdata); \r
- TlsSetValue(dwTlsIndex, NULL); \r
- }\r
- break; \r
- \r
- // DLL unload due to process termination or FreeLibrary:\r
- case DLL_PROCESS_DETACH: \r
- cci_debug_printf("%s DLL_PROCESS_DETACH", __FUNCTION__);\r
- //++ Copied from previous implementation:\r
- // Process Teardown "Problem"\r
- //\r
- // There are two problems that occur during process teardown:\r
- //\r
- // 1) Windows (NT/9x/2000) does not keep track of load/unload\r
- // ordering dependencies for use in process teardown.\r
- //\r
- // 2) The RPC exception handling in the RPC calls do not work\r
- // during process shutdown in Win9x.\r
- //\r
- // When a process is being torn down in Windows, the krbcc DLL\r
- // may get a DLL_PROCESS_DETACH before other DLLs are done\r
- // with it. Thus, it may disconnect from the RPC server\r
- // before the last shutdown RPC call.\r
- //\r
- // On NT/2000, this is ok because the RPC call will fail and just\r
- // return an error.\r
- //\r
- // On Win9x/Me, the RPC exception will not be caught.\r
- // However, Win9x ignores exceptions during process shutdown,\r
- // so the exception will never be seen unless a debugger is\r
- // attached to the proccess.\r
- //\r
- // A good potential woraround would be to have a global\r
- // variable that denotes whether the DLL is attached to the\r
- // process. If it is not, all entrypoints into the DLL should\r
- // return failure.\r
- //\r
- // A not as good workaround is below but ifdefed out.\r
- //\r
- // However, we can safely ignore this problem since it can\r
- // only affects people running debuggers under 9x/Me who are\r
- // using multiple DLLs that use this DLL.\r
- //\r
- WaitForSingleObject( hCCAPIv2Mutex, INFINITE );\r
-#if 0\r
- bool process_teardown_workaround = false;\r
- if (lpvReserved) {\r
- Init::InitInfo info;\r
- status = Init::Info(info);\r
- if (status) break;\r
- if (!info.isNT) process_teardown_workaround = true;\r
- }\r
- if (process_teardown_workaround)\r
- break;\r
-#endif\r
- // return value is ignored, so we set status for debugging purposes\r
- status = Client::Cleanup();\r
- status = Init::Cleanup();\r
- ReleaseMutex( hCCAPIv2Mutex );\r
- CloseHandle( hCCAPIv2Mutex );\r
- //-- Copied from previous implementation.\r
-\r
- // Release the allocated memory for this thread:\r
- ptspdata = (struct tspdata*)TlsGetValue(dwTlsIndex); \r
- if (ptspdata != NULL) LocalFree((HLOCAL) ptspdata);\r
- TlsFree(dwTlsIndex); // Release the TLS index.\r
- break; \r
- \r
- default: break; \r
- } \r
- \r
- UNREFERENCED_PARAMETER(hinstDLL); // no whining!\r
- UNREFERENCED_PARAMETER(lpvReserved); \r
- return status ? FALSE : TRUE;\r
-}\r
-\r
-\r
-#ifdef __cplusplus // If used by C++ code, \r
-extern "C" { // we need to export the C interface\r
-#endif\r
-\r
-__declspec(dllexport)\r
-BOOL WINAPI PutTspData(struct tspdata* dw) {\r
- LPVOID lpvData; \r
- struct tspdata** pData; // The stored memory pointer \r
-\r
- // Retrieve a data pointer for the current thread:\r
- lpvData = TlsGetValue(dwTlsIndex); \r
-\r
- // If NULL, allocate memory for the TLS slot for this thread:\r
- if (lpvData == NULL) {\r
- lpvData = (LPVOID) LocalAlloc(LPTR, sizeof(struct tspdata)); \r
- if (lpvData == NULL) return FALSE;\r
- if (!TlsSetValue(dwTlsIndex, lpvData)) return FALSE;\r
- }\r
-\r
- pData = (struct tspdata**) lpvData; // Cast to my data type.\r
- // In this example, it is only a pointer to a DWORD\r
- // but it can be a structure pointer to contain more complicated data.\r
-\r
- (*pData) = dw;\r
- return TRUE;\r
- }\r
-\r
-__declspec(dllexport)\r
-BOOL WINAPI GetTspData(struct tspdata** pdw) {\r
- struct tspdata* pData; // The stored memory pointer \r
-\r
- pData = (struct tspdata*)TlsGetValue(dwTlsIndex); \r
- if (pData == NULL) return FALSE;\r
- (*pdw) = pData;\r
- return TRUE;\r
- }\r
-\r
-#if 0 // replaced by clientEndpoint / serverEndpoint.\r
-__declspec(dllexport)\r
-char* WINAPI getEndpoint(enum EndpointType ep) {\r
- // The server endpoint is of the form CCS_<LSID>\r
- // The client endpoint is of the form CCAPI_<uuid>\r
- // Each client thread can have its own connection.\r
- //\r
- // NB: Caller must free the data the returned char* points to.\r
- struct tspdata* pData;\r
- char* s;\r
- char* uuid;\r
- unsigned int len;\r
-\r
- switch (ep) {\r
- case EPT_SERVER:\r
- s = (char*)malloc(32); // Length of CCS_<DWORD>\r
- sprintf(s, "%s_%ld", ep_prefices[EPT_SERVER], sessionToken);\r
- break;\r
- case EPT_CLIENT:\r
- GetTspData(&pData);\r
- uuid = tspdata_getUUID(pData);\r
- len = 4 + strlen(ep_prefices[ep]) + strlen(_user) + strlen(uuid);\r
- s = (char*)malloc(len);\r
- sprintf(s, "%s_%s_%s", ep_prefices[EPT_CLIENT], _user, uuid);\r
- break;\r
- default:;\r
- }\r
- cci_debug_printf("%s(%d) returning %s", __FUNCTION__, ep, s);\r
-\r
- return s;\r
- }\r
-#endif\r
-\r
-#ifdef __cplusplus\r
-}\r
-#endif\r
-\r
-/*********************************************************************/\r
-/* MIDL allocate and free */\r
-/*********************************************************************/\r
-\r
-void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len) {\r
- return(malloc(len));\r
- }\r
-\r
-void __RPC_USER midl_user_free(void __RPC_FAR * ptr) {\r
- free(ptr);\r
- }\r
+/*
+ * $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 <windows.h>
+#include <LMCons.h>
+
+extern "C" {
+#include "dllmain.h"
+#include "tls.h"
+#include "cci_debugging.h"
+#include "ccapi_context.h"
+#include "client.h"
+
+//void cci_thread_init__auxinit();
+ }
+
+#define CCAPI_V2_MUTEX_NAME TEXT("MIT_CCAPI_V4_MUTEX")
+
+// Process-specific data:
+static DWORD dwTlsIndex;
+static char _user[UNLEN+1]; // Username is used as part of the server and client endpoints.
+static HANDLE sessionToken;
+static char* ep_prefices[] = {"CCS", "CCAPI"};
+HANDLE hCCAPIv2Mutex = NULL;
+DWORD firstThreadID = 0;
+
+// These data structures are used by the old CCAPI implementation
+// to keep track of the state of the RPC connection. All data is static.
+static Init init;
+static Client client;
+
+// DllMain() is the entry-point function for this DLL.
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, // DLL module handle
+ DWORD fdwReason, // reason called
+ LPVOID lpvReserved) { // reserved
+
+ struct tspdata* ptspdata;
+ BOOL fIgnore;
+ BOOL bStatus;
+ DWORD status = 0; // 0 is success.
+ DWORD maxUN = sizeof(_user);
+ unsigned int i = 0;
+ unsigned int j = 0;
+
+ switch (fdwReason) {
+ // The DLL is loading due to process initialization or a call to LoadLibrary:
+ case DLL_PROCESS_ATTACH:
+ cci_debug_printf("%s DLL_PROCESS_ATTACH", __FUNCTION__);
+ // Process-wide mutex used to allow only one thread at a time into the RPC code:
+ hCCAPIv2Mutex = CreateMutex(NULL, FALSE, CCAPI_V2_MUTEX_NAME);
+
+ // Figure out our username; it's process-wide:
+ bStatus = GetUserName(_user, &maxUN);
+ if (!bStatus) return bStatus;
+
+ // Remove any characters that aren't valid endpoint characters:
+ while (_user[j] != 0) {
+ if (isalnum(_user[j])) _user[i++] = _user[j];
+ j++;
+ }
+ _user[i] = '\0';
+
+ // Our logon session is determined in client.cxx, old CCAPI code carried
+ // over to this implementation.
+
+ // Allocate a TLS index:
+ if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
+
+ // Initialize CCAPI once per DLL load:
+ firstThreadID = GetCurrentThreadId();
+
+ // Don't break; fallthrough: Initialize the TLS index for first thread.
+
+ // The attached process creates a new thread:
+ case DLL_THREAD_ATTACH:
+ // Initialize the TLS index for this thread:
+ ptspdata = (struct tspdata*) LocalAlloc(LPTR, sizeof(struct tspdata));
+ cci_debug_printf("%s DLL_THREAD_ATTACH; tsp*:0x%X", __FUNCTION__, ptspdata);
+ if (ptspdata == NULL) return FALSE;
+ fIgnore = TlsSetValue(dwTlsIndex, ptspdata);
+
+ memset(ptspdata, 0, sizeof(struct tspdata));
+
+ // Initialize CCAPI once per DLL load:
+ if (GetCurrentThreadId() == firstThreadID) cci_thread_init__auxinit();
+
+ break;
+
+ // The thread of the attached process terminates:
+ case DLL_THREAD_DETACH:
+ cci_debug_printf("%s DLL_THREAD_DETACH", __FUNCTION__);
+ // Release the allocated memory for this thread:
+ ptspdata = (struct tspdata*)TlsGetValue(dwTlsIndex);
+ if (ptspdata != NULL) {
+ LocalFree((HLOCAL) ptspdata);
+ TlsSetValue(dwTlsIndex, NULL);
+ }
+ break;
+
+ // DLL unload due to process termination or FreeLibrary:
+ case DLL_PROCESS_DETACH:
+ cci_debug_printf("%s DLL_PROCESS_DETACH", __FUNCTION__);
+ //++ Copied from previous implementation:
+ // Process Teardown "Problem"
+ //
+ // There are two problems that occur during process teardown:
+ //
+ // 1) Windows (NT/9x/2000) does not keep track of load/unload
+ // ordering dependencies for use in process teardown.
+ //
+ // 2) The RPC exception handling in the RPC calls do not work
+ // during process shutdown in Win9x.
+ //
+ // When a process is being torn down in Windows, the krbcc DLL
+ // may get a DLL_PROCESS_DETACH before other DLLs are done
+ // with it. Thus, it may disconnect from the RPC server
+ // before the last shutdown RPC call.
+ //
+ // On NT/2000, this is ok because the RPC call will fail and just
+ // return an error.
+ //
+ // On Win9x/Me, the RPC exception will not be caught.
+ // However, Win9x ignores exceptions during process shutdown,
+ // so the exception will never be seen unless a debugger is
+ // attached to the proccess.
+ //
+ // A good potential woraround would be to have a global
+ // variable that denotes whether the DLL is attached to the
+ // process. If it is not, all entrypoints into the DLL should
+ // return failure.
+ //
+ // A not as good workaround is below but ifdefed out.
+ //
+ // However, we can safely ignore this problem since it can
+ // only affects people running debuggers under 9x/Me who are
+ // using multiple DLLs that use this DLL.
+ //
+ WaitForSingleObject( hCCAPIv2Mutex, INFINITE );
+#if 0
+ bool process_teardown_workaround = false;
+ if (lpvReserved) {
+ Init::InitInfo info;
+ status = Init::Info(info);
+ if (status) break;
+ if (!info.isNT) process_teardown_workaround = true;
+ }
+ if (process_teardown_workaround)
+ break;
+#endif
+ // return value is ignored, so we set status for debugging purposes
+ status = Client::Cleanup();
+ status = Init::Cleanup();
+ ReleaseMutex( hCCAPIv2Mutex );
+ CloseHandle( hCCAPIv2Mutex );
+ //-- Copied from previous implementation.
+
+ // Release the allocated memory for this thread:
+ ptspdata = (struct tspdata*)TlsGetValue(dwTlsIndex);
+ if (ptspdata != NULL) LocalFree((HLOCAL) ptspdata);
+ TlsFree(dwTlsIndex); // Release the TLS index.
+ break;
+
+ default: break;
+ }
+
+ UNREFERENCED_PARAMETER(hinstDLL); // no whining!
+ UNREFERENCED_PARAMETER(lpvReserved);
+ return status ? FALSE : TRUE;
+}
+
+
+#ifdef __cplusplus // If used by C++ code,
+extern "C" { // we need to export the C interface
+#endif
+
+__declspec(dllexport)
+BOOL WINAPI PutTspData(struct tspdata* dw) {
+ LPVOID lpvData;
+ struct tspdata** pData; // The stored memory pointer
+
+ // Retrieve a data pointer for the current thread:
+ lpvData = TlsGetValue(dwTlsIndex);
+
+ // If NULL, allocate memory for the TLS slot for this thread:
+ if (lpvData == NULL) {
+ lpvData = (LPVOID) LocalAlloc(LPTR, sizeof(struct tspdata));
+ if (lpvData == NULL) return FALSE;
+ if (!TlsSetValue(dwTlsIndex, lpvData)) return FALSE;
+ }
+
+ pData = (struct tspdata**) lpvData; // Cast to my data type.
+ // In this example, it is only a pointer to a DWORD
+ // but it can be a structure pointer to contain more complicated data.
+
+ (*pData) = dw;
+ return TRUE;
+ }
+
+__declspec(dllexport)
+BOOL WINAPI GetTspData(struct tspdata** pdw) {
+ struct tspdata* pData; // The stored memory pointer
+
+ pData = (struct tspdata*)TlsGetValue(dwTlsIndex);
+ if (pData == NULL) return FALSE;
+ (*pdw) = pData;
+ return TRUE;
+ }
+
+#if 0 // replaced by clientEndpoint / serverEndpoint.
+__declspec(dllexport)
+char* WINAPI getEndpoint(enum EndpointType ep) {
+ // The server endpoint is of the form CCS_<LSID>
+ // The client endpoint is of the form CCAPI_<uuid>
+ // Each client thread can have its own connection.
+ //
+ // NB: Caller must free the data the returned char* points to.
+ struct tspdata* pData;
+ char* s;
+ char* uuid;
+ unsigned int len;
+
+ switch (ep) {
+ case EPT_SERVER:
+ s = (char*)malloc(32); // Length of CCS_<DWORD>
+ sprintf(s, "%s_%ld", ep_prefices[EPT_SERVER], sessionToken);
+ break;
+ case EPT_CLIENT:
+ GetTspData(&pData);
+ uuid = tspdata_getUUID(pData);
+ len = 4 + strlen(ep_prefices[ep]) + strlen(_user) + strlen(uuid);
+ s = (char*)malloc(len);
+ sprintf(s, "%s_%s_%s", ep_prefices[EPT_CLIENT], _user, uuid);
+ break;
+ default:;
+ }
+ cci_debug_printf("%s(%d) returning %s", __FUNCTION__, ep, s);
+
+ return s;
+ }
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*********************************************************************/
+/* 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);
+ }
-# . is ccapi/test.\r
-CO = ..\common\r
-COWIN = $(CO)\win\r
-LIBDIR = ..\lib\r
-LIBWIN = $(LIBDIR)\win\r
-SRV = ..\server\r
-SRVWIN = ..\server\win\r
-\r
-!include <Win32.Mak>\r
-\r
-INC = -I..\..\include -I..\..\util\et -I$(CO) -I$(COWIN) -I$(LIBDIR) -I$(LIBWIN)\r
-\r
-!if "$(CPU)" == "i386"\r
-cflags = $(cflags) /EHsc /MTd -D_CRTAPI1=_cdecl -D_CRTAPI2=_cdecl -DWINVER=0x0501 -D_WIN32_WINNT=0x0501 \\r
-$(INC)\r
-!else\r
-cflags = $(cflags) /W3 -D_CRTAPI1= -D_CRTAPI2= $(INC)\r
-!endif\r
-LIBS = $(LIBWIN)\ccapi.lib\r
-\r
-DSTROOT = .\r
-SRC = $(DSTROOT)\r
-#OBJDIR = $(DSTROOT)\obj\r
-OBJDIR = .\r
-OBJEXT = obj\r
-TESTDIR = $(DSTROOT)\tests\r
-TESTEXT = exe\r
-DSTDIR = $(DSTROOT)\ccapi_tests\r
-\r
-PINGOBJS = pingtest.obj \r
-SIMPLEOBJS = simple_lock_test.obj\r
-\r
-comobjs = cci_debugging.obj cci_stream.obj\r
-cowobjs = cci_os_debugging.obj \r
-libobjs = ccs_request_c.obj\r
- \r
-#all: build-base simple_lock_test pingtest \r
-all: build-base pingtest \r
-\r
-# compile base files used by all tests\r
-build-base: $(comobjs) $(libobjs) $(srvobjs)\r
- @echo "Base objects built."\r
-\r
-# rule to compile src files\r
-.c.obj:\r
- $(cc) $(cdebug) $(cflags) /Fo$(OBJDIR)\$(*B).$(OBJEXT) $(SRC)\$(*B).c\r
-\r
-$(comobjs) : $(CO)\$(*B).c\r
- $(cc) $(cdebug) $(cflags) $(CO)\$(*B).c\r
-\r
-$(cowobjs) : $(COWIN)\$(*B).c\r
- $(cc) $(cdebug) $(cflags) $(COWIN)\$(*B).c\r
-\r
-$(libobjs) : $(LIBWIN)\$(*B).c\r
- $(cc) $(cdebug) $(cflags) $(LIBWIN)\$(*B).c\r
-\r
-#$(srvobjs) : $(SRVWIN)\$*.c\r
-# $(cc) $(cdebug) $(cflags) $(SRVWIN)\$*.c\r
-\r
-simple_lock_test: simple_lock_test.obj $(OBJS)\r
- @echo R3+ Build $(*B) in $(TESTDIR)\r
- $(cc) $(cdebug) $(cflags) $(*B).c\r
- $(link) $(linkdebug) $(conflags) -out:$(TESTDIR)\$(*B).exe $(*B).obj \\r
- $(LIBS) rpcrt4.lib\r
- @echo R3- Built $(*B) in $(TESTDIR)\r
-\r
-pingtest: pingtest.obj\r
- @echo R4+ Build $(*B) in $(TESTDIR)\r
- $(cc) $(cdebug) $(cflags) $(*B).c\r
- $(link) $(linkdebug) $(conflags) -out:$(*B).exe $(PINGOBJS) $(libobjs) $(srvobjs) \\r
- $(LIBS) rpcrt4.lib\r
- @echo R4- Built $(*B) in $(TESTDIR)\r
-\r
-clean:\r
+# . is ccapi/test.
+CO = ..\common
+COWIN = $(CO)\win
+LIBDIR = ..\lib
+LIBWIN = $(LIBDIR)\win
+SRV = ..\server
+SRVWIN = ..\server\win
+
+!include <Win32.Mak>
+
+INC = -I..\..\include -I..\..\util\et -I$(CO) -I$(COWIN) -I$(LIBDIR) -I$(LIBWIN)
+
+!if "$(CPU)" == "i386"
+cflags = $(cflags) /EHsc /MTd -D_CRTAPI1=_cdecl -D_CRTAPI2=_cdecl -DWINVER=0x0501 -D_WIN32_WINNT=0x0501 \
+$(INC)
+!else
+cflags = $(cflags) /W3 -D_CRTAPI1= -D_CRTAPI2= $(INC)
+!endif
+LIBS = $(LIBWIN)\ccapi.lib
+
+DSTROOT = .
+SRC = $(DSTROOT)
+#OBJDIR = $(DSTROOT)\obj
+OBJDIR = .
+OBJEXT = obj
+TESTDIR = $(DSTROOT)\tests
+TESTEXT = exe
+DSTDIR = $(DSTROOT)\ccapi_tests
+
+PINGOBJS = pingtest.obj
+SIMPLEOBJS = simple_lock_test.obj
+
+comobjs = cci_debugging.obj cci_stream.obj
+cowobjs = cci_os_debugging.obj
+libobjs = ccs_request_c.obj
+
+#all: build-base simple_lock_test pingtest
+all: build-base pingtest
+
+# compile base files used by all tests
+build-base: $(comobjs) $(libobjs) $(srvobjs)
+ @echo "Base objects built."
+
+# rule to compile src files
+.c.obj:
+ $(cc) $(cdebug) $(cflags) /Fo$(OBJDIR)\$(*B).$(OBJEXT) $(SRC)\$(*B).c
+
+$(comobjs) : $(CO)\$(*B).c
+ $(cc) $(cdebug) $(cflags) $(CO)\$(*B).c
+
+$(cowobjs) : $(COWIN)\$(*B).c
+ $(cc) $(cdebug) $(cflags) $(COWIN)\$(*B).c
+
+$(libobjs) : $(LIBWIN)\$(*B).c
+ $(cc) $(cdebug) $(cflags) $(LIBWIN)\$(*B).c
+
+#$(srvobjs) : $(SRVWIN)\$*.c
+# $(cc) $(cdebug) $(cflags) $(SRVWIN)\$*.c
+
+simple_lock_test: simple_lock_test.obj $(OBJS)
+ @echo R3+ Build $(*B) in $(TESTDIR)
+ $(cc) $(cdebug) $(cflags) $(*B).c
+ $(link) $(linkdebug) $(conflags) -out:$(TESTDIR)\$(*B).exe $(*B).obj \
+ $(LIBS) rpcrt4.lib
+ @echo R3- Built $(*B) in $(TESTDIR)
+
+pingtest: pingtest.obj
+ @echo R4+ Build $(*B) in $(TESTDIR)
+ $(cc) $(cdebug) $(cflags) $(*B).c
+ $(link) $(linkdebug) $(conflags) -out:$(*B).exe $(PINGOBJS) $(libobjs) $(srvobjs) \
+ $(LIBS) rpcrt4.lib
+ @echo R4- Built $(*B) in $(TESTDIR)
+
+clean:
DEL *.$(OBJEXT)
\ No newline at end of file