| Onega's profileOnegaBlogListsNetwork | Help |
|
|
April 21 Changing the Startup type and description of VC++ 2008 service project#include <stdio.h> class COzSvcModule : public CAtlServiceModuleT< COzSvcModule, IDS_SERVICENAME > return hr; hService = OpenService( if (! ChangeServiceConfig( add #define _ATL_NO_COM_SUPPORT to stdafx.h for NON-COM project. To register the service, pass "-service" parameter, use "-unregserver" to uninstall it. January 18 dynamic_cast with COM interface pointerWhen I use c cast to get a pointer to an implementation class of an interface and call its method, it reports access violation upon the entry of the method, even if the method only contains one line: "return S_OK". In debugger I can see that some member variables are correctly initialized, but a few variables are unable to be evaluated by debugger. My first guess is that ctor of its parent is not called, so I manually added the call to initialization sequence of ctor of the implementation class, but it is not the fix. After some try and error process, it is solved by dynamic_cast. Environment: VC++ 2005 (without SP1). class CMyInterface: public CParentClass, // yes, it inherits from another class IMyInterface* p=NULL; When using C cast, some members of CParentClass are visible in debugger, but a few are not! November 27 ROT and typelibIf typelib is not properly registered, a COM object can be registered to ROT, but subsequent GetObject would fail with error : "Invalid Pointer". It is valid to have two typelib in one executable, but the registeration has to be taken manually via CComModule::RegisterTypeLib(LPCTSTR lpszIndex); CreateItemMoniker can be used to register a random interface object. October 15 RPC_E_CANTCALLOUT_ININPUTSYNCCALL Error with Out-of-Proc COM ServerSteps to reproduce: Create an out-of-proc COM server, add one method STDMETHODIMP ExeMsg::Test(long process_id, long thread_id) Create a MFC Dialog based application, add two buttons to it. Start a work thread to send a private message back to the main dialog, the private message handler will call method of the out-of-proc COM object. ON_MESSAGE(MSG_MYMSG, OnMsg) UINT TestSendMsgThreadProc(LPVOID unusedarg) void CMsgclientDlg::OnButton2() struct Parameters UINT COMProcThread(LPVOID pa) LRESULT CMsgclientDlg::OnMsg( WPARAM w, LPARAM l ) } if (!InSendMessage()) return 0; September 19 Purify reports memory leak in UpdateRegistryFromResource methodRational Purify reported memory leak in UpdateRegistryFromResource method, which is introduced by DECLARE_REGISTRY_RESOURCEID(...) macro. After I rebuilt with _ATL_STATIC_REGISTRY enabled, Rational Purify is happy. July 17 Wrapper class for using UDT (User Defined Type) in COMUDTs must be freed by caller, just like BSTR. So I created a template to ease the work of caller. template <typename UDT > class UDTWrapper : public UDT { public: UDTWrapper() { HRESULT hr = S_OK; CComPtr<ITypeLib> pTypelib; CComPtr<ITypeInfo> pTypeInfo; hr = LoadRegTypeLib(lib_id, 1, 0, GetUserDefaultLCID(), &pTypelib); _ASSERT(SUCCEEDED(hr) && pTypelib); hr = pTypelib->GetTypeInfoOfGuid(__uuidof(UDT), &pTypeInfo); _ASSERT(SUCCEEDED(hr) && pTypeInfo); hr = GetRecordInfoFromTypeInfo(pTypeInfo, &pRecInfo); pRecInfo->RecordInit(this); } ~UDTWrapper() { if (pRecInfo) { HRESULT hr = pRecInfo->RecordClear(this); printf("RecordClear return %08x\n", hr); } else { printf("RecInfo is NULL\n"); } } private: CComPtr<IRecordInfo> pRecInfo; public: static GUID lib_id; }; template <class UDT> GUID UDTWrapper<UDT>::lib_id; typedef UDTWrapper<UDT1Lib::sSiteStatus> sSiteStatusWrapper; typedef UDTWrapper<UDT1Lib::sStationStatus> sStationStatusWrapper; int main(int argc, char* argv[]) { CoInitialize(0); HRESULT hr = S_OK; UDTWrapper<UDT1Lib::sSiteStatus>::lib_id = __uuidof(UDT1Lib::__UDT1Lib); UDTWrapper<UDT1Lib::sStationStatus>::lib_id = __uuidof(UDT1Lib::__UDT1Lib); hr = TestGetSingleUdt(); //hr = TestGetStationStatus(); //hr = TestSiteStatusWrapper(); //hr = TestStationStatusWrapper(); printf("TestGetSingleUdt return %08x!\n", hr); system("Pause"); return 0; } VC++ 6.0 does not associate GUID with UDTs in tlh file, so I need to do the following workaround. #if _MSC_VER < 1400 // VC++ 2005 will associate GUID with used defined structures and type library. // but VC6 does not do this. namespace UDT1Lib{ struct __declspec(uuid("95d6c27d-baab-41e0-aeee-cd30e0b15bba")) __UDT1Lib; struct __declspec(uuid("3caf4043-6af3-4a2f-9518-77b6bd0b37e9")) sSiteStatus; struct __declspec(uuid("d1b94033-31c9-4623-9d4f-5278ae9a682a")) sStationStatus; } #endif July 01 COM Client Method Call Fails with ERROR_NOACCESS(0xC0000005)I encountered this problem in recent project development. It is very likely to be the same problem as documented in MSDN Q273721. Only one method failed, because it contains a parameter of IUnknown*. Another related KB article may be Q149231 Marshaling Code for Connection Point Interfaces. Solution: change method signature to use VARIANT instead of LPUNKNOWN/LPDISPATCH. June 21 Share COM objects between threads/processesThe CoCreateFreeThreadedMarshaler function enables an object to
efficiently marshal interface pointers between threads in the same
process. The IGlobalInterfaceTable interface is an efficient way for a process to store an interface pointer in a memory location that can be accessed from multiple apartments within the process, such as processwide variables and agile (free-threaded marshaled) objects containing interface pointers to other objects. The IRunningObjectTable interface manages access to the Running Object Table (ROT), a globally accessible look-up table on each workstation. May 14 Add ATL object to existing MFC SDI projectI met the following mistakes: missing [out] specifier in IDL file, so the method can't be called by vbscript; messing up CLSID and LIBID. AfxGetApp() and AfxGetMainWnd() return NULL -- workaround is to use theApp object, store HWND as a member of theApp class, initial it in theApp.InitInstance(). I also add connection point support to this project, but sink can't register to the interface because QueryInterface(IID_MyEventInterface, ...) failed with error code 0x80004002, interestingly QueryInterface(IID_IDispatch,...) is successful. Maybe that is why event source usually access client via IDispatch interface. After spending many hours diagnosing the problem, I found that the event interface shall also be registered in the event source project like other COM interface, always the event interface does not have its coclass. HKCR { CallbackServer.CallbackTest.1 = s 'CallbackTest Class' { CLSID = s '{AB2E5112-5FE5-49ED-A60E-DADAC49DFF05}' } CallbackServer.CallbackTest = s 'CallbackTest Class' { CLSID = s '{AB2E5112-5FE5-49ED-A60E-DADAC49DFF05}' CurVer = s 'CallbackServer.CallbackTest.1' } NoRemove CLSID { ForceRemove {AB2E5112-5FE5-49ED-A60E-DADAC49DFF05} = s 'CallbackTest Class' { ProgID = s 'CallbackServer.CallbackTest.1' VersionIndependentProgID = s 'CallbackServer.CallbackTest' ForceRemove 'Programmable' LocalServer32 = s '%MODULE%' val AppID = s '%APPID%' 'TypeLib' = s '{EC8F9F17-3EB2-42E0-A73C-F5CD74D77377}' } } } The hint is from a post here: http://www.codeproject.com/atl/conexe.asp |
|
|