Search code examples
windowsqtqfile

Why does my Qt application write to protected locations even in non-admin access privilege?


I am using Qt 5.4 on Windows. I encountered a strange issue. I tried to write a file to the program files directory while in non-admin user access level. I expected it not to write. But it wrote! No errors at all. Okay, but what's really strange is that only my program can 'see' that file but explorer doesn't show it neither did it show up when I tried dir, dir /ah or ls.

This is what explorer can seeThis is what explorer can see

This is what my program can seeThis is what my program can see And mind you, my program can see that file every time I start it and browse to that folder.

What on Earth is going on here?


Solution

  • Why is that happening?

    File Virtualization. File virtualization is a technique that Windows Vista+ OSes use to address the situation where an application wants to write to a location which is writable only by the administrators (like C:\Program Files or C:\Windows).

    When an application writes to such a system location Windows redirects all such file operations to a Virtual Store directory, which is located at %LOCALAPPDATA%\VirtualStore. Later, when the application reads back this file, the computer will provide the one in the Virtual Store. This way Windows 'fools' the program into believing that it read from and wrote to the protected location whereas actually it is only dealing with a virtual location.

    How to solve this 'problem'?

    The Manifest.

    The manifest is an XML file that can be embedded into the application. It tells Windows that the application is UAC-aware, and that it therefore should not do any file virtualization. So, now if the application attempts to access protected resources, then these operations will simply fail but the OS won't virtualize. When your application includes an application manifest with a requestedExecutionLevel value specified, Windows's virtualization of the registry and file system will be switched off.

    An example manifest file:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
        <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
        <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
            <security>
                <requestedPrivileges>
                    <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
                </requestedPrivileges>
            </security>
        </trustInfo>
    </assembly>  
    

    What to actually do?

    There are a few different ways to add a manifest file to a Qt app. I'll mention only one - which I feel is the easiest. You may add the other ways to this answer if you know.

    1. Create a manifest file (you can even use the one given above).
    2. Ensure that the requestedExecutionLevel tag is present (otherwise virtualization won't be turned off).
    3. Execute mt.exe -nologo -manifest <your manifest file> -outputresource:<your executable>;#1*.
    4. Done.

    *I found the mt.exe file in "C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\, it may be slightly different for you but it will surely be in the Microsoft SDKs\Windows folder


    Sources
    1. Qt cannot cannot create/write to C:\
    2. http://msdn.microsoft.com/en-us/library/bb756960.aspx
    3. http://blog.strixcode.com/2010/08/embedding-application-manifest-and.html
    4. http://qt-project.org/forums/viewthread/36726