希腊神话备忘录

Α	α	alpha		vowel
Β	β	beta
Γ	γ	gamma
Δ	δ	delta
Ε	ε	epsilon		vowel
Ζ	ζ	zeta			/'zi:tə/
Η	η	eta		vowel	/'i:tə/
Θ	θ	theta
Ι	ι	iota		vowel	/aɪ'əʊtə/
Κ	κ	kappa			/'kæpə/
Λ	λ	lambda
Μ	μ	mu			/mju:/

Ν	ν	nu			/nju:/
Ξ	ξ	xi			/ksi/,/ˈksaɪ/,/ˈzaɪ/
Ο	ο	omicron		vowel	/əuˈmaikrən/,/ˈɑmɪˌkrɑn/
Π	π	pi
Ρ	ρ	rho			/rəʊ/
Σ	σ/ς	sigma
Τ	τ	tau			/tɔ:/,/taʊ/
Υ	υ	upsilon		vowel	/ˈipsilon/,/ˈʌpsɨlɒn/
Φ	φ	phi			/faɪ/
Χ	χ	chi			/kaɪ/
Ψ	ψ	psi			/psaɪ/
Ω	ω	omega		vowel

Read more

asn.1中的方括号

asn.1编码以tag + length + value为基本单元,IMPLICIT模式是用context-specific tag替换后面通常是universal的tag;EXPLICIT模式是用context-specific tag的tlv包裏里层的universal tag的tlv。

ber编码时,会默认为EXPLICIT模式。

在bnf范式语法中

1
2
3
4
5
圆括号(): 相当于C语言算术表达式中圆括号()的作用。
尖括号<>: 内包含的为必选项。 
方括号[]: 内包含的为可选项。 
花括号{}: 内包含的为可重复0至无数次的项。 
|: 或or的意思;若要表示并and的意思,直接两个符号之间空白间隔。

而在asn.1语法中,方括号[Index]指示的是context-specific tag值,即0xA0 + Index;花括号{}用于SEQUENCE,SET或CHOICE的定义。如

1
2
Number2 ::= [7] IMPLICIT [1] INTEGER
AccountedClosed ::= [2] EXPLICIT BOOLEAN

这里Number2的tag值为0xA7;而对于AccountedClosed,当其值为true时其ber编码为

1
0xA2 0x3 0x1 0x1 0xFF

refer to:
https://blog.csdn.net/sever2012/article/details/7767867
https://www.cnblogs.com/qook/p/5957436.html

数字证书备忘录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ca: certification authority
pem: privacy enhanced mail, "begin"+base64+"end"
der: distinguished encoding rules, binary
crt: certificate
cer: certificate
csr: certificate signing request
pkcs: public key cryptography standard
ietf: internet engineering task force
pkcs#12/pfx/p12: file format encoding private keys, certificates and etc, rfc7292
pkcs#7: cryptographic message syntex standard
pkcs#10/p10: certification request syntax specification, rfc2986
x.509: public key certificates format standard
ber: basic encoding rules
per: packed encoding rules
crl: certificate revocation list
dsa: digital signature algorithm

refer to:
http://www.360doc.com/content/15/0520/10/21412_471902987.shtml
https://baike.baidu.com/item/BER/19940289?fr=aladdin
https://blog.csdn.net/mao834099514/article/details/109074661
https://datatracker.ietf.org/doc/html/rfc7292

asn.1编码的转换

这个工具在

1
strongswan/src/libstrongswan/asn1

以下是使用示例

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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <asn1/asn1.h>
#include <asn1/asn1_parser.h>
 
#define INTEGER_SIZE 32
 
