diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c
index a1d091e007495ce82585fda800149885bf85d198..e9a9723ab20b0c1cacf91422767f6eb2b59d9ce5 100644
--- a/dlls/uiautomationcore/tests/uiautomation.c
+++ b/dlls/uiautomationcore/tests/uiautomation.c
@@ -10560,6 +10560,171 @@ static void test_CUIAutomation_condition_ifaces(IUIAutomation *uia_iface)
     IUIAutomationBoolCondition_Release(bool_cond);
 }
 
+static void test_CUIAutomation_cache_request_iface(IUIAutomation *uia_iface)
+{
+    IUIAutomationPropertyCondition *prop_cond;
+    enum PropertyConditionFlags prop_flags;
+    IUIAutomationCacheRequest *cache_req;
+    enum AutomationElementMode elem_mode;
+    IUIAutomationCondition *cond, *cond2;
+    IUIAutomationNotCondition *not_cond;
+    enum TreeScope scope;
+    PROPERTYID prop_id;
+    HRESULT hr;
+    VARIANT v;
+
+    hr = IUIAutomation_CreateCacheRequest(uia_iface, NULL);
+    ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
+
+    /*
+     * CreateCacheRequest returns an IUIAutomationCacheRequest with the
+     * default cache request values set.
+     */
+    cache_req = NULL;
+    hr = IUIAutomation_CreateCacheRequest(uia_iface, &cache_req);
+    ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+    ok(!!cache_req, "cache_req == NULL\n");
+
+    /*
+     * TreeScope tests.
+     */
+    hr = IUIAutomationCacheRequest_get_TreeScope(cache_req, NULL);
+    ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
+
+    scope = 0;
+    hr = IUIAutomationCacheRequest_get_TreeScope(cache_req, &scope);
+    ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+    ok(scope == TreeScope_Element, "Unexpected scope %#x\n", scope);
+
+    /* Set it to something invalid. */
+    hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, 0);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
+
+    hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, TreeScope_Parent);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
+
+    hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, TreeScope_Ancestors);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
+
+    hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, TreeScope_Parent | TreeScope_Element);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
+
+    hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, TreeScope_Ancestors | TreeScope_Element);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
+
+    hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, ~(TreeScope_SubTree | TreeScope_Parent | TreeScope_Ancestors));
+    ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
+
+    /* Invalid values don't change anything. */
+    scope = 0;
+    hr = IUIAutomationCacheRequest_get_TreeScope(cache_req, &scope);
+    ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+    ok(scope == TreeScope_Element, "Unexpected scope %#x\n", scope);
+
+    /* Now set it to TreeScope_Children. */
+    hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, TreeScope_Children);
+    todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+
+    scope = 0;
+    hr = IUIAutomationCacheRequest_get_TreeScope(cache_req, &scope);
+    ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+    todo_wine ok(scope == TreeScope_Children, "Unexpected scope %#x\n", scope);
+
+    /*
+     * TreeFilter tests.
+     */
+    cond = NULL;
+    hr = IUIAutomationCacheRequest_get_TreeFilter(cache_req, NULL);
+    ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
+
+    cond = NULL;
+    hr = IUIAutomationCacheRequest_put_TreeFilter(cache_req, NULL);
+    ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
+
+    cond = NULL;
+    hr = IUIAutomationCacheRequest_put_TreeFilter(cache_req, (IUIAutomationCondition *)&Object);
+    ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
+
+    /* Default IUIAutomationCacheRequest has the ControlView condition. */
+    cond = NULL;
+    hr = IUIAutomationCacheRequest_get_TreeFilter(cache_req, &cond);
+    ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+    ok(!!cond, "cond == NULL\n");
+
+    hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationNotCondition, (void **)&not_cond);
+    IUIAutomationCondition_Release(cond);
+    ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+    ok(!!not_cond, "not_cond == NULL\n");
+
+    cond = NULL;
+    hr = IUIAutomationNotCondition_GetChild(not_cond, &cond);
+    ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+    ok(!!cond, "cond == NULL\n");
+
+    hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationPropertyCondition, (void **)&prop_cond);
+    IUIAutomationCondition_Release(cond);
+    ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+    ok(!!prop_cond, "prop_cond == NULL\n");
+
+    hr = IUIAutomationPropertyCondition_get_PropertyId(prop_cond, &prop_id);
+    ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+    ok(prop_id == UIA_IsControlElementPropertyId, "Unexpected prop_id %d.\n", prop_id);
+
+    VariantInit(&v);
+    hr = IUIAutomationPropertyCondition_get_PropertyValue(prop_cond, &v);
+    ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+    ok(check_variant_bool(&v, FALSE), "Unexpected BOOL %#x\n", V_BOOL(&v));
+    VariantClear(&v);
+
+    hr = IUIAutomationPropertyCondition_get_PropertyConditionFlags(prop_cond, &prop_flags);
+    ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+    ok(prop_flags == PropertyConditionFlags_None, "Unexpected flags %#x.\n", prop_flags);
+
+    IUIAutomationPropertyCondition_Release(prop_cond);
+    IUIAutomationNotCondition_Release(not_cond);
+
+    /* Set a new TreeFilter condition. */
+    cond = NULL;
+    hr = IUIAutomation_CreateTrueCondition(uia_iface, &cond);
+    ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+    ok(!!cond, "cond == NULL\n");
+
+    hr = IUIAutomationCacheRequest_put_TreeFilter(cache_req, cond);
+    ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+
+    hr = IUIAutomationCacheRequest_get_TreeFilter(cache_req, &cond2);
+    ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+    ok(!!cond2, "cond2 == NULL\n");
+    ok(iface_cmp((IUnknown *)cond, (IUnknown *)cond2), "cond != cond2\n");
+    IUIAutomationCondition_Release(cond);
+    IUIAutomationCondition_Release(cond2);
+
+    /*
+     * AutomationElementMode tests.
+     */
+    hr = IUIAutomationCacheRequest_get_AutomationElementMode(cache_req, NULL);
+    ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
+
+    elem_mode = 0;
+    hr = IUIAutomationCacheRequest_get_AutomationElementMode(cache_req, &elem_mode);
+    ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+    ok(elem_mode == AutomationElementMode_Full, "Unexpected element mode %#x\n", elem_mode);
+
+    /* Invalid value - maximum is AutomationElementMode_Full, 0x01. */
+    hr = IUIAutomationCacheRequest_put_AutomationElementMode(cache_req, 0x02);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
+
+    hr = IUIAutomationCacheRequest_put_AutomationElementMode(cache_req, AutomationElementMode_None);
+    todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+
+    elem_mode = 0;
+    hr = IUIAutomationCacheRequest_get_AutomationElementMode(cache_req, &elem_mode);
+    ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+    todo_wine ok(elem_mode == AutomationElementMode_None, "Unexpected element mode %#x\n", elem_mode);
+
+    IUIAutomationCacheRequest_Release(cache_req);
+}
+
 struct uia_com_classes {
     const GUID *clsid;
     const GUID *iid;
@@ -10660,6 +10825,7 @@ static void test_CUIAutomation(void)
 
     test_CUIAutomation_condition_ifaces(uia_iface);
     test_CUIAutomation_value_conversion(uia_iface);
+    test_CUIAutomation_cache_request_iface(uia_iface);
     test_ElementFromHandle(uia_iface, has_cui8);
     test_Element_GetPropertyValue(uia_iface);
 
diff --git a/dlls/uiautomationcore/uia_com_client.c b/dlls/uiautomationcore/uia_com_client.c
index 83205255c7c8c9fa5c85cb267478b9ab422dc628..96eaee412b45fb4bdbed1c3f416509ee2de40e4f 100644
--- a/dlls/uiautomationcore/uia_com_client.c
+++ b/dlls/uiautomationcore/uia_com_client.c
@@ -593,6 +593,264 @@ static HRESULT get_uia_condition_struct_from_iface(IUIAutomationCondition *condi
     return S_OK;
 }
 
+static HRESULT create_control_view_condition_iface(IUIAutomationCondition **out_condition)
+{
+    IUIAutomationCondition *prop_cond, *not_cond;
+    HRESULT hr;
+    VARIANT v;
+
+    if (!out_condition)
+        return E_POINTER;
+
+    *out_condition = NULL;
+
+    VariantInit(&v);
+    V_VT(&v) = VT_BOOL;
+    V_BOOL(&v) = VARIANT_FALSE;
+    hr = create_uia_property_condition_iface(&prop_cond, UIA_IsControlElementPropertyId, v, PropertyConditionFlags_None);
+    if (FAILED(hr))
+        return hr;
+
+    hr = create_uia_not_condition_iface(&not_cond, prop_cond);
+    if (FAILED(hr))
+    {
+        IUIAutomationCondition_Release(prop_cond);
+        return hr;
+    }
+
+    *out_condition = not_cond;
+
+    return S_OK;
+}
+
+/*
+ * IUIAutomationCacheRequest interface.
+ */
+struct uia_cache_request {
+    IUIAutomationCacheRequest IUIAutomationCacheRequest_iface;
+    LONG ref;
+
+    IUIAutomationCondition *view_condition;
+    struct UiaCacheRequest cache_req;
+};
+
+static inline struct uia_cache_request *impl_from_IUIAutomationCacheRequest(IUIAutomationCacheRequest *iface)
+{
+    return CONTAINING_RECORD(iface, struct uia_cache_request, IUIAutomationCacheRequest_iface);
+}
+
+static HRESULT WINAPI uia_cache_request_QueryInterface(IUIAutomationCacheRequest *iface, REFIID riid, void **ppv)
+{
+    *ppv = NULL;
+    if (IsEqualIID(riid, &IID_IUIAutomationCacheRequest) || IsEqualIID(riid, &IID_IUnknown))
+        *ppv = iface;
+    else
+        return E_NOINTERFACE;
+
+    IUIAutomationCacheRequest_AddRef(iface);
+    return S_OK;
+}
+
+static ULONG WINAPI uia_cache_request_AddRef(IUIAutomationCacheRequest *iface)
+{
+    struct uia_cache_request *uia_cache_request = impl_from_IUIAutomationCacheRequest(iface);
+    ULONG ref = InterlockedIncrement(&uia_cache_request->ref);
+
+    TRACE("%p, refcount %ld\n", uia_cache_request, ref);
+    return ref;
+}
+
+static ULONG WINAPI uia_cache_request_Release(IUIAutomationCacheRequest *iface)
+{
+    struct uia_cache_request *uia_cache_request = impl_from_IUIAutomationCacheRequest(iface);
+    ULONG ref = InterlockedDecrement(&uia_cache_request->ref);
+
+    TRACE("%p, refcount %ld\n", uia_cache_request, ref);
+
+    if (!ref)
+    {
+        IUIAutomationCondition_Release(uia_cache_request->view_condition);
+        heap_free(uia_cache_request);
+    }
+
+    return ref;
+}
+
+static HRESULT WINAPI uia_cache_request_AddProperty(IUIAutomationCacheRequest *iface, PROPERTYID prop_id)
+{
+    FIXME("%p, %d: stub\n", iface, prop_id);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI uia_cache_request_AddPattern(IUIAutomationCacheRequest *iface, PATTERNID pattern_id)
+{
+    FIXME("%p, %d: stub\n", iface, pattern_id);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI uia_cache_request_Clone(IUIAutomationCacheRequest *iface, IUIAutomationCacheRequest **out_req)
+{
+    FIXME("%p, %p: stub\n", iface, out_req);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI uia_cache_request_get_TreeScope(IUIAutomationCacheRequest *iface, enum TreeScope *scope)
+{
+    struct uia_cache_request *uia_cache_request = impl_from_IUIAutomationCacheRequest(iface);
+
+    TRACE("%p, %p\n", iface, scope);
+
+    if (!scope)
+        return E_POINTER;
+
+    *scope = uia_cache_request->cache_req.Scope;
+
+    return S_OK;
+}
+
+static HRESULT WINAPI uia_cache_request_put_TreeScope(IUIAutomationCacheRequest *iface, enum TreeScope scope)
+{
+    struct uia_cache_request *uia_cache_request = impl_from_IUIAutomationCacheRequest(iface);
+
+    TRACE("%p, %#x\n", iface, scope);
+
+    if (!scope || (scope & ~TreeScope_SubTree))
+        return E_INVALIDARG;
+
+    if ((scope & TreeScope_Children) || (scope & TreeScope_Descendants))
+    {
+        FIXME("Unimplemented TreeScope %#x\n", scope);
+        return E_NOTIMPL;
+    }
+
+    uia_cache_request->cache_req.Scope = scope;
+
+    return S_OK;
+}
+
+static HRESULT WINAPI uia_cache_request_get_TreeFilter(IUIAutomationCacheRequest *iface,
+        IUIAutomationCondition **filter)
+{
+    struct uia_cache_request *uia_cache_request = impl_from_IUIAutomationCacheRequest(iface);
+
+    TRACE("%p, %p\n", iface, filter);
+
+    if (!filter)
+        return E_POINTER;
+
+    IUIAutomationCondition_AddRef(uia_cache_request->view_condition);
+    *filter = uia_cache_request->view_condition;
+
+    return S_OK;
+}
+
+static HRESULT WINAPI uia_cache_request_put_TreeFilter(IUIAutomationCacheRequest *iface, IUIAutomationCondition *filter)
+{
+    struct uia_cache_request *uia_cache_request = impl_from_IUIAutomationCacheRequest(iface);
+    struct UiaCondition *cond_struct;
+    HRESULT hr;
+
+    TRACE("%p, %p\n", iface, filter);
+
+    if (!filter)
+        return E_POINTER;
+
+    hr = get_uia_condition_struct_from_iface(filter, &cond_struct);
+    if (FAILED(hr))
+        return hr;
+
+    uia_cache_request->cache_req.pViewCondition = cond_struct;
+    IUIAutomationCondition_Release(uia_cache_request->view_condition);
+    uia_cache_request->view_condition = filter;
+    IUIAutomationCondition_AddRef(filter);
+
+    return S_OK;
+}
+
+static HRESULT WINAPI uia_cache_request_get_AutomationElementMode(IUIAutomationCacheRequest *iface,
+        enum AutomationElementMode *mode)
+{
+    struct uia_cache_request *uia_cache_request = impl_from_IUIAutomationCacheRequest(iface);
+
+    TRACE("%p, %p\n", iface, mode);
+
+    if (!mode)
+        return E_POINTER;
+
+    *mode = uia_cache_request->cache_req.automationElementMode;
+
+    return S_OK;
+}
+
+static HRESULT WINAPI uia_cache_request_put_AutomationElementMode(IUIAutomationCacheRequest *iface,
+        enum AutomationElementMode mode)
+{
+    struct uia_cache_request *uia_cache_request = impl_from_IUIAutomationCacheRequest(iface);
+
+    TRACE("%p, %d\n", iface, mode);
+
+    if ((mode != AutomationElementMode_Full) && (mode != AutomationElementMode_None))
+        return E_INVALIDARG;
+
+    if (mode == AutomationElementMode_None)
+    {
+        FIXME("AutomationElementMode_None unsupported\n");
+        return E_NOTIMPL;
+    }
+
+    uia_cache_request->cache_req.automationElementMode = mode;
+
+    return S_OK;
+}
+
+static const IUIAutomationCacheRequestVtbl uia_cache_request_vtbl = {
+    uia_cache_request_QueryInterface,
+    uia_cache_request_AddRef,
+    uia_cache_request_Release,
+    uia_cache_request_AddProperty,
+    uia_cache_request_AddPattern,
+    uia_cache_request_Clone,
+    uia_cache_request_get_TreeScope,
+    uia_cache_request_put_TreeScope,
+    uia_cache_request_get_TreeFilter,
+    uia_cache_request_put_TreeFilter,
+    uia_cache_request_get_AutomationElementMode,
+    uia_cache_request_put_AutomationElementMode,
+};
+
+static HRESULT create_uia_cache_request_iface(IUIAutomationCacheRequest **out_cache_req)
+{
+    struct uia_cache_request *uia_cache_request;
+    IUIAutomationCondition *view_condition;
+    HRESULT hr;
+
+    if (!out_cache_req)
+        return E_POINTER;
+
+    *out_cache_req = NULL;
+    hr = create_control_view_condition_iface(&view_condition);
+    if (FAILED(hr))
+        return hr;
+
+    uia_cache_request = heap_alloc_zero(sizeof(*uia_cache_request));
+    if (!uia_cache_request)
+    {
+        IUIAutomationCondition_Release(view_condition);
+        return E_OUTOFMEMORY;
+    }
+
+    uia_cache_request->IUIAutomationCacheRequest_iface.lpVtbl = &uia_cache_request_vtbl;
+    uia_cache_request->ref = 1;
+
+    uia_cache_request->view_condition = view_condition;
+    get_uia_condition_struct_from_iface(view_condition, &uia_cache_request->cache_req.pViewCondition);
+    uia_cache_request->cache_req.Scope = TreeScope_Element;
+    uia_cache_request->cache_req.automationElementMode = AutomationElementMode_Full;
+
+    *out_cache_req = &uia_cache_request->IUIAutomationCacheRequest_iface;
+    return S_OK;
+}
+
 /*
  * IUIAutomationElementArray interface.
  */
@@ -1969,34 +2227,9 @@ static HRESULT WINAPI uia_iface_get_RawViewCondition(IUIAutomation6 *iface, IUIA
 
 static HRESULT WINAPI uia_iface_get_ControlViewCondition(IUIAutomation6 *iface, IUIAutomationCondition **out_condition)
 {
-    IUIAutomationCondition *prop_cond, *not_cond;
-    HRESULT hr;
-    VARIANT v;
-
     TRACE("%p, %p\n", iface, out_condition);
 
-    if (!out_condition)
-        return E_POINTER;
-
-    *out_condition = NULL;
-
-    VariantInit(&v);
-    V_VT(&v) = VT_BOOL;
-    V_BOOL(&v) = VARIANT_FALSE;
-    hr = create_uia_property_condition_iface(&prop_cond, UIA_IsControlElementPropertyId, v, PropertyConditionFlags_None);
-    if (FAILED(hr))
-        return hr;
-
-    hr = create_uia_not_condition_iface(&not_cond, prop_cond);
-    if (FAILED(hr))
-    {
-        IUIAutomationCondition_Release(prop_cond);
-        return hr;
-    }
-
-    *out_condition = not_cond;
-
-    return S_OK;
+    return create_control_view_condition_iface(out_condition);
 }
 
 static HRESULT WINAPI uia_iface_get_ContentViewCondition(IUIAutomation6 *iface, IUIAutomationCondition **out_condition)
@@ -2007,8 +2240,9 @@ static HRESULT WINAPI uia_iface_get_ContentViewCondition(IUIAutomation6 *iface,
 
 static HRESULT WINAPI uia_iface_CreateCacheRequest(IUIAutomation6 *iface, IUIAutomationCacheRequest **out_cache_req)
 {
-    FIXME("%p, %p: stub\n", iface, out_cache_req);
-    return E_NOTIMPL;
+    TRACE("%p, %p\n", iface, out_cache_req);
+
+    return create_uia_cache_request_iface(out_cache_req);
 }
 
 static HRESULT WINAPI uia_iface_CreateTrueCondition(IUIAutomation6 *iface, IUIAutomationCondition **out_condition)