Determining if currently renaming a file in Windows Explorer - windows

I am trying to check a Windows Explorer view to see if a file name is currently being renamed / edited when typing.
I have a system hook installed that monitors the keyboard for specific keystrokes and fires certain events. This is done in this manner:
If the keyboard hook sees the key pressed it fires a message to another thread and continue processing other system hooks.
Other thread receives the message and checks to see if an Explorer window is active and gets the interface to the IFolderView2.
Call IFolderView2::GetFocusedItem() to get the focused item in the folder view.
Check if the focused item is being renamed / is in edit mode (SVSI_EDIT) using IFolderView2:: GetSelectionState() - this is the part that fails
If not in rename mode perform an action on that file.
I've tried everything on Windows 7 but the SVSI_EDIT flag (0x00000002 specifically) is never returned. It's always (SVSI_FOCUSED | SVSI_SELECT) regardless of if the file is being renamed. Setting the SVSI_EDIT flag with works with IFolderView::SelectItem with the flag puts it into rename mode but I want to determine if it's in this mode already.
This has only been tested on Windows 7 x64 so far.
Does anyone know a way to determine if Explorer / the IFolderView etc. is currently in the rename file state? Any sneaky method will do if it's not possible through these interfaces.

If one file in in renaming mode, Windows will create a EDIT control at the position of the item. So things got straight:
Find the currently-focused control.
Get the CLASS of the control.
Check whether it's CLASS is an EDIT.
On CodeProject there is a great example about how to find the focused control. To get the CLASS name of that control, use GetClassName API.

Related

Can the last opened file location be directly altered?

As I understand it, when a file open dialog box (such as GetOpenFileName) is used, Windows will automatically remember where the last file was that was opened by the program, and Windows remembers these locations separately for each program. Is there a way to directly alter this, in order to cause the file picking dialog for program X to start in C:\Example\Directory?
I'm attempting to automate a program which has been programmed to work only through a GUI, and I don't have any access to the internals of this program (such as being able to alter how it calls the file picker). Instead, I'm using a mouse macro (via AutoHotkey). If I can be completely sure that the file picker will start in a particular place, I should be able to automate the rest with mouse clicks.
If you had access to the source code, I'd suggest you just change the lpstrInitialDir property of the OPENFILENAME passed to GetOpenFileName().
Outside of that, you'll want to change the registry keys for the MRUs:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32
What might make more sense, and might fix the issue you're having, is also changing the Working Directory so that the default location isn't "My Documents", if you're experiencing that.
Depending on the operating system, the results vary:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646839%28v=vs.85%29.aspx

Windows API hook, custom save as file dialog to save directly to webserver via POST

I want to write a custom save as dialog that is hooked into the File -> "Save As" of most Windows program. This custom dialog will allow the user to enter their username, password, destination folder and uploads the file to the web server via a POST. If the user clicks cancel, it will call the original file dialog.
I've been reading up about Windows API hooking and this is vaguely how I think I would approach this:
Intercept "Save As"
Display my custom dialog, return some temporary path on the drive
Let the program write file to the temporary path, assume it calls WINAPI CreateFile(...) for now
Read the temporary file and upload to web server
Clean up temporary file
But I still can't get my head around the steps required to pull this off. Assuming I can intercept the "Save As" and CreateFile function, how do I detect the CreateFile was called from a "Save As" and not just any random file creation? I can think of a hack where I keep track of the time difference of when the File dialog got open and CreateFile got called.
My alternative solution is to use the existing file dialog and create a special folder on the disk, that is constantly monitored. When a file gets written there it will call an external program that uploads the file. I haven't looked into how to do this yet. I suspect this is easier.
UPDATE
As a first baby step, I wrote a .NET task tray application that allows the user to enter their login details and a folder to monitor. Whenever a file gets dropped in there there it will upload to the web server. So far it seems to work. Now I just need to figure out how to add a nice shortcut to the left pane of the file dialog. Once that's done I think I got a solution I'm happy with.
There is no need to hook or patch anything. Create a shell namespace extension that supports IStorage::CreateStream and implements it by returning a stream that POSTs its data to the Web server. The user can then choose to save the file to your namespace extension in order to upload the file.
Hooking the standard save dialog requires you to inject a DLL into every running process and have it replace the import stub of the the Win32 API GetSaveFileName() function in the process's PE header (something anti-virus and anti-malware apps are not likely to be happy about).
Then there is the new-style save dialog that was introduced in Vista using the new IFileSaveDialog COM interface instead of GetSaveFileName(). For that, you would have to uninstall and replace Microsoft's default FileDialog COM object with a custom implementation.
That does not count custom-made save dialogs, which you are not likely to hook.
If, by some miracle, you can hook the dialog and have it return a custom path of your own creation, you don't need to hook CreateFile() itself, Just monitor the folder that you create for your purposes. Place it where it is unlikely that any other app (or user) besides you will write files to. You can create a custom subfolder in the user's or system'ss AppData folder for that purpose. You can use SHGetSpecialFolderPath() and/or SHGetKnownFolderPath() to find those folders.
The tricky part will be detecting when the file is finished being written to and has been closed. You will have to monitor the folder for changes, such as with ReadDirectoryChangesW() or SHChangeNotifyRegister(), and periodically open new/modified files for exclusive access. If a file is still open by someone else, you won't be able to open it yourself. But once you do open it, you can do whatever you want with it.

