xref: /illumos-gate/usr/src/common/smbsrv/smb_oem.c (revision bbf6f00c)
1da6c28aaSamw /*
2da6c28aaSamw  * CDDL HEADER START
3da6c28aaSamw  *
4da6c28aaSamw  * The contents of this file are subject to the terms of the
5da6c28aaSamw  * Common Development and Distribution License (the "License").
6da6c28aaSamw  * You may not use this file except in compliance with the License.
7da6c28aaSamw  *
8da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw  * See the License for the specific language governing permissions
11da6c28aaSamw  * and limitations under the License.
12da6c28aaSamw  *
13da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw  *
19da6c28aaSamw  * CDDL HEADER END
20da6c28aaSamw  */
21da6c28aaSamw /*
22*bbf6f00cSJordan Brown  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23da6c28aaSamw  * Use is subject to license terms.
24da6c28aaSamw  */
25da6c28aaSamw 
26da6c28aaSamw /*
27da6c28aaSamw  * Support for oem <-> unicode translations.
28da6c28aaSamw  */
29da6c28aaSamw 
30da6c28aaSamw #ifndef _KERNEL
31da6c28aaSamw #include <stdlib.h>
32da6c28aaSamw #include <thread.h>
33da6c28aaSamw #include <synch.h>
34da6c28aaSamw #include <string.h>
35*bbf6f00cSJordan Brown #else
36*bbf6f00cSJordan Brown #include <sys/ksynch.h>
37da6c28aaSamw #endif /* _KERNEL */
38*bbf6f00cSJordan Brown 
39*bbf6f00cSJordan Brown #include <sys/byteorder.h>
40da6c28aaSamw #include <smbsrv/alloc.h>
41da6c28aaSamw #include <smbsrv/string.h>
42*bbf6f00cSJordan Brown 
43da6c28aaSamw /*
44*bbf6f00cSJordan Brown  * cpid		The oemcpg_table index for this oempage.
45*bbf6f00cSJordan Brown  * value	The conversion values.
46*bbf6f00cSJordan Brown  */
47*bbf6f00cSJordan Brown typedef struct oempage {
48*bbf6f00cSJordan Brown 	uint32_t	cpid;
49*bbf6f00cSJordan Brown 	smb_wchar_t	*value;
50*bbf6f00cSJordan Brown } oempage_t;
51*bbf6f00cSJordan Brown 
52*bbf6f00cSJordan Brown /*
53*bbf6f00cSJordan Brown  * filename	The actual filename contains the codepage.
54*bbf6f00cSJordan Brown  * bytesperchar	The codepage uses double or single bytes per char.
55*bbf6f00cSJordan Brown  * oempage	The oempage is used to convert Unicode characters to
56*bbf6f00cSJordan Brown  *		OEM characters.  Memory needs to be allocated for
57*bbf6f00cSJordan Brown  *		the value field of oempage to store the table.
58*bbf6f00cSJordan Brown  * ucspage	The unicode page is used to convert OEM characters
59*bbf6f00cSJordan Brown  *		to Unicode characters.  Memory needs to be allocated
60*bbf6f00cSJordan Brown  *		for the value field of ucspage to store the table.
61*bbf6f00cSJordan Brown  * valid	True if the codepage has been initialized.
62da6c28aaSamw  */
63da6c28aaSamw typedef struct oem_codepage {
64*bbf6f00cSJordan Brown 	char		*filename;
65*bbf6f00cSJordan Brown 	uint32_t	bytesperchar;
66*bbf6f00cSJordan Brown 	oempage_t	oempage;
67*bbf6f00cSJordan Brown 	oempage_t	ucspage;
68*bbf6f00cSJordan Brown 	boolean_t	valid;
69da6c28aaSamw } oem_codepage_t;
70da6c28aaSamw 
71*bbf6f00cSJordan Brown static oem_codepage_t oemcpg_table[] = {
72*bbf6f00cSJordan Brown 	{"850.cpg",  1, {0, 0},  {0, 0},  0},	/* Multilingual Latin1 */
73*bbf6f00cSJordan Brown 	{"950.cpg",  2, {1, 0},  {1, 0},  0},	/* Chinese Traditional */
74*bbf6f00cSJordan Brown 	{"1252.cpg", 1, {2, 0},  {2, 0},  0},	/* MS Latin1 */
75*bbf6f00cSJordan Brown 	{"949.cpg",  2, {3, 0},  {3, 0},  0},	/* Korean */
76*bbf6f00cSJordan Brown 	{"936.cpg",  2, {4, 0},  {4, 0},  0},	/* Chinese Simplified */
77*bbf6f00cSJordan Brown 	{"932.cpg",  2, {5, 0},  {5, 0},  0},	/* Japanese */
78*bbf6f00cSJordan Brown 	{"852.cpg",  1, {6, 0},  {6, 0},  0},	/* Multilingual Latin2 */
79*bbf6f00cSJordan Brown 	{"1250.cpg", 1, {7, 0},  {7, 0},  0},	/* MS Latin2 */
80*bbf6f00cSJordan Brown 	{"1253.cpg", 1, {8, 0},  {8, 0},  0},	/* MS Greek */
81*bbf6f00cSJordan Brown 	{"737.cpg",  1, {9, 0},  {9, 0},  0},	/* Greek */
82*bbf6f00cSJordan Brown 	{"1254.cpg", 1, {10, 0}, {10, 0}, 0},	/* MS Turkish */
83*bbf6f00cSJordan Brown 	{"857.cpg",  1, {11, 0}, {11, 0}, 0},	/* Multilingual Latin5 */
84*bbf6f00cSJordan Brown 	{"1251.cpg", 1, {12, 0}, {12, 0}, 0},	/* MS Cyrillic */
85*bbf6f00cSJordan Brown 	{"866.cpg",  1, {13, 0}, {13, 0}, 0},	/* Cyrillic II */
86*bbf6f00cSJordan Brown 	{"1255.cpg", 1, {14, 0}, {14, 0}, 0},	/* MS Hebrew */
87*bbf6f00cSJordan Brown 	{"862.cpg",  1, {15, 0}, {15, 0}, 0},	/* Hebrew */
88*bbf6f00cSJordan Brown 	{"1256.cpg", 1, {16, 0}, {16, 0}, 0},	/* MS Arabic */
89*bbf6f00cSJordan Brown 	{"720.cpg",  1, {17, 0}, {17, 0}, 0}	/* Arabic */
90da6c28aaSamw };
91da6c28aaSamw 
92*bbf6f00cSJordan Brown #define	MAX_OEMPAGES	(sizeof (oemcpg_table) / sizeof (oemcpg_table[0]))
93*bbf6f00cSJordan Brown #define	MAX_UNICODE_IDX	65536
94da6c28aaSamw 
95da6c28aaSamw /*
96*bbf6f00cSJordan Brown  * The default SMB OEM codepage for English is codepage 850.
97da6c28aaSamw  */
98*bbf6f00cSJordan Brown smb_wchar_t oem_codepage_850[256] = {
99da6c28aaSamw 	0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
100da6c28aaSamw 	0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
101da6c28aaSamw 	0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
102da6c28aaSamw 	0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
103da6c28aaSamw 	0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
104da6c28aaSamw 	0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
105da6c28aaSamw 	0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
106da6c28aaSamw 	0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
107da6c28aaSamw 	0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
108da6c28aaSamw 	0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
109da6c28aaSamw 	0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
110da6c28aaSamw 	0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
111da6c28aaSamw 	0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
112da6c28aaSamw 	0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
113da6c28aaSamw 	0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
114da6c28aaSamw 	0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
115da6c28aaSamw 	0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
116da6c28aaSamw 	0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
117da6c28aaSamw 	0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
118da6c28aaSamw 	0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
119da6c28aaSamw 	0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
120da6c28aaSamw 	0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
121da6c28aaSamw 	0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0,
122da6c28aaSamw 	0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
123da6c28aaSamw 	0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3,
124da6c28aaSamw 	0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
125da6c28aaSamw 	0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE,
126da6c28aaSamw 	0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
127da6c28aaSamw 	0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE,
128da6c28aaSamw 	0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4,
129da6c28aaSamw 	0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8,
130da6c28aaSamw 	0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
131da6c28aaSamw };
132da6c28aaSamw 
133da6c28aaSamw /*
134*bbf6f00cSJordan Brown  * The default telnet OEM codepage for English is codepage 1252.
135da6c28aaSamw  */
136*bbf6f00cSJordan Brown smb_wchar_t oem_codepage_1252[256] = {
137da6c28aaSamw 	0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
138da6c28aaSamw 	0x9, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x10,
139da6c28aaSamw 	0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
140da6c28aaSamw 	0x19, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x20,
141da6c28aaSamw 	0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
142da6c28aaSamw 	0x29, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x30,
143da6c28aaSamw 	0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
144da6c28aaSamw 	0x39, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x40,
145da6c28aaSamw 	0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
146da6c28aaSamw 	0x49, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x50,
147da6c28aaSamw 	0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
148da6c28aaSamw 	0x59, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x60,
149da6c28aaSamw 	0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
150da6c28aaSamw 	0x69, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x70,
151da6c28aaSamw 	0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
152da6c28aaSamw 	0x79, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x20AC,
153da6c28aaSamw 	0x81, 0x201A, 0x192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6,
154da6c28aaSamw 	0x2030, 0x160, 0x2039, 0x152, 0x8D, 0x017D, 0x8F, 0x90,
155da6c28aaSamw 	0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC,
156da6c28aaSamw 	0x2122, 0x161, 0x203A, 0x153, 0x9D, 0x017E, 0x178, 0x00A0,
157da6c28aaSamw 	0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8,
158da6c28aaSamw 	0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0,
159da6c28aaSamw 	0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8,
160da6c28aaSamw 	0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0,
161da6c28aaSamw 	0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8,
162da6c28aaSamw 	0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0,
163da6c28aaSamw 	0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8,
164da6c28aaSamw 	0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0,
165da6c28aaSamw 	0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8,
166da6c28aaSamw 	0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0,
167da6c28aaSamw 	0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8,
168da6c28aaSamw 	0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF
169da6c28aaSamw };
170da6c28aaSamw 
171*bbf6f00cSJordan Brown static oempage_t *oem_get_oempage(uint32_t);
172*bbf6f00cSJordan Brown static oempage_t *oem_get_ucspage(uint32_t);
173*bbf6f00cSJordan Brown static void oem_codepage_init(uint32_t);
174*bbf6f00cSJordan Brown static void oem_codepage_setup(uint32_t);
175da6c28aaSamw 
176da6c28aaSamw /*
177*bbf6f00cSJordan Brown  * Convert a unicode string to an oem string.
178da6c28aaSamw  *
179*bbf6f00cSJordan Brown  * The conversion will stop at the end of the unicode string
180*bbf6f00cSJordan Brown  * or when (nbytes - 1) oem characters have been stored.
181da6c28aaSamw  *
182*bbf6f00cSJordan Brown  * The number of converted unicode characters is returned,
183*bbf6f00cSJordan Brown  * or 0 on error.
184da6c28aaSamw  */
185da6c28aaSamw size_t
186*bbf6f00cSJordan Brown ucstooem(char *oem, const smb_wchar_t *ucs, size_t nbytes, uint32_t cpid)
187da6c28aaSamw {
188*bbf6f00cSJordan Brown 	oempage_t	*ucspage;
189*bbf6f00cSJordan Brown 	uint32_t	count = 0;
190*bbf6f00cSJordan Brown 	smb_wchar_t	oemchar;
191da6c28aaSamw 
192*bbf6f00cSJordan Brown 	if (ucs == NULL || oem == NULL)
193da6c28aaSamw 		return (0);
194da6c28aaSamw 
195*bbf6f00cSJordan Brown 	if ((ucspage = oem_get_ucspage(cpid)) == NULL)
196da6c28aaSamw 		return (0);
197da6c28aaSamw 
198*bbf6f00cSJordan Brown 	while (nbytes != 0 && (oemchar = ucspage->value[*ucs]) != 0) {
199da6c28aaSamw 		if (oemchar & 0xff00 && nbytes >= MTS_MB_CHAR_MAX) {
200*bbf6f00cSJordan Brown 			*oem++ = oemchar >> 8;
201*bbf6f00cSJordan Brown 			*oem++ = (char)oemchar;
202da6c28aaSamw 			nbytes -= 2;
203da6c28aaSamw 		} else if (nbytes > 1) {
204*bbf6f00cSJordan Brown 			*oem++ = (char)oemchar;
205da6c28aaSamw 			nbytes--;
206*bbf6f00cSJordan Brown 		} else {
207da6c28aaSamw 			break;
208*bbf6f00cSJordan Brown 		}
209da6c28aaSamw 
210da6c28aaSamw 		count++;
211*bbf6f00cSJordan Brown 		ucs++;
212da6c28aaSamw 	}
213da6c28aaSamw 
214*bbf6f00cSJordan Brown 	*oem = '\0';
215da6c28aaSamw 	return (count);
216da6c28aaSamw }
217da6c28aaSamw 
218da6c28aaSamw /*
219*bbf6f00cSJordan Brown  * Convert an oem string to a unicode string.
220da6c28aaSamw  *
221*bbf6f00cSJordan Brown  * The conversion will stop at the end of the oem string or
222*bbf6f00cSJordan Brown  * when nwchars - 1 have been converted.
223*bbf6f00cSJordan Brown  *
224*bbf6f00cSJordan Brown  * The number of converted oem chars is returned, or 0 on error.
225*bbf6f00cSJordan Brown  * An oem char may be either 1 or 2 bytes.
226da6c28aaSamw  */
227da6c28aaSamw size_t
228*bbf6f00cSJordan Brown oemtoucs(smb_wchar_t *ucs, const char *oem, size_t nwchars, uint32_t cpid)
229da6c28aaSamw {
230*bbf6f00cSJordan Brown 	oempage_t	*oempage;
231*bbf6f00cSJordan Brown 	size_t		count = nwchars;
232*bbf6f00cSJordan Brown 	smb_wchar_t	oemchar;
233da6c28aaSamw 
234*bbf6f00cSJordan Brown 	if (ucs == NULL || oem == NULL)
235da6c28aaSamw 		return (0);
236da6c28aaSamw 
237*bbf6f00cSJordan Brown 	if ((oempage = oem_get_oempage(cpid)) == NULL)
238da6c28aaSamw 		return (0);
239da6c28aaSamw 
240*bbf6f00cSJordan Brown 	while ((oemchar = (smb_wchar_t)*oem++ & 0xff) != 0) {
241da6c28aaSamw 		/*
242*bbf6f00cSJordan Brown 		 * Cannot find one byte oemchar in table.
243*bbf6f00cSJordan Brown 		 * Must be a lead byte. Try two bytes.
244da6c28aaSamw 		 */
245da6c28aaSamw 		if ((oempage->value[oemchar] == 0) && (oemchar != 0)) {
246*bbf6f00cSJordan Brown 			oemchar = oemchar << 8 | (*oem++ & 0xff);
247da6c28aaSamw 			if (oempage->value[oemchar] == 0) {
248*bbf6f00cSJordan Brown 				*ucs = 0;
249da6c28aaSamw 				break;
250da6c28aaSamw 			}
251da6c28aaSamw 		}
252da6c28aaSamw #ifdef _BIG_ENDIAN
253*bbf6f00cSJordan Brown 		*ucs = LE_IN16(&oempage->value[oemchar]);
254da6c28aaSamw #else
255*bbf6f00cSJordan Brown 		*ucs = oempage->value[oemchar];
256da6c28aaSamw #endif
257da6c28aaSamw 		count--;
258*bbf6f00cSJordan Brown 		ucs++;
259da6c28aaSamw 	}
260da6c28aaSamw 
261*bbf6f00cSJordan Brown 	*ucs = 0;
262da6c28aaSamw 	return (nwchars - count);
263da6c28aaSamw }
264da6c28aaSamw 
265da6c28aaSamw /*
266*bbf6f00cSJordan Brown  * Get a pointer to the oem page for the specific codepage id.
267da6c28aaSamw  */
268*bbf6f00cSJordan Brown static oempage_t *
269*bbf6f00cSJordan Brown oem_get_oempage(uint32_t cpid)
270da6c28aaSamw {
271*bbf6f00cSJordan Brown 	if (cpid >= MAX_OEMPAGES)
272*bbf6f00cSJordan Brown 		return (NULL);
273*bbf6f00cSJordan Brown 
274*bbf6f00cSJordan Brown 	if (!oemcpg_table[cpid].valid) {
275*bbf6f00cSJordan Brown 		oem_codepage_init(cpid);
276*bbf6f00cSJordan Brown 
277*bbf6f00cSJordan Brown 		if (!oemcpg_table[cpid].valid)
278*bbf6f00cSJordan Brown 			return (NULL);
279*bbf6f00cSJordan Brown 	}
280*bbf6f00cSJordan Brown 
281*bbf6f00cSJordan Brown 	return (&oemcpg_table[cpid].oempage);
282da6c28aaSamw }
283da6c28aaSamw 
284da6c28aaSamw /*
285*bbf6f00cSJordan Brown  * Get a pointer to the ucs page for the specific codepage id.
286da6c28aaSamw  */
287*bbf6f00cSJordan Brown static oempage_t *
288*bbf6f00cSJordan Brown oem_get_ucspage(uint32_t cpid)
289da6c28aaSamw {
290*bbf6f00cSJordan Brown 	if (cpid >= MAX_OEMPAGES)
291*bbf6f00cSJordan Brown 		return (NULL);
292da6c28aaSamw 
293*bbf6f00cSJordan Brown 	if (!oemcpg_table[cpid].valid) {
294*bbf6f00cSJordan Brown 		oem_codepage_init(cpid);
295*bbf6f00cSJordan Brown 
296*bbf6f00cSJordan Brown 		if (!oemcpg_table[cpid].valid)
297*bbf6f00cSJordan Brown 			return (NULL);
298*bbf6f00cSJordan Brown 	}
299*bbf6f00cSJordan Brown 
300*bbf6f00cSJordan Brown 	return (&oemcpg_table[cpid].ucspage);
301*bbf6f00cSJordan Brown }
302da6c28aaSamw 
303da6c28aaSamw /*
304*bbf6f00cSJordan Brown  * Initialize the oem page in the oem table.
305da6c28aaSamw  */
306*bbf6f00cSJordan Brown static void
307*bbf6f00cSJordan Brown oem_codepage_init(uint32_t cpid)
308da6c28aaSamw {
309*bbf6f00cSJordan Brown #ifndef _KERNEL
310*bbf6f00cSJordan Brown 	static mutex_t mutex;
311da6c28aaSamw 
312*bbf6f00cSJordan Brown 	(void) mutex_lock(&mutex);
313*bbf6f00cSJordan Brown 	oem_codepage_setup(cpid);
314*bbf6f00cSJordan Brown 	(void) mutex_unlock(&mutex);
315*bbf6f00cSJordan Brown #else
316*bbf6f00cSJordan Brown 	static kmutex_t mutex;
317da6c28aaSamw 
318*bbf6f00cSJordan Brown 	mutex_enter(&mutex);
319*bbf6f00cSJordan Brown 	oem_codepage_setup(cpid);
320*bbf6f00cSJordan Brown 	mutex_exit(&mutex);
321*bbf6f00cSJordan Brown #endif /* _KERNEL */
322*bbf6f00cSJordan Brown }
323da6c28aaSamw 
324*bbf6f00cSJordan Brown static void
325*bbf6f00cSJordan Brown oem_codepage_setup(uint32_t cpid)
326*bbf6f00cSJordan Brown {
327*bbf6f00cSJordan Brown 	smb_wchar_t	*default_oem_cp;
328*bbf6f00cSJordan Brown 	oem_codepage_t	*oemcpg;
329*bbf6f00cSJordan Brown 	uint32_t	bytesperchar;
330*bbf6f00cSJordan Brown 	uint32_t	max_oem_index;
331*bbf6f00cSJordan Brown 	int		i;
332*bbf6f00cSJordan Brown 
333*bbf6f00cSJordan Brown 	switch (cpid) {
334*bbf6f00cSJordan Brown 	case OEM_CPG_850:
335*bbf6f00cSJordan Brown 		default_oem_cp = oem_codepage_850;
336*bbf6f00cSJordan Brown 		break;
337*bbf6f00cSJordan Brown 	case OEM_CPG_1252:
338*bbf6f00cSJordan Brown 		default_oem_cp = oem_codepage_1252;
339*bbf6f00cSJordan Brown 	default:
340da6c28aaSamw 		return;
341da6c28aaSamw 	}
342da6c28aaSamw 
343*bbf6f00cSJordan Brown 	oemcpg = &oemcpg_table[cpid];
344*bbf6f00cSJordan Brown 	if (oemcpg->valid)
345da6c28aaSamw 		return;
346da6c28aaSamw 
347da6c28aaSamw 	/*
348*bbf6f00cSJordan Brown 	 * max_oem_index will be 256 or 65536 dependent
349*bbf6f00cSJordan Brown 	 * on the OEM codepage.
350da6c28aaSamw 	 */
351*bbf6f00cSJordan Brown 	bytesperchar = oemcpg_table[cpid].bytesperchar;
352*bbf6f00cSJordan Brown 	max_oem_index = 1 << (bytesperchar * 8);
353da6c28aaSamw 
354*bbf6f00cSJordan Brown 	oemcpg->oempage.value =
355*bbf6f00cSJordan Brown 	    MEM_ZALLOC("oem", max_oem_index * sizeof (smb_wchar_t));
356*bbf6f00cSJordan Brown 	if (oemcpg->oempage.value == NULL)
357*bbf6f00cSJordan Brown 		return;
358da6c28aaSamw 
359*bbf6f00cSJordan Brown 	oemcpg->ucspage.value =
360*bbf6f00cSJordan Brown 	    MEM_ZALLOC("oem", MAX_UNICODE_IDX * sizeof (smb_wchar_t));
361*bbf6f00cSJordan Brown 	if (oemcpg->ucspage.value == NULL) {
362*bbf6f00cSJordan Brown 		MEM_FREE("oem", oemcpg->oempage.value);
363*bbf6f00cSJordan Brown 		oemcpg->oempage.value = NULL;
364*bbf6f00cSJordan Brown 		return;
365*bbf6f00cSJordan Brown 	}
366da6c28aaSamw 
367*bbf6f00cSJordan Brown 	for (i = 0; i < max_oem_index; i++) {
368*bbf6f00cSJordan Brown 		oemcpg->oempage.value[i] = default_oem_cp[i];
369*bbf6f00cSJordan Brown 		oemcpg->ucspage.value[default_oem_cp[i]] = (smb_wchar_t)i;
370*bbf6f00cSJordan Brown 	}
371da6c28aaSamw 
372*bbf6f00cSJordan Brown 	oemcpg->valid = B_TRUE;
373da6c28aaSamw }
374