windows-nt/Source/XPSP1/NT/mergedcomponents/advapi32/win31io.c
2020-09-26 16:20:57 +08:00

1477 lines
48 KiB
C

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
win31io.c
Abstract:
This file contains Win 3.1 Inter-Operability functions.
Author:
Steve Wood (stevewo) 21-Feb-1993
Revision History:
--*/
#include "advapi.h"
#include <stdio.h>
#include <winbasep.h>
#include "win31io.h"
#define EVENTLOG_SOURCE "Windows 3.1 Migration"
BOOL
WaitForEventLogToStart( VOID );
#define SIZE_OF_TOKEN_INFORMATION \
sizeof( TOKEN_USER ) \
+ sizeof( SID ) \
+ sizeof( ULONG ) * SID_MAX_SUB_AUTHORITIES
typedef struct _WIN31IO_STATE {
HANDLE EventLog;
HANDLE SoftwareRoot;
HANDLE UserRoot;
HANDLE Win31IOKey;
BOOL QueryOnly;
PWSTR WindowsPath;
PWSTR FileNamePart;
PWSTR WorkBuffer;
ULONG cchWorkBuffer;
PWIN31IO_STATUS_CALLBACK StatusCallback;
PVOID CallbackParameter;
WCHAR szWindowsDirectory[ MAX_PATH ];
PSID UserSid;
UCHAR TokenInformation[ SIZE_OF_TOKEN_INFORMATION ];
WCHAR QueryBuffer[ 64 ];
} WIN31IO_STATE, *PWIN31IO_STATE;
HANDLE
OpenCreateKey(
IN HANDLE Root,
IN PWSTR Path,
IN BOOL WriteAccess
);
BOOL
SnapShotWin31IniFilesToRegistry(
IN OUT PWIN31IO_STATE State
);
BOOL
SnapShotWin31GroupsToRegistry(
IN OUT PWIN31IO_STATE State
);
BOOL
SnapShotWin31RegDatToRegistry(
IN OUT PWIN31IO_STATE State
);
BOOL
InitializeWin31State(
IN WIN31IO_EVENT EventType,
OUT PWIN31IO_STATE State
);
VOID
TerminateWin31State(
IN WIN31IO_EVENT EventType,
IN OUT PWIN31IO_STATE State
);
BOOL
InitializeWin31State(
IN WIN31IO_EVENT EventType,
OUT PWIN31IO_STATE State
)
{
NTSTATUS Status;
ULONG cch;
HANDLE TokenHandle;
ULONG ReturnLength;
memset( State, 0, sizeof( *State ) );
cch = GetWindowsDirectoryW( State->szWindowsDirectory,
sizeof( State->szWindowsDirectory ) / sizeof (WCHAR)
);
State->WindowsPath = State->szWindowsDirectory;
State->FileNamePart = State->WindowsPath + cch;
*State->FileNamePart++ = OBJ_NAME_PATH_SEPARATOR;
if (EventType == Win31SystemStartEvent) {
State->SoftwareRoot = OpenCreateKey( NULL,
L"\\Registry\\Machine\\Software",
FALSE
);
if (State->SoftwareRoot == NULL) {
return FALSE;
}
}
else {
Status = RtlOpenCurrentUser( GENERIC_READ, &State->UserRoot );
if (!NT_SUCCESS( Status )) {
BaseSetLastNTError( Status );
return FALSE;
}
if (OpenThreadToken( GetCurrentThread(),
TOKEN_READ,
TRUE,
&TokenHandle
) ||
OpenProcessToken( GetCurrentProcess(),
TOKEN_READ,
&TokenHandle
)
) {
if (GetTokenInformation( TokenHandle,
TokenUser,
&State->TokenInformation,
sizeof( State->TokenInformation ),
&ReturnLength
)
) {
PTOKEN_USER UserToken = (PTOKEN_USER)&State->TokenInformation;
State->UserSid = UserToken->User.Sid;
}
CloseHandle( TokenHandle );
}
}
State->Win31IOKey = OpenCreateKey( EventType == Win31SystemStartEvent ?
State->SoftwareRoot : State->UserRoot,
L"Windows 3.1 Migration Status",
TRUE
);
if (State->Win31IOKey == NULL) {
if (State->SoftwareRoot != NULL) {
NtClose( State->SoftwareRoot );
}
if (State->UserRoot != NULL) {
NtClose( State->UserRoot );
}
if (State->EventLog != NULL) {
DeregisterEventSource( State->EventLog );
}
return FALSE;
}
else {
return TRUE;
}
return TRUE;
}
VOID
TerminateWin31State(
IN WIN31IO_EVENT EventType,
IN OUT PWIN31IO_STATE State
)
{
if (State->Win31IOKey != NULL) {
NtClose( State->Win31IOKey );
}
if (State->SoftwareRoot != NULL) {
NtClose( State->SoftwareRoot );
}
if (State->UserRoot != NULL) {
NtClose( State->UserRoot );
}
if (State->EventLog != NULL && State->EventLog != INVALID_HANDLE_VALUE) {
DeregisterEventSource( State->EventLog );
}
return;
}
#define MAX_EVENT_STRINGS 8
VOID
ReportWin31IOEvent(
IN PWIN31IO_STATE State,
IN WORD EventType,
IN DWORD EventId,
IN DWORD SizeOfRawData,
IN PVOID RawData,
IN DWORD NumberOfStrings,
...
)
{
va_list arglist;
ULONG i;
PWSTR Strings[ MAX_EVENT_STRINGS ];
va_start( arglist, NumberOfStrings );
if (NumberOfStrings > MAX_EVENT_STRINGS) {
NumberOfStrings = MAX_EVENT_STRINGS;
}
for (i=0; i<NumberOfStrings; i++) {
Strings[ i ] = va_arg( arglist, PWSTR );
}
if (State->EventLog == NULL) {
State->EventLog = RegisterEventSource( NULL, EVENTLOG_SOURCE );
if (State->EventLog == NULL) {
if (WaitForEventLogToStart()) {
State->EventLog = RegisterEventSource( NULL, EVENTLOG_SOURCE );
}
if (State->EventLog == NULL) {
KdPrint(( "WIN31IO: RegisterEventSource( %s ) failed - %u\n", EVENTLOG_SOURCE, GetLastError() ));
State->EventLog = INVALID_HANDLE_VALUE;
return;
}
}
}
if (State->EventLog != INVALID_HANDLE_VALUE) {
if (!ReportEventW( State->EventLog,
EventType,
0, // event category
EventId,
State->UserSid,
(WORD)NumberOfStrings,
SizeOfRawData,
Strings,
RawData
)
) {
KdPrint(( "WIN31IO: ReportEvent( %u ) failed - %u\n", EventId, GetLastError() ));
}
}
}
int
Win31IOExceptionHandler(
IN DWORD ExceptionCode,
IN PEXCEPTION_POINTERS ExceptionInfo,
IN OUT PWIN31IO_STATE State
);
int
Win31IOExceptionHandler(
IN DWORD ExceptionCode,
IN PEXCEPTION_POINTERS ExceptionInfo,
IN OUT PWIN31IO_STATE State
)
{
KdPrint(( "WIN31IO: Unexpected exception %08x at %08x referencing %08x\n",
ExceptionInfo->ExceptionRecord->ExceptionCode,
ExceptionInfo->ExceptionRecord->ExceptionAddress,
ExceptionInfo->ExceptionRecord->ExceptionInformation[ 1 ]
));
//
// Unexpected exception. Log the event with the exception record
// so we can figure it out later.
//
ReportWin31IOEvent( State,
EVENTLOG_ERROR_TYPE,
WIN31IO_EVENT_EXCEPTION,
sizeof( *(ExceptionInfo->ExceptionRecord) ),
ExceptionInfo->ExceptionRecord,
0
);
return EXCEPTION_EXECUTE_HANDLER;
}
DWORD
WINAPI
QueryWindows31FilesMigration(
IN WIN31IO_EVENT EventType
)
{
DWORD Flags;
WIN31IO_STATE State;
if (EventType == Win31LogoffEvent) {
return 0;
}
if (!InitializeWin31State( EventType, &State )) {
return 0;
}
State.QueryOnly = TRUE;
State.WorkBuffer = State.QueryBuffer;
State.cchWorkBuffer = sizeof( State.QueryBuffer ) / sizeof( WCHAR );
Flags = 0;
try {
try {
if (EventType == Win31SystemStartEvent) {
if (SnapShotWin31IniFilesToRegistry( &State )) {
Flags |= WIN31_MIGRATE_INIFILES;
}
if (SnapShotWin31RegDatToRegistry( &State )) {
Flags |= WIN31_MIGRATE_REGDAT;
}
}
else {
if (SnapShotWin31IniFilesToRegistry( &State )) {
Flags |= WIN31_MIGRATE_INIFILES;
}
if (SnapShotWin31GroupsToRegistry( &State )) {
Flags |= WIN31_MIGRATE_GROUPS;
}
}
}
except( Win31IOExceptionHandler( GetExceptionCode(),
GetExceptionInformation(),
&State
)
) {
BaseSetLastNTError( GetExceptionCode() );
}
}
finally {
TerminateWin31State( EventType, &State );
}
return Flags;
}
BOOL
WINAPI
SynchronizeWindows31FilesAndWindowsNTRegistry(
IN WIN31IO_EVENT EventType,
IN DWORD Flags,
IN PWIN31IO_STATUS_CALLBACK StatusCallback,
IN PVOID CallbackParameter
)
{
BOOL Result;
VIRTUAL_BUFFER Buffer;
ULONG cch;
WIN31IO_STATE State;
if (Flags == 0 || EventType == Win31LogoffEvent) {
return TRUE;
}
if (!InitializeWin31State( EventType, &State )) {
return TRUE;
}
State.QueryOnly = FALSE;
State.StatusCallback = StatusCallback;
State.CallbackParameter = CallbackParameter;
Result = FALSE;
try {
try {
try {
cch = ((64 * 1024) / sizeof( WCHAR )) - 1;
if (!CreateVirtualBuffer( &Buffer, cch * sizeof( WCHAR ), cch * sizeof( WCHAR ) )) {
leave;
}
State.WorkBuffer = Buffer.Base;
State.cchWorkBuffer = cch;
Result = TRUE;
if (EventType == Win31SystemStartEvent) {
if (Flags & WIN31_MIGRATE_INIFILES) {
Result &= SnapShotWin31IniFilesToRegistry( &State );
}
if (Flags & WIN31_MIGRATE_REGDAT) {
Result &= SnapShotWin31RegDatToRegistry( &State );
}
}
else {
if (Flags & WIN31_MIGRATE_INIFILES) {
Result &= SnapShotWin31IniFilesToRegistry( &State );
}
if (Flags & WIN31_MIGRATE_GROUPS) {
Result &= SnapShotWin31GroupsToRegistry( &State );
}
}
}
except( VirtualBufferExceptionHandler( GetExceptionCode(),
GetExceptionInformation(),
&Buffer
)
) {
if (GetExceptionCode() == STATUS_ACCESS_VIOLATION) {
BaseSetLastNTError( STATUS_NO_MEMORY );
}
else {
BaseSetLastNTError( GetExceptionCode() );
}
Result = FALSE;
}
}
except( Win31IOExceptionHandler( GetExceptionCode(),
GetExceptionInformation(),
&State
)
) {
BaseSetLastNTError( GetExceptionCode() );
Result = FALSE;
}
}
finally {
TerminateWin31State( EventType, &State );
FreeVirtualBuffer( &Buffer );
}
return Result;
}
BOOL
SnapShotWin31IniFileKey(
IN OUT PWIN31IO_STATE State,
IN PWSTR TempFileName,
IN PWSTR FileName,
IN PWSTR ApplicationName,
IN PWSTR KeyName
);
BOOL
SnapShotWin31IniFileSection(
IN OUT PWIN31IO_STATE State,
IN PWSTR TempFileName,
IN PWSTR FileName,
IN PWSTR ApplicationName
);
BOOL
SnapShotWin31IniFileSections(
IN OUT PWIN31IO_STATE State,
IN PWSTR TempFileName,
IN PWSTR FileName
);
BOOL
SnapShotWin31IniFilesToRegistry(
IN OUT PWIN31IO_STATE State
)
{
BOOL Result;
PWSTR s, s1, FileName, ApplicationName, KeyName;
ULONG n;
PWSTR CurrentFileName;
WCHAR Win31IniFileName[ MAX_PATH ];
WCHAR TempIniFileName[ MAX_PATH ];
HANDLE FindHandle;
WIN32_FIND_DATAW FindFileData;
HANDLE MigrationKey, Key;
ULONG cchBufferUsed;
MigrationKey = OpenCreateKey( State->Win31IOKey, L"IniFiles", !State->QueryOnly );
if (State->QueryOnly) {
if (MigrationKey != NULL) {
NtClose( MigrationKey );
return FALSE;
}
}
else {
if (MigrationKey == NULL) {
return FALSE;
}
}
Result = FALSE;
wcscpy( State->FileNamePart, L"system.ini" );
FindHandle = FindFirstFileW( State->WindowsPath, &FindFileData );
if (FindHandle != INVALID_HANDLE_VALUE) {
FindClose( FindHandle );
if (FindFileData.nFileSizeLow > 1024) {
Result = TRUE;
}
}
if (!Result || State->QueryOnly) {
if (MigrationKey == NULL) {
MigrationKey = OpenCreateKey( State->Win31IOKey, L"IniFiles", TRUE );
}
if (MigrationKey != NULL) {
NtClose( MigrationKey );
}
return Result;
}
cchBufferUsed = 0;
if (State->UserRoot != NULL) {
Result = QueryWin31IniFilesMappedToRegistry( WIN31_INIFILES_MAPPED_TO_USER,
State->WorkBuffer,
State->cchWorkBuffer,
&cchBufferUsed
);
}
else {
Result = QueryWin31IniFilesMappedToRegistry( WIN31_INIFILES_MAPPED_TO_SYSTEM,
State->WorkBuffer,
State->cchWorkBuffer,
&cchBufferUsed
);
}
if (Result) {
s = State->WorkBuffer;
State->WorkBuffer += cchBufferUsed;
State->cchWorkBuffer -= cchBufferUsed;
CurrentFileName = NULL;
TempIniFileName[ 0 ] = UNICODE_NULL;
do {
FileName = (PWSTR)((*s == UNICODE_NULL) ? NULL : s);
while (*s++) {
;
}
ApplicationName = (PWSTR)((*s == UNICODE_NULL) ? NULL : s);
while (*s++) {
;
}
KeyName = (PWSTR)((*s == UNICODE_NULL) ? NULL : s);
while (*s++) {
;
}
if (FileName) {
if (!CurrentFileName || _wcsicmp( FileName, CurrentFileName )) {
if (TempIniFileName[ 0 ] != UNICODE_NULL) {
WritePrivateProfileStringW( NULL, NULL, NULL, L"" );
if (!DeleteFileW( TempIniFileName )) {
KdPrint(( "WIN31IO: DeleteFile( %ws ) - failed (%u)\n",
TempIniFileName,
GetLastError()
));
}
TempIniFileName[ 0 ] = UNICODE_NULL;
}
CurrentFileName = NULL;
GetWindowsDirectoryW( Win31IniFileName, sizeof( Win31IniFileName ) / sizeof (WCHAR) );
wcscat( Win31IniFileName, L"\\" );
wcscat( Win31IniFileName, FileName );
wcscpy( TempIniFileName, Win31IniFileName );
_wcslwr( TempIniFileName );
s1 = wcsstr( TempIniFileName, L".ini" );
if (!s1) {
s1 = wcschr( TempIniFileName, UNICODE_NULL );
if (s1[-1] == L'.') {
s1--;
}
}
n = 0;
while (n < 1000) {
swprintf( s1, L".%03u", n++ );
if (CopyFileW( Win31IniFileName, TempIniFileName, TRUE )) {
if (State->StatusCallback != NULL) {
(State->StatusCallback)( FileName, State->CallbackParameter );
}
Key = OpenCreateKey( MigrationKey, FileName, TRUE );
if (Key != NULL) {
NtClose( Key );
}
CurrentFileName = FileName;
break;
}
else
if (GetLastError() != ERROR_FILE_EXISTS) {
if (GetLastError() != ERROR_FILE_NOT_FOUND) {
KdPrint(("WIN31IO: CopyFile( %ws, %ws ) failed - %u\n",
Win31IniFileName,
TempIniFileName,
GetLastError()
));
}
break;
}
}
if (CurrentFileName == NULL) {
TempIniFileName[ 0 ] = UNICODE_NULL;
CurrentFileName = FileName;
}
}
if (TempIniFileName[ 0 ] != UNICODE_NULL) {
if (ApplicationName) {
if (KeyName) {
if (SnapShotWin31IniFileKey( State,
TempIniFileName,
FileName,
ApplicationName,
KeyName
)
) {
ReportWin31IOEvent( State,
EVENTLOG_INFORMATION_TYPE,
WIN31IO_EVENT_MIGRATE_INI_VARIABLE,
0,
NULL,
3,
KeyName,
ApplicationName,
FileName
);
}
else {
ReportWin31IOEvent( State,
EVENTLOG_WARNING_TYPE,
WIN31IO_EVENT_MIGRATE_INI_VARIABLE_FAILED,
0,
NULL,
3,
KeyName,
ApplicationName,
FileName
);
}
}
else {
if (SnapShotWin31IniFileSection( State,
TempIniFileName,
FileName,
ApplicationName
)
) {
ReportWin31IOEvent( State,
EVENTLOG_INFORMATION_TYPE,
WIN31IO_EVENT_MIGRATE_INI_SECTION,
0,
NULL,
2,
ApplicationName,
FileName
);
}
else {
ReportWin31IOEvent( State,
EVENTLOG_WARNING_TYPE,
WIN31IO_EVENT_MIGRATE_INI_SECTION_FAILED,
0,
NULL,
2,
ApplicationName,
FileName
);
}
}
}
else {
if (SnapShotWin31IniFileSections( State,
TempIniFileName,
FileName
)
) {
ReportWin31IOEvent( State,
EVENTLOG_INFORMATION_TYPE,
WIN31IO_EVENT_MIGRATE_INI_FILE,
0,
NULL,
1,
FileName
);
}
else {
ReportWin31IOEvent( State,
EVENTLOG_WARNING_TYPE,
WIN31IO_EVENT_MIGRATE_INI_FILE_FAILED,
0,
NULL,
1,
FileName
);
}
}
}
}
}
while (*s != UNICODE_NULL);
State->WorkBuffer -= cchBufferUsed;
State->cchWorkBuffer += cchBufferUsed;
}
if (TempIniFileName[ 0 ] != UNICODE_NULL) {
WritePrivateProfileStringW( NULL, NULL, NULL, L"" );
if (!DeleteFileW( TempIniFileName )) {
KdPrint(( "WIN31IO: DeleteFile( %ws ) - failed (%u)\n",
TempIniFileName,
GetLastError()
));
}
}
if (MigrationKey != NULL) {
NtClose( MigrationKey );
}
return Result;
}
BOOL
SnapShotWin31IniFileKey(
IN OUT PWIN31IO_STATE State,
IN PWSTR TempFileName,
IN PWSTR FileName,
IN PWSTR ApplicationName,
IN PWSTR KeyName
)
{
ULONG cch;
cch = GetPrivateProfileStringW( ApplicationName,
KeyName,
NULL,
State->WorkBuffer,
State->cchWorkBuffer,
TempFileName
);
if (cch != 0) {
if (WritePrivateProfileStringW( ApplicationName,
KeyName,
State->WorkBuffer,
FileName
)
) {
return TRUE;
}
else {
KdPrint(( "WIN31IO: Copy to %ws [%ws].%ws == %ws (failed - %u)\n", FileName, ApplicationName, KeyName, State->WorkBuffer, GetLastError() ));
return FALSE;
}
}
else {
return TRUE;
}
}
BOOL
SnapShotWin31IniFileSection(
IN OUT PWIN31IO_STATE State,
IN PWSTR TempFileName,
IN PWSTR FileName,
IN PWSTR ApplicationName
)
{
BOOL Result;
PWSTR KeyName;
ULONG cch;
Result = TRUE;
cch = GetPrivateProfileStringW( ApplicationName,
NULL,
NULL,
State->WorkBuffer,
State->cchWorkBuffer,
TempFileName
);
if (cch != 0) {
KeyName = State->WorkBuffer;
cch += 1; // Account for extra null
State->WorkBuffer += cch;
State->cchWorkBuffer -= cch;
while (*KeyName != UNICODE_NULL) {
Result &= SnapShotWin31IniFileKey( State,
TempFileName,
FileName,
ApplicationName,
KeyName
);
while (*KeyName++) {
;
}
}
State->WorkBuffer -= cch;
State->cchWorkBuffer += cch;
}
return Result;
}
BOOL
SnapShotWin31IniFileSections(
IN OUT PWIN31IO_STATE State,
IN PWSTR TempFileName,
IN PWSTR FileName
)
{
BOOL Result;
PWSTR ApplicationName;
ULONG cch;
Result = TRUE;
cch = GetPrivateProfileStringW( NULL,
NULL,
NULL,
State->WorkBuffer,
State->cchWorkBuffer,
TempFileName
);
if (cch != 0) {
ApplicationName = State->WorkBuffer;
cch += 1; // Account for extra null
State->WorkBuffer += cch;
State->cchWorkBuffer -= cch;
while (*ApplicationName != UNICODE_NULL) {
Result &= SnapShotWin31IniFileSection( State,
TempFileName,
FileName,
ApplicationName
);
while (*ApplicationName++) {
;
}
}
State->WorkBuffer -= cch;
State->cchWorkBuffer += cch;
}
return Result;
}
BOOL
ConvertWindows31GroupsToRegistry(
IN OUT PWIN31IO_STATE State,
IN HANDLE MigrationKey,
IN HANDLE CommonGroupsKey,
IN HANDLE PersonalGroupsKey,
IN PWSTR IniFileName,
IN PWSTR GroupNames,
IN ULONG nGroupNames
);
BOOL
SnapShotWin31GroupsToRegistry(
IN OUT PWIN31IO_STATE State
)
{
BOOL Result;
PWSTR GroupNames, s;
DWORD nGroupNames, cchGroupNames;
HANDLE MigrationKey, PersonalGroupsKey, CommonGroupsKey;
MigrationKey = OpenCreateKey( State->Win31IOKey, L"Groups", !State->QueryOnly );
if (State->QueryOnly) {
if (MigrationKey != NULL) {
NtClose( MigrationKey );
return FALSE;
}
}
else {
if (MigrationKey == NULL) {
return FALSE;
}
}
Result = FALSE;
wcscpy( State->FileNamePart, L"progman.ini" );
if (GetFileAttributesW( State->WindowsPath ) != 0xFFFFFFFF) {
cchGroupNames = GetPrivateProfileStringW( L"Groups",
NULL,
L"",
State->WorkBuffer,
State->cchWorkBuffer,
State->WindowsPath
);
if (cchGroupNames != 0) {
Result = TRUE;
}
}
if (!Result || State->QueryOnly) {
if (MigrationKey == NULL) {
MigrationKey = OpenCreateKey( State->Win31IOKey, L"Groups", TRUE );
}
if (MigrationKey != NULL) {
NtClose( MigrationKey );
}
return Result;
}
if (cchGroupNames) {
PersonalGroupsKey = OpenCreateKey( State->UserRoot,
L"UNICODE Program Groups",
!State->QueryOnly
);
if (PersonalGroupsKey == NULL) {
if (MigrationKey != NULL) {
NtClose( MigrationKey );
}
return FALSE;
}
CommonGroupsKey = OpenCreateKey( NULL,
L"\\Registry\\Machine\\Software\\Program Groups",
FALSE
);
GroupNames = s = State->WorkBuffer;
nGroupNames = 0;
while (*s) {
while (*s++) {
;
}
nGroupNames += 1;
}
State->WorkBuffer = s + 1;
State->cchWorkBuffer -= cchGroupNames + 1;
ConvertWindows31GroupsToRegistry( State,
MigrationKey,
CommonGroupsKey,
PersonalGroupsKey,
State->WindowsPath,
GroupNames,
nGroupNames
);
State->WorkBuffer = GroupNames,
State->cchWorkBuffer += cchGroupNames + 1;
NtClose( PersonalGroupsKey );
if (CommonGroupsKey != NULL) {
NtClose( CommonGroupsKey );
}
}
if (MigrationKey != NULL) {
NtClose( MigrationKey );
}
return TRUE;
}
BOOL
ConvertWindows31GroupsToRegistry(
IN OUT PWIN31IO_STATE State,
IN HANDLE MigrationKey,
IN HANDLE CommonGroupsKey,
IN HANDLE PersonalGroupsKey,
IN PWSTR IniFileName,
IN PWSTR GroupNames,
IN ULONG nGroupNames
)
{
BOOL Result;
NTSTATUS Status;
PGROUP_DEF16 Group16;
PGROUP_DEF Group32;
UNICODE_STRING Group32Name;
PWSTR Group16PathName;
PWSTR Group16FileName;
PWSTR s;
ANSI_STRING AnsiString;
ULONG NumberOfPersonalGroupNames;
ULONG OldNumberOfPersonalGroupNames;
HANDLE GroupNamesKey, SettingsKey, Key;
NumberOfPersonalGroupNames = QueryNumberOfPersonalGroupNames( State->UserRoot,
&GroupNamesKey,
&SettingsKey
);
OldNumberOfPersonalGroupNames = NumberOfPersonalGroupNames;
Result = TRUE;
while (*GroupNames) {
//
// Get the group file (.grp) name
//
if (GetPrivateProfileStringW( L"Groups",
GroupNames,
L"",
State->WorkBuffer,
State->cchWorkBuffer,
IniFileName
)
) {
Group16PathName = State->WorkBuffer;
Group16 = LoadGroup16( Group16PathName );
if (Group16 != NULL) {
Group16FileName = Group16PathName + wcslen( Group16PathName );
while (Group16FileName > Group16PathName) {
if (Group16FileName[ -1 ] == OBJ_NAME_PATH_SEPARATOR) {
break;
}
Group16FileName -= 1;
}
//
// Get the group name.
//
if (Group16->pName == 0) {
RtlInitUnicodeString( &Group32Name, Group16FileName );
Status = STATUS_SUCCESS;
}
else {
RtlInitAnsiString( &AnsiString, (PSZ)PTR( Group16, Group16->pName ) );
Status = RtlAnsiStringToUnicodeString( &Group32Name, &AnsiString, TRUE );
s = Group32Name.Buffer;
while (*s) {
if (*s == OBJ_NAME_PATH_SEPARATOR) {
*s = L'/';
}
s += 1;
}
}
if (NT_SUCCESS( Status )) {
if (DoesExistGroup( PersonalGroupsKey, Group32Name.Buffer )) {
ReportWin31IOEvent( State,
EVENTLOG_INFORMATION_TYPE,
WIN31IO_EVENT_MIGRATE_GROUP_EXISTS,
0,
NULL,
2,
Group16PathName,
Group32Name.Buffer
);
}
else
if (DoesExistGroup( CommonGroupsKey, Group32Name.Buffer )) {
ReportWin31IOEvent( State,
EVENTLOG_INFORMATION_TYPE,
WIN31IO_EVENT_MIGRATE_GROUP_EXISTS,
0,
NULL,
2,
Group16PathName,
Group32Name.Buffer
);
}
else {
// DumpGroup16( State->WorkBuffer, Group16 );
Group32 = CreateGroupFromGroup16( AnsiString.Buffer, Group16 );
if (Group32 != NULL) {
if (Group32 == (PGROUP_DEF)-1) {
ReportWin31IOEvent( State,
EVENTLOG_WARNING_TYPE,
WIN31IO_EVENT_MIGRATE_GROUP_FAILED4,
0,
NULL,
1,
Group32Name.Buffer
);
Group32 = NULL;
}
else {
// DumpGroup( Group32Name.Buffer, Group32 );
if (!SaveGroup( PersonalGroupsKey,
Group32Name.Buffer,
Group32
)
) {
ReportWin31IOEvent( State,
EVENTLOG_WARNING_TYPE,
WIN31IO_EVENT_MIGRATE_GROUP_FAILED,
0,
NULL,
1,
Group32Name.Buffer
);
}
else
if (!NewPersonalGroupName( GroupNamesKey,
Group32Name.Buffer,
NumberOfPersonalGroupNames+1
)
) {
DeleteGroup( PersonalGroupsKey, Group32Name.Buffer );
ReportWin31IOEvent( State,
EVENTLOG_WARNING_TYPE,
WIN31IO_EVENT_MIGRATE_GROUP_FAILED,
0,
NULL,
1,
Group32Name.Buffer
);
}
else {
if (State->StatusCallback != NULL) {
(State->StatusCallback)( Group16FileName, State->CallbackParameter );
}
ReportWin31IOEvent( State,
EVENTLOG_INFORMATION_TYPE,
WIN31IO_EVENT_MIGRATE_GROUP,
0,
NULL,
1,
Group32Name.Buffer
);
NumberOfPersonalGroupNames += 1;
Key = OpenCreateKey( MigrationKey, Group16FileName, TRUE );
if (Key != NULL) {
NtClose( Key );
}
else {
KdPrint(("WIN31IO: (3)Unable to create sub migration key for %ws (%u)\n", State->WorkBuffer, GetLastError() ));
}
}
UnloadGroup( Group32 );
}
}
else {
WCHAR ErrorCode[ 32 ];
_snwprintf( ErrorCode,
sizeof( ErrorCode ) / sizeof( WCHAR ),
L"%u",
GetLastError()
);
ReportWin31IOEvent( State,
EVENTLOG_WARNING_TYPE,
WIN31IO_EVENT_MIGRATE_GROUP_FAILED1,
0,
NULL,
2,
State->WorkBuffer,
ErrorCode
);
}
}
RtlFreeUnicodeString( &Group32Name );
}
UnloadGroup16( Group16 );
}
else {
WCHAR ErrorCode[ 32 ];
_snwprintf( ErrorCode,
sizeof( ErrorCode ) / sizeof( WCHAR ),
L"%u",
GetLastError()
);
ReportWin31IOEvent( State,
EVENTLOG_WARNING_TYPE,
WIN31IO_EVENT_MIGRATE_GROUP_FAILED1,
0,
NULL,
2,
State->WorkBuffer,
ErrorCode
);
}
}
else {
ReportWin31IOEvent( State,
EVENTLOG_WARNING_TYPE,
WIN31IO_EVENT_MIGRATE_GROUP_FAILED2,
0,
NULL,
2,
IniFileName,
GroupNames
);
}
while (*GroupNames++) {
;
}
}
if (OldNumberOfPersonalGroupNames != NumberOfPersonalGroupNames) {
UNICODE_STRING ValueName;
ULONG ValueData = TRUE;
RtlInitUnicodeString( &ValueName, L"InitialArrange" );
Status = NtSetValueKey( SettingsKey,
&ValueName,
0,
REG_DWORD,
&ValueData,
sizeof( ValueData )
);
#if DBG
if (!NT_SUCCESS( Status )) {
KdPrint(( "WIN31IO: Unable to set value of %wZ - Status == %x\n", &ValueName, Status ));
}
#endif
}
NtClose( SettingsKey );
NtClose( GroupNamesKey );
return Result;
}
BOOL
SnapShotWin31RegDatToRegistry(
IN OUT PWIN31IO_STATE State
)
{
BOOL Result;
HANDLE MigrationKey;
PREG_HEADER16 RegDat16;
MigrationKey = OpenCreateKey( State->Win31IOKey, L"REG.DAT", !State->QueryOnly );
if (State->QueryOnly) {
if (MigrationKey != NULL) {
NtClose( MigrationKey );
return FALSE;
}
}
else {
if (MigrationKey == NULL) {
return FALSE;
}
}
Result = FALSE;
wcscpy( State->FileNamePart, L"reg.dat" );
if (GetFileAttributesW( State->WindowsPath ) != 0xFFFFFFFF) {
Result = TRUE;
}
if (!Result || State->QueryOnly) {
if (MigrationKey == NULL) {
MigrationKey = OpenCreateKey( State->Win31IOKey, L"REG.DAT", TRUE );
}
if (MigrationKey != NULL) {
NtClose( MigrationKey );
}
return Result;
}
RegDat16 = LoadRegistry16( State->WindowsPath );
if (RegDat16 != NULL) {
if (State->StatusCallback != NULL) {
(State->StatusCallback)( State->WindowsPath, State->CallbackParameter );
}
if (CreateRegistryClassesFromRegistry16( State->SoftwareRoot, RegDat16 )) {
ReportWin31IOEvent( State,
EVENTLOG_INFORMATION_TYPE,
WIN31IO_EVENT_MIGRATE_REGDAT,
0,
NULL,
1,
State->WindowsPath
);
}
else {
ReportWin31IOEvent( State,
EVENTLOG_WARNING_TYPE,
WIN31IO_EVENT_MIGRATE_REGDAT_FAILED,
0,
NULL,
1,
State->WindowsPath
);
}
UnloadRegistry16( RegDat16 );
}
if (MigrationKey != NULL) {
NtClose( MigrationKey );
}
return TRUE;
}
#define SERVICE_TO_WAIT_FOR "EventLog"
#define MAX_TICKS_WAIT 90000 // ms
BOOL
WaitForEventLogToStart( VOID )
{
BOOL bStarted = FALSE;
DWORD StartTickCount;
DWORD dwOldCheckPoint = (DWORD)-1;
SC_HANDLE hScManager = NULL;
SC_HANDLE hService = NULL;
SERVICE_STATUS ServiceStatus;
if ((hScManager = OpenSCManager( NULL,
NULL,
SC_MANAGER_CONNECT
)
) == (SC_HANDLE) NULL
) {
KdPrint(("WIN31IO: IsNetworkStarted: OpenSCManager failed, error = %d\n", GetLastError()));
goto Exit;
}
//
// OpenService
//
if ((hService = OpenService( hScManager,
SERVICE_TO_WAIT_FOR,
SERVICE_QUERY_STATUS
)
) == (SC_HANDLE) NULL
) {
KdPrint(("WIN31IO: IsNetworkStarted: OpenService failed, error = %d\n", GetLastError()));
goto Exit;
}
//
// Loop until the service starts or we think it never will start
// or we've exceeded our maximum time delay.
//
StartTickCount = GetTickCount();
while (!bStarted) {
if ((GetTickCount() - StartTickCount) > MAX_TICKS_WAIT) {
KdPrint(("WIN31IO: Max wait exceeded waiting for service <%s> to start\n", SERVICE_TO_WAIT_FOR));
break;
}
if (!QueryServiceStatus( hService, &ServiceStatus )) {
KdPrint(("WIN31IO: IsNetworkStarted: QueryServiceStatus failed, error = %d\n", GetLastError()));
break;
}
if (ServiceStatus.dwCurrentState == SERVICE_STOPPED) {
KdPrint(("WIN31IO: Service STOPPED"));
if (ServiceStatus.dwWin32ExitCode == ERROR_SERVICE_NEVER_STARTED) {
KdPrint(("WIN31IO: Waiting for 3 secs"));
Sleep(3000);
}
else {
KdPrint(("WIN31IO: Service exit code = %d, returning failure\n", ServiceStatus.dwWin32ExitCode));
break;
}
}
else
if ( (ServiceStatus.dwCurrentState == SERVICE_RUNNING) ||
(ServiceStatus.dwCurrentState == SERVICE_CONTINUE_PENDING) ||
(ServiceStatus.dwCurrentState == SERVICE_PAUSE_PENDING) ||
(ServiceStatus.dwCurrentState == SERVICE_PAUSED)
) {
bStarted = TRUE;
}
else
if (ServiceStatus.dwCurrentState == SERVICE_START_PENDING) {
//
// Wait to give a chance for the network to start.
//
Sleep( ServiceStatus.dwWaitHint );
}
else {
KdPrint(( "WIN31IO: Service in unknown state : %d\n", ServiceStatus.dwCurrentState ));
}
}
Exit:
if (hScManager != NULL) {
CloseServiceHandle( hScManager );
}
if (hService != NULL) {
CloseServiceHandle( hService );
}
return( bStarted );
}
HANDLE
OpenCreateKey(
IN HANDLE Root,
IN PWSTR Path,
IN BOOL WriteAccess
)
{
NTSTATUS Status;
HANDLE Key;
UNICODE_STRING KeyName;
OBJECT_ATTRIBUTES ObjectAttributes;
ULONG CreateDisposition;
RtlInitUnicodeString( &KeyName, Path );
InitializeObjectAttributes( &ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
Root,
NULL
);
Status = NtOpenKey( &Key,
WriteAccess ? (STANDARD_RIGHTS_WRITE |
KEY_QUERY_VALUE |
KEY_ENUMERATE_SUB_KEYS |
KEY_SET_VALUE |
KEY_CREATE_SUB_KEY
)
: GENERIC_READ,
&ObjectAttributes
);
if (NT_SUCCESS( Status )) {
return Key;
}
else
if (!WriteAccess) {
BaseSetLastNTError( Status );
return NULL;
}
Status = NtCreateKey( &Key,
STANDARD_RIGHTS_WRITE |
KEY_QUERY_VALUE |
KEY_ENUMERATE_SUB_KEYS |
KEY_SET_VALUE |
KEY_CREATE_SUB_KEY,
&ObjectAttributes,
0,
NULL,
0,
&CreateDisposition
);
if (!NT_SUCCESS( Status )) {
BaseSetLastNTError( Status );
return NULL;
}
else {
return Key;
}
}