windows-nt/Source/XPSP1/NT/base/pnp/setupapi/wowreg32/wowreg.c

1028 lines
25 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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);
}