]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Plumb SCM control signals through vmtoolsd in a generic way.
authorVMware, Inc <>
Thu, 17 Dec 2009 21:44:59 +0000 (13:44 -0800)
committerMarcelo Vanzin <mvanzin@vmware.com>
Thu, 17 Dec 2009 21:44:59 +0000 (13:44 -0800)
Instead of individually plumbing every possible control code the SCM
sends to services through vmtoolsd, provide a generic plumbing mechanism
and let plugins decide what they want to do.

The only remaining issue is that a few control codes are only sent after
some specific registration step (e.g., RegisterDeviceNotification); for
those cases, either we'll need to have vmtoolsd blindly register for all
possible control codes (which is not future proof since MS may add new
ones), or, when possible (such as in the device notification example),
let plugins do the registration themselves.

Change the two existing control messages (SESSION_CHANGE and SHUTDOWN) to
use the new mechanism, and fix all current usage sites.

Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
open-vm-tools/lib/include/vmware/tools/plugin.h
open-vm-tools/services/vmtoolsd/serviceObj.c
open-vm-tools/services/vmtoolsd/svcSignals.gm
open-vm-tools/tests/testPlugin/testPlugin.c

index c8d6d94fccec5f53f6580de8a08a30eb6587165f..eb6bf52cb53c41d41d640c31994ec901aee4b7d9 100644 (file)
 #define TOOLS_CORE_SIG_SHUTDOWN "tcs_shutdown"
 
 #if defined(G_PLATFORM_WIN32)
-/**
- * Signal sent when there's a change in the state of a user's session.
- *
- * @param[in]  src      The source object.
- * @param[in]  ctx      ToolsAppCtx *: The application context.
- * @param[in]  code     DWORD: Session state change code.
- * @param[in]  id       DWORD: Session ID.
- * @param[in]  data     Client data.
- */
-#define TOOLS_CORE_SIG_SESSION_CHANGE  "tcs_session_change"
 
 /**
- * Signal sent when the pre shutdown event is received in the service.
+ * Signal sent when the service receives a control message. For a list
+ * of control messages, see the documentation on MSDN:
+ *
+ *    http://msdn.microsoft.com/en-us/library/ms683241%28VS.85%29.aspx
+ *
+ * The signal is only available on Win32. Receiving this signal doesn't
+ * mean the service is running through the Windows SCM: plugins may detect
+ * equivalent notifications through other means and send this signal with
+ * the appropriate parameters so others can react to them.
  *
  * @param[in]  src      The source object.
  * @param[in]  ctx      ToolsAppCtx *: The application context.
- * @param[in]  handle   SERVICE_STATUS_HANDLE: Service status handle.
+ * @param[in]  handle   SERVICE_STATUS_HANDLE: Service status handle. May be
+ *                      NULL if process is not under SCM control.
+ * @param[in]  control  guint: The control code.
+ * @param[in]  evtType  guint: The event type.
+ * @param[in]  evtData  gpointer: Event data.
  * @param[in]  data     Client data.
+ *
+ * @return See MSDN documentation. NO_ERROR has precedence over
+ * ERROR_CALL_NOT_IMPLEMENTED; if any handler returns any value other than
+ * those two, then that value will be used as the return value, unless the
+ * Tools service itself also handles the control message, or the MSDN
+ * documentation specifies a return value.
  */
-#define TOOLS_CORE_SIG_PRESHUTDOWN "tcs_preshutdown"
+#define TOOLS_CORE_SIG_SERVICE_CONTROL  "tcs_service_control"
 
 #endif
 
index 30394dda90bbe8d91541841085bb7d55a66eac6e..7447592136b6697889a5ab28e45ba1329a3012b3 100644 (file)
@@ -92,6 +92,46 @@ ToolsCoreCapabilitiesAccumulator(GSignalInvocationHint *ihint,
 }
 
 
