windows-nt/Source/XPSP1/NT/base/ntsetup/textmode/spddlang/fe/fereg.c

779 lines
22 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
fereg.c
Abstract:
Japanese/korean-specific registry settings.
Author:
Ted Miller (tedm) 04-July-1995
Revision History:
Adapted from hideyukn's code in textmode\kernel\spconfig.c.
--*/
#include <precomp.h>
#pragma hdrstop
NTSTATUS
SpDeleteValueKey(
IN HANDLE hKeyRoot,
IN PWSTR KeyName,
IN PWSTR ValueName
);
NTSTATUS
FESetKeyboardParams(
IN PVOID SifHandle,
IN HANDLE ControlSetKeyHandle,
IN PHARDWARE_COMPONENT *HwComponents,
IN PWSTR LayerDriver
)
/*++
Routine Description:
Set parameters in the registry relating to the keyboard type
selected by the user.
Arguments:
SifHandle - supplies handle to open/loaded setup info file (txtsetup.sif).
ControlSetKeyHandle - supplies handle to open registry key for current
control set (ie, HKEY_LOCAL_MACHINE\CurrentControlSet).
HwComponents - supplies the address of the master hardware components
array.
Return Value:
NT Status code indicating result of operation.
--*/
{
WCHAR KeyEntryName[100] = L"Services\\";
NTSTATUS Status;
PWSTR KeyboardPortDriver;
PWSTR KeyboardId;
PWSTR KeyboardDll;
PWSTR KeyboardPnPId;
PWSTR KeyboardTypeStr;
PWSTR KeyboardSubtypeStr;
ULONG KeyboardType;
ULONG KeyboardSubtype;
ULONG val;
PHARDWARE_COMPONENT hw;
hw = HwComponents[HwComponentKeyboard];
//
// if third party's driver is selected, we don't write LayerDriver data
// into registry.
//
if(hw->ThirdPartyOptionSelected) {
//
// [This modification is requested by Japanese hardware provider]
//
// if user replace keyboard port driver with thirdpartys one,
// we should disable build-in keyboard port driver (i8042prt.sys)
// because if i8042prt is initialized faster than OEM driver and
// i8042prt can recoganize the port device, the oem driver will fail
// to initialization due to conflict of hardware resorce.
//
// ** BUG BUG **
//
// how about mouse? mouse might use i8042prt, we should not disbale
// it when user only replace keyboard port. this might causes critical
// error. But I believe, the mouse device also handled by OEM port
// driver.
//
// Disable the built-in port driver.
//
if(IS_FILETYPE_PRESENT(hw->FileTypeBits,HwFilePort)) {
val = SERVICE_DISABLED;
Status = SpOpenSetValueAndClose(
ControlSetKeyHandle,
L"Services\\i8042prt",
L"Start",
REG_DWORD,
&val,
sizeof(ULONG)
);
} else {
Status = STATUS_SUCCESS;
}
} else {
//
// Get keyboard port driver name and layer driver name from txtsetup.sif
//
KeyboardId = HwComponents[HwComponentKeyboard]->IdString;
KeyboardPortDriver = SpGetSectionKeyIndex(SifHandle,szKeyboard,KeyboardId,2);
KeyboardDll = SpGetSectionKeyIndex(SifHandle,szKeyboard,KeyboardId,3);
KeyboardTypeStr = SpGetSectionKeyIndex(SifHandle,szKeyboard,KeyboardId,4);
KeyboardSubtypeStr = SpGetSectionKeyIndex(SifHandle,szKeyboard,KeyboardId,5);
KeyboardPnPId = SpGetSectionKeyIndex(SifHandle,szKeyboard,KeyboardId,6);
if(KeyboardPortDriver && KeyboardDll) {
//
// Build registry path such as L"Services\\KeyboardPortDriver\\Parameters"
// and write into registry.
//
wcscat(KeyEntryName,KeyboardPortDriver);
wcscat(KeyEntryName,L"\\Parameters");
//
// Save Keyboard layout driver name.
//
Status = SpOpenSetValueAndClose(
ControlSetKeyHandle,
KeyEntryName,
LayerDriver,
REG_SZ,
KeyboardDll,
(wcslen(KeyboardDll)+1)*sizeof(WCHAR)
);
if(NT_SUCCESS(Status)) {
if (KeyboardPnPId) {
//
// Save Keyboard PnP Id.
//
Status = SpOpenSetValueAndClose(
ControlSetKeyHandle,
KeyEntryName,
L"OverrideKeyboardIdentifier",
REG_SZ,
KeyboardPnPId,
(wcslen(KeyboardPnPId)+1)*sizeof(WCHAR)
);
}
if(KeyboardTypeStr && KeyboardSubtypeStr) {
UNICODE_STRING UnicodeString;
//
// Convert the string to DWORD value.
//
RtlInitUnicodeString(&UnicodeString,KeyboardTypeStr);
RtlUnicodeStringToInteger(&UnicodeString,10,&KeyboardType);
RtlInitUnicodeString(&UnicodeString,KeyboardSubtypeStr);
RtlUnicodeStringToInteger(&UnicodeString,10,&KeyboardSubtype);
Status = SpOpenSetValueAndClose(
ControlSetKeyHandle,
KeyEntryName,
L"OverrideKeyboardType",
REG_DWORD,
&KeyboardType,
sizeof(ULONG)
);
if(NT_SUCCESS(Status)) {
Status = SpOpenSetValueAndClose(
ControlSetKeyHandle,
KeyEntryName,
L"OverrideKeyboardSubtype",
REG_DWORD,
&KeyboardSubtype,
sizeof(ULONG)
);
}
}
}
} else {
Status = STATUS_SUCCESS;
}
}
return(Status);
}
NTSTATUS
FEUpgradeKeyboardParams(
IN PVOID SifHandle,
IN HANDLE ControlSetKeyHandle,
IN PHARDWARE_COMPONENT *HwComponents,
IN PWSTR LayerDriver
)
{
BYTE DataBuffer[256];
ULONG LayerDriverLength;
PWSTR LayerDriverCandidate;
PWSTR LayerDriverName = NULL;
PWSTR KeyboardTypeStr = NULL;
PWSTR KeyboardSubtypeStr = NULL;
PWSTR KeyboardPnPId = NULL;
ULONG KeyboardType;
ULONG KeyboardSubtype;
NTSTATUS Status;
ULONG LineIndex;
UNICODE_STRING UnicodeString;
//
// This code is hardly depended on 'i8042prt.sys'.
// if the active driver for keyboard is not 'i8042prt.sys',
// we don't need to do this, but we write down this to registry for just in case.
//
//
// Get current keyboard layout driver name.
//
//
// from NT5, the keyword LayerDriver has been changed to
//
// "LayerDriver JPN" | "LayerDriver KOR"
//
// Since NT5 sets KeyboardType & KeyboardSubtype correctly
//
// When new LayerDriver key is opened successfully,
//
// it means system is >= NT5 and we don't need to do more.
//
Status = SpGetValueKey(ControlSetKeyHandle,
L"Services\\i8042prt\\Parameters",
LayerDriver,
sizeof(DataBuffer),
DataBuffer,
&LayerDriverLength);
if (NT_SUCCESS(Status)) {
return (STATUS_SUCCESS);
}
Status = SpGetValueKey(ControlSetKeyHandle,
L"Services\\i8042prt\\Parameters",
L"LayerDriver",
sizeof(DataBuffer),
DataBuffer,
&LayerDriverLength);
if (NT_SUCCESS(Status)) {
//
// Get pointer to registry data.
//
LayerDriverName = (PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)DataBuffer)->Data);
//
// Search driver name from txtsetup.sif.
//
for (LineIndex = 0; ; LineIndex++) {
//
// Get candidate layout driver name for this line.
//
LayerDriverCandidate = SpGetSectionLineIndex(SifHandle,szKeyboard,LineIndex,3);
if (LayerDriverCandidate == NULL) {
//
// We may reach at end of the list.
//
break;
}
//
// Compare this candidate with active layout driver.
//
if (_wcsicmp(LayerDriverName,LayerDriverCandidate) == 0) {
//
// This is what we want, Get KeyboardType and SubType from Sif.
//
KeyboardTypeStr = SpGetSectionLineIndex(SifHandle,szKeyboard,LineIndex,4);
KeyboardSubtypeStr = SpGetSectionLineIndex(SifHandle,szKeyboard,LineIndex,5);
KeyboardPnPId = SpGetSectionLineIndex(SifHandle,szKeyboard,LineIndex,6);
break;
}
}
Status = SpOpenSetValueAndClose(
ControlSetKeyHandle,
L"Services\\i8042prt\\Parameters",
LayerDriver,
REG_SZ,
LayerDriverName,
(wcslen(LayerDriverName)+1)*sizeof(WCHAR)
);
if (NT_SUCCESS(Status)) {
Status = SpDeleteValueKey(
ControlSetKeyHandle,
L"Services\\i8042prt\\Parameters",
L"LayerDriver"
);
}
}
if (KeyboardPnPId) {
//
// Save Keyboard PnP Id.
//
Status = SpOpenSetValueAndClose(
ControlSetKeyHandle,
L"Services\\i8042prt\\Parameters",
L"OverrideKeyboardIdentifier",
REG_SZ,
KeyboardPnPId,
(wcslen(KeyboardPnPId)+1)*sizeof(WCHAR)
);
}
if ((KeyboardTypeStr == NULL) || (KeyboardSubtypeStr == NULL)) {
//
// We could not find the driver from list, just use default..
//
KeyboardTypeStr = SpGetSectionKeyIndex(SifHandle,szKeyboard,L"STANDARD",4);
KeyboardSubtypeStr = SpGetSectionKeyIndex(SifHandle,szKeyboard,L"STANDARD",5);
if ((KeyboardTypeStr == NULL) || (KeyboardSubtypeStr == NULL)) {
//
// if it still has problem. set hardcodeed default (PC/AT Enhanced)...
//
KeyboardTypeStr = L"4\0";
KeyboardSubtypeStr = L"0\0";
}
}
//
// Convert the string to DWORD value.
//
RtlInitUnicodeString(&UnicodeString,KeyboardTypeStr);
RtlUnicodeStringToInteger(&UnicodeString,10,&KeyboardType);
RtlInitUnicodeString(&UnicodeString,KeyboardSubtypeStr);
RtlUnicodeStringToInteger(&UnicodeString,10,&KeyboardSubtype);
//
// Updates registry.
//
Status = SpOpenSetValueAndClose(
ControlSetKeyHandle,
L"Services\\i8042prt\\Parameters",
L"OverrideKeyboardType",
REG_DWORD,
&KeyboardType,
sizeof(ULONG)
);
if(NT_SUCCESS(Status)) {
Status = SpOpenSetValueAndClose(
ControlSetKeyHandle,
L"Services\\i8042prt\\Parameters",
L"OverrideKeyboardSubtype",
REG_DWORD,
&KeyboardSubtype,
sizeof(ULONG)
);
}
KdPrint(("KEYBOARD UPGRADE INFORMATION\n"));
KdPrint((" Current Keyboard layout = %ws\n",LayerDriverName));
KdPrint((" Upgrade keyboard Type = %d\n",KeyboardType));
KdPrint((" Upgrade keyboard Subtype = %d\n",KeyboardSubtype));
KdPrint((" Upgrade keyboard identifier = %ws\n",KeyboardPnPId));
return(Status);
}
#define KEYBOARD_LAYOUTS_PATH L"Control\\Keyboard Layouts"
#define IME_FILE_NAME L"IME file"
#define LAYOUT_TEXT_NAME L"Layout Text"
NTSTATUS
FEUpgradeKeyboardLayout(
IN HANDLE ControlSetKeyHandle,
IN PWSTR OldDefaultIMEName,
IN PWSTR NewDefaultIMEName,
IN PWSTR NewDefaultIMEText
)
{
OBJECT_ATTRIBUTES KeyRootObjA;
OBJECT_ATTRIBUTES KeyNodeObjA;
HANDLE KeyRoot;
HANDLE KeyNode;
NTSTATUS Status;
DWORD ResultLength;
UNICODE_STRING KeyboardRoot;
UNICODE_STRING KeyboardNode;
UNICODE_STRING IMEFile;
UNICODE_STRING LayoutText;
PBYTE DataBuffer[256];
WCHAR NodeKeyPath[64];
WCHAR SubKeyName[16];
ULONG EnumerateIndex = 0;
//
// Initalize "IME file" and "Layout Text".
//
RtlInitUnicodeString(&IMEFile,IME_FILE_NAME);
RtlInitUnicodeString(&LayoutText,LAYOUT_TEXT_NAME);
//
// Build Registry path for "keyboard Layouts".
//
RtlInitUnicodeString(&KeyboardRoot,KEYBOARD_LAYOUTS_PATH);
//
// Open "Keyboard Layouts" key.
//
InitializeObjectAttributes(&KeyRootObjA,
&KeyboardRoot,
OBJ_CASE_INSENSITIVE,
ControlSetKeyHandle, NULL);
Status = ZwOpenKey(&KeyRoot,KEY_ALL_ACCESS,&KeyRootObjA);
if (!NT_SUCCESS(Status)) {
KdPrint(("SPDDLANG:Fail to open (%x) (%ws)\n",Status,KeyboardRoot.Buffer));
//
// If we fail here, it might be upgrade from NT 3.1 or 3.5...
// Then just return as SUCCESS.
//
return (STATUS_SUCCESS);
}
//
// Enumerate installed keyboard layouts..
//
while (TRUE) {
Status = ZwEnumerateKey(KeyRoot,
EnumerateIndex,
KeyBasicInformation,
(PKEY_BASIC_INFORMATION)DataBuffer,
sizeof(DataBuffer),
&ResultLength);
if (!NT_SUCCESS(Status)) {
//
// we might reach end of data...
//
break;
}
//
// Initialize subkey buffer.
//
RtlZeroMemory(SubKeyName,sizeof(SubKeyName));
//
// Get subkey name..
//
RtlCopyMemory(SubKeyName,
((PKEY_BASIC_INFORMATION)DataBuffer)->Name,
((PKEY_BASIC_INFORMATION)DataBuffer)->NameLength);
//
// We know the key is everytime '8' characters...
//
if (((PKEY_BASIC_INFORMATION)DataBuffer)->NameLength != 0x10) {
SubKeyName[8] = L'\0';
}
//
// Build path for sub keys
//
wcscpy(NodeKeyPath,KEYBOARD_LAYOUTS_PATH);
KeyboardNode.Buffer = NodeKeyPath;
KeyboardNode.Length = wcslen(NodeKeyPath) * sizeof(WCHAR);
KeyboardNode.MaximumLength = sizeof(NodeKeyPath);
RtlAppendUnicodeToString(&KeyboardNode,L"\\");
RtlAppendUnicodeToString(&KeyboardNode,SubKeyName);
KdPrint(("SPDDLANG:SubKey = %ws\n",KeyboardNode.Buffer));
//
// Open its subkey...
//
InitializeObjectAttributes(&KeyNodeObjA,
&KeyboardNode,
OBJ_CASE_INSENSITIVE,
ControlSetKeyHandle, NULL);
Status = ZwOpenKey(&KeyNode,KEY_ALL_ACCESS,&KeyNodeObjA);
if (!NT_SUCCESS(Status)) {
KdPrint(("SPDDLANG:Fail to open (%x) (%ws)\n",Status,KeyboardNode.Buffer));
//
// We should not encounter error, because the key should be exist...
// Anyway, continue to enumerate...
//
EnumerateIndex++;
continue;
}
//
// Find "IME file" value key.
//
Status = ZwQueryValueKey(KeyNode,
&IMEFile,
KeyValuePartialInformation,
(PKEY_VALUE_PARTIAL_INFORMATION)DataBuffer,
sizeof(DataBuffer),
&ResultLength);
if (NT_SUCCESS(Status)) {
PWSTR IMEFileName = (PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)DataBuffer)->Data);
//
// Upcases the file name..
//
_wcsupr(IMEFileName);
if (wcsstr(IMEFileName,L".EXE")) {
KdPrint(("SPDDLANG:Delete IME file = %ws\n",IMEFileName));
//
// This is Old "EXE" type IME file, let it deleted.
//
ZwDeleteKey(KeyNode);
//
// Adjust enumeration number...
//
EnumerateIndex--;
} else {
KdPrint(("SPDDLANG:Keep IME file = %ws\n",IMEFileName));
//
// This might be New "DLL" type IME file. let it be as is..
//
if (OldDefaultIMEName && NewDefaultIMEName) {
//
// if this entry is for 3.x default IME. let it upgrade to new one.
//
if (wcsstr(IMEFileName,OldDefaultIMEName)) {
KdPrint(("SPDDLANG:Upgrade IME file = %ws to %ws\n",
IMEFileName,NewDefaultIMEName));
//
// Upgrade IME.
//
Status = ZwSetValueKey(KeyNode,
&IMEFile,
0,
REG_SZ,
(PVOID) NewDefaultIMEName,
(wcslen(NewDefaultIMEName)+1)*sizeof(WCHAR));
//
// Upgrade "Layout Text" also ?
//
if (NewDefaultIMEText) {
Status = ZwSetValueKey(KeyNode,
&LayoutText,
0,
REG_SZ,
(PVOID) NewDefaultIMEText,
(wcslen(NewDefaultIMEText)+1)*sizeof(WCHAR));
}
}
}
}
} else {
KdPrint(("SPDDLANG:no IME file\n"));
//
// This layout seems like does not have any IME, just leave it there.
//
Status = STATUS_SUCCESS;
}
ZwClose(KeyNode);
//
// Enumerate next..
//
EnumerateIndex++;
}
ZwClose(KeyRoot);
KdPrint(("SPDDLANG:Retcode = %x\n",Status));
if (Status == STATUS_NO_MORE_ENTRIES) {
//
// We enumerate all of sub keys...
//
Status = STATUS_SUCCESS;
}
return (Status);
}
#define DOSDEV_REG_PATH L"Control\\Session Manager\\DOS Devices"
NTSTATUS
FEUpgradeRemoveMO(
IN HANDLE ControlSetKeyHandle)
{
OBJECT_ATTRIBUTES KeyRootObjA;
HANDLE KeyRoot;
NTSTATUS Status;
DWORD ResultLength;
UNICODE_STRING DosDevice;
UNICODE_STRING UnicodeValueName;
BYTE DataBuffer[512];
WCHAR NodeKeyPath[64];
WCHAR ValueName[256];
PKEY_VALUE_FULL_INFORMATION ValueInfo;
PKEY_VALUE_PARTIAL_INFORMATION DataInfo;
ULONG EnumerateIndex = 0;
//
// Build Registry path for "Control\\Session Manager\\DOS Devices".
//
RtlInitUnicodeString(&DosDevice,DOSDEV_REG_PATH);
//
// Open "DOS Devices" key.
//
InitializeObjectAttributes(&KeyRootObjA,
&DosDevice,
OBJ_CASE_INSENSITIVE,
ControlSetKeyHandle, NULL);
Status = ZwOpenKey(&KeyRoot,KEY_ALL_ACCESS,&KeyRootObjA);
if (!NT_SUCCESS(Status)) {
KdPrint(("SPDDLANG:Fail to open (%x) (%ws)\n",Status,DosDevice.Buffer));
//
// If we fail here, it might be upgrade from NT 3.1 or 3.5...
// Then just return as SUCCESS.
//
return (STATUS_SUCCESS);
}
ValueInfo = (PKEY_VALUE_FULL_INFORMATION) DataBuffer;
//
// Enumerate all installed devices..
//
while (TRUE) {
Status = ZwEnumerateValueKey(KeyRoot,
EnumerateIndex,
KeyValueFullInformation,
DataBuffer,
sizeof(DataBuffer),
&ResultLength);
if (!NT_SUCCESS(Status)) {
//
// we might reach end of data...
//
break;
}
//
// Get subkey name..
//
RtlCopyMemory((PBYTE)ValueName,
ValueInfo->Name,
ValueInfo->NameLength);
ValueName[ValueInfo->NameLength / sizeof(WCHAR)] = UNICODE_NULL;
RtlInitUnicodeString(&UnicodeValueName,ValueName);
Status = ZwQueryValueKey(KeyRoot,
&UnicodeValueName,
KeyValuePartialInformation,
DataBuffer,
sizeof(DataBuffer),
&ResultLength);
DataInfo = (PKEY_VALUE_PARTIAL_INFORMATION) DataBuffer;
if (NT_SUCCESS(Status)) {
PWSTR PathData = (PWSTR)(DataInfo->Data);
//
// Upcases the file name..
//
_wcsupr(PathData);
if (wcsstr(PathData,L"\\OPTICALDISK")) {
KdPrint(("SPDDLANG:Delete MO %ws = %ws\n",ValueName,PathData));
Status = SpDeleteValueKey(
ControlSetKeyHandle,
DOSDEV_REG_PATH,
ValueName
);
}
}
//
// Enumerate next..
//
EnumerateIndex++;
}
ZwClose(KeyRoot);
KdPrint(("SPDDLANG:Retcode = %x\n",Status));
if (Status == STATUS_NO_MORE_ENTRIES) {
//
// We enumerate all of sub keys...
//
Status = STATUS_SUCCESS;
}
return (Status);
}