1477 lines
48 KiB
C
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;
|
|
}
|
|
}
|