How to disable cut, copy, paste, rename, etc from the Windows Registry?

I'm trying to create a software in VB.Net as my uni project to disable the following from a Windows 7 pc. I think they have to be disabled from the context menu of the Windows Registry, but instead of disabling the whole context menu, I'd like to disable the following individually.
Cut, copy, paste, rename, delete, open, print, share, create shortcut, open with, send to, new, properties.
I want to give users the option of disabling them selectively/individually via checkboxes so those options will be disabled in the right-click of a mouse.
My problem is I don't know which is the right key to disable as the registry is so huge & some keys are similiarly named.
Could anyone help me to say what are the exact key locations of the above-mentioned right-click functions in the Windows Registry or how to go about this ?
The deep flaw in the assumptions made in this question is that the context menu is configured by registry entries. It is not. Windows allows modifying a window's context menu by sending the WM_CONTEXTMENU message. Code, not config. If you are not happy with the default implementation of that message then you subclass the window procedure and provide your own message handler for that message so you can display your own context menu. This is core to the way Windows works.
Modifying the context menu of a program you didn't write is possible too but much more complicated. You use SetWindowsHookEx() to inject a DLL into the other process. You cannot write a DLL like that in VB.NET, it requires native code. Because that process won't have the CLR loaded to run your managed code.

IFileSaveDialog - choosing folders in Windows 7

In Vista, I have been using an IFileSaveDialog to let users pick a "save-as" folder. Users export a folder of images, say, and need to choose a new or existing target folder.
Briefly, the code goes like this:
IFileSaveDialog* dialog; // created
dialog->SetOptions(FOS_PICKFOLDERS);
dialog->Show(NULL);
dialog->GetResult(&shellItem)
In Windows 7, the FOS_PICKFOLDERS option appears to have been disallowed (and is marked as such in the API). The return value on the SetOptions call is E_INVALIDARG. If I use a IFileOpenDialog, I'm allowed to set the folders option, but the user is prompted with an error when choosing a nonexistent folder (despite my setting flags suggesting not to do this).
Is there an alternate way to get the new IFileDialog to act as a "save folder" dialog?
[To head off some comments, the SHBrowseForFolder API still exists, but is still not an acceptable solution for our UI deciders.]
The reason for this can be found in the documentation:
FOS_PICKFOLDERS: Present the Open dialog offering a choice of folders rather than files.
Using FOS_PICKFOLDERS for "save" was never supposed to be supported - but Vista didn't enforce it. Use IFileOpenDialog instead and you're good to go.
You are picking an existing folder (not specifying a folder to create), so open was always the correct choice.
I haven't played around with the Windows 7 dialogs yet, but downloaded the Windows® API Code Pack just this morning as I am implementing the Thumbnail Toolbar and Icon Overlay in the application I am working on. It'll probably point you in the right direction.

Is it possible to replace the system open file dialog?

I want to replace the standard system open file dialog with the one I wrote, that means no matter within which programs you are opening a file, my dialog will be shown instead of the standard one, is this possible?
It seems that that there is no such API provided to accomplish this, is it possible to use some hooking technique, but this has to be reliable and not to be treated as spyware by anti-virus tools?
any other options?
If this is not possible, is it possible to add to the spacebar or toolbar in the standard open file dialog a button which invokes my dialog, which allow users select a file and in turn returns the path of the selected file to the "File name" input box of the standard dialog?
Any hits, links and code examples will be appreciated.
Starting in Vista, the FileOpen/FileSave dialogs are now "Common Item Dialogs" of which IFileOpenDialog & IFileSaveDialog are the two published implementations.
Since they're just COM objects with known CLSIDs you might get away with just replacing them by re-registering using their CLSIDs. Never tried something like that, might trip all sorts of alarm bells.
Pre-Vista file dialogs can be hooked in process, but I've never come across anything about global hooks or equivalent.
If you copy a file/folder to a dialog's filename field it usually pastes the full path anyway.
For example, if you have open both a program calling the standard open/save dialog box and also have a window open at the file or path that you want to work with (open from/save to), you can simply copy the file/folder from the explorer window, and then paste into the filename field of the dialog box, and it will insert the full path of the file/folder. No custom script is required!
Alternatively, for those programs that use custom dialog boxes where this step fails, copy the same file/folder in the window into the address bar of the same window (assuming it is visible). This will paste the full path, which you can copy again, and then paste this full path into the custom dialog box. I often use this when creating Office hyperlinks (Ctrl+K), because the Insert Hyperlink dialog does not work for the first method.
You can also use similar methods but paste into address bar fields and it works.

Resources