CopyItems Function Hook crashes - winapi

i am trying to hook CopyItems function ,its working fine but when i am trying to call Real CopyItems Function in the Callback function it is getting crash , my code is as below, please help me.
PVOID GetInterfaceMethod(PVOID intf, DWORD methodIndex)
{
return *(PVOID*)(*(DWORD*)intf + methodIndex * 4);
}
typedef HRESULT (WINAPI *CopyItemsNext)(IUnknown *punkItems,IShellItem *psiDestinationFolder);
CopyItemsNext Real_CopyItems = NULL;
CopyItemsNext Actual_CopyItems;
HRESULT WINAPI CopyItemsCallback(IUnknown *punkItems,IShellItem *psiDestinationFolder)
{
MessageBoxW(NULL,L"CopyItems Function Called", L"HookedCopyItemS", MB_OK);
return Real_CopyItems(punkItems, psiDestinationFolder);
}
HRESULT WINAPI CoCreateInstanceCallback(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID *ppv)
{
const char *IFileOperation_GUID = "{3AD05575-8857-4850-9277-11B85BDB8E09}";
char GUIDString[64];
HRESULT HR = Real_CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv);
sprintf_s(GUIDString,64, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\0",
rclsid.Data1, rclsid.Data2, rclsid.Data3,
rclsid.Data4[0], rclsid.Data4[1],
rclsid.Data4[2], rclsid.Data4[3],
rclsid.Data4[4], rclsid.Data4[5],
rclsid.Data4[6], rclsid.Data4[7]);
if(strcmp(GUIDString, IFileOperation_GUID) == 0)
{
MessageBoxA(NULL, "IFileOperation_GUID Found", GUIDString, MB_OK);
if(Real_CopyItems == NULL)
{
Actual_CopyItems = (CopyItemsNext)GetInterfaceMethod(*ppv, 17);
MessageBoxA(NULL,"AFTER GetInterfaceMethod", "TEST", MB_OK);
if (MH_CreateHook(Actual_CopyItems, &CopyItemsCallback, reinterpret_cast<void**>(&Real_CopyItems)) != MH_OK)
{
MessageBoxW(NULL, L"Failed CreateHook Real_CopyItem", L"Info!", MB_ICONWARNING|MB_OK);
}
if (MH_EnableHook(Actual_CopyItems) != MH_OK)
{
MessageBoxW(NULL, L"Failed EnableHook Real_CopyItem", L"Info!", MB_ICONWARNING|MB_OK);
}
}
}
return HR;
}
//DllMain Function
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
if (MH_Initialize() != MH_OK)
{
MessageBoxW(NULL, L"Failed Initialize", L"Info!", MB_ICONWARNING|MB_OK);
}
if (MH_CreateHook(&CoCreateInstance, &CoCreateInstanceCallback, reinterpret_cast<void**>(&Real_CoCreateInstance)) != MH_OK)
{
MessageBoxW(NULL,L"Failed MH_CreateHook CoCreateInstance",L"Info!",MB_ICONWARNING|MB_OK);
}
if (MH_EnableHook(&CoCreateInstance) != MH_OK)
{
MessageBoxW(NULL,L"Failed MH_EnableHook StartDocA",L"Info!",MB_ICONWARNING|MB_OK);
}
break;
case DLL_PROCESS_DETACH:
if (MH_Uninitialize() != MH_OK)
{
}
if (MH_DisableHook(Actual_CopyItems) != MH_OK)
{
}
if (MH_DisableHook(&CoCreateInstance) != MH_OK)
{
}
break;
}
return TRUE;
}
In the above code inside the CopyItemsCallback function i am displaying Message box just to confirm weather the function is getting hook r not ,so i got that message box after that i am calling Real CopyItems Function but there it is getting crash so please check what is the problem with my code .

