534 lines
14 KiB
C++
534 lines
14 KiB
C++
// tsuserex.cpp : Implementation of DLL Exports.
|
|
|
|
|
|
// Note: Proxy/Stub Information
|
|
// To build a separate proxy/stub DLL,
|
|
// run nmake -f tsexusrmps.mk in the project directory.
|
|
|
|
#include "stdafx.h"
|
|
#include "resource.h"
|
|
#include "initguid.h"
|
|
#include "tsuserex.h" // generated file. class ids.
|
|
#include "tsuserex_i.c" // generated file. class ids.
|
|
#include "interfaces.h" // Definition of the TSUserExInterfaces class
|
|
#ifdef _RTM_
|
|
#include "tsusrcpy.h"
|
|
#endif
|
|
|
|
#define GUIDSIZE 40
|
|
|
|
TCHAR tchSnapinRegKey[] = TEXT( "Software\\Microsoft\\MMC\\SnapIns\\" );
|
|
|
|
TCHAR tchNodeRegKey[] = TEXT( "Software\\Microsoft\\MMC\\NodeTypes\\" );
|
|
|
|
TCHAR tchExtKey[] = TEXT( "\\Extensions\\PropertySheet" );
|
|
|
|
HRESULT Local_RegisterNodeType( const GUID *pGuidNodeType , const GUID *pGuidExtension , LPTSTR szDescription );
|
|
|
|
HRESULT Local_RegisterSnapinExt( const GUID *pGuidToRegister , const GUID *pAboutGuid , LPTSTR szNameString , LPTSTR szProvider , LPTSTR szVersion );
|
|
|
|
HRESULT Local_VerifyNodeType( const GUID *pGuidSnapin , const GUID *pGuidSnapinNodeTypeToVerify );
|
|
|
|
HINSTANCE ghInstance;
|
|
HINSTANCE GetInstance()
|
|
{
|
|
return ghInstance;
|
|
}
|
|
|
|
CComModule _Module;
|
|
|
|
// this object has IExtendPropertySheet interface.
|
|
BEGIN_OBJECT_MAP(ObjectMap)
|
|
OBJECT_ENTRY(CLSID_TSUserExInterfaces, TSUserExInterfaces)
|
|
#ifdef _RTM_
|
|
OBJECT_ENTRY(CLSID_ExtCopyNoUI, CExtCopyNoUI )
|
|
#endif
|
|
END_OBJECT_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// DLL Entry Point
|
|
|
|
extern "C"
|
|
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
|
{
|
|
if (dwReason == DLL_PROCESS_ATTACH)
|
|
{
|
|
ghInstance = hInstance;
|
|
|
|
_Module.Init(ObjectMap, hInstance);
|
|
|
|
DisableThreadLibraryCalls(hInstance);
|
|
|
|
|
|
}
|
|
else if (dwReason == DLL_PROCESS_DETACH)
|
|
{
|
|
// LOGMESSAGE0(_T("DllMain::Process being Detached..."));
|
|
_Module.Term();
|
|
}
|
|
return TRUE; // ok
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Used to determine whether the DLL can be unloaded by OLE
|
|
|
|
STDAPI DllCanUnloadNow(void)
|
|
{
|
|
// LOGMESSAGE1(_T("DllCanUnloadNow..Returing %s"), _Module.GetLockCount()==0 ? _T("S_OK") : _T("S_FALSE"));
|
|
return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
|
|
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Returns a class factory to create an object of the requested type
|
|
|
|
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
|
|
{
|
|
// LOGMESSAGE0(_T("DllGetClassObject.."));
|
|
return _Module.GetClassObject(rclsid, riid, ppv);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// DllRegisterServer - Adds entries to the system registry
|
|
|
|
/* extern */ const CLSID CLSID_LocalUser =
|
|
{ /* 5d6179c8-17ec-11d1-9aa9-00c04fd8fe93 */
|
|
0x5d6179c8,
|
|
0x17ec,
|
|
0x11d1,
|
|
{0x9a, 0xa9, 0x00, 0xc0, 0x4f, 0xd8, 0xfe, 0x93}
|
|
};
|
|
/* extern */ const GUID NODETYPE_User =
|
|
{ /* 5d6179cc-17ec-11d1-9aa9-00c04fd8fe93 */
|
|
0x5d6179cc,
|
|
0x17ec,
|
|
0x11d1,
|
|
{0x9a, 0xa9, 0x00, 0xc0, 0x4f, 0xd8, 0xfe, 0x93}
|
|
};
|
|
|
|
|
|
// /* extern */ const GUID NODETYPE_DSUser =
|
|
//{ /* 228D9A84-C302-11CF-9AA4-00AA004A5691 */
|
|
// 0x228D9A84,
|
|
// 0xC302,
|
|
// 0x11CF,
|
|
// {0x9A, 0xA4, 0x00, 0xAA, 0x00, 0x4A, 0x56, 0x91}
|
|
//};
|
|
|
|
|
|
// DS Snapin CLSID - {E355E538-1C2E-11d0-8C37-00C04FD8FE93}
|
|
const GUID CLSID_DSSnapin =
|
|
{
|
|
0xe355e538,
|
|
0x1c2e,
|
|
0x11d0,
|
|
{0x8c, 0x37, 0x0, 0xc0, 0x4f, 0xd8, 0xfe, 0x93}
|
|
};
|
|
|
|
|
|
/* extern */ const GUID NODETYPE_DSUser =
|
|
{ /* BF967ABA-0DE6-11D0-A285-00AA003049E2 */
|
|
0xBF967ABA,
|
|
0x0DE6,
|
|
0x11D0,
|
|
{0xA2, 0x85, 0x00, 0xAA, 0x00, 0x30, 0x49, 0xE2}
|
|
};
|
|
// bf967aba0de611d0a28500aa003049e2
|
|
|
|
|
|
|
|
STDAPI DllRegisterServer(void)
|
|
{
|
|
TCHAR tchNameString[ 160 ];
|
|
TCHAR tchProvider[ 160 ];
|
|
TCHAR tchVersion[ 16 ];
|
|
|
|
HRESULT hr = _Module.RegisterServer(TRUE);
|
|
|
|
if( SUCCEEDED( hr ) )
|
|
{
|
|
// register it as extension to localsecurity snapin
|
|
|
|
VERIFY_E( 0 , LoadString( _Module.GetResourceInstance( ) , IDS_NAMESTRING_SNAPIN , tchNameString , sizeof( tchNameString ) / sizeof( TCHAR ) ) );
|
|
|
|
VERIFY_E( 0 , LoadString( _Module.GetResourceInstance( ) , IDS_PROVIDER_SNAPIN , tchProvider , sizeof( tchProvider ) / sizeof( TCHAR ) ) );
|
|
|
|
VERIFY_E( 0 , LoadString( _Module.GetResourceInstance( ) , IDS_VERSION_SNAPIN , tchVersion , sizeof( tchVersion ) / sizeof( TCHAR ) ) );
|
|
|
|
|
|
hr = Local_RegisterSnapinExt( &CLSID_TSUserExInterfaces ,
|
|
&CLSID_TSUserExInterfaces ,
|
|
tchNameString ,
|
|
tchProvider ,
|
|
tchVersion
|
|
);
|
|
}
|
|
|
|
if( SUCCEEDED( hr ) )
|
|
{
|
|
hr = Local_RegisterNodeType( &NODETYPE_User , &CLSID_TSUserExInterfaces , _T( "Terminal Server property page extension" ) );
|
|
}
|
|
|
|
if( SUCCEEDED( hr ) )
|
|
{
|
|
// the dsadmin snapin does not list all its node, as there are lot of them
|
|
// so before registring ourself to extend the node,
|
|
// lets write the nodeType we are going to extend into registry ourselves
|
|
|
|
hr = Local_VerifyNodeType( &CLSID_DSSnapin , &NODETYPE_DSUser );
|
|
}
|
|
|
|
if( SUCCEEDED( hr ) )
|
|
{
|
|
hr = Local_RegisterNodeType( &NODETYPE_DSUser , &CLSID_TSUserExInterfaces , _T( "Terminal Server property page extension" ) );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Local_VerifyNodeType
|
|
// Checks first to see if NodeType exists, if not it'll create it
|
|
//---------------------------------------------------------------------------
|
|
HRESULT Local_VerifyNodeType( const GUID *pGuidSnapin , const GUID *pGuidSnapinNodeTypeToVerify )
|
|
{
|
|
OLECHAR szSnapin[ GUIDSIZE ];
|
|
|
|
OLECHAR szSnapinNodeType[ GUIDSIZE ];
|
|
|
|
HKEY hKey;
|
|
|
|
ASSERT_( pGuidSnapin != NULL );
|
|
|
|
ASSERT_( pGuidSnapinNodeTypeToVerify != NULL );
|
|
|
|
TCHAR tchRegKeyName[ MAX_PATH ];
|
|
|
|
if( StringFromGUID2( *pGuidSnapin , szSnapin , GUIDSIZE ) == 0 )
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if( StringFromGUID2( *pGuidSnapinNodeTypeToVerify , szSnapinNodeType , GUIDSIZE ) == 0 )
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
lstrcpy( tchRegKeyName , tchSnapinRegKey );
|
|
|
|
lstrcat( tchRegKeyName , szSnapin );
|
|
|
|
lstrcat( tchRegKeyName , _T( "\\NodeTypes\\" ) );
|
|
|
|
lstrcat( tchRegKeyName , szSnapinNodeType );
|
|
|
|
if( RegOpenKeyEx( HKEY_LOCAL_MACHINE , tchRegKeyName , 0 , KEY_READ , &hKey ) != ERROR_SUCCESS )
|
|
{
|
|
// Key does not exist
|
|
// Create the nodetype in snapin and in NodeType
|
|
|
|
DWORD disp;
|
|
|
|
if( RegCreateKeyEx( HKEY_LOCAL_MACHINE , tchRegKeyName , 0 , NULL , REG_OPTION_NON_VOLATILE , KEY_ALL_ACCESS , NULL , &hKey , &disp ) != ERROR_SUCCESS )
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
RegCloseKey( hKey );
|
|
|
|
lstrcpy( tchRegKeyName , tchNodeRegKey );
|
|
|
|
lstrcat( tchRegKeyName , szSnapinNodeType );
|
|
|
|
if( RegCreateKeyEx( HKEY_LOCAL_MACHINE , tchRegKeyName , 0 , NULL , REG_OPTION_NON_VOLATILE , KEY_ALL_ACCESS , NULL , &hKey , &disp ) != ERROR_SUCCESS )
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
}
|
|
|
|
RegCloseKey( hKey );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Local_RegisterSnapinExt
|
|
// Creates the extension node reg keys
|
|
//---------------------------------------------------------------------------
|
|
HRESULT Local_RegisterSnapinExt( const GUID *pGuidToRegister , const GUID *pAboutGuid , LPTSTR szNameString , LPTSTR szProvider , LPTSTR szVersion )
|
|
{
|
|
OLECHAR szGuid[ GUIDSIZE ];
|
|
|
|
TCHAR tchRegKeyName[ MAX_PATH ];
|
|
|
|
HKEY hKey;
|
|
|
|
HKEY hSubKey = NULL;
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
ASSERT_( pGuidToRegister != NULL );
|
|
ASSERT_( pAboutGuid != NULL );
|
|
ASSERT_( szNameString != NULL );
|
|
ASSERT_( szProvider != NULL );
|
|
ASSERT_( szVersion != NULL );
|
|
|
|
lstrcpy( tchRegKeyName , tchSnapinRegKey );
|
|
|
|
if( StringFromGUID2( *pGuidToRegister , szGuid , GUIDSIZE ) == 0 )
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
lstrcat( tchRegKeyName , szGuid );
|
|
|
|
DWORD disp;
|
|
|
|
do
|
|
{
|
|
if( RegCreateKeyEx( HKEY_LOCAL_MACHINE , tchRegKeyName , 0 , NULL , REG_OPTION_NON_VOLATILE , KEY_ALL_ACCESS , NULL , &hKey , &disp ) == ERROR_SUCCESS )
|
|
{
|
|
// if the key exist overwrite any and all values
|
|
|
|
OLECHAR szAboutGuid[ GUIDSIZE ];
|
|
|
|
if( StringFromGUID2( *pAboutGuid , szAboutGuid , GUIDSIZE ) > 0 )
|
|
{
|
|
RegSetValueEx( hKey , L"About" , 0 , REG_SZ , ( LPBYTE )szAboutGuid , sizeof( szAboutGuid ) );
|
|
}
|
|
|
|
// these calls should not fail but I'll test for it
|
|
|
|
VERIFY_S( ERROR_SUCCESS , RegSetValueEx( hKey , L"NameString" , 0 , REG_SZ , ( LPBYTE )szNameString , sizeof( TCHAR ) * ( lstrlen( szNameString ) + 1 ) ) );
|
|
|
|
VERIFY_S( ERROR_SUCCESS , RegSetValueEx( hKey , L"Provider" , 0 , REG_SZ , ( LPBYTE )szProvider , sizeof( TCHAR ) * ( lstrlen( szProvider ) + 1 ) ) );
|
|
|
|
VERIFY_S( ERROR_SUCCESS , RegSetValueEx( hKey , L"Version" , 0 , REG_SZ , ( LPBYTE )szVersion , sizeof( TCHAR ) * ( lstrlen( szVersion ) + 1 ) ) );
|
|
|
|
/*
|
|
lstrcpy( tchRegKeyName , L"NodeTypes\\" );
|
|
|
|
lstrcat( tchRegKeyName , szGuid );
|
|
|
|
if( RegCreateKeyEx( hKey , tchRegKeyName , 0 , NULL , REG_OPTION_NON_VOLATILE , KEY_ALL_ACCESS , NULL , &hSubKey , &disp ) == ERROR_SUCCESS )
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
*/
|
|
hr = S_OK;
|
|
}
|
|
|
|
} while( 0 );
|
|
|
|
RegCloseKey( hSubKey );
|
|
|
|
RegCloseKey( hKey );
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Local_RegisterNodeType
|
|
// pGuidToExt is the snapin we want to extend
|
|
// pGuidNodeType is the node in the snapin we'll register under
|
|
// pGuidExtension is us the property sheet extension
|
|
//---------------------------------------------------------------------------
|
|
HRESULT Local_RegisterNodeType( const GUID *pGuidNodeType , const GUID *pGuidExtension , LPTSTR szDescription )
|
|
{
|
|
OLECHAR szGuidNode[ GUIDSIZE ];
|
|
|
|
OLECHAR szGuidExt[ GUIDSIZE ];
|
|
|
|
TCHAR tchRegKeyName[ MAX_PATH ];
|
|
|
|
HKEY hKey;
|
|
|
|
ASSERT_( pGuidNodeType != NULL );
|
|
ASSERT_( pGuidExtension != NULL );
|
|
ASSERT_( szDescription != NULL );
|
|
|
|
lstrcpy( tchRegKeyName , tchNodeRegKey );
|
|
|
|
|
|
if( StringFromGUID2( *pGuidNodeType , szGuidNode , GUIDSIZE ) == 0 )
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if( StringFromGUID2( *pGuidExtension , szGuidExt , GUIDSIZE ) == 0 )
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
lstrcat( tchRegKeyName , szGuidNode );
|
|
|
|
lstrcat( tchRegKeyName , tchExtKey );
|
|
|
|
if( RegCreateKey( HKEY_LOCAL_MACHINE , tchRegKeyName , &hKey ) != ERROR_SUCCESS )
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
RegSetValueEx( hKey , szGuidExt , 0 , REG_SZ , ( LPBYTE )szDescription , sizeof( TCHAR ) * ( lstrlen( szDescription ) + 1 ) );
|
|
|
|
RegCloseKey( hKey );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Delete a key and all of its descendents.
|
|
//---------------------------------------------------------------------------
|
|
LONG RecursiveDeleteKey( HKEY hKeyParent , LPTSTR lpszKeyChild )
|
|
{
|
|
// Open the child.
|
|
HKEY hKeyChild;
|
|
|
|
LONG lRes = RegOpenKeyEx(hKeyParent, lpszKeyChild , 0 , KEY_ALL_ACCESS, &hKeyChild);
|
|
|
|
if (lRes != ERROR_SUCCESS)
|
|
{
|
|
return lRes;
|
|
}
|
|
|
|
// Enumerate all of the decendents of this child.
|
|
|
|
FILETIME time;
|
|
|
|
TCHAR szBuffer[256];
|
|
|
|
DWORD dwSize = sizeof( szBuffer ) / sizeof( TCHAR );
|
|
|
|
while( RegEnumKeyEx( hKeyChild , 0 , szBuffer , &dwSize , NULL , NULL , NULL , &time ) == S_OK )
|
|
{
|
|
// Delete the decendents of this child.
|
|
|
|
lRes = RecursiveDeleteKey(hKeyChild, szBuffer);
|
|
|
|
if (lRes != ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey(hKeyChild);
|
|
|
|
return lRes;
|
|
}
|
|
|
|
dwSize = sizeof( szBuffer ) / sizeof( TCHAR );
|
|
}
|
|
|
|
// Close the child.
|
|
|
|
RegCloseKey( hKeyChild );
|
|
|
|
// Delete this child.
|
|
|
|
return RegDeleteKey( hKeyParent , lpszKeyChild );
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Local_UnRegisterSnapinExt
|
|
// reconstruct the enter key then delete key
|
|
//---------------------------------------------------------------------------
|
|
HRESULT Local_UnRegisterSnapinExt( const GUID *pGuidExt )
|
|
{
|
|
TCHAR tchRegKeyName[ MAX_PATH ];
|
|
|
|
OLECHAR szGuidExt[ GUIDSIZE ];
|
|
|
|
ASSERT_( pGuidExt != NULL );
|
|
|
|
lstrcpy( tchRegKeyName , tchSnapinRegKey );
|
|
|
|
if( StringFromGUID2( *pGuidExt , szGuidExt , GUIDSIZE ) == 0 )
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
lstrcat( tchRegKeyName , szGuidExt );
|
|
|
|
if( RecursiveDeleteKey( HKEY_LOCAL_MACHINE , tchRegKeyName ) == ERROR_SUCCESS )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Local_UnregisterNodeType
|
|
//---------------------------------------------------------------------------
|
|
HRESULT Local_UnregisterNodeType( const GUID *pGuid , const GUID *pDeleteThisGuid )
|
|
{
|
|
OLECHAR szGuid[ GUIDSIZE ];
|
|
|
|
OLECHAR szDeleteThisGuid[ GUIDSIZE ];
|
|
|
|
HKEY hKey;
|
|
|
|
ASSERT_( pGuid != NULL );
|
|
ASSERT_( pDeleteThisGuid != NULL );
|
|
|
|
TCHAR tchRegKeyName[ MAX_PATH ];
|
|
|
|
lstrcpy( tchRegKeyName , tchNodeRegKey );
|
|
|
|
if( StringFromGUID2( *pGuid , szGuid , GUIDSIZE ) == 0 )
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
if( StringFromGUID2( *pDeleteThisGuid , szDeleteThisGuid , GUIDSIZE ) == 0 )
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
lstrcat( tchRegKeyName , szGuid );
|
|
|
|
lstrcat( tchRegKeyName , tchExtKey );
|
|
|
|
if( RegOpenKey( HKEY_LOCAL_MACHINE , tchRegKeyName , &hKey ) != ERROR_SUCCESS )
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
if( RegDeleteValue( hKey , szDeleteThisGuid ) == ERROR_SUCCESS )
|
|
{
|
|
RegCloseKey( hKey );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
return E_FAIL;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// DllUnregisterServer - Removes entries from the system registry
|
|
|
|
STDAPI DllUnregisterServer(void)
|
|
{
|
|
Local_UnRegisterSnapinExt( &CLSID_TSUserExInterfaces );
|
|
|
|
Local_UnregisterNodeType( &NODETYPE_User , &CLSID_TSUserExInterfaces );
|
|
|
|
Local_UnregisterNodeType( &NODETYPE_DSUser , &CLSID_TSUserExInterfaces );
|
|
|
|
try
|
|
{
|
|
|
|
_Module.UnregisterServer();
|
|
|
|
}
|
|
|
|
catch( ... )
|
|
{
|
|
ODS( L"TSUSEREX : Exception thrown" );
|
|
|
|
return E_FAIL;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|