[VBSCRIPT] Sync with Wine Staging 1.9.23. CORE-12409
[reactos.git] / reactos / dll / win32 / vbscript / global.c
index a3d01d5..1534805 100644 (file)
 #include "vbscript.h"
 
 #include <math.h>
+#include <wingdi.h>
 #include <mshtmhst.h>
 
-#define round(x) (((x) < 0) ? (int)((x) - 0.5) : (int)((x) + 0.5))
-
 #define VB_E_CANNOT_CREATE_OBJ 0x800a01ad
 #define VB_E_MK_PARSE_ERROR    0x800a01b0
 
@@ -106,9 +105,6 @@ static HRESULT return_short(VARIANT *res, short val)
 
 static HRESULT return_int(VARIANT *res, int val)
 {
-    if((short)val == val)
-        return return_short(res, val);
-
     if(res) {
         V_VT(res) = VT_I4;
         V_I4(res) = val;
@@ -127,6 +123,16 @@ static inline HRESULT return_double(VARIANT *res, double val)
     return S_OK;
 }
 
+static inline HRESULT return_float(VARIANT *res, float val)
+{
+    if(res) {
+        V_VT(res) = VT_R4;
+        V_R4(res) = val;
+    }
+
+    return S_OK;
+}
+
 static inline HRESULT return_null(VARIANT *res)
 {
     if(res)
@@ -196,11 +202,12 @@ static HRESULT set_object_site(script_ctx_t *ctx, IUnknown *obj)
         return S_OK;
 
     ax_site = create_ax_site(ctx);
-    if(ax_site)
+    if(ax_site) {
         hres = IObjectWithSite_SetSite(obj_site, ax_site);
+        IUnknown_Release(ax_site);
+    }
     else
         hres = E_OUTOFMEMORY;
-    IUnknown_Release(ax_site);
     IObjectWithSite_Release(obj_site);
     return hres;
 }
@@ -411,9 +418,7 @@ static HRESULT Global_CLng(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARI
     if(!res)
         return DISP_E_BADVARTYPE;
 
-    V_VT(res) = VT_I4;
-    V_I4(res) = i;
-    return S_OK;
+    return return_int(res, i);
 }
 
 static HRESULT Global_CBool(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
@@ -532,6 +537,8 @@ static HRESULT Global_Hex(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIA
 {
     WCHAR buf[17], *ptr;
     DWORD n;
+    HRESULT hres;
+    int ret;
 
     TRACE("%s\n", debugstr_variant(arg));
 
@@ -539,19 +546,16 @@ static HRESULT Global_Hex(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIA
     case VT_I2:
         n = (WORD)V_I2(arg);
         break;
-    case VT_I4:
-        n = V_I4(arg);
-        break;
-    case VT_EMPTY:
-        n = 0;
-        break;
     case VT_NULL:
         if(res)
             V_VT(res) = VT_NULL;
         return S_OK;
     default:
-        FIXME("unsupported type %s\n", debugstr_variant(arg));
-        return E_NOTIMPL;
+        hres = to_int(arg, &ret);
+        if(FAILED(hres))
+            return hres;
+        else
+            n = ret;
     }
 
     buf[16] = 0;
@@ -572,8 +576,43 @@ static HRESULT Global_Hex(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIA
 
 static HRESULT Global_Oct(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    HRESULT hres;
+    WCHAR buf[23], *ptr;
+    DWORD n;
+    int ret;
+
+    TRACE("%s\n", debugstr_variant(arg));
+
+    switch(V_VT(arg)) {
+    case VT_I2:
+        n = (WORD)V_I2(arg);
+        break;
+    case VT_NULL:
+        if(res)
+            V_VT(res) = VT_NULL;
+        return S_OK;
+    default:
+        hres = to_int(arg, &ret);
+        if(FAILED(hres))
+            return hres;
+        else
+            n = ret;
+    }
+
+    buf[22] = 0;
+    ptr = buf + 21;
+
+    if(n) {
+        do {
+            *ptr-- = '0' + (n & 0x7);
+            n >>= 3;
+        }while(n);
+        ptr++;
+    }else {
+        *ptr = '0';
+    }
+
+    return return_string(res, ptr);
 }
 
 static HRESULT Global_VarType(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
@@ -759,8 +798,13 @@ static HRESULT Global_Rnd(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIA
 
 static HRESULT Global_Timer(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    SYSTEMTIME lt;
+    double sec;
+
+    GetLocalTime(&lt);
+    sec = lt.wHour * 3600 + lt.wMinute * 60 + lt.wSecond + lt.wMilliseconds / 1000.0;
+    return return_float(res, sec);
+
 }
 
 static HRESULT Global_LBound(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
@@ -777,8 +821,24 @@ static HRESULT Global_UBound(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VA
 
 static HRESULT Global_RGB(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    HRESULT hres;
+    int i, color[3];
+
+    TRACE("%s %s %s\n", debugstr_variant(arg), debugstr_variant(arg + 1), debugstr_variant(arg + 2));
+
+    assert(args_cnt == 3);
+
+    for(i = 0; i < 3; i++) {
+        hres = to_int(arg + i, color + i);
+        if(FAILED(hres))
+            return hres;
+        if(color[i] > 255)
+            color[i] = 255;
+        if(color[i] < 0)
+            return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
+    }
+
+    return return_int(res, RGB(color[0], color[1], color[2]));
 }
 
 static HRESULT Global_Len(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
@@ -960,10 +1020,47 @@ static HRESULT Global_MidB(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARI
     return E_NOTIMPL;
 }
 
-static HRESULT Global_StrComp(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
+static HRESULT Global_StrComp(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    BSTR left, right;
+    int mode, ret;
+    HRESULT hres;
+    short val;
+
+    TRACE("(%s %s ...)\n", debugstr_variant(args), debugstr_variant(args+1));
+
+    assert(args_cnt == 2 || args_cnt == 3);
+
+    if (args_cnt == 3) {
+        hres = to_int(args+2, &mode);
+        if(FAILED(hres))
+            return hres;
+
+        if (mode != 0 && mode != 1) {
+            FIXME("unknown compare mode = %d\n", mode);
+            return E_FAIL;
+        }
+    }
+    else
+        mode = 0;
+
+    hres = to_string(args, &left);
+    if(FAILED(hres))
+        return hres;
+
+    hres = to_string(args+1, &right);
+    if(FAILED(hres))
+    {
+        SysFreeString(left);
+        return hres;
+    }
+
+    ret = mode ? strcmpiW(left, right) : strcmpW(left, right);
+    val = ret < 0 ? -1 : (ret > 0 ? 1 : 0);
+
+    SysFreeString(left);
+    SysFreeString(right);
+    return return_short(res, val);
 }
 
 static HRESULT Global_LCase(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
@@ -1270,7 +1367,7 @@ static HRESULT Global_Chr(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIA
         buf[len++] = c>>8;
     if(!len || IsDBCSLeadByteEx(cp, buf[0]))
         buf[len++] = c;
-    if(!MultiByteToWideChar(0, 0, buf, len, &ch, 1)) {
+    if(!MultiByteToWideChar(CP_ACP, 0, buf, len, &ch, 1)) {
         WARN("invalid arg %d, cp %d\n", c, cp);
         return E_FAIL;
     }
@@ -1745,10 +1842,64 @@ static HRESULT Global_StrReverse(vbdisp_t *This, VARIANT *arg, unsigned args_cnt
     return return_bstr(res, ret);
 }
 
-static HRESULT Global_InStrRev(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
+static HRESULT Global_InStrRev(vbdisp_t *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    int start, ret = 0;
+    BSTR str1, str2;
+    HRESULT hres;
+
+    TRACE("%s %s arg_cnt=%u\n", debugstr_variant(args), debugstr_variant(args+1), args_cnt);
+
+    if(args_cnt > 3) {
+        FIXME("Unsupported args\n");
+        return E_NOTIMPL;
+    }
+
+    assert(2 <= args_cnt && args_cnt <= 4);
+
+    if(V_VT(args) == VT_NULL || V_VT(args+1) == VT_NULL || (args_cnt > 2 && V_VT(args+2) == VT_NULL))
+        return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE);
+
+    hres = to_string(args, &str1);
+    if(FAILED(hres))
+        return hres;
+
+    hres = to_string(args+1, &str2);
+    if(SUCCEEDED(hres)) {
+        if(args_cnt > 2) {
+            hres = to_int(args+2, &start);
+            if(SUCCEEDED(hres) && start <= 0) {
+                FIXME("Unsupported start %d\n", start);
+                hres = E_NOTIMPL;
+            }
+        }else {
+            start = SysStringLen(str1);
+        }
+    } else {
+        str2 = NULL;
+    }
+
+    if(SUCCEEDED(hres)) {
+        const WCHAR *ptr;
+        size_t len;
+
+        len = SysStringLen(str2);
+        if(start >= len && start <= SysStringLen(str1)) {
+            for(ptr = str1+start-SysStringLen(str2); ptr >= str1; ptr--) {
+                if(!memcmp(ptr, str2, len*sizeof(WCHAR))) {
+                    ret = ptr-str1+1;
+                    break;
+                }
+            }
+        }
+    }
+
+    SysFreeString(str1);
+    SysFreeString(str2);
+    if(FAILED(hres))
+        return hres;
+
+    return return_int(res, ret);
 }
 
 static HRESULT Global_LoadPicture(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
@@ -1772,12 +1923,7 @@ static HRESULT Global_ScriptEngineMajorVersion(vbdisp_t *This, VARIANT *arg, uns
 
     assert(args_cnt == 0);
 
-    if(res) {
-        V_VT(res) = VT_I4;
-        V_I4(res) = VBSCRIPT_MAJOR_VERSION;
-    }
-
-    return S_OK;
+    return return_int(res, VBSCRIPT_MAJOR_VERSION);
 }
 
 static HRESULT Global_ScriptEngineMinorVersion(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
@@ -1786,12 +1932,7 @@ static HRESULT Global_ScriptEngineMinorVersion(vbdisp_t *This, VARIANT *arg, uns
 
     assert(args_cnt == 0);
 
-    if(res) {
-        V_VT(res) = VT_I4;
-        V_I4(res) = VBSCRIPT_MINOR_VERSION;
-    }
-
-    return S_OK;
+    return return_int(res, VBSCRIPT_MINOR_VERSION);
 }
 
 static HRESULT Global_ScriptEngineBuildVersion(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
@@ -1800,12 +1941,7 @@ static HRESULT Global_ScriptEngineBuildVersion(vbdisp_t *This, VARIANT *arg, uns
 
     assert(args_cnt == 0);
 
-    if(res) {
-        V_VT(res) = VT_I4;
-        V_I4(res) = VBSCRIPT_BUILD_VERSION;
-    }
-
-    return S_OK;
+    return return_int(res, VBSCRIPT_BUILD_VERSION);
 }
 
 static HRESULT Global_FormatNumber(vbdisp_t *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)