public long getFreeMemorySpace() throws JIException {
    System.gc();

    JIVariant results[] =
        service_dispatch.callMethodA(
            "ExecQuery",
            new Object[] {
              new JIString("select * from Win32_PerfRawData_PerfOS_Memory"),
              JIVariant.OPTIONAL_PARAM(),
              JIVariant.OPTIONAL_PARAM(),
              JIVariant.OPTIONAL_PARAM()
            });
    IJIDispatch wbemObjectSet_dispatch =
        (IJIDispatch) JIObjectFactory.narrowObject((results[0]).getObjectAsComObject());
    JIVariant variant = wbemObjectSet_dispatch.get("_NewEnum");
    IJIComObject object2 = variant.getObjectAsComObject();

    IJIEnumVariant enumVARIANT =
        (IJIEnumVariant) JIObjectFactory.narrowObject(object2.queryInterface(IJIEnumVariant.IID));
    if (wbemObjectSet_dispatch.get("Count").getObjectAsInt() != 1)
      return -1; // there should be 1 hint

    JIArray array = (JIArray) enumVARIANT.next(1)[0];
    JIVariant item = ((JIVariant[]) array.getArrayInstance())[0];
    IJIDispatch wbemObject_dispatch =
        (IJIDispatch) JIObjectFactory.narrowObject(item.getObjectAsComObject());
    return Long.parseLong(
        wbemObject_dispatch.get("AvailableKBytes").getObjectAsString().getString());
  }
  /* FIXME: This code sometimes fails with an "org.jinterop.dcom.common.JIException: An internal error occurred. [0x8001FFFF]"
   * on Windows 2008 */
  public int getCPUUsage() throws JIException {
    System.gc();

    JIVariant results[] =
        service_dispatch.callMethodA(
            "Get",
            new Object[] {
              new JIString("Win32_PerfRawData_PerfOS_Processor.Name='_Total'"),
              new Integer(0),
              JIVariant.OPTIONAL_PARAM()
            });

    IJIDispatch wbemObject_dispatch =
        (IJIDispatch) JIObjectFactory.narrowObject((results[0]).getObjectAsComObject());
    long ppt =
        Long.parseLong(
            wbemObject_dispatch.get("PercentProcessorTime").getObjectAsString().getString());
    long tss =
        Long.parseLong(
            wbemObject_dispatch.get("TimeStamp_Sys100NS").getObjectAsString().getString());

    if (this.percentprocessortime == -1 && this.timestamp == -1) {
      this.percentprocessortime = ppt;
      this.timestamp = tss;
      return -1;
    }

    double load =
        (1 - ((double) (this.percentprocessortime - ppt) / (double) (this.timestamp - tss))) * 100;
    this.percentprocessortime = ppt;
    this.timestamp = tss;

    return (int) Math.round(load);
  }
  public LinkedList<IJIDispatch> getDiskDrives() throws JIException {
    System.gc();

    // get all local disks
    JIVariant results[] =
        service_dispatch.callMethodA(
            "ExecQuery",
            new Object[] {
              new JIString("select * from Win32_LogicalDisk where DriveType = 3"),
              JIVariant.OPTIONAL_PARAM(),
              JIVariant.OPTIONAL_PARAM(),
              JIVariant.OPTIONAL_PARAM()
            });
    IJIDispatch wbemObjectSet_dispatch =
        (IJIDispatch) JIObjectFactory.narrowObject((results[0]).getObjectAsComObject());
    JIVariant variant = wbemObjectSet_dispatch.get("_NewEnum");
    IJIComObject object2 = variant.getObjectAsComObject();

    IJIEnumVariant enumVARIANT =
        (IJIEnumVariant) JIObjectFactory.narrowObject(object2.queryInterface(IJIEnumVariant.IID));

    LinkedList<IJIDispatch> drives = new LinkedList<IJIDispatch>();

    int count = wbemObjectSet_dispatch.get("Count").getObjectAsInt();
    for (int i = 0; i < count; i++) {
      Object[] values = enumVARIANT.next(1);
      JIArray array = (JIArray) values[0];
      JIVariant[] variants = (JIVariant[]) array.getArrayInstance();
      for (JIVariant item : variants) {
        drives.add((IJIDispatch) JIObjectFactory.narrowObject(item.getObjectAsComObject()));
      }
    }
    return drives;
  }
  public LinkedList<IJIDispatch> getServices() throws JIException {
    System.gc();

    // get all services which should start automatically but are not running
    JIVariant results[] =
        service_dispatch.callMethodA(
            "ExecQuery",
            new Object[] {
              new JIString(
                  "select * from Win32_Service where StartMode = 'Auto' and Started = FALSE"),
              JIVariant.OPTIONAL_PARAM(),
              JIVariant.OPTIONAL_PARAM(),
              JIVariant.OPTIONAL_PARAM()
            });

    IJIDispatch wbemObjectSet_dispatch =
        (IJIDispatch) JIObjectFactory.narrowObject((results[0]).getObjectAsComObject());
    JIVariant variant = wbemObjectSet_dispatch.get("_NewEnum");
    IJIComObject object2 = variant.getObjectAsComObject();
    IJIEnumVariant enumVARIANT =
        (IJIEnumVariant) JIObjectFactory.narrowObject(object2.queryInterface(IJIEnumVariant.IID));

    LinkedList<IJIDispatch> services = new LinkedList<IJIDispatch>();

    int count = wbemObjectSet_dispatch.get("Count").getObjectAsInt();
    for (int i = 0; i < count; i++) {
      Object[] values = enumVARIANT.next(1);
      JIArray array = (JIArray) values[0];
      JIVariant[] variants = (JIVariant[]) array.getArrayInstance();
      for (JIVariant item : variants) {
        IJIDispatch wbemObject_dispatch =
            (IJIDispatch) JIObjectFactory.narrowObject(item.getObjectAsComObject());
        services.add(wbemObject_dispatch);
      }
    }
    return services;
  }