⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nls.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 2 页
字号:
         *MultiByteString++ = Char;
         continue;
      }

      if (Char < 0x800)  /* 0x80-0x7ff: 2 bytes */
      {
         if (TempLength < 2)
         {
            SetLastError(ERROR_INSUFFICIENT_BUFFER);
            break;
         }
         MultiByteString[1] = 0x80 | (Char & 0x3f); Char >>= 6;
         MultiByteString[0] = 0xc0 | Char;
         MultiByteString += 2;
         TempLength -= 2;
         continue;
      }

      /* 0x800-0xffff: 3 bytes */
      if (TempLength < 3)
      {
         SetLastError(ERROR_INSUFFICIENT_BUFFER);
         break;
      }
      MultiByteString[2] = 0x80 | (Char & 0x3f); Char >>= 6;
      MultiByteString[1] = 0x80 | (Char & 0x3f); Char >>= 6;
      MultiByteString[0] = 0xe0 | Char;
      MultiByteString += 3;
      TempLength -= 3;
   }

   return MultiByteCount - TempLength;
}

/**
 * @name IntWideCharToMultiByteCP
 *
 * Internal version of WideCharToMultiByte for code page tables.
 *
 * @see WideCharToMultiByte
 * @todo Handle default characters and flags.
 */

static INT STDCALL
IntWideCharToMultiByteCP(UINT CodePage, DWORD Flags,
                         LPCWSTR WideCharString, INT WideCharCount,
                         LPSTR MultiByteString, INT MultiByteCount,
                         LPCSTR DefaultChar, LPBOOL UsedDefaultChar)
{
   PCODEPAGE_ENTRY CodePageEntry;
   PCPTABLEINFO CodePageTable;
   INT TempLength;

   /* Get code page table. */
   CodePageEntry = IntGetCodePageEntry(CodePage);
   if (CodePageEntry == NULL)
   {
      SetLastError(ERROR_INVALID_PARAMETER);
      return 0;
   }
   CodePageTable = &CodePageEntry->CodePageTable;

   /* Different handling for DBCS code pages. */
   if (CodePageTable->MaximumCharacterSize > 1)
   {
      DPRINT1("WideCharToMultiByte for DBCS codepages is not implemented!\n");
      return 0;
   }
   else
   {
      /* Does caller query for output buffer size? */
      if (MultiByteCount == 0)
         return WideCharCount;

      /* Adjust buffer size. Wine trick ;-) */
      if (MultiByteCount < WideCharCount)
      {
         WideCharCount = MultiByteCount;
         SetLastError(ERROR_INSUFFICIENT_BUFFER);
      }

      for (TempLength = WideCharCount;
           TempLength > 0;
           WideCharString++, TempLength--)
      {
         *MultiByteString++ = ((PCHAR)CodePageTable->WideCharTable)[*WideCharString];
      }

      /* FIXME */
      if (UsedDefaultChar != NULL)
         *UsedDefaultChar = FALSE;

      return WideCharCount;
   }
}

/** 
 * @name IntIsLeadByte
 *
 * Internal function to detect if byte is lead byte in specific character
 * table.
 */

static BOOL STDCALL
IntIsLeadByte(PCPTABLEINFO TableInfo, BYTE Byte)
{
   UINT LeadByteNo;

   if (TableInfo->MaximumCharacterSize == 2)
   {
      for (LeadByteNo = 0; LeadByteNo < MAXIMUM_LEADBYTES; LeadByteNo++)
      {
         if (TableInfo->LeadByte[LeadByteNo] == Byte)
            return TRUE;
      }
   }

   return FALSE;
}

/* PUBLIC FUNCTIONS ***********************************************************/

/**
 * @name GetNlsSectionName
 *
 * Construct a name of NLS section.
 *
 * @param CodePage
 *        Code page number.
 * @param Base
 *        Integer base used for converting to string. Usually set to 10.
 * @param Unknown
 *        As the name suggests the meaning of this parameter is unknown.
 *        The native version of Kernel32 passes it as the third parameter
 *        to NlsConvertIntegerToString function, which is used for the
 *        actual conversion of the code page number.
 * @param BaseName
 *        Base name of the section. (ex. "\\Nls\\NlsSectionCP")
 * @param Result
 *        Buffer that will hold the constructed name.
 * @param ResultSize
 *        Size of the buffer for the result.
 *
 * @return TRUE if the buffer was large enough and was filled with
 *         the requested information, FALSE otherwise.
 *
 * @implemented
 */

BOOL STDCALL
GetNlsSectionName(UINT CodePage, UINT Base, ULONG Unknown,
                  LPSTR BaseName, LPSTR Result, ULONG ResultSize)
{
   CHAR Integer[11];

   if (!NT_SUCCESS(RtlIntegerToChar(CodePage, Base, sizeof(Integer), Integer)))
      return FALSE;

   /*
    * If the name including the terminating NULL character doesn't
    * fit in the output buffer then fail.
    */
   if (strlen(Integer) + strlen(BaseName) >= ResultSize)
      return FALSE;

   lstrcpyA(Result, BaseName);
   lstrcatA(Result, Integer);

   return TRUE;
}