static chunk_t chunk_to_asn1(chunk_t chunk)
{
	chunk_t x;
	chunk_t y;
	chunk_t hash;
	chunk_t content;
	chunk_t asn1;
 
	x.ptr = chunk.ptr;
	x.len = INTEGER_SIZE;
	y.ptr = chunk.ptr + INTEGER_SIZE;
	y.len = INTEGER_SIZE;
	content.ptr = y.ptr + INTEGER_SIZE;
	content.len = chunk.len - INTEGER_SIZE * 3;
	hash.ptr = content.ptr + content.len;
	hash.len = INTEGER_SIZE;
 
	asn1 = asn1_wrap(ASN1_SEQUENCE, "mmmm",
		asn1_integer("c", x),
		asn1_integer("c", y),
		asn1_simple_object(ASN1_OCTET_STRING, hash),
		asn1_simple_object(ASN1_OCTET_STRING, content));
 
	chunk_free(&chunk);
	return asn1;
}
 
static const asn1Object_t patterns[] = {
	{ 0, "seq",			ASN1_SEQUENCE,		ASN1_NONE }, /*  0 */
	{ 1,   "x",			ASN1_INTEGER,		ASN1_BODY }, /*  1 */
	{ 1,   "y",			ASN1_INTEGER,		ASN1_BODY }, /*  2 */
	{ 1,   "hash",			ASN1_OCTET_STRING,	ASN1_BODY }, /*  3 */
	{ 1,   "content",		ASN1_OCTET_STRING,	ASN1_BODY }, /*  4 */
	{ 0, "exit",			ASN1_EOC,		ASN1_EXIT }
};
#define PATTERN_KEY_X			1
#define PATTERN_KEY_Y			2
#define PATTERN_KEY_HASH		3
#define PATTERN_KEY_CONTENT		4
 
static chunk_t correct_integer(chunk_t chunk)
{
	if (chunk.len == INTEGER_SIZE + 1)
		return chunk_skip(chunk, 1);
	return chunk;
}
 
static bool parse_asn1(chunk_t asn1, chunk_t* x, chunk_t* y, chunk_t* hash, chunk_t* content)
{
	chunk_t object;
	asn1_parser_t *parser;
	bool success = FALSE;
	int object_id, oid, i;
 
	parser = asn1_parser_create(patterns, asn1);
 
	while (parser->iterate(parser, &object_id, &object))
	{
		switch (object_id)
		{
			case PATTERN_KEY_X:
				*x = correct_integer(object);
				break;
			case PATTERN_KEY_Y:
				*y = correct_integer(object);
				break;
			case PATTERN_KEY_HASH:
				*hash = object;
				break;
			case PATTERN_KEY_CONTENT:
				*content = object;
				break;
		}
	}
	success = parser->success(parser);
	parser->destroy(parser);
	return success;
}
 
static bool chunk_from_asn1(chunk_t* chunk, chunk_t asn1)
{
	chunk_t x;
	chunk_t y;
	chunk_t hash;
	chunk_t content;
 
	if (!parse_asn1(asn1, &x, &y, &hash, &content))
		return false;
 
	*chunk = chunk_cat("cccc", x, y, content, hash);
	return true;
}
 
static void random_data(chunk_t chunk)
{
	int fd = open("/dev/urandom", O_RDONLY);
	read(fd, chunk.ptr, chunk.len);
	close(fd);
}
 
int test()
{
	bool is_ok;
	chunk_t result;
	chunk_t asn1;
	chunk_t total = chunk_alloc(INTEGER_SIZE * 3 + 345);
 
	random_data(total);
 
	asn1 = chunk_to_asn1(total);
	is_ok = chunk_from_asn1(&result, asn1);
 
	chunk_free(&result);
	chunk_free(&asn1);
	chunk_free(&total);
	return is_ok;
}

因为asn1模块里对ASN1_INTEGER类型有个two's complement处理,如果这个数最高位为1,则在此数前加一个0值字节,所以correct_integer函数的目地在于更正输出。

转载: linux下的多国语言解决方案

hello.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <libintl.h> // gettext
#include <locale.h>
 
#define _(STRING) gettext(STRING)
#define PACKAGE "hello"
#define LOCALEDIR "/usr/share/locale/"
 
int main(int argv, char* argc[])
{
	setlocale(LC_ALL, "");
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);
	printf(_("Hello, World\n"));
	printf(_("This is a example.\n"));
	return 0;
}

提取字符串

