I want to get and set visible columns in the Details View. I have a shell extension (implemented with a 3rd party library), and I add a menu item to the context menu when the user right-clicks on the folder background. By adding IObjectWithSite to my extension, I've been able to get the interface to IColumnManager.
There is no declaration for IColumnManager on www.pinvoke.net, and the only example of calling it that I have found in .NET is in a defunct branch of BExplorer. Based on that, I got GetColumnCount() working.
let mutable colCount = 0u;
columnManager.GetColumnCount (CM_ENUM_FLAGS.CM_ENUM_VISIBLE, &colCount)
(I'm working in F#. But for now I'm using C# to declare the interfaces and structures).
It looks like my next step is to get a PROPERTYKEY array by calling GetColumns(). This is defined as
HRESULT ( STDMETHODCALLTYPE *GetColumns )(
__RPC__in IColumnManager * This,
/* [in] */ CM_ENUM_FLAGS dwFlags,
/* [size_is][out] */ __RPC__out_ecount_full(cColumns) PROPERTYKEY *rgkeyOrder,
/* [in] */ UINT cColumns);
And here is an example doing it from C++, taken from http://blogs3805.rssing.com/chan-16291381/all_p568.html:
PROPERTYKEY *columns = new PROPERTYKEY[nColumns];
hr = pColumnManager->GetColumns(CM_ENUM_VISIBLE,
columns,
nColumns);
BExplorer has this for GetColumns:
void GetColumns(CM_ENUM_FLAGS dwFlags, [Out] [MarshalAs(UnmanagedType.LPArray)] PropertyKey[] rgkeyOrder, uint cColumns);
But it seems to me that SizeParamIndex would be needed here, since I'm marshaling an array. So I've also tried
void GetColumns([In] CM_ENUM_FLAGS dwFlags, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] PROPERTYKEY[] columns, [In] uint colCount);
Neither one works. When I do this
let columns = Array.init (int colCount) (fun i -> PROPERTYKEY())
columnManager.GetColumns (CM_ENUM_FLAGS.CM_ENUM_VISIBLE, columns, colCount)
I get a System.AccessViolationException with HResult=0x80004003.
My problem was that while fidgeting with the C# interface declaration for IColumnManager, I had changed the order of two functions. The order of functions has to match the order that will be found in the vtable at runtime.
Related
How can a Guid be associated with a Runtime Class to be used in the function call winrt::create_instance, so a winrt Runtime Class can be late bound? I don't see how in MIDL 3.0--though Interfaces work with uuid and version. Is this the answer to late binding in WinRT?
I still don't know how to use winrt::create_instance, but I took a really deep look into base.h. I found plenty of guts to late bind to a WinRT component dll using def calls and interop. This is my solution to the problem. It works. Choosing the right way to hold IUnknown was important, and there was some specifics I'm still working out; like why I have to wrap the IUnknown in a winrt::impl::abi_t<> (WinRT/COM conversion?). Using the following code you simply load the dll by file name (with qualified path if not in in the executable directory), and call the class according to it's runtime namespace.classname. It is absolutely not necessary to add the activatableclass to the Packackage.appxmanifest or to reference the winmd. A search shows a lot of people looking for this, but there is a general reluctance to point this out. It's just like COM really, with its own quirks.
UINT32 ret = 0;
void* dllHandle = WINRT_IMPL_LoadLibraryW(L"Project.dll");
if (!dllHandle) { throw; };
void* pProc = WINRT_IMPL_GetProcAddress(dllHandle, "DllGetActivationFactory");
auto DllGetActivationFactory = reinterpret_cast<int32_t(__stdcall*)(void* classId, void** factory)>(pProc);
static const WCHAR* cname = L"namespace.classname";
const UINT32 cnamelen = wcslen(cname);
HSTRING hcname = NULL;
HSTRING_HEADER header;
HRESULT hr = WindowsCreateStringReference(cname, cnamelen, &header, &hcname);
com_ptr< winrt::impl::abi_t<winrt::Windows::Foundation::IActivationFactory> > oCOMActivationFactory{ nullptr };
ret = (*DllGetActivationFactory)(&header, oCOMActivationFactory.put_void());
com_ptr< winrt::impl::abi_t<winrt::Windows::Foundation::IUnknown> > iObj{ nullptr };
ret = oCOMActivationFactory.get()->ActivateInstance(iObj.put_void());
winrt::com_ptr<ProxyServer::ImplementationInterface> iImplementationInterface{ nullptr };
winrt::copy_from_abi(iImplementationInterface, iObj.as<ProxyServer::ImplementationInterface>());
iImplementationInterface.get()->MyFunction();
oCOMActivationFactory.detach();
WindowsDeleteString(hcname);
I'm looking for a way of checking whether a std::function pointer is bound to a member function of a particular object. I'm aware that std::function itself has no '==' operator. I have however come across the std::function::target method which should be able, in principle, to give me the address of the function to which the pointer is pointing. My starting point was therefore this:
bool MyClass::isThePointerSetToMyMethod(std::function<void (const char*, string)> const& candidate)
{
// Create a pointer to the local reportFileError function using the same syntax that we did in the constructor:
std::function<void (const char *, string)> localFn = std::bind(&MyClass::theLocalMember, this,
std::placeholders::_1, std::placeholders::_2);
// Find the target
auto ptr1 = localFn.target< std::function<void (const char *, string)> >();
// Find the target of the candidate
auto ptr2 = candidate.target< std::function<void (const char *, string)> >();
// Compare the two pointers to see whether they actually point to the same function:
if (!ptr1 || !ptr2) return false;
if (*ptr1 == *ptr2)
return true;
else
return false;
}
This doesn't work, and the reason is that the values of 'ptr1' and 'ptr2' are always returned as null. According to the documentation for the std::function::target method, this must be because the type that I've specified for the target is not correct.
If I look at what target_type(localFn) actually is (using Visual C++ 2013), it's a bit frightening:
class std::_Bind<1,void,struct std::_Pmf_wrap<void (__thiscall MyClass::*)(char const *, string),void,class MyClass,char const *,string>,class MyClass * const,class std::_Ph<1> &,class std::_Ph<2> &>
Nevertheless, target_type(candidate) gives the same result, so I thought I'd try a typedef:
bool MyClass::isThePointerSetToMyMethod(std::function<void (const char*, string)> const& candidate)
{
typedef class std::_Bind<1,void,struct std::_Pmf_wrap<void (__thiscall MyClass::*)(char const *, string),void,class MyClass,char const *,string>,class MyClass * const,class std::_Ph<1> &,class std::_Ph<2> &> wally;
// Create a pointer to the local reportFileError function using the same syntax that we did in the constructor:
std::function<void (const char *, string)> localFn = std::bind(&MyClass::theLocalMember, this,
std::placeholders::_1, std::placeholders::_2);
// Find the target
auto ptr1 = localFn.target< wally >();
// Find the target of the candidate
auto ptr2 = candidate.target< wally >();
// Compare the two pointers to see whether they actually point to the same function:
if (!ptr1 || !ptr2) return false;
if (*ptr1 == *ptr2)
return true;
else
return false;
}
Alas this gets me no further; the values of ptr1 and ptr2 are still null.
So for now I've run out of ideas. Is there anyone reading this who knows either:
(1) The appropriate form for a typedef for a std::function pointer to the member function of a class, or
(2) A better way to achieve my ultimate objective, which is to tell whether a std::function pointer is pointing to a particular object's member function or whether it isn't?
[Background, in case anyone is interested: the reason I'm doing this is that I have a callback table where different callbacks are set to different functions depending on the state that the system is in; this makes state control very simple, as it means that in a given context I can call a given callback and know that the actions taken by the function I've called will be appropriate for the current state, without having to know anything about what that state actually is. Usually, when an object is instantiated which will change the system state, it takes control of the relevant callback(s) and binds them to whatever local member functions are appropriate for whatever state it's in. Under these circumstances, however, the object's destructor ought to return the callbacks to their status quo ante so that they are not left pointing to nothing.
Very rarely, an object may bind the callbacks to its member functions in its constructor, but before its destructor is called another object may take control of the same callbacks itself, and re-bind them to member functions of its own. If this happens, then the first object's destructor needs to be able to recognise that this has happened, and exit without affecting the callbacks' assignment to the second object's methods. The obvious way to do this is for the destructor to be able to check whether the callbacks are still assigned to its own methods or not, and if they are not then to leave well alone.]
Flesh out the callback table into a class which manages the table. All modifications to the table should be done through this class's interface. Internally, you would maintain a stack-like structure which lets you undo the changes done to the callback table. Barebones interface would look something like:
class CallbackTable
{
public:
bool ApplyChanges(...)
{
//Push the old values of the entries that would be changed here into your change-tracker stack and modify the table
}
bool UnApplyChanges(...)
{
//Pop the change-tracker stack and restore the table to the state it was in before the most recent change was applied.
}
};
My example:
PowerPoint start Excel when insert embedded workbook.
I continue to work with PowerPoint. Excel stays as hidden process.
When I close PowerPoint it says to Excel to close itself (Excel closed later then PowerPoint).
When I kill PowerPoint, Excel becomes zombie.
My add-in is loaded into Excel process.
What message(I read that COM STA objects communicate through windows messaging) I should intercept to be notified about such event? What hook should I use? Is there any mean to be notified about count of reference to COM object changes?
UPDATE
My question seems was ambiguous. I am not trying to handle case when I kill PowerPoint. It just for evidence that PowerPoint send some message to Excel when closed normally. I am trying to intercept this message for a good reason.
UPDATE2
I cannot use API - because API fails. I am trying to solve Creating class in new thread in new app domain and providing it with Office COM object in embedded mode leads to zombie process
In case if you kill 'PowerPoint' there will be no reference count changes in Excel. That is why it is not being unloaded.
I believe you may simply post WM_QUIT message to the main window of the Excel process. You may find it using "Spy++.exe" which is a tool bundled with Visual Studio. Also, it is possible, that you may acquire a class factory for some object in Excel and invoke the 'LockServer' method with fLock = FALSE. This will decrease the reference count of Excel server.
But take this as a hack, since an add-in should not influence the behavior of the host application.
None. COM on a local server does use windows messages but it uses private messages which are an implementation detail. All it really does is post messages to a hidden window meaning "you have new COM events in your apartment". The hidden window passes this to the COM library which uses (I believe) shared memory to communicate with other processes, and does the rest of the work such as finding out what the event is (call, call return etc).
In other words, there is no specific message to say "excel go away", and even if there was you couldn't rely on it becaues it is an implementation detail which can change.
When you close the PowerPoint document containing the embedded spreadsheet, PowerPoint will call IUnknown::Release() on all the objects it holds. Excel keeps an internal track of outstanding objects, and will close itself when they all go away.
If you have an add-in in the excel process, and want to know when excel closes, use the addin api to find out.
Depending on the type of Add-In there are different APIs for this. The COM add-ins have events you can register for. But that is a different question: "how can my Excel add-in get notification that an invisible Excel instance is closing".
Added Solution to actual problem/question not asked
#asd.and.Rizzo, this is occurring because you hare holding on to the objects created by Excel. This means that Excel thinks it cannot exit because someone is using the objects. Excel is correct because that somone is your add-in.
This sort of lifetime issue is typical when creating any Office or Excel add-in and is not unique to .Net add-ins.
You are wanting to solve the problem by cheating Excel's reference count. But it is in your hands: The reference count is only up because you are holding objects! If you release them the count will go down to zero with no cheating.
Solution
The best solution is to avoid sinking events and avoid holding on to any object. Depending on what your add-in is doing this may not be possible.
If you cannot, you must sink the document close events. In each, check how many documents are open. When the count reaches zero you should remove your event handlers, call Marshall.ReleaseComObject on every object you have ever held, and unload your add-in. Excel will then exit.
But please note: You must call Marshall.ReleaseComObject on every object you ever hold. If you don't, Excel will never exit. This should occur if you unload the AppDomain.
I found next (from interpreting COM interfaces as pure C structs + function and Direct X hacks). Works but does not fix problem for some reason. My be should do the same for Workbooks, Worksheets...
Declare:
typedef HRESULT STDMETHODCALLTYPE QueryInterfacePtr( REFIID, void **);
typedef ULONG STDMETHODCALLTYPE AddRefPtr( );
typedef ULONG STDMETHODCALLTYPE ReleasePtr( );
typedef ULONG STDMETHODCALLTYPE GetTypeInfoCountPtr( UINT *) ;
typedef ULONG STDMETHODCALLTYPE GetTypeInfoPtr ( UINT, LCID, ITypeInfo **) ;
typedef ULONG STDMETHODCALLTYPE GetIDsOfNamesPtr ( REFIID, LPOLESTR *,
UINT, LCID, DISPID *) ;
typedef ULONG STDMETHODCALLTYPE InvokePtr ( DISPID, REFIID,
LCID, WORD, DISPPARAMS *,
VARIANT *, EXCEPINFO *, UINT *) ;
typedef struct {
// IUnknown functions
QueryInterfacePtr * QueryInterface;
AddRefPtr * AddRef;
ReleasePtr * Release;
// IDispatch functions
GetTypeInfoCountPtr* GetTypeInfoCount;
GetTypeInfoPtr* GetTypeInfo;
GetIDsOfNamesPtr* GetIDsOfNames;
InvokePtr* Invoke;
} IDispatchInterceptor;
typedef ULONG __stdcall releasePTR(IDispatch *self);
typedef ULONG __stdcall addrefPTR(IDispatch *self);
Next I have done for Excel:
static IDispatch * application = NULL;
static releasePTR* realRelease = NULL;
static addrefPTR* realAddRef = NULL;
static ULONG wasAdd = 0;
static ULONG oldCount = 0;
HRESULT STDMETHODCALLTYPE QueryInterfaceNativeOutOfProcSrv(REFIID riid, void **ppv){
return application->QueryInterface(riid,ppv);
}
ULONG STDMETHODCALLTYPE AddRefNativeOutOfProcSrv(){
return application->AddRef();
}
ULONG STDMETHODCALLTYPE ReleaseNativeOutOfProcSrv(){
return application->Release();
}
ULONG STDMETHODCALLTYPE GetTypeInfoCountSrv( UINT * count) {
return application->GetTypeInfoCount(count);
}
ULONG STDMETHODCALLTYPE GetTypeInfoSrv ( UINT n, LCID id, ITypeInfo ** inf) {
return application->GetTypeInfo(n,id,inf);
}
ULONG STDMETHODCALLTYPE GetIDsOfNamesSrv ( REFIID a, LPOLESTR * b, UINT c, LCID d, DISPID * e) {
return application->GetIDsOfNames(a,b,c,d,e);
}
ULONG STDMETHODCALLTYPE InvokeSrv ( DISPID a, REFIID b, LCID c, WORD d, DISPPARAMS * e, VARIANT * i, EXCEPINFO * j, UINT *k) {
return application->Invoke(a,b,c,d,e,i,j,k);
}
static IDispatchInterceptor interceptor =
{QueryInterfaceNativeOutOfProcSrv,AddRefNativeOutOfProcSrv,ReleaseNativeOutOfProcSrv,
GetTypeInfoCountSrv,GetTypeInfoSrv,GetIDsOfNamesSrv,InvokeSrv
};
ULONG __stdcall release(IDispatch *self)
{
ULONG c = realRelease(self);
Log->logWrite("release %d",c);
if ( c == 1)
{
if (instance != NULL)
{
instance->OnBeginShutdown(NULL);
Log->logWrite("OnBeginShutdown %d",c);
instance->OnEmbeddedDisconnection();
Log->logWrite("OnEmbeddedDisconnection %d",c);
instance = NULL;
}
}
//if (c == 2) {
// c = realRelease(self);
// c = realRelease(self);
//}
return c;
}
ULONG __stdcall addref(IDispatch *self)
{
ULONG c = oldCount;
if (wasAdd == 0)
{
c = realAddRef(self);
oldCount = c;
wasAdd++;
}
else if (wasAdd == 1)
{
Log->logWrite("ADDREF FAKE %d",c);
wasAdd++;
}
else if (wasAdd == 2)
{
Log->logWrite("ADDREF FAKE %d",c);
wasAdd++;
}
else
{
c = realAddRef(self);
}
Log->logWrite("ADDREF %d",c);
return c;
}
void InterceptRelease( IDispatch obj){
void iunknown_vtable= (void*)((unsigned int)obj);
void* idispatch_vtable = (void*)(((unsigned int)iunknown_vtable)+8);
unsigned int* v1 = (unsigned int*)idispatch_vtable;
realRelease = (releasePTR*)*v1;
DWORD old;
VirtualProtect(v1,4,PAGE_EXECUTE_READWRITE,&old);
*v1 = (unsigned int) release;
//while(obj->Release() > 0){};
}
void InterceptAddRef( IDispatch obj){
void iunknown_vtable= (void*)((unsigned int)obj);
void* idispatch_vtable = (void*)(((unsigned int)iunknown_vtable)+4);
unsigned int* v1 = (unsigned int*)idispatch_vtable;
realAddRef = (addrefPTR*)*v1;
DWORD old;
VirtualProtect(v1,4,PAGE_EXECUTE_READWRITE,&old);
*v1 = (unsigned int) addref;
}
Apply:
IDispatch * app = Application;
InterceptRelease(app);
InterceptAddRef(app);
I have a good old fashioned win32 dll with functions of the form
void Foo1(int* value)
void Foo2(char* string)
void Foo3(MyType* data)
//ect...
I need to call this in QTP (vbscript) and retreive the data for use in the QTP application. Is this even possible in vbscript?
I have some controll over the DLL. It is written in c++. Building a COM server is not an option. Refactoring the code to include accessor methods with ordinal return types is flat out of the question (would be a maintainance and scabaility nightmare).
Editing to clarify the example...
I have...
void Add(int x, int y, int* result)
...I need to do the QTP equivalent of this...
int myX = 2;
int myY = 5;
int myResult = -1;
Add(myX, myY, &myResult);
//myResult should now be 7
...but in QTP.
Calling int Bar(int x, int y) in QTP is easy.
I need to know if its possible to call into void Foo(int* result)
in this way Foo(&myResult) and pass in a reference to result.
You can declare external functions like Win32 API but there are some limitations, I believe the function should have extern "C" linkage and not all types are supported. Here's an example of how to use the Win32 GetParent function from QTP, you may be able to extrapolate how to match your own function.
' Declare
Extern.Declare micHwnd, "GetParent", "user32.dll", "GetParent", micHwnd
' explanation: retVal name sourceDll name parameter
' Usage
hwnd = Extern.GetParent(Browser(“xxx”).GetROProperty("hwnd"))
The reason the name appears twice is so you can rename it for your script (I don't remember which is the name to look for and which is the name that you will use).
The answer is to pass by reference.
In the .h file declare the function:
extern "C" __declspec(dllexport) int HelloWorld(int &);
In the .cpp file define the function:
int HelloWorld(int& i)
{
i = 10;
return 55 + i;
}
QTP code:
Extern.Declare micInteger, "HelloWorld", "C:\test.dll", "HelloWorld", micInteger+micByRef
myNumber = 5
Extern.HelloWorld(myNumber)
MsgBox(myNumber)
Good day, folks!
I have a structure with 100+ parameters needed by my kernel. I create a buffer object for the data, do the write, and set a pointer to that data as a kernel argument. (The kernel arg is __global, but I've tried other types for it.)
So far so good! I can see the structure's elements from my kernel function just fine!
However, I want a dozen helper functions to have access to these parameters. I have tried, but I haven't found a way to do this. If I try to copy the (__global) vh into another global pointer, or a __local pointer, or a __private pointer, it fails. If I try to copy the structure data itself into a __global, or __local, or __private copy of the structure, it fails. I've tried byte-wise copies, I've tried async_work_group_copy, I've tried casts, I tried passing the whole __global pointer in to the helper functions, I've tried other types for the kernel arg itself, I've tried everything I can think of. It seems that it might not be possible to get this data to these helper functions, but it must be possible, right?
Any answer will be welcome, even if it's "that can't be done", or "you're an idiot". I've asked this question on another forum and had nobody has said even that much, though perhaps I didn't word my question properly. But ... I can't be the only person in the world with helper functions in their kernel code, right? How the heck do you get data to them that was passed in to the kernel function?
Thanks folks....
David
Thanks....
Here is an example which demonstrates the functionality you want, hope it helps!
Structure definitions:
typedef struct agent {
uint energy;
uint action;
uint type;
uint next;
} AGENT __attribute__ ((aligned (16)));
typedef struct sim_params {
uint size_x;
uint size_y;
uint size_xy;
uint max_agents;
uint null_agent_pointer;
uint grass_restart;
uint lines_per_thread;
} SIM_PARAMS;
typedef struct cell {
uint grass;
uint agent_pointer;
} CELL;
Helper function:
/*
* Helper function
*/
void removeAgentFromCell(__global AGENT * agents,
__global CELL * matrix,
uint cellIndex,
uint agentIndex,
uint previousAgentIndex,
SIM_PARAMS sim_params)
{
...
}
Main kernel:
/*
* The kernel
*/
__kernel void step1(__global AGENT * agents,
__global CELL * matrix,
__global ulong * seeds,
const uint turn,
const SIM_PARAMS sim_params)
{
uint index;
uint agentIndex;
uint previousAgentIndex;
...
// Call helper function
removeAgentFromCell(agents, matrix, index, agentIndex, previousAgentIndex, sim_params);
...
}
Tried and tested and working in AMD APP SDK (on both CPU and GPU) and Nvidia CUDA Toolkit. So I guess it will work in OSX.