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

📄 lang.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
        }
    }
    HeapFree( GetProcessHeap(), 0, bufferW );
    return ret;
}


/*
 * @implemented
 */
LANGID STDCALL
GetSystemDefaultLangID(VOID)
{
  return LANGIDFROMLCID(GetSystemDefaultLCID());
}


/*
 * @implemented
 */
LCID STDCALL
GetSystemDefaultLCID(VOID)
{
  LCID lcid;

  NtQueryDefaultLocale(FALSE, &lcid);

  return lcid;
}


/*
 * @implemented
 */
LANGID STDCALL
GetSystemDefaultUILanguage(VOID)
{
  LANGID LanguageId;
  NTSTATUS Status;

  Status = NtQueryInstallUILanguage(&LanguageId);
  if (!NT_SUCCESS(Status))
    {
      SetLastErrorByStatus(Status);
      return 0;
    }

  return LanguageId;
}


/*
 * @implemented
 */
LCID STDCALL
GetThreadLocale(VOID)
{
  return NtCurrentTeb()->CurrentLocale;
}


/*
 * @implemented
 */
LANGID STDCALL
GetUserDefaultLangID(VOID)
{
  return LANGIDFROMLCID(GetUserDefaultLCID());
}


/*
 * @implemented
 */
LCID STDCALL
GetUserDefaultLCID(VOID)
{
  LCID lcid;
  NTSTATUS Status;

  Status = NtQueryDefaultLocale(TRUE, &lcid);
  if (!NT_SUCCESS(Status))
    {
      SetLastErrorByStatus(Status);
      return 0;
    }

  return lcid;
}


/*
 * @implemented
 */
LANGID STDCALL
GetUserDefaultUILanguage(VOID)
{
  LANGID LangId;
  NTSTATUS Status;

  Status = NtQueryDefaultUILanguage(&LangId);
  if (!NT_SUCCESS(Status))
    {
      SetLastErrorByStatus(Status);
      return 0;
    }

  return LangId;
}


/*
 * @unimplemented
 */
GEOID
STDCALL
GetUserGeoID(
    GEOCLASS    GeoClass)
{
    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
    return 0;
}


/******************************************************************************
 *           IsValidLanguageGroup
 *
 * Determine if a language group is supported and/or installed.
 *
 * PARAMS
 *  LanguageGroup [I] Language Group Id (LGRPID_ values from "winnls.h")
 *  dwFlags [I] LGRPID_SUPPORTED=Supported, LGRPID_INSTALLED=Installed
 *
 * RETURNS
 *  TRUE, if lgrpid is supported and/or installed, according to dwFlags.
 *  FALSE otherwise.
 *
 * @implemented
 */