1
xgettext --keyword=_ hello.c -o hello.pot

编辑hello.pot

1
2
3
4
5
6
...
msgid "Hello, World\n"
msgstr "大家好!\n"
msgid "This is a example.\n"
msgstr "This is a example.\n"
...

将hello.pot编译为字节码

1
2
msgmerge zh_CN.po hello.pot
msgfmt zh_CN.po -o hello.mo

refer to:
https://leedd.com/linux-c-i18n-l10n-xgettext-msgfmt-rpmbuild/

乐理备忘录

和弦

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
C	1  3  5			C大三和弦
Cm	1 b3  5			C小三和弦
Caug	1  3 #5			C增和弦
Cdim	1 b3 b5			C减和弦
Csus2	1  2  5			C挂二和弦
Csus4	1  4  5			C挂四和弦
C6	1  3  5  6		C大六和弦
Cm6	1 b3  5  6		C小六和弦
Cm7	1 b3  5 b7		C小七和弦
Cmaj7	1  3  5  7		C大七和弦
C7	1  3  5 b7		C大小七和弦(C属七和弦)
C7-5	1  3 b5 b7		C七减五和弦
Cm7-5	1 b3 b5 b7		C小七减五和弦
C7sus4	1  4  5 b7		C七挂四和弦
Cdim7	1 b3 b5 bb7		C减七和弦
Cmaj9	1  3  5  7  2		C大九和弦
Cm9	1 b3  5  7  2		C小九和弦
C9	1  3  5 b7  2		C属九和弦
Cadd9	1  3  5  2		C加九和弦
C11	1  3  5 b7  2  4	C属十一和弦
Cm11	1 b3  5 b7  2  4	C小十一和弦
C13	1  3  4 b7  2  4  6	C十三和弦
 
大七和弦:	大小大	1 3 5 7 2 4 6	4 6 1 3 5 7 2
小七和弦:	小大小	6 1 3 5 7 2 4
小七大九和弦:	小大小	6 1 3 5 7 2 4	自然大调VI级
小七小九和弦:	小大小	3 5 7 2 4 6 1	自然大调III级
属七和弦:	大小小	5 7 2 4 6 1 3
属七降九和弦:	大小小	5 7 2 4b6 1 3	和声小调V级
属七升九和弦:	大小小	5 7 2 4#6 1 3	7音到9音=增三度=纯四度
属七alt和弦:	大小小	5 7 2 4		#5或b13、b5或#11、#9、b9,旋律小调VII级
半减七和弦:	小小大	7 2 4 6 1 3 5	自然大调VII级
减七和弦(Co7):	小小小	7 2 4b6 1 3 5	和声小调VII级
增三和弦:	大大	1 3#5		旋律小调3级
Csus2:			1 2 5		
Csus4(Csus):		1 4 5
六和弦:			3 5 1
四六和弦:		5 1 3
五六和弦:		3 5 7 1
三四和弦:		5 7 1 3
二和弦:			7 1 3 5

调式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
自然大调:	全全半全全全半,1 2 3 4 5 6 7 1
和声大调:	全全半全半三半,1 2 3 4 5b6 7 1
旋律大调:	全全半全半全全,1 2 3 4 5b6b7 1
自然小调:	全半全全半全全,6 7 1 2 3 4 5 6
和声小调:	全半全全半三半,6 7 1 2 3 4#5 6
旋律小调:	全半全全全全半,6 7 1 2 3#4#5 6
Ionian:		全全半全全全半,1 2 3 4 5 6 7 1,自然大调
Dorian:		全半全全全半全,2 3 4 5 6 7 1 2
Phrygian:	半全全全半全全,3 4 5 6 7 1 2 3
Lydian:		全全全半全全半,4 5 6 7 1 2 3 4
Mixolydian:	全全半全全半全,5 6 7 1 2 3 4 5
Aeolian:	全半全全半全全,6 7 1 2 3 4 5 6,自然小调
Locrian:	半全全半全全全,7 1 2 3 4 5 6 7
alter音阶:	半全半全全全全,1b2b3 3b5b6b7 1

