windows-nt/Source/XPSP1/NT/ds/nw/install/setupdll/setvalue.c
2020-09-26 16:20:57 +08:00

697 lines
23 KiB
C

/**********************************************************************/
/** Microsoft Windows NT **/
/** Copyright(c) Microsoft Corp., 1991 **/
/**********************************************************************/
/*
setvalue.c
Code to enable SetValue for everyone.
history:
terryk 09/30/93 Created
*/
#if defined(DEBUG)
static const char szFileName[] = __FILE__;
#define _FILENAME_DEFINED_ONCE szFileName
#endif
#include <string.h>
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <nwlsa.h>
#include <nwapi.h>
#include <nwcfg.h>
#include <nwcfg.hxx>
extern char achBuff[];
// exported functions
BOOL FAR PASCAL SetFileSysChangeValue( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult );
BOOL FAR PASCAL SetEverybodyPermission( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult );
BOOL FAR PASCAL SetupRegistryForNWCS( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult );
BOOL FAR PASCAL SetupRegistryWorker( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult );
BOOL FAR PASCAL DeleteGatewayPassword( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult );
BOOL FAR PASCAL CleanupRegistryForNWCS( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult );
//
// structure for registry munging
//
typedef struct REG_ENTRY_ {
DWORD Operation ;
LONG Level ;
LPWSTR s1 ;
LPWSTR s2 ;
} REG_ENTRY ;
//
// local routines
//
DWORD SetupShellExtensions(REG_ENTRY RegEntries[], DWORD dwNumEntries) ;
typedef DWORD (*LPNWCLEANUPGATEWAYSHARES)(VOID) ;
// Values & Tables that define registry data
#define MAX_REG_LEVEL 10
#define CREATE_ABS 1 // create/open a key with absolute path
#define CREATE_REL 2 // create/open a key with relative path
#define VALUE_STR 3 // write a string value
#define DELETE_ABS 4 // delete key with absolute path
#define DELETE_REL 5 // delete key with relative path
#define DELETE_VAL 6 // delete a value
#define DROP_STACK 7 // drop stack by one
REG_ENTRY RegCreateEntries[] =
{
{CREATE_ABS,0,L"SOFTWARE\\Classes\\NetWare_or_Compatible_Network", NULL},
{DELETE_REL,0,L"shellex\\ContextMenuHandlers\\NetWareMenus", NULL},
{DELETE_REL,0,L"shellex\\ContextMenuHandlers", NULL},
{DELETE_REL,0,L"shellex\\PropertySheetHandlers\\NetWarePage", NULL},
{DELETE_REL,0,L"shellex\\PropertySheetHandlers", NULL},
{DELETE_REL,0,L"shellex", NULL},
{DROP_STACK,0,NULL,NULL},
{DELETE_ABS,0,L"SOFTWARE\\Classes\\NetWare_or_Compatible_Network", NULL},
{CREATE_ABS, 0,L"SOFTWARE\\Classes\\Network\\Type", NULL},
{CREATE_REL,+1, L"3", NULL},
{CREATE_REL,+1, L"shellex", NULL},
{CREATE_REL,+1, L"ContextMenuHandlers", NULL},
{CREATE_REL,+1, L"NetWareMenus", NULL},
{VALUE_STR,0, L"", L"{8e9d6600-f84a-11ce-8daa-00aa004a5691}"},
{CREATE_REL,-1, L"PropertySheetHandlers", NULL},
{CREATE_REL,+1, L"NetWarePage", NULL},
{VALUE_STR,0, L"", L"{8e9d6600-f84a-11ce-8daa-00aa004a5691}"},
{CREATE_ABS, 0,L"SOFTWARE\\Classes\\CLSID", NULL},
{CREATE_REL,+1, L"{8e9d6600-f84a-11ce-8daa-00aa004a5691}", NULL},
{VALUE_STR,0, L"", L"NetWare Objects"},
{CREATE_REL,+1, L"InProcServer32", NULL},
{VALUE_STR,0, L"", L"nwprovau.dll"},
{VALUE_STR,0, L"ThreadingModel", L"Apartment"},
{CREATE_REL,-1, L"{e3f2bac0-099f-11cf-8daa-00aa004a5691}", NULL},
{VALUE_STR,0, L"", L"NetWare UNC Folder Menu"},
{CREATE_REL,+1, L"InProcServer32", NULL},
{VALUE_STR,0, L"", L"nwprovau.dll"},
{VALUE_STR,0, L"ThreadingModel", L"Apartment"},
{CREATE_REL,-1, L"{52c68510-09a0-11cf-8daa-00aa004a5691}", NULL},
{VALUE_STR,0, L"", L"NetWare Hood Verbs"},
{CREATE_REL,+1, L"InProcServer32", NULL},
{VALUE_STR,0, L"", L"nwprovau.dll"},
{VALUE_STR,0, L"ThreadingModel", L"Apartment"},
{CREATE_REL,-1, L"{208D2C60-3AEA-1069-A2D7-08002B30309D}", NULL},
{CREATE_REL,+1, L"shellex", NULL},
{CREATE_REL,+1, L"ContextMenuHandlers", NULL},
{CREATE_REL,+1, L"NetWareMenus", NULL},
{VALUE_STR,0, L"", L"{52c68510-09a0-11cf-8daa-00aa004a5691}"},
{CREATE_ABS, 0,L"SOFTWARE\\Classes\\Folder", NULL},
{CREATE_REL,+1, L"shellex", NULL},
{CREATE_REL,+1, L"ContextMenuHandlers", NULL},
{CREATE_REL,+1, L"NetWareUNCMenu", NULL},
{VALUE_STR,0, L"", L"{e3f2bac0-099f-11cf-8daa-00aa004a5691}"},
{CREATE_ABS, 0,L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion", NULL},
{CREATE_REL,+1, L"Shell Extensions", NULL},
{CREATE_REL,+1, L"Approved", NULL},
{VALUE_STR,0, L"{8e9d6600-f84a-11ce-8daa-00aa004a5691}", L"Shell extensions for NetWare"},
{VALUE_STR,0, L"{e3f2bac0-099f-11cf-8daa-00aa004a5691}", L"Shell extensions for NetWare"},
{VALUE_STR,0, L"{52c68510-09a0-11cf-8daa-00aa004a5691}", L"Shell extensions for NetWare"}
} ;
REG_ENTRY RegDeleteEntries[] =
{
{CREATE_ABS,0,L"SOFTWARE\\Classes\\Network\\Type\\3", NULL},
{DELETE_REL,0,L"shellex\\ContextMenuHandlers\\NetWareMenus", NULL},
{DELETE_REL,0,L"shellex\\ContextMenuHandlers", NULL},
{DELETE_REL,0,L"shellex\\PropertySheetHandlers\\NetWarePage", NULL},
{DELETE_REL,0,L"shellex\\PropertySheetHandlers", NULL},
{DELETE_REL,0,L"shellex", NULL},
{DROP_STACK,0,NULL,NULL},
{DELETE_ABS,0,L"SOFTWARE\\Classes\\Network\\Type\\3", NULL},
{DELETE_ABS,0,L"SOFTWARE\\Classes\\CLSID\\{8e9d6600-f84a-11ce-8daa-00aa004a5691}\\InProcServer32", NULL},
{DELETE_ABS,0,L"SOFTWARE\\Classes\\CLSID\\{8e9d6600-f84a-11ce-8daa-00aa004a5691}", NULL},
{DELETE_ABS,0,L"SOFTWARE\\Classes\\CLSID\\{e3f2bac0-099f-11cf-8daa-00aa004a5691}\\InProcServer32", NULL},
{DELETE_ABS,0,L"SOFTWARE\\Classes\\CLSID\\{e3f2bac0-099f-11cf-8daa-00aa004a5691}", NULL},
{DELETE_ABS,0,L"SOFTWARE\\Classes\\CLSID\\{52c68510-09a0-11cf-8daa-00aa004a5691}\\InProcServer32", NULL},
{DELETE_ABS,0,L"SOFTWARE\\Classes\\CLSID\\{52c68510-09a0-11cf-8daa-00aa004a5691}", NULL},
{DELETE_ABS,0,L"SOFTWARE\\Classes\\CLSID\\{208D2C60-3AEA-1069-A2D7-08002B30309D}\\shellex\\ContextMenuHandlers\\NetWareMenus", NULL},
{DELETE_ABS,0,L"SOFTWARE\\Classes\\Folder\\shellex\\ContextMenuHandlers\\NetWareUNCMenu", NULL},
{CREATE_ABS,0,L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved", NULL},
{DELETE_VAL,0,L"{8e9d6600-f84a-11ce-8daa-00aa004a5691}", NULL},
{DELETE_VAL,0,L"{e3f2bac0-099f-11cf-8daa-00aa004a5691}", NULL},
{DELETE_VAL,0,L"{52c68510-09a0-11cf-8daa-00aa004a5691}", NULL}
} ;
/*******************************************************************
NAME: SetEverybodyPermission
SYNOPSIS: Set the registry key to everybody "Set Value" (or whatever
the caller want.) This is called from the inf file
ENTRY: Registry key as the first parameter
Permisstion type as the second parameter
RETURN: BOOL - TRUE for success.
HISTORY:
terryk 07-May-1993 Created
********************************************************************/
typedef DWORD (*T_SetPermission)(HKEY hKey, DWORD dwPermission);
BOOL FAR PASCAL SetEverybodyPermission( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult )
{
HKEY hKey = (HKEY)atol( &(apszArgs[0][1]) ); // registry key
DWORD dwPermission = atol( apszArgs[1] ); // permission value
DWORD err = ERROR_SUCCESS;
do {
HINSTANCE hDll = LoadLibraryA( "nwapi32.dll" );
FARPROC pSetPermission = NULL;
if ( hDll == NULL )
{
err = GetLastError();
break;
}
pSetPermission = GetProcAddress( hDll, "NwLibSetEverybodyPermission" );
if ( pSetPermission == NULL )
{
err = GetLastError();
break;
}
err = (*(T_SetPermission)pSetPermission)( hKey, dwPermission );
} while ( FALSE );
wsprintfA( achBuff, "{\"%d\"}", err );
*ppszResult = achBuff;
return( err == ERROR_SUCCESS );
}
/*******************************************************************
NAME: SetFileSysChangeValue
SYNOPSIS: calls common setup routine. this old entry point is
is left here to handle any DLL/INF mismatch.
ENTRY: NONE from inf file.
RETURN: BOOL - TRUE for success.
(always return TRUE)
HISTORY:
chuckc 29-Oct-1993 Created
********************************************************************/
BOOL FAR PASCAL SetFileSysChangeValue( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult )
{
return SetupRegistryWorker( nArgs, apszArgs, ppszResult );
}
/*******************************************************************
NAME: SetupRegistryForNWCS
SYNOPSIS: calls common worker routine to setup registry.
ENTRY: NONE from inf file.
RETURN: BOOL - TRUE for success.
(always return TRUE)
HISTORY:
chuckc 29-Oct-1993 Created
********************************************************************/
BOOL FAR PASCAL SetupRegistryForNWCS( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult )
{
return SetupRegistryWorker( nArgs, apszArgs, ppszResult );
}
/*******************************************************************
NAME: SetupRegistryWorker
SYNOPSIS: set the FileSysChangeValue to please NETWARE.DRV.
also set win.ini parameter so wfwnet.drv knows we are there.
ENTRY: NONE from inf file.
RETURN: BOOL - TRUE for success.
(always return TRUE)
HISTORY:
chuckc 29-Oct-1993 Created
********************************************************************/
BOOL FAR PASCAL SetupRegistryWorker( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult )
{
DWORD err = 0, err1 = 0 ;
(void) nArgs ; // quiet the compiler
(void) apszArgs ; // quiet the compiler
if (!WriteProfileStringA("NWCS",
"NwcsInstalled",
"1"))
{
err = GetLastError() ;
}
if (!WritePrivateProfileStringA("386Enh",
"FileSysChange",
"off",
"system.ini"))
{
err1 = GetLastError() ;
}
if (err1 == NO_ERROR)
{
err1 = SetupShellExtensions(
RegCreateEntries,
sizeof(RegCreateEntries)/sizeof(RegCreateEntries[0])) ;
}
wsprintfA( achBuff, "{\"%d\"}", err ? err : err1 );
*ppszResult = achBuff;
return TRUE;
}
#define NWCLEANUPGATEWAYSHARES_NAME "NwCleanupGatewayShares"
#define NWPROVAU_DLL_NAME L"NWPROVAU"
/*******************************************************************
NAME: DeleteGatewayPassword
SYNOPSIS: delete the LSA secret used for gateway password.
also clears the NWCS installed bit. INF will be
changed to call CleanupRegistryForNWCS, but this entry
point is left here to handle DLL/INF mismatch.
ENTRY: NONE from inf file.
RETURN: BOOL - TRUE for success.
(always return TRUE)
HISTORY:
chuckc 29-Oct-1993 Created
********************************************************************/
BOOL FAR PASCAL
DeleteGatewayPassword(
DWORD nArgs,
LPSTR apszArgs[],
LPSTR * ppszResult
)
{
return TRUE ; // work is done in cleanup below which does everything.
}
/*******************************************************************
NAME: CleanupRegistryForNWCS
SYNOPSIS: delete the LSA secret used for gateway password.
also set flag that NWCS has been removed. this flag
is used by wfwnet.drv.
ENTRY: NONE from inf file.
RETURN: BOOL - TRUE for success.
(always return TRUE)
HISTORY:
chuckc 29-Oct-1993 Created
********************************************************************/
BOOL FAR PASCAL
CleanupRegistryForNWCS(
DWORD nArgs,
LPSTR apszArgs[],
LPSTR * ppszResult
)
{
HANDLE hDll ;
DWORD err = 0, err1 = 0 ;
LPNWCLEANUPGATEWAYSHARES lpfnNwCleanupGatewayShares = NULL ;
(void) nArgs ; // quiet the compiler
(void) apszArgs ; // quiet the compiler
if (!WriteProfileStringA("NWCS",
"NwcsInstalled",
"0"))
{
err = GetLastError() ;
}
err1 = NwDeletePassword(GATEWAY_USER) ;
if (!err)
err = err1 ;
if ((hDll = LoadLibraryW(NWPROVAU_DLL_NAME)) &&
(lpfnNwCleanupGatewayShares = (LPNWCLEANUPGATEWAYSHARES)
GetProcAddress(hDll, NWCLEANUPGATEWAYSHARES_NAME)))
{
err1 = (*lpfnNwCleanupGatewayShares)() ;
(void) FreeLibrary(hDll) ;
}
//
// ignore errors for this.
//
(void) SetupShellExtensions(
RegDeleteEntries,
sizeof(RegDeleteEntries)/sizeof(RegDeleteEntries[0])) ;
if (!err)
err = err1 ;
wsprintfA( achBuff, "{\"%d\"}", err );
*ppszResult = achBuff;
return TRUE;
}
/*******************************************************************
NAME: SetupShellExtensions
SYNOPSIS: setup the registry for shell extensions. function is driven
by a table of entries (RegEntries). for each entry there is a
Operation code that tells us what we are doing. key entries can
be created absolute or relative to previous positions, so we
maintain a stack of registry handles for the latter case. every
key that is created is initially put on the stack. values
are always written based on the 'current stack' position.
ENTRY: NONE
RETURN: Win32 error code
HISTORY:
chuckc 29-Nov-1995 Created
********************************************************************/
DWORD SetupShellExtensions(REG_ENTRY RegEntries[], DWORD dwNumEntries)
{
DWORD err, errClose, dwDisposition, i ;
HKEY hKey, RegHandleStack[MAX_REG_LEVEL] ;
LONG StackIndex = -1 ;
//
// Loop thru and for each entry. Then switch & do the appropriate
// operation in the registry.
//
for (i = 0; i < dwNumEntries; i++)
{
err = NO_ERROR ;
switch (RegEntries[i].Operation)
{
case CREATE_ABS:
//
// create/open a reg key with an absolute path. since this
// is absolute, we drop everything on the stack, and start
// all over again.
//
while (StackIndex >= 0)
{
errClose = RegCloseKey(RegHandleStack[StackIndex--]) ;
ASSERT(errClose == NO_ERROR) ;
}
err = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
RegEntries[i].s1, // subkey
0, // reserved
NULL, // class
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL, // default security
&hKey,
&dwDisposition) ; // not used
if (err != NO_ERROR)
{
break ;
}
//
// by default we advance the stack. no need check for overflow
// as the stack is empty.
//
RegHandleStack[++StackIndex] = hKey ;
break ;
case CREATE_REL:
//
// create/open a reg key relative to current stack. make sure
// there is something on the stack (check StackIndex >= 0).
// then see if we are advancing (+1), staying the same (0) or
// dropping back (-ve).
//
if (StackIndex < 0)
{
err = ERROR_INVALID_FUNCTION ;
break ;
}
if (RegEntries[i].Level == +1)
{
//
// opening next level down. continue as is and use
// most recently opened key as the starting point.
//
}
else if (RegEntries[i].Level == 0)
{
//
// opening at same level as last time. so we are done
// with the last key. what we want to do is close it
// and use the parent.
//
errClose = RegCloseKey(RegHandleStack[StackIndex--]) ;
ASSERT(errClose == NO_ERROR) ;
if (StackIndex < 0)
{
err = ERROR_INVALID_FUNCTION ;
break ;
}
}
else if (RegEntries[i].Level < 0)
{
//
// dropping back & opening at a higher level. cleanup
// handle for each level we pop.
//
LONG Count = RegEntries[i].Level ;
while (Count++ < 1)
{
errClose = RegCloseKey(RegHandleStack[StackIndex--]) ;
ASSERT(errClose == NO_ERROR) ;
if (StackIndex < -1)
{
err = ERROR_INVALID_FUNCTION ;
break ;
}
}
}
else
{
//
// only -ve numbers, 0 and 1 are valid
//
err = ERROR_INVALID_FUNCTION ;
break ;
}
//
// create key relative to current point
//
err = RegCreateKeyExW(RegHandleStack[StackIndex], // current key
RegEntries[i].s1, // subkey
0, // reserved
NULL, // class
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL, // default security
&hKey,
&dwDisposition) ; // not used
if (err != NO_ERROR)
{
break ;
}
//
// by default we advance the stack
//
RegHandleStack[++StackIndex] = hKey ;
if (StackIndex >= MAX_REG_LEVEL)
{
err = ERROR_INVALID_FUNCTION ;
break ;
}
break ;
case VALUE_STR:
//
// create a REG_SZ value at current point. check we have
// handle on stack.
//
if (StackIndex < 0)
{
err = ERROR_INVALID_FUNCTION ;
break ;
}
err = RegSetValueExW(
RegHandleStack[StackIndex], // current key
RegEntries[i].s1, // value name
0, // reserved
REG_SZ,
(BYTE *)RegEntries[i].s2, // value data
(wcslen(RegEntries[i].s2)+1)*sizeof(WCHAR)) ;
break ;
case DELETE_ABS:
//
// delete a key (absolute). no change to stack.
//
err = RegDeleteKeyW(HKEY_LOCAL_MACHINE,
RegEntries[i].s1) ; // subkey
if ( err == ERROR_FILE_NOT_FOUND )
err = NO_ERROR;
break ;
case DELETE_REL:
//
// delete a key (relative). no change to stack.
//
if (StackIndex < 0)
{
err = ERROR_INVALID_FUNCTION ;
break ;
}
err = RegDeleteKeyW(RegHandleStack[StackIndex], // current key
RegEntries[i].s1) ; // subkey
if ( err == ERROR_FILE_NOT_FOUND )
err = NO_ERROR;
break ;
case DELETE_VAL:
//
// delete value at current point. check we have handle on stack.
//
if (StackIndex < 0)
{
err = ERROR_INVALID_FUNCTION ;
break ;
}
err = RegDeleteValueW(RegHandleStack[StackIndex], // current key
RegEntries[i].s1) ; // value name
break ;
case DROP_STACK:
//
// drop current stack by one (closing the handle).
//
if (StackIndex < 0)
{
err = ERROR_INVALID_FUNCTION ;
break ;
}
errClose = RegCloseKey(RegHandleStack[StackIndex--]) ;
ASSERT(errClose == NO_ERROR) ;
break ;
default:
//
// error out if unknown operation
//
err = ERROR_INVALID_FUNCTION ;
break ;
}
if (err != NO_ERROR)
{
break ;
}
}
//
// cleanup open handles on the stack
//
while (StackIndex >= 0)
{
errClose = RegCloseKey(RegHandleStack[StackIndex--]) ;
ASSERT(errClose == NO_ERROR) ;
}
return err ;
}