Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

925 lines
22 KiB

  1. /*
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. macansi.c
  5. Abstract:
  6. This module contains conversion routines from macintosh ansi to unicode
  7. and vice versa
  8. Author:
  9. Jameel Hyder (microsoft!jameelh)
  10. Revision History:
  11. 10 Jul 1992 Initial Version
  12. Notes: Tab stop: 4
  13. --*/
  14. #define _MACANSI_LOCALS
  15. #define FILENUM FILE_MACANSI
  16. #include <afp.h>
  17. #define FlagOn(x, y) ((x) & (y))
  18. #ifdef ALLOC_PRAGMA
  19. #pragma alloc_text( INIT, AfpMacAnsiInit)
  20. #pragma alloc_text( PAGE, AfpMacAnsiDeInit)
  21. #pragma alloc_text( PAGE, AfpGetMacCodePage)
  22. #pragma alloc_text( PAGE, AfpConvertStringToUnicode)
  23. #pragma alloc_text( PAGE, AfpConvertStringToAnsi)
  24. #pragma alloc_text( PAGE, AfpConvertStringToMungedUnicode)
  25. #pragma alloc_text( PAGE, AfpConvertMungedUnicodeToAnsi)
  26. #pragma alloc_text( PAGE, AfpConvertMacAnsiToHostAnsi)
  27. #pragma alloc_text( PAGE, AfpConvertHostAnsiToMacAnsi)
  28. #pragma alloc_text( PAGE, AfpIsLegalShortname)
  29. #pragma alloc_text( PAGE, AfpIsProperSubstring)
  30. #endif
  31. /*** AfpMacAnsiInit
  32. *
  33. * Initialize the code page for macintosh ANSI.
  34. */
  35. NTSTATUS
  36. AfpMacAnsiInit(
  37. VOID
  38. )
  39. {
  40. NTSTATUS Status = STATUS_SUCCESS;
  41. int i, SizeAltTbl;
  42. // Allocate the table for the alternate unicode characters
  43. SizeAltTbl = (AFP_INVALID_HIGH - AFP_INITIAL_INVALID_HIGH + 1) * sizeof(WCHAR);
  44. if ((afpAltUnicodeTable = (PWCHAR)AfpAllocZeroedPagedMemory(SizeAltTbl)) == NULL)
  45. return STATUS_INSUFFICIENT_RESOURCES;
  46. // Allocate and initialize the table for the reverse mapping table
  47. SizeAltTbl = (AFP_INVALID_HIGH - AFP_INITIAL_INVALID_HIGH + 1)*sizeof(BYTE);
  48. if ((afpAltAnsiTable = (PBYTE)AfpAllocZeroedPagedMemory(SizeAltTbl)) == NULL)
  49. {
  50. AfpFreeMemory(afpAltUnicodeTable);
  51. afpAltUnicodeTable = NULL;
  52. return STATUS_INSUFFICIENT_RESOURCES;
  53. }
  54. // Initialize the tables for the alternate unicode characters
  55. for (i = AFP_INITIAL_INVALID_HIGH + 1; i <= AFP_INVALID_HIGH; i++)
  56. {
  57. if (!FsRtlIsAnsiCharacterLegalNtfs((BYTE)i, False))
  58. {
  59. afpAltUnicodeTable[i-AFP_INITIAL_INVALID_HIGH] = afpLastAltChar;
  60. afpAltAnsiTable[afpLastAltChar - (AFP_ALT_UNICODE_BASE + AFP_INITIAL_INVALID_HIGH)] = (BYTE)i;
  61. afpLastAltChar++;
  62. }
  63. }
  64. // HACK: Also add in a couple of codes for 'space' and 'period' - they are only
  65. // used if they are at end. Another one for the 'apple' character
  66. AfpMungedUnicodeSpace =
  67. afpAltUnicodeTable[ANSI_SPACE-AFP_INITIAL_INVALID_HIGH] = afpLastAltChar;
  68. afpAltAnsiTable[afpLastAltChar - (AFP_ALT_UNICODE_BASE + AFP_INITIAL_INVALID_HIGH)] = ANSI_SPACE;
  69. afpLastAltChar ++;
  70. AfpMungedUnicodePeriod =
  71. afpAltUnicodeTable[ANSI_PERIOD-AFP_INITIAL_INVALID_HIGH] = afpLastAltChar;
  72. afpAltAnsiTable[afpLastAltChar - (AFP_ALT_UNICODE_BASE + AFP_INITIAL_INVALID_HIGH)] = ANSI_PERIOD;
  73. afpLastAltChar ++;
  74. // This is yet another hack
  75. afpAppleUnicodeChar = afpLastAltChar;
  76. afpLastAltChar ++;
  77. RtlZeroMemory(&AfpMacCPTableInfo, sizeof(AfpMacCPTableInfo));
  78. return Status;
  79. }
  80. /*** AfpMacAnsiDeInit
  81. *
  82. * De-initialize the code page for macintosh ANSI.
  83. */
  84. VOID
  85. AfpMacAnsiDeInit(
  86. VOID
  87. )
  88. {
  89. PAGED_CODE( );
  90. if (AfpTranslationTable != NULL)
  91. {
  92. AfpFreeMemory(AfpTranslationTable);
  93. }
  94. if (AfpCasePreserveTranslationTable != NULL)
  95. {
  96. AfpFreeMemory(AfpCasePreserveTranslationTable);
  97. }
  98. if (AfpRevTranslationTable != NULL)
  99. {
  100. AfpFreeMemory(AfpRevTranslationTable);
  101. }
  102. if (afpAltUnicodeTable != NULL)
  103. {
  104. AfpFreeMemory(afpAltUnicodeTable);
  105. }
  106. if (afpAltAnsiTable != NULL)
  107. {
  108. AfpFreeMemory(afpAltAnsiTable);
  109. }
  110. if (AfpMacCPBaseAddress != NULL)
  111. {
  112. AfpFreeMemory(AfpMacCPBaseAddress);
  113. }
  114. }
  115. /*** AfpConvertStringToUnicode
  116. *
  117. * Convert a Mac ANSI string to a unicode string.
  118. */
  119. AFPSTATUS FASTCALL
  120. AfpConvertStringToUnicode(
  121. IN PANSI_STRING pAnsiString,
  122. OUT PUNICODE_STRING pUnicodeString
  123. )
  124. {
  125. NTSTATUS Status;
  126. ULONG ulCast;
  127. PAGED_CODE( );
  128. ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
  129. Status = RtlCustomCPToUnicodeN(&AfpMacCPTableInfo,
  130. pUnicodeString->Buffer,
  131. pUnicodeString->MaximumLength,
  132. &ulCast, pAnsiString->Buffer,
  133. pAnsiString->Length);
  134. if (NT_SUCCESS(Status))
  135. pUnicodeString->Length = (USHORT)ulCast;
  136. else
  137. {
  138. AFPLOG_ERROR(AFPSRVMSG_MACANSI2UNICODE, Status, NULL, 0, NULL);
  139. }
  140. return Status;
  141. }
  142. /*** AfpConvertStringToAnsi
  143. *
  144. * Convert a unicode string to a Mac ANSI string.
  145. */
  146. AFPSTATUS FASTCALL
  147. AfpConvertStringToAnsi(
  148. IN PUNICODE_STRING pUnicodeString,
  149. OUT PANSI_STRING pAnsiString
  150. )
  151. {
  152. NTSTATUS Status;
  153. ULONG ulCast;
  154. PAGED_CODE( );
  155. ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
  156. Status = RtlUnicodeToCustomCPN(&AfpMacCPTableInfo,
  157. pAnsiString->Buffer,
  158. pAnsiString->MaximumLength,
  159. &ulCast, pUnicodeString->Buffer,
  160. pUnicodeString->Length);
  161. if (NT_SUCCESS(Status))
  162. pAnsiString->Length = (USHORT)ulCast;
  163. else
  164. {
  165. AFPLOG_ERROR(AFPSRVMSG_UNICODE2MACANSI, Status, NULL, 0, NULL);
  166. }
  167. return Status;
  168. }
  169. /*** AfpConvertStringToMungedUnicode
  170. *
  171. * Convert a Mac ANSI string to a unicode string. If there are any characters
  172. * in the ansi string which are invalid filesystem (NTFS) characters, then
  173. * map them to alternate unicode characters based on the table.
  174. */
  175. AFPSTATUS FASTCALL
  176. AfpConvertStringToMungedUnicode(
  177. IN PANSI_STRING pAnsiString,
  178. OUT PUNICODE_STRING pUnicodeString
  179. )
  180. {
  181. USHORT i, len;
  182. BYTE c;
  183. NTSTATUS Status;
  184. ULONG ulCast;
  185. PWCHAR pWBuf;
  186. PAGED_CODE( );
  187. ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
  188. ASSERT(afpAltUnicodeTable != NULL);
  189. Status = RtlCustomCPToUnicodeN(&AfpMacCPTableInfo,
  190. pUnicodeString->Buffer,
  191. pUnicodeString->MaximumLength,
  192. &ulCast,
  193. pAnsiString->Buffer,
  194. pAnsiString->Length);
  195. if (NT_SUCCESS(Status))
  196. pUnicodeString->Length = (USHORT)ulCast;
  197. else
  198. {
  199. AFPLOG_ERROR(AFPSRVMSG_MACANSI2UNICODE, Status, NULL, 0, NULL);
  200. return Status;
  201. }
  202. // Walk the ANSI string looking for the invalid characters and map it
  203. // to the alternate set
  204. for (i = 0, len = pAnsiString->Length, pWBuf = pUnicodeString->Buffer;
  205. i < len;
  206. i++, pWBuf ++)
  207. {
  208. c = pAnsiString->Buffer[i];
  209. if (c == ANSI_APPLE_CHAR)
  210. *pWBuf = afpAppleUnicodeChar;
  211. else if (c < AFP_INITIAL_INVALID_HIGH)
  212. *pWBuf = c + AFP_ALT_UNICODE_BASE;
  213. else if (!FsRtlIsAnsiCharacterLegalNtfs(c, False))
  214. {
  215. ASSERT (c <= AFP_INVALID_HIGH);
  216. *pWBuf = afpAltUnicodeTable[c - AFP_INITIAL_INVALID_HIGH];
  217. }
  218. /* MSKK eichim, Appended to handle DBCS trailing 0x5c, 03/16/95 */
  219. #ifdef DBCS
  220. if (FsRtlIsLeadDbcsCharacter(c))
  221. i++;
  222. #endif // DBCS
  223. }
  224. // HACK: Make sure the last character in the name is not a 'space' or a '.'
  225. c = pAnsiString->Buffer[pAnsiString->Length - 1];
  226. if ((c == ANSI_SPACE) || (c == ANSI_PERIOD))
  227. /* MSKK hideyukn, Unicode char length not eqaul to ansi byte length in DBCS, 06/30/95 */
  228. #ifdef DBCS
  229. pUnicodeString->Buffer[(pUnicodeString->Length/sizeof(WCHAR)) - 1]
  230. = afpAltUnicodeTable[c - AFP_INITIAL_INVALID_HIGH];
  231. #else
  232. pUnicodeString->Buffer[len - 1] = afpAltUnicodeTable[c - AFP_INITIAL_INVALID_HIGH];
  233. #endif // DBCS
  234. return STATUS_SUCCESS;
  235. }
  236. /*** AfpConvertMungedUnicodeToAnsi
  237. *
  238. * Convert a unicode string with possible alternate unicode characters
  239. * to Mac Ansi.
  240. * This is inverse of AfpConvertStringToMungedUnicode().
  241. */
  242. NTSTATUS FASTCALL
  243. AfpConvertMungedUnicodeToAnsi(
  244. IN PUNICODE_STRING pUnicodeString,
  245. OUT PANSI_STRING pAnsiString
  246. )
  247. {
  248. USHORT i, len;
  249. WCHAR wc;
  250. NTSTATUS Status;
  251. ULONG ulCast;
  252. PBYTE pABuf;
  253. PAGED_CODE( );
  254. ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
  255. Status = RtlUnicodeToCustomCPN(&AfpMacCPTableInfo,
  256. pAnsiString->Buffer,
  257. pAnsiString->MaximumLength,
  258. &ulCast, pUnicodeString->Buffer,
  259. pUnicodeString->Length);
  260. if (NT_SUCCESS(Status))
  261. pAnsiString->Length = (USHORT)ulCast;
  262. else
  263. {
  264. AFPLOG_ERROR(AFPSRVMSG_UNICODE2MACANSI, Status, NULL, 0, NULL);
  265. }
  266. // Walk the Unicode string looking for alternate unicode chars and
  267. // replacing the ansi equivalents by the real ansi characters.
  268. for (i = 0, len = pUnicodeString->Length/(USHORT)sizeof(WCHAR), pABuf = pAnsiString->Buffer;
  269. i < len;
  270. i++, pABuf++)
  271. {
  272. wc = pUnicodeString->Buffer[i];
  273. if (wc == afpAppleUnicodeChar)
  274. *pABuf = ANSI_APPLE_CHAR;
  275. else if ((wc >= AFP_ALT_UNICODE_BASE) && (wc < afpLastAltChar))
  276. {
  277. wc -= AFP_ALT_UNICODE_BASE;
  278. if (wc < AFP_INITIAL_INVALID_HIGH)
  279. *pABuf = (BYTE)wc;
  280. else *pABuf = afpAltAnsiTable[wc - AFP_INITIAL_INVALID_HIGH];
  281. }
  282. /* MSKK hideyukn, Unicode char length not eqaul to ansi byte length in DBCS, 06/30/95 */
  283. #ifdef DBCS
  284. if (FsRtlIsLeadDbcsCharacter(*pABuf))
  285. pABuf++;
  286. #endif // DBCS
  287. }
  288. return Status;
  289. }
  290. /*** AfpConvertMacAnsiToHostAnsi
  291. *
  292. * Convert a Mac ansi string to its host counterpart in uppercase OEM codepage.
  293. * (in place). The name of this routine is misleading as a late bugfix was
  294. * made to change the codepage used, but the name of the routine didn't change
  295. * so none of the calling code had to be changed. It should really be called
  296. * AfpConvertMacAnsiToUpcaseOem. This routine is only called to uppercase
  297. * mac passwords for logon and changepassword.
  298. *
  299. */
  300. AFPSTATUS FASTCALL
  301. AfpConvertMacAnsiToHostAnsi(
  302. IN OUT PANSI_STRING pAnsiString
  303. )
  304. {
  305. LONG i, Len;
  306. BYTE *pBuf;
  307. PAGED_CODE( );
  308. ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
  309. // ASSERT (AfpTranslationTable != NULL);
  310. ASSERT (AfpCasePreserveTranslationTable != NULL);
  311. Len = pAnsiString->Length;
  312. pBuf = pAnsiString->Buffer;
  313. for (i = 0; i < Len; i++, pBuf++)
  314. {
  315. /* MSKK NaotoN Appended to handle DBCS Mac path name 11/10/93 */
  316. #ifdef DBCS
  317. if (FsRtlIsLeadDbcsCharacter( *pBuf )) {
  318. i++ ;
  319. pBuf++ ;
  320. }
  321. else
  322. #endif // DBCS
  323. *pBuf = AfpCasePreserveTranslationTable[*pBuf];
  324. }
  325. return AFP_ERR_NONE;
  326. }
  327. /*** AfpConvertHostAnsiToMacAnsi
  328. *
  329. * Convert a host unicode string to its mac counterpart in place.
  330. * Only characters <= 0x20 and >= 0x80 are translated.
  331. *
  332. * NOTE: This is extremely hacky and intended for translating messages only.
  333. */
  334. VOID FASTCALL
  335. AfpConvertHostAnsiToMacAnsi(
  336. IN OUT PANSI_STRING pAnsiString
  337. )
  338. {
  339. LONG i, Len;
  340. BYTE c, *pBuf;
  341. PAGED_CODE( );
  342. ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
  343. ASSERT (AfpRevTranslationTable != NULL);
  344. Len = pAnsiString->Length;
  345. pBuf = pAnsiString->Buffer;
  346. for (i = 0; i < Len; i++, pBuf++)
  347. {
  348. c = *pBuf;
  349. /* MSKK NaotoN Appended to skip if Kanji 12/17/93 */
  350. #ifdef DBCS
  351. if (FsRtlIsLeadDbcsCharacter( c )) {
  352. i++ ;
  353. pBuf++ ;
  354. }
  355. else
  356. #endif // DBCS
  357. if (c < 0x20)
  358. {
  359. *pBuf = AfpRevTranslationTable[c];
  360. }
  361. else if (c >= 0x80)
  362. {
  363. *pBuf = AfpRevTranslationTable[c-(0x80-0x20)];
  364. }
  365. }
  366. }
  367. /*** AfpEqualUnicodeString
  368. *
  369. * The AfpEqualUnicodeString function compares two counted unicode
  370. * strings for equality using case SENSITIVE compare. This routine
  371. * exists because it must be called at DPC level by the volume.c code
  372. * for comparing 2 non-paged strings, and the RtlEqualUnicodeString
  373. * routine that we would normally call is pageable code.
  374. *
  375. * Note that case INSENSITIVE compare would require accessing
  376. * paged up-case table info, and therefore could not be done at DPC level.
  377. *
  378. * Arguments:
  379. * String1 - Pointer to the first string.
  380. * String2 - Pointer to the second string.
  381. *
  382. * Return Value:
  383. * True if String1 equals String2 and False otherwise.
  384. *
  385. * Note: This is called at DPC level from volume.c and must not be made
  386. * a pageable routine.
  387. */
  388. BOOLEAN FASTCALL
  389. AfpEqualUnicodeString(
  390. IN PUNICODE_STRING String1,
  391. IN PUNICODE_STRING String2
  392. )
  393. {
  394. WCHAR *s1, *s2;
  395. USHORT n1, n2;
  396. n1 = (USHORT)(String1->Length/sizeof(WCHAR));
  397. n2 = (USHORT)(String2->Length/sizeof(WCHAR));
  398. if (n1 != n2)
  399. {
  400. return False;
  401. }
  402. s1 = String1->Buffer;
  403. s2 = String2->Buffer;
  404. while (n1--)
  405. {
  406. if (*s1++ != *s2++)
  407. {
  408. return False;
  409. }
  410. }
  411. return True;
  412. }
  413. /*** AfpPrefixUnicodeString
  414. *
  415. * The AfpPrefixUnicodeString function determines if the String1
  416. * counted string parameter is a prefix of the String2 counted string
  417. * parameter using case SENSITIVE compare. This routine exists because it
  418. * must be called at DPC level by the volume.c code for comparing
  419. * two non-paged strings, and the RtlPrefixUnicodeString routine that we
  420. * would normally call is pageable code.
  421. *
  422. * Note that case INSENSITIVE compare would require accessing
  423. * paged up-case table info, and therefore could not be done at DPC level.
  424. *
  425. * Arguments:
  426. * String1 - Pointer to the first unicode string.
  427. * String2 - Pointer to the second unicode string.
  428. *
  429. * Return Value:
  430. * True if String1 equals a prefix of String2 and False otherwise.
  431. *
  432. * Note: This is called at DPC level from volume.c and must not be made
  433. * a pageable routine.
  434. */
  435. BOOLEAN FASTCALL
  436. AfpPrefixUnicodeString(
  437. IN PUNICODE_STRING String1,
  438. IN PUNICODE_STRING String2
  439. )
  440. {
  441. PWSTR s1, s2;
  442. ULONG n;
  443. WCHAR c1, c2;
  444. if (String2->Length < String1->Length)
  445. {
  446. return False;
  447. }
  448. s1 = String1->Buffer;
  449. s2 = String2->Buffer;
  450. n = String1->Length/sizeof(WCHAR);
  451. while (n--)
  452. {
  453. c1 = *s1++;
  454. c2 = *s2++;
  455. if (c1 != c2)
  456. {
  457. return False;
  458. }
  459. }
  460. return True;
  461. }
  462. /*** AfpGetMacCodePage
  463. *
  464. * Open the default macintosh codepage, create a section backed by that file,
  465. * map a view to the section, and initialize the CodePage info structure
  466. * that is used with the RtlCustomCP routines. Then create the Mac Ansi to
  467. * Host Ansi mapping table.
  468. *
  469. * BEWARE!
  470. * This routine may only be called ONCE! This will be called from the first
  471. * admin call to ServerSetInfo. Therefore, there can be NO calls to the
  472. * macansi routines within this module (except for MacAnsiInit) before that
  473. * happens.
  474. */
  475. NTSTATUS FASTCALL
  476. AfpGetMacCodePage(
  477. IN LPWSTR PathCP
  478. )
  479. {
  480. NTSTATUS Status;
  481. FILESYSHANDLE FileHandle;
  482. UNICODE_STRING uPathCP, devPathCP;
  483. ULONG viewsize = 0;
  484. WCHAR UnicodeTable[2*AFP_XLAT_TABLE_SIZE];
  485. BYTE AnsiTable[2*AFP_XLAT_TABLE_SIZE + 1];
  486. UNICODE_STRING UnicodeString;
  487. ANSI_STRING AnsiString;
  488. LONG i;
  489. PAGED_CODE( );
  490. FileHandle.fsh_FileHandle = NULL;
  491. UnicodeString.Length = AFP_XLAT_TABLE_SIZE * sizeof(WCHAR);
  492. UnicodeString.MaximumLength = (AFP_XLAT_TABLE_SIZE + 1) * sizeof(WCHAR);
  493. UnicodeString.Buffer = UnicodeTable;
  494. RtlInitUnicodeString(&uPathCP, PathCP);
  495. devPathCP.Length = 0;
  496. devPathCP.MaximumLength = uPathCP.Length + DosDevices.Length + sizeof(WCHAR);
  497. if ((devPathCP.Buffer = (PWSTR)AfpAllocPagedMemory(devPathCP.MaximumLength)) == NULL)
  498. {
  499. Status = STATUS_NO_MEMORY;
  500. AFPLOG_ERROR(AFPSRVMSG_MAC_CODEPAGE, Status, NULL, 0, NULL);
  501. return Status;
  502. }
  503. AfpCopyUnicodeString(&devPathCP, &DosDevices);
  504. RtlAppendUnicodeStringToString(&devPathCP, &uPathCP);
  505. do
  506. {
  507. FORKSIZE liCPlen;
  508. LONG lCPlen, sizeread=0;
  509. Status = AfpIoOpen(NULL,
  510. AFP_STREAM_DATA,
  511. FILEIO_OPEN_FILE,
  512. &devPathCP,
  513. FILEIO_ACCESS_READ,
  514. FILEIO_DENY_NONE,
  515. False,
  516. &FileHandle);
  517. if (!NT_SUCCESS(Status))
  518. break;
  519. if (!NT_SUCCESS(Status = AfpIoQuerySize(&FileHandle,
  520. &liCPlen)))
  521. break;
  522. // NOTE: This assumes the codepage file will never be so big that
  523. // the high bit of the LowPart of the size will be set
  524. lCPlen = (LONG)liCPlen.LowPart;
  525. if ((AfpMacCPBaseAddress = (PUSHORT)AfpAllocPagedMemory(lCPlen)) == NULL)
  526. {
  527. Status = STATUS_NO_MEMORY;
  528. break;
  529. }
  530. Status = AfpIoRead(&FileHandle,
  531. &LIZero,
  532. lCPlen,
  533. &sizeread,
  534. (PBYTE)AfpMacCPBaseAddress);
  535. AfpIoClose(&FileHandle);
  536. if (!NT_SUCCESS(Status))
  537. break;
  538. if (sizeread != lCPlen)
  539. {
  540. Status = STATUS_UNSUCCESSFUL;
  541. break;
  542. }
  543. RtlInitCodePageTable(AfpMacCPBaseAddress, &AfpMacCPTableInfo);
  544. // Initialize mac ANSI to host upcase Oem translation table
  545. // Start by allocating memory for the table and filling it up.
  546. /* HitoshiT modify following line to keep Unicode translation table. 5/18/94 */
  547. #ifdef DBCS
  548. if ((AfpTranslationTable = AfpAllocPagedMemory(2*AFP_XLAT_TABLE_SIZE*sizeof(USHORT) + 1)) == NULL)
  549. #else
  550. if ((AfpTranslationTable = AfpAllocPagedMemory(2*AFP_XLAT_TABLE_SIZE + 1)) == NULL)
  551. #endif // DBCS
  552. {
  553. Status = STATUS_NO_MEMORY;
  554. break;
  555. }
  556. // Initialize mac ANSI to host Oem translation table
  557. // Start by allocating memory for the table and filling it up.
  558. #ifdef DBCS
  559. if ((AfpCasePreserveTranslationTable = AfpAllocPagedMemory(2*AFP_XLAT_TABLE_SIZE*sizeof(USHORT) + 1)) == NULL)
  560. #else
  561. if ((AfpCasePreserveTranslationTable = AfpAllocPagedMemory(2*AFP_XLAT_TABLE_SIZE + 1)) == NULL)
  562. #endif // DBCS
  563. {
  564. Status = STATUS_NO_MEMORY;
  565. break;
  566. }
  567. for (i = 0; i < 2*AFP_XLAT_TABLE_SIZE; i++)
  568. AnsiTable[i] = (BYTE)i;
  569. // Now translate this from Mac ANSI to unicode
  570. AnsiString.Length = 2*AFP_XLAT_TABLE_SIZE;
  571. AnsiString.MaximumLength = 2*AFP_XLAT_TABLE_SIZE + 1;
  572. AnsiString.Buffer = AnsiTable;
  573. UnicodeString.Length = 0;
  574. UnicodeString.MaximumLength = sizeof(UnicodeTable);
  575. UnicodeString.Buffer = UnicodeTable;
  576. Status = AfpConvertStringToUnicode(&AnsiString, &UnicodeString);
  577. if (!NT_SUCCESS(Status))
  578. break;
  579. // Now convert the entire table to uppercase host Oem Codepage
  580. AnsiString.Length = 0;
  581. /* HitoshiT modify following line to keep Unicode translation table 5/18/94 */
  582. #ifdef DBCS
  583. AnsiString.MaximumLength = 2*AFP_XLAT_TABLE_SIZE * sizeof(USHORT) + 1;
  584. #else
  585. AnsiString.MaximumLength = 2*AFP_XLAT_TABLE_SIZE + 1;
  586. #endif // DBCS
  587. AnsiString.Buffer = AfpTranslationTable;
  588. Status = RtlUpcaseUnicodeStringToOemString(&AnsiString, &UnicodeString, False);
  589. // Bug 342062
  590. // Bug introduced due to RtlpDidUnicodeToOemWork check
  591. // introduced in RtlUpcaseUnicodeStringToOemString
  592. // We have characters which will be mapped to default characters
  593. // and hence we should ignore STATUS_UNMAPPABLE_CHARACTER
  594. if ((!NT_SUCCESS(Status))&&(Status!=STATUS_UNMAPPABLE_CHARACTER))
  595. break;
  596. // Now convert the entire table to host Oem Codepage
  597. AnsiString.Length = 0;
  598. #ifdef DBCS
  599. AnsiString.MaximumLength = 2*AFP_XLAT_TABLE_SIZE * sizeof(USHORT) + 1;
  600. #else
  601. AnsiString.MaximumLength = 2*AFP_XLAT_TABLE_SIZE + 1;
  602. #endif // DBCS
  603. AnsiString.Buffer = AfpCasePreserveTranslationTable;
  604. Status = RtlUnicodeStringToOemString(&AnsiString, &UnicodeString, False);
  605. if ((!NT_SUCCESS(Status))&&(Status!=STATUS_UNMAPPABLE_CHARACTER))
  606. break;
  607. // Initialize host ANSI to mac ANSI translation table
  608. // Start by allocating memory for the table and filling it up.
  609. if ((AfpRevTranslationTable = AfpAllocPagedMemory(AFP_REV_XLAT_TABLE_SIZE + 1)) == NULL)
  610. {
  611. Status = STATUS_NO_MEMORY;
  612. break;
  613. }
  614. for (i = 0; i < 0x20; i++)
  615. AfpRevTranslationTable[i] = (BYTE)i;
  616. for (i = 0x80; i < 256; i++)
  617. AfpRevTranslationTable[i-(0x80-0x20)] = (BYTE)i;
  618. // Get rid of the line feed char
  619. AfpRevTranslationTable[0x0A] = 0;
  620. // Now translate host ANSI to unicode
  621. AnsiString.Length = AFP_REV_XLAT_TABLE_SIZE;
  622. AnsiString.MaximumLength = AFP_REV_XLAT_TABLE_SIZE + 1;
  623. AnsiString.Buffer = AfpRevTranslationTable;
  624. UnicodeString.Length = 0;
  625. Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, False);
  626. if (!NT_SUCCESS(Status))
  627. break;
  628. // and then translate from unicode to Mac ANSI
  629. Status = AfpConvertStringToAnsi(&UnicodeString, &AnsiString);
  630. } while (False);
  631. if (!NT_SUCCESS(Status))
  632. {
  633. AFPLOG_ERROR(AFPSRVMSG_MAC_CODEPAGE, Status, NULL, 0, NULL);
  634. if (AfpMacCPBaseAddress != NULL)
  635. {
  636. AfpFreeMemory(AfpMacCPBaseAddress);
  637. AfpMacCPBaseAddress = NULL;
  638. }
  639. if (FileHandle.fsh_FileHandle != NULL)
  640. {
  641. AfpIoClose(&FileHandle);
  642. }
  643. if (AfpTranslationTable != NULL)
  644. {
  645. AfpFreeMemory(AfpTranslationTable);
  646. AfpTranslationTable = NULL;
  647. }
  648. if (AfpCasePreserveTranslationTable != NULL)
  649. {
  650. AfpFreeMemory(AfpCasePreserveTranslationTable);
  651. AfpCasePreserveTranslationTable = NULL;
  652. }
  653. if (AfpRevTranslationTable != NULL)
  654. {
  655. AfpFreeMemory(AfpRevTranslationTable);
  656. AfpRevTranslationTable = NULL;
  657. }
  658. }
  659. AfpFreeMemory(devPathCP.Buffer);
  660. return Status;
  661. }
  662. /*** AfpIsLegalShortname
  663. *
  664. * Does a mac shortname conform to FAT 8.3 naming conventions?
  665. *
  666. */
  667. BOOLEAN FASTCALL
  668. AfpIsLegalShortname(
  669. IN PANSI_STRING pShortName // Mac ANSI string
  670. )
  671. {
  672. return(FsRtlIsFatDbcsLegal(*pShortName, False, False, False));
  673. }
  674. /*** AfpIsProperSubstring
  675. *
  676. * This routine looks for the substring pSubString in pString. Both
  677. * strings are in unicode, the comparison is done case insensitive
  678. * (i.e. ignoring case). This is used by the AfpCatSearch code.
  679. *
  680. */
  681. BOOLEAN FASTCALL
  682. AfpIsProperSubstring(
  683. IN PUNICODE_STRING pString,
  684. IN PUNICODE_STRING pSubString
  685. )
  686. {
  687. WCHAR *s1, *s2, *ts1;
  688. USHORT l1, l2, tl1;
  689. WCHAR buf1[AFP_LONGNAME_LEN], buf2[AFP_LONGNAME_LEN];
  690. UNICODE_STRING u1, u2;
  691. PAGED_CODE( );
  692. // see if this is a no-op?
  693. if (pSubString->Length > pString->Length)
  694. return False;
  695. AfpSetEmptyUnicodeString(&u1, sizeof(buf1), buf1);
  696. AfpSetEmptyUnicodeString(&u2, sizeof(buf2), buf2);
  697. if (!NT_SUCCESS(RtlUpcaseUnicodeString(&u1, pString, False)) ||
  698. !NT_SUCCESS(RtlUpcaseUnicodeString(&u2, pSubString, False)))
  699. return False;
  700. l1 = u1.Length/sizeof(WCHAR);
  701. s1 = u1.Buffer;
  702. do
  703. {
  704. l2 = u2.Length/sizeof(WCHAR);
  705. s2 = u2.Buffer;
  706. if (l2 > l1)
  707. return False;
  708. // look for the next occurrence of the first char of s2 in string s1
  709. while (l1)
  710. {
  711. if (*s2 == *s1)
  712. break;
  713. s1++;
  714. l1--;
  715. }
  716. if (l1 < l2)
  717. return False;
  718. if (l2 == 1)
  719. return True;
  720. l1--; l2--;
  721. s1++; s2++;
  722. ts1 = s1;
  723. tl1 = l1;
  724. while (l2)
  725. {
  726. // Look for substring s2 from current position in s1
  727. if (*s2 != *ts1)
  728. break;
  729. tl1--; l2--;
  730. ts1++; s2++;
  731. }
  732. if (l2 == 0)
  733. return True;
  734. } while (True);
  735. // Should never get here
  736. KeBugCheck(0);
  737. }
  738. /*** AfpStrChr
  739. *
  740. * DBCS sensitive strchr()
  741. *
  742. */
  743. PCHAR
  744. AfpStrChr(
  745. IN PBYTE String,
  746. IN DWORD StringLen,
  747. IN BYTE Char
  748. )
  749. {
  750. DWORD BytesRemaining;
  751. BytesRemaining = StringLen;
  752. while (BytesRemaining > 0)
  753. {
  754. /* MSKK hideyukn, strchr() does not work with DBCS, 08/07/95 */
  755. #ifdef DBCS
  756. if (FsRtlIsLeadDbcsCharacter(*String))
  757. {
  758. String += 2;
  759. continue;
  760. }
  761. #endif /* DBCS */
  762. if (*String == Char)
  763. {
  764. return(String);
  765. }
  766. String++;
  767. BytesRemaining--;
  768. }
  769. return(NULL);
  770. }