ruby-changes:6108
From: suke <ko1@a...>
Date: Sat, 28 Jun 2008 08:44:13 +0900 (JST)
Subject: [ruby-changes:6108] Ruby:r17620 (trunk): * ext/win32ole/win32ole.c : check String encoding when
suke 2008-06-28 08:43:57 +0900 (Sat, 28 Jun 2008) New Revision: 17620 Modified files: trunk/ChangeLog trunk/ext/win32ole/win32ole.c trunk/test/win32ole/test_win32ole.rb Log: * ext/win32ole/win32ole.c : check String encoding when converting String to VT_BSTR in OLE. * test/win32ole/test_win32ole.rb : ditto. http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ChangeLog?r1=17620&r2=17619&diff_format=u http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ext/win32ole/win32ole.c?r1=17620&r2=17619&diff_format=u http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/test/win32ole/test_win32ole.rb?r1=17620&r2=17619&diff_format=u Index: ChangeLog =================================================================== --- ChangeLog (revision 17619) +++ ChangeLog (revision 17620) @@ -1,3 +1,10 @@ +Sat Jun 28 08:40:18 2008 Masaki Suketa <masaki.suketa@n...> + + * ext/win32ole/win32ole.c : check String encoding when + converting String to VT_BSTR in OLE. + + * test/win32ole/test_win32ole.rb : ditto. + Sat Jun 28 01:08:42 2008 Tanaka Akira <akr@f...> * time.c (time_timespec): fix rounding negative float. Index: ext/win32ole/win32ole.c =================================================================== --- ext/win32ole/win32ole.c (revision 17619) +++ ext/win32ole/win32ole.c (revision 17620) @@ -116,7 +116,7 @@ #define WC2VSTR(x) ole_wc2vstr((x), TRUE) -#define WIN32OLE_VERSION "1.1.5" +#define WIN32OLE_VERSION "1.1.6" typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX) (REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*); @@ -201,6 +201,7 @@ static UINT g_cp_to_check = CP_ACP; static char g_lcid_to_check[8 + 1]; static VARTYPE g_nil_to = VT_ERROR; +static st_table *enc2cp_table; struct oledata { IDispatch *pDispatch; @@ -274,6 +275,7 @@ static void olemethod_free(struct olemethoddata *polemethod); static void olevariable_free(struct olevariabledata *polevar); static void oleparam_free(struct oleparamdata *pole); +static LPWSTR ole_vstr2wc(VALUE vstr); static LPWSTR ole_mb2wc(char *pm, int len); static VALUE ole_wc2vstr(LPWSTR pw, BOOL isfree); static VALUE ole_ary_m_entry(VALUE val, long *pid); @@ -518,6 +520,8 @@ static VALUE folevariant_value(VALUE self); static VALUE folevariant_vartype(VALUE self); static VALUE folevariant_set_value(VALUE self, VALUE val); +static void init_enc2cp(); +static void free_enc2cp(); typedef struct _Win32OLEIDispatch { @@ -1106,6 +1110,38 @@ } static LPWSTR +ole_vstr2wc(VALUE vstr) +{ + rb_encoding *enc; + int cp; + int size; + LPWSTR pw; + st_data_t data; + enc = rb_enc_get(vstr); + if (st_lookup(enc2cp_table, (st_data_t)enc, &data)) { + cp = data; + } else { + cp = ole_encoding2cp(enc); + if (code_page_installed(cp) || + cp == CP_ACP || + cp == CP_OEMCP || + cp == CP_MACCP || + cp == CP_THREAD_ACP || + cp == CP_SYMBOL || + cp == CP_UTF7 || + cp == CP_UTF8 ) { + st_insert(enc2cp_table, (st_data_t)enc, (st_data_t)cp); + } else { + rb_raise(eWIN32OLERuntimeError, "not installed Windows codepage(%d) according to `%s'", cp, rb_enc_name(enc)); + } + } + size = MultiByteToWideChar(cp, 0, StringValuePtr(vstr), -1, NULL, 0); + pw = SysAllocStringLen(NULL, size - 1); + MultiByteToWideChar(cp, 0, StringValuePtr(vstr), -1, pw, size); + return pw; +} + +static LPWSTR ole_mb2wc(char *pm, int len) { int size; @@ -1387,7 +1423,7 @@ break; case T_STRING: V_VT(var) = VT_BSTR; - V_BSTR(var) = ole_mb2wc(StringValuePtr(val), -1); + V_BSTR(var) = ole_vstr2wc(val); break; case T_FIXNUM: V_VT(var) = VT_I4; @@ -1465,7 +1501,7 @@ switch (TYPE(val)) { case T_STRING: if (V_VT(var) == (VT_BSTR | VT_BYREF)) { - *V_BSTRREF(var) = ole_mb2wc(StringValuePtr(val), -1); + *V_BSTRREF(var) = ole_vstr2wc(val); } break; case T_FIXNUM: @@ -2347,7 +2383,7 @@ rb_raise(rb_eRuntimeError, "CoCreateInstanceEx is not supported in this environment"); rb_scan_args(argc, argv, "2*", &ole, &host, &others); - pbuf = ole_mb2wc(StringValuePtr(ole), -1); + pbuf = ole_vstr2wc(ole); hr = CLSIDFromProgID(pbuf, &clsid); if (FAILED(hr)) hr = clsid_from_remote(host, ole, &clsid); @@ -2359,7 +2395,7 @@ "unknown OLE server: `%s'", StringValuePtr(ole)); memset(&serverinfo, 0, sizeof(COSERVERINFO)); - serverinfo.pwszName = ole_mb2wc(StringValuePtr(host), -1); + serverinfo.pwszName = ole_vstr2wc(host); memset(&multi_qi, 0, sizeof(MULTI_QI)); multi_qi.pIID = &IID_IDispatch; hr = gCoCreateInstanceEx(&clsid, NULL, clsctx, &serverinfo, 1, &multi_qi); @@ -2392,7 +2428,7 @@ "failed to create bind context"); } - pbuf = ole_mb2wc(StringValuePtr(moniker), -1); + pbuf = ole_vstr2wc(moniker); hr = MkParseDisplayName(pBindCtx, pbuf, &eaten, &pMoniker); SysFreeString(pbuf); if(FAILED(hr)) { @@ -2446,7 +2482,7 @@ } /* get CLSID from OLE server name */ - pBuf = ole_mb2wc(StringValuePtr(svr_name), -1); + pBuf = ole_vstr2wc(svr_name); hr = CLSIDFromProgID(pBuf, &clsid); if(FAILED(hr)) { hr = CLSIDFromString(pBuf, &clsid); @@ -2551,7 +2587,7 @@ if (file == Qnil) { file = ole; } - pBuf = ole_mb2wc(StringValuePtr(file), -1); + pBuf = ole_vstr2wc(file); hr = LoadTypeLibEx(pBuf, REGKIND_NONE, &pTypeLib); SysFreeString(pBuf); if (FAILED(hr)) @@ -2954,7 +2990,7 @@ } /* get CLSID from OLE server name */ - pBuf = ole_mb2wc(StringValuePtr(svr_name), -1); + pBuf = ole_vstr2wc(svr_name); hr = CLSIDFromProgID(pBuf, &clsid); if(FAILED(hr)) { hr = CLSIDFromString(pBuf, &clsid); @@ -3007,7 +3043,7 @@ } /* pNamedArgs[0] is <method name>, so "index + 1" */ - pOp->pNamedArgs[index + 1] = ole_mb2wc(StringValuePtr(key), -1); + pOp->pNamedArgs[index + 1] = ole_vstr2wc(key); value = rb_ary_entry(pair, 1); VariantInit(&(pOp->dp.rgvarg[index])); @@ -3075,7 +3111,7 @@ argc += 1; rb_funcall(paramS, rb_intern("unshift"), 1, cmd); } else { - wcmdname = ole_mb2wc(StringValuePtr(cmd), -1); + wcmdname = ole_vstr2wc(cmd); hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL, &wcmdname, 1, lcid, &DispID); SysFreeString(wcmdname); @@ -3103,7 +3139,7 @@ rb_block_call(param, rb_intern("each"), 0, 0, hash2named_arg, (VALUE)&op); pDispID = ALLOCA_N(DISPID, cNamedArgs + 1); - op.pNamedArgs[0] = ole_mb2wc(StringValuePtr(cmd), -1); + op.pNamedArgs[0] = ole_vstr2wc(cmd); hr = pole->pDispatch->lpVtbl->GetIDsOfNames(pole->pDispatch, &IID_NULL, op.pNamedArgs, @@ -3614,7 +3650,7 @@ OLEData_Get_Struct(self, pole); /* get ID from property name */ - pBuf[0] = ole_mb2wc(StringValuePtr(property), -1); + pBuf[0] = ole_vstr2wc(property); hr = pole->pDispatch->lpVtbl->GetIDsOfNames(pole->pDispatch, &IID_NULL, pBuf, 1, lcid, &dispID); SysFreeString(pBuf[0]); @@ -4210,7 +4246,7 @@ struct oledata *pole; IDispatch *pDispatch; - pBuf = ole_mb2wc(StringValuePtr(str_iid), -1); + pBuf = ole_vstr2wc(str_iid); hr = CLSIDFromString(pBuf, &iid); SysFreeString(pBuf); if(FAILED(hr)) { @@ -4868,7 +4904,7 @@ found = oletypelib_search_registry2(self, args); } if (found == Qfalse) { - pbuf = ole_mb2wc(StringValuePtr(typelib), -1); + pbuf = ole_vstr2wc(typelib); hr = LoadTypeLibEx(pbuf, REGKIND_NONE, &pTypeLib); SysFreeString(pbuf); if (SUCCEEDED(hr)) { @@ -5029,7 +5065,7 @@ HRESULT hr = S_OK; path = rb_funcall(self, rb_intern("path"), 0); if (path != Qnil) { - pbuf = ole_mb2wc(StringValuePtr(path), -1); + pbuf = ole_vstr2wc(path); hr = LoadTypeLibEx(pbuf, REGKIND_NONE, ppTypeLib); SysFreeString(pbuf); if (FAILED(hr)) @@ -5166,7 +5202,7 @@ if (file == Qnil) { file = typelib; } - pbuf = ole_mb2wc(StringValuePtr(file), -1); + pbuf = ole_vstr2wc(file); hr = LoadTypeLibEx(pbuf, REGKIND_NONE, &pTypeLib); if (FAILED(hr)) ole_raise(hr, eWIN32OLERuntimeError, "failed to LoadTypeLibEx"); @@ -8108,6 +8144,18 @@ return Qnil; } +static void +init_enc2cp() +{ + enc2cp_table = st_init_numtable(); +} + +static void +free_enc2cp() +{ + st_free_table(enc2cp_table); +} + void Init_win32ole() { @@ -8327,6 +8375,8 @@ eWIN32OLERuntimeError = rb_define_class("WIN32OLERuntimeError", rb_eRuntimeError); + init_enc2cp(); + atexit((void (*)(void))free_enc2cp); ole_init_cp(); cWIN32OLE_enc = ole_cp2encoding(cWIN32OLE_cp); } Index: test/win32ole/test_win32ole.rb =================================================================== --- test/win32ole/test_win32ole.rb (revision 17619) +++ test/win32ole/test_win32ole.rb (revision 17620) @@ -282,8 +282,8 @@ fso = WIN32OLE.new("Scripting.FileSystemObject") fname = fso.getTempName begin + obj = WIN32OLE_VARIANT.new([0x3042].pack("U*").force_encoding("UTF-8")) WIN32OLE.codepage = WIN32OLE::CP_UTF8 - obj = WIN32OLE_VARIANT.new([0x3042].pack("U*")) assert_equal("\xE3\x81\x82".force_encoding("CP65001"), obj.value) begin @@ -302,9 +302,9 @@ assert_equal("\xA4\xA2".force_encoding("CP20932"), obj.value) end - WIN32OLE.codepage = WIN32OLE::CP_UTF8 + WIN32OLE.codepage = cp file = fso.opentextfile(fname, 2, true) - file.write [0x3042].pack("U*") + file.write [0x3042].pack("U*").force_encoding("UTF-8") file.close str = "" open(fname, "r:ascii-8bit") {|ifs| @@ -318,8 +318,9 @@ rescue WIN32OLERuntimeError end if (WIN32OLE.codepage == 20932) + WIN32OLE.codepage = cp file = fso.opentextfile(fname, 2, true) - file.write [164, 162].pack("c*") + file.write [164, 162].pack("c*").force_encoding("EUC-JP") file.close open(fname, "r:ascii-8bit") {|ifs| str = ifs.read -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/