BOOL
STDCALL
IsValidLanguageGroup(
    LGRPID  LanguageGroup,
    DWORD   dwFlags)
{
    static const WCHAR szFormat[] = { '%','x','\0' };
    UNICODE_STRING szNlsKeyName = 
        RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls");
    UNICODE_STRING szLangGroupsKeyName = 
        RTL_CONSTANT_STRING(L"Language Groups");
    const int MAX_VALUE_NAME = 16;
    const int MAX_VALUE_SYMB = 128;

    BOOL bNtQuery;
    PKEY_VALUE_PARTIAL_INFORMATION kvpiInfo;

    WCHAR szValueName[MAX_VALUE_NAME];
    UNICODE_STRING ucsValueName;
    DWORD dwRetSize;
    PWSTR pwszValueData;

    DWORD dwSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + MAX_VALUE_SYMB * sizeof(WCHAR);

    OBJECT_ATTRIBUTES oaAttr;
    HANDLE hkey, hRootKey;
    BOOL bSupported = FALSE, bInstalled = FALSE;

    DPRINT("IsValidLanguageGroup() called\n");

    kvpiInfo = RtlAllocateHeap(RtlGetProcessHeap(),
			                  HEAP_ZERO_MEMORY,
			                  dwSize);

    switch (dwFlags)
    {
        case LGRPID_INSTALLED:
        case LGRPID_SUPPORTED:

            InitializeObjectAttributes(&oaAttr, &szNlsKeyName, 0, 0, NULL);
            if(NtOpenKey(&hRootKey, KEY_ALL_ACCESS, &oaAttr) != STATUS_SUCCESS) return FALSE;

            InitializeObjectAttributes(&oaAttr, &szLangGroupsKeyName, 0, hRootKey, NULL);
            if(NtOpenKey(&hkey, KEY_ALL_ACCESS, &oaAttr) != STATUS_SUCCESS) return FALSE;

            if(hRootKey) NtClose(hRootKey);

            swprintf(szValueName, szFormat, (ULONG)LanguageGroup);
            RtlInitUnicodeString(&ucsValueName, szValueName);

            bNtQuery = NtQueryValueKey(hkey,
                                       &ucsValueName,
                                       KeyValuePartialInformation,
                                       kvpiInfo,
                                       dwSize,
                                       &dwRetSize);
            if(hkey) NtClose(hkey);

            if(bNtQuery == STATUS_SUCCESS &&
               kvpiInfo->DataLength == sizeof(DWORD))
            {
                pwszValueData = (PWSTR)&kvpiInfo->Data[0];
                bSupported = TRUE;
                if(pwszValueData[0] == L'1') bInstalled = TRUE;
            }
            else
            {
                DPRINT("NtQueryValueKey() failed (Status %lx)\n", bNtQuery);
                RtlFreeHeap(RtlGetProcessHeap(), 0, kvpiInfo);
                return FALSE;
            }

        break;
    }

    RtlFreeHeap(RtlGetProcessHeap(), 0, kvpiInfo);

    if((dwFlags == LGRPID_SUPPORTED && bSupported) ||
       (dwFlags == LGRPID_INSTALLED && bInstalled))
    {
        DPRINT("Language group is supported and installed\n");
        return TRUE;
    }

    return FALSE;
}


/******************************************************************************
 *           IsValidLocale
 *
 * Determine if a locale is valid.
 *
 * PARAMS
 *  Locale  [I] LCID of the locale to check
 *  dwFlags [I] LCID_SUPPORTED = Valid
 *              LCID_INSTALLED = Valid and installed on the system
 *
 * RETURN
 *  TRUE,  if Locale is valid,
 *  FALSE, otherwise.
 *
 * @implemented
 */
BOOL STDCALL
IsValidLocale(LCID Locale,
	      DWORD dwFlags)
{
  OBJECT_ATTRIBUTES ObjectAttributes;
  PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
  WCHAR ValueNameBuffer[9];
  UNICODE_STRING KeyName;
  UNICODE_STRING ValueName;
  ULONG KeyInfoSize;
  ULONG ReturnedSize;
  HANDLE KeyHandle;
  PWSTR ValueData;
  NTSTATUS Status;

  DPRINT("IsValidLocale() called\n");

  if ((dwFlags & ~(LCID_SUPPORTED | LCID_INSTALLED)) ||
      (dwFlags == (LCID_SUPPORTED | LCID_INSTALLED)))
    {
      DPRINT("Invalid flags: %lx\n", dwFlags);
      return FALSE;
    }

  if (Locale & 0xFFFF0000)
    {
      RtlInitUnicodeString(&KeyName,
			   L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Nls\\Locale\\Alternate Sorts");
    }
  else
    {
      RtlInitUnicodeString(&KeyName,
			   L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Nls\\Locale");
    }

  InitializeObjectAttributes(&ObjectAttributes,
			     &KeyName,
			     OBJ_CASE_INSENSITIVE,
			     NULL,
			     NULL);

  Status = NtOpenKey(&KeyHandle,
		     KEY_QUERY_VALUE,
		     &ObjectAttributes);
  if (!NT_SUCCESS(Status))
    {
      DPRINT("NtOpenKey() failed (Status %lx)\n", Status);
      return FALSE;
    }

  swprintf(ValueNameBuffer, L"%08lx", (ULONG)Locale);
  RtlInitUnicodeString(&ValueName, ValueNameBuffer);

  KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 4 * sizeof(WCHAR);
  KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(),
			    HEAP_ZERO_MEMORY,
			    KeyInfoSize);
  if (KeyInfo == NULL)
    {
      DPRINT("RtlAllocateHeap() failed (Status %lx)\n", Status);
      NtClose(KeyHandle);
      return FALSE;
    }

  Status = NtQueryValueKey(KeyHandle,
			   &ValueName,
			   KeyValuePartialInformation,
			   KeyInfo,
			   KeyInfoSize,
			   &ReturnedSize);
  NtClose(KeyHandle);

  if (!NT_SUCCESS(Status))
    {
      DPRINT("NtQueryValueKey() failed (Status %lx)\n", Status);
      RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
      return FALSE;
    }

  if (dwFlags & LCID_SUPPORTED)
    {
      DPRINT("Locale is supported\n");
      RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
      return TRUE;
    }

  ValueData = (PWSTR)&KeyInfo->Data[0];
  if ((KeyInfo->Type == REG_SZ) &&
      (KeyInfo->DataLength == 2 * sizeof(WCHAR)) &&
      (ValueData[0] == L'1'))
    {
      DPRINT("Locale is supported and installed\n");
      RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
      return TRUE;
    }

  RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);

  DPRINT("IsValidLocale() called\n");

  return FALSE;
}


