[UDFS] Explicitly mention the license (GPLv2).
[reactos.git] / reactos / drivers / filesystems / udfs / namesup.cpp
1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
3 // All rights reserved
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
6 /*
7 Module:
8 Namesup.cpp
9
10 Abstract: FileName support routines
11 */
12
13 #include "udffs.h"
14
15 // '\dfdf\aaa\ffg' --> '\aaa\ffg'
16 // '\aaa\ffg' --> '\ffg'
17 PWCHAR
18 __fastcall
19 UDFDissectName(
20 IN PWCHAR Buffer,
21 OUT PUSHORT Length
22 )
23 {
24
25 USHORT i;
26
27 //#ifdef _X86_
28 #ifdef _MSC_VER
29
30 PWCHAR retval;
31
32 __asm push ebx
33 __asm push ecx
34
35 __asm mov ebx,Buffer
36 __asm xor ecx,ecx
37 Remove_leading_slash:
38 __asm cmp [word ptr ebx],L'\\'
39 __asm jne No_IncPointer
40 __asm add ebx,2
41 __asm jmp Remove_leading_slash
42 No_IncPointer:
43 __asm cmp [word ptr ebx],L':'
44 __asm jne Scan_1
45 __asm add ebx,2
46 __asm inc ecx
47 __asm jmp EO_Dissect
48 Scan_1:
49 __asm mov ax,[word ptr ebx]
50 __asm cmp ax,L'\\'
51 __asm je EO_Dissect
52 __asm or ax,ax
53 __asm jz EO_Dissect
54 __asm cmp ax,L':'
55 __asm jne Cont_scan
56 __asm or ecx,ecx
57 __asm jnz EO_Dissect
58 Cont_scan:
59 __asm inc ecx
60 __asm add ebx,2
61 __asm jmp Scan_1
62 EO_Dissect:
63 __asm mov retval,ebx
64 __asm mov i,cx
65
66 __asm pop ecx
67 __asm pop ebx
68
69 *Length = i;
70 return retval;
71
72 #else // NO X86 optimization , use generic C/C++
73
74 while (Buffer[0] == L'\\') {
75 Buffer++;
76 }
77 if (Buffer[0] == L':') {
78 *Length = 1;
79 return &(Buffer[1]);
80 }
81 for(i = 0; ( Buffer[i] != L'\\' &&
82 ((Buffer[i] != L':') || !i) &&
83 Buffer[i]); i++);
84 *Length = i;
85 return &(Buffer[i]);
86
87 #endif // _X86_
88
89 } // end UDFDissectName()
90
91 BOOLEAN
92 __fastcall
93 UDFIsNameValid(
94 IN PUNICODE_STRING SearchPattern,
95 OUT BOOLEAN* StreamOpen,
96 OUT ULONG* SNameIndex
97 ) {
98 LONG Index, l;
99 BOOLEAN _StreamOpen = FALSE;
100 PWCHAR Buffer;
101 WCHAR c, c0;
102
103 if(StreamOpen) (*StreamOpen) = FALSE;
104 // We can't create nameless file or too long path
105 if(!(l = SearchPattern->Length/sizeof(WCHAR)) ||
106 (l>UDF_X_PATH_LEN)) return FALSE;
107 Buffer = SearchPattern->Buffer;
108 for(Index = 0; Index<l; Index++, Buffer++) {
109 // Check for disallowed characters
110 c = (*Buffer);
111 if((c == L'*') ||
112 (c == L'>') ||
113 (c == L'\"') ||
114 (c == L'/') ||
115 (c == L'<') ||
116 (c == L'|') ||
117 ((c >= 0x0000) && (c <= 0x001f)) ||
118 (c == L'?')) return FALSE;
119 // check if this a Stream path (& validate it)
120 if(!(_StreamOpen) && // sub-streams are not allowed
121 (Index<(l-1)) && // stream name must be specified
122 ((_StreamOpen) = (c == L':'))) {
123 if(StreamOpen) (*StreamOpen) = TRUE;
124 if(SNameIndex) (*SNameIndex) = Index;
125 }
126 // According to NT IFS documentation neither SPACE nor DOT can be
127 // a trailing character
128 if(Index && (c == L'\\') ) {
129 if((c0 == L' ') ||
130 (_StreamOpen) || // stream is not a directory
131 (c0 == L'.')) return FALSE;
132 }
133 c0 = c;
134 }
135 // According to NT IFS documentation neither SPACE nor DOT can be
136 // a trailing character
137 if((c0 == L' ') ||
138 (c0 == L'.')) return FALSE;
139 return TRUE;
140 } // end UDFIsNameValid()
141
142
143 #ifndef _CONSOLE
144 /*
145
146 Routine Description:
147
148 This routine will compare two Unicode strings.
149 PtrSearchPattern may contain wildcards
150
151 Return Value:
152
153 BOOLEAN - TRUE if the expressions match, FALSE otherwise.
154
155 */
156 BOOLEAN
157 UDFIsNameInExpression(
158 IN PVCB Vcb,
159 IN PUNICODE_STRING FileName,
160 IN PUNICODE_STRING PtrSearchPattern,
161 OUT PBOOLEAN DosOpen,
162 IN BOOLEAN IgnoreCase,
163 IN BOOLEAN ContainsWC,
164 IN BOOLEAN CanBe8dot3,
165 IN BOOLEAN KeepIntact // passed to UDFDOSName
166 )
167 {
168 BOOLEAN Match = TRUE;
169 UNICODE_STRING ShortName;
170 WCHAR Buffer[13];
171
172 if(!PtrSearchPattern) return TRUE;
173 // we try to open file by LFN by default
174 if(DosOpen) (*DosOpen) = FALSE;
175 // If there are wildcards in the expression then we call the
176 // appropriate FsRtlRoutine.
177 if(ContainsWC) {
178 Match = FsRtlIsNameInExpression( PtrSearchPattern, FileName, IgnoreCase, NULL );
179 // Otherwise do a direct memory comparison for the name string.
180 } else if (RtlCompareUnicodeString(FileName, PtrSearchPattern, IgnoreCase)) {
181 Match = FALSE;
182 }
183
184 if(Match) return TRUE;
185
186 // check if SFN can match this pattern
187 if(!CanBe8dot3)
188 return FALSE;
189
190 // try to open by SFN
191 ShortName.Buffer = (PWCHAR)(&Buffer);
192 ShortName.MaximumLength = 13*sizeof(WCHAR);
193 UDFDOSName(Vcb, &ShortName, FileName, KeepIntact);
194
195 // PtrSearchPattern is upcased if we are called with IgnoreCase=TRUE
196 // DOSName is always upcased
197 // thus, we can use case-sensetive compare here to improve performance
198 if(ContainsWC) {
199 Match = FsRtlIsNameInExpression( PtrSearchPattern, &ShortName, FALSE, NULL );
200 // Otherwise do a direct memory comparison for the name string.
201 } else if (!RtlCompareUnicodeString(&ShortName, PtrSearchPattern, FALSE)) {
202 Match = TRUE;
203 }
204 if(DosOpen && Match) {
205 // remember that we've opened file by SFN
206 (*DosOpen) = TRUE;
207 }
208 return Match;
209 } // end UDFIsNameInExpression()
210
211 #endif
212
213 BOOLEAN
214 __fastcall
215 UDFIsMatchAllMask(
216 IN PUNICODE_STRING Name,
217 OUT BOOLEAN* DosOpen
218 )
219 {
220 USHORT i;
221 PWCHAR Buffer;
222
223 if(DosOpen)
224 *DosOpen = FALSE;
225 Buffer = Name->Buffer;
226 if(Name->Length == sizeof(WCHAR)) {
227 // Win32-style wildcard
228 if((*Buffer) != L'*')
229 return FALSE;
230 return TRUE;
231 } else
232 if(Name->Length == sizeof(WCHAR)*(8+1+3)) {
233 // DOS-style wildcard
234 for(i=0;i<8;i++,Buffer++) {
235 if((*Buffer) != DOS_QM)
236 return FALSE;
237 }
238 if((*Buffer) != DOS_DOT)
239 return FALSE;
240 Buffer++;
241 for(i=9;i<12;i++,Buffer++) {
242 if((*Buffer) != DOS_QM)
243 return FALSE;
244 }
245 if(*DosOpen)
246 *DosOpen = TRUE;
247 return TRUE;
248 } else
249 if(Name->Length == sizeof(WCHAR)*(3)) {
250 // DOS-style wildcard
251 if(Buffer[0] != DOS_STAR)
252 return FALSE;
253 if(Buffer[1] != DOS_DOT)
254 return FALSE;
255 if(Buffer[2] != DOS_STAR)
256 return FALSE;
257 if(*DosOpen)
258 *DosOpen = TRUE;
259 return TRUE;
260 } else {
261 return FALSE;
262 }
263 } // end UDFIsMatchAllMask()
264
265 BOOLEAN
266 __fastcall
267 UDFCanNameBeA8dot3(
268 IN PUNICODE_STRING Name
269 )
270 {
271 if(Name->Length >= 13 * sizeof(WCHAR))
272 return FALSE;
273
274 ULONG i,l;
275 ULONG dot_pos=0;
276 ULONG ext_len=0;
277 PWCHAR buff = Name->Buffer;
278
279 l = Name->Length / sizeof(WCHAR);
280
281 for(i=0; i<l; i++, buff++) {
282 if( ((*buff) == L'.') ||
283 ((*buff) == DOS_DOT) ) {
284 if(dot_pos)
285 return FALSE;
286 dot_pos = i+1;
287 } else
288 if(dot_pos) {
289 ext_len++;
290 if(ext_len > 3)
291 return FALSE;
292 } else
293 if(i >= 8) {
294 return FALSE;
295 }
296 }
297 return TRUE;
298 } // end UDFCanNameBeA8dot3()