3

I want to determine programmatically if my shell extension is called as a context menu handler or a drag-n-drop handler. I have registered my shell extension in proper location with same CLSID.

Registry:

[HKEY_CLASSES_ROOT\*\shellex\ContextMenuHandlers\{E991C840-C1EB-455C-AD64-282473005C58}]
@="Test Context Menu"

[HKEY_CLASSES_ROOT\Directory\shellex\DragDropHandlers\TestDragDrop]
@="{E991C840-C1EB-455C-AD64-282473005C58}"

I have no problem with registry, my extension is loaded.

I think best place to check want be in DllGetClassObject or in IShellExtInit::Initialize.

user2120666
  • 579
  • 1
  • 4
  • 16
  • "I have registered my shell extension in proper location with same CLSID." - what does that mean? What location is that (post the registry key paths). – sashoalm Mar 06 '14 at 16:45
  • Also, post some code. Where from do you want to determine that? From which entry-point? Do you mean from `IContextMenu::InvokeCommand`? – sashoalm Mar 06 '14 at 16:51
  • 2
    "I have two businesses, a pizzeria and a hair salon. I put them in the phone book with the same telephone number. When somebody calls the number, how do I know whether they are calling to order a pizza or to schedule a haircut?" Answer: Get two phone numbers. Use one for the pizzeria and one for the hair salon. Translation: Register two CLSIDs, one for the context menu and one for the drag-drop handler. – Raymond Chen Mar 06 '14 at 17:10
  • @RaymondChen: Thanks,by you already know that Microsoft uses this behaviour in own products: SendTo is context menu + drag and drop with same CLSID, also .LNK handler have same CLSID for context menu+drag and drop. – user2120666 Mar 06 '14 at 17:13
  • Also, from third-party extension, hardlink shell extension http://schinagl.priv.at/nt/hardlinkshellext/linkshellextension.html may also same CLSID for context, drag-n-drop and property sheet. – user2120666 Mar 06 '14 at 17:17
  • @user2120666: context menu handlers and property sheets use different interfaces (`IContextMenu` vs `IShellPropSheetExt`), so a single CLSID can implement them both. But a drag&drop handler does not have a distinct interface of its own, it merely uses `IShellExtInit`, which is not enough to differentiate with. – Remy Lebeau Mar 06 '14 at 19:25
  • Yes, this is point of this question. – user2120666 Mar 06 '14 at 19:29
  • 1
    "I want to combine my pizzeria and hair salon into a single business. When I answer the phone, I just wait for the caller to say 'I'd like to order a pizza' or 'I'd like to schedule a haircut', and some callers even say 'I'd like to do both.' That's okay, because my business can do both." That's what SendTo does. It doesn't know whether it is being created as a context menu or as a drop target. But if somebody asks for a context menu, it provides a context menu. If somebody asks for a drop target, it provides a drop target. If somebody asks for both, *it does both*. – Raymond Chen Mar 06 '14 at 19:42
  • @RaymondChen: Exact problem is setting different text in QueryContextMenu (context menu vs. drag drop menu). Like as 'Create shortcut' vs. 'Create shortcut here' – user2120666 Mar 07 '14 at 11:21
  • Then go back to the two-phone-number model. You can have a common base class that both implementations derive from. I don't see where SendTo or lnk registers as a DragDropHandler. They are just context menu handlers. – Raymond Chen Mar 07 '14 at 16:36

2 Answers2

3

You can detect type of extension with which shell wants to work only inside IShellExtInit.Initialize. For context menu handler pidlFolder is zero, for drag and drop handler pidlFolder is PIDL of folder.

Denis Anisimov
  • 3,297
  • 1
  • 10
  • 18
  • Not exactly true, for background context menu is pidlFolder set too. – Xearinox Mar 06 '14 at 20:42
  • I agree with you but in case of problem of @user2120666 it does not matter because context menu registered under * key will not be called when user call context menu of folder background. – Denis Anisimov Mar 06 '14 at 21:19
  • Don't try to predict the future based on circumstantial evidence. – Raymond Chen Mar 06 '14 at 21:23
  • @RaymondChen: Could you explain? – Denis Anisimov Mar 06 '14 at 21:28
  • Well, for example, pidlFolder being null could also mean that it's a property sheet handler. Your answer works only if the two things you need to distinguish are a nonfolder context menu and a nondefault drag-drop handler. it doesn't generalize. – Raymond Chen Mar 06 '14 at 22:48
  • In case of property sheet handler we can detect such shell request inside IClassFactory2::CreateInstanceLic or OurObject.QueryInterface. First riid will be IID_IShellPropSheetExt. The only situation as I know which we can not process correctly is described by @Xearinox. I agree with you that it is better to register different CLSID for each handler. But in some cases we can break the game rules but we must understand all rules and understand why we want to break the rules. – Denis Anisimov Mar 07 '14 at 07:09
  • Now upwote, I wait one day for another answer. – user2120666 Mar 07 '14 at 11:22
0

If you use the same CLSID for multiple extensions, then it does not know which extension is being instantiated, except maybe in QueryInterface() when the system queries for IContextMenu. If you really need to differentiate, it is best to just use separate CLSIDs, like Raymond Chen said. They can map to the same DLL, but that gives your code a chance to know which CLSID is being instantiated.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770