Example #1
0
static mrb_value input_device_get_id(mrb_state *mrb, mrb_value self)
{
    IDirectFBInputDevice* device = mrb_directfb_input_device(mrb, self);
    if (device != NULL) {
        DFBInputDeviceID id;
        DFBResult ret = device->GetID(device, &id);
        if (!ret) {
            return mrb_fixnum_value(id);
        }
    }
    return mrb_nil_value();
}
Example #2
0
static mrb_value input_device_get_description(mrb_state *mrb, mrb_value self)
{
    IDirectFBInputDevice* device = mrb_directfb_input_device(mrb, self);
    if (device != NULL) {
        DFBInputDeviceDescription desc;
        DFBResult ret = device->GetDescription(device, &desc);
        if (!ret) {
            return mrb_directfb_input_device_description_new(mrb, &desc);
        }
    }
    return mrb_nil_value();
}
Example #3
0
static mrb_value input_device_get_buttons(mrb_state *mrb, mrb_value self)
{
    IDirectFBInputDevice* device = mrb_directfb_input_device(mrb, self);
    if (device != NULL) {
        DFBInputDeviceButtonMask mask;
        DFBResult ret = device->GetButtons(device, &mask);
        if (!ret) {
            return mrb_fixnum_value(mask);
        }
    }
    return mrb_nil_value();
}
Example #4
0
static mrb_value input_device_get_lock_state(mrb_state *mrb, mrb_value self)
{
    IDirectFBInputDevice* device = mrb_directfb_input_device(mrb, self);
    if (device != NULL) {
        DFBInputDeviceLockState state;
        DFBResult ret = device->GetLockState(device, &state);
        if (!ret) {
            return mrb_fixnum_value(state);
        }
    }
    return mrb_nil_value();
}
Example #5
0
static mrb_value input_device_detach_event_buffer(mrb_state *mrb, mrb_value self)
{
    DFBResult ret = -1;
    IDirectFBInputDevice* device = mrb_directfb_input_device(mrb, self);
    if (device != NULL) {
        IDirectFBEventBuffer* event_buffer = NULL;
        mrb_value event_buffer_object;
        mrb_get_args(mrb, "o", &event_buffer_object);
        event_buffer = mrb_directfb_event_buffer(mrb, event_buffer_object);
        ret = device->DetachEventBuffer(device, event_buffer);
    }
    return mrb_fixnum_value(ret);
}
Example #6
0
static mrb_value input_device_create_event_buffer(mrb_state *mrb, mrb_value self)
{
    IDirectFBInputDevice* device = mrb_directfb_input_device(mrb, self);
    if (device != NULL) {

        IDirectFBEventBuffer* event_buffer;
        DFBResult ret = device->CreateEventBuffer(device, &event_buffer);
        if (!ret) {
            return mrb_directfb_event_buffer_value(mrb, event_buffer);
        }
    }
    return mrb_nil_value();
}
Example #7
0
static mrb_value input_device_get_xy(mrb_state *mrb, mrb_value self)
{
    IDirectFBInputDevice* device = mrb_directfb_input_device(mrb, self);
    if (device != NULL) {
        int x, y;
        DFBResult ret = device->GetXY(device, &x, &y);
        if (!ret) {
            mrb_value a[2];
            a[0] = mrb_fixnum_value(x);
            a[1] = mrb_fixnum_value(y);
            return mrb_ary_new_from_values(mrb, 2, a);
        }
    }
    return mrb_nil_value();
}
Example #8
0
static mrb_value input_device_get_axis(mrb_state *mrb, mrb_value self)
{
    IDirectFBInputDevice* device = mrb_directfb_input_device(mrb, self);
    if (device != NULL) {
        DFBResult ret;
        int pos;
        mrb_int axis;
        mrb_get_args(mrb, "i", &axis);
        ret = device->GetAxis(device, axis, &pos);
        if (!ret) {
            return mrb_fixnum_value(pos);
        }
    }
    return mrb_nil_value();
}
Example #9
0
static mrb_value input_device_get_button_state(mrb_state *mrb, mrb_value self)
{
    IDirectFBInputDevice* device = mrb_directfb_input_device(mrb, self);
    if (device != NULL) {
        DFBResult ret;
        DFBInputDeviceButtonState state;
        mrb_int button;
        mrb_get_args(mrb, "i", &button);
        ret = device->GetButtonState(device, button, &state);
        if (!ret) {
            return mrb_fixnum_value(state);
        }
    }
    return mrb_nil_value();
}
Example #10
0
static mrb_value input_device_get_key_state(mrb_state *mrb, mrb_value self)
{
    IDirectFBInputDevice* device = mrb_directfb_input_device(mrb, self);
    if (device != NULL) {
        DFBResult ret;
        DFBInputDeviceKeyState state;
        mrb_int key_id;
        mrb_get_args(mrb, "i", &key_id);
        ret = device->GetKeyState(device, key_id, &state);
        if (!ret) {
            return mrb_fixnum_value(state);
        }
    }
    return mrb_nil_value();
}
Example #11
0
static mrb_value input_device_get_keymap_entry(mrb_state *mrb, mrb_value self)
{
    IDirectFBInputDevice* device = mrb_directfb_input_device(mrb, self);
    if (device != NULL) {
        DFBInputDeviceKeymapEntry entry;
        DFBResult ret;

        mrb_int keycode;
        mrb_get_args(mrb, "i", &keycode);


        ret = device->GetKeymapEntry(device, keycode, &entry);
        if (!ret) {
            return mrb_directfb_input_device_keymap_entry_value(mrb, &entry);
        }
    }
    return mrb_nil_value();
}
Example #12
0
static DFBResult
Test_Sensitivity( IDirectFB        *dfb,
                  DFBInputDeviceID  device_id )
{
     DFBResult             ret;
     IDirectFBInputDevice *device;
     IDirectFBEventBuffer *buffer;
     int                   i, n;
     int                   sensitivities[] = { 0x100, 0x200, 0x80 };

     D_INFO( "DFBTest/Input: Testing sensitivity with input device %u...\n", device_id );

     ret = dfb->GetInputDevice( dfb, device_id, &device );
     if (ret) {
          D_DERROR( ret, "DFBTest/Input: GetInputDevice( %u ) failed!\n", device_id );
          return ret;
     }

     ret = device->CreateEventBuffer( device, &buffer );
     if (ret) {
          D_DERROR( ret, "DFBTest/Input: CreateEventBuffer() failed!\n" );
          device->Release( device );
          return ret;
     }

     for (i=0; i<D_ARRAY_SIZE(sensitivities); i++) {
          DFBInputDeviceConfig config;
          unsigned int         move = 0;

          D_INFO( "DFBTest/Input: Setting sensitivity to 0x%x, please move mouse!\n", sensitivities[i] );

          config.flags       = DIDCONF_SENSITIVITY;
          config.sensitivity = sensitivities[i];

          ret = device->SetConfiguration( device, &config );
          if (ret) {
               D_DERROR( ret, "DFBTest/Input: SetConfiguration() failed!\n" );
               buffer->Release( buffer );
               device->Release( device );
               return ret;
          }

          buffer->Reset( buffer );

          for (n=0; n<500; n++) {
               DFBInputEvent event;

               buffer->WaitForEvent( buffer );

               buffer->GetEvent( buffer, DFB_EVENT(&event) );

               switch (event.type) {
                    case DIET_AXISMOTION:
                         if (event.flags & DIEF_AXISREL) {
                              //D_INFO( "DFBTest/Input: Motion (axis %d) by %d\n", event.axis, event.axisrel );

                              if (event.axisrel > 0)
                                   move += event.axisrel;
                              else
                                   move -= event.axisrel;
                         }

                         break;

                    default:
                         break;
               }
          }

          D_INFO( "DFBTest/Input: Average movement %d.\n", move / n );

          direct_thread_sleep( 1000000 );
     }

     buffer->Release( buffer );
     device->Release( device );

     return DFB_OK;
}
Example #13
0
/** entry point */
int main(int argc, char *argv[])
{
    const char *uuid = NULL;
    int c;
    int listHostModes = 0;
    int quit = 0;
    const struct option options[] =
    {
        { "help",          no_argument,       NULL, 'h' },
        { "startvm",       required_argument, NULL, 's' },
        { "fixedres",      required_argument, NULL, 'f' },
        { "listhostmodes", no_argument,       NULL, 'l' },
        { "scale",         no_argument,       NULL, 'c' }
    };

    printf("VirtualBox DirectFB GUI built %s %s\n"
           "(C) 2004-" VBOX_C_YEAR " " VBOX_VENDOR "\n"
           "(C) 2004-2005 secunet Security Networks AG\n", __DATE__, __TIME__);

    for (;;)
    {
        c = getopt_long(argc, argv, "s:", options, NULL);
        if (c == -1)
            break;
        switch (c)
        {
            case 'h':
            {
                showusage();
                exit(0);
                break;
            }
            case 's':
            {
                // UUID as string, parse it
                RTUUID buuid;
                if (!RT_SUCCESS(RTUuidFromStr((PRTUUID)&buuid, optarg)))
                {
                    printf("Error, invalid UUID format given!\n");
                    showusage();
                    exit(-1);
                }
                uuid = optarg;
                break;
            }
            case 'f':
            {
                if (sscanf(optarg, "%ux%ux%u", &fixedVideoMode.width, &fixedVideoMode.height,
                           &fixedVideoMode.bpp) != 3)
                {
                    printf("Error, invalid resolution argument!\n");
                    showusage();
                    exit(-1);
                }
                useFixedVideoMode = 1;
                break;
            }
            case 'l':
            {
                listHostModes = 1;
                break;
            }
            case 'c':
            {
                scaleGuest = 1;
                break;
            }
            default:
                break;
        }
    }

    // check if we got a UUID
    if (!uuid)
    {
        printf("Error, no UUID given!\n");
        showusage();
        exit(-1);
    }


    /**
     * XPCOM setup
     */

    nsresult rc;
    /*
     * Note that we scope all nsCOMPtr variables in order to have all XPCOM
     * objects automatically released before we call NS_ShutdownXPCOM at the
     * end. This is an XPCOM requirement.
     */
    {
        nsCOMPtr<nsIServiceManager> serviceManager;
        rc = NS_InitXPCOM2(getter_AddRefs(serviceManager), nsnull, nsnull);
        if (NS_FAILED(rc))
        {
            printf("Error: XPCOM could not be initialized! rc=0x%x\n", rc);
            exit(-1);
        }

        // register our component
        nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(serviceManager);
        if (!registrar)
        {
            printf("Error: could not query nsIComponentRegistrar interface!\n");
            exit(-1);
        }
        registrar->AutoRegister(nsnull);

        /*
         * Make sure the main event queue is created. This event queue is
         * responsible for dispatching incoming XPCOM IPC messages. The main
         * thread should run this event queue's loop during lengthy non-XPCOM
         * operations to ensure messages from the VirtualBox server and other
         * XPCOM IPC clients are processed. This use case doesn't perform such
         * operations so it doesn't run the event loop.
         */
        nsCOMPtr<nsIEventQueue> eventQ;
        rc = NS_GetMainEventQ(getter_AddRefs (eventQ));
        if (NS_FAILED(rc))
        {
            printf("Error: could not get main event queue! rc=%08X\n", rc);
            return -1;
        }

        /*
         * Now XPCOM is ready and we can start to do real work.
         * IVirtualBox is the root interface of VirtualBox and will be
         * retrieved from the XPCOM component manager. We use the
         * XPCOM provided smart pointer nsCOMPtr for all objects because
         * that's very convenient and removes the need deal with reference
         * counting and freeing.
         */
        nsCOMPtr<nsIComponentManager> manager;
        rc = NS_GetComponentManager (getter_AddRefs (manager));
        if (NS_FAILED(rc))
        {
            printf("Error: could not get component manager! rc=%08X\n", rc);
            exit(-1);
        }

        nsCOMPtr<IVirtualBox> virtualBox;
        rc = manager->CreateInstanceByContractID(NS_VIRTUALBOX_CONTRACTID,
                                                 nsnull,
                                                 NS_GET_IID(IVirtualBox),
                                                 getter_AddRefs(virtualBox));
        if (NS_FAILED(rc))
        {
            printf("Error, could not instantiate object! rc=0x%x\n", rc);
            exit(-1);
        }

        nsCOMPtr<ISession> session;
        rc = manager->CreateInstance(CLSID_Session,
                                     nsnull,
                                     NS_GET_IID(ISession),
                                     getter_AddRefs(session));
        if (NS_FAILED(rc))
        {
            printf("Error: could not instantiate Session object! rc = %08X\n", rc);
            exit(-1);
        }

        // open session for this VM
        rc = virtualBox->OpenSession(session, NS_ConvertUTF8toUTF16(uuid).get());
        if (NS_FAILED(rc))
        {
            printf("Error: given machine not found!\n");
            exit(-1);
        }
        nsCOMPtr<IMachine> machine;
        session->GetMachine(getter_AddRefs(machine));
        if (!machine)
        {
            printf("Error: given machine not found!\n");
            exit(-1);
        }
        nsCOMPtr<IConsole> console;
        session->GetConsole(getter_AddRefs(console));
        if (!console)
        {
            printf("Error: cannot get console!\n");
            exit(-1);
        }

        nsCOMPtr<IDisplay> display;
        console->GetDisplay(getter_AddRefs(display));
        if (!display)
        {
            printf("Error: could not get display object!\n");
            exit(-1);
        }

        nsCOMPtr<IKeyboard> keyboard;
        nsCOMPtr<IMouse> mouse;
        VBoxDirectFB *frameBuffer = NULL;

        /**
         * Init DirectFB
         */
        IDirectFB *dfb = NULL;
        IDirectFBSurface *surface = NULL;
        IDirectFBInputDevice *dfbKeyboard = NULL;
        IDirectFBInputDevice *dfbMouse = NULL;
        IDirectFBEventBuffer *dfbEventBuffer = NULL;
        DFBSurfaceDescription dsc;
        int screen_width, screen_height;

        DFBCHECK(DirectFBInit(&argc, &argv));
        DFBCHECK(DirectFBCreate(&dfb));
        DFBCHECK(dfb->SetCooperativeLevel(dfb, DFSCL_FULLSCREEN));
        // populate our structure of supported video modes
        DFBCHECK(dfb->EnumVideoModes(dfb, enumVideoModesHandler, NULL));

        if (listHostModes)
        {
            printf("*****************************************************\n");
            printf("Number of available host video modes: %u\n", numVideoModes);
            for (uint32_t i = 0; i < numVideoModes; i++)
            {
                printf("Mode %u: xres = %u, yres = %u, bpp = %u\n", i,
                       videoModes[i].width, videoModes[i].height, videoModes[i].bpp);
            }
            printf("Note: display modes with bpp < have been filtered out\n");
            printf("*****************************************************\n");
            goto Leave;
        }

        if (useFixedVideoMode)
        {
            int32_t bestVideoMode = getBestVideoMode(fixedVideoMode.width,
                                                     fixedVideoMode.height,
                                                     fixedVideoMode.bpp);
            // validate the fixed mode
            if ((bestVideoMode == -1) ||
                ((fixedVideoMode.width  != videoModes[bestVideoMode].width) ||
                (fixedVideoMode.height != videoModes[bestVideoMode].height) ||
                (fixedVideoMode.bpp    != videoModes[bestVideoMode].bpp)))
            {
                printf("Error: the specified fixed video mode is not available!\n");
                exit(-1);
            }
        } else
        {
            initialVideoMode = getBestVideoMode(640, 480, 16);
            if (initialVideoMode == -1)
            {
                printf("Error: initial video mode 640x480x16 is not available!\n");
                exit(-1);
            }
        }

        dsc.flags = DSDESC_CAPS;
        dsc.caps = DSCAPS_PRIMARY;
        DFBCHECK(dfb->CreateSurface(dfb, &dsc, &surface));
        DFBCHECK(surface->Clear(surface, 0, 0, 0, 0));
        DFBCHECK(surface->GetSize(surface, &screen_width, &screen_height));
        DFBCHECK(dfb->GetInputDevice(dfb, DIDID_KEYBOARD, &dfbKeyboard));
        DFBCHECK(dfbKeyboard->CreateEventBuffer(dfbKeyboard, &dfbEventBuffer));
        DFBCHECK(dfb->GetInputDevice(dfb, DIDID_MOUSE, &dfbMouse));
        DFBCHECK(dfbMouse->AttachEventBuffer(dfbMouse, dfbEventBuffer));


        if (useFixedVideoMode)
        {
            printf("Information: setting video mode to %ux%ux%u\n", fixedVideoMode.width,
                   fixedVideoMode.height, fixedVideoMode.bpp);
            DFBCHECK(dfb->SetVideoMode(dfb, fixedVideoMode.width,
                                       fixedVideoMode.height, fixedVideoMode.bpp));
        } else
        {
            printf("Information: starting with default video mode %ux%ux%u\n",
                   videoModes[initialVideoMode].width, videoModes[initialVideoMode].height,
                   videoModes[initialVideoMode].bpp);
            DFBCHECK(dfb->SetVideoMode(dfb, videoModes[initialVideoMode].width,
                                            videoModes[initialVideoMode].height,
                                            videoModes[initialVideoMode].bpp));
        }

        // register our framebuffer
        frameBuffer = new VBoxDirectFB(dfb, surface);
        display->SetFramebuffer(0, frameBuffer);

        /**
         * Start the VM execution thread
         */
        console->PowerUp(NULL);

        console->GetKeyboard(getter_AddRefs(keyboard));
        console->GetMouse(getter_AddRefs(mouse));

        /**
         * Main event loop
         */
        #define MAX_KEYEVENTS 10
        PRInt32 keyEvents[MAX_KEYEVENTS];
        int numKeyEvents;

        while (!quit)
        {
            DFBInputEvent event;

            numKeyEvents = 0;
            DFBCHECK(dfbEventBuffer->WaitForEvent(dfbEventBuffer));
            while (dfbEventBuffer->GetEvent(dfbEventBuffer, DFB_EVENT(&event)) == DFB_OK)
            {
                int mouseXDelta = 0;
                int mouseYDelta = 0;
                int mouseZDelta = 0;
                switch (event.type)
                {
                    #define QUEUEEXT() keyEvents[numKeyEvents++] = 0xe0
                    #define QUEUEKEY(scan) keyEvents[numKeyEvents++] = scan | (event.type == DIET_KEYRELEASE ? 0x80 : 0x00)
                    #define QUEUEKEYRAW(scan) keyEvents[numKeyEvents++] = scan
                    case DIET_KEYPRESS:
                    case DIET_KEYRELEASE:
                    {
                        // @@@AH development hack to get out of it!
                        if ((event.key_id == DIKI_ESCAPE) && (event.modifiers & (DIMM_CONTROL | DIMM_ALT)))
                            quit = 1;

                        if (numKeyEvents < MAX_KEYEVENTS)
                        {
                            //printf("%s: key_code: 0x%x\n", event.type == DIET_KEYPRESS ? "DIET_KEYPRESS" : "DIET_KEYRELEASE", event.key_code);
                            switch ((uint32_t)event.key_id)
                            {
                                case DIKI_CONTROL_R:
                                    QUEUEEXT();
                                    QUEUEKEY(0x1d);
                                    break;
                                case DIKI_INSERT:
                                    QUEUEEXT();
                                    QUEUEKEY(0x52);
                                    break;
                                case DIKI_DELETE:
                                    QUEUEEXT();
                                    QUEUEKEY(0x53);
                                    break;
                                case DIKI_HOME:
                                    QUEUEEXT();
                                    QUEUEKEY(0x47);
                                    break;
                                case DIKI_END:
                                    QUEUEEXT();
                                    QUEUEKEY(0x4f);
                                    break;
                                case DIKI_PAGE_UP:
                                    QUEUEEXT();
                                    QUEUEKEY(0x49);
                                    break;
                                case DIKI_PAGE_DOWN:
                                    QUEUEEXT();
                                    QUEUEKEY(0x51);
                                    break;
                                case DIKI_LEFT:
                                    QUEUEEXT();
                                    QUEUEKEY(0x4b);
                                    break;
                                case DIKI_RIGHT:
                                    QUEUEEXT();
                                    QUEUEKEY(0x4d);
                                    break;
                                case DIKI_UP:
                                    QUEUEEXT();
                                    QUEUEKEY(0x48);
                                    break;
                                case DIKI_DOWN:
                                    QUEUEEXT();
                                    QUEUEKEY(0x50);
                                    break;
                                case DIKI_KP_DIV:
                                    QUEUEEXT();
                                    QUEUEKEY(0x35);
                                    break;
                                case DIKI_KP_ENTER:
                                    QUEUEEXT();
                                    QUEUEKEY(0x1c);
                                    break;
                                case DIKI_PRINT:
                                    // the break code is inverted!
                                    if (event.type == DIET_KEYPRESS)
                                    {
                                        QUEUEEXT();
                                        QUEUEKEY(0x2a);
                                        QUEUEEXT();
                                        QUEUEKEY(0x37);
                                    } else
                                    {
                                        QUEUEEXT();
                                        QUEUEKEY(0x37);
                                        QUEUEEXT();
                                        QUEUEKEY(0x2a);
                                    }
                                    break;
                                case DIKI_PAUSE:
                                    // This is a super weird key. No break code and a 6 byte
                                    // combination.
                                    if (event.type == DIET_KEYPRESS)
                                    {
                                        QUEUEKEY(0xe1);
                                        QUEUEKEY(0x1d);
                                        QUEUEKEY(0x45);
                                        QUEUEKEY(0xe1);
                                        QUEUEKEY(0x9d);
                                        QUEUEKEY(0xc5);
                                    }
                                    break;
                                case DIKI_META_L:
                                    // the left Windows logo is a bit different
                                    if (event.type == DIET_KEYPRESS)
                                    {
                                        QUEUEEXT();
                                        QUEUEKEYRAW(0x1f);
                                    } else
                                    {
                                        QUEUEEXT();
                                        QUEUEKEYRAW(0xf0);
                                        QUEUEKEYRAW(0x1f);
                                    }
                                    break;
                                case DIKI_META_R:
                                    // the right Windows logo is a bit different
                                    if (event.type == DIET_KEYPRESS)
                                    {
                                        QUEUEEXT();
                                        QUEUEKEYRAW(0x27);
                                    } else
                                    {
                                        QUEUEEXT();
                                        QUEUEKEYRAW(0xf0);
                                        QUEUEKEYRAW(0x27);
                                    }
                                    break;
                                case DIKI_SUPER_R:
                                    // the popup menu is a bit different
                                    if (event.type == DIET_KEYPRESS)
                                    {
                                        QUEUEEXT();
                                        QUEUEKEYRAW(0x2f);
                                    } else
                                    {
                                        QUEUEEXT();
                                        QUEUEKEYRAW(0xf0);
                                        QUEUEKEYRAW(0x2f);
                                    }
                                    break;

                                default:
                                    // check if we got a hardware scancode
                                    if (event.key_code != -1)
                                    {
                                        // take the scancode from DirectFB as is
                                        QUEUEKEY(event.key_code);
                                    } else
                                    {
                                        // XXX need extra handling!
                                    }
                            }
                        }
                        break;
                    }
                    #undef QUEUEEXT
                    #undef QUEUEKEY
                    #undef QUEUEKEYRAW

                    case DIET_AXISMOTION:
                    {
                        switch (event.axis)
                        {
                            case DIAI_X:
                                mouseXDelta += event.axisrel;
                                break;
                            case DIAI_Y:
                                mouseYDelta += event.axisrel;
                                break;
                            case DIAI_Z:
                                mouseZDelta += event.axisrel;
                                break;
                            default:
                                break;
                        }
                        // fall through
                    }
                    case DIET_BUTTONPRESS:
                        // fall through;
                    case DIET_BUTTONRELEASE:
                    {
                        int buttonState = 0;
                        if (event.buttons & DIBM_LEFT)
                            buttonState |= MouseButtonState::LeftButton;
                        if (event.buttons & DIBM_RIGHT)
                            buttonState |= MouseButtonState::RightButton;
                        if (event.buttons & DIBM_MIDDLE)
                            buttonState |= MouseButtonState::MiddleButton;
                        mouse->PutMouseEvent(mouseXDelta, mouseYDelta, mouseZDelta,
                                             buttonState);
                        break;
                    }
                    default:
                        break;
                }
            }
            // did we get any keyboard events?
            if (numKeyEvents > 0)
            {
                uint32_t codesStored;
                if (numKeyEvents > 1)
                {
                    keyboard->PutScancodes(numKeyEvents, keyEvents,
                                           &codesStored);
                } else
                {
                    keyboard->PutScancode(keyEvents[0]);
                }
            }
        }
        {
            nsCOMPtr<IProgress> progress;
            console->PowerDown(getter_AddRefs(progress));
            progress->WaitForCompletion(-1);
        }
    }

Leave:
    /*
     * Perform the standard XPCOM shutdown procedure.
     */
    NS_ShutdownXPCOM(nsnull);

    return 0;
}