Increase number of characters in filename field of GetOpenFileName file selection dialog - winapi

Our app allows multiple files to be selected in a file selection dialog which is shown via the GetOpenFileName function (this question also applies to folks using CFileDialog, etc...)
There appears to be a limit to the number of characters that can be typed into the filename field (259 seems to be the magic number - not sure why).
We have tried changing the following members of the OPENFILENAME structure:
lpstrFile - point to our own buffer, sized at 4K bytes
nMaxFile - set to the size of lpstrFile (we are compiling ANSI, so this is effectively 4000
But these values appear to not increase the input width of the filename field in the dialog.
I am going to experiment with sending a EM_SETLIMITTEXT message to the control, but wanted to know if anyone else has a solution.
EDIT - solved this myself: solution I can't accept out my own answer, but here it is for posterity. If anyone else has a better solution, please post it - or feel free to mod up my solution so future searchers will find it at the top.

Turns out that the edit control (At least in my development environment) is a combo box, so EM_SETLIMITTEXT isn't appropriate.
Instead, I tracked down the combo box using GetDlgCtrl on the parent of the file open dialog (I do this in the OnInitDialog handler), cast it to CComboBox*, then call LimitText() to set the limit.
This could also be done by sending a CB_LIMITTEXT message to the control for those of you who are not working with CFileDialog. The appropriate value here is most likely the OPENFIILENAME.nMaxFile value that is passed in.

From Naming a File or Directory on MSDN:
In the Windows API (with some exceptions discussed in the following paragraphs), the maximum length for a path is MAX_PATH, which is defined as 260 characters.
Even if you could coerce longer strings out of the dialog, you may run into trouble down the line when using APIs that have been coded against MAX_PATH.
The docs go on to say:
The Windows API has many functions
that also have Unicode versions to
permit an extended-length path for a
maximum total path length of 32,767
characters. This type of path is
composed of components separated by
backslashes, each up to the value
returned in the
lpMaximumComponentLength parameter of
the GetVolumeInformation function. To
specify an extended-length path, use
the "\\?\" prefix. For example,
"\\?\D:\<very long path>". (The
characters < > are used here for
visual clarity and cannot be part of a
valid path string.)

I believe this is a hard limit that cannot be bypassed. The only time it should matter is when you want to select more than one file, since the limit is enough for the maximum file name length.
I have added an "All Files" button to these dialogs for opening all of the files in a folder; that's the only workaround I have found.

Related

For the use of the LocalizedResourceName property

I wish to customize my own folder style, I tried to make the folder get remarks by modifying the LocalizedResourceName property in desktop.ini.
I try to set LocalizedResourceName to a Chinese string. But it is displayed as garbled characters when it is actually displayed.
I noticed the following code in the desktop.ini of the system folder:
LocalizedResourceName=#%SystemRoot%\system32\shell32.dll,-21798
So I try to write a .dll file by myself, encapsulate the icon and string, and use it.
I already know how to make a resource-only dll file, but I don't know how to get a certain resource in the file. (ie, get the number -21798 in the above example code)
How should I do ?
By convention, a positive resource number is an index (0 is the first resource etc.) and negative numbers are resource ids. In this specific case, it is the string resource with the id of abs(-21798) that Windows would pass to LoadString.
If you want to create your own .dll, add a string with an id of 2 for example (any number between 2 and 0xffff) and in your .ini you would use #c:\path\mydll.dll,-2.
Before you go to all this trouble, just try saving the .ini as UTF-16 LE (Unicode in Notepad) and use Chinese strings directly without the #.

How to prevent specific line/s inside a notepad file from being edited?

I have a file that can be opened thru notepad application.
Basically, this file(which can be opened thru notepad) is created by a software and that software uses the values inside that file to run. You can edit the values inside the file using its software.
I just want specific lines(values) to be restricted from being edited because I am implementing strict values inside that file that no one will be able to edit except me.
Is there any clever way to restrict specific lines inside that file from being edited?
I tried the basic way - I used the change permission read/write on that file but I can't change ANY values inside the file which is undesirable.
Note: I have very little to no experience about python, c++, or java but any suggestion will give me idea to learn from it.
Edit:
Here's an example inside the file:
[Type Data]
Comment=Standard Dispense
[Shared_A]
802=1
807=750
11=0
12=0
.
What I want is restrict the value from row/column "807" which is equal to number 750.
I want this number 750 not to be edited even from the software so that other people will not mess it up. I want to set this value as standard value.
Is there any program that you can write inside that file so that it cannot be edited from the software unless I open that file and edit it?
I work from a production/manufacturing company that uses the software that is used for dispensing.
A text file is simply a sequence of bytes that represent code units to encode code points in any given character set. Every byte value is a potentially legal character encoding, leaving no values to encode additional semantics (like guard regions).
With that it should be obvious that there is nothing you can do to partially limit editing of a file using a standard text editor. Whatever problem you are trying to solve, this is not a solution. Next time around you might want to ask about the problem you are trying to solve rather than your proposed solution.

Delphi TOpenDialog/TSaveDialog last used path

Referring my question to this answer: https://stackoverflow.com/a/4016075/698266, in particular step 3 says "Otherwise, if the application has used an Open or Save As dialog box in the past, the path most recently used is selected as the initial directory."
Where does Windows save this information?
Note: by experimenting, it seems to be linked to the application file name without its path - i.e. the same executable copied in different directories "sees" the same last path information, while changing the exe file name makes the dialogs point to the user's Documents directory.
My actual interest is for testing purposes. I need to "reset" this information in order to test my application in conditions similar to a first run.
Windows XP uses HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\LastVisitedMRU and the format of each item seems to be ExeFilename+Path with both strings zero terminated and in UTF-16LE format. The MRU list is stored as a string named MRUList.
Newer versions of Windows uses HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\LastVisitedPidlMRU and HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\LastVisitedPidlMRULegacy and the format seems to be ExeFilename+ItemIdList (ExeFilename in UTF-16LE and zero terminated). The MRU list seems to be a list of DWORDs in a binary value named MRUListEx and the list is terminated by 0xffffffff.
I would assume that the change happened in Vista because that is when the new IFileDialog was added. LastVisitedPidlMRULegacy is probably used when GetOpen/SaveFileName is called with a custom template and/or hook function.
I finally found the answer myself.
For Windows 10 (this may be different in different versions of Windows, as David pointed up) there's a list of values in the registry that keep track of the executable name and its associated last "visited" path.
The list can be found in this key:
HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\LastVisitedPidlMRU
In order to reset the default open/save path for a particular program, you have to find the value whose data string (UNICODE) starts with your executable name and delete it. If you watch at the data string, you'll notice that the last used path is there, after the executable name.

What is the internal format of the binary registry keys under LastVisitedPidlMRU and LastVisitedPidlMRULegacy?

The first part is the app exe name in null-terminated Unicode, which is easy enough. Past that, each level of the path is included, first in non-Unicode, then Unicode (except for the path root/drive, which is just non-Unicode), but separated by unknown data structures.
My underlying problem is that the .Net Reportviewer control's UI export button calls the common dialog, but the control doesn't expose any way of setting the initial folder. I'd like to reliably read/write these keys to manage default open/save behavior.
Example registry key dump (app is notepad.exe, path is "C:\Stuff\DLTemp\HattoriHanzo"):
"10"=hex:6e,00,6f,00,74,00,65,00,70,00,61,00,64,00,2e,00,65,00,78,00,65,00,00,\
00,14,00,1f,50,e0,4f,d0,20,ea,3a,69,10,a2,d8,08,00,2b,30,30,9d,19,00,2f,43,\
3a,5c,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,4c,00,31,00,\
00,00,00,00,87,48,c0,8a,10,00,53,74,75,66,66,00,38,00,08,00,04,00,ef,be,7b,\
44,5a,69,87,48,c0,8a,2a,00,00,00,1f,d8,01,00,00,00,ca,04,00,00,00,00,00,00,\
00,00,00,00,00,00,00,00,53,00,74,00,75,00,66,00,66,00,00,00,14,00,50,00,31,\
00,00,00,00,00,87,48,b1,95,10,00,44,4c,54,65,6d,70,00,00,3a,00,08,00,04,00,\
ef,be,1c,45,60,7e,87,48,b1,95,2a,00,00,00,61,5b,02,00,00,00,62,00,00,00,00,\
00,00,00,00,00,00,00,00,00,00,00,44,00,4c,00,54,00,65,00,6d,00,70,00,00,00,\
16,00,5e,00,31,00,00,00,00,00,87,48,ca,9a,10,00,48,41,54,54,4f,52,7e,31,00,\
00,46,00,08,00,04,00,ef,be,87,48,ab,90,87,48,ca,9a,2a,00,00,00,e3,e3,04,00,\
00,00,0e,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,48,00,61,00,74,00,74,\
00,6f,00,72,00,69,00,48,00,61,00,6e,00,7a,00,6f,00,00,00,18,00,00,00
You can decode the remaining bytes using the SHGetPathFromIDListW Windows API call.
For example, see the C# implementation of it at https://svcperf.codeplex.com/SourceControl/latest#src/Viewer/UIUtils/MruFileHelper.cs , but that class decodes OpenSavePidlMRU, which doesn't contain the executable name. You can do the same with the remaining bytes that you get from LastVisitedPidlMRU.

"TCHAR cFileName[MAX_PATH];" - mistake in the MSDN library?

http://msdn.microsoft.com/en-us/library/windows/desktop/aa365740%28v=vs.85%29.aspx
cFileName
The name of the file.
The value of MAX_PATH is the same as almost the same as _MAX_FNAME, but using the first is misleading in this case. Anyway, if they meant the full path with name, should it be cFileName[MAX_PATH+_MAX_FNAME];? What was the purpose of using MAX_PATH?
The MAX_PATH constant represents the maximum length of an entire path, including the file name and the extension. It is irrelevant whether it is a relative path, a fully-qualified path, or even just a file name; they all have the same maximum length.
Thus, you would never see MAX_PATH + _MAX_FNAME because that would exceed the maximum length allowed for a path.
You'll find pretty much everything you ever wanted to know about paths in Win32 in this article. Note that some APIs (these will generally be called out explicitly in the docs ) accept long path names, indicated with a special prefix, which are not subject to the limitations of MAX_PATH.
The function signature is correct in this case. Sometimes, though, there are snippets of sample code on MSDN that accompany the docs, and this sample code ranges anywhere from stylistically curious to an utter abomination. It's always worth using a good healthy dose of common sense when trying to adapt sample code you find.
There's no mistake here. In Windows APIs that are subject to limits on length, the maximum length of a name is (usually) MAX_PATH. It doesn't matter whether the name is a fully specified absolute path, a relative path, or just a file name, the length limit is still MAX_PATH.
It may well be that the underlying file system has different limits. It's perfectly plausible that the native file system limit could be less than 260. But if the API declares a limit of 260 characters, then that's the limit when using that particular API.
If ever you think that the MSDN library is incorrect, it's easy enough to check. Take a look at the definition in the Windows header file and compare it with that given in the MSDN library. Invariably you will find that the MSDN library is accurate.

Resources