自然大调4152637

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 C:	 C  D  E  F  G  A  B  C
#C:	#C #D #E #F #G #A #B #C
bD:	bD bE  F bG bA bB  C bD
 D:	 D  E #F  G  A  B #C  D
bE:	bE  F  G bA bB  C  D bE
 E:	 E #F #G  A  B #C #D  E
 F:	 F  G  A bB  C  D  E  F
#F:	#F #G #A  B #C #D #E #F
bG:	bG bA bB bC bD bE  F bG
 G:	 G  A  B  C  D  E #F  G
bA:	bA bB  C bD bE  F  G bA
 A:	 A  B #C  D  E #F #G  A
bB:	bB  C  D bE  F  G  A bB
 B:	 B #C #D  E #F #G #A  B

自然小调

1
2
3
4
5
6
7
 A:	 A  B  C  D  E  F  G  A
 B:	 B #C  D  E #F  G  A  B
 C:	 C  D bE  F  G bA bB  C
 D:	 D  E  F  G  A bB  C  D
 E:	 E #F  G  A  B  C  D  E
 F:	 F  G bA bB  C bD bE  F
 G:	 G  A bB  C  D bE  F  G

中国五声

1
2
3
4
宫	商	角	徵	羽
do	re	mi	sol	la
1	2	3	5	6
	全	全	全半	全

日本五声

1
2
3
4
5
6
7
8
9
10
11
12
13
吕音阶(阳音阶)
do	re	mi	sol	la
律音阶
sol	la	do	re	mi
	全	全半	全	全
阴音阶上行形
1	2	b3	5	6
阴音阶下行形
1	2	b3	5	b6
 
la	si	do	mi	fa
6	7	1	3	4
	全	半	全全	半

refer to:
https://weibo.com/p/1001603900313475143262
https://www.zhihu.com/question/34528429

音乐中的英文单词

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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
属七升九和弦: dominant seventh sharp ninth chord
bD: D flat
调: key
音高: pitch
调律: temperament
纯五度: perfect 5th
小七度: Minor 7th
半音音阶: chromatic scale
自然音阶: diatonic scale
经过音: passing tone
辅助音: neighboring tone/auxiliary tone/upper to lower
全音音阶: whole tone scale 
五声音阶: pentatonic scale
旋律小调: melodic minor
和声小调: harmonic minor
旋律音程: melodic interval
和声音程: harmonic interval
等音程: enharmonic interval
大三和弦: major triad
七和弦: seventh chord
第一转位: first inversion
 
二三四五六七九十度: 英语序数词
八度: octave
三全音: tri-tone
协和: consonant
不协和: dissonant
转调: modulation
移调: transposition
 
二全音符: breve
全音符: semibreve, whole note
二分音符: minim, half note
四分音符: crotchet
八分音符: quaver
十六分音符: semiquaver
三十二分音符: demisemiquaver
六十四分音符: hemidemisemi quaver
 
二拍: duple meters(2/2, 2/4, 2/8)
三拍: triple meters(3/2, 3/4, 3/8)
四拍: quadruple meters(4/2, 4/4, 4/8)
五拍: quintuple meters
普通拍子: common meters
复二拍: compound duple meters(6/2, 6/4, 6/8)
复三拍: compound triple meters(9/4, 9/8)
复四拍: compound quadruple meters(12/4, 12/8, 12/16)
混合拍: irregular meters(7/4, 11/7)
 
二连音: duplet
三连音: triplet
四连音: quadruplet
五连音: quintuplet
六连音: sextuplet
本连音: septuplet
 
主音: tonic
上主音: supertonic
中音: mediant
下属音: subdominant
属音: dominant
下中音: submediant/super-dominant
导音: leading tone/subtonic
 
伊奥尼亚调式: ionian
多利亚调式: dorian
弗里及亚调式: phrygian
利底亚调式: lydian
混合利底亚调式: mixolydian
爱奥利亚调式: aeolian
洛克利亚调式: locrian
 
