/*
 *  call-seq:
 *     WIN32OLE.new(server, [host]) -> WIN32OLE object
 * 
 *  Returns a new WIN32OLE object(OLE Automation object).
 *  The first argument server specifies OLE Automation server.
 *  The first argument should be CLSID or PROGID.
 *  If second argument host specified, then returns OLE Automation 
 *  object on host. 
 *
 *      WIN32OLE.new('Excel.Application') # => Excel OLE Automation WIN32OLE object.
 *      WIN32OLE.new('{00024500-0000-0000-C000-000000000046}') # => Excel OLE Automation WIN32OLE object.
 */
static VALUE
fole_initialize(argc, argv, self)
    int argc;
    VALUE *argv;
    VALUE self;
{
    VALUE svr_name;
    VALUE host;
    VALUE others;
    HRESULT hr;
    CLSID   clsid;
    OLECHAR *pBuf;
    IDispatch *pDispatch;

    rb_secure(4);
    rb_call_super(0, 0);
    rb_scan_args(argc, argv, "11*", &svr_name, &host, &others);

    if (ruby_safe_level > 0 && OBJ_TAINTED(svr_name)) {
        rb_raise(rb_eSecurityError, "Insecure Object Creation - %s",
                 StringValuePtr(svr_name));
    }
    if (!NIL_P(host)) {
        if (ruby_safe_level > 0 && OBJ_TAINTED(host)) {
            rb_raise(rb_eSecurityError, "Insecure Object Creation - %s",
                     StringValuePtr(svr_name));
        }
        return ole_create_dcom(argc, argv, self);
    }

    /* get CLSID from OLE server name */
    pBuf  = ole_mb2wc(StringValuePtr(svr_name), -1);
    hr = CLSIDFromProgID(pBuf, &clsid);
    if(FAILED(hr)) {
        hr = CLSIDFromString(pBuf, &clsid);
    }
    SysFreeString(pBuf);
    if(FAILED(hr)) {
        ole_raise(hr, eWIN32OLE_RUNTIME_ERROR, 
                  "unknown OLE server: `%s'",
                  StringValuePtr(svr_name));
    }

    /* get IDispatch interface */
    hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
                          &IID_IDispatch, (void**)&pDispatch);
    if(FAILED(hr)) {
        ole_raise(hr, eWIN32OLE_RUNTIME_ERROR,
                  "failed to create WIN32OLE object from `%s'",
                  StringValuePtr(svr_name));
    }
    
    ole_set_member(self, pDispatch);
    return self;
}