0

I hooked the CopyItems method of IFileOperation to monitor/intercept file copy in windows. My problem is how can i retrieve the full file name from IShellItem(last param of CopyItems)

function New_CopyItems(p: Pointer; punkItems: IUnknown;psiDestinationFolder: IShellItem): HResult; stdcall;

The psiDestinationFolder have a method called GetDisplayName that return only the folder name of current file was begin copied!! But i want to get full file name and don't know what i should to do !? There is any other method to help me getting full name ?? Or i have to using another API ....?

Excuse me if my English is bad!

Kamran
  • 387
  • 1
  • 3
  • 19

1 Answers1

2

The CopyItems method copies potentially multiple items. So right off the bat you are mistaken looking for a single file name. This is a very complex API and you do need to read the documentation carefully and understand clearly how the function works.

The psiDestinationFolder parameter is an IShellItem that identifies the destination. Use the GetDisplayName method to get the file path.

The other parameter, punkItems is more complex. It is documented like this:

Pointer to the IUnknown of the IShellItemArray, IDataObject, or IEnumShellItems object which represents the group of items to be copied. You can also point to an IPersistIDList object to represent a single item, effectively accomplishing the same function as IFileOperation::CopyItem.

This is telling you that there could be an IShellItemArray, IDataObject, IEnumShellItems or a IPersistIDList object behind the IUnknown interface that you receive. And that there could be multiple items in that single object, each one to be copied to the destination folder. You will need to query punkItems for each possible interface in turn until you find out which of these possibilities you have to deal with. And then handle each one with special code. In order to test this you'll need to write code that calls CopyItems with each of the possible interfaces. You'll find out how to do all of this from the documentation of each of the four interfaces. If you don't already know shell programming and COM well, expect to do so by the time you complete this work.

Finally, I doubt that this is a very good way to detect file copying. Files are copied using many different APIs. And IFileOperation.CopyItems is but one of them. If you only hook IFileOperation.CopyItems then you'll miss a lot of file copy operations.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Davide, The punkItems can help me to get the file path of source file ! For doing this i should using `punkItems.QueryInterface(IID_IShellItemArray, _ShellItemArray)` to covnert punkItems to `ShellItemArray` and then get current file path from `ShellItemArray` ! but `QueryInterface` always return false ! can you help me to convert ? – Kamran Jul 21 '14 at 06:36
  • Please read my answer, and the documentation again. Read very carefully and understand that punkItems can be an object that does not support IShellItemArray. – David Heffernan Jul 21 '14 at 06:39
  • I read your answer, I test for converting to `IDataObject` but only return false ! `punkItems.QueryInterface(IID_IDataObject, _DataObject)` ! – Kamran Jul 21 '14 at 06:41
  • Keep working through the list. However, my final paragraph contains the best advice. – David Heffernan Jul 21 '14 at 06:42
  • Thanks, About your final paragraph: I found hooking `ZwReadFile` and `ZwWriteFile` the best way ! it works perfectly but its hard to distinguish FileCopy/FileCut to other file operation! – Kamran Jul 21 '14 at 06:48
  • Your meant of List is `IPersistIDList` ? – Kamran Jul 21 '14 at 08:25
  • You don't know what it is. According to the documentation, it could be any of the four interfaces listed. – David Heffernan Jul 21 '14 at 08:32
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/57665/discussion-between-user3725553-and-david-heffernan). – Kamran Jul 21 '14 at 10:54