连音: legato
断音: staccato
持音: sostenuto
震音: trembolo
滑音: glissando
切分音: syncopation
先现音: anticipation
延现音: suspension
装饰音: ornament
颤音: trill
波音: mordent
逆波音: inverted mordent/lower mordent/schneller
复波音: double mordent
回音: inverted turn
琶音: arpeggio
模进: sequence
旋律模进: melodic sequence
和声模进: harmonic sequence
旋律进行: melodic progression
旋律轮廓: melodic contour
 
完全终止: perfect cadence
不完全终止: imperfect cadence
半终止: half cadence
正格终止: authentic cadence
变格终止: plagal cadence
阻碍终止: interrupted cadence
伪终止: deceptive cadence
 
三段式: temary form/ABA
变奏曲式: variation form/A, A1, A2, A3
分节歌: strophic form/a, a, a, ...
回旋曲式: rondo form/ABACA
奏鸣曲式: sonata form
 
前奏: prelude
间奏: interlude
尾声: coda
三声中部: trio
华彩乐段: cadanza
改编(缩编): reduction
 
独奏: solo
二重奏: duet
三重奏: trio
四重奏: quartet
五重奏: quintet
合奏: ensemble
 
受难曲: passion
交响曲: symphony
协奏曲: concerto
奏鸣曲: sonata
小奏鸣曲: sonatina
练习曲: etude
进行曲: march
序曲: overture
叙事曲: ballata
间奏曲: inter mezzo
随想曲: capriccio
幻想曲: fantasia
摇篮曲: lullaby
安魂曲: reguiem
小夜曲: serenade
夜曲: nocturn
狂想曲: rhapsody
小步舞曲: minuet
创意曲: invention
谐谑曲: scherzo
布鲁斯: blues
 
宣叙调: recitative
咏叹调: aria
 
管弦乐队: orchestra
指挥: conductor
指挥台: podium
长笛: flute
单簧管: charinet
小号: trumpet
短号: cornet
长号: trombone
大号: tuba
小提琴: violin
中提琴: viola
大提琴: cello
竖琴: harp
键盘乐器: clavier
木琴: xylophone
萨克斯管: saxophone
打击乐: percussion
手风琴: accordion
风琴: organ
 
女高音: soprano
女中音: mezzo soprano
男高音: tenor
男中音: bariton
 
文艺复兴: Renaissance
巴洛克: Baroque
洛可可: Rococo = Rocaille + Coquilles
复调: polyphony

refer to:
http://blog.sina.com.cn/s/blog_d2b7cd6a0102wts1.html
https://wenku.baidu.com/view/bbaca6e981c758f5f61f6779.html

C标准库中的strtok

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
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
 
#ifdef WIN32
#define EU_STRTOK strtok_s
#define EU_STRDUP _strdup
#else
#define EU_STRTOK strtok_r
#define EU_STRDUP strdup
#endif
 
int main()
{
	char str[1000] = "Steven Jobs, Bruce Lee, Jack Chen, George W Bush";
	char* pNames[100];
	int idxNames = 0;
	char* pWords[100];
	int idxWords = 0;
	char* buf = str;
	char* outPtr = NULL;
	while (NULL != (buf = EU_STRTOK(NULL == outPtr? buf : NULL, ",", &outPtr)))
	{
		char* innerPtr = NULL;
		pNames[idxNames++] = EU_STRDUP(buf);
		while (NULL != (buf = EU_STRTOK(NULL == innerPtr? buf : NULL, " ", &innerPtr)))
		{
			pWords[idxWords++] = buf;
		}
	}
 
	return 0; // here, to watch pNames and pWords contents in debug mode.
}

strtok有一个缺陷,比如对于源串",hello,the,world!",分隔符",",分隔结果会少了空串""。

std版字符串token提取

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
#include <iostream>
#include <locale>
#include <sstream>
 
struct csv_whitespace : std::ctype<wchar_t>
{
	bool do_is(mask m, char_type c) const
	{
		if ((m & space) && c == L' ') {
			return false; // space will NOT be classified as whitespace
		}
		if ((m & space) && c == L',') {
			return true; // comma will be classified as whitespace
		}
		return ctype::do_is(m, c); // leave the rest to the parent class
	}
};
 
