Check if a given path is a special folder path? - windows

On Windows, one can get any special folder path using SHGetKnownFolderPath or SHGetSpecialFolder (If I remember correctly this last one). However, I want the reverse, I have a path and want to know which special folder it belongs to, if any. I prefer this approach, because to find out if a given path's is in a particular special folder or not, I'll have to enumerate all special folders for all users which is a bit of ugly, but if there's no other way, the sky is the limit :)
I searched it but couldn't find anything useful. So does WinApi has a function to do just that?
Thanks.

You can use IKnownFolderManager::FindFolderFromPath
Available since Vista.
PS: check out the CComPtr<> class for simpler interfacing with COM.
Here is a sample i just made up, showing how to use it:
#include <atlsafe.h>
#include <Shobjidl.h>
#include <comdef.h>
void PrintKnownFolder( const CComPtr<IKnownFolder>& folder )
{
KNOWNFOLDER_DEFINITION def;
HRESULT hr = folder->GetFolderDefinition( &def );
if( SUCCEEDED(hr) ) {
std::wcout << L"Result: " << def.pszName << std::endl;
FreeKnownFolderDefinitionFields( &def );
} else {
_com_error err(hr);
std::wcout << L"Error while querying GetFolderDefinition: " << err.ErrorMessage() << std::endl;
}
}
class CCoInitialize
{
public:
CCoInitialize() : m_hr(CoInitialize(NULL)) { }
~CCoInitialize() { if (SUCCEEDED(m_hr)) CoUninitialize(); }
operator HRESULT() const { return m_hr; }
private:
HRESULT m_hr;
};
bool test()
{
CCoInitialize co;
CComPtr<IKnownFolderManager> knownFolderManager;
HRESULT hr = knownFolderManager.CoCreateInstance( CLSID_KnownFolderManager );
if( !SUCCEEDED(hr) ) {
_com_error err(hr);
std::wcout << L"Error while creating KnownFolderManager: " << err.ErrorMessage() << std::endl;
return false;
}
CComPtr<IKnownFolder> folder;
hr = knownFolderManager->FindFolderFromPath( L"C:\\Users\\All Users\\Microsoft", FFFP_NEARESTPARENTMATCH, &folder );
if( SUCCEEDED(hr) ) {
PrintKnownFolder(folder);
} else {
_com_error err(hr);
std::wcout << L"Error while querying KnownFolderManager for nearest match: " << err.ErrorMessage() << std::endl;
}
// dispose it.
folder.Attach( NULL );
hr = knownFolderManager->FindFolderFromPath( L"C:\\Users\\All Users\\Microsoft", FFFP_EXACTMATCH, &folder );
if( SUCCEEDED(hr) ) {
PrintKnownFolder(folder);
} else {
_com_error err(hr);
std::wcout << L"Error while querying KnownFolderManager for exact match: " << err.ErrorMessage() << std::endl;
}
return true;
}
CCoInitialize borrowed from The Old New Thing

Related

vulkan unable to find validation layers

I'm following a vulkan tutorial and when i'm trying to check for validation layer support.
the function always returns false when it is supposed to return true.
this is the code:
bool app::checkValidationLayersSupport() {
uint32_t layersCount = 0;
vkEnumerateInstanceLayerProperties(&layersCount, nullptr);
std::vector<VkLayerProperties> availableLayers(layersCount);
vkEnumerateInstanceLayerProperties(&layersCount, availableLayers.data());
std::cout << layersCount << "\n";
for (const char* layerName : validationLayers) {
std::cout << layerName << "\n";
for (const auto& layerProperties : availableLayers) {
if (strcmp(layerName, layerProperties.layerName) == 0) {
std::cout << layerProperties.layerName << std::endl;
return true;
}
}
}
return false;}
validationLayers value is { "VK_LAYER_KHRONOS_validation" } (std::vector<const char*>)
after vkEnumerateInstanceLayerProperties LayersCount value is 5 so i think the problem is that the second vkEnumerateInstanceLayerProperties can't change the value of availableLayers so it remains empty
edit:
I checked it and the second vkEnumerateInstanceLayerProperties is initializing the vector but the needed validation layer is not in it.
fix: i reinstalled the sdk

how to implement onvif CreatePullPointSubscription operation by gsoap

