xref: /onnv-gate/usr/src/common/smbsrv/smb_oem.c (revision 10966:37e5dcdf36d3)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
215331Samw /*
22*10966SJordan.Brown@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
235331Samw  * Use is subject to license terms.
245331Samw  */
255331Samw 
265331Samw /*
275331Samw  * Support for oem <-> unicode translations.
285331Samw  */
295331Samw 
305331Samw #ifndef _KERNEL
315331Samw #include <stdlib.h>
325331Samw #include <thread.h>
335331Samw #include <synch.h>
345331Samw #include <string.h>
35*10966SJordan.Brown@Sun.COM #else
36*10966SJordan.Brown@Sun.COM #include <sys/ksynch.h>
375331Samw #endif /* _KERNEL */
38*10966SJordan.Brown@Sun.COM 
39*10966SJordan.Brown@Sun.COM #include <sys/byteorder.h>
405331Samw #include <smbsrv/alloc.h>
415331Samw #include <smbsrv/string.h>
42*10966SJordan.Brown@Sun.COM 
435331Samw /*
44*10966SJordan.Brown@Sun.COM  * cpid		The oemcpg_table index for this oempage.
45*10966SJordan.Brown@Sun.COM  * value	The conversion values.
46*10966SJordan.Brown@Sun.COM  */
47*10966SJordan.Brown@Sun.COM typedef struct oempage {
48*10966SJordan.Brown@Sun.COM 	uint32_t	cpid;
49*10966SJordan.Brown@Sun.COM 	smb_wchar_t	*value;
50*10966SJordan.Brown@Sun.COM } oempage_t;
51*10966SJordan.Brown@Sun.COM 
52*10966SJordan.Brown@Sun.COM /*
53*10966SJordan.Brown@Sun.COM  * filename	The actual filename contains the codepage.
54*10966SJordan.Brown@Sun.COM  * bytesperchar	The codepage uses double or single bytes per char.
55*10966SJordan.Brown@Sun.COM  * oempage	The oempage is used to convert Unicode characters to
56*10966SJordan.Brown@Sun.COM  *		OEM characters.  Memory needs to be allocated for
57*10966SJordan.Brown@Sun.COM  *		the value field of oempage to store the table.
58*10966SJordan.Brown@Sun.COM  * ucspage	The unicode page is used to convert OEM characters
59*10966SJordan.Brown@Sun.COM  *		to Unicode characters.  Memory needs to be allocated
60*10966SJordan.Brown@Sun.COM  *		for the value field of ucspage to store the table.
61*10966SJordan.Brown@Sun.COM  * valid	True if the codepage has been initialized.
625331Samw  */
635331Samw typedef struct oem_codepage {
64*10966SJordan.Brown@Sun.COM 	char		*filename;
65*10966SJordan.Brown@Sun.COM 	uint32_t	bytesperchar;
66*10966SJordan.Brown@Sun.COM 	oempage_t	oempage;
67*10966SJordan.Brown@Sun.COM 	oempage_t	ucspage;
68*10966SJordan.Brown@Sun.COM 	boolean_t	valid;
695331Samw } oem_codepage_t;
705331Samw 
71*10966SJordan.Brown@Sun.COM static oem_codepage_t oemcpg_table[] = {
72*10966SJordan.Brown@Sun.COM 	{"850.cpg",  1, {0, 0},  {0, 0},  0},	/* Multilingual Latin1 */
73*10966SJordan.Brown@Sun.COM 	{"950.cpg",  2, {1, 0},  {1, 0},  0},	/* Chinese Traditional */
74*10966SJordan.Brown@Sun.COM 	{"1252.cpg", 1, {2, 0},  {2, 0},  0},	/* MS Latin1 */
75*10966SJordan.Brown@Sun.COM 	{"949.cpg",  2, {3, 0},  {3, 0},  0},	/* Korean */
76*10966SJordan.Brown@Sun.COM 	{"936.cpg",  2, {4, 0},  {4, 0},  0},	/* Chinese Simplified */
77*10966SJordan.Brown@Sun.COM 	{"932.cpg",  2, {5, 0},  {5, 0},  0},	/* Japanese */
78*10966SJordan.Brown@Sun.COM 	{"852.cpg",  1, {6, 0},  {6, 0},  0},	/* Multilingual Latin2 */
79*10966SJordan.Brown@Sun.COM 	{"1250.cpg", 1, {7, 0},  {7, 0},  0},	/* MS Latin2 */
80*10966SJordan.Brown@Sun.COM 	{"1253.cpg", 1, {8, 0},  {8, 0},  0},	/* MS Greek */
81*10966SJordan.Brown@Sun.COM 	{"737.cpg",  1, {9, 0},  {9, 0},  0},	/* Greek */
82*10966SJordan.Brown@Sun.COM 	{"1254.cpg", 1, {10, 0}, {10, 0}, 0},	/* MS Turkish */
83*10966SJordan.Brown@Sun.COM 	{"857.cpg",  1, {11, 0}, {11, 0}, 0},	/* Multilingual Latin5 */
84*10966SJordan.Brown@Sun.COM 	{"1251.cpg", 1, {12, 0}, {12, 0}, 0},	/* MS Cyrillic */
85*10966SJordan.Brown@Sun.COM 	{"866.cpg",  1, {13, 0}, {13, 0}, 0},	/* Cyrillic II */
86*10966SJordan.Brown@Sun.COM 	{"1255.cpg", 1, {14, 0}, {14, 0}, 0},	/* MS Hebrew */
87*10966SJordan.Brown@Sun.COM 	{"862.cpg",  1, {15, 0}, {15, 0}, 0},	/* Hebrew */
88*10966SJordan.Brown@Sun.COM 	{"1256.cpg", 1, {16, 0}, {16, 0}, 0},	/* MS Arabic */
89*10966SJordan.Brown@Sun.COM 	{"720.cpg",  1, {17, 0}, {17, 0}, 0}	/* Arabic */
905331Samw };
915331Samw 
92*10966SJordan.Brown@Sun.COM #define	MAX_OEMPAGES	(sizeof (oemcpg_table) / sizeof (oemcpg_table[0]))
93*10966SJordan.Brown@Sun.COM #define	MAX_UNICODE_IDX	65536
945331Samw 
955331Samw /*
96*10966SJordan.Brown@Sun.COM  * The default SMB OEM codepage for English is codepage 850.
975331Samw  */
98*10966SJordan.Brown@Sun.COM smb_wchar_t oem_codepage_850[256] = {
995331Samw 	0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
1005331Samw 	0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
1015331Samw 	0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
1025331Samw 	0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
1035331Samw 	0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
1045331Samw 	0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
1055331Samw 	0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
1065331Samw 	0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
1075331Samw 	0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
1085331Samw 	0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
1095331Samw 	0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
1105331Samw 	0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
1115331Samw 	0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
1125331Samw 	0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
1135331Samw 	0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
1145331Samw 	0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
1155331Samw 	0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
1165331Samw 	0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
1175331Samw 	0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
1185331Samw 	0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
1195331Samw 	0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
1205331Samw 	0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
1215331Samw 	0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0,
1225331Samw 	0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
1235331Samw 	0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3,
1245331Samw 	0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
1255331Samw 	0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE,
1265331Samw 	0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
1275331Samw 	0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE,
1285331Samw 	0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4,
1295331Samw 	0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8,
1305331Samw 	0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
1315331Samw };
1325331Samw 
1335331Samw /*
134*10966SJordan.Brown@Sun.COM  * The default telnet OEM codepage for English is codepage 1252.
1355331Samw  */
136*10966SJordan.Brown@Sun.COM smb_wchar_t oem_codepage_1252[256] = {
1375331Samw 	0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
1385331Samw 	0x9, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x10,
1395331Samw 	0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
1405331Samw 	0x19, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x20,
1415331Samw 	0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
1425331Samw 	0x29, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x30,
1435331Samw 	0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
1445331Samw 	0x39, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x40,
1455331Samw 	0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
1465331Samw 	0x49, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x50,
1475331Samw 	0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
1485331Samw 	0x59, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x60,
1495331Samw 	0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
1505331Samw 	0x69, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x70,
1515331Samw 	0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
1525331Samw 	0x79, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x20AC,
1535331Samw 	0x81, 0x201A, 0x192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6,
1545331Samw 	0x2030, 0x160, 0x2039, 0x152, 0x8D, 0x017D, 0x8F, 0x90,
1555331Samw 	0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC,
1565331Samw 	0x2122, 0x161, 0x203A, 0x153, 0x9D, 0x017E, 0x178, 0x00A0,
1575331Samw 	0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8,
1585331Samw 	0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0,
1595331Samw 	0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8,
1605331Samw 	0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0,
1615331Samw 	0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8,
1625331Samw 	0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0,
1635331Samw 	0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8,
1645331Samw 	0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0,
1655331Samw 	0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8,
1665331Samw 	0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0,
1675331Samw 	0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8,
1685331Samw 	0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF
1695331Samw };
1705331Samw 
171*10966SJordan.Brown@Sun.COM static oempage_t *oem_get_oempage(uint32_t);
172*10966SJordan.Brown@Sun.COM static oempage_t *oem_get_ucspage(uint32_t);
173*10966SJordan.Brown@Sun.COM static void oem_codepage_init(uint32_t);
174*10966SJordan.Brown@Sun.COM static void oem_codepage_setup(uint32_t);
1755331Samw 
1765331Samw /*
177*10966SJordan.Brown@Sun.COM  * Convert a unicode string to an oem string.
1785331Samw  *
179*10966SJordan.Brown@Sun.COM  * The conversion will stop at the end of the unicode string
180*10966SJordan.Brown@Sun.COM  * or when (nbytes - 1) oem characters have been stored.
181*10966SJordan.Brown@Sun.COM  *
182*10966SJordan.Brown@Sun.COM  * The number of converted unicode characters is returned,
183*10966SJordan.Brown@Sun.COM  * or 0 on error.
1845331Samw  */
185*10966SJordan.Brown@Sun.COM size_t
ucstooem(char * oem,const smb_wchar_t * ucs,size_t nbytes,uint32_t cpid)186*10966SJordan.Brown@Sun.COM ucstooem(char *oem, const smb_wchar_t *ucs, size_t nbytes, uint32_t cpid)
1875331Samw {
188*10966SJordan.Brown@Sun.COM 	oempage_t	*ucspage;
189*10966SJordan.Brown@Sun.COM 	uint32_t	count = 0;
190*10966SJordan.Brown@Sun.COM 	smb_wchar_t	oemchar;
191*10966SJordan.Brown@Sun.COM 
192*10966SJordan.Brown@Sun.COM 	if (ucs == NULL || oem == NULL)
1935331Samw 		return (0);
1945331Samw 
195*10966SJordan.Brown@Sun.COM 	if ((ucspage = oem_get_ucspage(cpid)) == NULL)
196*10966SJordan.Brown@Sun.COM 		return (0);
197*10966SJordan.Brown@Sun.COM 
198*10966SJordan.Brown@Sun.COM 	while (nbytes != 0 && (oemchar = ucspage->value[*ucs]) != 0) {
199*10966SJordan.Brown@Sun.COM 		if (oemchar & 0xff00 && nbytes >= MTS_MB_CHAR_MAX) {
200*10966SJordan.Brown@Sun.COM 			*oem++ = oemchar >> 8;
201*10966SJordan.Brown@Sun.COM 			*oem++ = (char)oemchar;
202*10966SJordan.Brown@Sun.COM 			nbytes -= 2;
203*10966SJordan.Brown@Sun.COM 		} else if (nbytes > 1) {
204*10966SJordan.Brown@Sun.COM 			*oem++ = (char)oemchar;
205*10966SJordan.Brown@Sun.COM 			nbytes--;
206*10966SJordan.Brown@Sun.COM 		} else {
207*10966SJordan.Brown@Sun.COM 			break;
208*10966SJordan.Brown@Sun.COM 		}
209*10966SJordan.Brown@Sun.COM 
210*10966SJordan.Brown@Sun.COM 		count++;
211*10966SJordan.Brown@Sun.COM 		ucs++;
212*10966SJordan.Brown@Sun.COM 	}
213*10966SJordan.Brown@Sun.COM 
214*10966SJordan.Brown@Sun.COM 	*oem = '\0';
215*10966SJordan.Brown@Sun.COM 	return (count);
2165331Samw }
2175331Samw 
2185331Samw /*
219*10966SJordan.Brown@Sun.COM  * Convert an oem string to a unicode string.
220*10966SJordan.Brown@Sun.COM  *
221*10966SJordan.Brown@Sun.COM  * The conversion will stop at the end of the oem string or
222*10966SJordan.Brown@Sun.COM  * when nwchars - 1 have been converted.
2235331Samw  *
224*10966SJordan.Brown@Sun.COM  * The number of converted oem chars is returned, or 0 on error.
225*10966SJordan.Brown@Sun.COM  * An oem char may be either 1 or 2 bytes.
2265331Samw  */
227*10966SJordan.Brown@Sun.COM size_t
oemtoucs(smb_wchar_t * ucs,const char * oem,size_t nwchars,uint32_t cpid)228*10966SJordan.Brown@Sun.COM oemtoucs(smb_wchar_t *ucs, const char *oem, size_t nwchars, uint32_t cpid)
2295331Samw {
230*10966SJordan.Brown@Sun.COM 	oempage_t	*oempage;
231*10966SJordan.Brown@Sun.COM 	size_t		count = nwchars;
232*10966SJordan.Brown@Sun.COM 	smb_wchar_t	oemchar;
2335331Samw 
234*10966SJordan.Brown@Sun.COM 	if (ucs == NULL || oem == NULL)
2355331Samw 		return (0);
2365331Samw 
237*10966SJordan.Brown@Sun.COM 	if ((oempage = oem_get_oempage(cpid)) == NULL)
2385331Samw 		return (0);
2395331Samw 
240*10966SJordan.Brown@Sun.COM 	while ((oemchar = (smb_wchar_t)*oem++ & 0xff) != 0) {
2415331Samw 		/*
242*10966SJordan.Brown@Sun.COM 		 * Cannot find one byte oemchar in table.
243*10966SJordan.Brown@Sun.COM 		 * Must be a lead byte. Try two bytes.
2445331Samw 		 */
2455331Samw 		if ((oempage->value[oemchar] == 0) && (oemchar != 0)) {
246*10966SJordan.Brown@Sun.COM 			oemchar = oemchar << 8 | (*oem++ & 0xff);
2475331Samw 			if (oempage->value[oemchar] == 0) {
248*10966SJordan.Brown@Sun.COM 				*ucs = 0;
2495331Samw 				break;
2505331Samw 			}
2515331Samw 		}
2525331Samw #ifdef _BIG_ENDIAN
253*10966SJordan.Brown@Sun.COM 		*ucs = LE_IN16(&oempage->value[oemchar]);
2545331Samw #else
255*10966SJordan.Brown@Sun.COM 		*ucs = oempage->value[oemchar];
2565331Samw #endif
2575331Samw 		count--;
258*10966SJordan.Brown@Sun.COM 		ucs++;
2595331Samw 	}
2605331Samw 
261*10966SJordan.Brown@Sun.COM 	*ucs = 0;
2625331Samw 	return (nwchars - count);
2635331Samw }
2645331Samw 
2655331Samw /*
266*10966SJordan.Brown@Sun.COM  * Get a pointer to the oem page for the specific codepage id.
2675331Samw  */
268*10966SJordan.Brown@Sun.COM static oempage_t *
oem_get_oempage(uint32_t cpid)269*10966SJordan.Brown@Sun.COM oem_get_oempage(uint32_t cpid)
2705331Samw {
271*10966SJordan.Brown@Sun.COM 	if (cpid >= MAX_OEMPAGES)
272*10966SJordan.Brown@Sun.COM 		return (NULL);
273*10966SJordan.Brown@Sun.COM 
274*10966SJordan.Brown@Sun.COM 	if (!oemcpg_table[cpid].valid) {
275*10966SJordan.Brown@Sun.COM 		oem_codepage_init(cpid);
276*10966SJordan.Brown@Sun.COM 
277*10966SJordan.Brown@Sun.COM 		if (!oemcpg_table[cpid].valid)
278*10966SJordan.Brown@Sun.COM 			return (NULL);
279*10966SJordan.Brown@Sun.COM 	}
280*10966SJordan.Brown@Sun.COM 
281*10966SJordan.Brown@Sun.COM 	return (&oemcpg_table[cpid].oempage);
2825331Samw }
2835331Samw 
2845331Samw /*
285*10966SJordan.Brown@Sun.COM  * Get a pointer to the ucs page for the specific codepage id.
2865331Samw  */
287*10966SJordan.Brown@Sun.COM static oempage_t *
oem_get_ucspage(uint32_t cpid)288*10966SJordan.Brown@Sun.COM oem_get_ucspage(uint32_t cpid)
2895331Samw {
290*10966SJordan.Brown@Sun.COM 	if (cpid >= MAX_OEMPAGES)
291*10966SJordan.Brown@Sun.COM 		return (NULL);
292*10966SJordan.Brown@Sun.COM 
293*10966SJordan.Brown@Sun.COM 	if (!oemcpg_table[cpid].valid) {
294*10966SJordan.Brown@Sun.COM 		oem_codepage_init(cpid);
295*10966SJordan.Brown@Sun.COM 
296*10966SJordan.Brown@Sun.COM 		if (!oemcpg_table[cpid].valid)
297*10966SJordan.Brown@Sun.COM 			return (NULL);
298*10966SJordan.Brown@Sun.COM 	}
299*10966SJordan.Brown@Sun.COM 
300*10966SJordan.Brown@Sun.COM 	return (&oemcpg_table[cpid].ucspage);
3015331Samw }
3025331Samw 
3035331Samw /*
304*10966SJordan.Brown@Sun.COM  * Initialize the oem page in the oem table.
3055331Samw  */
306*10966SJordan.Brown@Sun.COM static void
oem_codepage_init(uint32_t cpid)307*10966SJordan.Brown@Sun.COM oem_codepage_init(uint32_t cpid)
3085331Samw {
309*10966SJordan.Brown@Sun.COM #ifndef _KERNEL
310*10966SJordan.Brown@Sun.COM 	static mutex_t mutex;
311*10966SJordan.Brown@Sun.COM 
312*10966SJordan.Brown@Sun.COM 	(void) mutex_lock(&mutex);
313*10966SJordan.Brown@Sun.COM 	oem_codepage_setup(cpid);
314*10966SJordan.Brown@Sun.COM 	(void) mutex_unlock(&mutex);
315*10966SJordan.Brown@Sun.COM #else
316*10966SJordan.Brown@Sun.COM 	static kmutex_t mutex;
3175331Samw 
318*10966SJordan.Brown@Sun.COM 	mutex_enter(&mutex);
319*10966SJordan.Brown@Sun.COM 	oem_codepage_setup(cpid);
320*10966SJordan.Brown@Sun.COM 	mutex_exit(&mutex);
321*10966SJordan.Brown@Sun.COM #endif /* _KERNEL */
322*10966SJordan.Brown@Sun.COM }
3235331Samw 
324*10966SJordan.Brown@Sun.COM static void
oem_codepage_setup(uint32_t cpid)325*10966SJordan.Brown@Sun.COM oem_codepage_setup(uint32_t cpid)
326*10966SJordan.Brown@Sun.COM {
327*10966SJordan.Brown@Sun.COM 	smb_wchar_t	*default_oem_cp;
328*10966SJordan.Brown@Sun.COM 	oem_codepage_t	*oemcpg;
329*10966SJordan.Brown@Sun.COM 	uint32_t	bytesperchar;
330*10966SJordan.Brown@Sun.COM 	uint32_t	max_oem_index;
331*10966SJordan.Brown@Sun.COM 	int		i;
3325331Samw 
333*10966SJordan.Brown@Sun.COM 	switch (cpid) {
334*10966SJordan.Brown@Sun.COM 	case OEM_CPG_850:
335*10966SJordan.Brown@Sun.COM 		default_oem_cp = oem_codepage_850;
336*10966SJordan.Brown@Sun.COM 		break;
337*10966SJordan.Brown@Sun.COM 	case OEM_CPG_1252:
338*10966SJordan.Brown@Sun.COM 		default_oem_cp = oem_codepage_1252;
339*10966SJordan.Brown@Sun.COM 	default:
3405331Samw 		return;
3415331Samw 	}
3425331Samw 
343*10966SJordan.Brown@Sun.COM 	oemcpg = &oemcpg_table[cpid];
344*10966SJordan.Brown@Sun.COM 	if (oemcpg->valid)
345*10966SJordan.Brown@Sun.COM 		return;
3465331Samw 
3475331Samw 	/*
348*10966SJordan.Brown@Sun.COM 	 * max_oem_index will be 256 or 65536 dependent
349*10966SJordan.Brown@Sun.COM 	 * on the OEM codepage.
3505331Samw 	 */
351*10966SJordan.Brown@Sun.COM 	bytesperchar = oemcpg_table[cpid].bytesperchar;
352*10966SJordan.Brown@Sun.COM 	max_oem_index = 1 << (bytesperchar * 8);
3535331Samw 
354*10966SJordan.Brown@Sun.COM 	oemcpg->oempage.value =
355*10966SJordan.Brown@Sun.COM 	    MEM_ZALLOC("oem", max_oem_index * sizeof (smb_wchar_t));
356*10966SJordan.Brown@Sun.COM 	if (oemcpg->oempage.value == NULL)
357*10966SJordan.Brown@Sun.COM 		return;
3585331Samw 
359*10966SJordan.Brown@Sun.COM 	oemcpg->ucspage.value =
360*10966SJordan.Brown@Sun.COM 	    MEM_ZALLOC("oem", MAX_UNICODE_IDX * sizeof (smb_wchar_t));
361*10966SJordan.Brown@Sun.COM 	if (oemcpg->ucspage.value == NULL) {
362*10966SJordan.Brown@Sun.COM 		MEM_FREE("oem", oemcpg->oempage.value);
363*10966SJordan.Brown@Sun.COM 		oemcpg->oempage.value = NULL;
364*10966SJordan.Brown@Sun.COM 		return;
365*10966SJordan.Brown@Sun.COM 	}
366*10966SJordan.Brown@Sun.COM 
367*10966SJordan.Brown@Sun.COM 	for (i = 0; i < max_oem_index; i++) {
368*10966SJordan.Brown@Sun.COM 		oemcpg->oempage.value[i] = default_oem_cp[i];
369*10966SJordan.Brown@Sun.COM 		oemcpg->ucspage.value[default_oem_cp[i]] = (smb_wchar_t)i;
370*10966SJordan.Brown@Sun.COM 	}
371*10966SJordan.Brown@Sun.COM 
372*10966SJordan.Brown@Sun.COM 	oemcpg->valid = B_TRUE;
3735331Samw }
374