1*23b7c7b8SHermès Bélusca-Maïto /*++
2*23b7c7b8SHermès Bélusca-Maïto 
3*23b7c7b8SHermès Bélusca-Maïto Copyright (c) 1989-2000 Microsoft Corporation
4*23b7c7b8SHermès Bélusca-Maïto 
5*23b7c7b8SHermès Bélusca-Maïto Module Name:
6*23b7c7b8SHermès Bélusca-Maïto 
7*23b7c7b8SHermès Bélusca-Maïto     NameSup.c
8*23b7c7b8SHermès Bélusca-Maïto 
9*23b7c7b8SHermès Bélusca-Maïto Abstract:
10*23b7c7b8SHermès Bélusca-Maïto 
11*23b7c7b8SHermès Bélusca-Maïto     This module implements the Fat Name support routines
12*23b7c7b8SHermès Bélusca-Maïto 
13*23b7c7b8SHermès Bélusca-Maïto 
14*23b7c7b8SHermès Bélusca-Maïto --*/
15*23b7c7b8SHermès Bélusca-Maïto 
16*23b7c7b8SHermès Bélusca-Maïto #include "fatprocs.h"
17*23b7c7b8SHermès Bélusca-Maïto 
18*23b7c7b8SHermès Bélusca-Maïto #define Dbg                              (DEBUG_TRACE_NAMESUP)
19*23b7c7b8SHermès Bélusca-Maïto 
20*23b7c7b8SHermès Bélusca-Maïto #ifdef ALLOC_PRAGMA
21*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, Fat8dot3ToString)
22*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatIsNameInExpression)
23*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatStringTo8dot3)
24*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatSetFullFileNameInFcb)
25*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatGetUnicodeNameFromFcb)
26*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatUnicodeToUpcaseOem)
27*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatSelectNames)
28*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatEvaluateNameCase)
29*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatSpaceInName)
30*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatUnicodeRestoreShortNameCase)
31*23b7c7b8SHermès Bélusca-Maïto #endif
32*23b7c7b8SHermès Bélusca-Maïto 
33*23b7c7b8SHermès Bélusca-Maïto 
34*23b7c7b8SHermès Bélusca-Maïto BOOLEAN
FatIsNameInExpression(IN PIRP_CONTEXT IrpContext,IN OEM_STRING Expression,IN OEM_STRING Name)35*23b7c7b8SHermès Bélusca-Maïto FatIsNameInExpression (
36*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
37*23b7c7b8SHermès Bélusca-Maïto     IN OEM_STRING Expression,
38*23b7c7b8SHermès Bélusca-Maïto     IN OEM_STRING Name
39*23b7c7b8SHermès Bélusca-Maïto     )
40*23b7c7b8SHermès Bélusca-Maïto 
41*23b7c7b8SHermès Bélusca-Maïto /*++
42*23b7c7b8SHermès Bélusca-Maïto 
43*23b7c7b8SHermès Bélusca-Maïto Routine Description:
44*23b7c7b8SHermès Bélusca-Maïto 
45*23b7c7b8SHermès Bélusca-Maïto     This routine compare a name and an expression and tells the caller if
46*23b7c7b8SHermès Bélusca-Maïto     the name is equal to or not equal to the expression.  The input name
47*23b7c7b8SHermès Bélusca-Maïto     cannot contain wildcards, while the expression may contain wildcards.
48*23b7c7b8SHermès Bélusca-Maïto 
49*23b7c7b8SHermès Bélusca-Maïto Arguments:
50*23b7c7b8SHermès Bélusca-Maïto 
51*23b7c7b8SHermès Bélusca-Maïto     Expression - Supplies the input expression to check against
52*23b7c7b8SHermès Bélusca-Maïto                  The caller must have already upcased the Expression.
53*23b7c7b8SHermès Bélusca-Maïto 
54*23b7c7b8SHermès Bélusca-Maïto     Name - Supplies the input name to check for.  The caller must have
55*23b7c7b8SHermès Bélusca-Maïto            already upcased the name.
56*23b7c7b8SHermès Bélusca-Maïto 
57*23b7c7b8SHermès Bélusca-Maïto Return Value:
58*23b7c7b8SHermès Bélusca-Maïto 
59*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN - TRUE if Name is an element in the set of strings denoted
60*23b7c7b8SHermès Bélusca-Maïto         by the input Expression and FALSE otherwise.
61*23b7c7b8SHermès Bélusca-Maïto 
62*23b7c7b8SHermès Bélusca-Maïto --*/
63*23b7c7b8SHermès Bélusca-Maïto 
64*23b7c7b8SHermès Bélusca-Maïto {
65*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
66*23b7c7b8SHermès Bélusca-Maïto 
67*23b7c7b8SHermès Bélusca-Maïto     //
68*23b7c7b8SHermès Bélusca-Maïto     //  Call the appropriate FsRtl routine do to the real work
69*23b7c7b8SHermès Bélusca-Maïto     //
70*23b7c7b8SHermès Bélusca-Maïto 
71*23b7c7b8SHermès Bélusca-Maïto     return FsRtlIsDbcsInExpression( &Expression,
72*23b7c7b8SHermès Bélusca-Maïto                                     &Name );
73*23b7c7b8SHermès Bélusca-Maïto 
74*23b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( IrpContext );
75*23b7c7b8SHermès Bélusca-Maïto }
76*23b7c7b8SHermès Bélusca-Maïto 
77*23b7c7b8SHermès Bélusca-Maïto 
78*23b7c7b8SHermès Bélusca-Maïto VOID
79*23b7c7b8SHermès Bélusca-Maïto FatStringTo8dot3 (
80*23b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
81*23b7c7b8SHermès Bélusca-Maïto     _In_ OEM_STRING InputString,
82*23b7c7b8SHermès Bélusca-Maïto     _Out_writes_bytes_(11) PFAT8DOT3 Output8dot3
83*23b7c7b8SHermès Bélusca-Maïto     )
84*23b7c7b8SHermès Bélusca-Maïto 
85*23b7c7b8SHermès Bélusca-Maïto /*++
86*23b7c7b8SHermès Bélusca-Maïto 
87*23b7c7b8SHermès Bélusca-Maïto Routine Description:
88*23b7c7b8SHermès Bélusca-Maïto 
89*23b7c7b8SHermès Bélusca-Maïto     Convert a string into fat 8.3 format.  The string must not contain
90*23b7c7b8SHermès Bélusca-Maïto     any wildcards.
91*23b7c7b8SHermès Bélusca-Maïto 
92*23b7c7b8SHermès Bélusca-Maïto Arguments:
93*23b7c7b8SHermès Bélusca-Maïto 
94*23b7c7b8SHermès Bélusca-Maïto     InputString - Supplies the input string to convert
95*23b7c7b8SHermès Bélusca-Maïto 
96*23b7c7b8SHermès Bélusca-Maïto     Output8dot3 - Receives the converted string, the memory must be supplied
97*23b7c7b8SHermès Bélusca-Maïto         by the caller.
98*23b7c7b8SHermès Bélusca-Maïto 
99*23b7c7b8SHermès Bélusca-Maïto Return Value:
100*23b7c7b8SHermès Bélusca-Maïto 
101*23b7c7b8SHermès Bélusca-Maïto     None.
102*23b7c7b8SHermès Bélusca-Maïto 
103*23b7c7b8SHermès Bélusca-Maïto --*/
104*23b7c7b8SHermès Bélusca-Maïto 
105*23b7c7b8SHermès Bélusca-Maïto {
106*23b7c7b8SHermès Bélusca-Maïto     ULONG i;
107*23b7c7b8SHermès Bélusca-Maïto     ULONG j;
108*23b7c7b8SHermès Bélusca-Maïto 
109*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
110*23b7c7b8SHermès Bélusca-Maïto 
111*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatStringTo8dot3\n", 0);
112*23b7c7b8SHermès Bélusca-Maïto     DebugTrace( 0, Dbg, "InputString = %Z\n", &InputString);
113*23b7c7b8SHermès Bélusca-Maïto 
114*23b7c7b8SHermès Bélusca-Maïto     NT_ASSERT( InputString.Length <= 12 );
115*23b7c7b8SHermès Bélusca-Maïto 
116*23b7c7b8SHermès Bélusca-Maïto     //
117*23b7c7b8SHermès Bélusca-Maïto     //  Make the output name all blanks
118*23b7c7b8SHermès Bélusca-Maïto     //
119*23b7c7b8SHermès Bélusca-Maïto 
120*23b7c7b8SHermès Bélusca-Maïto     RtlFillMemory( Output8dot3, 11, UCHAR_SP );
121*23b7c7b8SHermès Bélusca-Maïto 
122*23b7c7b8SHermès Bélusca-Maïto     //
123*23b7c7b8SHermès Bélusca-Maïto     //  Copy over the first part of the file name.  Stop when we get to
124*23b7c7b8SHermès Bélusca-Maïto     //  the end of the input string or a dot.
125*23b7c7b8SHermès Bélusca-Maïto     //
126*23b7c7b8SHermès Bélusca-Maïto 
127*23b7c7b8SHermès Bélusca-Maïto     for (i = 0;
128*23b7c7b8SHermès Bélusca-Maïto          (i < (ULONG)InputString.Length) && (InputString.Buffer[i] != '.') && (i < 11);
129*23b7c7b8SHermès Bélusca-Maïto          i += 1) {
130*23b7c7b8SHermès Bélusca-Maïto 
131*23b7c7b8SHermès Bélusca-Maïto         (*Output8dot3)[i] = InputString.Buffer[i];
132*23b7c7b8SHermès Bélusca-Maïto     }
133*23b7c7b8SHermès Bélusca-Maïto 
134*23b7c7b8SHermès Bélusca-Maïto     //
135*23b7c7b8SHermès Bélusca-Maïto     //  Check if we need to process an extension
136*23b7c7b8SHermès Bélusca-Maïto     //
137*23b7c7b8SHermès Bélusca-Maïto 
138*23b7c7b8SHermès Bélusca-Maïto     if (i < (ULONG)InputString.Length) {
139*23b7c7b8SHermès Bélusca-Maïto 
140*23b7c7b8SHermès Bélusca-Maïto         //
141*23b7c7b8SHermès Bélusca-Maïto         //  Make sure we have a dot and then skip over it.
142*23b7c7b8SHermès Bélusca-Maïto         //
143*23b7c7b8SHermès Bélusca-Maïto 
144*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( (InputString.Length - i) <= 4 );
145*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( InputString.Buffer[i] == '.' );
146*23b7c7b8SHermès Bélusca-Maïto 
147*23b7c7b8SHermès Bélusca-Maïto         i += 1;
148*23b7c7b8SHermès Bélusca-Maïto 
149*23b7c7b8SHermès Bélusca-Maïto         //
150*23b7c7b8SHermès Bélusca-Maïto         //  Copy over the extension.  Stop when we get to the
151*23b7c7b8SHermès Bélusca-Maïto         //  end of the input string.
152*23b7c7b8SHermès Bélusca-Maïto         //
153*23b7c7b8SHermès Bélusca-Maïto 
154*23b7c7b8SHermès Bélusca-Maïto         for (j = 8; (i < (ULONG)InputString.Length); j += 1, i += 1) {
155*23b7c7b8SHermès Bélusca-Maïto 
156*23b7c7b8SHermès Bélusca-Maïto             (*Output8dot3)[j] = InputString.Buffer[i];
157*23b7c7b8SHermès Bélusca-Maïto         }
158*23b7c7b8SHermès Bélusca-Maïto     }
159*23b7c7b8SHermès Bélusca-Maïto 
160*23b7c7b8SHermès Bélusca-Maïto     //
161*23b7c7b8SHermès Bélusca-Maïto     //  Before we return check if we should translate the first character
162*23b7c7b8SHermès Bélusca-Maïto     //  from 0xe5 to 0x5.
163*23b7c7b8SHermès Bélusca-Maïto     //
164*23b7c7b8SHermès Bélusca-Maïto 
165*23b7c7b8SHermès Bélusca-Maïto     if ((*Output8dot3)[0] == 0xe5) {
166*23b7c7b8SHermès Bélusca-Maïto 
167*23b7c7b8SHermès Bélusca-Maïto         (*Output8dot3)[0] = FAT_DIRENT_REALLY_0E5;
168*23b7c7b8SHermès Bélusca-Maïto     }
169*23b7c7b8SHermès Bélusca-Maïto 
170*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(-1, Dbg, "FatStringTo8dot3 -> (VOID)\n", 0);
171*23b7c7b8SHermès Bélusca-Maïto 
172*23b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( IrpContext );
173*23b7c7b8SHermès Bélusca-Maïto 
174*23b7c7b8SHermès Bélusca-Maïto     return;
175*23b7c7b8SHermès Bélusca-Maïto }
176*23b7c7b8SHermès Bélusca-Maïto 
177*23b7c7b8SHermès Bélusca-Maïto 
178*23b7c7b8SHermès Bélusca-Maïto VOID
Fat8dot3ToString(_In_ PIRP_CONTEXT IrpContext,_In_ PDIRENT Dirent,_In_ BOOLEAN RestoreCase,_Out_ POEM_STRING OutputString)179*23b7c7b8SHermès Bélusca-Maïto Fat8dot3ToString (
180*23b7c7b8SHermès Bélusca-Maïto     _In_ PIRP_CONTEXT IrpContext,
181*23b7c7b8SHermès Bélusca-Maïto     _In_ PDIRENT Dirent,
182*23b7c7b8SHermès Bélusca-Maïto     _In_ BOOLEAN RestoreCase,
183*23b7c7b8SHermès Bélusca-Maïto     _Out_ POEM_STRING OutputString
184*23b7c7b8SHermès Bélusca-Maïto     )
185*23b7c7b8SHermès Bélusca-Maïto 
186*23b7c7b8SHermès Bélusca-Maïto /*++
187*23b7c7b8SHermès Bélusca-Maïto 
188*23b7c7b8SHermès Bélusca-Maïto Routine Description:
189*23b7c7b8SHermès Bélusca-Maïto 
190*23b7c7b8SHermès Bélusca-Maïto     Convert fat 8.3 format into a string.  The 8.3 name must be well formed.
191*23b7c7b8SHermès Bélusca-Maïto 
192*23b7c7b8SHermès Bélusca-Maïto Arguments:
193*23b7c7b8SHermès Bélusca-Maïto 
194*23b7c7b8SHermès Bélusca-Maïto     Dirent - Supplies the input 8.3 name to convert
195*23b7c7b8SHermès Bélusca-Maïto 
196*23b7c7b8SHermès Bélusca-Maïto     RestoreCase - If TRUE, then the magic reserved bits are used to restore
197*23b7c7b8SHermès Bélusca-Maïto         the original case.
198*23b7c7b8SHermès Bélusca-Maïto 
199*23b7c7b8SHermès Bélusca-Maïto     OutputString - Receives the converted name, the memory must be supplied
200*23b7c7b8SHermès Bélusca-Maïto         by the caller.
201*23b7c7b8SHermès Bélusca-Maïto 
202*23b7c7b8SHermès Bélusca-Maïto Return Value:
203*23b7c7b8SHermès Bélusca-Maïto 
204*23b7c7b8SHermès Bélusca-Maïto     None
205*23b7c7b8SHermès Bélusca-Maïto 
206*23b7c7b8SHermès Bélusca-Maïto --*/
207*23b7c7b8SHermès Bélusca-Maïto 
208*23b7c7b8SHermès Bélusca-Maïto {
209*23b7c7b8SHermès Bélusca-Maïto     ULONG StringIndex;
210*23b7c7b8SHermès Bélusca-Maïto     ULONG BaseLength, ExtensionLength;
211*23b7c7b8SHermès Bélusca-Maïto 
212*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
213*23b7c7b8SHermès Bélusca-Maïto 
214*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "Fat8dot3ToString\n", 0);
215*23b7c7b8SHermès Bélusca-Maïto 
216*23b7c7b8SHermès Bélusca-Maïto     //
217*23b7c7b8SHermès Bélusca-Maïto     //  First, find the length of the base component.
218*23b7c7b8SHermès Bélusca-Maïto     //
219*23b7c7b8SHermès Bélusca-Maïto 
220*23b7c7b8SHermès Bélusca-Maïto     for (BaseLength = 8; BaseLength > 0; BaseLength -= 1) {
221*23b7c7b8SHermès Bélusca-Maïto 
222*23b7c7b8SHermès Bélusca-Maïto         if (Dirent->FileName[BaseLength - 1] != UCHAR_SP) {
223*23b7c7b8SHermès Bélusca-Maïto 
224*23b7c7b8SHermès Bélusca-Maïto             break;
225*23b7c7b8SHermès Bélusca-Maïto         }
226*23b7c7b8SHermès Bélusca-Maïto     }
227*23b7c7b8SHermès Bélusca-Maïto 
228*23b7c7b8SHermès Bélusca-Maïto     //
229*23b7c7b8SHermès Bélusca-Maïto     //  Now find the length of the extension.
230*23b7c7b8SHermès Bélusca-Maïto     //
231*23b7c7b8SHermès Bélusca-Maïto 
232*23b7c7b8SHermès Bélusca-Maïto     for (ExtensionLength = 3; ExtensionLength > 0; ExtensionLength -= 1) {
233*23b7c7b8SHermès Bélusca-Maïto 
234*23b7c7b8SHermès Bélusca-Maïto         if (Dirent->FileName[8 + ExtensionLength - 1] != UCHAR_SP) {
235*23b7c7b8SHermès Bélusca-Maïto 
236*23b7c7b8SHermès Bélusca-Maïto             break;
237*23b7c7b8SHermès Bélusca-Maïto         }
238*23b7c7b8SHermès Bélusca-Maïto     }
239*23b7c7b8SHermès Bélusca-Maïto 
240*23b7c7b8SHermès Bélusca-Maïto     //
241*23b7c7b8SHermès Bélusca-Maïto     //  If there was a base part, copy it and check the case.  Don't forget
242*23b7c7b8SHermès Bélusca-Maïto     //  if the first character needs to be changed from 0x05 to 0xe5.
243*23b7c7b8SHermès Bélusca-Maïto     //
244*23b7c7b8SHermès Bélusca-Maïto 
245*23b7c7b8SHermès Bélusca-Maïto     if (BaseLength != 0) {
246*23b7c7b8SHermès Bélusca-Maïto 
247*23b7c7b8SHermès Bélusca-Maïto         RtlCopyMemory( OutputString->Buffer, Dirent->FileName, BaseLength );
248*23b7c7b8SHermès Bélusca-Maïto 
249*23b7c7b8SHermès Bélusca-Maïto         if (OutputString->Buffer[0] == FAT_DIRENT_REALLY_0E5) {
250*23b7c7b8SHermès Bélusca-Maïto 
251*23b7c7b8SHermès Bélusca-Maïto             OutputString->Buffer[0] = 0xe5;
252*23b7c7b8SHermès Bélusca-Maïto         }
253*23b7c7b8SHermès Bélusca-Maïto 
254*23b7c7b8SHermès Bélusca-Maïto         //
255*23b7c7b8SHermès Bélusca-Maïto         //  Now if we are to restore case, look for A-Z
256*23b7c7b8SHermès Bélusca-Maïto         //
257*23b7c7b8SHermès Bélusca-Maïto 
258*23b7c7b8SHermès Bélusca-Maïto         if (FatData.ChicagoMode &&
259*23b7c7b8SHermès Bélusca-Maïto             RestoreCase &&
260*23b7c7b8SHermès Bélusca-Maïto             FlagOn(Dirent->NtByte, FAT_DIRENT_NT_BYTE_8_LOWER_CASE)) {
261*23b7c7b8SHermès Bélusca-Maïto 
262*23b7c7b8SHermès Bélusca-Maïto             for (StringIndex = 0; StringIndex < BaseLength; StringIndex += 1) {
263*23b7c7b8SHermès Bélusca-Maïto 
264*23b7c7b8SHermès Bélusca-Maïto                 //
265*23b7c7b8SHermès Bélusca-Maïto                 //  Depending on whether the media was built in a system that was
266*23b7c7b8SHermès Bélusca-Maïto                 //  running with "code page invariance" (see FatEvaluateNameCase),
267*23b7c7b8SHermès Bélusca-Maïto                 //  there could be double-byte OEM characters lying in wait here.
268*23b7c7b8SHermès Bélusca-Maïto                 //  Gotta skip them.
269*23b7c7b8SHermès Bélusca-Maïto                 //
270*23b7c7b8SHermès Bélusca-Maïto 
271*23b7c7b8SHermès Bélusca-Maïto                 if (FsRtlIsLeadDbcsCharacter(OutputString->Buffer[StringIndex])) {
272*23b7c7b8SHermès Bélusca-Maïto 
273*23b7c7b8SHermès Bélusca-Maïto                     StringIndex += 1;
274*23b7c7b8SHermès Bélusca-Maïto                     continue;
275*23b7c7b8SHermès Bélusca-Maïto                 }
276*23b7c7b8SHermès Bélusca-Maïto 
277*23b7c7b8SHermès Bélusca-Maïto                 if ((OutputString->Buffer[StringIndex] >= 'A') &&
278*23b7c7b8SHermès Bélusca-Maïto                     (OutputString->Buffer[StringIndex] <= 'Z')) {
279*23b7c7b8SHermès Bélusca-Maïto 
280*23b7c7b8SHermès Bélusca-Maïto                     OutputString->Buffer[StringIndex] += 'a' - 'A';
281*23b7c7b8SHermès Bélusca-Maïto                 }
282*23b7c7b8SHermès Bélusca-Maïto             }
283*23b7c7b8SHermès Bélusca-Maïto         }
284*23b7c7b8SHermès Bélusca-Maïto     }
285*23b7c7b8SHermès Bélusca-Maïto 
286*23b7c7b8SHermès Bélusca-Maïto     //
287*23b7c7b8SHermès Bélusca-Maïto     //  If there was an extension, copy that over.  Else we now know the
288*23b7c7b8SHermès Bélusca-Maïto     //  size of the string.
289*23b7c7b8SHermès Bélusca-Maïto     //
290*23b7c7b8SHermès Bélusca-Maïto 
291*23b7c7b8SHermès Bélusca-Maïto     if (ExtensionLength != 0) {
292*23b7c7b8SHermès Bélusca-Maïto 
293*23b7c7b8SHermès Bélusca-Maïto         PUCHAR o, d;
294*23b7c7b8SHermès Bélusca-Maïto 
295*23b7c7b8SHermès Bélusca-Maïto         //
296*23b7c7b8SHermès Bélusca-Maïto         //  Now add the dot
297*23b7c7b8SHermès Bélusca-Maïto         //
298*23b7c7b8SHermès Bélusca-Maïto 
299*23b7c7b8SHermès Bélusca-Maïto         OutputString->Buffer[BaseLength++] = '.';
300*23b7c7b8SHermès Bélusca-Maïto 
301*23b7c7b8SHermès Bélusca-Maïto         //
302*23b7c7b8SHermès Bélusca-Maïto         //  Copy over the extension into the output buffer.
303*23b7c7b8SHermès Bélusca-Maïto         //
304*23b7c7b8SHermès Bélusca-Maïto 
305*23b7c7b8SHermès Bélusca-Maïto         o = (PUCHAR)&OutputString->Buffer[BaseLength];
306*23b7c7b8SHermès Bélusca-Maïto         d = &Dirent->FileName[8];
307*23b7c7b8SHermès Bélusca-Maïto 
308*23b7c7b8SHermès Bélusca-Maïto         switch (ExtensionLength) {
309*23b7c7b8SHermès Bélusca-Maïto         case 3:
310*23b7c7b8SHermès Bélusca-Maïto             *o++ = *d++;
311*23b7c7b8SHermès Bélusca-Maïto         case 2:
312*23b7c7b8SHermès Bélusca-Maïto             *o++ = *d++;
313*23b7c7b8SHermès Bélusca-Maïto         case 1:
314*23b7c7b8SHermès Bélusca-Maïto             *o++ = *d++;
315*23b7c7b8SHermès Bélusca-Maïto         }
316*23b7c7b8SHermès Bélusca-Maïto 
317*23b7c7b8SHermès Bélusca-Maïto         //
318*23b7c7b8SHermès Bélusca-Maïto         //  Set the output string length
319*23b7c7b8SHermès Bélusca-Maïto         //
320*23b7c7b8SHermès Bélusca-Maïto 
321*23b7c7b8SHermès Bélusca-Maïto         OutputString->Length = (USHORT)(BaseLength + ExtensionLength);
322*23b7c7b8SHermès Bélusca-Maïto 
323*23b7c7b8SHermès Bélusca-Maïto         //
324*23b7c7b8SHermès Bélusca-Maïto         //  Now if we are to restore case, look for A-Z
325*23b7c7b8SHermès Bélusca-Maïto         //
326*23b7c7b8SHermès Bélusca-Maïto 
327*23b7c7b8SHermès Bélusca-Maïto         if (FatData.ChicagoMode &&
328*23b7c7b8SHermès Bélusca-Maïto             RestoreCase &&
329*23b7c7b8SHermès Bélusca-Maïto             FlagOn(Dirent->NtByte, FAT_DIRENT_NT_BYTE_3_LOWER_CASE)) {
330*23b7c7b8SHermès Bélusca-Maïto 
331*23b7c7b8SHermès Bélusca-Maïto             for (StringIndex = BaseLength;
332*23b7c7b8SHermès Bélusca-Maïto                  StringIndex < OutputString->Length;
333*23b7c7b8SHermès Bélusca-Maïto                  StringIndex++ ) {
334*23b7c7b8SHermès Bélusca-Maïto 
335*23b7c7b8SHermès Bélusca-Maïto                 //
336*23b7c7b8SHermès Bélusca-Maïto                 //  Depending on whether the media was built in a system that was
337*23b7c7b8SHermès Bélusca-Maïto                 //  running with "code page invariance" (see FatEvaluateNameCase),
338*23b7c7b8SHermès Bélusca-Maïto                 //  there could be double-byte OEM characters lying in wait here.
339*23b7c7b8SHermès Bélusca-Maïto                 //  Gotta skip them.
340*23b7c7b8SHermès Bélusca-Maïto                 //
341*23b7c7b8SHermès Bélusca-Maïto 
342*23b7c7b8SHermès Bélusca-Maïto                 if (FsRtlIsLeadDbcsCharacter(OutputString->Buffer[StringIndex])) {
343*23b7c7b8SHermès Bélusca-Maïto 
344*23b7c7b8SHermès Bélusca-Maïto                     StringIndex += 1;
345*23b7c7b8SHermès Bélusca-Maïto                     continue;
346*23b7c7b8SHermès Bélusca-Maïto                 }
347*23b7c7b8SHermès Bélusca-Maïto 
348*23b7c7b8SHermès Bélusca-Maïto                 if ((OutputString->Buffer[StringIndex] >= 'A') &&
349*23b7c7b8SHermès Bélusca-Maïto                     (OutputString->Buffer[StringIndex] <= 'Z')) {
350*23b7c7b8SHermès Bélusca-Maïto 
351*23b7c7b8SHermès Bélusca-Maïto                     OutputString->Buffer[StringIndex] += 'a' - 'A';
352*23b7c7b8SHermès Bélusca-Maïto                 }
353*23b7c7b8SHermès Bélusca-Maïto             }
354*23b7c7b8SHermès Bélusca-Maïto         }
355*23b7c7b8SHermès Bélusca-Maïto 
356*23b7c7b8SHermès Bélusca-Maïto     } else {
357*23b7c7b8SHermès Bélusca-Maïto 
358*23b7c7b8SHermès Bélusca-Maïto         //
359*23b7c7b8SHermès Bélusca-Maïto         //  Set the output string length
360*23b7c7b8SHermès Bélusca-Maïto         //
361*23b7c7b8SHermès Bélusca-Maïto 
362*23b7c7b8SHermès Bélusca-Maïto         OutputString->Length = (USHORT)BaseLength;
363*23b7c7b8SHermès Bélusca-Maïto     }
364*23b7c7b8SHermès Bélusca-Maïto 
365*23b7c7b8SHermès Bélusca-Maïto     //
366*23b7c7b8SHermès Bélusca-Maïto     //  And return to our caller
367*23b7c7b8SHermès Bélusca-Maïto     //
368*23b7c7b8SHermès Bélusca-Maïto 
369*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(-1, Dbg, "Fat8dot3ToString, OutputString = \"%Z\" -> VOID\n", OutputString);
370*23b7c7b8SHermès Bélusca-Maïto 
371*23b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( IrpContext );
372*23b7c7b8SHermès Bélusca-Maïto 
373*23b7c7b8SHermès Bélusca-Maïto     return;
374*23b7c7b8SHermès Bélusca-Maïto }
375*23b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)376*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
377*23b7c7b8SHermès Bélusca-Maïto VOID
378*23b7c7b8SHermès Bélusca-Maïto FatGetUnicodeNameFromFcb (
379*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
380*23b7c7b8SHermès Bélusca-Maïto     IN PFCB Fcb,
381*23b7c7b8SHermès Bélusca-Maïto     IN OUT PUNICODE_STRING Lfn
382*23b7c7b8SHermès Bélusca-Maïto     )
383*23b7c7b8SHermès Bélusca-Maïto 
384*23b7c7b8SHermès Bélusca-Maïto /*++
385*23b7c7b8SHermès Bélusca-Maïto 
386*23b7c7b8SHermès Bélusca-Maïto Routine Description:
387*23b7c7b8SHermès Bélusca-Maïto 
388*23b7c7b8SHermès Bélusca-Maïto     This routine will return the unicode name for a given Fcb.  If the
389*23b7c7b8SHermès Bélusca-Maïto     file has an LFN, it will return this.  Otherwise it will return
390*23b7c7b8SHermès Bélusca-Maïto     the UNICODE conversion of the Oem name, properly cased.
391*23b7c7b8SHermès Bélusca-Maïto 
392*23b7c7b8SHermès Bélusca-Maïto Arguments:
393*23b7c7b8SHermès Bélusca-Maïto 
394*23b7c7b8SHermès Bélusca-Maïto     Fcb - Supplies the Fcb to query.
395*23b7c7b8SHermès Bélusca-Maïto 
396*23b7c7b8SHermès Bélusca-Maïto     Lfn - Supplies a string that already has enough storage for the
397*23b7c7b8SHermès Bélusca-Maïto         full unicode name.
398*23b7c7b8SHermès Bélusca-Maïto 
399*23b7c7b8SHermès Bélusca-Maïto Return Value:
400*23b7c7b8SHermès Bélusca-Maïto 
401*23b7c7b8SHermès Bélusca-Maïto     None
402*23b7c7b8SHermès Bélusca-Maïto 
403*23b7c7b8SHermès Bélusca-Maïto --*/
404*23b7c7b8SHermès Bélusca-Maïto 
405*23b7c7b8SHermès Bélusca-Maïto {
406*23b7c7b8SHermès Bélusca-Maïto     PDIRENT Dirent;
407*23b7c7b8SHermès Bélusca-Maïto     PBCB DirentBcb = NULL;
408*23b7c7b8SHermès Bélusca-Maïto     ULONG DirentByteOffset;
409*23b7c7b8SHermès Bélusca-Maïto 
410*23b7c7b8SHermès Bélusca-Maïto     CCB LocalCcb;
411*23b7c7b8SHermès Bélusca-Maïto 
412*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
413*23b7c7b8SHermès Bélusca-Maïto 
414*23b7c7b8SHermès Bélusca-Maïto     NT_ASSERT((MAX_LFN_CHARACTERS * sizeof( WCHAR)) == Lfn->MaximumLength);
415*23b7c7b8SHermès Bélusca-Maïto 
416*23b7c7b8SHermès Bélusca-Maïto     //
417*23b7c7b8SHermès Bélusca-Maïto     //  We'll start by locating the dirent for the name.
418*23b7c7b8SHermès Bélusca-Maïto     //
419*23b7c7b8SHermès Bélusca-Maïto 
420*23b7c7b8SHermès Bélusca-Maïto     FatStringTo8dot3( IrpContext,
421*23b7c7b8SHermès Bélusca-Maïto                       Fcb->ShortName.Name.Oem,
422*23b7c7b8SHermès Bélusca-Maïto                       &LocalCcb.OemQueryTemplate.Constant );
423*23b7c7b8SHermès Bélusca-Maïto 
424*23b7c7b8SHermès Bélusca-Maïto     LocalCcb.Flags = 0;
425*23b7c7b8SHermès Bélusca-Maïto     LocalCcb.UnicodeQueryTemplate.Length = 0;
426*23b7c7b8SHermès Bélusca-Maïto     LocalCcb.ContainsWildCards = FALSE;
427*23b7c7b8SHermès Bélusca-Maïto 
428*23b7c7b8SHermès Bélusca-Maïto     FatLocateDirent( IrpContext,
429*23b7c7b8SHermès Bélusca-Maïto                      Fcb->ParentDcb,
430*23b7c7b8SHermès Bélusca-Maïto                      &LocalCcb,
431*23b7c7b8SHermès Bélusca-Maïto                      Fcb->LfnOffsetWithinDirectory,
432*23b7c7b8SHermès Bélusca-Maïto                      NULL,
433*23b7c7b8SHermès Bélusca-Maïto                      &Dirent,
434*23b7c7b8SHermès Bélusca-Maïto                      &DirentBcb,
435*23b7c7b8SHermès Bélusca-Maïto                      (PVBO)&DirentByteOffset,
436*23b7c7b8SHermès Bélusca-Maïto                      NULL,
437*23b7c7b8SHermès Bélusca-Maïto                      Lfn,
438*23b7c7b8SHermès Bélusca-Maïto                      NULL );
439*23b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
440*23b7c7b8SHermès Bélusca-Maïto 
441*23b7c7b8SHermès Bélusca-Maïto         //
442*23b7c7b8SHermès Bélusca-Maïto         //  If we didn't find the Dirent, something is terribly wrong.
443*23b7c7b8SHermès Bélusca-Maïto         //
444*23b7c7b8SHermès Bélusca-Maïto 
445*23b7c7b8SHermès Bélusca-Maïto         if ((DirentBcb == NULL) ||
446*23b7c7b8SHermès Bélusca-Maïto             (DirentByteOffset != Fcb->DirentOffsetWithinDirectory)) {
447*23b7c7b8SHermès Bélusca-Maïto 
448*23b7c7b8SHermès Bélusca-Maïto             FatRaiseStatus( IrpContext, STATUS_FILE_INVALID );
449*23b7c7b8SHermès Bélusca-Maïto         }
450*23b7c7b8SHermès Bélusca-Maïto 
451*23b7c7b8SHermès Bélusca-Maïto         //
452*23b7c7b8SHermès Bélusca-Maïto         //  Check for the easy case.
453*23b7c7b8SHermès Bélusca-Maïto         //
454*23b7c7b8SHermès Bélusca-Maïto 
455*23b7c7b8SHermès Bélusca-Maïto         if (Lfn->Length == 0) {
456*23b7c7b8SHermès Bélusca-Maïto 
457*23b7c7b8SHermès Bélusca-Maïto             NTSTATUS Status;
458*23b7c7b8SHermès Bélusca-Maïto             OEM_STRING ShortName;
459*23b7c7b8SHermès Bélusca-Maïto             UCHAR ShortNameBuffer[12];
460*23b7c7b8SHermès Bélusca-Maïto 
461*23b7c7b8SHermès Bélusca-Maïto             //
462*23b7c7b8SHermès Bélusca-Maïto             //  If we thought that there was an LFN here and didn't find one,
463*23b7c7b8SHermès Bélusca-Maïto             //  we're as dead.  This shouldn't happen in normal operation, but
464*23b7c7b8SHermès Bélusca-Maïto             //  if someone scrambles a directory by hand ...
465*23b7c7b8SHermès Bélusca-Maïto             //
466*23b7c7b8SHermès Bélusca-Maïto 
467*23b7c7b8SHermès Bélusca-Maïto             NT_ASSERT( Fcb->LfnOffsetWithinDirectory == Fcb->DirentOffsetWithinDirectory );
468*23b7c7b8SHermès Bélusca-Maïto 
469*23b7c7b8SHermès Bélusca-Maïto             if (Fcb->LfnOffsetWithinDirectory != Fcb->DirentOffsetWithinDirectory) {
470*23b7c7b8SHermès Bélusca-Maïto 
471*23b7c7b8SHermès Bélusca-Maïto                 FatRaiseStatus( IrpContext, STATUS_FILE_INVALID );
472*23b7c7b8SHermès Bélusca-Maïto             }
473*23b7c7b8SHermès Bélusca-Maïto 
474*23b7c7b8SHermès Bélusca-Maïto             //
475*23b7c7b8SHermès Bélusca-Maïto             //  There is no LFN, so manufacture a UNICODE name.
476*23b7c7b8SHermès Bélusca-Maïto             //
477*23b7c7b8SHermès Bélusca-Maïto 
478*23b7c7b8SHermès Bélusca-Maïto             ShortName.Length = 0;
479*23b7c7b8SHermès Bélusca-Maïto             ShortName.MaximumLength = 12;
480*23b7c7b8SHermès Bélusca-Maïto             ShortName.Buffer = (PCHAR)ShortNameBuffer;
481*23b7c7b8SHermès Bélusca-Maïto 
482*23b7c7b8SHermès Bélusca-Maïto             Fat8dot3ToString( IrpContext, Dirent, TRUE, &ShortName );
483*23b7c7b8SHermès Bélusca-Maïto 
484*23b7c7b8SHermès Bélusca-Maïto             //
485*23b7c7b8SHermès Bélusca-Maïto             //  OK, now convert this string to UNICODE
486*23b7c7b8SHermès Bélusca-Maïto             //
487*23b7c7b8SHermès Bélusca-Maïto 
488*23b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
489*23b7c7b8SHermès Bélusca-Maïto #pragma prefast( suppress:28931, "needed for debug build" )
490*23b7c7b8SHermès Bélusca-Maïto #endif
491*23b7c7b8SHermès Bélusca-Maïto             Status = RtlOemStringToCountedUnicodeString( Lfn,
492*23b7c7b8SHermès Bélusca-Maïto                                                          &ShortName,
493*23b7c7b8SHermès Bélusca-Maïto                                                          FALSE );
494*23b7c7b8SHermès Bélusca-Maïto 
495*23b7c7b8SHermès Bélusca-Maïto             NT_ASSERT( Status == STATUS_SUCCESS );
496*23b7c7b8SHermès Bélusca-Maïto         }
497*23b7c7b8SHermès Bélusca-Maïto 
498*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
499*23b7c7b8SHermès Bélusca-Maïto 
500*23b7c7b8SHermès Bélusca-Maïto         FatUnpinBcb( IrpContext, DirentBcb );
501*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
502*23b7c7b8SHermès Bélusca-Maïto }
503*23b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)504*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
505*23b7c7b8SHermès Bélusca-Maïto VOID
506*23b7c7b8SHermès Bélusca-Maïto FatSetFullFileNameInFcb (
507*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
508*23b7c7b8SHermès Bélusca-Maïto     IN PFCB Fcb
509*23b7c7b8SHermès Bélusca-Maïto     )
510*23b7c7b8SHermès Bélusca-Maïto 
511*23b7c7b8SHermès Bélusca-Maïto /*++
512*23b7c7b8SHermès Bélusca-Maïto 
513*23b7c7b8SHermès Bélusca-Maïto Routine Description:
514*23b7c7b8SHermès Bélusca-Maïto 
515*23b7c7b8SHermès Bélusca-Maïto     If the FullFileName field in the Fcb has not yet been filled in, we
516*23b7c7b8SHermès Bélusca-Maïto     proceed to do so.
517*23b7c7b8SHermès Bélusca-Maïto 
518*23b7c7b8SHermès Bélusca-Maïto Arguments:
519*23b7c7b8SHermès Bélusca-Maïto 
520*23b7c7b8SHermès Bélusca-Maïto     Fcb - Supplies the file.
521*23b7c7b8SHermès Bélusca-Maïto 
522*23b7c7b8SHermès Bélusca-Maïto Return Value:
523*23b7c7b8SHermès Bélusca-Maïto 
524*23b7c7b8SHermès Bélusca-Maïto     None
525*23b7c7b8SHermès Bélusca-Maïto 
526*23b7c7b8SHermès Bélusca-Maïto --*/
527*23b7c7b8SHermès Bélusca-Maïto 
528*23b7c7b8SHermès Bélusca-Maïto {
529*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
530*23b7c7b8SHermès Bélusca-Maïto 
531*23b7c7b8SHermès Bélusca-Maïto     if (Fcb->FullFileName.Buffer == NULL) {
532*23b7c7b8SHermès Bélusca-Maïto 
533*23b7c7b8SHermès Bélusca-Maïto         UNICODE_STRING Lfn;
534*23b7c7b8SHermès Bélusca-Maïto         PFCB TmpFcb = Fcb;
535*23b7c7b8SHermès Bélusca-Maïto         PFCB StopFcb;
536*23b7c7b8SHermès Bélusca-Maïto         PWCHAR TmpBuffer;
537*23b7c7b8SHermès Bélusca-Maïto         ULONG PathLength = 0;
538*23b7c7b8SHermès Bélusca-Maïto 
539*23b7c7b8SHermès Bélusca-Maïto         //
540*23b7c7b8SHermès Bélusca-Maïto         //  We will assume we do this infrequently enough, that it's OK to
541*23b7c7b8SHermès Bélusca-Maïto         //  to a pool allocation here.
542*23b7c7b8SHermès Bélusca-Maïto         //
543*23b7c7b8SHermès Bélusca-Maïto 
544*23b7c7b8SHermès Bélusca-Maïto         Lfn.Length = 0;
545*23b7c7b8SHermès Bélusca-Maïto         Lfn.MaximumLength = MAX_LFN_CHARACTERS * sizeof(WCHAR);
546*23b7c7b8SHermès Bélusca-Maïto         Lfn.Buffer = FsRtlAllocatePoolWithTag( PagedPool,
547*23b7c7b8SHermès Bélusca-Maïto                                                MAX_LFN_CHARACTERS * sizeof(WCHAR),
548*23b7c7b8SHermès Bélusca-Maïto                                                TAG_FILENAME_BUFFER );
549*23b7c7b8SHermès Bélusca-Maïto 
550*23b7c7b8SHermès Bélusca-Maïto         _SEH2_TRY {
551*23b7c7b8SHermès Bélusca-Maïto 
552*23b7c7b8SHermès Bélusca-Maïto             //
553*23b7c7b8SHermès Bélusca-Maïto             //  First determine how big the name will be.  If we find an
554*23b7c7b8SHermès Bélusca-Maïto             //  ancestor with a FullFileName, our work is easier.
555*23b7c7b8SHermès Bélusca-Maïto             //
556*23b7c7b8SHermès Bélusca-Maïto 
557*23b7c7b8SHermès Bélusca-Maïto             while (TmpFcb != Fcb->Vcb->RootDcb) {
558*23b7c7b8SHermès Bélusca-Maïto 
559*23b7c7b8SHermès Bélusca-Maïto                 if ((TmpFcb != Fcb) && (TmpFcb->FullFileName.Buffer != NULL)) {
560*23b7c7b8SHermès Bélusca-Maïto 
561*23b7c7b8SHermès Bélusca-Maïto                     PathLength += TmpFcb->FullFileName.Length;
562*23b7c7b8SHermès Bélusca-Maïto 
563*23b7c7b8SHermès Bélusca-Maïto                     Fcb->FullFileName.Buffer = FsRtlAllocatePoolWithTag( PagedPool,
564*23b7c7b8SHermès Bélusca-Maïto                                                                          PathLength,
565*23b7c7b8SHermès Bélusca-Maïto                                                                          TAG_FILENAME_BUFFER );
566*23b7c7b8SHermès Bélusca-Maïto 
567*23b7c7b8SHermès Bélusca-Maïto                     RtlCopyMemory( Fcb->FullFileName.Buffer,
568*23b7c7b8SHermès Bélusca-Maïto                                    TmpFcb->FullFileName.Buffer,
569*23b7c7b8SHermès Bélusca-Maïto                                    TmpFcb->FullFileName.Length );
570*23b7c7b8SHermès Bélusca-Maïto 
571*23b7c7b8SHermès Bélusca-Maïto                     break;
572*23b7c7b8SHermès Bélusca-Maïto                 }
573*23b7c7b8SHermès Bélusca-Maïto 
574*23b7c7b8SHermès Bélusca-Maïto                 PathLength += TmpFcb->FinalNameLength + sizeof(WCHAR);
575*23b7c7b8SHermès Bélusca-Maïto 
576*23b7c7b8SHermès Bélusca-Maïto                 TmpFcb = TmpFcb->ParentDcb;
577*23b7c7b8SHermès Bélusca-Maïto             }
578*23b7c7b8SHermès Bélusca-Maïto 
579*23b7c7b8SHermès Bélusca-Maïto             //
580*23b7c7b8SHermès Bélusca-Maïto             //  If FullFileName.Buffer is still NULL, allocate it.
581*23b7c7b8SHermès Bélusca-Maïto             //
582*23b7c7b8SHermès Bélusca-Maïto 
583*23b7c7b8SHermès Bélusca-Maïto             if (Fcb->FullFileName.Buffer == NULL) {
584*23b7c7b8SHermès Bélusca-Maïto 
585*23b7c7b8SHermès Bélusca-Maïto                 Fcb->FullFileName.Buffer = FsRtlAllocatePoolWithTag( PagedPool,
586*23b7c7b8SHermès Bélusca-Maïto                                                                      PathLength,
587*23b7c7b8SHermès Bélusca-Maïto                                                                      TAG_FILENAME_BUFFER );
588*23b7c7b8SHermès Bélusca-Maïto             }
589*23b7c7b8SHermès Bélusca-Maïto 
590*23b7c7b8SHermès Bélusca-Maïto             StopFcb = TmpFcb;
591*23b7c7b8SHermès Bélusca-Maïto 
592*23b7c7b8SHermès Bélusca-Maïto             TmpFcb = Fcb;
593*23b7c7b8SHermès Bélusca-Maïto             TmpBuffer =  Fcb->FullFileName.Buffer + PathLength / sizeof(WCHAR);
594*23b7c7b8SHermès Bélusca-Maïto 
595*23b7c7b8SHermès Bélusca-Maïto             Fcb->FullFileName.Length =
596*23b7c7b8SHermès Bélusca-Maïto             Fcb->FullFileName.MaximumLength = (USHORT)PathLength;
597*23b7c7b8SHermès Bélusca-Maïto 
598*23b7c7b8SHermès Bélusca-Maïto             while (TmpFcb != StopFcb) {
599*23b7c7b8SHermès Bélusca-Maïto 
600*23b7c7b8SHermès Bélusca-Maïto                 FatGetUnicodeNameFromFcb( IrpContext,
601*23b7c7b8SHermès Bélusca-Maïto                                           TmpFcb,
602*23b7c7b8SHermès Bélusca-Maïto                                           &Lfn );
603*23b7c7b8SHermès Bélusca-Maïto 
604*23b7c7b8SHermès Bélusca-Maïto                 TmpBuffer -= Lfn.Length / sizeof(WCHAR);
605*23b7c7b8SHermès Bélusca-Maïto 
606*23b7c7b8SHermès Bélusca-Maïto                 RtlCopyMemory( TmpBuffer, Lfn.Buffer, Lfn.Length );
607*23b7c7b8SHermès Bélusca-Maïto 
608*23b7c7b8SHermès Bélusca-Maïto                 TmpBuffer -= 1;
609*23b7c7b8SHermès Bélusca-Maïto 
610*23b7c7b8SHermès Bélusca-Maïto                 *TmpBuffer = L'\\';
611*23b7c7b8SHermès Bélusca-Maïto 
612*23b7c7b8SHermès Bélusca-Maïto                 TmpFcb = TmpFcb->ParentDcb;
613*23b7c7b8SHermès Bélusca-Maïto             }
614*23b7c7b8SHermès Bélusca-Maïto 
615*23b7c7b8SHermès Bélusca-Maïto         } _SEH2_FINALLY {
616*23b7c7b8SHermès Bélusca-Maïto 
617*23b7c7b8SHermès Bélusca-Maïto             if (_SEH2_AbnormalTermination()) {
618*23b7c7b8SHermès Bélusca-Maïto 
619*23b7c7b8SHermès Bélusca-Maïto                 if (Fcb->FullFileName.Buffer) {
620*23b7c7b8SHermès Bélusca-Maïto 
621*23b7c7b8SHermès Bélusca-Maïto                     ExFreePool( Fcb->FullFileName.Buffer );
622*23b7c7b8SHermès Bélusca-Maïto                     Fcb->FullFileName.Buffer = NULL;
623*23b7c7b8SHermès Bélusca-Maïto                 }
624*23b7c7b8SHermès Bélusca-Maïto             }
625*23b7c7b8SHermès Bélusca-Maïto 
626*23b7c7b8SHermès Bélusca-Maïto             ExFreePool( Lfn.Buffer );
627*23b7c7b8SHermès Bélusca-Maïto         } _SEH2_END;
628*23b7c7b8SHermès Bélusca-Maïto     }
629*23b7c7b8SHermès Bélusca-Maïto }
630*23b7c7b8SHermès Bélusca-Maïto 
631*23b7c7b8SHermès Bélusca-Maïto VOID
FatUnicodeToUpcaseOem(IN PIRP_CONTEXT IrpContext,IN POEM_STRING OemString,IN PUNICODE_STRING UnicodeString)632*23b7c7b8SHermès Bélusca-Maïto FatUnicodeToUpcaseOem (
633*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
634*23b7c7b8SHermès Bélusca-Maïto     IN POEM_STRING OemString,
635*23b7c7b8SHermès Bélusca-Maïto     IN PUNICODE_STRING UnicodeString
636*23b7c7b8SHermès Bélusca-Maïto     )
637*23b7c7b8SHermès Bélusca-Maïto 
638*23b7c7b8SHermès Bélusca-Maïto /*++
639*23b7c7b8SHermès Bélusca-Maïto 
640*23b7c7b8SHermès Bélusca-Maïto Routine Description:
641*23b7c7b8SHermès Bélusca-Maïto 
642*23b7c7b8SHermès Bélusca-Maïto     This routine is our standard routine for trying to use stack space
643*23b7c7b8SHermès Bélusca-Maïto     if possible when calling RtlUpcaseUnicodeStringToCountedOemString().
644*23b7c7b8SHermès Bélusca-Maïto 
645*23b7c7b8SHermès Bélusca-Maïto     If an unmappable character is encountered, we set the destination
646*23b7c7b8SHermès Bélusca-Maïto     length to 0.
647*23b7c7b8SHermès Bélusca-Maïto 
648*23b7c7b8SHermès Bélusca-Maïto Arguments:
649*23b7c7b8SHermès Bélusca-Maïto 
650*23b7c7b8SHermès Bélusca-Maïto     OemString - Specifies the destination string.  Space is already assumed to
651*23b7c7b8SHermès Bélusca-Maïto         be allocated.  If there is not enough, then we allocate enough
652*23b7c7b8SHermès Bélusca-Maïto         space.
653*23b7c7b8SHermès Bélusca-Maïto 
654*23b7c7b8SHermès Bélusca-Maïto     UnicodeString - Specifies the source string.
655*23b7c7b8SHermès Bélusca-Maïto 
656*23b7c7b8SHermès Bélusca-Maïto Return Value:
657*23b7c7b8SHermès Bélusca-Maïto 
658*23b7c7b8SHermès Bélusca-Maïto     None.
659*23b7c7b8SHermès Bélusca-Maïto 
660*23b7c7b8SHermès Bélusca-Maïto --*/
661*23b7c7b8SHermès Bélusca-Maïto 
662*23b7c7b8SHermès Bélusca-Maïto {
663*23b7c7b8SHermès Bélusca-Maïto     NTSTATUS Status;
664*23b7c7b8SHermès Bélusca-Maïto 
665*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
666*23b7c7b8SHermès Bélusca-Maïto 
667*23b7c7b8SHermès Bélusca-Maïto     Status = RtlUpcaseUnicodeStringToCountedOemString( OemString,
668*23b7c7b8SHermès Bélusca-Maïto                                                        UnicodeString,
669*23b7c7b8SHermès Bélusca-Maïto                                                        FALSE );
670*23b7c7b8SHermès Bélusca-Maïto 
671*23b7c7b8SHermès Bélusca-Maïto     if (Status == STATUS_BUFFER_OVERFLOW) {
672*23b7c7b8SHermès Bélusca-Maïto 
673*23b7c7b8SHermès Bélusca-Maïto         OemString->Buffer = NULL;
674*23b7c7b8SHermès Bélusca-Maïto         OemString->Length = 0;
675*23b7c7b8SHermès Bélusca-Maïto         OemString->MaximumLength = 0;
676*23b7c7b8SHermès Bélusca-Maïto 
677*23b7c7b8SHermès Bélusca-Maïto         Status = RtlUpcaseUnicodeStringToCountedOemString( OemString,
678*23b7c7b8SHermès Bélusca-Maïto                                                            UnicodeString,
679*23b7c7b8SHermès Bélusca-Maïto                                                            TRUE );
680*23b7c7b8SHermès Bélusca-Maïto     }
681*23b7c7b8SHermès Bélusca-Maïto 
682*23b7c7b8SHermès Bélusca-Maïto     if (!NT_SUCCESS(Status)) {
683*23b7c7b8SHermès Bélusca-Maïto 
684*23b7c7b8SHermès Bélusca-Maïto         if (Status == STATUS_UNMAPPABLE_CHARACTER) {
685*23b7c7b8SHermès Bélusca-Maïto 
686*23b7c7b8SHermès Bélusca-Maïto             OemString->Length = 0;
687*23b7c7b8SHermès Bélusca-Maïto 
688*23b7c7b8SHermès Bélusca-Maïto         } else {
689*23b7c7b8SHermès Bélusca-Maïto 
690*23b7c7b8SHermès Bélusca-Maïto             FatNormalizeAndRaiseStatus( IrpContext, Status );
691*23b7c7b8SHermès Bélusca-Maïto         }
692*23b7c7b8SHermès Bélusca-Maïto     }
693*23b7c7b8SHermès Bélusca-Maïto 
694*23b7c7b8SHermès Bélusca-Maïto     return;
695*23b7c7b8SHermès Bélusca-Maïto }
696*23b7c7b8SHermès Bélusca-Maïto 
697*23b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)698*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
699*23b7c7b8SHermès Bélusca-Maïto VOID
700*23b7c7b8SHermès Bélusca-Maïto FatSelectNames (
701*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
702*23b7c7b8SHermès Bélusca-Maïto     IN PDCB Parent,
703*23b7c7b8SHermès Bélusca-Maïto     IN POEM_STRING OemName,
704*23b7c7b8SHermès Bélusca-Maïto     IN PUNICODE_STRING UnicodeName,
705*23b7c7b8SHermès Bélusca-Maïto     IN OUT POEM_STRING ShortName,
706*23b7c7b8SHermès Bélusca-Maïto     IN PUNICODE_STRING SuggestedShortName OPTIONAL,
707*23b7c7b8SHermès Bélusca-Maïto     IN OUT BOOLEAN *AllLowerComponent,
708*23b7c7b8SHermès Bélusca-Maïto     IN OUT BOOLEAN *AllLowerExtension,
709*23b7c7b8SHermès Bélusca-Maïto     IN OUT BOOLEAN *CreateLfn
710*23b7c7b8SHermès Bélusca-Maïto     )
711*23b7c7b8SHermès Bélusca-Maïto 
712*23b7c7b8SHermès Bélusca-Maïto /*++
713*23b7c7b8SHermès Bélusca-Maïto 
714*23b7c7b8SHermès Bélusca-Maïto Routine Description:
715*23b7c7b8SHermès Bélusca-Maïto 
716*23b7c7b8SHermès Bélusca-Maïto     This routine takes the original UNICODE string that the user specified,
717*23b7c7b8SHermès Bélusca-Maïto     and the upcased Oem equivalent.  This routine then decides if the OemName
718*23b7c7b8SHermès Bélusca-Maïto     is acceptable for dirent, or whether a short name has to be manufactured.
719*23b7c7b8SHermès Bélusca-Maïto 
720*23b7c7b8SHermès Bélusca-Maïto     Two values are returned to the caller.  One tells the caller if the name
721*23b7c7b8SHermès Bélusca-Maïto     happens to be all lower case < 0x80.  In this special case we don't
722*23b7c7b8SHermès Bélusca-Maïto     have to create an Lfn.  Also we tell the caller if it must create an LFN.
723*23b7c7b8SHermès Bélusca-Maïto 
724*23b7c7b8SHermès Bélusca-Maïto Arguments:
725*23b7c7b8SHermès Bélusca-Maïto 
726*23b7c7b8SHermès Bélusca-Maïto     OemName -  Supplies the proposed short Oem name.
727*23b7c7b8SHermès Bélusca-Maïto 
728*23b7c7b8SHermès Bélusca-Maïto     ShortName - If this OemName is OK for storeage in a dirent it is copied to
729*23b7c7b8SHermès Bélusca-Maïto         this string, otherwise this string is filled with a name that is OK.
730*23b7c7b8SHermès Bélusca-Maïto         If OemName and ShortName are the same string, no copy is done.
731*23b7c7b8SHermès Bélusca-Maïto 
732*23b7c7b8SHermès Bélusca-Maïto     UnicodeName - Provides the original final name.
733*23b7c7b8SHermès Bélusca-Maïto 
734*23b7c7b8SHermès Bélusca-Maïto     SuggestedShortName - a first-try short name to try before auto-generation
735*23b7c7b8SHermès Bélusca-Maïto         is used
736*23b7c7b8SHermès Bélusca-Maïto 
737*23b7c7b8SHermès Bélusca-Maïto     AllLowerComponent - Returns whether this component was all lower case.
738*23b7c7b8SHermès Bélusca-Maïto 
739*23b7c7b8SHermès Bélusca-Maïto     AllLowerExtension - Returns wheather the extension was all lower case.
740*23b7c7b8SHermès Bélusca-Maïto 
741*23b7c7b8SHermès Bélusca-Maïto     CreateLfn - Tells the caller if we must create an LFN for the UnicodeName or
742*23b7c7b8SHermès Bélusca-Maïto         SuggestedLongName
743*23b7c7b8SHermès Bélusca-Maïto 
744*23b7c7b8SHermès Bélusca-Maïto Return Value:
745*23b7c7b8SHermès Bélusca-Maïto 
746*23b7c7b8SHermès Bélusca-Maïto     None.
747*23b7c7b8SHermès Bélusca-Maïto 
748*23b7c7b8SHermès Bélusca-Maïto --*/
749*23b7c7b8SHermès Bélusca-Maïto 
750*23b7c7b8SHermès Bélusca-Maïto {
751*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN GenerateShortName;
752*23b7c7b8SHermès Bélusca-Maïto 
753*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
754*23b7c7b8SHermès Bélusca-Maïto 
755*23b7c7b8SHermès Bélusca-Maïto     //
756*23b7c7b8SHermès Bélusca-Maïto     //  First see if we must generate a short name.
757*23b7c7b8SHermès Bélusca-Maïto     //
758*23b7c7b8SHermès Bélusca-Maïto 
759*23b7c7b8SHermès Bélusca-Maïto     if ((OemName->Length == 0) ||
760*23b7c7b8SHermès Bélusca-Maïto         !FatIsNameShortOemValid( IrpContext, *OemName, FALSE, FALSE, FALSE ) ||
761*23b7c7b8SHermès Bélusca-Maïto         FatSpaceInName( IrpContext, UnicodeName )) {
762*23b7c7b8SHermès Bélusca-Maïto 
763*23b7c7b8SHermès Bélusca-Maïto         WCHAR ShortNameBuffer[12];
764*23b7c7b8SHermès Bélusca-Maïto         UNICODE_STRING ShortUnicodeName;
765*23b7c7b8SHermès Bélusca-Maïto         GENERATE_NAME_CONTEXT Context;
766*23b7c7b8SHermès Bélusca-Maïto         BOOLEAN TrySuggestedShortName;
767*23b7c7b8SHermès Bélusca-Maïto 
768*23b7c7b8SHermès Bélusca-Maïto         PDIRENT Dirent;
769*23b7c7b8SHermès Bélusca-Maïto         PBCB Bcb = NULL;
770*23b7c7b8SHermès Bélusca-Maïto         ULONG ByteOffset;
771*23b7c7b8SHermès Bélusca-Maïto         NTSTATUS Status;
772*23b7c7b8SHermès Bélusca-Maïto 
773*23b7c7b8SHermès Bélusca-Maïto         GenerateShortName = TRUE;
774*23b7c7b8SHermès Bélusca-Maïto 
775*23b7c7b8SHermès Bélusca-Maïto         TrySuggestedShortName = (SuggestedShortName != NULL);
776*23b7c7b8SHermès Bélusca-Maïto 
777*23b7c7b8SHermès Bélusca-Maïto         //
778*23b7c7b8SHermès Bélusca-Maïto         //  Now generate a short name.
779*23b7c7b8SHermès Bélusca-Maïto         //
780*23b7c7b8SHermès Bélusca-Maïto 
781*23b7c7b8SHermès Bélusca-Maïto         ShortUnicodeName.Length = 0;
782*23b7c7b8SHermès Bélusca-Maïto         ShortUnicodeName.MaximumLength = 12 * sizeof(WCHAR);
783*23b7c7b8SHermès Bélusca-Maïto         ShortUnicodeName.Buffer = ShortNameBuffer;
784*23b7c7b8SHermès Bélusca-Maïto 
785*23b7c7b8SHermès Bélusca-Maïto         RtlZeroMemory( &Context, sizeof( GENERATE_NAME_CONTEXT ) );
786*23b7c7b8SHermès Bélusca-Maïto 
787*23b7c7b8SHermès Bélusca-Maïto         _SEH2_TRY {
788*23b7c7b8SHermès Bélusca-Maïto 
789*23b7c7b8SHermès Bélusca-Maïto             while ( TRUE ) {
790*23b7c7b8SHermès Bélusca-Maïto 
791*23b7c7b8SHermès Bélusca-Maïto                 FatUnpinBcb( IrpContext, Bcb );
792*23b7c7b8SHermès Bélusca-Maïto 
793*23b7c7b8SHermès Bélusca-Maïto                 if (TrySuggestedShortName) {
794*23b7c7b8SHermès Bélusca-Maïto 
795*23b7c7b8SHermès Bélusca-Maïto                     //
796*23b7c7b8SHermès Bélusca-Maïto                     //  Try our caller's candidate first. Note that this must have
797*23b7c7b8SHermès Bélusca-Maïto                     //  been uppercased previously.
798*23b7c7b8SHermès Bélusca-Maïto                     //
799*23b7c7b8SHermès Bélusca-Maïto 
800*23b7c7b8SHermès Bélusca-Maïto                     ShortUnicodeName.Length = SuggestedShortName->Length;
801*23b7c7b8SHermès Bélusca-Maïto                     ShortUnicodeName.MaximumLength = SuggestedShortName->MaximumLength;
802*23b7c7b8SHermès Bélusca-Maïto                     ShortUnicodeName.Buffer = SuggestedShortName->Buffer;
803*23b7c7b8SHermès Bélusca-Maïto 
804*23b7c7b8SHermès Bélusca-Maïto                     TrySuggestedShortName = FALSE;
805*23b7c7b8SHermès Bélusca-Maïto 
806*23b7c7b8SHermès Bélusca-Maïto                 } else {
807*23b7c7b8SHermès Bélusca-Maïto 
808*23b7c7b8SHermès Bélusca-Maïto                     RtlGenerate8dot3Name( UnicodeName, TRUE, &Context, &ShortUnicodeName );
809*23b7c7b8SHermès Bélusca-Maïto                 }
810*23b7c7b8SHermès Bélusca-Maïto 
811*23b7c7b8SHermès Bélusca-Maïto                 //
812*23b7c7b8SHermès Bélusca-Maïto                 //  We have a candidate, make sure it doesn't exist.
813*23b7c7b8SHermès Bélusca-Maïto                 //
814*23b7c7b8SHermès Bélusca-Maïto 
815*23b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
816*23b7c7b8SHermès Bélusca-Maïto #pragma prefast( suppress:28931, "needed for debug build" )
817*23b7c7b8SHermès Bélusca-Maïto #endif
818*23b7c7b8SHermès Bélusca-Maïto                 Status = RtlUnicodeStringToCountedOemString( ShortName,
819*23b7c7b8SHermès Bélusca-Maïto                                                              &ShortUnicodeName,
820*23b7c7b8SHermès Bélusca-Maïto                                                              FALSE );
821*23b7c7b8SHermès Bélusca-Maïto 
822*23b7c7b8SHermès Bélusca-Maïto                 NT_ASSERT( Status == STATUS_SUCCESS );
823*23b7c7b8SHermès Bélusca-Maïto 
824*23b7c7b8SHermès Bélusca-Maïto                 FatLocateSimpleOemDirent( IrpContext,
825*23b7c7b8SHermès Bélusca-Maïto                                           Parent,
826*23b7c7b8SHermès Bélusca-Maïto                                           ShortName,
827*23b7c7b8SHermès Bélusca-Maïto                                           &Dirent,
828*23b7c7b8SHermès Bélusca-Maïto                                           &Bcb,
829*23b7c7b8SHermès Bélusca-Maïto                                           (PVBO)&ByteOffset );
830*23b7c7b8SHermès Bélusca-Maïto 
831*23b7c7b8SHermès Bélusca-Maïto                 if (Bcb == NULL) {
832*23b7c7b8SHermès Bélusca-Maïto 
833*23b7c7b8SHermès Bélusca-Maïto                     _SEH2_LEAVE;
834*23b7c7b8SHermès Bélusca-Maïto 
835*23b7c7b8SHermès Bélusca-Maïto                 }
836*23b7c7b8SHermès Bélusca-Maïto             }
837*23b7c7b8SHermès Bélusca-Maïto 
838*23b7c7b8SHermès Bélusca-Maïto         } _SEH2_FINALLY {
839*23b7c7b8SHermès Bélusca-Maïto 
840*23b7c7b8SHermès Bélusca-Maïto             FatUnpinBcb( IrpContext, Bcb );
841*23b7c7b8SHermès Bélusca-Maïto         } _SEH2_END;
842*23b7c7b8SHermès Bélusca-Maïto 
843*23b7c7b8SHermès Bélusca-Maïto     } else {
844*23b7c7b8SHermès Bélusca-Maïto 
845*23b7c7b8SHermès Bélusca-Maïto         //
846*23b7c7b8SHermès Bélusca-Maïto         //  Only do this copy if the two string are indeed different.
847*23b7c7b8SHermès Bélusca-Maïto         //
848*23b7c7b8SHermès Bélusca-Maïto 
849*23b7c7b8SHermès Bélusca-Maïto         if (ShortName != OemName) {
850*23b7c7b8SHermès Bélusca-Maïto             ShortName->Length = OemName->Length;
851*23b7c7b8SHermès Bélusca-Maïto 
852*23b7c7b8SHermès Bélusca-Maïto             //
853*23b7c7b8SHermès Bélusca-Maïto             // If FsRtlIsFatDbcsLegal() on OemName fails, we will not
854*23b7c7b8SHermès Bélusca-Maïto             // be in this code path, so we infer that ShortName's
855*23b7c7b8SHermès Bélusca-Maïto             // buffer is big enough to hold the full FAT file name in
856*23b7c7b8SHermès Bélusca-Maïto             // OemName.
857*23b7c7b8SHermès Bélusca-Maïto             //
858*23b7c7b8SHermès Bélusca-Maïto 
859*23b7c7b8SHermès Bélusca-Maïto             _Analysis_assume_(ShortName->MaximumLength <= OemName->Length);
860*23b7c7b8SHermès Bélusca-Maïto 
861*23b7c7b8SHermès Bélusca-Maïto             RtlCopyMemory( ShortName->Buffer, OemName->Buffer, OemName->Length );
862*23b7c7b8SHermès Bélusca-Maïto         }
863*23b7c7b8SHermès Bélusca-Maïto 
864*23b7c7b8SHermès Bélusca-Maïto         GenerateShortName = FALSE;
865*23b7c7b8SHermès Bélusca-Maïto     }
866*23b7c7b8SHermès Bélusca-Maïto 
867*23b7c7b8SHermès Bélusca-Maïto     //
868*23b7c7b8SHermès Bélusca-Maïto     //  Now see if the caller will have to use unicode string as an LFN
869*23b7c7b8SHermès Bélusca-Maïto     //
870*23b7c7b8SHermès Bélusca-Maïto 
871*23b7c7b8SHermès Bélusca-Maïto     if (GenerateShortName) {
872*23b7c7b8SHermès Bélusca-Maïto 
873*23b7c7b8SHermès Bélusca-Maïto         *CreateLfn = TRUE;
874*23b7c7b8SHermès Bélusca-Maïto         *AllLowerComponent = FALSE;
875*23b7c7b8SHermès Bélusca-Maïto         *AllLowerExtension = FALSE;
876*23b7c7b8SHermès Bélusca-Maïto 
877*23b7c7b8SHermès Bélusca-Maïto     } else {
878*23b7c7b8SHermès Bélusca-Maïto 
879*23b7c7b8SHermès Bélusca-Maïto         FatEvaluateNameCase( IrpContext,
880*23b7c7b8SHermès Bélusca-Maïto                              UnicodeName,
881*23b7c7b8SHermès Bélusca-Maïto                              AllLowerComponent,
882*23b7c7b8SHermès Bélusca-Maïto                              AllLowerExtension,
883*23b7c7b8SHermès Bélusca-Maïto                              CreateLfn );
884*23b7c7b8SHermès Bélusca-Maïto     }
885*23b7c7b8SHermès Bélusca-Maïto 
886*23b7c7b8SHermès Bélusca-Maïto     return;
887*23b7c7b8SHermès Bélusca-Maïto }
888*23b7c7b8SHermès Bélusca-Maïto 
889*23b7c7b8SHermès Bélusca-Maïto 
890*23b7c7b8SHermès Bélusca-Maïto VOID
FatEvaluateNameCase(IN PIRP_CONTEXT IrpContext,IN PUNICODE_STRING UnicodeName,IN OUT BOOLEAN * AllLowerComponent,IN OUT BOOLEAN * AllLowerExtension,IN OUT BOOLEAN * CreateLfn)891*23b7c7b8SHermès Bélusca-Maïto FatEvaluateNameCase (
892*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
893*23b7c7b8SHermès Bélusca-Maïto     IN PUNICODE_STRING UnicodeName,
894*23b7c7b8SHermès Bélusca-Maïto     IN OUT BOOLEAN *AllLowerComponent,
895*23b7c7b8SHermès Bélusca-Maïto     IN OUT BOOLEAN *AllLowerExtension,
896*23b7c7b8SHermès Bélusca-Maïto     IN OUT BOOLEAN *CreateLfn
897*23b7c7b8SHermès Bélusca-Maïto     )
898*23b7c7b8SHermès Bélusca-Maïto 
899*23b7c7b8SHermès Bélusca-Maïto /*++
900*23b7c7b8SHermès Bélusca-Maïto 
901*23b7c7b8SHermès Bélusca-Maïto Routine Description:
902*23b7c7b8SHermès Bélusca-Maïto 
903*23b7c7b8SHermès Bélusca-Maïto     This routine takes a UNICODE string and sees if it is eligible for
904*23b7c7b8SHermès Bélusca-Maïto     the special case optimization.
905*23b7c7b8SHermès Bélusca-Maïto 
906*23b7c7b8SHermès Bélusca-Maïto Arguments:
907*23b7c7b8SHermès Bélusca-Maïto 
908*23b7c7b8SHermès Bélusca-Maïto     UnicodeName - Provides the original final name.
909*23b7c7b8SHermès Bélusca-Maïto 
910*23b7c7b8SHermès Bélusca-Maïto     AllLowerComponent - Returns whether this compoent was all lower case.
911*23b7c7b8SHermès Bélusca-Maïto 
912*23b7c7b8SHermès Bélusca-Maïto     AllLowerExtension - Returns wheather the extension was all lower case.
913*23b7c7b8SHermès Bélusca-Maïto 
914*23b7c7b8SHermès Bélusca-Maïto     CreateLfn - Tells the call if we must create an LFN for the UnicodeName.
915*23b7c7b8SHermès Bélusca-Maïto 
916*23b7c7b8SHermès Bélusca-Maïto Return Value:
917*23b7c7b8SHermès Bélusca-Maïto 
918*23b7c7b8SHermès Bélusca-Maïto     None.
919*23b7c7b8SHermès Bélusca-Maïto 
920*23b7c7b8SHermès Bélusca-Maïto --*/
921*23b7c7b8SHermès Bélusca-Maïto 
922*23b7c7b8SHermès Bélusca-Maïto {
923*23b7c7b8SHermès Bélusca-Maïto     ULONG i;
924*23b7c7b8SHermès Bélusca-Maïto     UCHAR Uppers = 0;
925*23b7c7b8SHermès Bélusca-Maïto     UCHAR Lowers = 0;
926*23b7c7b8SHermès Bélusca-Maïto 
927*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN ExtensionPresent = FALSE;
928*23b7c7b8SHermès Bélusca-Maïto 
929*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
930*23b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( IrpContext );
931*23b7c7b8SHermès Bélusca-Maïto 
932*23b7c7b8SHermès Bélusca-Maïto     *CreateLfn = FALSE;
933*23b7c7b8SHermès Bélusca-Maïto 
934*23b7c7b8SHermès Bélusca-Maïto     for (i = 0; i < UnicodeName->Length / sizeof(WCHAR); i++) {
935*23b7c7b8SHermès Bélusca-Maïto 
936*23b7c7b8SHermès Bélusca-Maïto         WCHAR c;
937*23b7c7b8SHermès Bélusca-Maïto 
938*23b7c7b8SHermès Bélusca-Maïto         c = UnicodeName->Buffer[i];
939*23b7c7b8SHermès Bélusca-Maïto 
940*23b7c7b8SHermès Bélusca-Maïto         if ((c >= 'A') && (c <= 'Z')) {
941*23b7c7b8SHermès Bélusca-Maïto 
942*23b7c7b8SHermès Bélusca-Maïto             Uppers += 1;
943*23b7c7b8SHermès Bélusca-Maïto 
944*23b7c7b8SHermès Bélusca-Maïto         } else if ((c >= 'a') && (c <= 'z')) {
945*23b7c7b8SHermès Bélusca-Maïto 
946*23b7c7b8SHermès Bélusca-Maïto             Lowers += 1;
947*23b7c7b8SHermès Bélusca-Maïto 
948*23b7c7b8SHermès Bélusca-Maïto         } else if ((c >= 0x0080) && FatData.CodePageInvariant) {
949*23b7c7b8SHermès Bélusca-Maïto 
950*23b7c7b8SHermès Bélusca-Maïto             break;
951*23b7c7b8SHermès Bélusca-Maïto         }
952*23b7c7b8SHermès Bélusca-Maïto 
953*23b7c7b8SHermès Bélusca-Maïto         //
954*23b7c7b8SHermès Bélusca-Maïto         //  If we come to a period, figure out if the extension was
955*23b7c7b8SHermès Bélusca-Maïto         //  all one case.
956*23b7c7b8SHermès Bélusca-Maïto         //
957*23b7c7b8SHermès Bélusca-Maïto 
958*23b7c7b8SHermès Bélusca-Maïto         if (c == L'.') {
959*23b7c7b8SHermès Bélusca-Maïto 
960*23b7c7b8SHermès Bélusca-Maïto             *CreateLfn = (Lowers != 0) && (Uppers != 0);
961*23b7c7b8SHermès Bélusca-Maïto 
962*23b7c7b8SHermès Bélusca-Maïto             *AllLowerComponent = !(*CreateLfn) && (Lowers != 0);
963*23b7c7b8SHermès Bélusca-Maïto 
964*23b7c7b8SHermès Bélusca-Maïto             ExtensionPresent = TRUE;
965*23b7c7b8SHermès Bélusca-Maïto 
966*23b7c7b8SHermès Bélusca-Maïto             //
967*23b7c7b8SHermès Bélusca-Maïto             //  Now reset the uppers and lowers count.
968*23b7c7b8SHermès Bélusca-Maïto             //
969*23b7c7b8SHermès Bélusca-Maïto 
970*23b7c7b8SHermès Bélusca-Maïto             Uppers = Lowers = 0;
971*23b7c7b8SHermès Bélusca-Maïto         }
972*23b7c7b8SHermès Bélusca-Maïto     }
973*23b7c7b8SHermès Bélusca-Maïto 
974*23b7c7b8SHermès Bélusca-Maïto     //
975*23b7c7b8SHermès Bélusca-Maïto     //  Now check again for creating an LFN.
976*23b7c7b8SHermès Bélusca-Maïto     //
977*23b7c7b8SHermès Bélusca-Maïto 
978*23b7c7b8SHermès Bélusca-Maïto     *CreateLfn = (*CreateLfn ||
979*23b7c7b8SHermès Bélusca-Maïto                   (i != UnicodeName->Length / sizeof(WCHAR)) ||
980*23b7c7b8SHermès Bélusca-Maïto                   ((Lowers != 0) && (Uppers != 0)));
981*23b7c7b8SHermès Bélusca-Maïto 
982*23b7c7b8SHermès Bélusca-Maïto     //
983*23b7c7b8SHermès Bélusca-Maïto     //  Now we know the final state of CreateLfn, update the two
984*23b7c7b8SHermès Bélusca-Maïto     //  "AllLower" booleans.
985*23b7c7b8SHermès Bélusca-Maïto     //
986*23b7c7b8SHermès Bélusca-Maïto 
987*23b7c7b8SHermès Bélusca-Maïto     if (ExtensionPresent) {
988*23b7c7b8SHermès Bélusca-Maïto 
989*23b7c7b8SHermès Bélusca-Maïto         *AllLowerComponent = !(*CreateLfn) && *AllLowerComponent;
990*23b7c7b8SHermès Bélusca-Maïto         *AllLowerExtension = !(*CreateLfn) && (Lowers != 0);
991*23b7c7b8SHermès Bélusca-Maïto 
992*23b7c7b8SHermès Bélusca-Maïto     } else {
993*23b7c7b8SHermès Bélusca-Maïto 
994*23b7c7b8SHermès Bélusca-Maïto         *AllLowerComponent = !(*CreateLfn) && (Lowers != 0);
995*23b7c7b8SHermès Bélusca-Maïto         *AllLowerExtension = FALSE;
996*23b7c7b8SHermès Bélusca-Maïto     }
997*23b7c7b8SHermès Bélusca-Maïto 
998*23b7c7b8SHermès Bélusca-Maïto     return;
999*23b7c7b8SHermès Bélusca-Maïto }
1000*23b7c7b8SHermès Bélusca-Maïto 
1001*23b7c7b8SHermès Bélusca-Maïto 
1002*23b7c7b8SHermès Bélusca-Maïto BOOLEAN
FatSpaceInName(IN PIRP_CONTEXT IrpContext,IN PUNICODE_STRING UnicodeName)1003*23b7c7b8SHermès Bélusca-Maïto FatSpaceInName (
1004*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
1005*23b7c7b8SHermès Bélusca-Maïto     IN PUNICODE_STRING UnicodeName
1006*23b7c7b8SHermès Bélusca-Maïto     )
1007*23b7c7b8SHermès Bélusca-Maïto 
1008*23b7c7b8SHermès Bélusca-Maïto /*++
1009*23b7c7b8SHermès Bélusca-Maïto 
1010*23b7c7b8SHermès Bélusca-Maïto Routine Description:
1011*23b7c7b8SHermès Bélusca-Maïto 
1012*23b7c7b8SHermès Bélusca-Maïto     This routine takes a UNICODE string and sees if it contains any spaces.
1013*23b7c7b8SHermès Bélusca-Maïto 
1014*23b7c7b8SHermès Bélusca-Maïto Arguments:
1015*23b7c7b8SHermès Bélusca-Maïto 
1016*23b7c7b8SHermès Bélusca-Maïto     UnicodeName - Provides the final name.
1017*23b7c7b8SHermès Bélusca-Maïto 
1018*23b7c7b8SHermès Bélusca-Maïto Return Value:
1019*23b7c7b8SHermès Bélusca-Maïto 
1020*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN - TRUE if it does, FALSE if it doesn't.
1021*23b7c7b8SHermès Bélusca-Maïto 
1022*23b7c7b8SHermès Bélusca-Maïto --*/
1023*23b7c7b8SHermès Bélusca-Maïto 
1024*23b7c7b8SHermès Bélusca-Maïto {
1025*23b7c7b8SHermès Bélusca-Maïto     ULONG i;
1026*23b7c7b8SHermès Bélusca-Maïto 
1027*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
1028*23b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( IrpContext );
1029*23b7c7b8SHermès Bélusca-Maïto 
1030*23b7c7b8SHermès Bélusca-Maïto     for (i=0; i < UnicodeName->Length/sizeof(WCHAR); i++) {
1031*23b7c7b8SHermès Bélusca-Maïto 
1032*23b7c7b8SHermès Bélusca-Maïto         if (UnicodeName->Buffer[i] == L' ') {
1033*23b7c7b8SHermès Bélusca-Maïto             return TRUE;
1034*23b7c7b8SHermès Bélusca-Maïto         }
1035*23b7c7b8SHermès Bélusca-Maïto     }
1036*23b7c7b8SHermès Bélusca-Maïto 
1037*23b7c7b8SHermès Bélusca-Maïto     return FALSE;
1038*23b7c7b8SHermès Bélusca-Maïto }
1039*23b7c7b8SHermès Bélusca-Maïto 
1040*23b7c7b8SHermès Bélusca-Maïto VOID
FatUnicodeRestoreShortNameCase(IN PUNICODE_STRING ShortNameWithCase,IN BOOLEAN LowerCase8,IN BOOLEAN LowerCase3)1041*23b7c7b8SHermès Bélusca-Maïto FatUnicodeRestoreShortNameCase(
1042*23b7c7b8SHermès Bélusca-Maïto     IN PUNICODE_STRING ShortNameWithCase,
1043*23b7c7b8SHermès Bélusca-Maïto     IN BOOLEAN LowerCase8,
1044*23b7c7b8SHermès Bélusca-Maïto     IN BOOLEAN LowerCase3
1045*23b7c7b8SHermès Bélusca-Maïto     )
1046*23b7c7b8SHermès Bélusca-Maïto 
1047*23b7c7b8SHermès Bélusca-Maïto /*++
1048*23b7c7b8SHermès Bélusca-Maïto 
1049*23b7c7b8SHermès Bélusca-Maïto Routine Description:
1050*23b7c7b8SHermès Bélusca-Maïto 
1051*23b7c7b8SHermès Bélusca-Maïto     Given an 8.3 filename in a UNICODE_STRING, fix the case of the
1052*23b7c7b8SHermès Bélusca-Maïto     name given the two 8do3 case flags.
1053*23b7c7b8SHermès Bélusca-Maïto 
1054*23b7c7b8SHermès Bélusca-Maïto Arguments:
1055*23b7c7b8SHermès Bélusca-Maïto 
1056*23b7c7b8SHermès Bélusca-Maïto     ShortNameWithCase - the UNICODE_STRING containing the short name.
1057*23b7c7b8SHermès Bélusca-Maïto     LowerCase8, LowerCase3 - the flag indicating whether to downcase the 8dot3 name component.
1058*23b7c7b8SHermès Bélusca-Maïto 
1059*23b7c7b8SHermès Bélusca-Maïto Return Value:
1060*23b7c7b8SHermès Bélusca-Maïto 
1061*23b7c7b8SHermès Bélusca-Maïto     None.
1062*23b7c7b8SHermès Bélusca-Maïto 
1063*23b7c7b8SHermès Bélusca-Maïto --*/
1064*23b7c7b8SHermès Bélusca-Maïto {
1065*23b7c7b8SHermès Bélusca-Maïto     USHORT i;
1066*23b7c7b8SHermès Bélusca-Maïto     UNICODE_STRING DownCaseSeg;
1067*23b7c7b8SHermès Bélusca-Maïto 
1068*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
1069*23b7c7b8SHermès Bélusca-Maïto 
1070*23b7c7b8SHermès Bélusca-Maïto     NT_ASSERT( ShortNameWithCase->Length <= 24 );
1071*23b7c7b8SHermès Bélusca-Maïto 
1072*23b7c7b8SHermès Bélusca-Maïto     //
1073*23b7c7b8SHermès Bélusca-Maïto     //  Have to repair the case of the short name
1074*23b7c7b8SHermès Bélusca-Maïto     //
1075*23b7c7b8SHermès Bélusca-Maïto 
1076*23b7c7b8SHermès Bélusca-Maïto     for (i = 0; i < (ShortNameWithCase->Length/sizeof(WCHAR)) &&
1077*23b7c7b8SHermès Bélusca-Maïto                 ShortNameWithCase->Buffer[i] != L'.'; i++);
1078*23b7c7b8SHermès Bélusca-Maïto 
1079*23b7c7b8SHermès Bélusca-Maïto     //
1080*23b7c7b8SHermès Bélusca-Maïto     //  Now pointing at the '.', or otherwise the end of name component
1081*23b7c7b8SHermès Bélusca-Maïto     //
1082*23b7c7b8SHermès Bélusca-Maïto 
1083*23b7c7b8SHermès Bélusca-Maïto     if (LowerCase8) {
1084*23b7c7b8SHermès Bélusca-Maïto 
1085*23b7c7b8SHermès Bélusca-Maïto         DownCaseSeg.Buffer = ShortNameWithCase->Buffer;
1086*23b7c7b8SHermès Bélusca-Maïto         DownCaseSeg.MaximumLength = DownCaseSeg.Length = i*sizeof(WCHAR);
1087*23b7c7b8SHermès Bélusca-Maïto 
1088*23b7c7b8SHermès Bélusca-Maïto         RtlDowncaseUnicodeString(&DownCaseSeg, &DownCaseSeg, FALSE);
1089*23b7c7b8SHermès Bélusca-Maïto     }
1090*23b7c7b8SHermès Bélusca-Maïto 
1091*23b7c7b8SHermès Bélusca-Maïto     i++;
1092*23b7c7b8SHermès Bélusca-Maïto 
1093*23b7c7b8SHermès Bélusca-Maïto     //
1094*23b7c7b8SHermès Bélusca-Maïto     //  Now pointing at first wchar of the extension.
1095*23b7c7b8SHermès Bélusca-Maïto     //
1096*23b7c7b8SHermès Bélusca-Maïto 
1097*23b7c7b8SHermès Bélusca-Maïto     if (LowerCase3) {
1098*23b7c7b8SHermès Bélusca-Maïto 
1099*23b7c7b8SHermès Bélusca-Maïto         //
1100*23b7c7b8SHermès Bélusca-Maïto         //  It is not neccesarily the case that we can rely on the flag
1101*23b7c7b8SHermès Bélusca-Maïto         //  indicating that we really have an extension.
1102*23b7c7b8SHermès Bélusca-Maïto         //
1103*23b7c7b8SHermès Bélusca-Maïto 
1104*23b7c7b8SHermès Bélusca-Maïto         if ((i*sizeof(WCHAR)) < ShortNameWithCase->Length) {
1105*23b7c7b8SHermès Bélusca-Maïto             DownCaseSeg.Buffer = &ShortNameWithCase->Buffer[i];
1106*23b7c7b8SHermès Bélusca-Maïto             DownCaseSeg.MaximumLength = DownCaseSeg.Length = ShortNameWithCase->Length - i*sizeof(WCHAR);
1107*23b7c7b8SHermès Bélusca-Maïto 
1108*23b7c7b8SHermès Bélusca-Maïto             RtlDowncaseUnicodeString(&DownCaseSeg, &DownCaseSeg, FALSE);
1109*23b7c7b8SHermès Bélusca-Maïto         }
1110*23b7c7b8SHermès Bélusca-Maïto     }
1111*23b7c7b8SHermès Bélusca-Maïto 
1112*23b7c7b8SHermès Bélusca-Maïto }
1113*23b7c7b8SHermès Bélusca-Maïto 
1114*23b7c7b8SHermès Bélusca-Maïto 
1115