|
thanks Todd,
How does the activeX register itself for IE Events?
are there any security considerations?
Is there any sample example/code provided for the same?
|
|
|
|
|
Hello all,
Just a little historyof my project. I have started to develop COM component. Now, I evolve to DCOM component -> switch from IUnknow to IDispatch and DLL server to NTService server.
I have many interfaces.
And one give me this error and it's the most important.
Here the IDL def in the Library part:
[
object,
uuid(535765EA-C024-423A-B921-9F77416CF47F),
dual,
helpstring("ISearchMidiScore Interface, the search interface and the most important"),
pointer_default(unique)
]
interface ISearchMidiScore : IDispatch
{
[helpstring("SetCompareClass, allow user to change the comparison method")]
HRESULT SetCompareClass(
[in] CompareClassEnum classType);
[helpstring("SetSettings, allow user to change the number of result returned")]
HRESULT SetSettings(
[in] int maxSearchElement,
[in] float maxScore);
[helpstring("SearchFromText, allow user to search a music from a set of midi notes separate by a coma")]
HRESULT SearchFromText(
[in, string] BSTR text,
[out] IEnumScoreResult** ppenum);
[helpstring("SearchFromAudio, allow user to search a music from a PCM or a WAV buffer")]
HRESULT SearchFromAudio(
[in] BYTE* audioBuffer,
[in] ULONG audioLength,
[out] IEnumScoreResult** ppenum);
[helpstring("SearchFromScore, allow user to search from a previous score convertion")]
HRESULT SearchFromScore(
[in, out] IScoreDesc* score,
[out] IEnumScoreResult** ppenum);
};
[
object,
uuid(54901242-0019-4986-9328-7260EAEF7D9C),
dual,
helpstring("IEnumScoreResult Interface, enum the result set construct by previous call to ISearchMidiScore search methods"),
pointer_default(unique)
]
interface IEnumScoreResult : IDispatch
{
typedef [unique] IEnumScoreResult *LPENUMSCORERESULT;
[id(1)]
HRESULT Next(
[in] ULONG celt,
[out, size_is(celt), length_is(*pceltFetched)]
IScoreResult **rgelt,
[out] ULONG *pceltFetched);
[id(2)]
HRESULT Skip(
[in] ULONG celt);
[id(3)]
HRESULT Reset();
[id(4)]
HRESULT Clone(
[out] IEnumScoreResult **ppenum);
};
I call the ISearchMidiScore::SearchFromScore(score, enum), it returns a pointer.
When I call IEnumScoreResult::Next, I got the kernel exception.
I have other function working like this 2 - one is calling and give an enumerator pointer - it always work fine.
Before I switch, they work fine too.
Can't see what it is? Do you have any idea? Do you need more info?
Bruno
|
|
|
|
|
The third variable must not be NULL. Should use a long variable and pass its adress.
This solve the problem....
|
|
|
|
|
Hello All!
I'm implementing a COM object using ATL under BCB5.
The target is a DLL. It is compiled and built OK. Also I have
a client application that calls DllGetClassObject directly
from this DLL (after dynamic linking) and tries to get
supported CLSID & IID pair.
At that moment I've got the error, that interface is not
supported. After debugging deep inside ATL implemetation
code I've discovered that _ATL_INTMAP_ENTRY map of
my object contains only IUnknown. Please could someone
point out the problem.
Here is some excerpt from implemenation header:
=========================================
class ATL_NO_VTABLE TFooIndexerImpl :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<TFooIndexerImpl, &CLSID_FooIndexer>,
public IFooIndexer
{
public:
TFooIndexerImpl()
{
}
// Data used when registering Object
//
DECLARE_THREADING_MODEL(otApartment);
DECLARE_PROGID("Indexer.FooIndexer");
DECLARE_DESCRIPTION("");
...
BEGIN_COM_MAP(TFooIndexerImpl)
COM_INTERFACE_ENTRY(IFooIndexer)
END_COM_MAP()
// IFooIndexer
public:
...
};
===========================================
And in another module an object map is defined:
===========================================
BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_FooIndexer, TFooIndexerImpl)
END_OBJECT_MAP()
===========================================
So, why the call DllGetClassObject(CLSID_FooIndexer,IID_IFooIndexer,...)
fails?
Thanks in advance.
|
|
|
|
|
Why are you calling DllGetClassObject directly? If this is a COM object instantiate it with CoCreate. If you going to call dll functions directly forgo the COM hassles and just make a normal dll and use loadlibrary.
|
|
|
|
|
Calling DllGetClassObject directly is not restricted by any standard, as I know. This approach eliminates the necessity to register a server in the system registry, moreover such a server may be located in arbitrary way implied by software. But this is not the question. Do you mean that ATL does not conform to all generally allowed methods of interactions?
After a little investigation of ATL headers I've found out that my problem arises from the fact, that OBJECT_ENTRY macro uses standard ATL's class factory class, namely CComClassFactory. Then a client asks a server to create an object with some interface, supported by my custom COM object, ATL makes a call to CComClassFactory. The ATL templates are written in such a way, that CComClassFactory does not know anything about my custom interface (it knows only IClassFactory) and returns an error. So, now, the question is, how to bind custom interfaces to standard CComClassFactory?
The other possible decision is to change client application.
I've tried to call DllGetClassObject requesting IID_IClassFactory
first, and then use an aquired pointer to call CreateInstance for
custom interface. This is the standard approach. But it doesn't
work in very strange manner:
the call to DllGetClassObject returns success and
fills provided IClassFactory pointer with _something_ like
an object without IClassFactory methods!
// obtaining &DllGetClassObject for pGetClass
...
if( SUCCEEDED((*pGetClass)(clsid, IID_IClassFactory, &pVoid)))
{
pUnk = ((LPUNKNOWN)pVoid);
pCF = (LPCLASSFACTORY)pUnk; // dummy line
// pCF->AddRef(); // if uncommented, works fine
// pCF->LockServer(TRUE); // memory exception, if uncomment
if( SUCCEEDED(pCF->CreateInstance(NULL, riid, &pVoid))) // memory
exception
{
}
// pCF->LockServer(FALSE);
pCF->Release();
return pVoid;
}
Because I haven't even started to write applied code, the results are from ATL itself. I'm confused by now.
|
|
|
|
|
Hi,
I have a DCOM application, where the component fires 8-10 events.
But all the events are similar in structure. (ie. they doesnt have any data associated with them).
The only difference is the event name.
So, I can easily use a single event to Notify all my events to
the client (And have some Parameter that distinguishes the event
to the client).
Now, my question is will this (using a single event in place of many events)
provide any PERFORMANCE benefits in a DCOM application ??
if yes, How ?? (some technical description will be appreciated)
anyway, the number of Network RoundTrips is going to be the same...
if no,
What will be a good COM programming practice in this situation.
(using a Single event or using different events)
Thanks,
Firoz.
|
|
|
|
|
Usually Events in COM are a kind of painful.
these were designed for in- process DLLs.
Each event takes 5 round trips from source to sink to complete its duty.
Just imagine, how much load on the network due to these round trips..
If you have 8- 10 events.........think.. 40-50 round trips( calls)
I will come up with more info.wait..
Cheers,
Anand.
|
|
|
|
|
I want to develop an ASP Application which will use ATL COM components.. I want to create a connection in my ATL COM components which will be called from 'Global.asa'.. i am returning a reference of _ConnectionPtr from my component...
i want to use that reference for my all the ASP pages for calling all other components.. so for that purpose i am passing that reference as first argument to all my other components functions... and in all other components i want to use that connection reference for opening my recordset...
the code is:
// Global.asa //////////////////////////////////////////////////////////////////////////////
Sub Application_OnStart
Dim ob
set ob = Server.CreateObject("MyDLL.Class")
// This method 'GetConnection' will return the reference of _ConnectionPtr
Application("con") = ob.GetConnection()
End Sub
// Other.asp //////////////////////////////////////////////////////////////////////////////
<%
Dim obj
set obj = Server.CreateObject("MyOtherDLL.Class")
result = obj.SomeFunction(Application("con"), "some string")
response.write result
%>
This is giving me error like
Type Missmatch 'SomeFunction'
//////////////////////////////////////////////////////////////////////////////////////////////
The definition of the function 'SomeFunction' is:
HRESULT SomeFunction(IDispatch *conn, BSTR str, short *result)
{
_ConnectionPtr pCon( __uuidof( Connection ) );
pCon = _variant_t( (IDispatch*)conn, true); // i think where the problem is
_RecordSetPtr pRst;
_CommandPtr pCmd;
..... rest of the code
}
Please give me some suggession ...
how can i make connection in Global.asa by means of a DLL and pass it to my other DLLs which will be called from different ASP pages...
Thanks in Advance...
JubiNishoo
|
|
|
|
|
Hi,
I have just started coding in ATL. I recently posted a question but didn't get much answers.
The question remains still there: What exactly is an apartment? Is it a process boundary or method boundary? What about methods calling each other?
Waiting for an answer,
Ali
Our scientific power has outrun our spiritual power. We have guided missiles and misguided men (Martin Luther King Jr)
|
|
|
|
|
An apartment is a thread. By installing a COM object for STA access (Single Threaded Access) Formally known as "Apartment" you can presume that no method or access to an object instance will be made from some other thread while it is processing a request from another. This simplifies the design by reducing the need for consideration of more complex synchronization issues but limits what the object can do. Note that an object instance can have many interfaces and these interface references all will comply with the Apartment model if that is how the instance was created.
It's important to note that an instance does not "exist or live in an apartment" though many people think of it this way. An object instance is simply a chunk of memory containing the state of the object.
Geoffrey Feldman
geoff@seabasecns.com
|
|
|
|
|
An apartment is NOT a thread. An apartment is a logical grouping of COM objects that share the same concurrency requirements. A thread enters an apartment by calling CoInitialize or CoInitializeEx.
STA stands for Single Threaded Apartment, not Single Threaded Access. By implementing your object using STA model, or apartment threading model, you are relying on COM to synchronize calls to your object.
geoff wrote:
but limits what the object can do.
How does implementing an object as single threaded limit what it can do?
|
|
|
|
|
I stand corrected, particularly in that an apartment is not a thread. I do find this topic hard to describe correctly and I think so does microsoft. I think the tangle comes with confusing the process of execution with the description of how it is to take place. And STA? Double whoops, you are right on that as well.
Geoffrey Feldman
geoff@seabasecns.com
|
|
|
|
|
How to understanding marshaling !
It is a bridge of commumication between proxy and stub code.
COM
|
|
|
|
|
Can you be a little more specific with your question?
Marshaling is just a term for the serialization of a routine's arguments. This allows for the call to be sent over a wire to another thread/process/machine. Then the return values are marshaled and returned to the calling process.
When you create an IDL file and compile it, you can also generate the proxy code which will do all the marshaling for you. Once this code is compiled and registered (and installed on the machines in question), COM will automatically load the proxy to marshal the calls.
Tim Smith
Descartes Systems Sciences, Inc.
|
|
|
|
|
I'm trying to implement IOleCommandTarget in my BHO class, using the following code:
// IEPowerUp.h : Declaration of the CIEPowerUp
#ifndef __IEPOWERUP_H_
#define __IEPOWERUP_H_
#include "resource.h" // main symbols
/////////////////////////////////////////////////////////////////////////////
// CIEPowerUp
class ATL_NO_VTABLE CIEPowerUp :
public CComObjectRootEx<ccomsinglethreadmodel>,
public CComCoClass<ciepowerup, &clsid_iepowerup="">,
public IOleCommandTarget,
public IObjectWithSiteImpl<ciepowerup>,
public IDispatchImpl<iiepowerup, &iid_iiepowerup,="" &libid_test2lib="">
{
public:
CIEPowerUp();
DECLARE_REGISTRY_RESOURCEID(IDR_IEPOWERUP)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CIEPowerUp)
COM_INTERFACE_ENTRY(IIEPowerUp)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IOleCommandTarget)
COM_INTERFACE_ENTRY_IMPL(IObjectWithSite)
END_COM_MAP()
// IOleCommandTarget
public:
STDMETHODIMP CIEPowerUp::QueryStatus(const GUID* pguidCmdGroup,ULONG cCmds,OLECMD prgCmds[],OLECMDTEXT* pCmdText);
// IObjectWithSite
public:
STDMETHOD(SetSite)(IUnknown* pUnkSite);
// IIEPowerUp
public:
STDMETHOD(InitHooks)(BOOL fUnload = false);
public:
CComQIPtr<iwebbrowser2, &iid_iwebbrowser2=""> m_spWebBrowser2;
protected:
HWND m_hWnd;
IInputObjectSite* m_pSite;
public:
BOOL m_bCtrlDown;
POINT m_pMPoint;
int m_iStatus;
int m_iLastStatus;
DWORD m_LastTime;
DWORD m_DelayAmount;
};
#endif //__IEPOWERUP_H_
Unfortunately, I get the following compile errors. Can anyone help me figure out what I'm doing wrong?
--------------------Configuration: Test2 - Win32 Debug--------------------
Compiling...
IEPowerUp.cpp
Test2.cpp
d:\program files\microsoft visual studio\vc98\atl\include\atlcom.h(1827) : error C2259: 'CComObject<class ciepowerup="">' : cannot instantiate abstract class due to following members:
d:\program files\microsoft visual studio\vc98\atl\include\atlcom.h(1823) : while compiling class-template member function 'long __stdcall ATL::CComCreator<class atl::ccomobject<class="" ciepowerup=""> >::CreateInstance(void *,const struct _GUID &,
void ** )'
d:\program files\microsoft visual studio\vc98\atl\include\atlcom.h(1827) : warning C4259: 'long __stdcall IOleCommandTarget::Exec(const struct _GUID *,unsigned long,unsigned long,struct tagVARIANT *,struct tagVARIANT *)' : pure virtual function was
not defined
d:\program files\microsoft visual studio\vc98\include\docobj.h(1453) : see declaration of 'Exec'
d:\program files\microsoft visual studio\vc98\atl\include\atlcom.h(1823) : while compiling class-template member function 'long __stdcall ATL::CComCreator<class atl::ccomobject<class="" ciepowerup=""> >::CreateInstance(void *,const struct _GUID &,
void ** )'
d:\program files\microsoft visual studio\vc98\atl\include\atlcom.h(1827) : error C2259: 'CComObject<class ciepowerup="">' : cannot instantiate abstract class due to following members:
d:\program files\microsoft visual studio\vc98\atl\include\atlcom.h(1823) : while compiling class-template member function 'long __stdcall ATL::CComCreator<class atl::ccomobject<class="" ciepowerup=""> >::CreateInstance(void *,const struct _GUID &,
void ** )'
d:\program files\microsoft visual studio\vc98\atl\include\atlcom.h(1827) : warning C4259: 'long __stdcall IOleCommandTarget::Exec(const struct _GUID *,unsigned long,unsigned long,struct tagVARIANT *,struct tagVARIANT *)' : pure virtual function was
not defined
d:\program files\microsoft visual studio\vc98\include\docobj.h(1453) : see declaration of 'Exec'
d:\program files\microsoft visual studio\vc98\atl\include\atlcom.h(1823) : while compiling class-template member function 'long __stdcall ATL::CComCreator<class atl::ccomobject<class="" ciepowerup=""> >::CreateInstance(void *,const struct _GUID &,
void ** )'
Generating Code...
Error executing cl.exe.
Test2.dll - 2 error(s), 2 warning(s)
|
|
|
|
|
I found the lines that are causing the errors. There're located in Test2.cpp (contains the regular regsvr32 functions):
BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_IEPowerUp, CIEPowerUp)
END_OBJECT_MAP()
|
|
|
|
|
Hint: pure virtual function was not defined. You forgot to put the Exec() method in your class.
--Mike--
My really out-of-date homepage
"Why does anyone have a web page? Too much free time... not enough friends... justifying owning a computer." -- Noel Crane on Felicity
Sonork - 100.10414 AcidHelm
Big fan of Alyson Hannigan.
|
|
|
|
|
Augh! I've spent hours and hours trying bunchs of different variations of implementing it, and it all comes down to this .
Thank you so much; it's working perfectly now!
|
|
|
|
|
How would i go about using IDirectDraw7 and IDirecDrawSurface7 inside my ATL type library.
The DirectShow IDL's do this but i cannot figure out how.
I've tried using "import "DDrawex.h" and "include "ddrawex.h" but these give type redefinitions.
Here's a clip from DirectShow's DDStream.idl
import "unknwn.idl";
import "mmstream.idl";
cpp_quote("//")
cpp_quote("// The following declarations within the 'if 0' block are dummy typedefs used to make")
cpp_quote("// the ddstream.idl file build. The actual definitions are contained in DDRAW.H")
cpp_quote("//")
cpp_quote("#if 0")
typedef void * LPDDSURFACEDESC;
typedef struct tDDSURFACEDESC DDSURFACEDESC;
cpp_quote("#endif")
cpp_quote("#include <ddraw.h>")
enum {
DDSFF_PROGRESSIVERENDER = 0x00000001
};
interface IDirectDraw;
interface IDirectDrawSurface;
interface IDirectDrawPalette;
interface IDirectDrawMediaStream;
interface IDirectDrawStreamSample;
// IDirectDrawMediaStream
[
object,
local,
uuid(F4104FCE-9A70-11d0-8FDE-00C04FD9189D),
pointer_default(unique)
]
interface IDirectDrawMediaStream : IMediaStream
{
HRESULT GetFormat(
[out] DDSURFACEDESC *pDDSDCurrent,
[out] IDirectDrawPalette **ppDirectDrawPalette,
[out] DDSURFACEDESC *pDDSDDesired,
[out] DWORD *pdwFlags);
....continued......
mmstream.idl doesn't use the directdraw interfaces at all.
Doing this gives me
error MIDL2337 : unsatisfied forward declaration : IDirectDrawSurface7
is there any way to do this?
"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken
Bobby Ward
|
|
|
|
|
The application that I'm working on has an OnIdle() handler. It was written by someone else - despite my suggestion that a timer would better suit the situation. :P
Now, I've added a few more ATL objects (the project already had a few), and for some strange reason, simply having the object created at initialization time causes an OnIdle() call after the App has closed and cleared some of it's state.
class CMyObject :
public CComObjectRootEx<CComSingleThreadModel>,
public IMyInterface {
...
};
class CMyApp : public CWinApp {
...
CComObject<CMyObject> *m_pObj;
...
BOOL OnIdle(long);
void Init();
...
};
void CMyApp::Init() {
...
CComObject<CMyObject>::CreateInstance(&m_pObj);
...
}
BOOL CMyApp::OnIdle(long) {
...
CMainFrame *pMF = static_cast<CMainFrame *>(m_pMainWnd);
...
}
The initialization goes fine, and hell it has nothing to do with the App or main frame. Then, when I close the application, it crashes because OnIdle() is getting called AFTER the App state has been cleared, and pMF is NULL.
Does simply creating an ATL object somehow screw around with the application message queues? Is the OnIdle() getting called from another thread? My ATL objects are all using CComSingleThreadModel...
J
|
|
|
|
|
If anyone's curious as to what the hell I was babbling about, I found the problem.
The trouble is, when the CMainFrame closes, it calls AfxOleCanExitApp() to check if there are any outstanding object references. If there are, the frame gets hidden but NOT destroyed. That's why OnIdle() was still being called, and why it was dying when it tried to use the CMainFrame.
Now, my problem has changed. I have to find a way to release all my objects before the main window gets closed. Seems a little odd...
J
|
|
|
|
|
Not Odd, that's the correct way to go. You must get the object pointer and
release it in OnDestroy(). For ActiveX, you should not have to do this since
CWnd does it for you.
|
|
|
|
|
I agree, it makes sense for graphic components and ActiveX controls. However, the object to which the dangling reference belongs is an Active Script engine, and is currently owned by the App. If I simply move it to the main frame, everything will probably work.
But that doesn't fit the conceptual layout of our application. We have a scripting engine that gets created when the application starts, and killed when the application ends. That makes more sense than a scripting engine that gets created and destroyed with the frame window...
J
|
|
|
|
|
I have a com object in a local server (ATL) with one method that just sets some dummy output data. If I set the parameter type to be:
[out] long* pLong
then it at least works in release mode (I can get the value from a different process). If I set the parameter type to be:
[out] BSTR* pString
then it will generate a "out of memory error". Both versions won't work in debug mode.
My question is, how do I specify output parameter type if it is not an in-proc-server?
|
|
|
|
|