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