Reverted latest changes.
[reactos.git] / reactos / 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: dos8dot3.c,v 1.6 2002/09/08 10:23:41 chorns Exp $
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 const PWCHAR RtlpShortIllegals = L" ;+=[]',\"*\\<>/?:|";
40
41
42 /* FUNCTIONS *****************************************************************/
43
44 static BOOLEAN
45 RtlpIsShortIllegal(WCHAR Char)
46 {
47 int i;
48
49 for (i = 0; RtlpShortIllegals[i]; i++)
50 {
51 if (Char == RtlpShortIllegals[i])
52 return(TRUE);
53 }
54
55 return(FALSE);
56 }
57
58
59 VOID STDCALL
60 RtlGenerate8dot3Name(IN PUNICODE_STRING Name,
61 IN BOOLEAN AllowExtendedCharacters,
62 IN OUT PGENERATE_NAME_CONTEXT Context,
63 OUT PUNICODE_STRING Name8dot3)
64 {
65 WCHAR NameBuffer[8];
66 WCHAR ExtBuffer[4];
67 USHORT StrLength;
68 USHORT NameLength;
69 USHORT ExtLength;
70 USHORT CopyLength;
71 USHORT DotPos;
72 USHORT i, j;
73 USHORT CurrentIndex;
74
75 memset(NameBuffer, 0, sizeof(NameBuffer));
76 memset(ExtBuffer, 0, sizeof(ExtBuffer));
77
78 StrLength = Name->Length / sizeof(WCHAR);
79 DPRINT("StrLength: %hu\n", StrLength);
80
81 /* Find last dot in Name */
82 DotPos = 0;
83 for (i = 0; i < StrLength; i++)
84 {
85 if (Name->Buffer[i] == L'.')
86 {
87 DotPos = i;
88 }
89 }
90
91 if (DotPos == 0)
92 {
93 DotPos = i;
94 }
95 DPRINT("DotPos: %hu\n", DotPos);
96
97 /* Copy name (6 valid characters max) */
98 for (i = 0, NameLength = 0; NameLength < 6 && i < DotPos; i++)
99 {
100 if ((!RtlpIsShortIllegal(Name->Buffer[i])) &&
101 (Name->Buffer[i] != L'.'))
102 {
103 NameBuffer[NameLength++] = RtlUpcaseUnicodeChar(Name->Buffer[i]);
104 }
105 }
106 DPRINT("NameBuffer: '%.08S'\n", NameBuffer);
107 DPRINT("NameLength: %hu\n", NameLength);
108
109 /* Copy extension (4 valid characters max) */
110 if (DotPos < StrLength)
111 {
112 for (i = DotPos, ExtLength = 0; ExtLength < 4 && i < StrLength; i++)
113 {
114 if (!RtlpIsShortIllegal(Name->Buffer[i]))
115 {
116 ExtBuffer[ExtLength++] = RtlUpcaseUnicodeChar(Name->Buffer[i]);
117 }
118 }
119 }
120 else
121 {
122 ExtLength = 0;
123 }
124 DPRINT("ExtBuffer: '%.04S'\n", ExtBuffer);
125 DPRINT("ExtLength: %hu\n", ExtLength);
126
127 /* Determine next index */
128 CurrentIndex = Context->LastIndexValue;
129 CopyLength = min(NameLength, (CurrentIndex < 10) ? 6 : 5);
130 DPRINT("CopyLength: %hu\n", CopyLength);
131
132 if ((Context->NameLength == CopyLength) &&
133 (wcsncmp(Context->NameBuffer, NameBuffer, CopyLength) == 0) &&
134 (Context->ExtensionLength == ExtLength) &&
135 (wcsncmp(Context->ExtensionBuffer, ExtBuffer, ExtLength) == 0))
136 CurrentIndex++;
137 else
138 CurrentIndex = 1;
139 DPRINT("CurrentIndex: %hu\n", CurrentIndex);
140
141 /* Build the short name */
142 for (i = 0; i < CopyLength; i++)
143 {
144 Name8dot3->Buffer[i] = NameBuffer[i];
145 }
146
147 Name8dot3->Buffer[i++] = L'~';
148 if (CurrentIndex >= 10)
149 Name8dot3->Buffer[i++] = (CurrentIndex / 10) + L'0';
150 Name8dot3->Buffer[i++] = (CurrentIndex % 10) + L'0';
151
152 for (j = 0; j < ExtLength; i++, j++)
153 {
154 Name8dot3->Buffer[i] = ExtBuffer[j];
155 }
156
157 Name8dot3->Length = i * sizeof(WCHAR);
158
159 DPRINT("Name8dot3: '%wZ'\n", Name8dot3);
160
161 /* Update context */
162 Context->NameLength = CopyLength;
163 for (i = 0; i < CopyLength; i++)
164 {
165 Context->NameBuffer[i] = NameBuffer[i];
166 }
167
168 Context->ExtensionLength = ExtLength;
169 for (i = 0; i < ExtLength; i++)
170 {
171 Context->ExtensionBuffer[i] = ExtBuffer[i];
172 }
173
174 Context->LastIndexValue = CurrentIndex;
175 }
176
177
178 BOOLEAN STDCALL
179 RtlIsNameLegalDOS8Dot3(IN PUNICODE_STRING UnicodeName,
180 IN PANSI_STRING AnsiName,
181 OUT PBOOLEAN SpacesFound)
182 {
183 PANSI_STRING name = AnsiName;
184 ANSI_STRING DummyString;
185 CHAR Buffer[12];
186 char *str;
187 ULONG Length;
188 ULONG i;
189 NTSTATUS Status;
190 BOOLEAN HasSpace = FALSE;
191 BOOLEAN HasDot = FALSE;
192
193 if (UnicodeName->Length > 24)
194 {
195 return(FALSE); /* name too long */
196 }
197
198 if (!name)
199 {
200 name = &DummyString;
201 name->Length = 0;
202 name->MaximumLength = 12;
203 name->Buffer = Buffer;
204 }
205
206 Status = RtlUpcaseUnicodeStringToCountedOemString(name,
207 UnicodeName,
208 FALSE);
209 if (!NT_SUCCESS(Status))
210 {
211 return(FALSE);
212 }
213
214 Length = name->Length;
215 str = name->Buffer;
216
217 if (!(Length == 1 && *str == '.') &&
218 !(Length == 2 && *str == '.' && *(str + 1) == '.'))
219 {
220 for (i = 0; i < Length; i++, str++)
221 {
222 switch (*str)
223 {
224 case ' ':
225 HasSpace = TRUE;
226 break;
227
228 case '.':
229 if ((HasDot) || /* two or more dots */
230 (i == 0) || /* dot is first char */
231 (i + 1 == Length) || /* dot is last char */
232 (Length - i > 4) || /* more than 3 chars of extension */
233 (HasDot == FALSE && i > 8)) /* name is longer than 8 chars */
234 return(FALSE);
235 HasDot = TRUE;
236 break;
237 }
238 }
239 }
240
241 /* Name is longer than 8 chars and does not have an extension */
242 if (Length > 8 && HasDot == FALSE)
243 {
244 return(FALSE);
245 }
246
247 if (SpacesFound)
248 *SpacesFound = HasSpace;
249
250 return(TRUE);
251 }
252
253 /* EOF */