/**
 * @name GetCPFileNameFromRegistry
 *
 * Get file name of code page definition file.
 *
 * @param CodePage
 *        Code page number to get file name of.
 * @param FileName
 *        Buffer that is filled with file name of successful return. Can
 *        be set to NULL.
 * @param FileNameSize
 *        Size of the buffer to hold file name in WCHARs.
 *
 * @return TRUE if the file name was retrieved, FALSE otherwise.
 *
 * @implemented
 */

BOOL STDCALL
GetCPFileNameFromRegistry(UINT CodePage, LPWSTR FileName, ULONG FileNameSize)
{
   WCHAR ValueNameBuffer[11];
   UNICODE_STRING KeyName, ValueName;
   OBJECT_ATTRIBUTES ObjectAttributes;
   NTSTATUS Status;
   HANDLE KeyHandle;
   PKEY_VALUE_PARTIAL_INFORMATION Kvpi;
   DWORD KvpiSize;

   /* Convert the codepage number to string. */
   ValueName.Buffer = ValueNameBuffer;
   ValueName.MaximumLength = sizeof(ValueNameBuffer);
   if (!NT_SUCCESS(RtlIntegerToUnicodeString(CodePage, 10, &ValueName)))
      return FALSE;

   /* Open the registry key containing file name mappings. */
   RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\System\\"
                        L"CurrentControlSet\\Control\\Nls\\CodePage");
   InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE,
			      NULL, NULL);
   Status = NtOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
   if (!NT_SUCCESS(Status))
   {
      return FALSE;
   }

   /* Allocate buffer that will be used to query the value data. */
   KvpiSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
              (MAX_PATH * sizeof(WCHAR));
   Kvpi = HeapAlloc(GetProcessHeap(), 0, KvpiSize);
   if (Kvpi == NULL)
   {
      NtClose(KeyHandle);
      return FALSE;
   }

   /* Query the file name for our code page. */
   Status = NtQueryValueKey(KeyHandle, &ValueName, KeyValuePartialInformation,
                            Kvpi, KvpiSize, &KvpiSize);

   NtClose(KeyHandle);

   /* Check if we succeded and the value is non-empty string. */
   if (NT_SUCCESS(Status) && Kvpi->Type == REG_SZ &&
       Kvpi->DataLength > sizeof(WCHAR))
   {
      if (FileName != NULL)
      {
         lstrcpynW(FileName, (WCHAR*)Kvpi->Data,
                   min(Kvpi->DataLength / sizeof(WCHAR), FileNameSize));
      }
      return TRUE;
   }

   return FALSE;
}

/**
 * @name IsValidCodePage
 *
 * Detect if specified code page is valid and present in the system.
 *
 * @param CodePage
 *        Code page number to query.
 *
 * @return TRUE if code page is present.
 */

BOOL STDCALL
IsValidCodePage(UINT CodePage)
{
   if (CodePage == CP_UTF8 || CodePage == CP_UTF7)
      return TRUE;
   if (IntGetLoadedCodePageEntry(CodePage))
      return TRUE;
   return GetCPFileNameFromRegistry(CodePage, NULL, 0);
}

/**
 * @name MultiByteToWideChar
 *
 * Convert a multi-byte string to wide-charater equivalent.
 *
 * @param CodePage
 *        Code page to be used to perform the conversion. It can be also
 *        one of the special values (CP_ACP for ANSI code page, CP_MACCP
 *        for Macintosh code page, CP_OEMCP for OEM code page, CP_THREAD_ACP
 *        for thread active code page, CP_UTF7 or CP_UTF8).
 * @param Flags
 *        Additional conversion flags (MB_PRECOMPOSED, MB_COMPOSITE,
 *        MB_ERR_INVALID_CHARS, MB_USEGLYPHCHARS).
 * @param MultiByteString
 *        Input buffer.
 * @param MultiByteCount
 *        Size of MultiByteString, or -1 if MultiByteString is NULL
 *        terminated.
 * @param WideCharString
 *        Output buffer.
 * @param WideCharCount
 *        Size in WCHARs of WideCharString, or 0 if the caller just wants
 *        to know how large WideCharString should be for a successful
 *        conversion.
 *
 * @return Zero on error, otherwise the number of WCHARs written
 *         in the WideCharString buffer.
 *
 * @implemented
 */

INT STDCALL
MultiByteToWideChar(UINT CodePage, DWORD Flags,
                    LPCSTR MultiByteString, INT MultiByteCount,
                    LPWSTR WideCharString, INT WideCharCount)
{
   /* Check the parameters. */
   if (MultiByteString == NULL ||
       (WideCharString == NULL && WideCharCount > 0) ||
       (PVOID)MultiByteString == (PVOID)WideCharString)
   {
      SetLastError(ERROR_INVALID_PARAMETER);
      return 0;
   }

   /* Determine the input string length. */
   if (MultiByteCount < 0)
   {
      MultiByteCount = lstrlenA(MultiByteString) + 1;
   }

   switch (CodePage)
   {
      case CP_UTF8:
         return IntMultiByteToWideCharUTF8(
            Flags, MultiByteString, MultiByteCount,
            WideCharString, WideCharCount);

      case CP_UTF7:
         DPRINT1("MultiByteToWideChar for CP_UTF7 is not implemented!\n");
         return 0;

      case CP_SYMBOL:
         DPRINT1("MultiByteToWideChar for CP_SYMBOL is not implemented!\n");
         return 0;

      default:
         return IntMultiByteToWideCharCP(
            CodePage, Flags, MultiByteString, MultiByteCount,
            WideCharString, WideCharCount);
   }
}