int main()
{
	std::wstring in = L"Column 1,  Column 2, Column 3\n123,456,789";
	std::wstring token;
 
	std::wcout << "default locale:\n";
	std::wistringstream s1(in);
	while (s1 >> token) {
		std::wcout << ">" << token << '\n';
	}
 
	std::wcout << "locale with modified ctype:\n";
	std::wistringstream s2(in);
	csv_whitespace* my_ws = new csv_whitespace;
	s2.imbue(std::locale(s2.getloc(), my_ws));
	while (s2 >> token) {
		std::wcout << ">" << token << '\n';
	}
	return 0;
}

std版宽字符转ASCII字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <locale>
 
int main()
{
	std::locale loc;
 
	const char narrow_phrase[] = "Seventy-seven foxes";
	wchar_t wide_phrase[sizeof(narrow_phrase)];
 
	std::wcout << L"The first wide character is: ";
	wchar_t wc = std::use_facet<std::ctype<wchar_t>>(loc).widen(*narrow_phrase);
	std::wcout << wc << std::endl;
 
	std::wcout << L"The wide-character phrase is: ";
	std::use_facet<std::ctype<wchar_t>>(loc).widen(narrow_phrase,
		narrow_phrase + sizeof(narrow_phrase),
		wide_phrase);
	std::wcout << wide_phrase << std::endl;
 
	return 0;
}

std版日期字符串解析

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
#include <iostream>
#include <sstream>
#include <locale>
#include <iomanip>
 
int main()
{
	std::tm t = {};
	std::istringstream ss("2011-Februar-18 23:12:34");
	//ss.imbue(std::locale("de_DE.utf-8"));
	try {
		ss.imbue(std::locale("de-DE"));
	}
	catch (std::exception e) {
		std::cout << e.what() << std::endl;
	}
	ss >> std::get_time(&t, "%Y-%b-%d %H:%M:%S");
	if (ss.fail()) {
		std::cout << "Parse failed\n";
	}
	else {
		std::cout << std::put_time(&t, "%c") << '\n';
	}
	return 0;
}

refer to:
https://en.cppreference.com/w/cpp/locale/locale/name
https://social.msdn.microsoft.com/Forums/en-US/0fb287af-bb58-4c60-a3da-14fe84c16948/stdlocaleglobalstdlocalequotzhcnquot-gets-quotbad-locale-namequot?forum=vcgeneral
https://docs.microsoft.com/en-us/cpp/c-runtime-library/locale-names-languages-and-country-region-strings?redirectedfrom=MSDN&view=msvc-160

Windows驱动从设备名获取dos盘符路径

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
NTSTATUS querySymbolicLink(PUNICODE_STRING symbolicLinkName, PUNICODE_STRING linkTarget)
{
	OBJECT_ATTRIBUTES oa;
	NTSTATUS status;
	HANDLE handle;
 
	InitializeObjectAttributes(&oa, symbolicLinkName, OBJ_CASE_INSENSITIVE, 0, 0);
	status = ZwOpenSymbolicLinkObject(&handle, GENERIC_READ, &oa);
	if (!NT_SUCCESS(status))
		return status;
 
	linkTarget->MaximumLength = 200 * sizeof(WCHAR);
	linkTarget->Length = 0;
	linkTarget->Buffer = ExAllocatePool(PagedPool, linkTarget->MaximumLength);
	if (!linkTarget->Buffer)
	{
		ZwClose(handle);
		return STATUS_INSUFFICIENT_RESOURCES;
	}
	RtlZeroMemory(linkTarget->Buffer, linkTarget->MaximumLength);
 
	status = ZwQuerySymbolicLinkObject(handle, linkTarget, NULL);
	ZwClose(handle);
 
	if (!NT_SUCCESS(status))
	{
		ExFreePool(linkTarget->Buffer);
	}
	return status;
}
 
