How to detect OneDrive online-only files - winapi

Starting from Windows 10 Fall Creators Update (version 16299.15) and OneDrive build 17.3.7064.1005 the On-Demand Files are available for users (https://support.office.com/en-us/article/learn-about-onedrive-files-on-demand-0e6860d3-d9f3-4971-b321-7092438fb38e)
Any OneDrive file now can have one of the following type: online-only, locally available, and always available.
Using WinAPI how can I know that the file (e.g. "C:\Users\Username\OneDrive\Getting started with OneDrive.pdf") is online-only file?

After years, I'm still using FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS attribute described here to determine if a file or a directory is completely present locally or not.
Microsoft docs says the following for FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS:
When this attribute is set, it means that the file or directory is not fully present locally. For a file that means that not all of its data is on local storage (e.g. it may be sparse with some data still in remote storage). For a directory it means that some of the directory contents are being virtualized from another location. Reading the file / enumerating the directory will be more expensive than normal, e.g. it will cause at least some of the file/directory content to be fetched from a remote store. Only kernel-mode callers can set this bit.
There are some advantages of FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS:
It can be used for both files and directories.
It can be set in kernel mode only, so there is no chance for anyone to set the attribute arbitrary.
And as it described in this answer, there are still some interesting undocumented attributes which can provide additional information about cloud files.
Note: I didn't accept Jonathan Potter's answer because I mentioned FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS attribute in comments and started using it a year earlier than he updated his answer.

To check for "online only" all you need is to call GetFileAttributes() and see if the FILE_ATTRIBUTE_OFFLINE attribute is set.
In fact this isn't new for OneDrive, that attribute has existed for a long time.
There are other OneDrive attributes available via the shell (although the property you need is PKEY_StorageProviderState rather than PKEY_FilePlaceholderStatus) but "online only" is easy to check for.
Edit: Another filesystem attribute, FILE_ATTRIBUTE_PINNED is new for Windows 10, and is used by OneDrive to indicate a file that's "always available".
Edit: As of 2019 it appears that OneDrive now uses FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS rather than FILE_ATTRIBUTE_OFFLINE, as suggested below.
Edit: PKEY_StorageProviderState was broken in Windows 10 1903, and still not fixed in 1909. It returns 4 ("uploading") for all files in any apps other than Explorer.

Take a look at the PKEY_FilePlaceholderStatus property for the file (at the shell level, not the file-system level). This blog post has a example program you can test. This question also hints to some undocumented properties you might want to take a look at.
Microsoft has a UWP example on MSDN.

Related

Standard location of system-wide configuration files of an app?

Since Windows Vista, our friends from Redmond are putting an end to the habit of storing configuration files in C:\Program Files\<AppName>\config.ini. Ok, they introduced Registry Virtualisation, but it's always better to fix your stuff, right?
I'm planning to fix a pre-Vista app which runs as a service, and which needs to maintain a machine-wide configuration file.
Where do I store the config file? And what would be the most portable/future-proof way of obtaining the path to that location?
You could store the values in the registry in something inheriting from \HKLM\ directly, which would give portability.
If there are a large number of values, or a complex structure to them, then you could store a file location in the registry, and store your configuration at that destination.
After improving my Google-fu starting from a related question, I think I've found the definitive answer in this microsoft blog post which actually describes much more than what I originally wanted to know.

ctime, mtime, holding directory, windows, linux

Let's clarify this once and for all. I tried to Google this but it seems this information can't be found in one place.
When a file is created or removed, the holding directory mtime changes on Windows and Linux both. ctime also changes on Linux bot not on Windows because there ctime is create time.
If a file is reopened and written to, the holding directory does not change. However, both on Windows and Linux the file mtime changes, and on Linux the ctime changes too, on Windows the ctime is create time.
Is this correct? What caveats are there? Are there exceptions over, say Windows network shares? Or Samba?
Edit: those who have voted to close this as off-topic, please leave a comment on which site do you think this is on topic. There are tons of mtime/ctime questions on Stackoverflow and just because I didn't include PHP snippets that rely on this knowledge it doesn't mean there are none :/
Think of it this way:
A directory is a file that holds pointers (or 'links') to files.
As of that:
Changing the content of a file will not affect the directory (unless the file is first deleted and then created again with the same name, as mentioned by Gabor Garami above)
Adding, Deleting or Renaming files will change the content of the directory-file which will cause its ctime/mtime to change as you have described, depending on the OS

GetOpenFilename api call in Windows 7 won't allow direct access to My Documents

In many of my Access (2002) programs I use the GetOpenFileNameA and GetSaveFileNameA functions from comdlg32.dll. I often set the initial directory to the user's My Documents folder (using calls to SHGetSpecialFolderLocation and SHGetPathFromIDListA from shell32). This all works fine under Windows XP.
However, I recently switched to Windows 7 as my development environment and have been getting the following error message:
You can’t open this location using
this program. Please try a different
location.
The function I use to get the My Documents location is returning the correct folder. However, even if I hard code that directory location into the GetOpenFileNameA call, I still get the error.
I came across this post: http://social.msdn.microsoft.com/Forums/en-US/windowsuidevelopment/thread/3391f1dd-25b0-4102-9d5c-58309cc72c9d but, even adapting it to work with Access instead of Excel, I had no luck.
EDIT: Suddenly this is no longer a problem for me. I suspect a windows update went out addressing this issue. Does anyone know if that's true or not?
EDIT: It turns out this is still a problem. Also, in case it helps in the troubleshooting I have found that I get this error message for any of the special folder locations (My Music, My Documents, etc). Also, if I change the location of the My Music folder to, say, C:\Test then I get this message when I try to open the folder C:\Test, while the folder C:\Users\Mike\Music (the original My Music location) opens without a hitch.
Windows 7 adds the concept of a "library", which is basically a virtual folder that includes the contents of at least two actual subdirectories. One place it uses the library is the "My Documents" folder, which (at least by default) is a library that includes both the user's documents directory ("c:\users\whoever\documents") and the public documents directory (C:\users\public\documents").
As such, the basic approach you're using simply can't work -- there is no path that denotes the Documents folder. The documents folder needs to be specified by a PIDL, not a path.
Edit: It's not clear what's going on if you can't open C:\users\user\Documents. A quick test in C++ works fine using code like:
OPENFILENAME data = {0};
wchar_t filename[256] = {0};
data.lpstrInitialDir = L"C:\\users\\jerry\\documents";
data.lStructSize = sizeof(data);
data.lpstrFile = filename;
data.nMaxFile = sizeof(filename);
GetOpenFileName(&data);
OTOH, there's no real need to specify the initial path -- the Documents folder is the default anyway.
The link I posted in my original question (http://social.msdn.microsoft.com/Forums/en-US/windowsuidevelopment/thread/3391f1dd-25b0-4102-9d5c-58309cc72c9d) held the answer after all. I'll summarize things here. To fix this behavior, you need to do away with the STRIPFOLDERBIT flag in the shell compatibility registry entry for all affected programs.
Keep in mind (and this is what tripped me up for so long) that 32-bit programs have entries in a special registry section if you have 64-bit windows. Here's the quick and dirty:
Rename STRIPFOLDERBIT to xSTRIPFOLDERBIT for the following keys (as applicable):
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\excel.exe
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\msaccess.exe
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\excel.exe
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\msaccess.exe

Set directory permissions with inheritance during application installation?

I found a thread on the Microsoft Forums where the answer tells how to set directory permissions using the LockPermission table. I tried it, but it doesn't seem to set the inheritance for any of the subdirectories. I need to be able to set the permissions for a particular folder that I create and have those permissions be inherited by all of the files and directories within and beneath it. Is there a way to do this without having to add a line in the LockPermission table for each and every directory (and file) that I want to affect?
For anyone looking to know the joys and pains of using MsiLockPermissionsEx, here is a tutorial, some best practices and a helper script. The helper script extracts SDDL from existing system resources - so you just use Regedit and Windows Explorer to set permissions and the helper script extracts them for you.
The article also discusses the challenge of supporting XP and Windows 7 permissions with a single package.
You can check it out here: http://csi-windows.com/toolkit/csigetsddlfromobject
You can either see if the MsiLockPermissionsEx support in MSI 5 handles this (and is an acceptable dependency for you as currently it's only available on Windows 7), or you can implement custom support. The LockPermissions support available in earlier versions of Windows Installer has the limitation you describe (and others).

Registry vs. INI file for storing user configurable application settings [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
I'm a new Windows programmer and I'm not sure where I should store user configurable application settings. I understand the need to provide a user friendly means for the user to change application settings, like an Edit | Settings form or similar. But where should I store the values after the user hits the Apply button on that form?
What are the pros and cons of storing settings in the Windows registry vs. storing them in a local INI file or config file or similar?
Pros of config file:
Easy to do. Don't need to know any Windows API calls. You just need to know the file I/O interface of your programming language.
Portable. If you port your application to another OS, you don't need to change your settings format.
User-editable. The user can edit the config file outside of the program executing.
Pros of registry:
Secure. The user can't accidentally delete the config file or corrupt the data unless he/she knows about regedit. And then the user is just asking for trouble.
I'm no expert Windows programmer, but I'm sure that using the registry makes it easier to do other Windows-specific things (user-specific settings, network administration stuff like group policy, or whatever else).
If you just need a simple way to store config information, I would recommend a config file, using INI or XML as the format. I suggest using the registry only if there is something specific you want to get out of using the registry.
Jeff Atwood has a great article about Windows' registry and why is better to use .INI files instead.
My life would be a heck of a lot easier if per-application settings were stored in a place I could easily see them, manipulate them, and back them up. Like, say... in INI files.
The registry is a single point of failure. That's why every single registry editing tip you'll ever find starts with a big fat screaming disclaimer about how you can break your computer with regedit.
The registry is opaque and binary. As much as I dislike the angle bracket tax, at least XML config files are reasonably human-readable, and they allow as many comments as you see fit.
The registry has to be in sync with the filesystem. Delete an application without "uninstalling" it and you're left with stale registry cruft. Or if an app has a poorly written uninstaller. The filesystem is no longer the statement of record-- it has to be kept in sync with the registry somehow. It's a total violation of the DRY principle.
The registry is monolithic. Let's say you wanted to move an application to a different path on your machine, or even to a different machine altogether. Good luck extracting the relevant settings for that one particular application from the giant registry tarball. A given application typically has dozens of settings strewn all over the registry.
There's one more advantage to using an INI file over the registry which I haven't seen mentioned:
If the user is using some sort of volume/file based encryption, they can get the INI file to be encrypted pretty easily. With the registry it will probably be more problematic.
According to the documentation for GetPrivateProfileString, you should use the registry for storing initialisation information.
However, in so saying, if you still want to use .ini files, and use the standard profile APIs (GetPrivateProfileString, WritePrivateProfileString, and the like) for accessing them, they provide built-in ways to automatically provide "virtual .ini files" backed by the registry. Win-win!
There's a similar question here that covers some of the pros and cons.
I would suggest not using the registry unless your application absolutely needs it. From my understanding, Microsoft is trying to discourage the use of the registry due to the flexibility of settings files. Also, I wouldn't recommend using .ini files, but instead using some of the built-in functionality to .Net for saving user/app settings.
Use of an ini file, in the same directory as the application, makes it possible to back it up with the application. So after you reload your OS, you simply restore the application directory, and you have your configuration the way you want it.
I agree with Daniel. If it's a large application I think I'd do things in the registry. If it's a small application and you want to have aspects of it user-configurable without making a configuration form, go for a quick INI file.
I usually do the parsing like this (if the format in the .ini file is option = value, 1 per line, comments starting with #):
static void Parse()
{
StreamReader tr = new StreamReader("config.ini");
string line;
Dictionary<string, string> config = new Dictionary<string, string>();
while ((line = tr.ReadLine()) != null)
{
// Allow for comments and empty lines.
if (line == "" || line.StartsWith("#"))
continue;
string[] kvPair = line.Split('=');
// Format must be option = value.
if (kvPair.Length != 2)
continue;
// If the option already exists, it's overwritten.
config[kvPair[0].Trim()] = kvPair[1].Trim();
}
}
Edit: Sorry, I thought you had specified the language. The implementation above is in C#.
As Daniel indicated, storing configuration data in the registry gives you the option to use Admin Templates. That is, you can define an Admin Template, use it in a Group Policy and administer the configuration of your application network-wide. Depending on the nature of the application, this can be a big boon.
The existing answers cover a lot of ground but I thought I would mention one other point.
I use the registry to store system-wide settings. That is, when 2 or more programs need the exact same setting. In other words, a setting shared by several programs.
In all other cases I use a local config file that sits either in the same path as the executable or one level down (in a Configuration directory). The reasons are already covered in other answers (portable, can be edited with a text editor etc).
Why put system-wide settings into the registry? Well, I found that if a setting is shared but you use local config files you end up duplicating settings. This may mean you end up needing to change a setting in multiple places.
For example, say Program A and Program B both point to the same database. You can have a "system-wide" registry setting for the connection string. If you want to point to a different database, you can change the connection string in one place, and both programs will now run against the other database.
Note - there is no point in using the registry in this way if two or more programs don't need to use the same values. Such as, Program A and Program B both needing a database connection string that may be the same, but not always. For example, I want Program B to now use a test database but Program A should carry on using a production database.
With the above example, you could have some local configuration override system-wide settings but it may start getting overly complicated for simple tasks.
The registry is optimized for quick access and easy update, and it's the only way to do certain Windows-specific things like associating with an extension. And you can ignore the argument about deleting a single directory to uninstall your program - Windows Vista won't let you modify files in the Program Files directory, so your config will need to go in a different folder anyway.
There's a general guideline for Windows programming - do things the way Microsoft expects you to, and your life will be a lot easier.
That said, I can see the appeal of the INI file, and I wouldn't blame anyone for considering it.
There is one drawback to ini or config files and that is locating them if the user has the option to select where the program is installed.
Other disadvantage of using the registry is that it is a pain if you are working in a mixed environment of 32 and 64 bit applications, as the system call for accessing the registry will randomly(*) add \Wow6432Node\ to your registry path making you crazy while debugging.
(*of course not randomly, but very easy to get lost)
Advantages:
Replacement for a large number of configuration files.
Common administrative functions at a central point.
Almost any data can be saved by applications / drivers.
In contrast to configuration files, code sequences can even be saved.
Access faster than files because the database is indexed.
Access can be logged using the RegMon utility
Disadvantages:
Difficult to work with in the absence of graphical configuration programs.
Direct changes using the registry editor can create inconsistent states produce.
Incomplete uninstallers leave “reminiscences” in the registry Cause problems, e.g. with a new installation.
Installed applications are difficult to export to other PCs.
Chronically poorly documented.
Proprietary structure, therefore not suitable for standard DB access (e.g. SQL)
Computer-specific, therefore not portable to other computers.
Insufficient protection of the registry: depends on the configuration.

Resources