TEST_F(ContextMapTest, VerifyWithThreadsPathological) { ContextMap<size_t> mp; // Context collection and exit race threads: vector<std::shared_ptr<CoreContext>> contexts; // Exit race controller: AutoRequired<ExitRaceSignal> signal; // Create a number of dependent contexts: for(size_t i = 0; i < 100; i++) { AutoCreateContext context; contexts.push_back(context); // Store a shared pointer mp.Add(i, context); // Start the context context->Initiate(); } // Set the signal: signal->Signal(); // Verify that the map empties once our zero-count is hit: for(size_t i = 0; i < contexts.size(); i++) { contexts[i]->SignalShutdown(true); } // Clear the context collection: contexts.clear(); EXPECT_EQ(0UL, mp.size()) << "Context map did not empty as expected"; }
TEST_F(ContextMapTest, ConcurrentDestructionTestPathological) { for(size_t i = 0; i < 100; i++) { // Create our map and a few contexts: ContextMap<string> mp; AutoCreateContext contexts[4]; weak_ptr<SimpleThreaded> threads[4]; // Insert into the map: mp.Add("pathological_destruction0", contexts[0]); mp.Add("pathological_destruction1", contexts[1]); mp.Add("pathological_destruction2", contexts[2]); mp.Add("pathological_destruction3", contexts[3]); // Add a thread and kick off the context: for(size_t i = ARRAYCOUNT(contexts); i--;) { threads[i] = contexts[i]->Inject<SimpleThreaded>(); contexts[i]->Initiate(); } // Immediately tear contexts down: for(size_t i = ARRAYCOUNT(contexts); i--;) contexts[i]->SignalShutdown(); // Wait on anything not signalled: for(size_t i = 0; i < ARRAYCOUNT(threads); i++) { auto cur = threads[i].lock(); if(cur) ASSERT_TRUE(cur->WaitFor(std::chrono::seconds(1))) << "Spawned thread did not exit in a timely fashion"; } } }
TEST_F(ContextMapTest, VerifySimpleEnumeration) { ContextMap<string> mp; AutoCreateContext ctxt1; AutoCreateContext ctxt2; AutoCreateContext ctxt3; mp.Add("context_se_1", ctxt1); mp.Add("context_se_2", ctxt2); mp.Add("context_se_3", ctxt3); std::set<std::string> found; size_t count = 0; mp.Enumerate( [&count, &found] (const string& name, std::shared_ptr<CoreContext>& ctxt) -> bool { count++; found.insert(name); return true; } ); EXPECT_EQ(3UL, count) << "Failed to enumerate all expected context pointers"; EXPECT_EQ(1UL, found.count("context_se_1")) << "Failed to find map element '1'"; EXPECT_EQ(1UL, found.count("context_se_2")) << "Failed to find map element '2'"; EXPECT_EQ(1UL, found.count("context_se_3")) << "Failed to find map element '3'"; }
// Fetches a previously constructed context by name. Context* GetContext(const String& name) { ContextMap::iterator i = contexts.find(name); if (i == contexts.end()) return NULL; return (*i).second; }
CQueue::OnCreateFile( /*[in]*/ IWDFIoQueue* pQueue, /*[in]*/ IWDFIoRequest* pRequest, /*[in]*/ IWDFFile* pFileObject ) { UNREFERENCED_PARAMETER(pQueue); TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FLAG_QUEUE, "%!FUNC! Entry"); // This critical section protects the section of code where we // Create the serializer and results interfaces used in handling I/O messages. // We only need to create them once, then we hang on to them for the lifetime of this // queue object. CComCritSecLock<CComAutoCriticalSection> Lock(m_CriticalSection); HRESULT hr = S_OK; // Create the WPD serializer if ((hr == S_OK) && (m_pWpdSerializer == NULL)) { hr = CoCreateInstance(CLSID_WpdSerializer, NULL, CLSCTX_INPROC_SERVER, IID_IWpdSerializer, (VOID**)&m_pWpdSerializer); CHECK_HR(hr, "Failed to CoCreate CLSID_WpdSerializer"); } // Create the client context map and associate it with the File Object // so we can obtain it on a per-client basis. if (hr == S_OK) { ContextMap* pClientContextMap = new ContextMap(); if(pClientContextMap != NULL) { hr = pFileObject->AssignContext(this, (void*)pClientContextMap); CHECK_HR(hr, "Failed to set client context map"); // Release the client context map if we cannot set it // properly if(FAILED(hr)) { pClientContextMap->Release(); pClientContextMap = NULL; } } else { hr = E_OUTOFMEMORY; CHECK_HR(hr, "Failed to create client context map"); } } pRequest->Complete(hr); return; }
TEST_F(ContextMapTest, VerifyWithThreads) { ContextMap<string> mp; std::shared_ptr<SimpleThreaded> threaded; std::weak_ptr<CoreContext> weakContext; { AutoCreateContext context; // Obtain a weak pointer of our own, and add to the context: weakContext = context; mp.Add("context_withthreads", context); // Add a thread to hold the context open for awhile: threaded = context->Inject<SimpleThreaded>(); // Start the context context->Initiate(); } // Assert that the context still actually exists: ASSERT_TRUE(!weakContext.expired()) << "Simple thread exited before it was signalled to exit"; { // Verify that we can still find the context while the thread is alive: std::shared_ptr<CoreContext> context = mp.Find("context_withthreads"); ASSERT_TRUE(!!context.get()) << "Map evicted a context before expected"; // Relock the weak context, verify that we get back the same pointer: auto relocked = weakContext.lock(); EXPECT_EQ(relocked, context) << "Mapped context pointer was not identical to a previously stored context pointer"; // Terminate whole context context->SignalTerminate(); } // Release our threaded entity: threaded.reset(); { // Verify that the context is gone now that everything in it has stopped running auto ctxt = mp.Find("context_withthreads"); EXPECT_FALSE(ctxt) << "Context was not properly evicted from the map"; // Just return early if the context was empty as we expected, the next part of this test is for diagnostics if(!ctxt) return; // Release the pointer so we aren't guilty of holding a reference to the very thing whose // destruction we are trying to assure. ctxt.reset(); // Sleep for a little bit and run the verification again. If the prior expectation fails, // but this one succeeds, it could be due to race conditions in CoreThread std::this_thread::sleep_for(std::chrono::milliseconds(10)); ctxt = mp.Find("context_withthreads"); EXPECT_FALSE(ctxt) << "Context was not properly evicted even after waiting for a time to ensure eviction"; } }
void KJavaServerMaintainer::releaseContext(QObject *w, const QString &doc) { ContextMap::iterator it = m_contextmap.find(qMakePair(w, doc)); if(it != m_contextmap.end() && --(*it).second <= 0) { kdDebug(6100) << "KJavaServerMaintainer::releaseContext" << endl; (*it).first->deleteLater(); m_contextmap.remove(it); } }
static void retrace_glXDestroyContext(trace::Call &call) { ContextMap::iterator it; it = context_map.find(call.arg(1).toUIntPtr()); if (it == context_map.end()) { return; } it->second->release(); context_map.erase(it); }
static Context * getContext(unsigned long long context_ptr) { if (context_ptr == 0) { return NULL; } ContextMap::const_iterator it; it = context_map.find(context_ptr); return (it != context_map.end()) ? it->second : NULL; }
TEST_F(ContextMapTest, OutOfOrderDeletionTest) { try { AutoCreateContext controlled; ContextMap<size_t> mp; // Add the current context to the map: mp.Add(1, controlled); // Map is destroyed first, then the enclosed context--no exceptions should be thrown } catch(...) { FAIL() << "Exception thrown while attempting an out-of-order teardown"; } }
static void retrace_wglDeleteContext(trace::Call &call) { unsigned long long hglrc = call.arg(0).toUIntPtr(); ContextMap::iterator it; it = context_map.find(hglrc); if (it == context_map.end()) { return; } it->second->release(); context_map.erase(it); }
KJavaAppletContext *KJavaServerMaintainer::getContext(QObject *w, const QString &doc) { ContextMap::key_type key = qMakePair(w, doc); ContextMap::iterator it = m_contextmap.find(key); if(it != m_contextmap.end()) { ++((*it).second); return (*it).first; } KJavaAppletContext *const context = new KJavaAppletContext(); m_contextmap.insert(key, qMakePair(context, 1)); return context; }
static Context * getContext(unsigned long long context_ptr) { if (context_ptr == 0) { return NULL; } ContextMap::const_iterator it; it = context_map.find(context_ptr); if (it == context_map.end()) { return (context_map[context_ptr] = glretrace::createContext()); } return it->second; }
static glws::Context * getContext(unsigned long long context_ptr) { if (context_ptr == 0) { return NULL; } ContextMap::const_iterator it; it = context_map.find(context_ptr); if (it == context_map.end()) { return (context_map[context_ptr] = ws->createContext(visual, NULL)); } return it->second; }
static void retrace_eglDestroyContext(trace::Call &call) { unsigned long long orig_context = call.arg(1).toUIntPtr(); ContextMap::iterator it; it = context_map.find(orig_context); if (it != context_map.end()) { glretrace::Context *currentContext = glretrace::getCurrentContext(); if (it->second != currentContext) { // TODO: reference count delete it->second; } context_map.erase(it); } }
static Context * getContext(unsigned long long context_ptr) { if (context_ptr == 0) { return NULL; } ContextMap::const_iterator it; it = context_map.find(context_ptr); if (it == context_map.end()) { assert(false); return NULL; } return it->second; }
CQueue::OnCleanup( IWDFObject* pWdfObject ) { // Destroy the client context map HRESULT hr = S_OK; ContextMap* pClientContextMap = NULL; hr = pWdfObject->RetrieveContext((void**)&pClientContextMap); if((hr == S_OK) && (pClientContextMap != NULL)) { pClientContextMap->Release(); pClientContextMap = NULL; } }
static void retrace_CGLDestroyContext(trace::Call &call) { if (call.ret->toUInt() != kCGLNoError) { return; } unsigned long long ctx = call.arg(0).toUIntPtr(); ContextMap::iterator it; it = context_map.find(ctx); if (it == context_map.end()) { return; } delete it->second; context_map.erase(it); }
CQueue::OnCleanup( IWDFObject* pWdfObject ) { TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FLAG_QUEUE, "%!FUNC! Entry"); // Destroy the client context map HRESULT hr = S_OK; ContextMap* pClientContextMap = NULL; hr = pWdfObject->RetrieveContext((void**)&pClientContextMap); if((hr == S_OK) && (pClientContextMap != NULL)) { pClientContextMap->Release(); pClientContextMap = NULL; } }
TEST_F(ContextMapTest, AdjacentCleanupTest) { ContextMap<string> mp; std::weak_ptr<CoreContext> outerWeak; std::weak_ptr<CoreContext> innerWeak; // Add two contexts, and let one go out of scope AutoCreateContext outer; mp.Add("0", outer); outerWeak = outer; { AutoCreateContext inner; mp.Add("1", inner); innerWeak = inner; // Verify that we can find both contexts std::shared_ptr<CoreContext> outerSearched = mp.Find("0"); ASSERT_TRUE(!!outerSearched.get()) << "Outer context just added, but couldn't be found"; std::shared_ptr<CoreContext> innerSearched = mp.Find("1"); ASSERT_TRUE(!!innerSearched.get()) << "Inner context just added, but couldn't be found"; } // Inner should be 404 by now ASSERT_TRUE(innerWeak.expired()) << "Unexpected outstanding reference to the inner context"; // Try to find the outer context. This should evict the inner context. mp.Find("0"); ASSERT_EQ(1UL, mp.size()) << "Proximity eviction didn't function as expected"; }
/** * This method is called when we receive a WPD_COMMAND_OBJECT_RESOURCES_CLOSE * command. * * The parameters sent to us are: * - WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT: the context the driver returned to * the client in OnOpenResource. * * The driver should: * - Destroy any data associated with this context. */ HRESULT WpdObjectResources::OnCloseResource( _In_ IPortableDeviceValues* pParams, _In_ IPortableDeviceValues* pResults) { HRESULT hr = S_OK; LPWSTR wszResourceContext = NULL; ContextMap* pContextMap = NULL; UNREFERENCED_PARAMETER(pResults); // First get ALL parameters for this command. If we cannot get ALL parameters // then E_INVALIDARG should be returned and no further processing should occur. // Get the resource context identifier for this resource operation. We will // need this to lookup the specific resource context in the client context map. hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT, &wszResourceContext); if (hr != S_OK) { hr = E_INVALIDARG; CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT"); } // Get the client context map so we can retrieve the resource context for this resource // operation using the WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT property value obtained above. if (hr == S_OK) { hr = pParams->GetIUnknownValue(PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP, (IUnknown**)&pContextMap); CHECK_HR(hr, "Failed to get PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP"); } // Destroy any data allocated/associated with the resource context and then remove it from the context map. // We no longer need to keep this context around because the resource operation has been ended. if (hr == S_OK) { pContextMap->Remove(wszResourceContext); } // Free the memory. CoTaskMemFree ignores NULLs so no need to check. CoTaskMemFree(wszResourceContext); SAFE_RELEASE(pContextMap); return hr; }
/** * This method is called when we receive a WPD_COMMAND_OBJECT_ENUMERATION_END_FIND * command. * * The parameters sent to us are: * - WPD_PROPERTY_OBJECT_ENUMERATION_CONTEXT: the context the driver returned to * the client in OnStartFind. * * The driver should: * - Destroy any data associated with this context. */ HRESULT WpdObjectEnumerator::OnEndFind( _In_ IPortableDeviceValues* pParams, _Inout_ IPortableDeviceValues* pResults) { HRESULT hr = S_OK; LPWSTR wszEnumContext = NULL; ContextMap* pContextMap = NULL; UNREFERENCED_PARAMETER(pResults); // First get ALL parameters for this command. If we cannot get ALL parameters // then E_INVALIDARG should be returned and no further processing should occur. // Get the enumeration context identifier for this enumeration operation. We will // need this to lookup the specific enumeration context in the client context map. hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_ENUMERATION_CONTEXT, &wszEnumContext); if (hr != S_OK) { hr = E_INVALIDARG; CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_ENUMERATION_CONTEXT"); } // Get the client context map so we can retrieve the enumeration context for this enumeration // operation using the WPD_PROPERTY_OBJECT_ENUMERATION_CONTEXT property value obtained above. if (hr == S_OK) { hr = GetClientContextMap(pParams, &pContextMap); CHECK_HR(hr, "Failed to get the client context map"); } // Destroy any data allocated/associated with the enumeration context and then remove it from the context map. // We no longer need to keep this context around because the enumeration has been ended. if (hr == S_OK) { pContextMap->Remove(wszEnumContext); } // Free the memory. CoTaskMemFree ignores NULLs so no need to check. CoTaskMemFree(wszEnumContext); SAFE_RELEASE(pContextMap); return hr; }
// Fetches a context by index. Context* GetContext(int index) { ContextMap::iterator i = contexts.begin(); int count = 0; if (index >= GetNumContexts()) index = GetNumContexts() - 1; while (count < index) { ++i; ++count; } if (i == contexts.end()) return NULL; return (*i).second; }
static Context * getContext(unsigned long long ctx) { if (ctx == 0) { return NULL; } ContextMap::const_iterator it; it = context_map.find(ctx); if (it == context_map.end()) { Context *context; context_map[ctx] = context = glretrace::createContext(sharedContext); if (!sharedContext) { sharedContext = context; } return context; } return it->second; }
void Shutdown() { // Notify all plugins we're being shutdown. PluginRegistry::Instance()->NotifyShutdown(); // Release all remaining contexts. for (ContextMap::iterator itr = contexts.begin(); itr != contexts.end(); ++itr) Core::Log::Message(Log::LT_WARNING, "Context '%s' still active on shutdown.", (*itr).first.CString()); contexts.clear(); TemplateCache::Shutdown(); StyleSheetFactory::Shutdown(); StyleSheetSpecification::Shutdown(); FontDatabase::Shutdown(); TextureDatabase::Shutdown(); Factory::Instance()->Shutdown(); Factory::DestroyInstance(); Log::Shutdown(); PluginRegistry::DestroyInstance(); PropertyParserColour::DestroyInstance(); PropCounterSingleton::DestroyInstance(); initialised = false; if (render_interface != NULL) render_interface->RemoveReference(); if (file_interface != NULL) file_interface->RemoveReference(); if (system_interface != NULL) system_interface->RemoveReference(); render_interface = NULL; file_interface = NULL; system_interface = NULL; }
TEST_F(ContextMapTest, VerifySimple) { ContextMap<string> mp; // Create a new context and add it to the map: { AutoCreateContext context; // Verify the reference count or the rest of the test will fail ASSERT_EQ(context.use_count(), 1) << "A newly created context's use count isn't what was expected"; // Add and ensure the reference count is unmodified mp.Add("context_simple", context); ASSERT_EQ(context.use_count(), 1) << "The map altered the context use count"; // We should be able to find this context now: std::shared_ptr<CoreContext> found = mp.Find("context_simple"); EXPECT_TRUE(!!found.get()) << "Failed to find a context that was just inserted into a context map"; } // We shouldn't be able to find it now that it's gone out of scope: std::shared_ptr<CoreContext> notFound = mp.Find("context_simple"); EXPECT_FALSE(!!notFound.get()) << "Context was not evicted as expected when it went out of scope"; }
int map_main(int argc, char* argv[]) { ContextMap *context = new ContextMap(); if (!context->parseCmdArgs(argc, argv, 1) || context->getShowHelp() || !context->isValidState()) { if (!context->getErrorMsg().empty()) { cerr << context->getErrorMsg() << endl; } map_help(); delete context; return 0; } FileMap *fileMap = new FileMap(context); bool retVal = fileMap->mapFiles(); delete fileMap; delete context; return retVal ? 0 : 1; }
/** * This method is called when we receive a WPD_COMMAND_OBJECT_RESOURCES_READ * command. * * The parameters sent to us are: * - WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT: the context the driver returned to * the client in OnOpenResource. * - WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_TO_READ: the number of bytes to * read from the resource. * * The driver should: * - Read data associated with the resource and return it back to the caller in * WPD_PROPERTY_OBJECT_RESOURCES_DATA. * - Report the number of bytes actually read from the resource in * WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_READ. This number may be smaller * than WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_TO_READ when reading the last * chunk of data from the resource. */ HRESULT WpdObjectResources::OnReadResource( _In_ IPortableDeviceValues* pParams, _In_ IPortableDeviceValues* pResults) { HRESULT hr = S_OK; LPWSTR wszResourceContext = NULL; DWORD dwNumBytesToRead = 0; DWORD dwNumBytesRead = 0; BYTE* pBuffer = NULL; DWORD cbBuffer = 0; WpdObjectResourceContext* pResourceContext = NULL; ContextMap* pContextMap = NULL; // Get the enumeration context identifier for this enumeration operation. We will // need this to lookup the specific enumeration context in the client context map. hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT, &wszResourceContext); if (hr != S_OK) { hr = E_INVALIDARG; CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT"); } // Get the number of bytes to read if (hr == S_OK) { hr = pParams->GetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_TO_READ, &dwNumBytesToRead); CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_TO_READ"); } // Get the destination buffer if (hr == S_OK) { hr = pParams->GetBufferValue(WPD_PROPERTY_OBJECT_RESOURCES_DATA, &pBuffer, &cbBuffer); CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_DATA"); } // Get the client context map so we can retrieve the resource context for this resource // operation using the WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT property value obtained above. if (hr == S_OK) { hr = pParams->GetIUnknownValue(PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP, (IUnknown**)&pContextMap); CHECK_HR(hr, "Failed to get PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP"); } if (hr == S_OK) { pResourceContext = (WpdObjectResourceContext*)pContextMap->GetContext(wszResourceContext); if (pResourceContext == NULL) { hr = E_INVALIDARG; CHECK_HR(hr, "Missing resource context"); } } // Read the next chunk of data for this request if (hr == S_OK && pBuffer != NULL) { hr = ReadDataFromResource(pResourceContext, pBuffer, dwNumBytesToRead, &dwNumBytesRead); CHECK_HR(hr, "Failed to read %d bytes from resource", dwNumBytesToRead); } if (hr == S_OK && pBuffer != NULL) { hr = pResults->SetBufferValue(WPD_PROPERTY_OBJECT_RESOURCES_DATA, pBuffer, dwNumBytesRead); CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_RESOURCES_DATA"); } if (hr == S_OK) { hr = pResults->SetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_READ, dwNumBytesRead); CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_READ"); } // Free the memory. CoTaskMemFree ignores NULLs so no need to check. CoTaskMemFree(wszResourceContext); // Free the memory. CoTaskMemFree ignores NULLs so no need to check. CoTaskMemFree(pBuffer); SAFE_RELEASE(pContextMap); return hr; }
/** * This method is called when we receive a WPD_COMMAND_OBJECT_RESOURCES_OPEN * command. * * The parameters sent to us are: * - WPD_PROPERTY_OBJECT_RESOURCES_OBJECT_ID: the object identifier of the * object which contains the specified resource * * - WPD_PROPERTY_OBJECT_RESOURCES_RESOURCE_KEYS: the specified resource * to open * * - WPD_PROPERTY_OBJECT_RESOURCES_ACCESS_MODE: the access mode to which to * open the specified resource * * The driver should: * - Create a new context for this resource operation. * - Return an identifier for the context in WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT. * - Set the optimal transfer size in WPD_PROPERTY_OBJECT_RESOURCES_OPTIMAL_TRANSFER_BUFFER_SIZE * */ HRESULT WpdObjectResources::OnOpenResource( _In_ IPortableDeviceValues* pParams, _In_ IPortableDeviceValues* pResults) { HRESULT hr = S_OK; LPWSTR wszObjectID = NULL; PROPERTYKEY Key = WPD_PROPERTY_NULL; DWORD dwMode = STGM_READ; CAtlStringW strStrObjectID; CAtlStringW strResourceContext; ContextMap* pContextMap = NULL; // Get the Object identifier of the object which contains the specified resource hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_RESOURCES_OBJECT_ID, &wszObjectID); if (hr != S_OK) { hr = E_INVALIDARG; CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_OBJECT_ID"); } // Get the resource key if (hr == S_OK) { hr = pParams->GetKeyValue(WPD_PROPERTY_OBJECT_RESOURCES_RESOURCE_KEYS, &Key); CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_RESOURCE_KEYS"); } // Get the access mode if (hr == S_OK) { hr = pParams->GetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_RESOURCES_ACCESS_MODE, &dwMode); CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_ACCESS_MODE"); } // Validate whether the params given to us are correct. In this case, we need to check that the object // supports the resource requested, and can be opened in the requested access mode. if (hr == S_OK) { // In this sample, we only have one object (README_FILE_OBJECT_ID) which supports a // resource (WPD_RESOURCE_DEFAULT) for reading only. // So if any other Object ID or any other resource is specified, it must be invalid. strStrObjectID = wszObjectID; if(strStrObjectID.CompareNoCase(README_FILE_OBJECT_ID) != 0) { hr = E_INVALIDARG; CHECK_HR(hr, "Object [%ws] does not support resources", wszObjectID); } if (hr == S_OK) { if (!IsEqualPropertyKey(Key, WPD_RESOURCE_DEFAULT)) { hr = E_INVALIDARG; CHECK_HR(hr, "Only WPD_RESOURCE_DEFAULT is supported in this sample driver"); } } if (hr == S_OK) { if ((dwMode & STGM_WRITE) != 0) { hr = E_ACCESSDENIED; CHECK_HR(hr, "This resource is not available for write access"); } } } // Get the context map which the driver stored in pParams for convenience if (hr == S_OK) { hr = pParams->GetIUnknownValue(PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP, (IUnknown**)&pContextMap); CHECK_HR(hr, "Failed to get PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP"); } // Create a new resource operation context, initialize it, and add it to the client context map. if (hr == S_OK) { WpdObjectResourceContext* pResourceContext = new WpdObjectResourceContext(); if (pResourceContext != NULL) { // Initialize the resource context with ... pResourceContext->m_strObjectID = wszObjectID; pResourceContext->m_Resource = Key; pResourceContext->m_BytesTransferred = 0; pResourceContext->m_BytesTotal = GetObjectSize(wszObjectID); // Add the resource context to the context map pContextMap->Add(pResourceContext, strResourceContext); // Release the resource context because it has been AddRef'ed during Add() SAFE_RELEASE(pResourceContext); } else { hr = E_OUTOFMEMORY; CHECK_HR(hr, "Failed to allocate resource context"); } } if (hr == S_OK) { hr = pResults->SetStringValue(WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT, strResourceContext); CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT"); } // Set the optimal buffer size if (hr == S_OK) { hr = pResults->SetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_RESOURCES_OPTIMAL_TRANSFER_BUFFER_SIZE, FILE_OPTIMAL_READ_BUFFER_SIZE_VALUE); CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_RESOURCES_OPTIMAL_TRANSFER_BUFFER_SIZE value"); } // Free the memory. CoTaskMemFree ignores NULLs so no need to check. CoTaskMemFree(wszObjectID); SAFE_RELEASE(pContextMap); return hr; }
virtual void OnContextDestroy(Context* context) { contexts.erase(context->GetName()); }