IFileOperation::CopyItems is a COM method, not a regular Win32 function, so you need to treat it differently than CoCreateInstance, which is a plain Win32 API.
When you call a COM method using C++ syntax, what you don't see is the "this" pointer (same as the interface pointer) being passed behind the scenes as a hidden parameter. But if you want to call a COM method using C-style code, you have to deal with this manually.
So your definition of the CopyItems function should instead look something like this:
typedef HRESULT (STDMETHODCALLTYPE *CopyItemsNext)(IFileOperation * pThis, IUnknown *punkItems, IShellItem *psiDestinationFolder);
...and when you call through to the 'real' one, you'll have to pass that pThis as the first parameter.
Note that this trick is specific to COM, you can't in general treat C++ methods this way. It just happens that COM was designed to be usable from plain C, so COM requires that the 'this' pointer is passed just as a normal parameter would be. (COM methods are marked with STDMETHODCALLTYPE which is what tells the compiler to treat them differently than methods without that.) However, for non-COM C++ classes, a compiler might do something else, such as passing the this pointer in a register.
--
By the way, note that the DWORD in your GetInterfaceMethod will only work on 32-bit windows; use DWORD_PTR if you want a type that is always the size of a pointer and which will then work with either 32-bit or 64-bit code.

Related

How to write an application to control a driver which is pnp and in kmdf?

