获得使用打开保存对话框操作文件的记录

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

20141117231005

代码也很简单:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102

#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;
}



Tips

主线程退出前请先退出子线程

我们知道理论上如果一个进程的主线程退出,整个进程就会销毁,子线程自然也是要退出的。但是这并不意味着,程序退出的时候我们就能不问不管自己创建的子线程,因为不管他还真有可能出问题。下面是一个典型的主线程退出过程中,而子线程未退出,造成死锁整个进程的分析图,死锁在c runtime里,死锁原因看图便知,也不用太多解释了。

20141106094954

Tips

ClipMonitor 简单的剪切板监控工具

周末花了点时间写了个剪切板监控工具,他会记录剪切板里面的数据,并且支持用HEX和TEXT对数据进行分析。
涉及到的技术很简单,网上已经有一堆了,没什么可说的,我这里主要是加入了HEX的模块,方便对未知的剪切板数据进行分析而已。

20141102204618

20141102204638

20141102204651

下载:ClipMonitor

Tips