Click here to Skip to main content
11,566,149 members (48,980 online)
Click here to Skip to main content

Getting and setting desktop folder names

, 24 Jan 2003 CPOL 74.6K 740 35
Rate this:
Please Sign up or sign in to vote.
Gives you copy/paste-able functions to retrieve the localized folder names, and to set/get user-defined folder names for dekstop folders

Introduction

For a certain application we were developing, we needed to retrieve the names of some of the common shell folders on the desktop like My Computer, Recycle Bin etc. We soon discovered that by default each OS comes with some pre-defined names depending on what Language version of the OS was used. These strings were stored inside Shell32.dll. But the user was free to rename any of these folders, and when he did that the new strings were stored in the registry. I do not know, how many people will find this code useful, but in case someone ever encounters a situation where he needs to do this, he need not spend the long hours we had to spend before we discovered that this was simply a matter of reading Shell32.dll and the registry. I've written some functions which you can use in your programs directly, by including a single header file.

Typical Usage

// This will retrieve the localized
// names stored in Shell32.dll
cout << "Localized folder names\r\n";
cout << "------------------------------\r\n";
cout << GetLocalizedName(MyComputer) << "\r\n";
cout << GetLocalizedName(MyDocuments) << "\r\n";
cout << GetLocalizedName(NetworkNeighbourhood) << "\r\n";
cout << GetLocalizedName(RecycleBin) << "\r\n";
cout << GetLocalizedName(InternetExplorer) << "\r\n";

cout << "\r\n";

// Let's change the user defined names
// that are stored in the registry
SetCustomName(MyComputer,"Nish's Computer");
SetCustomName(RecycleBin,"Trash Can");

// This retrieves the user defined names
// from the registry
cout << "User-defined folder names\r\n";
cout << "------------------------------\r\n";
cout << GetCustomName(MyComputer) << "\r\n";
cout << GetCustomName(MyDocuments) << "\r\n";
cout << GetCustomName(NetworkNeighbourhood) << "\r\n";
cout << GetCustomName(RecycleBin) << "\r\n";
cout << GetCustomName(InternetExplorer) << "\r\n"; 

The Functions

For all three functions I am using a custom enum to specify the desktop folder

enum IconFolder
{
    MyComputer,
    MyDocuments,
    NetworkNeighbourhood,
    RecycleBin,
    InternetExplorer
};

GetLocalizedName

CString GetLocalizedName(IconFolder folder)
{
    HMODULE sh32lib = LoadLibrary("Shell32.dll");
    char buff[256];

    switch(folder)
    {
    case MyComputer:
        LoadString(sh32lib,9216,buff,255);
        break;
    case MyDocuments:
        LoadString(sh32lib,9227,buff,255);
        break;
    case NetworkNeighbourhood:
        LoadString(sh32lib,9217,buff,255);
        break;
    case RecycleBin:
        LoadString(sh32lib,8964,buff,255);
        break;
    case InternetExplorer:
        LoadString(sh32lib,9222,buff,255);
        break;
    default:
        strcpy(buff,"Invalid Folder Request");
        break;
    }

    FreeLibrary(sh32lib);
    return CString(buff);
}

As you can see, all I do is to load strings from Shell32.dll, the string table entry identifiers are hard coded and I have tested this on Windows XP Home and Professional. I do believe that they will be the same for Windows 2000 versions, but I am not as sure for other OSes like Windows ME. If someone could test it and let me know, that'd be awfully nice.

GetCustomName

CString GetCustomName(IconFolder folder)
{
    HKEY hKey = 0;
    CString keyname = 
        "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\";

    switch(folder)
    {
    case MyComputer:
        keyname += "{20D04FE0-3AEA-1069-A2D8-08002B30309D}";
        break;
    case MyDocuments:
        keyname += "{450D8FBA-AD25-11D0-98A8-0800361B1103}";
        break;
    case NetworkNeighbourhood:
        keyname += "{208D2C60-3AEA-1069-A2D7-08002B30309D}";
        break;
    case RecycleBin:
        keyname += "{645FF040-5081-101B-9F08-00AA002F954E}";
        break;
    case InternetExplorer:
        keyname += "{871C5380-42A0-1069-A2EA-08002B30309D}";
        break;
    default:        
        keyname = "";
        break;
    }

    BYTE buff[256];

    if(keyname.GetLength())
    {
        LONG result = ::RegOpenKeyEx(HKEY_CURRENT_USER,
            (LPCTSTR)keyname,0,KEY_READ,&hKey);

        ZeroMemory(buff,255);
        DWORD sz = sizeof buff;
        DWORD typ = REG_SZ;

        RegQueryValueEx(hKey,"",0,&typ,buff,&sz);

        RegCloseKey(hKey);
    }
    else
    {
        return CString("Invalid Folder Request");
    }

    if(CString(buff).GetLength())
        return CString(buff);
    else
        return CString("No custom definition");
}

Well, this is pretty simple too; just a matter of reading some registry entries. Basically this is exactly what the OS does too when it shows the desktop icons, it first reads these registry values and if they are blank, then it will extract the strings out of Shell32.dll.

SetCustomName