/*
 * @unimplemented
 */
int
STDCALL
LCMapStringA (
    LCID    Locale,
    DWORD   dwMapFlags,
    LPCSTR  lpSrcStr,
    int cchSrc,
    LPSTR   lpDestStr,
    int cchDest
    )
{
    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
    return 0;
}


/*
 * @unimplemented
 */
int
STDCALL
LCMapStringW (
    LCID    Locale,
    DWORD   dwMapFlags,
    LPCWSTR lpSrcStr,
    int cchSrc,
    LPWSTR  lpDestStr,
    int cchDest
    )
{
    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
    return 0;
}


/*
 * @unimplemented
 */
BOOL
STDCALL
SetCalendarInfoA(
    LCID     Locale,
    CALID    Calendar,
    CALTYPE  CalType,
    LPCSTR  lpCalData)
{
    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
    return 0;
}

/*
 * @unimplemented
 */
BOOL
STDCALL
SetCalendarInfoW(
    LCID     Locale,
    CALID    Calendar,
    CALTYPE  CalType,
    LPCWSTR  lpCalData)
{
    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
    return 0;
}


/**********************************************************************
 * @implemented
 * RIPPED FROM WINE's dlls\kernel\locale.c ver 0.9.29
 *
 *           SetLocaleInfoA    (KERNEL32.@)
 *
 * Set the current locale info.
 *
 * PARAMS
 *  Locale   [I] LCID of the locale
 *  LCType   [I] LCTYPE_ flags from "winnls.h"
 *  lpLCData [I] Information to set
 *
 * RETURNS
 *  Success: TRUE. The information given will be returned by GetLocaleInfoA()
 *           whenever it is called without LOCALE_NOUSEROVERRIDE.
 *  Failure: FALSE. Use GetLastError() to determine the cause.
 */
