Leaked source code of windows server 2003
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.

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