今天无意中看到了HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSavePidlMRU这个键值的用途,虽然感觉没啥实际用途,但是也挺有趣的,于是写了个小程序读取它。这个键值的意义非常明确,就是记录打开保存对话框的最近操作的文件的PIDL。所以我们可以通过PIDL来获得文件路径,就这么简单,确实没啥特别的实际用途吧,就当娱乐了。枚举的效果如下:

20141117231005

代码也很简单:


#include "stdafx.h"
#include <atlbase.h>
#include <atlstr.h>
#include <Shlobj.h>
#include <locale.h>
#include <vector>

#pragma comment(lib, "shell32.lib")

const TCHAR mru_path[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\OpenSavePidlMRU");

void EnumMRUValue(HKEY subkey, std::vector &mru;_files)
{
    ULONG i = 0, j = 0;
    TCHAR value_name[MAX_PATH];
    ULONG value_name_length = MAX_PATH;
    UCHAR data_buffer[1024];
    ULONG data_length = sizeof(data_buffer);
    while (RegEnumValue(subkey, i++, value_name, &value;_name_length, 0, NULL, data_buffer, &data;_length) == ERROR_SUCCESS)
    {
        if (_tcscmp(value_name, TEXT("MRUListEx")) != 0) {
            CComPtr malloc_ptr;
            HRESULT hr = SHGetMalloc(&malloc;_ptr);
            LPITEMIDLIST file_pidl = (LPITEMIDLIST)malloc_ptr->Alloc(sizeof(UCHAR) + data_length);

            if (file_pidl) {
                memcpy(file_pidl, data_buffer, data_length);
                WCHAR file_path[MAX_PATH] = { 0 };
                if (SHGetPathFromIDList(file_pidl, file_path)) {
                    mru_files.push_back(file_path);
                    
                }
                malloc_ptr->Free(file_pidl);
            }
        }

        value_name_length = MAX_PATH;
        data_length = sizeof(data_buffer);
    }
}

BOOL PrintMRUFiles()
{
    HKEY subkey;
    LSTATUS l = RegOpenKeyEx(HKEY_CURRENT_USER, mru_path, 0, KEY_READ, &subkey;);
    if (l != ERROR_SUCCESS) {
        return FALSE;
    }
    ULONG i = 0;
    TCHAR key_name[MAX_PATH];
    ULONG key_name_length = MAX_PATH;
    while (RegEnumKeyEx(subkey, i++, key_name, &key;_name_length, 0, NULL, NULL, NULL) == ERROR_SUCCESS)
    {
        HKEY ext_key;
        LSTATUS l = RegOpenKeyEx(subkey, key_name, 0, KEY_READ, &ext;_key);
        if (l == ERROR_SUCCESS) {
            
            std::vector mru_files;
            EnumMRUValue(ext_key, mru_files);
            if (mru_files.size() > 0) {
                _tprintf(TEXT("Extension Name : %s\n"), key_name);
                ULONG j = 0;
                for (std::vector::iterator it = mru_files.begin(); it != mru_files.end(); ++it) {

                    WIN32_FILE_ATTRIBUTE_DATA attribute_data = { 0 };
                    
                    if (GetFileAttributesEx(it->GetString(), GetFileExInfoStandard, &attribute;_data)) {
                        ULONGLONG file_size = ((ULONGLONG)attribute_data.nFileSizeHigh) << 32 | attribute_data.nFileSizeLow;
                        _tprintf(TEXT("\t %u %s  % 11I64u KB] %s\n"), j++,
                            (attribute_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0 ? TEXT("[FILE") : TEXT("[DIR "),
                            (file_size + 1023) / 1024,
                            it->GetString());
                    }
                    else {
                        _tprintf(TEXT("\t %u [ERROR_FILE_NOT_FOUND] %s\n"), j++,
                            it->GetString());
                    }
                    
                }
            }
            
            RegCloseKey(ext_key);
        }

        key_name_length = MAX_PATH;
    }
    
    RegCloseKey(subkey);
    return TRUE;
}


int _tmain(int argc, _TCHAR* argv[])
{
    setlocale(LC_ALL, "chs");
    PrintMRUFiles();
    return 0;
}