RtlGenerate8dot3Name() is now "pass"ed
[reactos.git] / ntoskrnl / rtl / dos8dot3.c
1 /*
2  *  ReactOS kernel
3  *  Copyright (C) 2002 ReactOS Team
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /* $Id$
20  *
21  * COPYRIGHT:       See COPYING in the top level directory
22  * PROJECT:         ReactOS kernel
23  * FILE:            ntoskrnl/rtl/dos8dot3.c
24  * PURPOSE:         Short name (8.3 name) functions
25  * PROGRAMMER:      Eric Kohl
26  */
27
28 /* INCLUDES ******************************************************************/
29
30 #include <ddk/ntddk.h>
31 #include <ntos/minmax.h>
32
33 #define NDEBUG
34 #include <internal/debug.h>
35
36
37 /* CONSTANTS *****************************************************************/
38
39 #ifndef LIBCAPTIVE
40 static const WCHAR *RtlpShortIllegals;
41 #endif /* LIBCAPTIVE */
42
43
44 /* FUNCTIONS *****************************************************************/
45
46 #ifndef LIBCAPTIVE
47
48 static BOOLEAN
49 RtlpIsShortIllegal(WCHAR Char)
50 {
51   int i;
52
53   if (!RtlpShortIllegals)
54     RtlpShortIllegals = REACTOS_UCS2(L" ;+=[]',\"*\\<>/?:|");
55
56   for (i = 0; RtlpShortIllegals[i]; i++)
57     {
58       if (Char == RtlpShortIllegals[i])
59         return(TRUE);
60     }
61
62   return(FALSE);
63 }
64
65
66 VOID STDCALL
67 RtlGenerate8dot3Name(IN PUNICODE_STRING Name,
68                      IN BOOLEAN AllowExtendedCharacters,
69                      IN OUT PGENERATE_NAME_CONTEXT Context,
70                      OUT PUNICODE_STRING Name8dot3)
71 {
72   WCHAR NameBuffer[8];
73   WCHAR ExtBuffer[4];
74   USHORT StrLength;
75   USHORT NameLength;
76   USHORT ExtLength;
77   USHORT CopyLength;
78   USHORT DotPos;
79   USHORT i, j;
80   USHORT CurrentIndex;
81
82   memset(NameBuffer, 0, sizeof(NameBuffer));
83   memset(ExtBuffer, 0, sizeof(ExtBuffer));
84
85   StrLength = Name->Length / sizeof(WCHAR);
86   DPRINT("StrLength: %hu\n", StrLength);
87
88   /* Find last dot in Name */
89   DotPos = 0;
90   for (i = 0; i < StrLength; i++)
91     {
92       if (Name->Buffer[i] == L'.')
93         {
94           DotPos = i;
95         }
96     }
97
98   if (DotPos == 0)
99     {
100       DotPos = i;
101     }
102   DPRINT("DotPos: %hu\n", DotPos);
103
104   /* Copy name (6 valid characters max) */
105   for (i = 0, NameLength = 0; NameLength < 6 && i < DotPos; i++)
106     {
107       if ((!RtlpIsShortIllegal(Name->Buffer[i])) &&
108           (Name->Buffer[i] != L'.'))
109         {
110           NameBuffer[NameLength++] = RtlUpcaseUnicodeChar(Name->Buffer[i]);
111         }
112     }
113   DPRINT("NameBuffer: '%.08S'\n", NameBuffer);
114   DPRINT("NameLength: %hu\n", NameLength);
115
116   /* Copy extension (4 valid characters max) */
117   if (DotPos < StrLength)
118     {
119       for (i = DotPos, ExtLength = 0; ExtLength < 4 && i < StrLength; i++)
120         {
121           if (!RtlpIsShortIllegal(Name->Buffer[i]))
122             {
123               ExtBuffer[ExtLength++] = RtlUpcaseUnicodeChar(Name->Buffer[i]);
124             }
125         }
126     }
127   else
128     {
129       ExtLength = 0;
130     }
131   DPRINT("ExtBuffer: '%.04S'\n", ExtBuffer);
132   DPRINT("ExtLength: %hu\n", ExtLength);
133
134   /* Determine next index */
135   CurrentIndex = Context->LastIndexValue;
136   CopyLength = min(NameLength, (CurrentIndex < 10) ? 6 : 5);
137   DPRINT("CopyLength: %hu\n", CopyLength);
138
139   if ((Context->NameLength == CopyLength) &&
140       (wcsncmp(Context->NameBuffer, NameBuffer, CopyLength) == 0) &&
141       (Context->ExtensionLength == ExtLength) &&
142       (wcsncmp(Context->ExtensionBuffer, ExtBuffer, ExtLength) == 0))
143     CurrentIndex++;
144   else
145     CurrentIndex = 1;
146   DPRINT("CurrentIndex: %hu\n", CurrentIndex);
147
148   /* Build the short name */
149   for (i = 0; i < CopyLength; i++)
150     {
151       Name8dot3->Buffer[i] = NameBuffer[i];
152     }
153
154   Name8dot3->Buffer[i++] = L'~';
155   if (CurrentIndex >= 10)
156     Name8dot3->Buffer[i++] = (CurrentIndex / 10) + L'0';
157   Name8dot3->Buffer[i++] = (CurrentIndex % 10) + L'0';
158
159   for (j = 0; j < ExtLength; i++, j++)
160     {
161       Name8dot3->Buffer[i] = ExtBuffer[j];
162     }
163
164   Name8dot3->Length = i * sizeof(WCHAR);
165
166   DPRINT("Name8dot3: '%wZ'\n", Name8dot3);
167
168   /* Update context */
169   Context->NameLength = CopyLength;
170   for (i = 0; i < CopyLength; i++)
171     {
172       Context->NameBuffer[i] = NameBuffer[i];
173     }
174
175   Context->ExtensionLength = ExtLength;
176   for (i = 0; i < ExtLength; i++)
177     {
178       Context->ExtensionBuffer[i] = ExtBuffer[i];
179     }
180
181   Context->LastIndexValue = CurrentIndex;
182 }
183
184
185 BOOLEAN STDCALL
186 RtlIsNameLegalDOS8Dot3(IN PUNICODE_STRING UnicodeName,
187                        IN PANSI_STRING AnsiName,
188                        OUT PBOOLEAN SpacesFound)
189 {
190   PANSI_STRING name = AnsiName;
191   ANSI_STRING DummyString;
192   CHAR Buffer[12];
193   char *str;
194   ULONG Length;
195   ULONG i;
196   NTSTATUS Status;
197   BOOLEAN HasSpace = FALSE;
198   BOOLEAN HasDot = FALSE;
199
200   if (UnicodeName->Length > 24)
201     {
202       return(FALSE); /* name too long */
203     }
204
205   if (!name)
206     {
207       name = &DummyString;
208       name->Length = 0;
209       name->MaximumLength = 12;
210       name->Buffer = Buffer;
211     }
212
213   Status = RtlUpcaseUnicodeStringToCountedOemString(name,
214                                                     UnicodeName,
215                                                     FALSE);
216   if (!NT_SUCCESS(Status))
217     {
218       return(FALSE);
219     }
220
221   Length = name->Length;
222   str = name->Buffer;
223
224   if (!(Length == 1 && *str == '.') &&
225       !(Length == 2 && *str == '.' && *(str + 1) == '.'))
226     {
227       for (i = 0; i < Length; i++, str++)
228         {
229           switch (*str)
230             {
231               case ' ':
232                 HasSpace = TRUE;
233                 break;
234
235               case '.':
236                 if ((HasDot) ||                 /* two or more dots */
237                     (i == 0) ||                 /* dot is first char */
238                     (i + 1 == Length) ||        /* dot is last char */
239                     (Length - i > 4) ||         /* more than 3 chars of extension */
240                     (HasDot == FALSE && i > 8)) /* name is longer than 8 chars */
241                   return(FALSE);
242                 HasDot = TRUE;
243                 break;
244             }
245         }
246     }
247
248   /* Name is longer than 8 chars and does not have an extension */
249   if (Length > 8 && HasDot == FALSE)
250     {
251       return(FALSE);
252     }
253
254   if (SpacesFound)
255     *SpacesFound = HasSpace;
256
257   return(TRUE);
258 }
259
260 #endif /* LIBCAPTIVE */
261
262 /* EOF */