void SetCustomName(IconFolder folder, CString foldername)
{
    HKEY hKey = 0;
    CString keyname = 
        "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\";

    switch(folder)
    {
    case MyComputer:
        keyname += "{20D04FE0-3AEA-1069-A2D8-08002B30309D}";
        break;
    case MyDocuments:
        keyname += "{450D8FBA-AD25-11D0-98A8-0800361B1103}";
        break;
    case NetworkNeighbourhood:
        keyname += "{208D2C60-3AEA-1069-A2D7-08002B30309D}";
        break;
    case RecycleBin:
        keyname += "{645FF040-5081-101B-9F08-00AA002F954E}";
        break;
    case InternetExplorer:
        keyname += "{871C5380-42A0-1069-A2EA-08002B30309D}";
        break;
    default:        
        keyname = "";
        break;
    }

    if(keyname.GetLength())
    {
        LONG result = ::RegOpenKeyEx(HKEY_CURRENT_USER,
            (LPCTSTR)keyname,0,KEY_WRITE,&hKey);

        RegSetValueEx(hKey,"",0,REG_SZ,
            (const BYTE*)foldername.GetBuffer(0),foldername.GetLength());
        foldername.ReleaseBuffer();

        RegCloseKey(hKey);

        LPITEMIDLIST pidl;
        SHGetSpecialFolderLocation(NULL,CSIDL_DESKTOP,&pidl);
        SHChangeNotify(SHCNE_ASSOCCHANGED,SHCNF_IDLIST,pidl,0);
    }
}

Here, we simply update the registry entries with the new custom strings. If you save a NULL string, then the OS will use the language specific strings from Shell32.dll. There is some interesting bit of code in the end that I use to force a refresh of the desktop icon names. I tried everything from invalidating the desktop, sending WM_PAINT messages to sending F5 key messages, but none of them worked. This was the only code that worked for me.

Refreshing the desktop trick (save this one)

LPITEMIDLIST pidl;
SHGetSpecialFolderLocation(NULL,CSIDL_DESKTOP,&pidl);
SHChangeNotify(SHCNE_ASSOCCHANGED,SHCNF_IDLIST,pidl,0);

Conclusion

The basic problem with using these type of registry reads and DLL string reads is that you never know when Microsoft will change the string identifiers or the registry locations in their next OS versions. But that's a risk you have to live with, and whenever they make a change, you'll have to be prepared to do version checks and do the required stuff depending on the IS versions detected. I do hope at least a few people would have benefited from this articles. Feel free to submit your feedback through the forum at the bottom of this article.

License

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

Share

About the Author

Nish Nishant
United States United States
Nish Nishant is a Software Architect/Consultant based out of Columbus, Ohio. He has over 15 years of software industry experience in various roles including Lead Software Architect, Principal Software Engineer, and Product Manager. Nish is a recipient of the annual Microsoft Visual C++ MVP Award since 2002 (13 consecutive awards as of 2014).

Nish is an industry acknowledged expert in the Microsoft technology stack. He authored
C++/CLI in Action for Manning Publications in 2005, and had previously co-authored
Extending MFC Applications with the .NET Framework for Addison Wesley in 2003. In addition, he has over 140 published technology articles on CodeProject.com and another 250+ blog articles on his
WordPress blog. Nish is vastly experienced in team management, mentoring teams, and directing all stages of software development.

Contact Nish : You can reach Nish on his google email id voidnish.

Website and Blog

You may also be interested in...

Comments and Discussions

 
Questionhow do you know the identification of resource, like my computer、my document? Pin
nenfa3-Jan-10 16:24
membernenfa3-Jan-10 16:24 
Generaladd or set quota settings to a user using .net interface Pin
sreedhar.prudhvi20-Jun-04 19:40
membersreedhar.prudhvi20-Jun-04 19:40 
GeneralHelp Needed Pin
Anonymous19-May-04 21:19
sussAnonymous19-May-04 21:19 
GeneralNice,but not the best way... Pin
kim-ryo25-Jan-03 17:21
memberkim-ryo25-Jan-03 17:21 
GeneralRe: Nice,but not the best way... Pin
A. Riazi25-Jan-03 17:53
memberA. Riazi25-Jan-03 17:53 
GeneralRe: Nice,but not the best way... Pin
Nishant S25-Jan-03 18:47
editorNishant S25-Jan-03 18:47 
GeneralRe: Nice,but not the best way... Pin
A. Riazi26-Jan-03 4:02
memberA. Riazi26-Jan-03 4:02 
GeneralRe: Nice,but not the best way... Pin
Nishant S26-Jan-03 4:25
editorNishant S26-Jan-03 4:25 
GeneralRe: Nice,but not the best way... Pin
Nishant S25-Jan-03 18:43
editorNishant S25-Jan-03 18:43 
GeneralRe: Nice,but not the best way... Pin
kim-ryo25-Jan-03 18:55
memberkim-ryo25-Jan-03 18:55 
GeneralRe: Nice,but not the best way... Pin
Nishant S26-Jan-03 4:25
editorNishant S26-Jan-03 4:25 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150624.2 | Last Updated 25 Jan 2003
Article Copyright 2003 by Nish Nishant
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid