3 * Copyright (C) 2002 ReactOS Team
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.
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.
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.
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * FILE: lib/rtl/dos8dot3.c
24 * PURPOSE: Short name (8.3 name) functions
25 * PROGRAMMER: Eric Kohl
28 /* INCLUDES ******************************************************************/
36 /* CONSTANTS *****************************************************************/
38 const PCHAR RtlpShortIllegals
= " ;+=[],\"*\\<>/?:|";
41 /* FUNCTIONS *****************************************************************/
44 RtlpIsShortIllegal(CHAR Char
)
46 return strchr(RtlpShortIllegals
, Char
) ? TRUE
: FALSE
;
50 RtlpGetCheckSum(PUNICODE_STRING Name
)
56 Length
= Name
->Length
/ sizeof(WCHAR
);
60 Hash
= (Hash
+ (*c
<< 4) + (*c
>> 4)) * 11;
67 RtlpGetIndexLength(ULONG Index
)
75 return Length
? Length
: 1;
83 RtlGenerate8dot3Name(IN PUNICODE_STRING Name
,
84 IN BOOLEAN AllowExtendedCharacters
,
85 IN OUT PGENERATE_NAME_CONTEXT Context
,
86 OUT PUNICODE_STRING Name8dot3
)
102 StrLength
= Name
->Length
/ sizeof(WCHAR
);
103 DPRINT("StrLength: %hu\n", StrLength
);
105 /* Find last dot in Name */
107 for (i
= 0; i
< StrLength
; i
++)
109 if (Name
->Buffer
[i
] == L
'.')
119 DPRINT("DotPos: %hu\n", DotPos
);
121 /* Copy name (6 valid characters max) */
122 for (i
= 0, NameLength
= 0; NameLength
< 6 && i
< DotPos
; i
++)
125 RtlUpcaseUnicodeToOemN(&c
, sizeof(CHAR
), &Count
, &Name
->Buffer
[i
], sizeof(WCHAR
));
126 if (Count
!= 1 || c
== 0 || RtlpIsShortIllegal(c
))
128 NameBuffer
[NameLength
++] = L
'_';
132 NameBuffer
[NameLength
++] = (WCHAR
)c
;
136 DPRINT("NameBuffer: '%.08S'\n", NameBuffer
);
137 DPRINT("NameLength: %hu\n", NameLength
);
139 /* Copy extension (4 valid characters max) */
140 if (DotPos
< StrLength
)
142 for (i
= DotPos
, ExtLength
= 0; ExtLength
< 4 && i
< StrLength
; i
++)
145 RtlUpcaseUnicodeToOemN(&c
, sizeof(CHAR
), &Count
, &Name
->Buffer
[i
], sizeof(WCHAR
));
146 if (Count
!= 1 || c
== 0 || RtlpIsShortIllegal(Name
->Buffer
[i
]))
148 ExtBuffer
[ExtLength
++] = L
'_';
152 ExtBuffer
[ExtLength
++] = c
;
160 DPRINT("ExtBuffer: '%.04S'\n", ExtBuffer
);
161 DPRINT("ExtLength: %hu\n", ExtLength
);
163 /* Determine next index */
164 IndexLength
= RtlpGetIndexLength(Context
->LastIndexValue
);
165 if (Context
->CheckSumInserted
)
167 CopyLength
= min(NameLength
, 8 - 4 - 1 - IndexLength
);
168 Checksum
= RtlpGetCheckSum(Name
);
172 CopyLength
= min(NameLength
, 8 - 1 - IndexLength
);
176 DPRINT("CopyLength: %hu\n", CopyLength
);
178 if ((Context
->NameLength
== CopyLength
) &&
179 (wcsncmp(Context
->NameBuffer
, NameBuffer
, CopyLength
) == 0) &&
180 (Context
->ExtensionLength
== ExtLength
) &&
181 (wcsncmp(Context
->ExtensionBuffer
, ExtBuffer
, ExtLength
) == 0) &&
182 (Checksum
== Context
->Checksum
) &&
183 (Context
->LastIndexValue
< 999))
186 Context
->LastIndexValue
++;
187 if (Context
->CheckSumInserted
== FALSE
&&
188 Context
->LastIndexValue
> 9)
190 Context
->CheckSumInserted
= TRUE
;
191 Context
->LastIndexValue
= 1;
192 Context
->Checksum
= RtlpGetCheckSum(Name
);
198 Context
->LastIndexValue
= 1;
199 Context
->CheckSumInserted
= FALSE
;
202 IndexLength
= RtlpGetIndexLength(Context
->LastIndexValue
);
204 DPRINT("CurrentIndex: %hu, IndexLength %hu\n", Context
->LastIndexValue
, IndexLength
);
206 if (Context
->CheckSumInserted
)
208 CopyLength
= min(NameLength
, 8 - 4 - 1 - IndexLength
);
212 CopyLength
= min(NameLength
, 8 - 1 - IndexLength
);
215 /* Build the short name */
216 memcpy(Name8dot3
->Buffer
, NameBuffer
, CopyLength
* sizeof(WCHAR
));
218 if (Context
->CheckSumInserted
)
221 Checksum
= Context
->Checksum
;
222 for (i
= 0; i
< 4; i
++)
224 Name8dot3
->Buffer
[j
--] = (Checksum
% 16) > 9 ? (Checksum
% 16) + L
'A' - 10 : (Checksum
% 16) + L
'0';
229 Name8dot3
->Buffer
[j
++] = L
'~';
230 j
+= IndexLength
- 1;
231 CurrentIndex
= Context
->LastIndexValue
;
232 for (i
= 0; i
< IndexLength
; i
++)
234 Name8dot3
->Buffer
[j
--] = (CurrentIndex
% 10) + L
'0';
237 j
+= IndexLength
+ 1;
239 memcpy(Name8dot3
->Buffer
+ j
, ExtBuffer
, ExtLength
* sizeof(WCHAR
));
240 Name8dot3
->Length
= (j
+ ExtLength
) * sizeof(WCHAR
);
242 DPRINT("Name8dot3: '%wZ'\n", Name8dot3
);
245 Context
->NameLength
= CopyLength
;
246 Context
->ExtensionLength
= ExtLength
;
247 memcpy(Context
->NameBuffer
, NameBuffer
, CopyLength
* sizeof(WCHAR
));
248 memcpy(Context
->ExtensionBuffer
, ExtBuffer
, ExtLength
* sizeof(WCHAR
));
256 RtlIsNameLegalDOS8Dot3(IN PUNICODE_STRING UnicodeName
,
257 IN PANSI_STRING AnsiName
,
258 OUT PBOOLEAN SpacesFound
)
260 PANSI_STRING name
= AnsiName
;
261 ANSI_STRING DummyString
;
267 BOOLEAN HasSpace
= FALSE
;
268 BOOLEAN HasDot
= FALSE
;
270 if (UnicodeName
->Length
> 24)
272 return(FALSE
); /* name too long */
279 name
->MaximumLength
= 12;
280 name
->Buffer
= Buffer
;
283 Status
= RtlUpcaseUnicodeStringToCountedOemString(name
,
286 if (!NT_SUCCESS(Status
))
291 Length
= name
->Length
;
294 if (!(Length
== 1 && *str
== '.') &&
295 !(Length
== 2 && *str
== '.' && *(str
+ 1) == '.'))
297 for (i
= 0; i
< Length
; i
++, str
++)
306 if ((HasDot
) || /* two or more dots */
307 (i
== 0) || /* dot is first char */
308 (i
+ 1 == Length
) || /* dot is last char */
309 (Length
- i
> 4) || /* more than 3 chars of extension */
310 (HasDot
== FALSE
&& i
> 8)) /* name is longer than 8 chars */
315 if (RtlpIsShortIllegal(*str
))
323 /* Name is longer than 8 chars and does not have an extension */
324 if (Length
> 8 && HasDot
== FALSE
)
330 *SpacesFound
= HasSpace
;
340 RtlVolumeDeviceToDosName(
341 IN PVOID VolumeDeviceObject
,
342 OUT PUNICODE_STRING DosName
346 return STATUS_NOT_IMPLEMENTED
;