WCHAR *rtlVolumeDeviceToDosName(WCHAR *deviceName)
{
	NTSTATUS status;
	UNICODE_STRING driveLetterName;
	WCHAR driveLetterNameBuf[128];
	WCHAR c;
	WCHAR driLetter[3];
	UNICODE_STRING linkTarget;
 
	for (c = L'A'; c <= L'Z'; c++)
	{
		RtlInitEmptyUnicodeString(&driveLetterName, driveLetterNameBuf, sizeof(driveLetterNameBuf));
		RtlAppendUnicodeToString(&driveLetterName, L"\\??\\");
		driLetter[0] = c;
		driLetter[1] = L':';
		driLetter[2] = 0;
		RtlAppendUnicodeToString(&driveLetterName, driLetter);
 
		status = querySymbolicLink(&driveLetterName, &linkTarget);
		if (!NT_SUCCESS(status))
			continue;
 
		if (_wcsnicmp(linkTarget.Buffer, deviceName, linkTarget.Length) == 0)
		{
			deviceName += linkTarget.Length - 2;
			deviceName[0] = c;
			deviceName[1] = L":";
			ExFreePool(linkTarget.Buffer);
			break;
		}
		ExFreePool(linkTarget.Buffer);
	}
	return deviceName;
}
 
WCHAR *getDosPath(WCHAR *path)
{
	WCHAR device[] = L"\\Device\\";
 
	if (strIsStartWith(path, device))
	{
		path = rtlVolumeDeviceToDosName(path);
	}
 
	return path;
}

获取HANDLE对应的文件路径

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
#include <Windows.h>
#include <psapi.h>
#include <wchar.h>
 
WCHAR *getFilePathByHandle(HANDLE hFile, WCHAR* filePath, int filePathLen)
{
	DWORD dwFileSizeHi = 0;
	DWORD dwFileSizeLo = GetFileSize(hFile, &dwFileSizeHi);
	HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, dwFileSizeLo, NULL);
 
	filePath[0] = 0;
	if (NULL != hFileMap)
	{
		void* pMem = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1);
		if (NULL != pMem)
		{
			if (0 == GetMappedFileNameW(GetCurrentProcess(), pMem, filePath, filePathLen))
			{
				// GetLastError
			}
			UnmapViewOfFile(pMem);
		}
		CloseHandle(hFileMap);
	}
	return filePath;
}
 
wchar_t toLower(wchar_t ch)
{
	if ('A' <= ch && ch <= 'Z')
		ch = ch - 'A' + 'a';
	return ch;
}
 
int isNoCaseBeginWith(wchar_t* l, wchar_t* r)
{
	if (*l == 0 && *r == 0)
		return 1;
	if (*l == 0 || *r == 0)
		return 0;
	for (; 0 != *l && 0 != *r; l++, r++)
	{
		if (toLower(*l) != toLower(*r))
			return 0;
	}
	return 1;
}
 
WCHAR* getDosFilePath(WCHAR *dosPath, int len, WCHAR* kernelPath)
{
	wchar_t path[3] = L"C:";
	wchar_t szBuf[MAX_PATH] = { 0 };
	for (wchar_t ch = L'A'; ch <= L'Z'; ch++)
	{
		path[0] = ch;
		QueryDosDevice(path, szBuf, MAX_PATH);
		if (isNoCaseBeginWith(kernelPath, szBuf))
		{
			swprintf_s(dosPath, len, L"%s%s", path, kernelPath + wcslen(szBuf));
			return dosPath;
		}
	}
	dosPath[0] = 0;
	return dosPath;
}
 
int main()
{
	HANDLE hFile = CreateFileW(L"d:\\test.txt",
		GENERIC_READ,
		FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
		NULL,
		OPEN_EXISTING,
		0x00,
		NULL);
 
	if (INVALID_HANDLE_VALUE == hFile)
	{
		return 0;
	}
 
	WCHAR path[1024];
	getFilePathByHandle(hFile, path, 1024);
 
	WCHAR dosPath[1024];
	getDosFilePath(dosPath, 1024, path);
 
	CloseHandle(hFile);
 
	return 0;
}