From: VMware, Inc <> Date: Thu, 17 Dec 2009 21:44:59 +0000 (-0800) Subject: Plumb SCM control signals through vmtoolsd in a generic way. X-Git-Tag: 2009.12.16-217847~35 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d9252b39f5e39a9cf1a41f03bc490a7b25072d11;p=thirdparty%2Fopen-vm-tools.git Plumb SCM control signals through vmtoolsd in a generic way. 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 --- diff --git a/open-vm-tools/lib/include/vmware/tools/plugin.h b/open-vm-tools/lib/include/vmware/tools/plugin.h index c8d6d94fc..eb6bf52cb 100644 --- a/open-vm-tools/lib/include/vmware/tools/plugin.h +++ b/open-vm-tools/lib/include/vmware/tools/plugin.h @@ -135,26 +135,34 @@ #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 diff --git a/open-vm-tools/services/vmtoolsd/serviceObj.c b/open-vm-tools/services/vmtoolsd/serviceObj.c index 30394dda9..744759213 100644 --- a/open-vm-tools/services/vmtoolsd/serviceObj.c +++ b/open-vm-tools/services/vmtoolsd/serviceObj.c @@ -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 } diff --git a/open-vm-tools/services/vmtoolsd/svcSignals.gm b/open-vm-tools/services/vmtoolsd/svcSignals.gm index 37629ed15..fb2410e76 100644 --- a/open-vm-tools/services/vmtoolsd/svcSignals.gm +++ b/open-vm-tools/services/vmtoolsd/svcSignals.gm @@ -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 diff --git a/open-vm-tools/tests/testPlugin/testPlugin.c b/open-vm-tools/tests/testPlugin/testPlugin.c index f7ef4fe8c..917aca5ca 100644 --- a/open-vm-tools/tests/testPlugin/testPlugin.c +++ b/open-vm-tools/tests/testPlugin/testPlugin.c @@ -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, ®Data }, { TOOLS_CORE_SIG_SET_OPTION, TestPluginSetOption, ®Data }, #if defined(G_PLATFORM_WIN32) - { TOOLS_CORE_SIG_SESSION_CHANGE, TestPluginSessionChange, ®Data }, - { TOOLS_CORE_SIG_PRESHUTDOWN, TestPluginPreShutdownChange, ®Data }, + { TOOLS_CORE_SIG_SERVICE_CONTROL, TestPluginServiceControl, ®Data }, #endif }; TestApp tapp[] = {