Click here to Skip to main content
15,889,096 members
Articles / Programming Languages / Shell
Tip/Trick

When A File Is Not A File

Rate me:
Please Sign up or sign in to vote.
4.77/5 (14 votes)
13 Nov 2016CPOL2 min read 16.7K   207   7   1
Getting information about a file that does not yet exist

Introduction

This code is based around the excellent article on MSDN, Creating a simple pidl: For the times you care enough to send the very fake[^], who's ideas I converted to C#. It describes how to fool the Windows shell into believing a particular file exists, when in fact it is not there. This can be useful in order to discover how the shell is going to handle this file - What icon will it show? What sort of details are available?

Background

I am looking at setting various properties for files as I write the files. I thought that it would be nice to collect these properties before the file was saved, so I looked into getting what properties were available for particular file types. Although this system does not supply all of those answers, it was a path I went down in during the research, and I thought that this was worthy of its own article.

How It Works

When the shell obtains information for a file, it seeks it out in the file system, receiving a WIN32_FIND_DATA structure containing basic details about the file. What we do here is attach an IBindCtx to the shell, telling it not to bother looking for this particular file, but to ask our component for the WIN32_FIND_DATA instead. However the structure we pass to the shell is not real - we've just made it up. The shell still believes us, however, and uses our fake data as if it were a real file.

Under the covers, this is handled by our implementation of IFileSystemBindData, which provides the shell with the WIN32_FIND_DATA upon request. Once we have provided the shell with this, we then ask it to produce a PIDL for our fake file, which is a series of bytes that identifies the item to the shell. From this identifier, we can as the shell anything we want out the file it represents. This is all accomplished in just a few lines of code.

C#
void CreateBindCtx(out IBindCtx pbc) {
    System.Runtime.InteropServices.ComTypes.BIND_OPTS bo =
                new System.Runtime.InteropServices.ComTypes.BIND_OPTS() {
        cbStruct = Marshal.SizeOf(typeof(System.Runtime.InteropServices.ComTypes.BIND_OPTS)),
        dwTickCountDeadline = 0,
        grfFlags = 0,
        grfMode = STGM_CREATE
    };
    try {
        CreateBindCtx(0, out pbc);
        pbc.SetBindOptions(ref bo);
        pbc.RegisterObjectParam(STR_FILE_SYS_BIND_DATA, (IFileSystemBindData)this);
    }
    catch {
        pbc = null;
        throw;
    }
}

void CreateSimplePidl(string path) {
    IBindCtx pbc;
    uint sfgao;
    CreateBindCtx(out pbc);
    SHParseDisplayName(path, pbc, out _ppidl, 0, out sfgao);
}

Using the Code

Once the PIDL has been created, it can be used in a multitude of shell functions and objects. In this example, I have exposed two methods - one to create an IShellItem object, which provides access to information about the fake file itself, and one to create an IShellFolder object, to supply information about the folder that contains this fake file, and how it would display it. In the demo, I use these objects to obtain basic properties about the file (IShellItem2.GetPropertyStore), and to get the icon for the file (IShellFolder.GetUIObjectOf). The shell documentation provides a lot more that could be achieved by this.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Australia Australia
Been programming for 40 years now, starting when I was 13 on DEC PDP 11 (back in the day of paper tape storage, and hex switch boot procedures). Got right into micro-computers from an early age, with machines like the Dick Smith Sorcerer and the CompuColor II. Started CP/M and MS-DOS programming in the mid 1980's. By the end of the '80's, I was just starting to get a good grip on OOP (Had Zortech C++ V1.0).

Got into ATL and COM programming early 2002. As a result, my gutter vocabulary has expanded, but it certainly keeps me off the streets.

Recently, I have had to stop working full time as a programmer due to permanent brain damage as a result of a tumour (I just can't keep up the pace required to meet KPI's). I still like to keep my hand in it, though, and will probably post more articles here as I discover various tricky things.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Farhad Reza15-Nov-16 1:19
Farhad Reza15-Nov-16 1:19 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.