Referring to onvif core specification: If the subscription is accepted, the response contains a WS-EndpointReference to the
instantiated pull point. This WS-Endpoint provides a PullMessages operation, which is
used by the client to retrieve Notifications.
But I can't see the codes about instancing pull point, and I don't know how to implement it. Here is my coding.
SOAP_FMAC5 int SOAP_FMAC6 __tev__CreatePullPointSubscription(struct soap* soap, struct _tev__CreatePullPointSubscription *tev__CreatePullPointSubscription, struct _tev__CreatePullPointSubscriptionResponse *tev__CreatePullPointSubscriptionResponse)
{
tev__CreatePullPointSubscriptionResponse->SubscriptionReference.Address = (char *)soap_malloc(soap, sizeof(char) * 128);
strcpy(tev__CreatePullPointSubscriptionResponse->SubscriptionReference.Address, "http://192.168.12.1/Subscription?Idx=0");
tev__CreatePullPointSubscriptionResponse->wsnt__CurrentTime=time(NULL);
tev__CreatePullPointSubscriptionResponse->wsnt__TerminationTime=tev__CreatePullPointSubscriptionResponse->wsnt__CurrentTime+60;
return SOAP_OK;
}
Can anyone brighten me? Thank you in advance.
void CreatePullPointSubscription() {
struct soap *m_soap = soap_new();
m_soap->connect_timeout = SOAP_REQUEST_TIMEOUT_IN_SECONDS;
m_soap->recv_timeout = SOAP_REQUEST_TIMEOUT_IN_SECONDS;
m_soap->send_timeout = SOAP_REQUEST_TIMEOUT_IN_SECONDS;
PullPointSubscriptionBindingProxy subscriptionProxy(m_soap);
subscriptionProxy.soap_endpoint = xAddr;
if (addCredentialsToCall(m_soap)) {
_tev__CreatePullPointSubscription request;
_tev__CreatePullPointSubscriptionResponse response;
auto ret = subscriptionProxy.CreatePullPointSubscription(&request, response);
if (ret != SOAP_OK) {
soap_stream_fault(m_soap, std::cerr);
} else {
auto address = response.SubscriptionReference.Address;
std::cout << address << std::endl;
std::cout << "Subscription metadata: " << response.SubscriptionReference.Metadata << std::endl;
std::cout << "Termination time " << response.wsnt__TerminationTime << std::endl;
std::cout << "Current time " << response.wsnt__CurrentTime << std::endl;
std::string uuid = std::string(soap_rand_uuid(m_soap, "urn:uuid:"));
struct SOAP_ENV__Header header;
header.wsa5__MessageID = (char *) uuid.c_str();
header.wsa5__To = response.SubscriptionReference.Address;
m_soap->header = &header;
if (addCredentialsToCall(m_soap)) {
_tev__PullMessages tev__PullMessages;
tev__PullMessages.Timeout = "PT600S";
tev__PullMessages.MessageLimit = 100;
_tev__PullMessagesResponse tev__PullMessagesResponse;
auto ret = subscriptionProxy.PullMessages(&tev__PullMessages, tev__PullMessagesResponse);
for (auto msg : tev__PullMessagesResponse.wsnt__NotificationMessage) {
std::cout << "\tMessage is :" << msg->Topic->__mixed << std::endl;
}
} else {
std::cout << "Couldn't set credentials!!!" << std::endl;
}
}
}
subscriptionProxy.destroy();
}
This worked for me atleast to pull the event initializers.

How to take advantage of the Move Semantics for a better performance in C++11?

