1028 lines
25 KiB
C
1028 lines
25 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
wowreg.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This is the surragate process for registration of 32 dlls from a 64 bit process.
|
||
|
And vice-versa.
|
||
|
|
||
|
The parent process passes relevent IPC data on the cmdline, and the surragate
|
||
|
process then coordinates the registration of this data with the parent process.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Andrew Ritz (andrewr) 3-Feb-2000
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Andrew Ritz (andrewr) 3-Feb-2000 - Created It
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <shellapi.h>
|
||
|
#include <tchar.h>
|
||
|
#include <stdio.h>
|
||
|
#include <setupapi.h>
|
||
|
#include <spapip.h>
|
||
|
#include <ole2.h>
|
||
|
#include <rc_ids.h>
|
||
|
|
||
|
#ifndef UNICODE
|
||
|
#error UNICODE assumed
|
||
|
#endif
|
||
|
|
||
|
#ifndef _WIN64
|
||
|
#include <wow64t.h>
|
||
|
#endif
|
||
|
|
||
|
#include "..\unicode\msg.h"
|
||
|
#include "memory.h"
|
||
|
#include "..\sputils\locking.h"
|
||
|
#include "childreg.h"
|
||
|
#include "cntxtlog.h"
|
||
|
|
||
|
|
||
|
#define DLLINSTALL "DllInstall"
|
||
|
#define DLLREGISTER "DllRegisterServer"
|
||
|
#define DLLUNREGISTER "DllUnregisterServer"
|
||
|
|
||
|
typedef struct _OLE_CONTROL_DATA {
|
||
|
LPTSTR FullPath;
|
||
|
UINT RegType;
|
||
|
PVOID LogContext;
|
||
|
|
||
|
BOOL Register; // or unregister
|
||
|
|
||
|
LPCTSTR Argument;
|
||
|
|
||
|
} OLE_CONTROL_DATA, *POLE_CONTROL_DATA;
|
||
|
|
||
|
#if DBG
|
||
|
|
||
|
VOID
|
||
|
WowRegAssertFailed(
|
||
|
IN PSTR FileName,
|
||
|
IN UINT LineNumber,
|
||
|
IN PSTR Condition
|
||
|
)
|
||
|
{
|
||
|
int i;
|
||
|
CHAR Name[MAX_PATH];
|
||
|
PCHAR p;
|
||
|
LPSTR Msg;
|
||
|
DWORD MsgLen;
|
||
|
DWORD GlobalSetupFlags = pSetupGetGlobalFlags();
|
||
|
|
||
|
//
|
||
|
// Use dll name as caption
|
||
|
//
|
||
|
GetModuleFileNameA(NULL,Name,MAX_PATH);
|
||
|
if(p = strrchr(Name,'\\')) {
|
||
|
p++;
|
||
|
} else {
|
||
|
p = Name;
|
||
|
}
|
||
|
|
||
|
MsgLen = strlen(p)+strlen(FileName)+strlen(Condition)+128;
|
||
|
try {
|
||
|
|
||
|
Msg = _alloca(MsgLen);
|
||
|
|
||
|
wsprintfA(
|
||
|
Msg,
|
||
|
"Assertion failure at line %u in file %s!%s: %s%s",
|
||
|
LineNumber,
|
||
|
p,
|
||
|
FileName,
|
||
|
Condition,
|
||
|
(GlobalSetupFlags & PSPGF_NONINTERACTIVE) ? "\r\n" : "\n\nCall DebugBreak()?"
|
||
|
);
|
||
|
|
||
|
OutputDebugStringA(Msg);
|
||
|
|
||
|
if(GlobalSetupFlags & PSPGF_NONINTERACTIVE) {
|
||
|
i = IDYES;
|
||
|
} else {
|
||
|
i = MessageBoxA(
|
||
|
NULL,
|
||
|
Msg,
|
||
|
p,
|
||
|
MB_YESNO | MB_TASKMODAL | MB_ICONSTOP | MB_SETFOREGROUND
|
||
|
);
|
||
|
}
|
||
|
|
||
|
} except (EXCEPTION_EXECUTE_HANDLER) {
|
||
|
OutputDebugStringA("WOWREG32 ASSERT!!!! (out of stack)\r\n");
|
||
|
i=IDYES;
|
||
|
}
|
||
|
if(i == IDYES) {
|
||
|
DebugBreak();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#define MYASSERT(x) if(!(x)) { WowRegAssertFailed(__FILE__,__LINE__,#x); }
|
||
|
|
||
|
#else
|
||
|
#define MYASSERT(x)
|
||
|
#endif
|
||
|
|
||
|
VOID
|
||
|
DebugPrintEx(
|
||
|
DWORD Level,
|
||
|
PCTSTR format,
|
||
|
... OPTIONAL
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Send a formatted string to the debugger.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
format - standard printf format string.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NONE.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
TCHAR buf[1026]; // bigger than max size
|
||
|
va_list arglist;
|
||
|
|
||
|
va_start(arglist, format);
|
||
|
wvsprintf(buf, format, arglist);
|
||
|
DbgPrintEx(DPFLTR_SETUP_ID, Level, (PCH)"%ws",buf);
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
RegisterUnregisterControl(
|
||
|
PWOW_IPC_REGION_TOSURRAGATE pControlDataFromRegion,
|
||
|
PDWORD FailureCode);
|
||
|
|
||
|
|
||
|
#define IDLE_TIMER 1000*60 // 60 seconds
|
||
|
//
|
||
|
// Keep statistics...
|
||
|
//
|
||
|
INT RegisteredControls = 0;
|
||
|
|
||
|
PWSTR RegionName;
|
||
|
PWSTR SignalReadyEvent;
|
||
|
PWSTR SignalCompleteEvent;
|
||
|
PWSTR ThisProgramName;
|
||
|
#ifndef _WIN64
|
||
|
BOOL Wow64 = FALSE;
|
||
|
#endif
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
ParseArgs(
|
||
|
IN int argc,
|
||
|
IN PWSTR *argv
|
||
|
)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
ThisProgramName = argv[0];
|
||
|
|
||
|
|
||
|
if(argc != 7) { // program name plus 3 required switches and their input
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < argc; i++) {
|
||
|
if (0 == _wcsicmp(argv[i],SURRAGATE_REGIONNAME_SWITCH)) {
|
||
|
RegionName = argv[i+1];
|
||
|
}
|
||
|
|
||
|
if (0 == _wcsicmp(argv[i],SURRAGATE_SIGNALREADY_SWITCH)) {
|
||
|
SignalReadyEvent = argv[i+1];
|
||
|
}
|
||
|
|
||
|
if (0 == _wcsicmp(argv[i],SURRAGATE_SIGNALCOMPLETE_SWITCH)) {
|
||
|
SignalCompleteEvent = argv[i+1];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!SignalCompleteEvent || !SignalReadyEvent || !RegionName) {
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
return(TRUE);
|
||
|
|
||
|
}
|
||
|
|
||
|
void
|
||
|
Usage(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
TCHAR Buffer[2048];
|
||
|
if(LoadString(GetModuleHandle(NULL),IDS_WRONGUSE,Buffer,sizeof(Buffer)/sizeof(TCHAR))) {
|
||
|
_ftprintf( stderr,TEXT("%s\n"),Buffer);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int
|
||
|
__cdecl
|
||
|
main(
|
||
|
IN int argc,
|
||
|
IN char *argvA[]
|
||
|
)
|
||
|
{
|
||
|
BOOL b;
|
||
|
PWSTR *argv;
|
||
|
HANDLE hReady = NULL;
|
||
|
HANDLE hComplete = NULL;
|
||
|
HANDLE hFileMap = NULL;
|
||
|
PVOID Region = NULL;
|
||
|
PWOW_IPC_REGION_TOSURRAGATE pInput;
|
||
|
PWOW_IPC_REGION_FROMSURRAGATE pOutput;
|
||
|
HANDLE hEvent[1];
|
||
|
DWORD WaitResult, FailureCode;
|
||
|
|
||
|
#ifndef _WIN64
|
||
|
{
|
||
|
ULONG_PTR ul = 0;
|
||
|
NTSTATUS st;
|
||
|
st = NtQueryInformationProcess(NtCurrentProcess(),
|
||
|
ProcessWow64Information,
|
||
|
&ul,
|
||
|
sizeof(ul),
|
||
|
NULL);
|
||
|
|
||
|
if (NT_SUCCESS(st) && (0 != ul)) {
|
||
|
// 32-bit code running on Win64
|
||
|
Wow64 = TRUE;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
//
|
||
|
// Assume failure.
|
||
|
//
|
||
|
b = FALSE;
|
||
|
|
||
|
argv = CommandLineToArgvW(GetCommandLine(), &argc);
|
||
|
if (!argv) {
|
||
|
//
|
||
|
// out of memory ?
|
||
|
//
|
||
|
DebugPrintEx(
|
||
|
DPFLTR_ERROR_LEVEL,
|
||
|
L"WOWREG32: Low Memory\n");
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
if(!ParseArgs(argc,argv)) {
|
||
|
DebugPrintEx(
|
||
|
DPFLTR_ERROR_LEVEL,
|
||
|
L"WOWREG32: Invalid Usage\n");
|
||
|
Usage();
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// open the region and the named events
|
||
|
//
|
||
|
|
||
|
hFileMap = OpenFileMapping(
|
||
|
FILE_MAP_READ| FILE_MAP_WRITE,
|
||
|
FALSE,
|
||
|
RegionName
|
||
|
);
|
||
|
if (!hFileMap) {
|
||
|
DebugPrintEx(
|
||
|
DPFLTR_ERROR_LEVEL,
|
||
|
L"WOWREG32: OpenFileMapping (%s) failed, ec = %x\n", RegionName, GetLastError());
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
Region = MapViewOfFile(
|
||
|
hFileMap,
|
||
|
FILE_MAP_READ | FILE_MAP_WRITE,
|
||
|
0,
|
||
|
0,
|
||
|
0
|
||
|
);
|
||
|
if (!Region) {
|
||
|
DebugPrintEx(
|
||
|
DPFLTR_ERROR_LEVEL,
|
||
|
L"WOWREG32: MapViewOfFile failed, ec = %x\n", GetLastError());
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
hReady = OpenEvent(EVENT_MODIFY_STATE | SYNCHRONIZE,FALSE, SignalReadyEvent);
|
||
|
if (!hReady) {
|
||
|
DebugPrintEx(
|
||
|
DPFLTR_ERROR_LEVEL,
|
||
|
L"WOWREG32: OpenEvent (%s) failed, ec = %x\n", SignalReadyEvent, GetLastError());
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
hComplete = OpenEvent(EVENT_MODIFY_STATE | SYNCHRONIZE,FALSE, SignalCompleteEvent);
|
||
|
if (!hComplete) {
|
||
|
DebugPrintEx(
|
||
|
DPFLTR_ERROR_LEVEL,
|
||
|
L"WOWREG32: OpenEvent (%s) failed, ec = %x\n", SignalCompleteEvent, GetLastError());
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
pInput = (PWOW_IPC_REGION_TOSURRAGATE) Region;
|
||
|
pOutput = (PWOW_IPC_REGION_FROMSURRAGATE) Region;
|
||
|
|
||
|
//
|
||
|
// the process is now initialized. we now wait for either our event to be
|
||
|
// signalled or for our idle timer to fire, in which case we will exit the
|
||
|
// program
|
||
|
//
|
||
|
hEvent[0] = hReady;
|
||
|
|
||
|
while (1) {
|
||
|
|
||
|
do {
|
||
|
WaitResult = MsgWaitForMultipleObjectsEx(
|
||
|
1,
|
||
|
&hEvent[0],
|
||
|
IDLE_TIMER,
|
||
|
QS_ALLINPUT,
|
||
|
MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
|
||
|
|
||
|
if (WaitResult == WAIT_OBJECT_0 + 1) {
|
||
|
MSG msg;
|
||
|
|
||
|
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||
|
TranslateMessage(&msg);
|
||
|
DispatchMessage(&msg);
|
||
|
}
|
||
|
}
|
||
|
} while(WaitResult != WAIT_TIMEOUT &&
|
||
|
WaitResult != WAIT_OBJECT_0 &&
|
||
|
WaitResult != WAIT_FAILED);
|
||
|
|
||
|
|
||
|
if (WaitResult == WAIT_TIMEOUT) {
|
||
|
//
|
||
|
// we hit the idle timer, so let the process unwind and go away now.
|
||
|
//
|
||
|
//
|
||
|
// it doesn't matter too much, but make the return code "false" if the
|
||
|
// process has gone away without ever registering any controls.
|
||
|
//
|
||
|
b = (RegisteredControls != 0);
|
||
|
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
MYASSERT(WaitResult == WAIT_OBJECT_0);
|
||
|
|
||
|
//
|
||
|
// reset our event so we only process each control one time
|
||
|
//
|
||
|
ResetEvent(hReady);
|
||
|
|
||
|
//
|
||
|
// register the control
|
||
|
//
|
||
|
b = RegisterUnregisterControl(pInput,&FailureCode);
|
||
|
#ifdef PRERELEASE
|
||
|
if (!b) {
|
||
|
DebugPrintEx(
|
||
|
DPFLTR_ERROR_LEVEL,
|
||
|
L"First call to register control failed, trying again.\n"
|
||
|
L"If you have a debugger attached to this process, it will"
|
||
|
L" now call DebugBreak() so that you can debug this registration failure\n" );
|
||
|
if (IsDebuggerPresent()) {
|
||
|
DebugBreak();
|
||
|
}
|
||
|
b = RegisterUnregisterControl(pInput,&FailureCode);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
//
|
||
|
// write an output status. Note that you cannot access pInput after
|
||
|
// this point because pOutput and pInput are overloaded views of the
|
||
|
// same memory region.
|
||
|
//
|
||
|
pOutput->Win32Error = b ? ERROR_SUCCESS : GetLastError();
|
||
|
pOutput->FailureCode= b ? SPREG_SUCCESS : FailureCode;
|
||
|
|
||
|
//
|
||
|
// set an event to tell the parent process to read our status and give
|
||
|
// us the next control to register.
|
||
|
//
|
||
|
SetEvent(hComplete);
|
||
|
|
||
|
if (b) {
|
||
|
RegisteredControls += 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
fprintf( stdout,"Registered %d controls\n", RegisteredControls );
|
||
|
|
||
|
DebugPrintEx(
|
||
|
DPFLTR_INFO_LEVEL,
|
||
|
L"WOWREG32: registered %d controls\n", RegisteredControls);
|
||
|
|
||
|
exit:
|
||
|
if (Region) {
|
||
|
UnmapViewOfFile( Region );
|
||
|
}
|
||
|
|
||
|
if (hFileMap) {
|
||
|
CloseHandle(hFileMap);
|
||
|
}
|
||
|
|
||
|
if (hReady) {
|
||
|
CloseHandle(hReady);
|
||
|
}
|
||
|
|
||
|
if (hComplete) {
|
||
|
CloseHandle(hComplete);
|
||
|
}
|
||
|
|
||
|
|
||
|
return(b);
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
pSetupRegisterDllInstall(
|
||
|
IN POLE_CONTROL_DATA OleControlData,
|
||
|
IN HMODULE ControlDll,
|
||
|
IN PDWORD ExtendedStatus
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
call the "DllInstall" entrypoint for the specified dll
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
OleControlData - pointer to the OLE_CONTROL_DATA structure for the dll
|
||
|
to be registered
|
||
|
|
||
|
ControlDll - module handle to the dll to be registered
|
||
|
|
||
|
ExtendedStatus - receives updated SPREG_* flag indicating outcome
|
||
|
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Win32 error code indicating outcome.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
LPEXCEPTION_POINTERS ExceptionPointers = NULL;
|
||
|
HRESULT (__stdcall *InstallRoutine) (BOOL bInstall, LPCTSTR pszCmdLine);
|
||
|
HRESULT InstallStatus;
|
||
|
|
||
|
DWORD d = NO_ERROR;
|
||
|
|
||
|
//
|
||
|
// parameter validation
|
||
|
//
|
||
|
if (!ControlDll) {
|
||
|
*ExtendedStatus = SPREG_UNKNOWN;
|
||
|
return ERROR_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// get function pointer to "DllInstall" entrypoint
|
||
|
//
|
||
|
InstallRoutine = NULL; // shut up PreFast
|
||
|
try {
|
||
|
(FARPROC)InstallRoutine = GetProcAddress(
|
||
|
ControlDll, DLLINSTALL );
|
||
|
} except (
|
||
|
ExceptionPointers = GetExceptionInformation(),
|
||
|
EXCEPTION_EXECUTE_HANDLER) {
|
||
|
}
|
||
|
if(ExceptionPointers) {
|
||
|
//
|
||
|
// something went wrong...record an error
|
||
|
//
|
||
|
d = ExceptionPointers->ExceptionRecord->ExceptionCode;
|
||
|
|
||
|
WriteLogEntry(
|
||
|
OleControlData->LogContext,
|
||
|
SETUP_LOG_ERROR,
|
||
|
MSG_LOG_OLE_CONTROL_INTERNAL_EXCEPTION,
|
||
|
NULL,
|
||
|
OleControlData->FullPath
|
||
|
);
|
||
|
|
||
|
DebugPrintEx(DPFLTR_TRACE_LEVEL,L"WOWREG32: ...exception in GetProcAddress handled\n");
|
||
|
|
||
|
*ExtendedStatus = SPREG_GETPROCADDR;
|
||
|
|
||
|
} else if(InstallRoutine) {
|
||
|
//
|
||
|
// now call the function
|
||
|
//
|
||
|
DebugPrintEx(DPFLTR_TRACE_LEVEL,L"WOWREG32: installing...\n");
|
||
|
|
||
|
*ExtendedStatus = SPREG_DLLINSTALL;
|
||
|
try {
|
||
|
|
||
|
InstallStatus = InstallRoutine(OleControlData->Register, OleControlData->Argument);
|
||
|
|
||
|
if(FAILED(InstallStatus)) {
|
||
|
|
||
|
d = InstallStatus;
|
||
|
|
||
|
WriteLogEntry(
|
||
|
OleControlData->LogContext,
|
||
|
SETUP_LOG_ERROR|SETUP_LOG_BUFFER,
|
||
|
MSG_LOG_OLE_CONTROL_API_FAILED,
|
||
|
NULL,
|
||
|
OleControlData->FullPath,
|
||
|
TEXT(DLLINSTALL)
|
||
|
);
|
||
|
WriteLogError(OleControlData->LogContext,
|
||
|
SETUP_LOG_ERROR,
|
||
|
d);
|
||
|
|
||
|
} else if(InstallStatus) {
|
||
|
WriteLogEntry(OleControlData->LogContext,
|
||
|
SETUP_LOG_WARNING,
|
||
|
MSG_LOG_OLE_CONTROL_API_WARN,
|
||
|
NULL,
|
||
|
OleControlData->FullPath,
|
||
|
TEXT(DLLINSTALL),
|
||
|
InstallStatus
|
||
|
);
|
||
|
} else {
|
||
|
WriteLogEntry(
|
||
|
OleControlData->LogContext,
|
||
|
SETUP_LOG_VERBOSE,
|
||
|
MSG_LOG_OLE_CONTROL_API_OK,
|
||
|
NULL,
|
||
|
OleControlData->FullPath,
|
||
|
TEXT(DLLINSTALL)
|
||
|
);
|
||
|
}
|
||
|
} except (
|
||
|
ExceptionPointers = GetExceptionInformation(),
|
||
|
EXCEPTION_EXECUTE_HANDLER) {
|
||
|
|
||
|
d = ExceptionPointers->ExceptionRecord->ExceptionCode;
|
||
|
|
||
|
WriteLogEntry(
|
||
|
OleControlData->LogContext,
|
||
|
SETUP_LOG_ERROR,
|
||
|
MSG_LOG_OLE_CONTROL_API_EXCEPTION,
|
||
|
NULL,
|
||
|
OleControlData->FullPath,
|
||
|
TEXT(DLLINSTALL)
|
||
|
);
|
||
|
|
||
|
DebugPrintEx(DPFLTR_TRACE_LEVEL,L"WOWREG32: ...exception in DllInstall handled\n");
|
||
|
|
||
|
}
|
||
|
|
||
|
DebugPrintEx(DPFLTR_TRACE_LEVEL,L"WOWREG32: ...installed\n");
|
||
|
} else {
|
||
|
*ExtendedStatus = SPREG_GETPROCADDR;
|
||
|
}
|
||
|
|
||
|
return d;
|
||
|
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
pSetupRegisterDllRegister(
|
||
|
IN POLE_CONTROL_DATA OleControlData,
|
||
|
IN HMODULE ControlDll,
|
||
|
IN PDWORD ExtendedStatus
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
call the "DllRegisterServer" or "DllUnregisterServer" entrypoint for the
|
||
|
specified dll
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
OleControlData - contains data about dll to be registered
|
||
|
ControlDll - module handle to the dll to be registered
|
||
|
|
||
|
ExtendedStatus - receives an extended status depending on the outcome of
|
||
|
this operation
|
||
|
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Win32 error code indicating outcome.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
LPEXCEPTION_POINTERS ExceptionPointers = NULL;
|
||
|
HRESULT (__stdcall *RegisterRoutine) (VOID);
|
||
|
HRESULT RegisterStatus;
|
||
|
|
||
|
DWORD d = NO_ERROR;
|
||
|
|
||
|
//
|
||
|
// parameter validation
|
||
|
//
|
||
|
if (!ControlDll) {
|
||
|
return ERROR_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// get the function pointer to the actual routine we want to call
|
||
|
//
|
||
|
RegisterRoutine = NULL; // shut up preFast
|
||
|
try {
|
||
|
(FARPROC)RegisterRoutine = GetProcAddress(
|
||
|
ControlDll, OleControlData->Register ? DLLREGISTER : DLLUNREGISTER);
|
||
|
} except (
|
||
|
ExceptionPointers = GetExceptionInformation(),
|
||
|
EXCEPTION_EXECUTE_HANDLER) {
|
||
|
}
|
||
|
if(ExceptionPointers) {
|
||
|
|
||
|
//
|
||
|
// something went wrong, horribly wrong
|
||
|
//
|
||
|
d = ExceptionPointers->ExceptionRecord->ExceptionCode;
|
||
|
|
||
|
WriteLogEntry(
|
||
|
OleControlData->LogContext,
|
||
|
SETUP_LOG_ERROR,
|
||
|
MSG_LOG_OLE_CONTROL_INTERNAL_EXCEPTION,
|
||
|
NULL,
|
||
|
OleControlData->FullPath
|
||
|
);
|
||
|
|
||
|
DebugPrintEx(DPFLTR_TRACE_LEVEL,L"WOWREG32: ...exception in GetProcAddress handled\n");
|
||
|
|
||
|
*ExtendedStatus = SPREG_GETPROCADDR;
|
||
|
|
||
|
} else if(RegisterRoutine) {
|
||
|
|
||
|
DebugPrintEx(DPFLTR_TRACE_LEVEL,L"WOWREG32: registering...\n");
|
||
|
*ExtendedStatus = SPREG_REGSVR;
|
||
|
try {
|
||
|
|
||
|
RegisterStatus = RegisterRoutine();
|
||
|
|
||
|
if(FAILED(RegisterStatus)) {
|
||
|
|
||
|
d = RegisterStatus;
|
||
|
|
||
|
WriteLogEntry(OleControlData->LogContext,
|
||
|
SETUP_LOG_ERROR | SETUP_LOG_BUFFER,
|
||
|
MSG_LOG_OLE_CONTROL_API_FAILED,
|
||
|
NULL,
|
||
|
OleControlData->FullPath,
|
||
|
OleControlData->Register ? TEXT(DLLREGISTER) : TEXT(DLLUNREGISTER)
|
||
|
);
|
||
|
|
||
|
WriteLogError(OleControlData->LogContext,
|
||
|
SETUP_LOG_ERROR,
|
||
|
d);
|
||
|
} else if(RegisterStatus) {
|
||
|
WriteLogEntry(OleControlData->LogContext,
|
||
|
SETUP_LOG_WARNING,
|
||
|
MSG_LOG_OLE_CONTROL_API_WARN,
|
||
|
NULL,
|
||
|
OleControlData->FullPath,
|
||
|
OleControlData->Register ? TEXT(DLLREGISTER) : TEXT(DLLUNREGISTER),
|
||
|
RegisterStatus
|
||
|
);
|
||
|
} else {
|
||
|
WriteLogEntry(OleControlData->LogContext,
|
||
|
SETUP_LOG_VERBOSE,
|
||
|
MSG_LOG_OLE_CONTROL_API_OK,
|
||
|
NULL,
|
||
|
OleControlData->FullPath,
|
||
|
OleControlData->Register ? TEXT(DLLREGISTER) : TEXT(DLLUNREGISTER)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
} except (
|
||
|
ExceptionPointers = GetExceptionInformation(),
|
||
|
EXCEPTION_EXECUTE_HANDLER) {
|
||
|
|
||
|
d = ExceptionPointers->ExceptionRecord->ExceptionCode;
|
||
|
|
||
|
WriteLogEntry(
|
||
|
OleControlData->LogContext,
|
||
|
SETUP_LOG_ERROR,
|
||
|
MSG_LOG_OLE_CONTROL_API_EXCEPTION,
|
||
|
NULL,
|
||
|
OleControlData->FullPath,
|
||
|
OleControlData->Register ? TEXT(DLLREGISTER) : TEXT(DLLUNREGISTER)
|
||
|
);
|
||
|
DebugPrintEx(DPFLTR_TRACE_LEVEL,L"WOWREG32: ...exception in DllRegisterServer handled\n");
|
||
|
|
||
|
}
|
||
|
|
||
|
DebugPrintEx(DPFLTR_TRACE_LEVEL,L"WOWREG32: ...registered\n");
|
||
|
|
||
|
} else {
|
||
|
|
||
|
d = GetLastError();
|
||
|
|
||
|
WriteLogEntry(OleControlData->LogContext,
|
||
|
SETUP_LOG_ERROR | SETUP_LOG_BUFFER,
|
||
|
MSG_LOG_OLE_CONTROL_NOT_REGISTERED_GETPROC_FAILED,
|
||
|
NULL,
|
||
|
OleControlData->FullPath,
|
||
|
OleControlData->Register ? TEXT(DLLREGISTER) : TEXT(DLLUNREGISTER)
|
||
|
);
|
||
|
|
||
|
WriteLogError(OleControlData->LogContext,
|
||
|
SETUP_LOG_ERROR,
|
||
|
d);
|
||
|
|
||
|
|
||
|
*ExtendedStatus = SPREG_GETPROCADDR;
|
||
|
|
||
|
}
|
||
|
|
||
|
return d;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
pSetupRegisterLoadDll(
|
||
|
IN POLE_CONTROL_DATA OleControlData,
|
||
|
OUT HMODULE *ControlDll
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
get the module handle to the specified dll
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
OleControlData - contains path to dll to be loaded
|
||
|
|
||
|
ControlDll - module handle for the dll
|
||
|
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Win32 error code indicating outcome.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
LPEXCEPTION_POINTERS ExceptionPointers = NULL;
|
||
|
|
||
|
DWORD d = NO_ERROR;
|
||
|
|
||
|
DebugPrintEx(DPFLTR_TRACE_LEVEL,L"WOWREG32: loading dll...\n");
|
||
|
|
||
|
#ifndef _WIN64
|
||
|
if(Wow64) {
|
||
|
//
|
||
|
// don't remap directory the directory that the caller provided
|
||
|
//
|
||
|
Wow64DisableFilesystemRedirector(OleControlData->FullPath);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
try {
|
||
|
|
||
|
*ControlDll = LoadLibrary(OleControlData->FullPath);
|
||
|
|
||
|
} except (
|
||
|
ExceptionPointers = GetExceptionInformation(),
|
||
|
EXCEPTION_EXECUTE_HANDLER) {
|
||
|
}
|
||
|
|
||
|
#ifndef _WIN64
|
||
|
if(Wow64) {
|
||
|
//
|
||
|
// re-enable the redirection on this file
|
||
|
//
|
||
|
Wow64EnableFilesystemRedirector();
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if(ExceptionPointers) {
|
||
|
|
||
|
WriteLogEntry(
|
||
|
OleControlData->LogContext,
|
||
|
SETUP_LOG_ERROR,
|
||
|
MSG_LOG_OLE_CONTROL_LOADLIBRARY_EXCEPTION,
|
||
|
NULL,
|
||
|
OleControlData->FullPath
|
||
|
);
|
||
|
|
||
|
DebugPrintEx(DPFLTR_TRACE_LEVEL,L"WOWREG32: ...exception in LoadLibrary handled\n");
|
||
|
d = ExceptionPointers->ExceptionRecord->ExceptionCode;
|
||
|
|
||
|
} else if (!*ControlDll) {
|
||
|
d = GetLastError();
|
||
|
|
||
|
//
|
||
|
// LoadLibrary failed.
|
||
|
// File not found is not an error. We want to know about
|
||
|
// other errors though.
|
||
|
//
|
||
|
|
||
|
d = GetLastError();
|
||
|
|
||
|
DebugPrintEx(DPFLTR_TRACE_LEVEL,L"WOWREG32: ...dll not loaded (%u)\n",d);
|
||
|
|
||
|
WriteLogEntry(
|
||
|
OleControlData->LogContext,
|
||
|
SETUP_LOG_ERROR|SETUP_LOG_BUFFER,
|
||
|
MSG_LOG_OLE_CONTROL_LOADLIBRARY_FAILED,
|
||
|
NULL,
|
||
|
OleControlData->FullPath
|
||
|
);
|
||
|
WriteLogError(
|
||
|
OleControlData->LogContext,
|
||
|
SETUP_LOG_ERROR,
|
||
|
d
|
||
|
);
|
||
|
|
||
|
} else {
|
||
|
DebugPrintEx(DPFLTR_TRACE_LEVEL,L"WOWREG32: ...dll loaded\n");
|
||
|
}
|
||
|
|
||
|
return d;
|
||
|
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
RegisterUnregisterControl(
|
||
|
PWOW_IPC_REGION_TOSURRAGATE RegistrationData,
|
||
|
PDWORD FailureCode
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
main registration routine for registering a dll.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
RegistrationData - pointer to WOW_IPC_REGION_TOSURRAGATE structure indicating
|
||
|
file to be processed
|
||
|
FailureCode - SPREG_* code indicating outcome of operation.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Win32 error code indicating outcome.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
LPEXCEPTION_POINTERS ExceptionPointers = NULL;
|
||
|
HMODULE ControlDll = NULL;
|
||
|
PTSTR Extension;
|
||
|
DWORD d = NO_ERROR;
|
||
|
DWORD Count;
|
||
|
OLE_CONTROL_DATA OleControlData;
|
||
|
WCHAR Path[MAX_PATH];
|
||
|
PWSTR p;
|
||
|
|
||
|
//
|
||
|
// could use CoInitializeEx as an optimization as OleInitialize is
|
||
|
// probably overkill...but this is probably just a perf hit at
|
||
|
// worst
|
||
|
//
|
||
|
DebugPrintEx(DPFLTR_TRACE_LEVEL,L"WOWREG32: calling OleInitialize\n");
|
||
|
|
||
|
OleControlData.FullPath = RegistrationData->FullPath;
|
||
|
OleControlData.Argument = RegistrationData->Argument;
|
||
|
OleControlData.LogContext = NULL;
|
||
|
OleControlData.Register = RegistrationData->Register;
|
||
|
OleControlData.RegType = RegistrationData->RegType;
|
||
|
|
||
|
wcscpy(Path,RegistrationData->FullPath);
|
||
|
p = wcsrchr(Path,'\\');
|
||
|
if (p) {
|
||
|
*p = L'\0';
|
||
|
}
|
||
|
|
||
|
SetCurrentDirectory( Path );
|
||
|
|
||
|
d = (DWORD)OleInitialize(NULL);
|
||
|
if (d != NO_ERROR) {
|
||
|
*FailureCode = SPREG_UNKNOWN;
|
||
|
DebugPrintEx(DPFLTR_ERROR_LEVEL,L"WOWREG32: OleInitialize failed, ec = 0x%08x\n", d);
|
||
|
goto clean0;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
DebugPrintEx(DPFLTR_TRACE_LEVEL,L"WOWREG32: back from OleInitialize\n");
|
||
|
|
||
|
try {
|
||
|
//
|
||
|
// protect everything in TRY-EXCEPT, we're calling unknown code (DLL's)
|
||
|
//
|
||
|
d = pSetupRegisterLoadDll( &OleControlData, &ControlDll );
|
||
|
|
||
|
if (d == NO_ERROR) {
|
||
|
|
||
|
//
|
||
|
// We successfully loaded it. Now call the appropriate routines.
|
||
|
//
|
||
|
//
|
||
|
// On register, do DLLREGISTER, then DLLINSTALL
|
||
|
// On unregister, do DLLINSTALL, then DLLREGISTER
|
||
|
//
|
||
|
if (OleControlData.Register) {
|
||
|
|
||
|
if (OleControlData.RegType & FLG_REGSVR_DLLREGISTER && (d == NO_ERROR) ) {
|
||
|
|
||
|
d = pSetupRegisterDllRegister(
|
||
|
&OleControlData,
|
||
|
ControlDll,
|
||
|
FailureCode );
|
||
|
|
||
|
}
|
||
|
|
||
|
if (OleControlData.RegType & FLG_REGSVR_DLLINSTALL && (d == NO_ERROR) ) {
|
||
|
|
||
|
d = pSetupRegisterDllInstall(
|
||
|
&OleControlData,
|
||
|
ControlDll,
|
||
|
FailureCode );
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
|
||
|
if (OleControlData.RegType & FLG_REGSVR_DLLINSTALL && (d == NO_ERROR) ) {
|
||
|
|
||
|
d = pSetupRegisterDllInstall(
|
||
|
&OleControlData,
|
||
|
ControlDll,
|
||
|
FailureCode );
|
||
|
}
|
||
|
|
||
|
if (OleControlData.RegType & FLG_REGSVR_DLLREGISTER && (d == NO_ERROR) ) {
|
||
|
|
||
|
d = pSetupRegisterDllRegister(
|
||
|
&OleControlData,
|
||
|
ControlDll,
|
||
|
FailureCode );
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
ControlDll = NULL;
|
||
|
*FailureCode = SPREG_LOADLIBRARY;
|
||
|
}
|
||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
||
|
//
|
||
|
// If our exception was an AV, then use Win32 invalid param error, otherwise, assume it was
|
||
|
// an inpage error dealing with a mapped-in file.
|
||
|
//
|
||
|
d = ERROR_INVALID_DATA;
|
||
|
*FailureCode = SPREG_UNKNOWN;
|
||
|
}
|
||
|
|
||
|
if (ControlDll) {
|
||
|
FreeLibrary(ControlDll);
|
||
|
}
|
||
|
|
||
|
OleUninitialize();
|
||
|
|
||
|
DebugPrintEx(DPFLTR_TRACE_LEVEL,L"WOWREG32: back from OleUninitialize, exit RegisterUnregisterDll\n");
|
||
|
|
||
|
clean0:
|
||
|
|
||
|
if (d == NO_ERROR) {
|
||
|
*FailureCode = SPREG_SUCCESS;
|
||
|
}
|
||
|
|
||
|
SetLastError(d);
|
||
|
|
||
|
return (d == NO_ERROR);
|
||
|
|
||
|
}
|
||
|
|
||
|
|