more eol-style
authorKen Raeburn <raeburn@mit.edu>
Tue, 5 Feb 2008 18:33:20 +0000 (18:33 +0000)
committerKen Raeburn <raeburn@mit.edu>
Tue, 5 Feb 2008 18:33:20 +0000 (18:33 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@20218 dc483132-0cff-0310-8789-dd5450dbe970

21 files changed:
src/ccapi/common/win/OldCC/autolock.hxx
src/ccapi/common/win/OldCC/ccutil.cxx
src/ccapi/common/win/OldCC/ccutil.def
src/ccapi/common/win/OldCC/init.cxx
src/ccapi/common/win/OldCC/init.hxx
src/ccapi/common/win/OldCC/opts.cxx
src/ccapi/common/win/OldCC/opts.hxx
src/ccapi/common/win/OldCC/secure.cxx
src/ccapi/common/win/OldCC/secure.hxx
src/ccapi/common/win/OldCC/util.cxx
src/ccapi/common/win/ccs_reply.Acf
src/ccapi/common/win/ccs_reply.Idl
src/ccapi/common/win/ccs_request.Acf
src/ccapi/common/win/ccs_request.idl
src/ccapi/doc/CCAPI-Windows-Design.html
src/ccapi/lib/win/OldCC/client.cxx
src/ccapi/lib/win/OldCC/rpc.cxx
src/ccapi/lib/win/ccapi.def
src/ccapi/lib/win/ccapi_os_ipc.cxx
src/ccapi/lib/win/dllmain.cxx
src/ccapi/test/Makefile.w32

index 9fc7595140127bc6054dec393783d96cb281298b..bbd773488c0271d9b354647a877e06b19620f64d 100644 (file)
@@ -1,53 +1,53 @@
-/*\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 */
index e5e5baef561979e6563c2094143844b5c5532de1..729104de7ed3d53651393643dde1542921573ba3 100644 (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;
+}
index a187c805d0221798e122a7cfd3a09075ddcdd8ef..57113f094ea3c556394bc81f634ec963d82e16db 100644 (file)
@@ -1,5 +1,5 @@
-;LIBRARY               COMERR32\r
-HEAPSIZE       8192\r
-\r
-EXPORTS\r
+;LIBRARY               COMERR32
+HEAPSIZE       8192
+
+EXPORTS
     
\ No newline at end of file
index af93722feb21f55c45b47ee3179e8b1566d9761b..feb7ad3ad957a64e9ee5773f419be24d6f113ca0 100644 (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;
+}
index f50db776abba5531b0c7e74c955ca9d8f8d88acb..9bac7f8f9e252d939d1aea65dbc15f4af9b67b60 100644 (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
-#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)
index c6a40d64db51e50fb7e9afb0034732dced4a9704..bd5f503ea63f988245ee6eea22b86f761196767a 100644 (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 <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()
+{
+}
index 1732ceb2592e3c954f7808e93e46516ffc71ef1a..755ce4ae609adc333fcc6ae57b2823240f835cfa 100644 (file)
@@ -1,56 +1,56 @@
-/*\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];
+};
index a32235fd6480b1d1243f559f5a7b357dc91cac5a..99ba08a25dd463376330a0cd9b42643942e31a1f 100644 (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 "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
index 009e36c74804e43cd5e204f581d70580608b088a..3714c6f847234db9d3c64880f1a1ae8928d5dbb2 100644 (file)
@@ -1,60 +1,60 @@
-/*\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;
+};
index 62b204b927af2eb0724525aca14409ed3fb65d72..8694c373ce9bb4f3c99b22743adf47f26240ebac 100644 (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 <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;
+    }
index 89e8abe7adaedb36edd573fe17350bbd2ff7a550..aea44d74c62fdc76d2c6cb43e14dee092e104b81 100644 (file)
@@ -1,31 +1,31 @@
-/*\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();
+    }
index 4c6f6f3043e9356676300383c7dd00ed540906c6..9035a4d00172ea58e0dd391f0ea6f500934c8c14 100644 (file)
@@ -1,60 +1,60 @@
-/*\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 */
+
+    }
index 853a15252a50045579d1b58a70371bb9ab1c189a..625bcce6532b3ef51c0ad1b092a095c8e9b9b653 100644 (file)
@@ -1,31 +1,31 @@
-/*\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
+{
+
+}
index bd693142c009b9d183e5a891f5a593272f30e604..8c68fd8f3a0649922b0944524985bbff2521483b 100644 (file)
@@ -1,58 +1,58 @@
-/*\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 );
+}
index 8be161447a6a83b4c02d754cd804bdb5f3a12efe..72af7e92a7ba28a4bf216d420cee6928d48fc7ae 100644 (file)
-<!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 &amp; clarifications </h2>\r
-<p>&quot;Client&quot; and &quot;server&quot; 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 &quot;request.&quot; 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 &quot;reply.&quot; 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 &quot;&lt;USER&gt;.&quot; </p>\r
-<p>The Windows Logon Security Identifier is referred to as &quot;&lt;LSID&gt;.&quot; </p>\r
-<p>&lt;UUID&gt; means a thread-specific UUID.</p>\r
-<p>&lt;SST&gt; 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_&lt;LSID&gt; and the client's endpoint is CCAPI_&lt;UUID&gt;, 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_&lt;LSID&gt; endpoint to listen for connection requests and client requests. \r
-    It has the functions\r
-    <ul>\r
-      <li>ccs_rpc_connect(msgtype, UUIDlen, &lt;UUID&gt;, status)</li>\r
-      <li>ccs_rpc_request(msgtype, UUIDlen, &lt;UUID&gt;, 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_&lt;UUID&gt; 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 &lt;UUID&gt; 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 &lt;LSID&gt;, which the client and server should have in common. </li>\r
-  <li>Test if server is listening to the CCS_&lt;LSID&gt; endpoint.\r
-      <ul>\r
-        <li>If not, quit. (! Start it?) </li>\r
-      </ul>\r
-  </li>\r
-  <li>Call ccs_connect(&lt;UUID&gt;) on the CCS_&lt;LSID&gt; 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_&lt;LSID&gt; endpoint. </li>\r
-</ul>\r
-<h3>Establishing a connection: </h3>\r
-<ul>\r
-  <li>Client calls ccs_connect(&lt;UUID&gt;) on server's CCS_&lt;LSID&gt; 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_&lt;UUID&gt;.\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, &lt;UUID&gt;, 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_&lt;UUID&gt;.</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>&nbsp;</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 &amp; clarifications </h2>
+<p>&quot;Client&quot; and &quot;server&quot; 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 &quot;request.&quot; 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 &quot;reply.&quot; 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 &quot;&lt;USER&gt;.&quot; </p>
+<p>The Windows Logon Security Identifier is referred to as &quot;&lt;LSID&gt;.&quot; </p>
+<p>&lt;UUID&gt; means a thread-specific UUID.</p>
+<p>&lt;SST&gt; 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_&lt;LSID&gt; and the client's endpoint is CCAPI_&lt;UUID&gt;, 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_&lt;LSID&gt; endpoint to listen for connection requests and client requests. 
+    It has the functions
+    <ul>
+      <li>ccs_rpc_connect(msgtype, UUIDlen, &lt;UUID&gt;, status)</li>
+      <li>ccs_rpc_request(msgtype, UUIDlen, &lt;UUID&gt;, 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_&lt;UUID&gt; 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 &lt;UUID&gt; 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 &lt;LSID&gt;, which the client and server should have in common. </li>
+  <li>Test if server is listening to the CCS_&lt;LSID&gt; endpoint.
+      <ul>
+        <li>If not, quit. (! Start it?) </li>
+      </ul>
+  </li>
+  <li>Call ccs_connect(&lt;UUID&gt;) on the CCS_&lt;LSID&gt; 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_&lt;LSID&gt; endpoint. </li>
+</ul>
+<h3>Establishing a connection: </h3>
+<ul>
+  <li>Client calls ccs_connect(&lt;UUID&gt;) on server's CCS_&lt;LSID&gt; 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_&lt;UUID&gt;.
+        <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, &lt;UUID&gt;, 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_&lt;UUID&gt;.</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>&nbsp;</p>
+<p>------<br />
+  Stop: <br />
+Start: </p>
+</body>
+</html>
index 1f9051093f7039b87fe8914b0b78e1178985f427..4928d4c5363814f689c8d75c0417c67a3ae203ff 100644 (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 "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;
+    }
index 332f1c503b9393c23ff08acd756ee526cc25457b..29edc3c5792f7a9ffdd421f282dc9d0c32a1be2e 100644 (file)
@@ -1,79 +1,79 @@
-/*\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
index 0450331ece1aabe9a0a0e58ed8ea2942f22e6baf..d062e55f52b181e1ef5e466172e8d53edacd15a8 100644 (file)
@@ -1,39 +1,39 @@
-;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
index 7ee917627736f7270947d6af90810a96508d4c7d..770e75b6a80826488d61082b7eda5672ba4d64fb 100644 (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
index 7000e1418458d1a9b672d17bfc0e306c578b15a4..dafbab28c1c4a57946afb189be6b6200a53c6612 100644 (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);
+    }
index c6e1c535dda60332d75d4962179e55516ad7dc47..8c3da95153465e2b83cb9bb9e0a86adccee22b62 100644 (file)
@@ -1,75 +1,75 @@
-# . 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