/**
 * @name WideCharToMultiByte
 *
 * Convert a wide-charater string to closest multi-byte equivalent.
 *
 * @param CodePage
 *        Code page to be used to perform the conversion. It can be also
 *        one of the special values (CP_ACP for ANSI code page, CP_MACCP
 *        for Macintosh code page, CP_OEMCP for OEM code page, CP_THREAD_ACP
 *        for thread active code page, CP_UTF7 or CP_UTF8).
 * @param Flags
 *        Additional conversion flags (WC_NO_BEST_FIT_CHARS, WC_COMPOSITECHECK,
 *        WC_DISCARDNS, WC_SEPCHARS, WC_DEFAULTCHAR).
 * @param WideCharString
 *        Points to the wide-character string to be converted.
 * @param WideCharCount
 *        Size in WCHARs of WideCharStr, or 0 if the caller just wants to
 *        know how large WideCharString should be for a successful conversion.
 * @param MultiByteString
 *        Points to the buffer to receive the translated string.
 * @param MultiByteCount
 *        Specifies the size in bytes of the buffer pointed to by the
 *        MultiByteString parameter. If this value is zero, the function
 *        returns the number of bytes required for the buffer.
 * @param DefaultChar
 *        Points to the character used if a wide character cannot be
 *        represented in the specified code page. If this parameter is
 *        NULL, a system default value is used.
 * @param UsedDefaultChar
 *        Points to a flag that indicates whether a default character was
 *        used. This parameter can be NULL.
 *
 * @return Zero on error, otherwise the number of bytes written in the
 *         MultiByteString buffer. Or the number of bytes needed for
 *         the MultiByteString buffer if MultiByteCount is zero.
 *
 * @implemented
 */

INT STDCALL
WideCharToMultiByte(UINT CodePage, DWORD Flags,
                    LPCWSTR WideCharString, INT WideCharCount,
                    LPSTR MultiByteString, INT MultiByteCount,
                    LPCSTR DefaultChar, LPBOOL UsedDefaultChar)
{
   /* Check the parameters. */
   if (WideCharString == NULL ||
       (MultiByteString == NULL && MultiByteCount > 0) ||
       (PVOID)WideCharString == (PVOID)MultiByteString)
   {
      SetLastError(ERROR_INVALID_PARAMETER);
      return 0;
   }

   /* Determine the input string length. */
   if (WideCharCount < 0)
   {
      WideCharCount = lstrlenW(WideCharString) + 1;
   }

   switch (CodePage)
   {
      case CP_UTF8:
         return IntWideCharToMultiByteUTF8(
            CodePage, Flags, WideCharString, WideCharCount,
            MultiByteString, MultiByteCount, DefaultChar,
            UsedDefaultChar);

      case CP_UTF7:
         DPRINT1("WideCharToMultiByte for CP_UTF7 is not implemented!\n");
         return 0;

      case CP_SYMBOL:
         DPRINT1("WideCharToMultiByte for CP_SYMBOL is not implemented!\n");
         return 0;

      default:
         return IntWideCharToMultiByteCP(
            CodePage, Flags, WideCharString, WideCharCount,
            MultiByteString, MultiByteCount, DefaultChar,
            UsedDefaultChar);
   }
}

/**
 * @name GetACP
 *
 * Get active ANSI code page number.
 *
 * @implemented
 */

UINT STDCALL
GetACP(VOID)
{
   return AnsiCodePage.CodePageTable.CodePage;
}

/**
 * @name GetOEMCP
 *
 * Get active OEM code page number.
 * 
 * @implemented
 */

UINT STDCALL
GetOEMCP(VOID)
{
   return OemCodePage.CodePageTable.CodePage;
}

/**
 * @name IsDBCSLeadByteEx
 *
 * Determine if passed byte is lead byte in specified code page.
 *
 * @implemented
 */

BOOL STDCALL
IsDBCSLeadByteEx(UINT CodePage, BYTE TestByte)
{
   PCODEPAGE_ENTRY CodePageEntry;

   CodePageEntry = IntGetCodePageEntry(CodePage);
   if (CodePageEntry != NULL)
      return IntIsLeadByte(&CodePageEntry->CodePageTable, TestByte);

   SetLastError(ERROR_INVALID_PARAMETER);
   return FALSE;
}

/**
 * @name IsDBCSLeadByteEx
 *
 * Determine if passed byte is lead byte in current ANSI code page.
 *
 * @implemented
 */

BOOL STDCALL
IsDBCSLeadByte(BYTE TestByte)
{
   return IntIsLeadByte(&AnsiCodePage.CodePageTable, TestByte);
}

/* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -