Windows2003-3790/termsrv/tsuserex/tsuserex.cpp

610 lines
17 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 <shlwapi.h>
#include "tsuserex_i.c" // generated file. class ids.
#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 szNameStringIndirect , LPTSTR szProvider , LPTSTR szVersion );
HRESULT Local_VerifyNodeType( const GUID *pGuidSnapin , const GUID *pGuidSnapinNodeTypeToVerify );
HINSTANCE ghInstance;
HINSTANCE GetInstance()
{
return ghInstance;
}
/////////////////////////////////////////////////////////////////////////////
// Register the class
STDAPI RegisterADsExt(void)
{
HRESULT hr;
HKEY hKey = NULL;
DWORD dwDisposition;
/////////////////////
// Register the class
////////////////////
hr = RegCreateKeyEx( HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\ADs\\Providers\\LDAP\\Extensions\\User\\{E2E9CAE6-1E7B-4B8E-BABD-E9BF6292AC29}"),
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&hKey,
&dwDisposition );
///////////////////////////////////////////
// Register the Interface
////////////////////////////////////////////
const wchar_t szIf[] = L"{C4930E79-2989-4462-8A60-2FCF2F2955EF}";
if(ERROR_SUCCESS == hr)
{
hr = RegSetValueEx( hKey, _T("Interfaces"), 0, REG_MULTI_SZ, (const BYTE *) szIf, sizeof(szIf));
}
if(NULL != hKey)
{
RegCloseKey(hKey);
hKey = NULL;
}
hr = RegCreateKeyEx( HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\ADs\\Providers\\WinNT\\Extensions\\User\\{E2E9CAE6-1E7B-4B8E-BABD-E9BF6292AC29}"),
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&hKey,
&dwDisposition );
if(ERROR_SUCCESS == hr)
{
hr = RegSetValueEx( hKey, _T("Interfaces"), 0, REG_MULTI_SZ, (const BYTE *) szIf, sizeof(szIf));
}
if(NULL != hKey)
{
RegCloseKey(hKey);
}
return S_OK;
}
CComModule _Module;
// this object has IExtendPropertySheet interface.
BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_TSUserExInterfaces, TSUserExInterfaces)
#ifdef _RTM_
OBJECT_ENTRY(CLSID_ExtCopyNoUI, CExtCopyNoUI )
#endif
OBJECT_ENTRY(CLSID_ADsTSUserEx, ADsTSUserEx)
END_OBJECT_MAP()
/////////////////////////////////////////////////////////////////////////////
// DLL Entry Point
extern "C"
BOOL APIENTRY 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 tchSysDllPathName[ MAX_PATH ];
TCHAR tchNameStringIndirect[ MAX_PATH ];
TCHAR tchProvider[ 160 ];
TCHAR tchVersion[ 16 ];
HRESULT hr = _Module.RegisterServer(TRUE);
RegisterADsExt();
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 ) ) );
GetModuleFileName(_Module.GetResourceInstance(), tchSysDllPathName, sizeof(tchSysDllPathName) / sizeof(TCHAR));
tchSysDllPathName[(sizeof(tchSysDllPathName)/sizeof(tchSysDllPathName[0]))-1] = L'\0';
wsprintf(tchNameStringIndirect, L"@%s,-%d", tchSysDllPathName, IDS_NAMESTRING_SNAPIN);
hr = Local_RegisterSnapinExt( &CLSID_TSUserExInterfaces ,
&CLSID_TSUserExInterfaces ,
tchNameString ,
tchNameStringIndirect ,
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 szNameStringIndirect , 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"NameStringIndirect" , 0 , REG_SZ , ( LPBYTE )szNameStringIndirect , sizeof( TCHAR ) * ( lstrlen( szNameStringIndirect ) + 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 );
SHDeleteKey( HKEY_LOCAL_MACHINE,
_T("SOFTWARE\\Microsoft\\ADs\\Providers\\LDAP\\Extensions\\User\\{E2E9CAE6-1E7B-4B8E-BABD-E9BF6292AC29}") );
SHDeleteKey( HKEY_LOCAL_MACHINE,
_T("SOFTWARE\\Microsoft\\ADs\\Providers\\WinNT\\Extensions\\User\\{E2E9CAE6-1E7B-4B8E-BABD-E9BF6292AC29}") );
try
{
_Module.UnregisterServer();
}
catch( ... )
{
ODS( L"TSUSEREX : Exception thrown" );
return E_FAIL;
}
return S_OK;
}