static void
VmBackupScriptOpRelease(VmBackupOp *_op)  // IN
{
   size_t i;
   VmBackupScriptOp *op = (VmBackupScriptOp *) _op;

   if (op->type != VMBACKUP_SCRIPT_FREEZE && op->state->scripts != NULL) {
      VmBackupScript *scripts = op->state->scripts;
      for (i = 0; scripts[i].path != NULL; i++) {
         free(scripts[i].path);
         if (scripts[i].proc != NULL) {
            ProcMgr_Free(scripts[i].proc);
         }
      }
      free(op->state->scripts);
      op->state->scripts = NULL;
      op->state->currentScript = 0;
   }

   free(op);
}
static gboolean
PowerOpsScriptCallback(gpointer _state)
{
   PowerOpState *state = _state;

   ASSERT(state->pid != INVALID_PID);

   if (!ProcMgr_IsAsyncProcRunning(state->pid)) {
      int exitcode;
      gboolean success;

      success = (ProcMgr_GetExitCode(state->pid, &exitcode) == 0 &&
                 exitcode == 0);
      g_message("Script exit code: %d, success = %d\n", exitcode, success);
      PowerOpsStateChangeDone(state, success);
      ProcMgr_Free(state->pid);
      state->pid = INVALID_PID;
      return FALSE;
   }
   return TRUE;
}
static gboolean
GuestInfoVMSupport(RpcInData *data)
{
#if defined(_WIN32)

    char vmSupportCmd[] = "vm-support.vbs";
    char *vmSupportPath = NULL;
    gchar *vmSupport = NULL;

    SECURITY_ATTRIBUTES saProcess = {0}, saThread = {0};

    ProcMgr_AsyncProc *vmSupportProc = NULL;
    ProcMgr_ProcArgs vmSupportProcArgs = {0};

    /*
     * Construct the commandline to be passed during execution
     * This will be the path of our vm-support.vbs
     */
    vmSupportPath = GuestApp_GetInstallPath();

    if (vmSupportPath == NULL) {
       return RPCIN_SETRETVALS(data,
                               "GuestApp_GetInstallPath failed", FALSE);
    }

    /* Put together absolute vm-support filename. */
    vmSupport = g_strdup_printf("cscript \"%s%s%s\" -u",
                                vmSupportPath, DIRSEPS, vmSupportCmd);
    vm_free(vmSupportPath);

    saProcess.nLength = sizeof saProcess;
    saProcess.bInheritHandle = TRUE;

    saThread.nLength = sizeof saThread;

    vmSupportProcArgs.lpProcessAttributes = &saProcess;
    vmSupportProcArgs.lpThreadAttributes = &saThread;
    vmSupportProcArgs.dwCreationFlags = CREATE_NO_WINDOW;

    g_message("Starting vm-support script - %s\n", vmSupport);
    vmSupportProc = ProcMgr_ExecAsync(vmSupport, &vmSupportProcArgs);
    g_free(vmSupport);

    if (vmSupportProc == NULL) {
       g_warning("Error starting vm-support script\n");
       return RPCIN_SETRETVALS(data,
                               "Error starting vm-support script", FALSE);
    }

    ProcMgr_Free(vmSupportProc);
    return RPCIN_SETRETVALS(data, "", TRUE);

#else

     gchar *vmSupportCmdArgv[] = {"vm-support", "-u", NULL};

     g_message("Starting vm-support script - %s\n", vmSupportCmdArgv[0]);
     if (!g_spawn_async(NULL, vmSupportCmdArgv, NULL,
                        G_SPAWN_SEARCH_PATH |
                        G_SPAWN_STDOUT_TO_DEV_NULL |
                        G_SPAWN_STDERR_TO_DEV_NULL,
                        NULL, NULL, NULL, NULL)) {
        g_warning("Error starting vm-support script\n");
        return RPCIN_SETRETVALS(data,
                                "Error starting vm-support script", FALSE);
     }

     return RPCIN_SETRETVALS(data, "", TRUE);

#endif
}
static VmBackupOpStatus
VmBackupScriptOpQuery(VmBackupOp *_op) // IN
{
   VmBackupOpStatus ret = VMBACKUP_STATUS_PENDING;
   VmBackupScriptOp *op = (VmBackupScriptOp *) _op;
   VmBackupScript *scripts = op->state->scripts;
   VmBackupScript *currScript = NULL;

   if (scripts != NULL && op->state->currentScript >= 0) {
      currScript = &scripts[op->state->currentScript];
   }

   if (op->canceled) {
      ret = VMBACKUP_STATUS_CANCELED;
      goto exit;
   } else if (scripts == NULL || currScript == NULL || currScript->proc == NULL) {
      ret = VMBACKUP_STATUS_FINISHED;
      goto exit;
   }

   if (!ProcMgr_IsAsyncProcRunning(currScript->proc)) {
      int exitCode;
      Bool succeeded;

      succeeded = (ProcMgr_GetExitCode(currScript->proc, &exitCode) == 0 &&
                   exitCode == 0);
      ProcMgr_Free(currScript->proc);
      currScript->proc = NULL;

      /*
       * If thaw scripts fail, keep running and only notify the failure after
       * all others have run.
       */
      if (!succeeded) {
          if (op->type == VMBACKUP_SCRIPT_FREEZE) {
             ret = VMBACKUP_STATUS_ERROR;
             goto exit;
          } else if (op->type == VMBACKUP_SCRIPT_THAW) {
             op->thawFailed = TRUE;
          }
      }

      switch (VmBackupRunNextScript(op)) {
      case -1:
         ret = VMBACKUP_STATUS_ERROR;
         break;

      case 0:
         ret = op->thawFailed ? VMBACKUP_STATUS_ERROR : VMBACKUP_STATUS_FINISHED;
         break;

      default:
         break;
      }
   }

exit:
   if (ret == VMBACKUP_STATUS_ERROR) {
      /* Report the script error to the host */
      VmBackup_SendEvent(VMBACKUP_EVENT_REQUESTOR_ERROR,
                         VMBACKUP_SCRIPT_ERROR,
                         "Custom quiesce script failed.");
   }
   return ret;
}