ReactOS 0.4.16-dev-125-g798ea90
dos8dot3.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/rtl/dos8dot3.c
5 * PURPOSE: Short name (8.3 name) functions
6 * PROGRAMMER: Eric Kohl
7 */
8
9/* INCLUDES ******************************************************************/
10
11#include <rtl.h>
12
13#define NDEBUG
14#include <debug.h>
15
17
18/* CONSTANTS *****************************************************************/
19
20const ULONG RtlpShortIllegals[] = { 0xFFFFFFFF, 0xFC009C04, 0x38000000, 0x10000000 };
21
22/* FUNCTIONS *****************************************************************/
23
27
28static BOOLEAN
30{
31 return (Char < 128 && (RtlpShortIllegals[Char / 32] & (1 << (Char % 32))));
32}
33
34static USHORT
36{
37 PWCHAR CurrentChar;
39 USHORT Saved;
41
42 if (!Name->Length)
43 return 0;
44
45 if (Name->Length == sizeof(WCHAR))
46 return Name->Buffer[0];
47
48 CurrentChar = Name->Buffer;
49 Hash = (*CurrentChar << 8) + *(CurrentChar + 1);
50
51 if (Name->Length == 2 * sizeof(WCHAR))
52 return Hash;
53
54 Saved = Hash;
55 Length = 2;
56
57 do
58 {
59 CurrentChar += 2;
60 Hash = (Hash << 7) + *CurrentChar;
61 Hash = (Saved >> 1) + (Hash << 8);
62
63 if (Length + 1 < Name->Length / sizeof(WCHAR))
64 {
65 Hash += *(CurrentChar + 1);
66 }
67
68 Saved = Hash;
69 Length += 2;
70 }
71 while (Length < Name->Length / sizeof(WCHAR));
72
73 return Hash;
74}
75
76/*
77 * @implemented
78 */
79VOID
85{
86 ULONG Length = Name->Length / sizeof(WCHAR);
87 ULONG IndexLength;
89 ULONG DotPos;
90 WCHAR IndexBuffer[8];
91 WCHAR Char;
92 USHORT Checksum;
93
94 if (!Context->NameLength)
95 {
96 DotPos = Length;
97
98 /* Find last dot in Name */
99 for (Index = 0; Index < Length; Index++)
100 {
101 if (Name->Buffer[Index] == L'.')
102 DotPos = Index;
103 }
104
105 /* Copy name. OEM string length can't exceed 6. */
106 UCHAR OemSizeLeft = 6;
107 for (Index = 0; (Index < DotPos) && OemSizeLeft; Index++)
108 {
109 Char = Name->Buffer[Index];
110
111 if ((Char > L' ') && (Char != L'.') &&
112 ((Char < 127) || (AllowExtendedCharacters && RtlIsValidOemCharacter(&Char))))
113 {
114 if (RtlpIsShortIllegal(Char))
115 Char = L'_';
116 else if (Char >= L'a' && Char <= L'z')
117 Char = RtlpUpcaseUnicodeChar(Char);
118
119 /* Beware of MB OEM codepage */
121 {
122 if (OemSizeLeft < 2)
123 break;
124 OemSizeLeft--;
125 }
126
127 Context->NameBuffer[Context->NameLength] = Char;
128 Context->NameLength++;
129 OemSizeLeft--;
130 }
131 }
132
133 /* Copy extension (4 valid characters max) */
134 Context->ExtensionLength = 0;
135 if (DotPos < Length)
136 {
137 Context->ExtensionBuffer[0] = L'.';
138 Context->ExtensionLength = 1;
139
140 while (DotPos < Length && Context->ExtensionLength < 4)
141 {
142 Char = Name->Buffer[DotPos];
143
144 if ((Char > L' ') && (Char != L'.') &&
145 ((Char < 127) || (AllowExtendedCharacters && RtlIsValidOemCharacter(&Char))))
146 {
147 if (RtlpIsShortIllegal(Char))
148 Char = L'_';
149 else if (Char >= L'a' && Char <= L'z')
150 Char = RtlpUpcaseUnicodeChar(Char);
151
152 Context->ExtensionBuffer[Context->ExtensionLength++] = Char;
153 }
154
155 Char = UNICODE_NULL;
156 ++DotPos;
157 }
158
159 if (Char != UNICODE_NULL)
160 Context->ExtensionBuffer[Context->ExtensionLength - 1] = L'~';
161 }
162
163 if (Context->NameLength <= 2)
164 {
165 Checksum = Context->Checksum = RtlpGetCheckSum(Name);
166
167 for (Index = 0; Index < 4; Index++)
168 {
169 Context->NameBuffer[Context->NameLength + Index] =
170 (Checksum & 0xF) > 9 ? (Checksum & 0xF) + L'A' - 10 : (Checksum & 0xF) + L'0';
171 Checksum >>= 4;
172 }
173
174 Context->CheckSumInserted = TRUE;
175 Context->NameLength += 4;
176 }
177 }
178
179 ++Context->LastIndexValue;
180
181 if (Context->LastIndexValue > 4 && !Context->CheckSumInserted)
182 {
183 Checksum = Context->Checksum = RtlpGetCheckSum(Name);
184
185 for (Index = 2; Index < 6; Index++)
186 {
187 Context->NameBuffer[Index] =
188 (Checksum & 0xF) > 9 ? (Checksum & 0xF) + L'A' - 10 : (Checksum & 0xF) + L'0';
189 Checksum >>= 4;
190 }
191
192 Context->CheckSumInserted = TRUE;
193 Context->NameLength = 6;
194 Context->LastIndexValue = 1;
195 }
196
197 /* Calculate index length and index buffer */
198 Index = Context->LastIndexValue;
199 for (IndexLength = 1; IndexLength <= 7 && Index > 0; IndexLength++)
200 {
201 IndexBuffer[8 - IndexLength] = L'0' + (Index % 10);
202 Index /= 10;
203 }
204
205 IndexBuffer[8 - IndexLength] = L'~';
206
207 /* Reset name length */
208 Name8dot3->Length = 0;
209
210 /* If name present */
211 if (Context->NameLength)
212 {
213 /* Copy name buffer */
214 Length = Context->NameLength * sizeof(WCHAR);
215 RtlCopyMemory(Name8dot3->Buffer, Context->NameBuffer, Length);
216 Name8dot3->Length = Length;
217 }
218
219 /* Copy index buffer */
220 Length = IndexLength * sizeof(WCHAR);
221 RtlCopyMemory(Name8dot3->Buffer + (Name8dot3->Length / sizeof(WCHAR)),
222 IndexBuffer + (8 - IndexLength),
223 Length);
224 Name8dot3->Length += Length;
225
226 /* If extension present */
227 if (Context->ExtensionLength)
228 {
229 /* Copy extension buffer */
230 Length = Context->ExtensionLength * sizeof(WCHAR);
231 RtlCopyMemory(Name8dot3->Buffer + (Name8dot3->Length / sizeof(WCHAR)),
232 Context->ExtensionBuffer,
233 Length);
234 Name8dot3->Length += Length;
235 }
236}
237
238
239/*
240 * @implemented
241 * Note: the function does not conform to the annotations.
242 * SpacesFound is not always set!
243 */
248NTAPI
252{
253 static const char Illegal[] = "*?<>|\"+=,;[]:/\\\345";
254 int Dot = -1;
255 int i;
256 char Buffer[12];
258 BOOLEAN GotSpace = FALSE;
260
261 if (!OemName)
262 {
263 OemString.Length = sizeof(Buffer);
264 OemString.MaximumLength = sizeof(Buffer);
265 OemString.Buffer = Buffer;
267 }
268
270 if (!NT_SUCCESS(Status))
271 return FALSE;
272
273 if ((OemName->Length > 12) || (OemName->Buffer == NULL)) return FALSE;
274
275 /* a starting . is invalid, except for . and .. */
276 if (OemName->Buffer[0] == '.')
277 {
278 if (OemName->Length != 1 && (OemName->Length != 2 || OemName->Buffer[1] != '.')) return FALSE;
280
281 return TRUE;
282 }
283
284 for (i = 0; i < OemName->Length; i++)
285 {
286 switch (OemName->Buffer[i])
287 {
288 case ' ':
289 /* leading/trailing spaces not allowed */
290 if (!i || i == OemName->Length-1 || OemName->Buffer[i+1] == '.') return FALSE;
291 GotSpace = TRUE;
292 break;
293
294 case '.':
295 if (Dot != -1) return FALSE;
296 Dot = i;
297 break;
298
299 default:
300 if (strchr(Illegal, OemName->Buffer[i])) return FALSE;
301 break;
302 }
303 }
304 /* check file part is shorter than 8, extension shorter than 3
305 * dot cannot be last in string
306 */
307 if (Dot == -1)
308 {
309 if (OemName->Length > 8) return FALSE;
310 }
311 else
312 {
313 if (Dot > 8 || (OemName->Length - Dot > 4) || Dot == OemName->Length - 1) return FALSE;
314 }
315
316 if (NameContainsSpaces) *NameContainsSpaces = GotSpace;
317
318 return TRUE;
319}
320
321/* EOF */
unsigned char BOOLEAN
char * strchr(const char *String, int ch)
Definition: utclib.c:501
LONG NTSTATUS
Definition: precomp.h:26
#define NTSYSAPI
Definition: ntoskrnl.h:12
Definition: bufpool.h:45
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
static int Hash(const char *)
Definition: reader.c:2257
static USHORT RtlpGetCheckSum(PUNICODE_STRING Name)
Definition: dos8dot3.c:35
PUSHORT NlsUnicodeToMbOemTable
Definition: nlsboot.c:22
static BOOLEAN RtlpIsShortIllegal(const WCHAR Char)
Definition: dos8dot3.c:29
BOOLEAN NTAPI RtlIsValidOemCharacter(IN PWCHAR Char)
Definition: unicode.c:514
VOID NTAPI RtlGenerate8dot3Name(IN PUNICODE_STRING Name, IN BOOLEAN AllowExtendedCharacters, IN OUT PGENERATE_NAME_CONTEXT Context, OUT PUNICODE_STRING Name8dot3)
Definition: dos8dot3.c:81
const ULONG RtlpShortIllegals[]
Definition: dos8dot3.c:20
#define _IRQL_requires_max_(irql)
Definition: driverspecs.h:230
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
IN PDCB IN POEM_STRING OemName
Definition: fatprocs.h:1305
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
BOOLEAN NTAPI RtlIsNameLegalDOS8Dot3(_In_ PUNICODE_STRING Name, _Inout_opt_ POEM_STRING OemName, _Inout_opt_ PBOOLEAN NameContainsSpaces)
NTSYSAPI NTSTATUS WINAPI RtlUpcaseUnicodeStringToCountedOemString(STRING *, const UNICODE_STRING *, BOOLEAN)
#define HIBYTE(W)
Definition: jmemdos.c:486
#define _Must_inspect_result_
Definition: ms_sal.h:558
_Inout_opt_ POEM_STRING _Out_opt_ PBOOLEAN NameContainsSpaces
Definition: rtlfuncs.h:3103
WCHAR NTAPI RtlpUpcaseUnicodeChar(_In_ WCHAR Source)
Definition: nlsboot.c:160
BOOLEAN NlsMbOemCodePageTag
Definition: nlsboot.c:19
#define Dot(u, v)
Definition: normal.c:49
#define UNICODE_NULL
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define L(x)
Definition: ntvdm.h:50
unsigned short USHORT
Definition: pedump.c:61
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
unsigned char * PBOOLEAN
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
uint16_t * PUSHORT
Definition: typedefs.h:56
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define IN
Definition: typedefs.h:39
uint16_t * PWCHAR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
STRING OEM_STRING
Definition: umtypes.h:203
_In_ WDFCOLLECTION _In_ ULONG Index
_In_ BOOLEAN _Inout_ PGENERATE_NAME_CONTEXT _Inout_ PUNICODE_STRING Name8dot3
Definition: rtlfuncs.h:1600
*BytesInOemString PCHAR OemString
Definition: rtlfuncs.h:1574
_In_ BOOLEAN AllowExtendedCharacters
Definition: rtlfuncs.h:1598
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180