After many trials I still do not understand how to properly take advantage of the move semantics in order to not copy the result of the operation and just use the pointer, or std::move, to "exchange" the data pointed to. This will be very usefull to speed-up more complicated functions like f(g(),h(i(l,m),n(),p(q()))
The objective is to have:
t3={2,4,6};
t1={}; // empty
While executing the code below the output is:
t3={2,4,6};
t1={1,2,3};
Code:
namespace MTensor {
typedef std::vector<double> Tensor1DType;
class Tensor1D {
private:
//std::shared_ptr<Tensor1DType> data = std::make_shared<Tensor1DType>();
Tensor1DType * data = new Tensor1DType;
public:
Tensor1D() {
};
Tensor1D(const Tensor1D& other) {
for(int i=0;i<other.data->size();i++) {
data->push_back(other.data->at(i));
}
}
Tensor1D(Tensor1D&& other) : data(std::move(other.data)) {
other.data = nullptr;
}
~Tensor1D() {
delete data;
};
int size() {
return data->size();
};
void insert(double value) {
data->push_back(value);
}
void insert(const std::initializer_list<double>& valuesList) {
for(auto value : valuesList) {
data->push_back(value);
}
}
double operator() (int i) {
if(i>data->size()) {
std::cout << "index must be within vector dimension" << std::endl;
exit(1);
}
return data->at(i);
}
Tensor1D& operator=(Tensor1D&& other) {
if (this == &other){
return *this;
}
data = other.data;
other.data = nullptr;
return *this;
}
void printTensor(Tensor1DType info) {
for(int i=0;i<info.size();i++) {
std::cout << info.at(i) << "," << std::endl;
}
}
void printTensor() {
for(int i=0;i<data->size();i++) {
std::cout << data->at(i) << "," << std::endl;
}
}
};
} // end of namespace MTensor
In file main.cpp:
MTensor::Tensor1D scalarProduct1D(MTensor::Tensor1D t1, double scalar) {
MTensor::Tensor1D tensor;
for(int i=0;i<t1.size();++i) {
tensor.insert(t1(i) * scalar);
}
//return std::move(tensor);
return tensor;
}
int main() {
MTensor::Tensor1D t1;
t1.insert({1,2,3});
std::cout << "t1:" << std::endl;
t1.printTensor();
MTensor::Tensor1D t3(scalarProduct1D(t1,2));
std::cout << "t3:" << std::endl;
t3.printTensor();
std::cout << "t1:" << std::endl;
t1.printTensor();
return 0;
}
Your use of new is a red flag, especially on a std::vector.
std::vectors support move semantics natively. They are a memory management class. Manual memory management of a memory management class is a BIG red flag.
Follow the rule of 0. =default your move constructor, move assignment, copy constructor, destructor and copy assignment. Remove the * from the vector. Don't allocate it. Replace data-> with data.
The second thing you should do is change:
MTensor::Tensor1D scalarProduct1D(MTensor::Tensor1D t1, double scalar) {
As it stands you take the first argument by value. That is great.
But once you take it by value, you should reuse it! Return t1 instead of creating a new temporary and returning it.
For that to be efficient, you will want to have a way to modify a tensor in-place.
void set(int i, double v) {
if(i>data->size()) {
std::cout << "index must be within vector dimension" << std::endl;
exit(1);
}
data.at(i) = v;
}
which gives us:
MTensor::Tensor1D scalarProduct1D(MTensor::Tensor1D t1, double scalar) {
for(int i=0;i<t1.size();++i) {
ts.set(i, t1(i) * scalar);
}
return t1; // implicitly moved
}
We are now getting close.
The final thing you have to do is this:
MTensor::Tensor1D t3(scalarProduct1D(std::move(t1),2));
to move the t1 into the scalarProduct1D.
A final problem with your code is that you use at and you check bounds. at's purpose is to check bounds. If you use at, don't check bounds (do so with a try/catch). If you check bounds, use [].
End result:
typedef std::vector<double> Tensor1DType;
class Tensor1D {
private:
//std::shared_ptr<Tensor1DType> data = std::make_shared<Tensor1DType>();
Tensor1DType data;
public:
Tensor1D() {};
Tensor1D(const Tensor1D& other)=default;
Tensor1D(Tensor1D&& other)=default;
~Tensor1D()=default;
Tensor1D& operator=(Tensor1D&& other)=default;
Tensor1D& operator=(Tensor1D const& other)=default;
Tensor1D(const std::initializer_list<double>& valuesList) {
insert(valuesList);
}
int size() const {
return data.size();
};
void insert(double value) {
data.push_back(value);
}
void insert(const std::initializer_list<double>& valuesList) {
data.insert( data.end(), valuesList.begin(), valuesList.end() );
}
double operator() (int i) const {
if(i>data.size()) {
std::cout << "index must be within vector dimension" << std::endl;
exit(1);
}
return data[i];
}
void set(int i, double v) {
if(i>data->size()) {
std::cout << "index must be within vector dimension" << std::endl;
exit(1);
}
data.at(i) = v;
}
static void printTensor(Tensor1DType const& info) {
for(double e : info) {
std::cout << e << "," << std::endl;
}
}
void printTensor() const {
printTensor(data);
}
};
MTensor::Tensor1D scalarProduct1D(MTensor::Tensor1D t1, double scalar) {
for(int i=0;i<t1.size();++i) {
t1.set(i, t1(i) * scalar);
}
return t1;
}
int main() {
MTensor::Tensor1D t1 = {1,2,3};
std::cout << "t1:" << std::endl;
t1.printTensor();
MTensor::Tensor1D t3(scalarProduct1D(std::move(t1),2));
std::cout << "t3:" << std::endl;
t3.printTensor();
std::cout << "t1:" << std::endl;
t1.printTensor();
return 0;
}
with a few other minor fixes (like using range-for, DRY, etc).
You need to move t1 when calling scalarProduct1D, otherwise you'll make a copy:
MTensor::Tensor1D t3(scalarProduct1D(std::move(t1),2));
You need to explicitly use std::move because t1 is an lvalue expression.
Note that you'll have to fix your printing functions to avoid dereferencing nullptr if you want accessing the moved-from object to be a valid operation. I instead suggest to avoid making method invocation on moved-from objects valid as it requires additional checks and doesn't follow the idea of "this object has been moved, now it's in an invalid state".
live wandbox example

C++ Move constructor for class containing vector

I have written a move constructor for a class in the following way:
class A
{
std::vector<double> m;
A(A&& other)
: m{other.m}
{
}
}
Is this the correct way to move other.m to m?
Should I be doing this instead?
A(A&& other)
: m{std::move(other.m)}
{
}
Or perhaps I should be doing something else entirely?
The second snippet is the correct way to move other.m since it's a lvalue that needs to be turned into r-value-reference for std::vector move constructor to kick in.
even though, in this very specific example, it will be enough to simply write
A(A&& rhs) = default;
the compiler will generate a constructor that moves each member of rhs to the corresponing member of *this.
p.s. you also probably meant to make the constructor public.
/******************************************************************************
Below program demonstrates how to use move constructor and move assignment operator
*******************************************************************************/
#include <iostream>
#include <algorithm>
#include <vector>
class MemoryBlock
{
public:
MemoryBlock()
{
this->id++;
std::cout << "Default Constructor"<<std::endl;
}
// Simple constructor that initializes the resource.
explicit MemoryBlock(size_t length)
: _length(length)
, _data(new int[length])
{
this->id++;
std::cout << "Constructor In MemoryBlock(size_t). length = and id ="
<< _length << "." <<id<< std::endl;
}
// Destructor.
~MemoryBlock()
{
this->id--;
std::cout << "Destructor In ~MemoryBlock(). length = and id ="
<< _length << "."<<id;
if (_data != nullptr)
{
std::cout << " Deleting resource.";
// Delete the resource.
delete[] _data;
}
std::cout << std::endl;
}
// Copy constructor.
MemoryBlock(const MemoryBlock& other)
: _length(other._length)
, _data(new int[other._length])
{
this->id++;
std::cout << " Copy Constructor MemoryBlock(const MemoryBlock&). length = and id ="
<< other._length << "." <<id<<"Copying resource." << std::endl;
std::copy(other._data, other._data + _length, _data);
}
// Copy assignment operator.
MemoryBlock& operator=(const MemoryBlock& other)
{
std::cout << "Assignment operator In operator=(const MemoryBlock&). length = "
<< other._length << ". Copying resource." << std::endl;
if (this != &other)
{
// Free the existing resource.
delete[] _data;
_length = other._length;
_data = new int[_length];
std::copy(other._data, other._data + _length, _data);
}
return *this;
}
// Retrieves the length of the data resource.
size_t Length() const
{
return _length;
}
//Move copy constructor
MemoryBlock(MemoryBlock&& other) noexcept
: _data(nullptr)
, _length(0)
{
std::cout << "Move Constructor In MemoryBlock(MemoryBlock&&). length = "
<< other._length << ". Moving resource." << std::endl;
// Copy the data pointer and its length from the
// source object.
_data = other._data;
_length = other._length;
// Release the data pointer from the source object so that
// the destructor does not free the memory multiple times.
other._data = nullptr;
other._length = 0;
}
// Move assignment operator.
MemoryBlock& operator=(MemoryBlock&& other) noexcept
{
std::cout << "Move assignment operator In operator=(MemoryBlock&&). length = "
<< other._length << "." << std::endl;
if (this != &other)
{
// Free the existing resource.
delete[] _data;
// Copy the data pointer and its length from the
// source object.
_data = other._data;
_length = other._length;
// Release the data pointer from the source object so that
// the destructor does not free the memory multiple times.
other._data = nullptr;
other._length = 0;
}
return *this;
}
private:
size_t _length; // The length of the resource.
int* _data; // The resource.
static int id;
};
int MemoryBlock::id=0;
int main()
{
std::vector<MemoryBlock> v1;
MemoryBlock m1(100);
MemoryBlock m2(100);
MemoryBlock m3(100);
v1.push_back(m1);
v1.push_back(m2);
v1.push_back(m3);
return 0;
}

Mac OS X : boost interprocess semaphore timed_wait : Abnormal CPU consumption

After porting a code segment from Windows to Mac OS X, I found it to consume a whole CPU core while running; the responsible call for the CPU consumption is boost::interprocess::interprocess_semaphore::timed_wait.
Here follows the code portion which reproduces this behaviour.
#include <boost/interprocess/sync/interprocess_semaphore.hpp>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/thread/thread_time.hpp>
#include <iostream>
static bool gStopRequested(false);
struct ShmObj
{
boost::interprocess::interprocess_semaphore mSemaphore;
ShmObj() : mSemaphore(0) {};
~ShmObj() {};
};
int main(char* argc, const char** argv)
{
boost::interprocess::shared_memory_object* lShmObj = NULL;
std::string lShmObjName("My_Boost_Interprocess_Test");
boost::interprocess::mapped_region* lRegion;
ShmObj* lObj;
//Create shared segment
try
{
lShmObj = new boost::interprocess::shared_memory_object(boost::interprocess::create_only, lShmObjName.c_str(), boost::interprocess::read_write);
}
catch (boost::interprocess::interprocess_exception &ex)
{
if (ex.get_error_code() != boost::interprocess::already_exists_error)
{
std::cerr << "Some error" << std::endl;
exit(1);
}
else
{
std::cerr << "Already exists, just taking it back." << std::endl;
try
{
lShmObj = new boost::interprocess::shared_memory_object(boost::interprocess::open_only, lShmObjName.c_str(), boost::interprocess::read_write);
}
catch (boost::interprocess::interprocess_exception &ex2)
{
std::cerr << "D'oh !" << std::endl;
exit(1);
}
}
}
if (!lShmObj)
{
exit(1);
}
lShmObj->truncate(sizeof(ShmObj));
lRegion = new boost::interprocess::mapped_region(*lShmObj, boost::interprocess::read_write);
lObj = new (lRegion->get_address()) ShmObj;
// The loop
while (!gStopRequested)
{
boost::system_time lDeadlineAbsoluteTime = boost::get_system_time() + boost::posix_time::milliseconds(500);
if (lObj->mSemaphore.timed_wait(lDeadlineAbsoluteTime))
{
std::cout << "acquired !" << std::endl;
}
else
{
std::cout << "tick" << std::endl;
}
}
}
Then, I read that unnamed semaphores were not available under Mac OS X, so I thought it could be because unnamed semaphores were not efficiently emulated... I then tried the following, unsucessfully:
#include <boost/interprocess/sync/named_semaphore.hpp>
#include <boost/thread/thread_time.hpp>
#include <iostream>
static bool gStopRequested(false);
int main(char* argc, const char** argv)
{
boost::interprocess::named_semaphore::remove("My_Boost_Interprocess_Test");
boost::interprocess::named_semaphore lMySemaphore(boost::interprocess::open_or_create, "My_Boost_Interprocess_Test", 1);
// The loop
while (!gStopRequested)
{
boost::system_time lDeadlineAbsoluteTime = boost::get_system_time() + boost::posix_time::milliseconds(500);
if (lMySemaphore.timed_wait(lDeadlineAbsoluteTime))
{
std::cout << "acquired !" << std::endl;
}
else
{
std::cout << "tick" << std::endl;
}
}
}
I was actually expecting a better behaviour of boost::interprocess on Mac OS X because of the available Posix primitives, but it is actually not. Any idea for a resolution? Thanks a lot.
I successfully Used Mach semaphores instead of the ones of boost::interprocess... see http://pkaudio.blogspot.com/2010/05/mac-os-x-no-timed-semaphore-waits.html

Resources