source: trunk/src/ufat32/unicode.c@ 197

Last change on this file since 197 was 193, checked in by Valery V. Sedletski, 8 years ago

UFAT32.DLL: Make FORMAT and CHKDSK more portable.

Make FS utilities more portable. Move all system-depemdent functions to os2.c.
Add CHKDSK standalone version. Also, FORMAT and CHKDSK now successfully build
for win32 target. Rename fat32chk.exe to f32chk.exe. Now CHKDSK and FORMAT
standalone versions are called fat32chk.exe and fat32fmt.exe, for consistency.
Add win32 makefile.

File size: 15.2 KB
Line 
1#include <malloc.h>
2#include <string.h>
3#include <stdio.h>
4
5#include "fat32c.h"
6
7#include <uconv.h>
8
9#define MAX_TRANS_TABLE 0x100
10#define ARRAY_TRANS_TABLE ( 0x10000 / MAX_TRANS_TABLE )
11
12#define INDEX_OF_START MAX_TRANS_TABLE
13#define INDEX_OF_FIRSTINFO MAX_TRANS_TABLE
14#define INDEX_OF_LCASECONV ( MAX_TRANS_TABLE + 1 )
15#define INDEX_OF_END INDEX_OF_LCASECONV
16#define EXTRA_ELEMENT ( INDEX_OF_END - INDEX_OF_START + 1 )
17
18#define ARRAY_COUNT_PAGE 4
19#define MAX_ARRAY_PAGE ( 0x100 / ARRAY_COUNT_PAGE )
20
21#define ARRAY_COUNT_UNICODE 256
22#define MAX_ARRAY_UNICODE (( USHORT )( 0x10000L / ARRAY_COUNT_UNICODE ))
23
24VOID SetUni2NLS( USHORT usPage, USHORT usChar, USHORT usCode );
25VOID TranslateAllocBuffer( VOID );
26
27extern F32PARMS f32Parms;
28
29int (* CALLCONV pUniCreateUconvObject)(UniChar * code_set, UconvObject * uobj);
30int (* CALLCONV pUniUconvToUcs)(
31 UconvObject uobj, /* I - Uconv object handle */
32 void * * inbuf, /* IO - Input buffer */
33 size_t * inbytes, /* IO - Input buffer size (bytes) */
34 UniChar * * outbuf, /* IO - Output buffer size */
35 size_t * outchars, /* IO - Output size (chars) */
36 size_t * subst ); /* IO - Substitution count */
37int (* CALLCONV pUniUconvFromUcs)(
38 UconvObject uobj,
39 UniChar * * inbuf,
40 size_t * inchars,
41 void * * outbuf,
42 size_t * outbytes,
43 size_t * subst );
44int (* CALLCONV pUniMapCpToUcsCp)( ULONG ulCp, UniChar *ucsCp, size_t n );
45UniChar (* CALLCONV pUniTolower )( UniChar uin );
46int (* CALLCONV pUniQueryUconvObject )
47 (UconvObject uobj, uconv_attribute_t *attr, size_t size, char first[256], char other[256], udcrange_t udcrange[32]);
48
49static ULONG ulNewCP = 0;
50
51typedef struct _UniPage
52{
53USHORT usCode[256];
54} UNIPAGE, *PUNIPAGE;
55
56static PUSHORT rgUnicode[ ARRAY_COUNT_UNICODE ] = { NULL, };
57
58UCHAR rgFirstInfo[ 256 ] = { 0 , };
59static PUNIPAGE rgPage[ ARRAY_COUNT_PAGE ] = { NULL, };
60
61static UCHAR rgLCase[ 256 ] =
62{ 0,
63 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
64 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
65 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
66 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
67 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
68 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
69 61, 62, 63, 64,
70 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
71 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
72 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
73 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
74 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
75 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
76 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
77 141, 142, 143, 144, 145, 146, 147, 148, 149, 150,
78 151, 152, 153, 154, 155, 156, 157, 158, 159, 160,
79 161, 162, 163, 164, 165, 166, 167, 168, 169, 170,
80 171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
81 181, 182, 183, 184, 185, 186, 187, 188, 189, 190,
82 191, 192, 193, 194, 195, 196, 197, 198, 199, 200,
83 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
84 211, 212, 213, 214, 215, 216, 217, 218, 219, 220,
85 221, 222, 223, 224, 225, 226, 227, 228, 229, 230,
86 231, 232, 233, 234, 235, 236, 237, 238, 239, 240,
87 241, 242, 243, 244, 245, 246, 247, 248, 249, 250,
88 251, 252, 253, 254, 255
89};
90
91HMODULE hModConv = 0;
92HMODULE hModUni = 0;
93
94/************************************************************************
95*
96************************************************************************/
97USHORT QueryUni2NLS( USHORT usPage, USHORT usChar )
98{
99 return rgPage[ usPage / MAX_ARRAY_PAGE ][ usPage % MAX_ARRAY_PAGE ].usCode[ usChar ];
100}
101
102/******************************************************************
103*
104******************************************************************/
105USHORT QueryNLS2Uni( USHORT usCode )
106{
107 return rgUnicode[ usCode / MAX_ARRAY_UNICODE ][ usCode % MAX_ARRAY_UNICODE ];
108}
109
110/******************************************************************
111*
112******************************************************************/
113VOID GetFirstInfo( PBOOL pFirstInfo )
114{
115 memcpy( pFirstInfo, rgFirstInfo, sizeof( rgFirstInfo ));
116}
117
118/******************************************************************
119*
120******************************************************************/
121BOOL TranslateInit(PVOID16 rgTrans[], USHORT usSize)
122{
123 ULONG ulCode;
124 USHORT usPage;
125 USHORT usChar;
126 INT iIndex;
127
128 PVOID16 *prgTrans = ( PVOID16 * )rgTrans;
129
130 if( rgPage[ 0 ] == NULL )
131 TranslateAllocBuffer();
132
133 if (usSize != sizeof( PVOID ) * ( ARRAY_COUNT_UNICODE + 2 ) )
134 return FALSE;
135
136 for( iIndex = 0; iIndex < ARRAY_COUNT_UNICODE; iIndex++ )
137 memcpy( rgUnicode[ iIndex ], (void *)(void _Far16 *)prgTrans[ iIndex ], sizeof( USHORT ) * MAX_ARRAY_UNICODE );
138
139 for( iIndex = 0; iIndex < MAX_ARRAY_UNICODE; iIndex++ )
140 rgFirstInfo[ iIndex ] = ( UCHAR )((( PUSHORT )( prgTrans[ ARRAY_COUNT_UNICODE ] ))[ iIndex ]);
141
142 for( iIndex = 0; iIndex < MAX_ARRAY_UNICODE; iIndex++ )
143 rgLCase[ iIndex ] = ( UCHAR )((( PUSHORT )( prgTrans[ ARRAY_COUNT_UNICODE + 1 ] ))[ iIndex ]);
144
145 for( iIndex = 0; iIndex < ARRAY_COUNT_PAGE; iIndex++ )
146 memset( rgPage[ iIndex ], '_', sizeof( UNIPAGE ) * MAX_ARRAY_PAGE );
147
148 for (ulCode = 0; ulCode < 0x10000; ulCode++)
149 {
150 usPage = (QueryNLS2Uni(( USHORT )ulCode ) >> 8) & 0x00FF;
151 usChar = QueryNLS2Uni(( USHORT )ulCode ) & 0x00FF;
152
153 SetUni2NLS( usPage, usChar, ( USHORT )ulCode );
154 }
155
156 //f32Parms.fTranslateNames = TRUE;
157
158 return TRUE;
159}
160
161/******************************************************************
162*
163******************************************************************/
164VOID TranslateAllocBuffer( VOID )
165{
166 INT iIndex;
167
168 for( iIndex = 0; iIndex < ARRAY_COUNT_PAGE; iIndex++ )
169 rgPage[ iIndex ] = malloc( sizeof( UNIPAGE ) * MAX_ARRAY_PAGE );
170
171 for( iIndex = 0; iIndex < ARRAY_COUNT_UNICODE; iIndex++ )
172 rgUnicode[ iIndex ] = malloc( sizeof( USHORT ) * MAX_ARRAY_UNICODE );
173}
174
175/******************************************************************
176*
177******************************************************************/
178BOOL LoadTranslateTable(BOOL fSilent)
179{
180 APIRET rc;
181 ULONG ulParmSize;
182 BYTE rgData[ 256 ];
183 // Extra space for DBCS lead info and case conversion
184 UniChar *rgTranslate[ MAX_TRANS_TABLE + EXTRA_ELEMENT ] = { NULL, };
185 PBYTE pChar;
186 UniChar *pUni;
187 UconvObject uconv_object = NULL;
188 INT iIndex;
189 size_t bytes_left;
190 size_t uni_chars_left;
191 size_t num_subs;
192 ULONG rgCP[3];
193 ULONG cbCP;
194 // Extra space for DBCS lead info and case conversion
195 PVOID16 rgTransTable[ MAX_TRANS_TABLE + EXTRA_ELEMENT ] = { NULL, };
196 char rgFirst[ 256 ];
197 USHORT first, second;
198 USHORT usCode;
199 UniChar ucsCp[ 12 ];
200 UniChar rgUniBuffer[ ARRAY_TRANS_TABLE ];
201
202 rc = DosLoadModule(rgData, sizeof rgData, "UCONV.DLL", &hModConv);
203 if (rc)
204 {
205 printf("FAT32: No NLS support found (%s does not load).\n", rgData);
206 printf("FAT32: No UNICODE translate table loaded!\n");
207 rc = TRUE;
208 goto free_exit;
209 }
210 rc = DosQueryProcAddr(hModConv, 0L,
211 "UniCreateUconvObject", (PFN *)&pUniCreateUconvObject);
212 if (rc)
213 {
214 printf("FAT32: ERROR: Could not find address of UniCreateUconvObject.\n");
215 rc = FALSE;
216 goto free_exit;
217 }
218 rc = DosQueryProcAddr(hModConv, 0L,
219 "UniUconvToUcs", (PFN *)&pUniUconvToUcs);
220 if (rc)
221 {
222 printf("FAT32: ERROR: Could not find address of UniUconvToUcs.\n");
223 rc = FALSE;
224 goto free_exit;
225 }
226
227 rc = DosQueryProcAddr(hModConv, 0L,
228 "UniUconvFromUcs", (PFN *)&pUniUconvFromUcs);
229 if (rc)
230 {
231 printf("FAT32: ERROR: Could not find address of UniUconvFromUcs.\n");
232 rc = FALSE;
233 goto free_exit;
234 }
235
236 rc = DosQueryProcAddr(hModConv, 0L,
237 "UniMapCpToUcsCp", (PFN *)&pUniMapCpToUcsCp);
238 if (rc)
239 {
240 printf("FAT32: ERROR: Could not find address of UniMapCpToUcsCp.\n");
241 rc = FALSE;
242 goto free_exit;
243 }
244
245 rc = DosQueryProcAddr(hModConv, 0L,
246 "UniQueryUconvObject", (PFN *)&pUniQueryUconvObject);
247 if (rc)
248 {
249 printf("FAT32: ERROR: Could not find address of UniQueryUconvObject.\n");
250 rc = FALSE;
251 goto free_exit;
252 }
253
254 rc = DosLoadModule(rgData, sizeof rgData, "LIBUNI.DLL", &hModUni);
255 if (rc)
256 {
257 printf("FAT32: No NLS support found (%s does not load).\n", rgData);
258 printf("FAT32: No UNICODE translate table loaded!\n");
259 rc = TRUE;
260 goto free_exit;
261 }
262
263 rc = DosQueryProcAddr(hModUni, 0L,
264 "UniTolower", (PFN *)&pUniTolower);
265 if (rc)
266 {
267 printf("FAT32: ERROR: Could not find address of UniTolower.\n");
268 rc = FALSE;
269 goto free_exit;
270 }
271
272 if( ulNewCP )
273 rgCP[ 0 ] = ulNewCP;
274 else
275 DosQueryCp(sizeof rgCP, rgCP, &cbCP);
276
277 if (f32Parms.ulCurCP == rgCP[0])
278 {
279 rc = FALSE;
280 goto free_exit;
281 }
282
283#if 0
284 if (f32Parms.ulCurCP && !fSayYes)
285 {
286 BYTE chChar;
287 printf("Loaded unicode translate table is for CP %lu\n", f32Parms.ulCurCP);
288 printf("Current CP is %lu\n", rgCP[0]);
289 printf("Would you like to reload the translate table for this CP [Y/N]? ");
290 fflush(stdout);
291
292 for (;;)
293 {
294 chChar = getch();
295 switch (chChar)
296 {
297 case 'y':
298 case 'Y':
299 chChar = 'Y';
300 break;
301 case 'n':
302 case 'N':
303 chChar = 'N';
304 break;
305 default :
306 DosBeep(660, 10);
307 continue;
308 }
309 printf("%c\n", chChar);
310 break;
311 }
312 if (chChar == 'N')
313 {
314 rc = FALSE;
315 goto free_exit;
316 }
317 }
318#endif
319
320 rc = pUniMapCpToUcsCp( rgCP[ 0 ], ucsCp, sizeof( ucsCp ) / sizeof( UniChar ));
321 if( rc != ULS_SUCCESS )
322 {
323 printf("FAT32: ERROR: UniMapCpToUcsCp error: return code = %u\n", rc );
324 rc = FALSE;
325 goto free_exit;
326 }
327
328 rc = pUniCreateUconvObject( ucsCp, &uconv_object);
329 if (rc != ULS_SUCCESS)
330 {
331 printf("FAT32: ERROR: UniCreateUconvObject error: return code = %u\n", rc);
332 rc = FALSE;
333 goto free_exit;
334 }
335
336 rc = pUniQueryUconvObject( uconv_object, NULL, 0, rgFirst, NULL, NULL );
337 if (rc != ULS_SUCCESS)
338 {
339 printf("FAT32: ERROR: UniQueryUConvObject error: return code = %u\n", rc);
340 rc = FALSE;
341 goto free_exit;
342 }
343
344 // Allocation for conversion, DBCS lead info and case conversion
345 for( iIndex = 0; iIndex <= INDEX_OF_END ; iIndex ++ )
346 {
347 rgTransTable[ iIndex ] = rgTranslate[ iIndex ] = malloc( sizeof(USHORT ) * ARRAY_TRANS_TABLE );
348 memset( rgTranslate[ iIndex ], 0, sizeof( USHORT ) * ARRAY_TRANS_TABLE );
349 }
350
351 // Initialize SBCS only for conversion and set DBCS lead info
352 for( iIndex = 0; iIndex < ARRAY_TRANS_TABLE; iIndex++ )
353 {
354 rgData[ iIndex ] = ( rgFirst[ iIndex ] == 1 ) ? iIndex : 0;
355 rgTranslate[ INDEX_OF_FIRSTINFO ][ iIndex ] = rgFirst[ iIndex ];
356 }
357
358 pChar = rgData;
359 bytes_left = sizeof rgData;
360 pUni = ( PVOID )rgTranslate[ 0 ];
361 uni_chars_left = ARRAY_TRANS_TABLE;
362
363 rc = pUniUconvToUcs(uconv_object,
364 (PVOID *)&pChar,
365 &bytes_left,
366 &pUni,
367 &uni_chars_left,
368 &num_subs);
369
370 if (rc != ULS_SUCCESS)
371 {
372 printf("FAT32: ERROR: UniUconvToUcs failed, rc = %u\n", rc);
373 rc = FALSE;
374 goto free_exit;
375 }
376
377 // Translate upper case to lower case
378 for( iIndex = 0; iIndex < ARRAY_TRANS_TABLE; iIndex++ )
379 rgUniBuffer[ iIndex ] = pUniTolower( rgTranslate[ 0 ][ iIndex ] );
380
381 // Convert lower case in Unicode to codepage code
382 pUni = ( PVOID )rgUniBuffer;
383 uni_chars_left = ARRAY_TRANS_TABLE;
384 pChar = rgData;
385 bytes_left = sizeof rgData;
386
387 rc = pUniUconvFromUcs( uconv_object,
388 &pUni,
389 &uni_chars_left,
390 ( PVOID * )&pChar,
391 &bytes_left,
392 &num_subs );
393
394 if (rc != ULS_SUCCESS)
395 {
396 printf("FAT32: ERROR: UniUconvFromUcs failed, rc = %u\n", rc);
397 rc = FALSE;
398 goto free_exit;
399 }
400
401 // Store codepage code to transtable
402 for( iIndex = 0; iIndex < ARRAY_TRANS_TABLE; iIndex++ )
403 rgTranslate[ INDEX_OF_LCASECONV ][ iIndex ] = rgData[ iIndex ] ? rgData[ iIndex ] : iIndex;
404
405 // Translate DBCS code to unicode
406 for( first = 0; first < ARRAY_TRANS_TABLE; first++ )
407 {
408 if( rgFirst[ first ] == 2 )
409 {
410 for( second = 0; second < 0x100; second++ )
411 {
412 usCode = first | (( second << 8 ) & 0xFF00 );
413
414 pChar = ( PVOID )&usCode;
415 bytes_left = sizeof usCode;
416 pUni = ( PVOID )&rgTranslate[ second ][ first ];
417 uni_chars_left = 1;
418
419 rc = pUniUconvToUcs(uconv_object,
420 (PVOID *)&pChar,
421 &bytes_left,
422 &pUni,
423 &uni_chars_left,
424 &num_subs);
425
426 if (rc != ULS_SUCCESS)
427 {
428 printf("FAT32: ERROR: UniUconvToUcs failed, rc = %u\n", rc);
429 rc = FALSE;
430 goto free_exit;
431 }
432 }
433 }
434 }
435
436 ulParmSize = sizeof rgTransTable;
437 if( !TranslateInit((PVOID)rgTransTable, ulParmSize))
438 rc = ERROR_INVALID_PARAMETER;
439 else
440 rc = 0;
441
442 if (rc)
443 {
444 printf("FAT32: ERROR: Unable to set translate table for current Codepage.\n");
445 rc = FALSE;
446 goto free_exit;
447 }
448
449 f32Parms.ulCurCP = rgCP[0];
450 if( ! fSilent )
451 printf("FAT32: Unicode translate table for CP %lu loaded.\n", rgCP[0]);
452 rc = TRUE;
453free_exit:
454
455 for( iIndex = 0; iIndex <= INDEX_OF_END; iIndex++ )
456 if( rgTranslate[ iIndex ])
457 free( rgTranslate[ iIndex ]);
458
459 if( hModConv )
460 DosFreeModule( hModConv);
461
462 if( hModUni )
463 DosFreeModule( hModUni );
464
465 return rc;
466}
467
468/******************************************************************
469*
470******************************************************************/
471VOID SetUni2NLS( USHORT usPage, USHORT usChar, USHORT usCode )
472{
473 rgPage[ usPage / MAX_ARRAY_PAGE ][ usPage % MAX_ARRAY_PAGE ].usCode[ usChar ] = usCode;
474}
475
476/******************************************************************
477*
478******************************************************************/
479VOID GetCaseConversion( PUCHAR pCase )
480{
481 memcpy( pCase, rgLCase, sizeof( rgLCase ));
482}
483
484VOID TranslateInitDBCSEnv( VOID )
485{
486 GetFirstInfo(( PBOOL )rgFirstInfo );
487}
488
489VOID CaseConversionInit( VOID )
490{
491 GetCaseConversion(rgLCase);
492}
493
494void CodepageConvInit(BOOL fSilent)
495{
496 LoadTranslateTable(fSilent);
497 TranslateInitDBCSEnv();
498 CaseConversionInit();
499}
Note: See TracBrowser for help on using the repository browser.