+#if defined(_WIN32)
+/**
+ * Accumulator function for the "service control" signal. Updates the return
+ * value according to the signal's documentation.
+ *
+ * @param[in]  ihint       Unused.
+ * @param[out] retval      Return value of the signal.
+ * @param[in]  handlerRet  Return value from the current handler.
+ * @param[in]  data        Unused.
+ *
+ * @return TRUE.
+ */
+
+static gboolean
+ToolsCoreServiceControlAccumulator(GSignalInvocationHint *ihint,
+                                   GValue *retval,
+                                   const GValue *handlerRet,
+                                   gpointer data)
+{
+   guint ret = g_value_get_uint(retval);
+   guint handlerVal = g_value_get_uint(handlerRet);
+   switch (ret) {
+   case ERROR_CALL_NOT_IMPLEMENTED:
+      ret = handlerVal;
+      break;
+
+   case NO_ERROR:
+      if (handlerVal != ERROR_CALL_NOT_IMPLEMENTED) {
+         ret = handlerVal;
+      }
+      break;
+
+   default:
+      break;
+   }
+   g_value_set_uint(retval, ret);
+   return TRUE;
+}
+#endif
+
 /**
  * Initializes the ToolsCoreService class. Sets up the signals that are sent
  * by the vmtoolsd service.
@@ -168,29 +208,19 @@ ToolsCore_Service_class_init(gpointer _klass,
                 1,
                 G_TYPE_POINTER);
 #if defined(G_PLATFORM_WIN32)
-   g_signal_new(TOOLS_CORE_SIG_SESSION_CHANGE,
+   g_signal_new(TOOLS_CORE_SIG_SERVICE_CONTROL,
                 G_OBJECT_CLASS_TYPE(klass),
                 G_SIGNAL_RUN_LAST,
                 0,
                 NULL,
                 NULL,
-                g_cclosure_user_marshal_VOID__POINTER_UINT_UINT,
-                G_TYPE_NONE,
-                3,
-                G_TYPE_POINTER,
+                g_cclosure_user_marshal_UINT__POINTER_POINTER_UINT_UINT_POINTER,
                 G_TYPE_UINT,
-                G_TYPE_UINT);
-
-   g_signal_new(TOOLS_CORE_SIG_PRESHUTDOWN,
-                G_OBJECT_CLASS_TYPE(klass),
-                G_SIGNAL_RUN_LAST,
-                0,
-                NULL,
-                NULL,
-                g_cclosure_user_marshal_VOID__POINTER_POINTER,
-                G_TYPE_NONE,
-                2,
+                5,
+                G_TYPE_POINTER,
                 G_TYPE_POINTER,
+                G_TYPE_UINT,
+                G_TYPE_UINT,
                 G_TYPE_POINTER);
 #endif
 }
index 37629ed152589e955e63a78195ed891fb51d4066..fb2410e7684d6459f40a07456c71ad3b798ac708 100644 (file)
@@ -30,11 +30,7 @@ POINTER:POINTER,BOOLEAN
 # The "set option" signal.
 BOOLEAN:POINTER,STRING,STRING
 
-# The "session change" signal.
+# The "service control" signal.
 # Used on Win32 only.
-VOID:POINTER,UINT,UINT
-
-# The "pre shutdown" signal.
-# Used on Win32 only.
-VOID:POINTER,POINTER
+UINT:POINTER,POINTER,UINT,UINT,POINTER
 
index f7ef4fe8ccc24022ac83bb500c63210d7405fbdc..917aca5ca4839d585a482581b7a44cb4f5bf3bec 100644 (file)
@@ -182,47 +182,31 @@ TestPluginReset(gpointer src,
 
 #if defined(G_PLATFORM_WIN32)
 /**
- * Handles a session state change callback; this is only called on Windows,
- * from both the "vmsvc" instance (handled by SCM notifications) and from
- * "vmusr" with the "fast user switch" plugin.
+ * Handles a service control signal; this is only called on Windows.
  *
- * @param[in]  src      The source object.
- * @param[in]  ctx      The application context.
- * @param[in]  code     Session state change code.
- * @param[in]  id       Session ID.
- * @param[in]  data     Client data.
- */
-
-static void
-TestPluginSessionChange(gpointer src,
-                        ToolsAppCtx *ctx,
-                        DWORD code,
-                        DWORD sessionId,
-                        ToolsPluginData *plugin)
-{
-   g_debug("Got session state change signal, code = %u, id = %u\n", code, sessionId);
-}
-
-
-/**
- * Handles the preshutdown callback; this is only called on Windows Vista & up,
- * from the "vmsvc" instance. This is called only "upgrade at powercycle" flag is
- * set in the UI. If the upgrader is launched, the service waits for upgrader
- * to terminate before shutting down.
+ * @param[in] src                    The source object.
+ * @param[in] ctx                    The application context.
+ * @param[in] serviceStatusHandle    Handle of type SERVICE_STATUS_HANDLE.
+ * @param[in] controlCode            Control code.
+ * @param[in] eventType              Unused.
+ * @param[in] eventData              Unused.
+ * @param[in] data                   Unused.
  *
- * @param[in]  src      The source object.
- * @param[in]  ctx      ToolsAppCtx *: The application context.
- * @param[in]  serviceStatusHandle     A handle of type SERVICE_STATUS_HANDLE
- * @param[in]  data     Client data.
+ * @retval ERROR_CALL_NOT_IMPLEMENTED
  */
 
-static void
-TestPluginPreShutdownChange(gpointer src,
-                            ToolsAppCtx *ctx,
-                            gpointer serviceStatusHandle,
-                            gpointer data)
+static DWORD
+TestPluginServiceControl(gpointer src,
+                         ToolsAppCtx *ctx,
+                         gpointer serviceStatusHandle,
+                         guint controlCode,
+                         guint eventType,
+                         gpointer eventData,
+                         gpointer data)
 {
-   g_debug("%s: Got preshutdown signal for app %s\n", __FUNCTION__, ctx->name);
+   g_debug("Got service control signal, code = %u, event = %u\n",
+           controlCode, eventType);
+   return ERROR_CALL_NOT_IMPLEMENTED;
 }
 #endif
 
@@ -327,8 +311,7 @@ ToolsOnLoad(ToolsAppCtx *ctx)
       { TOOLS_CORE_SIG_CAPABILITIES, TestPluginCapabilities, &regData },
       { TOOLS_CORE_SIG_SET_OPTION, TestPluginSetOption, &regData },
 #if defined(G_PLATFORM_WIN32)
-      { TOOLS_CORE_SIG_SESSION_CHANGE, TestPluginSessionChange, &regData },
-      { TOOLS_CORE_SIG_PRESHUTDOWN, TestPluginPreShutdownChange, &regData },
+      { TOOLS_CORE_SIG_SERVICE_CONTROL, TestPluginServiceControl, &regData },
 #endif
    };
    TestApp tapp[] = {