[PATCH v8 2/3] shell32: Implement FolderItems_Item.

Sebastian Lackner sebastian at fds-team.de
Mon Aug 22 11:34:07 CDT 2016


On 22.08.2016 18:09, Alex Henrie wrote:
>>> +
>>> +            if (!PathCombineW(path, V_BSTR(dir), file_info.cFileName))
>>> +            {
>>> +                ret = E_OUTOFMEMORY;
>>> +                goto fail;
>>> +            }
>>
>> I think it makes more sense to store the relative paths, there is no
>> need to prepend the directory name in advance. FolderItemsImpl_Item
>> also expects a relative path for example.
> 
> Are you sure? In the common case, FolderItemsImpl_Item receives a
> VT_I4 index and can simply pass the saved path from the array to
> FolderItem_Constructor. If we save filenames instead, we'll have to
> call PathCombineW, SysAllocString, and SysFreeString in both the VT_I4
> and the VT_BSTR cases.

I definitely think this is better. It is wasting a lot of memory when
the full path is computed in advance. Also, it would be more consistent
with the existing calls to FolderItem_Constructor(). If you are concerned
about having the code twice, you could either implement it in the
constructor itself (and simplify the existing code) or by using a common
implementation for both VT_I4 and VT_BSTR. Something like this should work
(pseudo-code):

--- snip ---
    switch (V_VT(&index))
    {
        case VT_I2:
            i = V_I2(&index);
            break;

        case VT_I4:
            i = V_I4(&index);
            break;

        case VT_BSTR:
            [...]
            break;

        case VT_ERROR:
            return FolderItem_Constructor(&This->dir, ppid);

        default:
            return E_NOTIMPL;
    }

    if (i < 0 || i >= This->item_count)
        return S_FALSE;

    [... call constructor ...]
--- snip ---

Please note that after this change it might no longer be necessary to
use SysAllocString for the internal variables.

> 
>>> +
>>> +            paths = HeapReAlloc(GetProcessHeap(), 0, This->item_paths, (This->item_count + 1) * sizeof(BSTR));
>>
>> It seems more reasonable to increase the buffer size in bigger chunks.
>> Its better to have a few entries overhead than to do frequent reallocs.
> 
> How about allocating 128 string pointers (1 kibibyte) at a time? The
> code would be:
> 
> if (This->item_count % 128)
> {
>     paths = HeapReAlloc(GetProcessHeap(), 0, This->item_paths,
>                         (1 + This->item_count / 128) * 128 * sizeof(BSTR));
>     if (!paths)
>         goto fail;
>     This->item_paths = paths;
> }

It is probably fine, but actually it might be easier to just add a "item_size"
variable corresponding to the current amount of allocated memory. For example:

--- snip ---
    item_size = 128;
    This->item_paths = HeapAlloc(GetProcessHeap(), 0, item_size * sizeof(...));
    [...]
            if (This->item_count >= item_size)
            {
                paths = HeapReAlloc(GetProcessHeap(), 0, This->item_paths, (item_size + 128) * sizeof(...));
                if (!paths)
                {
                    ret = E_OUTOFMEMORY;
                    goto fail;
                }
                This->item_paths = paths;
                item_size += 128;
            }
--- snip ---




More information about the wine-devel mailing list