[WIDL]
[reactos.git] / reactos / tools / widl / write_msft.c
index c5b9aa0..a191bef 100644 (file)
@@ -172,7 +172,7 @@ static void ctl2_init_segdir(
 
     segdir = &typelib->typelib_segdir[MSFT_SEG_TYPEINFO];
 
-    for (i = 0; i < 15; i++) {
+    for (i = 0; i < MSFT_SEG_MAX; i++) {
        segdir[i].offset = -1;
        segdir[i].length = 0;
        segdir[i].res08 = -1;
@@ -825,7 +825,6 @@ static int encode_type(
     case VT_UI4:
     case VT_R4:
     case VT_ERROR:
-    case VT_BSTR:
     case VT_HRESULT:
        *encoded_type = default_type;
        *width = 4;
@@ -861,8 +860,9 @@ static int encode_type(
 
     case VT_UNKNOWN:
     case VT_DISPATCH:
+    case VT_BSTR:
         *encoded_type = default_type;
-        *width = 4;
+        *width = pointer_size;
         *alignment = 4;
         break;
 
@@ -873,7 +873,7 @@ static int encode_type(
     case VT_LPSTR:
     case VT_LPWSTR:
         *encoded_type = 0xfffe0000 | vt;
-        *width = 4;
+        *width = pointer_size;
         *alignment = 4;
         break;
 
@@ -896,7 +896,7 @@ static int encode_type(
         if(next_vt == VT_DISPATCH || next_vt == VT_UNKNOWN) {
             chat("encode_type: skipping ptr\n");
             *encoded_type = target_type;
-            *width = 4;
+            *width = pointer_size;
             *alignment = 4;
             *decoded_size = child_size;
             break;
@@ -926,13 +926,12 @@ static int encode_type(
 
        *encoded_type = typeoffset;
 
-       *width = 4;
+       *width = pointer_size;
        *alignment = 4;
        *decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
         break;
     }
 
-
     case VT_SAFEARRAY:
        {
        type_t *element_type = type_alias_get_aliasee(type_array_get_element(type));
@@ -964,13 +963,12 @@ static int encode_type(
 
        *encoded_type = typeoffset;
 
-       *width = 4;
+       *width = pointer_size;
        *alignment = 4;
        *decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
        break;
        }
 
-
     case VT_USERDEFINED:
       {
         int typeinfo_offset;
@@ -1117,7 +1115,7 @@ static int encode_var(
             chat("encode_var: skipping ptr\n");
             *encoded_type = target_type;
             *decoded_size = child_size;
-            *width = 4;
+            *width = pointer_size;
             *alignment = 4;
             return 0;
         }
@@ -1146,7 +1144,7 @@ static int encode_var(
 
        *encoded_type = typeoffset;
 
-       *width = 4;
+       *width = pointer_size;
        *alignment = 4;
        *decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
         return 0;
@@ -1191,6 +1189,8 @@ static void write_value(msft_typelib_t* typelib, int *out, int vt, const void *v
     case VT_UINT:
     case VT_HRESULT:
     case VT_PTR:
+    case VT_UNKNOWN:
+    case VT_DISPATCH:
       {
         const unsigned int lv = get_ulong_val(*(const unsigned int *)value, vt);
         if((lv & 0x3ffffff) == lv) {
@@ -1230,7 +1230,7 @@ static void write_value(msft_typelib_t* typelib, int *out, int vt, const void *v
 }
 
 static HRESULT set_custdata(msft_typelib_t *typelib, REFGUID guid,
-                            int vt, int value, int *offset)
+                            int vt, const void *value, int *offset)
 {
     MSFT_GuidEntry guidentry;
     int guidoffset;
@@ -1244,7 +1244,7 @@ static HRESULT set_custdata(msft_typelib_t *typelib, REFGUID guid,
     guidentry.next_hash = -1;
 
     guidoffset = ctl2_alloc_guid(typelib, &guidentry);
-    write_value(typelib, &data_out, vt, &value);
+    write_value(typelib, &data_out, vt, value);
 
     custoffset = ctl2_alloc_segment(typelib, MSFT_SEG_CUSTDATAGUID, 12, 0);
 
@@ -1257,6 +1257,33 @@ static HRESULT set_custdata(msft_typelib_t *typelib, REFGUID guid,
     return S_OK;
 }
 
+/* It's possible to have a default value for pointer arguments too.
+   In this case default value has a referenced type, e.g.
+   'LONG*' argument gets VT_I4, 'DOUBLE*' - VT_R8. IUnknown* and IDispatch*
+   are recognised too and stored as VT_UNKNOWN and VT_DISPATCH.
+   But IUnknown/IDispatch arguments can only have default value of 0
+   (or expression that resolves to zero) while other pointers can have
+   any default value. */
+static int get_defaultvalue_vt(type_t *type)
+{
+    int vt = get_type_vt(type);
+    if (type_get_type(type) == TYPE_ENUM)
+        vt = VT_I4;
+    else
+   {
+        vt = get_type_vt(type);
+        if (vt == VT_PTR && is_ptr(type)) {
+            vt = get_type_vt(type_pointer_get_ref(type));
+            /* The only acceptable value for pointers to non-basic types
+               is NULL, it's stored as VT_I4 for both 32 and 64 bit typelibs. */
+            if (vt == VT_USERDEFINED)
+                vt = VT_I4;
+        }
+    }
+
+    return vt;
+}
+
 static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index)
 {
     int offset, name_offset;
@@ -1481,10 +1508,7 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index)
               {
                 int vt;
                 expr_t *expr = (expr_t *)attr->u.pval;
-                if (type_get_type(arg->type) == TYPE_ENUM)
-                    vt = VT_INT;
-                else
-                    vt = get_type_vt(arg->type);
+                vt = get_defaultvalue_vt(arg->type);
                 paramflags |= 0x30; /* PARAMFLAG_FHASDEFAULT | PARAMFLAG_FOPT */
                 if (expr->type == EXPR_STRLIT || expr->type == EXPR_WSTRLIT)
                 {
@@ -1726,7 +1750,7 @@ static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var)
         break;
     case TKIND_DISPATCH:
         var_kind = 3; /* VAR_DISPATCH */
-        typeinfo->datawidth = 4;
+        typeinfo->datawidth = pointer_size;
         var_alignment = 4;
         break;
     default:
@@ -1979,7 +2003,7 @@ static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinte
     msft_typeinfo = create_msft_typeinfo(typelib, TKIND_DISPATCH, dispinterface->name,
                                          dispinterface->attrs);
 
-    msft_typeinfo->typeinfo->size = 4;
+    msft_typeinfo->typeinfo->size = pointer_size;
     msft_typeinfo->typeinfo->typekind |= 0x2100;
 
     msft_typeinfo->typeinfo->flags |= 0x1000; /* TYPEFLAG_FDISPATCHABLE */
@@ -2024,8 +2048,7 @@ static void add_interface_typeinfo(msft_typelib_t *typelib, type_t *interface)
         return;
     }
 
-    if (is_attr(interface->attrs, ATTR_DISPINTERFACE))
-    {
+    if (is_attr(interface->attrs, ATTR_DISPINTERFACE)) {
         add_dispinterface_typeinfo(typelib, interface);
         return;
     }
@@ -2045,7 +2068,7 @@ static void add_interface_typeinfo(msft_typelib_t *typelib, type_t *interface)
 
     interface->typelib_idx = typelib->typelib_header.nrtypeinfos;
     msft_typeinfo = create_msft_typeinfo(typelib, TKIND_INTERFACE, interface->name, interface->attrs);
-    msft_typeinfo->typeinfo->size = 4;
+    msft_typeinfo->typeinfo->size = pointer_size;
     msft_typeinfo->typeinfo->typekind |= 0x2200;
 
     for (derived = inherit; derived; derived = type_iface_get_inherit(derived))
@@ -2102,6 +2125,9 @@ static void add_enum_typeinfo(msft_typelib_t *typelib, type_t *enumeration)
     var_t *cur;
     msft_typeinfo_t *msft_typeinfo;
 
+    if (-1 < enumeration->typelib_idx)
+        return;
+
     enumeration->typelib_idx = typelib->typelib_header.nrtypeinfos;
     msft_typeinfo = create_msft_typeinfo(typelib, TKIND_ENUM, enumeration->name, enumeration->attrs);
     msft_typeinfo->typeinfo->size = 0;
@@ -2209,7 +2235,7 @@ static void add_coclass_typeinfo(msft_typelib_t *typelib, type_t *cls)
         first_source->flags |= 0x1;
 
     msft_typeinfo->typeinfo->cImplTypes = num_ifaces;
-    msft_typeinfo->typeinfo->size = 4;
+    msft_typeinfo->typeinfo->size = pointer_size;
     msft_typeinfo->typeinfo->typekind |= 0x2200;
 }
 
@@ -2265,6 +2291,7 @@ static void add_entry(msft_typelib_t *typelib, const statement_t *stmt)
     switch(stmt->type) {
     case STMT_LIBRARY:
     case STMT_IMPORT:
+    case STMT_PRAGMA:
     case STMT_CPPQUOTE:
     case STMT_DECLARATION:
         /* not included in typelib */
@@ -2546,7 +2573,12 @@ static void save_all_changes(msft_typelib_t *typelib)
 
     if (strendswith( typelib_name, ".res" ))  /* create a binary resource file */
     {
-        add_output_to_resources( "TYPELIB", "#1" );
+        char typelib_id[13] = "#1";
+
+        expr_t *expr = get_attrp( typelib->typelib->attrs, ATTR_ID );
+        if (expr)
+            sprintf( typelib_id, "#%d", expr->cval );
+        add_output_to_resources( "TYPELIB", typelib_id );
         output_typelib_regscript( typelib->typelib );
         flush_output_resources( typelib_name );
     }
@@ -2560,9 +2592,11 @@ int create_msft_typelib(typelib_t *typelib)
     const statement_t *stmt;
     time_t cur_time;
     char *time_override;
-    unsigned int version = 5 << 24 | 1 << 16 | 164; /* 5.01.0164 */
-    GUID midl_time_guid    = {0xde77ba63,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}}; 
-    GUID midl_version_guid = {0xde77ba64,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}}; 
+    unsigned int version = 7 << 24 | 555; /* 7.00.0555 */
+    GUID midl_time_guid    = {0xde77ba63,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}};
+    GUID midl_version_guid = {0xde77ba64,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}};
+    GUID midl_info_guid = {0xde77ba65,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}};
+    char info_string[128];
 
     pointer_size = (typelib_kind == SYS_WIN64) ? 8 : 4;
 
@@ -2609,8 +2643,10 @@ int create_msft_typelib(typelib_t *typelib)
        and midl's version number */
     time_override = getenv( "WIDL_TIME_OVERRIDE");
     cur_time = time_override ? atol( time_override) : time(NULL);
-    set_custdata(msft, &midl_time_guid, VT_UI4, cur_time, &msft->typelib_header.CustomDataOffset);
-    set_custdata(msft, &midl_version_guid, VT_UI4, version, &msft->typelib_header.CustomDataOffset);
+    sprintf(info_string, "Created by WIDL version %s at %s\n", PACKAGE_VERSION, ctime(&cur_time));
+    set_custdata(msft, &midl_info_guid, VT_BSTR, info_string, &msft->typelib_header.CustomDataOffset);
+    set_custdata(msft, &midl_time_guid, VT_UI4, &cur_time, &msft->typelib_header.CustomDataOffset);
+    set_custdata(msft, &midl_version_guid, VT_UI4, &version, &msft->typelib_header.CustomDataOffset);
 
     if (typelib->stmts)
         LIST_FOR_EACH_ENTRY( stmt, typelib->stmts, const statement_t, entry )