windows-nt/Source/XPSP1/NT/base/wow64/regremap/wow64reg/wow64ipc.c
2020-09-26 16:20:57 +08:00

672 lines
13 KiB
C

/*++
Copyright (c) 1999-2000 Microsoft Corporation
Module Name:
wow64ipc.c
Abstract:
This module will do the communication machanism among different processes that need
to interact with the wow64 services, like winlogon will notify wow64svc.
Author:
ATM Shafiqul Khalid (askhalid) 22-Mar-2000
Revision History:
--*/
#include <windows.h>
#include <memory.h>
#include <wow64reg.h>
#include <stdio.h>
#include "reflectr.h"
#define SHMEMSIZE 4096
LPVOID lpvMem = NULL; // pointer to shared memory
HANDLE hMapObject = NULL;
HANDLE hWow64Event = NULL;
HANDLE hWow64Mutex = NULL;
LIST_OBJECT *pList = NULL;
//SECURITY_DESCRIPTOR sdWow64SharedMemory;
//SECURITY_ATTRIBUTES saWow64SharedMemory;
BOOL
Wow64CreateLock (
DWORD dwOption
)
/*++
Routine Description:
Create or open Event wow64 service need to check.
Arguments:
dwOption -
OPEN_EXISTING_SHARED_MEMORY -- shouldn't be the first process to create this.
Return Value:
TRUE if the function has successfully created/opened the memory.
FALSE otherwise.
--*/
{
hWow64Mutex = CreateMutex(
NULL, // SD
FALSE,// initial owner
WOW64_SVC_REFLECTOR_MUTEX_NAME // object name
);
if ( hWow64Mutex == NULL )
return FALSE;
if ( GetLastError() != ERROR_ALREADY_EXISTS && dwOption == OPEN_EXISTING_SHARED_RESOURCES) {
Wow64CloseLock ();
return FALSE;
}
return TRUE;
}
VOID
Wow64CloseLock ()
/*++
Routine Description:
Close wow64 service event.
Arguments:
None.
Return Value:
None.
--*/
{
if ( NULL != hWow64Mutex )
CloseHandle ( hWow64Mutex );
hWow64Mutex = NULL;
}
Wow64CreateEvent (
DWORD dwOption,
HANDLE *hEvent
)
/*++
Routine Description:
Create or open Event wow64 service need to check.
Arguments:
dwOption -
OPEN_EXISTING_SHARED_MEMORY -- shouldn't be the first process to create this.
Return Value:
TRUE if the function has successfully created/opened the memory.
FALSE otherwise.
--*/
{
*hEvent = NULL;
hWow64Event = CreateEvent(
NULL, // SD
TRUE, // reset type
FALSE,// initial state
WOW64_SVC_REFLECTOR_EVENT_NAME // object name
);
if ( hWow64Event == NULL )
return FALSE;
if ( GetLastError() != ERROR_ALREADY_EXISTS && dwOption == OPEN_EXISTING_SHARED_RESOURCES) {
Wow64CloseEvent ();
return FALSE;
}
*hEvent = hWow64Event;
return TRUE;
}
VOID
Wow64CloseEvent ()
/*++
Routine Description:
Close wow64 service event.
Arguments:
None.
Return Value:
None.
--*/
{
if ( NULL != hWow64Event )
CloseHandle ( hWow64Event );
hWow64Event = NULL;
}
BOOL
LockSharedMemory ()
{
DWORD Ret;
Ret = WaitForSingleObject( hWow64Mutex, 1000*5*60); // 5 min is good enough
//
// now you can access shared memory
//
//Log information if error occur
if ( Ret == WAIT_OBJECT_0 || Ret == WAIT_ABANDONED )
return TRUE;
//
// check for abandaned case
//
return FALSE;
}
BOOL
UnLockSharedMemory ()
{
if ( ReleaseMutex ( hWow64Mutex ) )
return TRUE;
return FALSE;
}
BOOL
CreateSharedMemory (
DWORD dwOption
)
/*++
Routine Description:
Create or open shared memory, used by different process.
Arguments:
dwOption -
OPEN_EXISTING_SHARED_MEMORY -- shouldn't be the first process to create this.
Return Value:
TRUE if the function has successfully created/opened the memory.
FALSE otherwise.
--*/
{
BOOL fInit;
//if (!InitializeSecurityDescriptor( &sdWow64SharedMemory, SECURITY_DESCRIPTOR_REVISION ))
// return FALSE;
// saWow64SharedMemory.nLength = sizeof ( SECURITY_ATTRIBUTES );
// saWow64SharedMemory.bInheritHandle = TRUE;
// saWow64SharedMemory.lpSecurityDescriptor = &sdWow64SharedMemory;
// Create a named file mapping object.
hMapObject = CreateFileMapping(
INVALID_HANDLE_VALUE, // use paging file
NULL, //&saWow64SharedMemory, // no security attributes
PAGE_READWRITE, // read/write access
0, // size: high 32-bits
SHMEMSIZE, // size: low 32-bits
SHRED_MEMORY_NAME ); // name of map object
if (hMapObject == NULL)
return FALSE;
// The first process to attach initializes memory.
fInit = (GetLastError() != ERROR_ALREADY_EXISTS);
if (fInit && dwOption == OPEN_EXISTING_SHARED_RESOURCES ) {
CloseSharedMemory ();
return FALSE; // no shared memory exist
}
// Get a pointer to the file-mapped shared memory.
pList = (LIST_OBJECT *) MapViewOfFile(
hMapObject, // object to map view of
FILE_MAP_WRITE, // read/write access
0, // high offset: map from
0, // low offset: beginning
0); // default: map entire file
if (pList == NULL)
return FALSE;
// Initialize memory if this is the first process.
if (fInit) {
memset( ( PBYTE )pList, '\0', SHMEMSIZE);
pList->MaxCount = ( SHMEMSIZE - sizeof ( LIST_OBJECT ) ) / (LIST_NAME_LEN*sizeof (WCHAR));
}
//
// Also initialize all the locking and synchronization object
//
if ( !Wow64CreateLock ( dwOption ) ) {
CloseSharedMemory ();
return FALSE;
}
return TRUE;
}
VOID
CloseSharedMemory ()
{
if (pList != NULL )
UnmapViewOfFile(pList);
pList = NULL;
// Close the process's handle to the file-mapping object.
if ( hMapObject!= NULL )
CloseHandle(hMapObject);
hMapObject = NULL;
Wow64CloseLock ();
}
// initially try to transfer only one object
BOOL
EnQueueObject (
PWCHAR pObjName,
WCHAR Type
)
/*++
Routine Description:
Put an object name in the queue.
Arguments:
pObjName - Name of the object to put in the quque.
Type - L: Loading hive
U: Unloading Hive
Return Value:
TRUE if the function has successfully created/opened the memory.
FALSE otherwise.
--*/
{
// lpvMem check if this value is NULL
// wait to get the lock on shared memory
DWORD Len;
DWORD i;
if ( pList == NULL )
return FALSE;
Len = wcslen (pObjName);
if (Len == 0 || Len > 256 )
return FALSE;
if (!LockSharedMemory ())
return FALSE;
if ( pList->Count == pList->MaxCount ) {
UnLockSharedMemory ();
return FALSE;
}
for ( i=0; i<pList->MaxCount; i++) {
if (pList->Name[i][0] == UNICODE_NULL ) break;
}
if ( i == pList->MaxCount ) {
UnLockSharedMemory ();
return FALSE;
}
wcscpy ( pList->Name[i], pObjName);
pList->Count++;
pList->Name[i][LIST_NAME_LEN-1] = Type;
UnLockSharedMemory ();
SignalWow64Svc ();
// write data
// release data
return TRUE;
}
BOOL
DeQueueObject (
PWCHAR pObjName,
PWCHAR Type
)
/*++
Routine Description:
Get a name of object from the queue.
Arguments:
pObjName - Name of the object that receive the name.
Type - L: Loading hive
U: Unloading Hive
Return Value:
TRUE if the function has successfully created/opened the memory.
FALSE otherwise.
--*/
{
// lpvMem check if this value is NULL
// wait to get the lock on shared memory
DWORD Len;
DWORD i;
if ( pList == NULL )
return FALSE;
if (!LockSharedMemory ())
return FALSE;
if ( pList->Count == 0 ) {
UnLockSharedMemory ();
return FALSE;
}
for ( i=0; i < pList->MaxCount; i++) {
if (pList->Name[i][0] != UNICODE_NULL ) break;
}
if ( i == pList->MaxCount ) {
UnLockSharedMemory ();
return FALSE;
}
wcscpy ( pObjName, pList->Name[i]);
pList->Name[i][0] = UNICODE_NULL;
pList->Count--;
*Type = pList->Name[i][LIST_NAME_LEN-1];
UnLockSharedMemory ();
//SignalWow64Svc ();
// write data
// release data
return TRUE;
}
//signal wowservice to receive the data.
BOOL
SignalWow64Svc ()
{
//this might be a simple event trigger or set event
if ( SetEvent ( hWow64Event ) )
return TRUE;
return FALSE;
}
BOOL
CheckAdminPriviledge ()
/*++
Routine Description:
Check if the running thread has admin priviledge.
Arguments:
None.
Return Value:
TRUE if the calling thread has admin proviledge.
FALSE otherwise.
--*/
{
BOOL bRetCode = FALSE;
/*
HANDLE TokenHandle;
BOOL b;
DWORD ReturnLength;
PTOKEN_USER TokenInfo;
//
// If we're impersonating, use the thread token, otherwise
// use the process token.
//
PTOKEN_USER Result = NULL;
b = OpenThreadToken(
GetCurrentThread(),
TOKEN_QUERY,
FALSE,
&TokenHandle
);
if (!b) {
if (GetLastError() == ERROR_NO_TOKEN) {
//
// We're not impersonating, try the process token
//
b = OpenProcessToken(
GetCurrentProcess(),
TOKEN_QUERY,
&TokenHandle
);
if (!b) {
return FALSE;
}
} else {
//
// We failed for some unexpected reason, return NULL and
// let the caller figure it out if he so chooses.
//
return FALSE;
}
}
ReturnLength = GetSidLengthRequired( SID_MAX_SUB_AUTHORITIES ) + sizeof( TOKEN_USER );
TokenInfo = (PTOKEN_USER)malloc( ReturnLength );
if (TokenInfo != NULL) {
b = GetTokenInformation (
TokenHandle,
TokenGroups,
TokenInfo,
ReturnLength,
&ReturnLength
);
if (b) {
Result = TokenInfo;
} else {
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
//
// Reallocate TokenInfo
//
free( TokenInfo );
TokenInfo = (PTOKEN_USER)malloc( ReturnLength );
if (TokenInfo != NULL) {
b = GetTokenInformation (
TokenHandle,
TokenGroups,
TokenInfo,
ReturnLength,
&ReturnLength
);
if (b) {
Result = TokenInfo;
}
} else {
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return FALSE;
}
}
}
} else {
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return FALSE;
}
DWORD dwSidSize = 0;
SID_NAME_USE SidType;
DWORD strSize = 80;
WCHAR str [80];
SID_NAME_USE sidType;
BOOL bProceede = TRUE;
DWORD dwRet = LookupAccountName (
NULL,
L"Administrators",
NULL,
&dwSidSize,
str,
&strSize,
&sidType );
if ( dwSidSize == 0)
if ( !dwRet ) {
cBase.PrintErrorWin32 ( GetLastError () );
bProceede = FALSE;
}
PSID psid = NULL;
if ( bProceede )
if ( dwSidSize ) {
psid = (PSID) GlobalAlloc ( GPTR, dwSidSize );
if ( psid == NULL )
bProceede = FALSE;
else {
strSize = 80;
dwRet = LookupAccountName (
NULL,
L"Administrators",
psid,
&dwSidSize,
str,
&strSize,
&sidType );
if ( ! dwRet )
bProceede = FALSE;
}
}
//now check
if ( Result == NULL )
bProceede = FALSE;
TOKEN_GROUPS *pGroups = ( TOKEN_GROUPS *)Result;
if ( bProceede )
for ( int i=0; i < pGroups->GroupCount; i++ ) {
if ( EqualSid ( pGroups->Groups [i].Sid, psid ) ){
bRetCode = TRUE;
break;
}
};
if ( psid != NULL )
GlobalFree ( psid );
if ( Result != NULL )
free ( Result );
*/
return bRetCode;
}