BOOL
STDCALL
SetLocaleInfoA (
    LCID    Locale,
    LCTYPE  LCType,
    LPCSTR  lpLCData
    )
{
    UINT codepage = CP_ACP;
    WCHAR *strW;
    DWORD len;
    BOOL ret;

    if (!(LCType & LOCALE_USE_CP_ACP)) codepage = get_lcid_codepage( Locale );

    if (!lpLCData)
    {
        SetLastError( ERROR_INVALID_PARAMETER );
        return FALSE;
    }
    len = MultiByteToWideChar( codepage, 0, lpLCData, -1, NULL, 0 );
    if (!(strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
    {
        SetLastError( ERROR_NOT_ENOUGH_MEMORY );
        return FALSE;
    }
    MultiByteToWideChar( codepage, 0, lpLCData, -1, strW, len );
    ret = SetLocaleInfoW( Locale, LCType, strW );
    HeapFree( GetProcessHeap(), 0, strW );
    return ret;
}


/**********************************************************************
 * @implemented
 * RIPPED FROM WINE's dlls\kernel\locale.c ver 0.9.29
 *
 *           SetLocaleInfoW    (KERNEL32.@)
 *
 * See SetLocaleInfoA.
 *
 */
BOOL
STDCALL
SetLocaleInfoW (
    LCID    Locale,
    LCTYPE  LCType,
    LPCWSTR lpLCData
    )
{
    const WCHAR *value;
    UNICODE_STRING valueW;
    NTSTATUS status;
    HANDLE hkey;

    LCType &= 0xffff;
    value = RosGetLocaleValueName( LCType );

    if (!lpLCData || !value)
    {
        SetLastError( ERROR_INVALID_PARAMETER );
        return FALSE;
    }

    if (LCType == LOCALE_IDATE || LCType == LOCALE_ILDATE)
    {
        SetLastError( ERROR_INVALID_FLAGS );
        return FALSE;
    }

    if (!(hkey = RosCreateRegistryKey())) return FALSE;
    RtlInitUnicodeString( &valueW, value );
    status = NtSetValueKey( hkey, &valueW, 0, REG_SZ, (PVOID)lpLCData, (lstrlenW(lpLCData)+1)*sizeof(WCHAR) );

    if (LCType == LOCALE_SSHORTDATE || LCType == LOCALE_SLONGDATE)
    {
        /* Set I-value from S value */
        WCHAR *lpD, *lpM, *lpY;
        WCHAR szBuff[2];

        lpD = wcschr(lpLCData, 'd');
        lpM = wcschr(lpLCData, 'M');
        lpY = wcschr(lpLCData, 'y');

        if (lpD <= lpM)
        {
            szBuff[0] = '1'; /* D-M-Y */
        }
        else
        {
            if (lpY <= lpM)
                szBuff[0] = '2'; /* Y-M-D */
            else
                szBuff[0] = '0'; /* M-D-Y */
        }

        szBuff[1] = '\0';

        if (LCType == LOCALE_SSHORTDATE)
            LCType = LOCALE_IDATE;
        else
            LCType = LOCALE_ILDATE;

        value = RosGetLocaleValueName( LCType );

        RtlInitUnicodeString( &valueW, value );
        status = NtSetValueKey( hkey, &valueW, 0, REG_SZ, szBuff, sizeof(szBuff) );
    }

    NtClose( hkey );

    if (status) SetLastError( RtlNtStatusToDosError(status) );
    return !status;
}


/**********************************************************************
 * @implemented
 * RIPPED FROM WINE's dlls\kernel\locale.c rev 1.42
 *
 *           SetThreadLocale    (KERNEL32.@)
 *
 * Set the current threads locale.
 *
 * PARAMS
 *  lcid [I] LCID of the locale to set
 *
 * RETURNS
 *  Success: TRUE. The threads locale is set to lcid.
 *  Failure: FALSE. Use GetLastError() to determine the cause.
 *
 */
BOOL WINAPI SetThreadLocale( LCID lcid )
{
    DPRINT("SetThreadLocale(0x%04lX)\n", lcid);

    lcid = ConvertDefaultLocale(lcid);

    if (lcid != GetThreadLocale())
    {
        if (!IsValidLocale(lcid, LCID_SUPPORTED))
        {
            SetLastError(ERROR_INVALID_PARAMETER);
            return FALSE;
        }

        NtCurrentTeb()->CurrentLocale = lcid;
        /* FIXME: NtCurrentTeb()->code_page = get_lcid_codepage( lcid );
         * Wine save the acp for easy/fast access, but ROS has no such Teb member.
         * Maybe add this member to ros as well?
         */

        /*
        Lag test app for 

⌨️ 快捷键说明

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