so I will detail so that we can easily understand
I have to make a driver for a pcie card, I already have the driver that I wrote in kmdf, now I am using this driver, unfortunately I find myself stuck, I have to write an application (which for example would call the METHOD_IN_DIRECT function that I defined in a switch case in my IoDeviceControl)
I therefore tried to start from an example on github and modified it so that it works ... but obviously as this example is for a NONpnp driver it is not usable for my driver which is pnp.
So I looked for examples of applications that worked with a pnp driver to see the model / shape, but I can't find a tutorial / sites / example on the realization of this famous application, one of the only sites that spoke about it was saying:
"Set an interface guide so the application can find the device and talk to it."
now my question is:
"how to write an aplication to control a PNP driver"
the main in "test.c":
int __cdecl
main(
_In_ ULONG argc,
_In_reads_(argc) PCHAR argv[]
)
{
HANDLE hDevice;
DWORD errNum = 0;
CHAR driverLocation[MAX_PATH];
BOOL ok;
LONG error;
// ULONG bytesReturned;
printf("main start. \n");
//
//open the device
printf("createFile. \n");
hDevice = CreateFileA(DRIVER_NAME,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hDevice == INVALID_HANDLE_VALUE){...}
printf("press enter \n");
int c = getchar();
printf("reception d'un charactere . \n");
if (c) {
printf("ioctl go \n");
DoIoctls(hDevice);
printf("ioctl end \n");
//
// Close the handle to the device before unloading the driver.
//
CloseHandle(hDevice);
//
// Unload the driver. Ignore any errors.
//
ManageDriver(DRIVER_NAME, driverLocation, DRIVER_FUNC_REMOVE);
}
c = getchar();
return;
}
here is the main of "test.c" which is at the base for nonpnp but that I modified that said I do not know how to embed the use of the GUID in my application (I imagine that it is because of that that it does not work).
the function DoIoctl :
VOID
DoIoctls(
HANDLE hDevice
)
{
char OutputBuffer[100];
char InputBuffer[200];
BOOL bRc;
ULONG bytesReturned;
//
// Printing Input & Output buffer pointers and size
//
printf("\nInputBuffer Pointer = %p, BufLength = %Id\n", InputBuffer,sizeof(InputBuffer));
printf("OutputBuffer Pointer = %p BufLength = %Id\n", OutputBuffer,sizeof(OutputBuffer));
//
// Performing METHOD_IN_DIRECT
//
printf("\nCalling DeviceIoControl METHOD_IN_DIRECT\n");
if (FAILED(StringCchCopy(InputBuffer, sizeof(InputBuffer),"this String is from User Application; using METHOD_IN_DIRECT")))
{
return;
}
if (FAILED(StringCchCopy(OutputBuffer, sizeof(OutputBuffer),"This String is from User Application in OutBuffer; using METHOD_IN_DIRECT")))
{
return;
}
bRc = DeviceIoControl(hDevice,
(DWORD)Spw_PCIe_IOCTL_IN_BUFFERED,
InputBuffer,
(DWORD)strlen(InputBuffer) + 1,
OutputBuffer,
sizeof(OutputBuffer),
&bytesReturned,
NULL
);
if (!bRc)
{
printf("Error in DeviceIoControl : %d \n", GetLastError());
return;
}
printf(" Number of bytes transfered from OutBuffer: %d\n",bytesReturned);
//
// Performing METHOD_OUT_DIRECT
//
printf("\nCalling DeviceIoControl METHOD_OUT_DIRECT\n");
if (FAILED(StringCchCopy(InputBuffer, sizeof(InputBuffer), "this String is from User Application; using METHOD_OUT_DIRECT"))) {
return;
}
memset(OutputBuffer, 0, sizeof(OutputBuffer));
bRc = DeviceIoControl(hDevice,
(DWORD)Spw_PCIe_IOCTL_OUT_BUFFERED,
InputBuffer,
(DWORD)strlen(InputBuffer) + 1,
OutputBuffer,
sizeof(OutputBuffer),
&bytesReturned,
NULL
);
if (!bRc)
{
printf("Error in DeviceIoControl : : %d", GetLastError());
return;
}
printf(" OutBuffer (%d): %s\n", bytesReturned, OutputBuffer);
return;
}
function ManageDriver :
BOOLEAN
ManageDriver( // <- ManageDriver
IN LPCTSTR DriverName,
IN LPCTSTR ServiceName,
IN USHORT Function
)
{
SC_HANDLE schSCManager;
BOOLEAN rCode = TRUE;
schSCManager = OpenSCManager(NULL, // local machine
NULL, // local database
SC_MANAGER_ALL_ACCESS // access required
)
// Do the requested function.
switch (Function) {;
case DRIVER_FUNC_REMOVE: // REMOVE
printf("remove case. \n");
// Stop the driver.
StopDriver(schSCManager,DriverName);
// Remove the driver service.
RemoveDriver(schSCManager,DriverName);
// Ignore all errors.
rCode = TRUE;
break;
default:
printf("Unknown ManageDriver() function. \n");
rCode = FALSE;
break;
}
// Close handle to service control manager.
if (schSCManager) {
CloseServiceHandle(schSCManager);
}
return rCode;
} // ManageDriver fin
function remove :
BOOLEAN
RemoveDriver( // <- RemoveDriver
_In_ SC_HANDLE SchSCManager,
_In_ LPCTSTR DriverName
)
{
SC_HANDLE schService;
BOOLEAN rCode;
// Open the handle to the existing service.
schService = OpenService(SchSCManager,DriverName,SERVICE_ALL_ACCESS);
// Mark the service for deletion from the service control manager database.
DeleteService(schService)
if (schService) {
CloseServiceHandle(schService);
}
return rCode;
} // RemoveDriver fin
function StartDriver :
BOOLEAN
StartDriver(
_In_ SC_HANDLE SchSCManager,
_In_ LPCTSTR DriverName
)
{
SC_HANDLE schService;
DWORD err;
// Open the handle to the existing service.
schService = OpenService(SchSCManager, DriverName,SERVICE_ALL_ACCESS );
// Start the execution of the service (i.e. start the driver).
StartService(schService, // service identifier
0, // number of arguments
NULL // pointer to arguments
)
// Close the service object.
if (schService) {
CloseServiceHandle(schService);
}
return TRUE;
} // StartDriver fin
function StopDriver :
BOOLEAN
StopDriver(
_In_ SC_HANDLE SchSCManager,
_In_ LPCTSTR DriverName
)
{
BOOLEAN rCode = TRUE;
SC_HANDLE schService;
SERVICE_STATUS serviceStatus;
//
// Open the handle to the existing service.
//
schService = OpenService(SchSCManager,
DriverName,
SERVICE_ALL_ACCESS
);
//
// Request that the service stop.
//
ControlService(schService,
SERVICE_CONTROL_STOP,
&serviceStatus
)
//
// Close the service object.
//
if (schService) {
CloseServiceHandle(schService);
}
return rCode;
} // StopDriver fin
I deleted everything that is debugger otherwise there is sure that it would not be clear
if you had any indication maybe I'm wrong about the nature of applications maybe the solution is very dumb but if you know anything about writing application for pnp driver I'm a taker
to shorten it :
i would need an application skeleton, but not just any, i need one that works for a pnp driver.
(it doesn't matter which driver as long as it's a pnp)
this is to be able to compare with my application and see what is missing from my aplication to support plug and play
cordially thank you all
You need to obtain the device path using the SetupDi functions as shown in this answer.

DLL Entry Point of Windows Hook

I implement a DLL to record user's input by using SetWindowsHookEx function.
Besides, I inject my DLL after the hooked program runs.
The return values of SetWindowsHookEx indicate that they all hook the process successfully.
However, I don't know why when I set my hook in DLL_THREAD_ATTACH , the message hook works good. But the hook will be disconnected when the thread dies, which is very annoying for me to log user's input.
When I set my hook in DLL_PROCESS_ATTACH, it will enters that case, but it seems that my hook never receives the callback of HOOKPROC.
Therefore, I only post DllMain and SetMyHook function.
My code structure :
BOOL APIENTRY DllMain( HINSTANCE hInst, DWORD ul_reason_for_call, LPVOID lpReserved )
{
switch( ul_reason_for_call )
{
case DLL_PROCESS_ATTACH:
MainHwnd = GetMainWindow();
SetMyHook(hWnd_tid, hInst);
break;
case DLL_PROCESS_DETACH:
ClearMyHook();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
__declspec(dllexport) BOOL WINAPI SetMyHook(DWORD tid, HMODULE hInstance)
{
Hook = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)MsgHook, hInstance, tid);
MHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)MenuHook, hInstance, tid);
if(Hook && MHook)
return TRUE;
else
return FALSE;
}
__declspec(dllexport) BOOL ClearMyHook(void)
{
if (UnhookWindowsHookEx(Hook) && UnhookWindowsHookEx(MHook))
{
return TRUE;
}
return FALSE;
}
Notice:
If I move the code in the case DLL_PROCESS_ATTACH to DLL_THREAD_ATTACH, it will work!!
I don't know why it will happen...

Register a proxy/stub in HKEY_CURRENT_USER

The MIDL compiler generates code for a proxy/stub with registration routines that write to HKEY_LOCAL_MACHINE. Is there any way (preferably without hacking the MIDL-generated code and without bypassing all that generated code in favor of custom code) to register a MIDL-generated p/s in HKEY_CURRENT_USER?
Also: Will this work if both the p/s and the COM server are registered per-user like this? I just found (after a very frustrating 48 hours) that a p/s registered machine-wide will not work correctly if the COM server is registered per-user. Specifically, the asynchronous call logic (ICallFactory::CreateCall) of the p/s will fail under these circumstances.
Using RegOverridePredefKey is the right answer.
Then register with:
regsvr32 /n /i:user C:\src\myCode.dll
With "/i:user", regsvr32 calls your the "DllInstall" function instead of DllRegisterServer.
Example implementation of DllInstall:
extern "C" STDAPI DllInstall(BOOL bInstall, _In_opt_ LPCWSTR pszCmdLine)
{
HRESULT hr = E_FAIL;
static const wchar_t szUserSwitch[] = L"user";
if (pszCmdLine != NULL)
{
if (_wcsnicmp(pszCmdLine, szUserSwitch, _countof(szUserSwitch)) == 0)
{
ATL::AtlSetPerUserRegistration(true); // is this really needed??
}
}
LSTATUS status = RegCreateKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\Classes", 0, 0, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0, &hkcu_classes, &disposition);
if (status == ERROR_SUCCESS)
{
status = RegOverridePredefKey(HKEY_CLASSES_ROOT, hkcu_classes);
}
hr = HRESULT_FROM_NT(status);
if (SUCCEEDED(hr))
{
if (bInstall)
{
hr = DllRegisterServer();
if (FAILED(hr))
{
DllUnregisterServer();
}
}
else
{
hr = DllUnregisterServer();
}
}
}

Hooking into message pump of STA Apartment COM object activated in DllHost by DllSurrogate

I have a fairly complex requirement. My STA COM object is implemented in a DLL (can't move it to out-of-process EXE). By the means of DllSurrogate I am hosting my object in a dllhost.exe process. My object has an UI attached to it (a plain modeless dialog) but I need the PreTranslateAccelerator mechanism in order for some shortcuts to work, etc. Since COM activates my object and hosts it in the default dllhost.com, I am obviously not controlling the message pump.
Is there still a way to pre-translate messages in this scenario? I doubt COM has foreseen such a specific scenario but maybe I am missing something.
Okay here it is. I hope I didn't leave out anything important. Basically, I have created a custom CMyComCreator instead of the default one. Instead of just creating a COM object and returning an interface pointer, I spin a worker UiThread. I use MyData structure to pass data across threads. Once the worker thread has finished setting up, I use the CComGITPtr to transfer the marshalled interface pointer from the UiThread back to the main. The consumers (out-of-process) end up with interface pointers that talk directly to the UiThread bypassing the main thread. You may think of CMyDialog as a modeless dialog which sends a PostQuitMessage on destruction to terminate the message loop. That's all. May look cumbersome but it works good.
struct MyData
{
ATL::CComGITPtr<IUnknown> Unk;
ATL::CEvent Event;
HRESULT hr;
MyData() : hr(E_OUTOFMEMORY), Event(FALSE, FALSE) { }
};
static CMessageLoop * MessageLoop;
class CMyComCreator
{
public:
static HRESULT WINAPI CreateInstance(
_In_opt_ void* pv,
_In_ REFIID riid,
_COM_Outptr_ LPVOID* ppv)
{
ATLASSERT(ppv != NULL);
if (ppv == NULL)
return E_POINTER;
*ppv = NULL;
HRESULT hRes = E_OUTOFMEMORY;
MyData* data = NULL;
ATLPREFAST_SUPPRESS(6014 28197)
/* prefast noise VSW 489981 */
ATLTRY(data = _ATL_NEW MyData)
ATLPREFAST_UNSUPPRESS()
if (data != NULL)
{
HANDLE thread = (HANDLE)_beginthreadex(NULL, 0, UiThread, (void *)data, 0, NULL);
if (thread)
{
WaitForSingleObject(data->Event, INFINITE);
CloseHandle(thread);
hRes = data->hr;
if (SUCCEEDED(hRes))
{
ATL::CComPtr<IUnknown> unk;
hRes = data->Unk.CopyTo(&unk);
if (SUCCEEDED(hRes))
{
hRes = unk->QueryInterface(riid, ppv);
}
}
}
delete data;
}
return hRes;
}
};
typedef CMyComCreator _CreatorClass;
static unsigned __stdcall UiThread(void * param)
{
CoInitializeEx(0, COINIT_APARTMENTTHREADED);
MyData * data = (MyData *)param;
ATL::CComObject<CMyDialog> * bb;
data->hr = ATL::CComObject<CMyDialog>::CreateInstance(&bb);
ATL::CComPtr<IUnknown> unk((IDispatch *) bb);
data->Unk = unk;
unk.Release();
data->Event.Set();
if (SUCCEEDED(data->hr))
{
CMessageLoop theLoop;
MessageLoop = &theLoop;
int nRet = theLoop.Run();
MessageLoop = NULL;
}
CoUninitialize();
return 0;
}
I needed to pack everything in a single DLL.
In which case, DllSurrogate is not the only way of doing this. There's also Rundll32:
INFO: Windows Rundll and Rundll32 Interface
This would allow you to run your own message loop inside the DLL's EntryPoint and have complete control over message processing, including PreTranslateMessage. You can copy the message loop logic from an ATL EXE server.
Bear in mind, there's still 32-bit and 64-bit version of "RunDll32.exe" in every 64-bit Windows OS. Use the one which matches the bit-ness of your DLL.

How to create a IconHandler used by the shell in c++?

I tried to code an icon handler in c++ but i have some issues to do this. I followed the turoriel from codeproject
The difference with this tutorial is i wanna code my dll with an ATL project from the wizard of visual studio (2013). So i create a new ATL project and i had a COM +1 class to this project (this the code of the header).
The problem is it seams that my dll is attach but is detach right after.
I'll put some code and more explication bellow :
extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
_AtlModule.InitLibId();
//_AtlModule.RegisterAppId();
}
return _AtlModule.DllMain(dwReason, lpReserved);;
}
This is my entry point of my dll. I did a lot of try and test on this entry point. I tried to write some log in function of the dwReason and this function is launch only when i compile. One time with the attribute DLL_PROCESS_ATTACH and an other time with the attribute DLL_PROCESS_DETACH. After that nothing seams to work even when i set my registry to call this dll in the IconHandler of my file.
I'll put my dllmain.h, my handler.h, my idl file and my rgs file. If you need more code to help me i'll put them later.
dllmain.h
class CQIIconDllModule : public ATL::CAtlDllModuleT< CQIIconDllModule >
{
public :
DECLARE_LIBID(LIBID_QIIconDllLib)
DECLARE_REGISTRY_APPID_RESOURCEID(IDR_QIHANDLER, "{7FFCD43D-9EB3-4F76-940C-98C333FB8A99}")
};
extern class CQIIconDllModule _AtlModule;
IconHandler.h
// QIHandler.h : Declaration of the CQIHandler
#pragma once
#include "resource.h" // main symbols
#include <ShlObj.h>
#include "QIIconDll_i.h"
#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
#endif
using namespace ATL;
// CQIHandler
class ATL_NO_VTABLE CQIHandler :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CQIHandler, &CLSID_QIHandler>,
public IQIHandler,
public IPersistFile,
public IExtractIcon
{
public:
CQIHandler()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_QIHANDLER)
DECLARE_NOT_AGGREGATABLE(CQIHandler)
BEGIN_COM_MAP(CQIHandler)
COM_INTERFACE_ENTRY(IQIHandler)
COM_INTERFACE_ENTRY(IPersistFile)
COM_INTERFACE_ENTRY(IExtractIcon)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
public:
// IPersistFile
STDMETHODIMP GetClassID( CLSID* ) { return E_NOTIMPL; }
STDMETHODIMP IsDirty() { return E_NOTIMPL; }
STDMETHODIMP Save( LPCOLESTR, BOOL ) { return E_NOTIMPL; }
STDMETHODIMP SaveCompleted( LPCOLESTR ) { return E_NOTIMPL; }
STDMETHODIMP GetCurFile( LPOLESTR* ) { return E_NOTIMPL; }
STDMETHODIMP Load( LPCOLESTR wszFile, DWORD )
{
USES_CONVERSION;
lstrcpyn ( m_szFilename, W2CT(wszFile), MAX_PATH );
return S_OK;
}
// IExtractIcon
STDMETHODIMP GetIconLocation( UINT uFlags, LPTSTR szIconFile, UINT cchMax,
int* piIndex, UINT* pwFlags );
STDMETHODIMP Extract( LPCTSTR pszFile, UINT nIconIndex, HICON* phiconLarge,
HICON* phiconSmall, UINT nIconSize );
protected:
TCHAR m_szFilename[MAX_PATH]; // Full path to the file in question.
};
OBJECT_ENTRY_AUTO(__uuidof(QIHandler), CQIHandler)
my idl file
// QIIconDll.idl : IDL source for QIIconDll
//
// This file will be processed by the MIDL tool to
// produce the type library (QIIconDll.tlb) and marshalling code.
import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(a817e7a2-43fa-11d0-9e44-00aa00b6770a),
dual,
pointer_default(unique)
]
interface IComponentRegistrar : IDispatch
{
[id(1)] HRESULT Attach([in] BSTR bstrPath);
[id(2)] HRESULT RegisterAll();
[id(3)] HRESULT UnregisterAll();
[id(4)] HRESULT GetComponents([out] SAFEARRAY(BSTR)* pbstrCLSIDs, [out] SAFEARRAY(BSTR)* pbstrDescriptions);
[id(5)] HRESULT RegisterComponent([in] BSTR bstrCLSID);
[id(6)] HRESULT UnregisterComponent([in] BSTR bstrCLSID);
};
[
object,
uuid(1A80BA8B-2932-4EB4-AA88-5216F92BBA33),
pointer_default(unique)
]
interface IQIHandler : IUnknown{
};
[
uuid(17AD604F-FDD1-453C-A2D2-EAD3FCC42AB5),
version(1.0),
custom(a817e7a1-43fa-11d0-9e44-00aa00b6770a,"{D32D9690-E6A4-44D8-A949-5F39D35269F8}")
]
library QIIconDllLib
{
importlib("stdole2.tlb");
[
uuid(D32D9690-E6A4-44D8-A949-5F39D35269F8)
]
coclass CompReg
{
[default] interface IComponentRegistrar;
};
[
uuid(7FFCD43D-9EB3-4F76-940C-98C333FB8A99)
]
coclass QIHandler
{
[default] interface IQIHandler;
};
};
rgs file :
HKCR
{
NoRemove CLSID
{
ForceRemove {D32D9690-E6A4-44D8-A949-5F39D35269F8} = s 'CompReg Class'
{
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Apartment'
}
TypeLib = s '{17AD604F-FDD1-453C-A2D2-EAD3FCC42AB5}'
Version = s '1.0'
}
}
}
rgs handler file :
HKCR
{
NoRemove CLSID
{
ForceRemove {7FFCD43D-9EB3-4F76-940C-98C333FB8A99} = s 'QIHandler Class'
{
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Apartment'
}
TypeLib = s '{17AD604F-FDD1-453C-A2D2-EAD3FCC42AB5}'
Version = s '1.0'
}
}
NoRemove qifile
{
NoRemove DefaultIcon = s '%%1'
NoRemove ShellEx
{
ForceRemove IconHandler = s '{7FFCD43D-9EB3-4F76-940C-98C333FB8A99}'
}
}
}
I hope i was clear in my explanation. If you need more information to response at my question just tell me i'll be fast with my answer. I'll thank you to take your time to help me.
Florian
EDIT :
See my test on my dllmain. cpp
BOOL ret = false;
FILE *file;
fopen_s(&file, "test.txt","a+"); /* apend file (add text to
a file or create a file if it does not exist.*/
if (dwReason == DLL_PROCESS_ATTACH)
{
fprintf(file,"%s","Initialize AtlModule\n"); /*writes*/
_AtlModule.InitLibId();
HRESULT hr = _AtlModule.RegisterAppId();
if (SUCCEEDED(hr))
{
fprintf(file,"%s","Registrer app succeeded \n"); /*writes*/
hr = _AtlModule.RegisterServer(TRUE, &CLSID_QIHandler);
if (SUCCEEDED(hr))
{
fprintf(file,"%s","RegisterServer succeeded \n"); /*writes*/
hr = _AtlModule.UpdateRegistryAppId(TRUE);
if (SUCCEEDED(hr))
{
fprintf(file,"%s","UpdateRegistryAppId succeeded \n"); /*writes*/
ret = true;
}
}
}
}
#ifdef _DEBUG
else if (dwReason == DLL_PROCESS_DETACH)
{
_AtlModule.UpdateRegistryAppId(FALSE);
_AtlModule.Term();
}//*/
#endif
if (dwReason == DLL_PROCESS_DETACH && lpReserved != NULL)
{
ret = true;
}
else if (dwReason == DLL_PROCESS_DETACH)
{
fprintf(file,"%s","Execption ! \n"); /*writes*/
}
fclose(file); /*done!*/
return ret;
The result in my test.txt :
Initialize AtlModule
Registrer app succeeded
RegisterServer succeeded
UpdateRegistryAppId succeeded
Execption !
Sombody here have a idee ?
I didn't found any solution to work my solution. So i write my handler in C# even if this is not the best way to do that because that call some native function.
I used the follow tutorial from code-project : NET-Shell-Extensions-Shell-Icon-Handlers
I hope this tutorial gonna help some people. If someone have the answer to my preview question i will be glad to know what i have to do.
Florian

Resources