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