在Shell扩展编程中提取函数

时间:2019-04-05 20:43:55

标签: winapi visual-c++

我想将一些DropHandler代码提取到一个单独的函数中,但是不知道在使用接口指针或一般C ++时该怎么做。我只想使用单独的功能获取DragEnter中的第一项。

HRESULT drop_handler::GetFirstItem(IDataObject* p_data_obj, IShellItemArray* items, IShellItem* first_item)
{
    HRESULT hr = SHCreateShellItemArrayFromDataObject(p_data_obj, IID_PPV_ARGS(&items));
    if (hr != ERROR_SUCCESS)
    {
        return E_INVALIDARG;
    }

    DWORD item_count;
    items->GetCount(&item_count);
    if (item_count != 1)
    {
        items->Release();
        return E_INVALIDARG;
    }

    hr = items->GetItemAt(0, &first_item);
    if (hr != ERROR_SUCCESS)
    {
        items->Release();
        return E_INVALIDARG;
    }

    return ERROR_SUCCESS;
}

HRESULT drop_handler::DragEnter(IDataObject* p_data_obj, DWORD gtf_key_state, POINTL pt, DWORD* pdw_effect)
{
    IShellItemArray* items = nullptr;
    IShellItem* dragged_item = nullptr;
    HRESULT hr = GetFirstItem(p_data_obj, items, dragged_item);
    if (hr != ERROR_SUCCESS)
    {
        return E_INVALIDARG;
    }

    //...use dragged_item

此代码尝试会使Explorer崩溃。我不确定应该使用哪种类型的函数签名和指针。

修改:每个安德斯的固定答案

HRESULT drop_handler::GetFirstItem(IDataObject* p_data_obj, IShellItemArray*& items, IShellItem*& first_item)
{
    HRESULT hr = SHCreateShellItemArrayFromDataObject(p_data_obj, IID_PPV_ARGS(&items));
    if (hr != ERROR_SUCCESS)
    {
        return E_INVALIDARG;
    }

    DWORD item_count;
    hr = items->GetCount(&item_count);
    if (hr != ERROR_SUCCESS || item_count != 1)
    {
        items->Release();
        return E_INVALIDARG;
    }

    hr = items->GetItemAt(0, &first_item);
    if (hr != ERROR_SUCCESS)
    {
        items->Release();
        return E_INVALIDARG;
    }

    return ERROR_SUCCESS;
}

HRESULT drop_handler::DragEnter(IDataObject* p_data_obj, DWORD gtf_key_state, POINTL pt, DWORD* pdw_effect)
{
    IShellItemArray* items;
    IShellItem* dragged_item;
    HRESULT hr = GetFirstItem(p_data_obj, items, dragged_item);
    if (hr != ERROR_SUCCESS)
    {
        return E_INVALIDARG;
    }

    //...use dragged_item

1 个答案:

答案 0 :(得分:1)

您对IShellItemArray*IShellItem*的处理是错误的。 GetFirstItem将在失败时释放IShellItemArray*,但在成功时您将泄漏它,并且first_item将永远不会正确返回。 items中的first_itemDragEnter将永远无效。

IShellItemArray*应该是GetFirstItem中的局部变量。

IShellItem* first_item参数必须为IShellItem** first_itemIShellItem*& first_item,以便指针值正确返回给调用者。

您永远不会检查GetCount的返回值。

由于指针存在问题,您可能需要在使用它们之前添加一些assert来验证接口指针是否为非空。