1005 lines
21 KiB
C++
1005 lines
21 KiB
C++
//
|
|
// Copyright 1997 - Microsoft
|
|
//
|
|
|
|
//
|
|
// CCOMPUTR.CPP - Handles the computer object property pages.
|
|
//
|
|
|
|
#include "pch.h"
|
|
|
|
#include "client.h"
|
|
#include "server.h"
|
|
#include "ccomputr.h"
|
|
|
|
#include "varconv.h"
|
|
|
|
//
|
|
// Begin Class Definitions
|
|
//
|
|
DEFINE_MODULE("IMADMUI")
|
|
DEFINE_THISCLASS("CComputer")
|
|
#define THISCLASS CComputer
|
|
#define LPTHISCLASS LPCComputer
|
|
|
|
// ************************************************************************
|
|
//
|
|
// Constructor / Destructor
|
|
//
|
|
// ************************************************************************
|
|
|
|
//
|
|
// CreateInstance()
|
|
//
|
|
LPVOID
|
|
CComputer_CreateInstance( void )
|
|
{
|
|
TraceFunc( "CComputer_CreateInstance()\n" );
|
|
|
|
LPTHISCLASS lpcc = new THISCLASS( );
|
|
if (!lpcc)
|
|
RETURN(lpcc);
|
|
|
|
HRESULT hr = THR( lpcc->Init( ) );
|
|
|
|
if ( hr )
|
|
{
|
|
delete lpcc;
|
|
RETURN(NULL);
|
|
}
|
|
|
|
RETURN((LPVOID) lpcc);
|
|
}
|
|
|
|
//
|
|
// CreateCComputer( )
|
|
//
|
|
LPVOID
|
|
CreateIntelliMirrorClientComputer(
|
|
IADs * pads)
|
|
{
|
|
TraceFunc( "CreateCComputer(" );
|
|
TraceMsg( TF_FUNC, "pads = 0x%08x )\n", pads );
|
|
|
|
HRESULT hr;
|
|
LPTHISCLASS lpcc = NULL;
|
|
|
|
if ( !pads )
|
|
{
|
|
hr = THR( E_POINTER );
|
|
goto Error;
|
|
}
|
|
|
|
lpcc = new THISCLASS( );
|
|
if ( !lpcc )
|
|
{
|
|
hr = THR( E_OUTOFMEMORY );
|
|
goto Error;
|
|
}
|
|
|
|
hr = THR( lpcc->Init( ) );
|
|
if ( hr )
|
|
goto Error;
|
|
|
|
hr = lpcc->Init2( pads );
|
|
if (hr != S_FALSE) {
|
|
hr = THR(E_FAIL); // account exists?
|
|
goto Error;
|
|
}
|
|
|
|
Cleanup:
|
|
RETURN((LPVOID) lpcc);
|
|
|
|
Error:
|
|
if (lpcc) {
|
|
delete lpcc;
|
|
lpcc = NULL;
|
|
}
|
|
|
|
switch (hr) {
|
|
case S_OK:
|
|
break;
|
|
|
|
default:
|
|
MessageBoxFromHResult( NULL, IDC_ERROR_CREATINGACCOUNT_TITLE, hr );
|
|
break;
|
|
}
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Init2( )
|
|
//
|
|
STDMETHODIMP
|
|
THISCLASS::Init2(
|
|
IADs * pads )
|
|
{
|
|
TraceClsFunc( "Init2( ... )\n" );
|
|
|
|
HRESULT hr;
|
|
|
|
_pads = pads;
|
|
_pads->AddRef( );
|
|
|
|
hr = _pads->Get( NETBOOTGUID, &_vGUID );
|
|
if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND )
|
|
goto Cleanup;
|
|
|
|
hr = _pads->Get( NETBOOTSAP, &_vSCP );
|
|
if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND )
|
|
goto Cleanup;
|
|
|
|
hr = _pads->Get( NETBOOTMACHINEFILEPATH, &_vMachineFilepath );
|
|
if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND )
|
|
goto Cleanup;
|
|
|
|
hr = _pads->Get( NETBOOTINITIALIZATION, &_vInitialization );
|
|
if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND )
|
|
goto Cleanup;
|
|
|
|
if ( _vSCP.vt == VT_EMPTY
|
|
|| _vGUID.vt == VT_EMPTY
|
|
|| _vInitialization.vt == VT_EMPTY
|
|
|| _vMachineFilepath.vt == VT_EMPTY )
|
|
{
|
|
//
|
|
// These must be blank since we are setting the attributes
|
|
// of a newly created MAO.
|
|
//
|
|
hr = S_FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
Cleanup:
|
|
HRETURN(hr);
|
|
}
|
|
|
|
//
|
|
// Constructor
|
|
//
|
|
THISCLASS::THISCLASS( )
|
|
{
|
|
TraceClsFunc( "CComputer()\n" );
|
|
|
|
InterlockIncrement( g_cObjects );
|
|
|
|
TraceFuncExit();
|
|
}
|
|
|
|
//
|
|
// Init()
|
|
//
|
|
STDMETHODIMP
|
|
THISCLASS::Init( )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
TraceClsFunc( "Init()\n" );
|
|
|
|
// IUnknown stuff
|
|
BEGIN_QITABLE_IMP( CComputer, IShellExtInit );
|
|
QITABLE_IMP( IShellExtInit );
|
|
QITABLE_IMP( IShellPropSheetExt );
|
|
QITABLE_IMP( IMAO );
|
|
END_QITABLE_IMP( CComputer );
|
|
Assert( _cRef == 0);
|
|
AddRef( );
|
|
|
|
hr = CheckClipboardFormats( );
|
|
|
|
// Private Members
|
|
Assert( !_pads );
|
|
Assert( !_pDataObj );
|
|
|
|
VariantInit( &_vGUID );
|
|
VariantInit( &_vMachineFilepath );
|
|
VariantInit( &_vInitialization );
|
|
VariantInit( &_vSCP );
|
|
|
|
// _InitParams should already be zero'ed.
|
|
_InitParams.dwSize = sizeof(_InitParams);
|
|
|
|
_uMode = MODE_SHELL; // default
|
|
|
|
HRETURN(hr);
|
|
}
|
|
|
|
//
|
|
// Destructor
|
|
//
|
|
THISCLASS::~THISCLASS( )
|
|
{
|
|
TraceClsFunc( "~CComputer()\n" );
|
|
|
|
// Members
|
|
if ( _pads )
|
|
{
|
|
//
|
|
// note: we shouldn't commit anything in the destructor -- we can't
|
|
// catch failures here. We'll just have to make sure that we
|
|
// explicitly commit changes when necessary
|
|
//
|
|
#if 0
|
|
// Commit any changes before we release
|
|
THR( _pads->SetInfo( ) );
|
|
#endif
|
|
_pads->Release( );
|
|
}
|
|
|
|
if ( _pDataObj )
|
|
_pDataObj->Release( );
|
|
|
|
if ( _pszObjectName )
|
|
TraceFree( _pszObjectName );
|
|
|
|
VariantClear( &_vGUID );
|
|
VariantClear( &_vMachineFilepath );
|
|
VariantClear( &_vInitialization );
|
|
VariantClear( &_vSCP );
|
|
|
|
#if 0 // EricB might be adding an AddRef( ) to this. Until then, don't release.
|
|
if ( _InitParams.pDsObj )
|
|
_InitParams.pDsObj->Release( );
|
|
#endif
|
|
|
|
InterlockDecrement( g_cObjects );
|
|
|
|
TraceFuncExit();
|
|
};
|
|
|
|
|
|
// ************************************************************************
|
|
//
|
|
// IUnknown
|
|
//
|
|
// ************************************************************************
|
|
|
|
//
|
|
// QueryInterface()
|
|
//
|
|
STDMETHODIMP
|
|
THISCLASS::QueryInterface(
|
|
REFIID riid,
|
|
LPVOID *ppv )
|
|
{
|
|
TraceClsFunc( "" );
|
|
|
|
HRESULT hr = ::QueryInterface( this, _QITable, riid, ppv );
|
|
|
|
// Ugly ugly ulgy... but it works
|
|
if ( hr == E_NOINTERFACE && _pDataObj ) {
|
|
hr = _pDataObj->QueryInterface( riid, ppv );
|
|
}
|
|
|
|
QIRETURN( hr, riid );
|
|
}
|
|
|
|
//
|
|
// AddRef()
|
|
//
|
|
STDMETHODIMP_(ULONG)
|
|
THISCLASS::AddRef( void )
|
|
{
|
|
TraceClsFunc( "[IUnknown] AddRef( )\n" );
|
|
|
|
InterlockIncrement( _cRef );
|
|
|
|
RETURN(_cRef);
|
|
}
|
|
|
|
//
|
|
// Release()
|
|
//
|
|
STDMETHODIMP_(ULONG)
|
|
THISCLASS::Release( void )
|
|
{
|
|
TraceClsFunc( "[IUnknown] Release( )\n" );
|
|
|
|
InterlockDecrement( _cRef );
|
|
|
|
if ( _cRef )
|
|
RETURN(_cRef);
|
|
|
|
TraceDo( delete this );
|
|
|
|
RETURN(0);
|
|
}
|
|
|
|
|
|
// ************************************************************************
|
|
//
|
|
// IShellExtInit
|
|
//
|
|
// ************************************************************************
|
|
|
|
//
|
|
// Initialize()
|
|
//
|
|
STDMETHODIMP
|
|
THISCLASS::Initialize(
|
|
LPCITEMIDLIST pidlFolder,
|
|
LPDATAOBJECT lpdobj,
|
|
HKEY hkeyProgID )
|
|
{
|
|
TraceClsFunc( "[IShellExtInit] Initialize( " );
|
|
TraceMsg( TF_FUNC, " pidlFolder = 0x%08x, lpdobj = 0x%08x, hkeyProgID = 0x%08x )\n",
|
|
pidlFolder, lpdobj, hkeyProgID );
|
|
|
|
if ( !lpdobj )
|
|
RETURN(E_INVALIDARG);
|
|
|
|
HRESULT hr = S_OK;
|
|
FORMATETC fmte;
|
|
STGMEDIUM stg = { 0 };
|
|
STGMEDIUM stgOptions = { 0 };
|
|
|
|
LPWSTR pszObjectName;
|
|
LPWSTR pszClassName;
|
|
LPWSTR pszAttribPrefix;
|
|
|
|
LPDSOBJECT pDsObject;
|
|
LPDSOBJECTNAMES pDsObjectNames;
|
|
LPDSDISPLAYSPECOPTIONS pDsDisplayOptions;
|
|
|
|
BOOL b;
|
|
|
|
// Hang onto it
|
|
_pDataObj = lpdobj;
|
|
_pDataObj->AddRef( );
|
|
|
|
//
|
|
// Retrieve the Object Names
|
|
//
|
|
fmte.cfFormat = (CLIPFORMAT)g_cfDsObjectNames;
|
|
fmte.tymed = TYMED_HGLOBAL;
|
|
fmte.dwAspect = DVASPECT_CONTENT;
|
|
fmte.lindex = -1;
|
|
fmte.ptd = 0;
|
|
|
|
hr = THR( lpdobj->GetData( &fmte, &stg) );
|
|
if ( hr )
|
|
goto Cleanup;
|
|
|
|
pDsObjectNames = (LPDSOBJECTNAMES) stg.hGlobal;
|
|
|
|
Assert( stg.tymed == TYMED_HGLOBAL );
|
|
|
|
TraceMsg( TF_ALWAYS, "Object's Namespace CLSID: " );
|
|
TraceMsgGUID( TF_ALWAYS, pDsObjectNames->clsidNamespace );
|
|
TraceMsg( TF_ALWAYS, "\tNumber of Objects: %u \n", pDsObjectNames->cItems );
|
|
|
|
Assert( pDsObjectNames->cItems == 1 );
|
|
|
|
pDsObject = (LPDSOBJECT) pDsObjectNames->aObjects;
|
|
|
|
pszObjectName = (LPWSTR) PtrToByteOffset( pDsObjectNames, pDsObject->offsetName );
|
|
pszClassName = (LPWSTR) PtrToByteOffset( pDsObjectNames, pDsObject->offsetClass );
|
|
|
|
TraceMsg( TF_ALWAYS, "Object Name (Class): %s (%s)\n", pszObjectName, pszClassName );
|
|
|
|
//
|
|
// This must be a "Computer" class
|
|
//
|
|
if ( StrCmp( pszClassName, DSCOMPUTERCLASSNAME ) )
|
|
{
|
|
hr = S_FALSE;
|
|
goto Error;
|
|
}
|
|
|
|
//
|
|
// Retrieve the Display Spec Options
|
|
//
|
|
fmte.cfFormat = (CLIPFORMAT)g_cfDsDisplaySpecOptions;
|
|
fmte.tymed = TYMED_HGLOBAL;
|
|
fmte.dwAspect = DVASPECT_CONTENT;
|
|
fmte.lindex = -1;
|
|
fmte.ptd = 0;
|
|
|
|
hr = THR( lpdobj->GetData( &fmte, &stgOptions ) );
|
|
if ( hr )
|
|
goto Cleanup;
|
|
|
|
pDsDisplayOptions = (LPDSDISPLAYSPECOPTIONS) stgOptions.hGlobal;
|
|
|
|
Assert( stgOptions.tymed == TYMED_HGLOBAL );
|
|
Assert( pDsDisplayOptions->dwSize >= sizeof(DSDISPLAYSPECOPTIONS) );
|
|
|
|
pszAttribPrefix = (LPWSTR) PtrToByteOffset( pDsDisplayOptions, pDsDisplayOptions->offsetAttribPrefix );
|
|
|
|
// TraceMsg( TF_ALWAYS, TEXT("Attribute Prefix: %s\n"), pszAttribPrefix );
|
|
|
|
if ( StrCmpW( pszAttribPrefix, STRING_ADMIN ) == 0 )
|
|
{
|
|
_uMode = MODE_ADMIN;
|
|
}
|
|
// else default from Init()
|
|
|
|
TraceMsg( TF_ALWAYS, TEXT("Mode: %s\n"), _uMode ? TEXT("Admin") : TEXT("Shell") );
|
|
|
|
ReleaseStgMedium( &stgOptions );
|
|
|
|
_pszObjectName = TraceStrDup( pszObjectName );
|
|
if ( !_pszObjectName )
|
|
goto OutOfMemory;
|
|
|
|
// create the DS notify object
|
|
hr = THR( ADsPropCreateNotifyObj( _pDataObj, _pszObjectName, &_hwndNotify ) );
|
|
if (FAILED( hr ))
|
|
goto Error;
|
|
|
|
b = ADsPropGetInitInfo( _hwndNotify, &_InitParams );
|
|
if ( !b )
|
|
{
|
|
hr = E_FAIL;
|
|
goto Error;
|
|
}
|
|
|
|
hr = THR( _InitParams.hr );
|
|
if (FAILED( hr ))
|
|
goto Error;
|
|
|
|
hr = THR( _InitParams.pDsObj->QueryInterface( IID_IADs, (void**) &_pads ) );
|
|
if (FAILED( hr ))
|
|
goto Error;
|
|
|
|
//
|
|
// Retrieve the attributes
|
|
//
|
|
hr = _pads->Get( NETBOOTGUID, &_vGUID );
|
|
if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND )
|
|
goto Error;
|
|
|
|
hr = _pads->Get( NETBOOTSAP, &_vSCP );
|
|
if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND )
|
|
goto Error;
|
|
|
|
//
|
|
// Check to see if this is an MAO that we need to add
|
|
// ourselves to.
|
|
//
|
|
if ( _vSCP.vt == VT_EMPTY && _vGUID.vt == VT_EMPTY )
|
|
{
|
|
//
|
|
// This MAO is not a IntelliMirror client or server.
|
|
//
|
|
hr = S_FALSE;
|
|
goto Error;
|
|
}
|
|
|
|
hr = _pads->Get( NETBOOTMACHINEFILEPATH, &_vMachineFilepath );
|
|
if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND )
|
|
goto Error;
|
|
|
|
hr = _pads->Get( NETBOOTINITIALIZATION, &_vInitialization );
|
|
if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND )
|
|
goto Error;
|
|
|
|
//
|
|
// Fix HR
|
|
//
|
|
if ( hr == E_ADS_PROPERTY_NOT_FOUND )
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
ReleaseStgMedium( &stg );
|
|
|
|
HRETURN(hr);
|
|
OutOfMemory:
|
|
hr = E_OUTOFMEMORY;
|
|
// fall thru
|
|
Error:
|
|
switch (hr) {
|
|
case S_OK:
|
|
break;
|
|
|
|
case S_FALSE:
|
|
hr = E_FAIL; // don't show page
|
|
break;
|
|
|
|
default:
|
|
MessageBoxFromHResult( NULL, IDS_ERROR_READINGCOMPUTERACCOUNT, hr );
|
|
break;
|
|
}
|
|
goto Cleanup;
|
|
}
|
|
|
|
// ************************************************************************
|
|
//
|
|
// IShellPropSheetExt
|
|
//
|
|
// ************************************************************************
|
|
|
|
//
|
|
// AddPages()
|
|
//
|
|
STDMETHODIMP
|
|
THISCLASS::AddPages(
|
|
LPFNADDPROPSHEETPAGE lpfnAddPage,
|
|
LPARAM lParam)
|
|
{
|
|
TraceClsFunc( "[IShellPropSheetExt] AddPages( )\n" );
|
|
|
|
if ( !lpfnAddPage )
|
|
HRETURN(E_POINTER);
|
|
|
|
HRESULT hr = S_OK;
|
|
BOOL fServer;
|
|
|
|
hr = THR( IsServer( &fServer ) );
|
|
if (FAILED( hr ))
|
|
goto Error;
|
|
|
|
if ( fServer )
|
|
{
|
|
//
|
|
// Add the "IntelliMirror" tab for servers
|
|
//
|
|
hr = THR( ::AddPagesEx( NULL,
|
|
CServerTab_CreateInstance,
|
|
lpfnAddPage,
|
|
lParam,
|
|
(LPUNKNOWN) (IShellExtInit*) this ) );
|
|
if (FAILED( hr ))
|
|
goto Error;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Add the "IntelliMirror" tab for clients
|
|
//
|
|
hr = THR( ::AddPagesEx( NULL,
|
|
CClientTab_CreateInstance,
|
|
lpfnAddPage,
|
|
lParam,
|
|
(LPUNKNOWN) (IShellExtInit*) this ) );
|
|
if (FAILED( hr ))
|
|
goto Error;
|
|
}
|
|
|
|
// Release our count on it.
|
|
// _pDataObj->Release( );
|
|
// _pDataObj = NULL;
|
|
|
|
Error:
|
|
HRETURN(hr);
|
|
}
|
|
|
|
//
|
|
// ReplacePage()
|
|
//
|
|
STDMETHODIMP
|
|
THISCLASS::ReplacePage(
|
|
UINT uPageID,
|
|
LPFNADDPROPSHEETPAGE lpfnReplaceWith,
|
|
LPARAM lParam )
|
|
{
|
|
|
|
TraceClsFunc( "[IShellPropSheetExt] ReplacePage( ) *** NOT_IMPLEMENTED ***\n" );
|
|
|
|
RETURN(E_NOTIMPL);
|
|
}
|
|
|
|
// ************************************************************************
|
|
//
|
|
// IMAO (Private)
|
|
//
|
|
// ************************************************************************
|
|
|
|
//
|
|
// CommitChanges( )
|
|
//
|
|
STDMETHODIMP
|
|
THISCLASS::CommitChanges( void )
|
|
{
|
|
TraceClsFunc("[IMAO] CommitChanges( )\n" );
|
|
|
|
HRESULT hr = THR( _pads->SetInfo( ) );
|
|
|
|
HRETURN(hr);
|
|
}
|
|
|
|
//
|
|
// IsAdmin( )
|
|
//
|
|
STDMETHODIMP
|
|
THISCLASS::IsAdmin(
|
|
BOOL * fAdmin )
|
|
{
|
|
TraceClsFunc( "[IMAO] IsAdmin( )\n" );
|
|
|
|
if ( !fAdmin )
|
|
HRETURN( E_INVALIDARG );
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
*fAdmin = (_uMode == MODE_ADMIN);
|
|
|
|
HRETURN(hr);
|
|
}
|
|
|
|
//
|
|
// IsServer( )
|
|
//
|
|
STDMETHODIMP
|
|
THISCLASS::IsServer(
|
|
BOOL * fServer )
|
|
{
|
|
TraceClsFunc( "[IMAO] IsServer( )\n" );
|
|
|
|
if ( !fServer )
|
|
HRETURN( E_INVALIDARG );
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
*fServer = (_vSCP.vt != VT_EMPTY);
|
|
|
|
HRETURN(hr);
|
|
}
|
|
|
|
//
|
|
// IsClient( )
|
|
//
|
|
STDMETHODIMP
|
|
THISCLASS::IsClient(
|
|
BOOL * fClient )
|
|
{
|
|
TraceClsFunc( "[IMAO] IsClient( )\n" );
|
|
if ( !fClient)
|
|
HRETURN( E_INVALIDARG );
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
*fClient = (_vGUID.vt != VT_EMPTY ) |
|
|
(_vMachineFilepath.vt != VT_EMPTY ) |
|
|
(_vInitialization.vt != VT_EMPTY );
|
|
|
|
HRETURN(hr);
|
|
}
|
|
|
|
//
|
|
// SetServerName( )
|
|
//
|
|
STDMETHODIMP
|
|
THISCLASS::SetServerName(
|
|
LPWSTR pszName )
|
|
{
|
|
TraceClsFunc( "[IMAO] SetServerName( " );
|
|
TraceMsg( TF_FUNC, "pszName = %s )\n", pszName );
|
|
|
|
HRESULT hr = S_OK;
|
|
LPWSTR pszFilepath = NULL;
|
|
VARIANT var;
|
|
|
|
if ( V_VT( &_vMachineFilepath ) == VT_BSTR )
|
|
{
|
|
pszFilepath = StrChr( _vMachineFilepath.bstrVal, L'\\' );
|
|
}
|
|
|
|
//
|
|
// Create variant with new Server\Filepath string
|
|
//
|
|
VariantInit( &var );
|
|
if ( !pszName || pszName[0] == L'\0' ) {
|
|
hr = THR( _pads->PutEx( ADS_PROPERTY_CLEAR, NETBOOTMACHINEFILEPATH, var ) );
|
|
DebugMsg( "Cleared MachineFilepath\n" );
|
|
} else {
|
|
if ( pszFilepath ) {
|
|
WCHAR szBuf[ DNS_MAX_NAME_LENGTH + 1 + 128 /* DHCP BOOTP PATH */ + 1 ];
|
|
wsprintf( szBuf, L"%s\\%s", pszName, pszFilepath );
|
|
PackStringToVariant( &var, szBuf);
|
|
DebugMsg( "Set MachineFilepath to %s\n", szBuf );
|
|
} else {
|
|
hr = PackStringToVariant( &var, pszName );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
DebugMsg( "Set MachineFilepath to %s\n", pszName );
|
|
}
|
|
|
|
//
|
|
// Set the property
|
|
//
|
|
hr = THR( _pads->Put( NETBOOTMACHINEFILEPATH, var ) );
|
|
}
|
|
|
|
if (FAILED( hr ))
|
|
goto Cleanup;
|
|
//
|
|
// Release the old variant and shallow copy the new one to the
|
|
// MachineFilepath variant. No need to release the "var".
|
|
//
|
|
VariantClear( &_vMachineFilepath );
|
|
_vMachineFilepath = var;
|
|
VariantInit( &var ); // don't free
|
|
|
|
Cleanup:
|
|
VariantClear( &var );
|
|
HRETURN(hr);
|
|
}
|
|
|
|
|
|
//
|
|
// GetServerName( )
|
|
//
|
|
STDMETHODIMP
|
|
THISCLASS::GetServerName(
|
|
LPWSTR * ppszName )
|
|
{
|
|
TraceClsFunc( "[IMAO] GetServerName( " );
|
|
TraceMsg( TF_FUNC, "*ppszName = 0x%08x )\n", *ppszName );
|
|
|
|
HRESULT hr = S_OK;
|
|
LPWSTR psz = _vMachineFilepath.bstrVal;
|
|
|
|
if ( !ppszName )
|
|
HRETURN( E_INVALIDARG );
|
|
|
|
*ppszName = NULL;
|
|
|
|
if ( _vMachineFilepath.vt != VT_BSTR || _vMachineFilepath.bstrVal == NULL )
|
|
HRETURN( E_ADS_PROPERTY_NOT_FOUND );
|
|
|
|
if ( *psz == L'\0' ) {
|
|
hr = S_FALSE;
|
|
} else {
|
|
// Find the Filepath
|
|
while ( *psz && *psz != L'\\' )
|
|
psz++;
|
|
|
|
*psz = L'\0';
|
|
*ppszName = (LPWSTR) TraceStrDup( _vMachineFilepath.bstrVal );
|
|
|
|
if ( !*ppszName )
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
HRETURN(hr);
|
|
}
|
|
|
|
|
|
//
|
|
// SetGUID( )
|
|
//
|
|
STDMETHODIMP
|
|
THISCLASS::SetGUID(
|
|
LPWSTR pszGUID )
|
|
{
|
|
TraceClsFunc("[IMAO] SetGUID( )\n" );
|
|
|
|
HRESULT hr = E_FAIL;
|
|
BYTE uGUID[16];
|
|
VARIANT var;
|
|
|
|
VariantInit( &var );
|
|
if ( !pszGUID ) {
|
|
|
|
hr = THR( _pads->PutEx( ADS_PROPERTY_CLEAR, NETBOOTGUID, var ) );
|
|
if (FAILED( hr ))
|
|
goto Cleanup;
|
|
|
|
VariantClear( &_vGUID );
|
|
|
|
} else {
|
|
|
|
if ( ValidateGuid(pszGUID,uGUID,NULL) == S_OK ) {
|
|
|
|
//
|
|
// Put it into a variant
|
|
//
|
|
PackBytesToVariant( &var, uGUID, 16 );
|
|
|
|
VariantClear( &_vGUID );
|
|
_vGUID = var;
|
|
|
|
hr = THR( _pads->Put( NETBOOTGUID, _vGUID ) );
|
|
if (FAILED( hr ))
|
|
goto Cleanup;
|
|
}
|
|
else // I don't know what it is.
|
|
{
|
|
Assert( FALSE );
|
|
VariantClear( &var );
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
HRETURN(hr);
|
|
}
|
|
|
|
//
|
|
// GetGUID( )
|
|
//
|
|
STDMETHODIMP
|
|
THISCLASS::GetGUID(
|
|
IN LPWSTR * ppszGUID OPTIONAL,
|
|
IN LPBYTE uGUID OPTIONAL )
|
|
{
|
|
TraceClsFunc("[IMAO] GetGUID( )\n" );
|
|
|
|
HRESULT hr = S_OK;
|
|
LPBYTE ptr = NULL;
|
|
VARIANT var = _vGUID;
|
|
LONG Length;
|
|
|
|
if ( ppszGUID != NULL ) {
|
|
*ppszGUID = NULL;
|
|
}
|
|
|
|
if ( var.vt == VT_EMPTY )
|
|
HRETURN( HRESULT_FROM_WIN32(ERROR_INVALID_DATA));
|
|
|
|
if ( SafeArrayGetDim( var.parray ) != 1 )
|
|
HRETURN( HRESULT_FROM_WIN32(ERROR_INVALID_DATA));
|
|
|
|
hr = THR( SafeArrayGetUBound( var.parray, 1, &Length ) );
|
|
if (FAILED( hr ))
|
|
goto Cleanup;
|
|
|
|
Assert( Length == 15 );
|
|
if ( Length != 15 )
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
|
|
goto Cleanup;
|
|
}
|
|
|
|
hr = THR( SafeArrayAccessData( var.parray, (LPVOID*)&ptr ) );
|
|
if (FAILED( hr ))
|
|
goto Cleanup;
|
|
|
|
if ( uGUID != NULL ) {
|
|
memcpy( uGUID, ptr, 16 * sizeof(BYTE) );
|
|
}
|
|
|
|
if ( ppszGUID != NULL ) {
|
|
*ppszGUID = PrettyPrintGuid( ptr );
|
|
if ( !*ppszGUID )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
Cleanup:
|
|
if ( ptr )
|
|
SafeArrayUnaccessData( var.parray );
|
|
HRETURN(hr);
|
|
}
|
|
|
|
|
|
//
|
|
// GetSAP( )
|
|
//
|
|
STDMETHODIMP
|
|
THISCLASS::GetSAP(
|
|
LPVOID *punk )
|
|
{
|
|
TraceClsFunc( "[IMAO] GetSAP( punk )\n" );
|
|
|
|
HRESULT hr = S_OK;
|
|
LPWSTR pszDN = NULL;
|
|
|
|
*punk = NULL;
|
|
|
|
if ( _vSCP.vt != VT_BSTR ) {
|
|
hr = E_ADS_PROPERTY_NOT_FOUND;
|
|
goto Cleanup;
|
|
}
|
|
|
|
Assert( _vSCP.vt == VT_BSTR );
|
|
Assert( _vSCP.bstrVal );
|
|
|
|
// pre-pend the "LDAP://server/" from our DN
|
|
hr = _FixObjectPath( V_BSTR( &_vSCP ), &pszDN );
|
|
if (FAILED( hr ))
|
|
goto Cleanup;
|
|
|
|
// Bind to the MAO in the DS
|
|
hr = THR( ADsGetObject( pszDN, IID_IADs, punk ) );
|
|
if (FAILED( hr ))
|
|
goto Cleanup;
|
|
|
|
Cleanup:
|
|
if ( pszDN )
|
|
TraceFree( pszDN );
|
|
|
|
HRETURN(hr);
|
|
}
|
|
|
|
//
|
|
// _FixObjectPath( )
|
|
//
|
|
HRESULT
|
|
THISCLASS::_FixObjectPath( LPWSTR pszOldObjectPath, LPWSTR *ppszNewObjectPath )
|
|
{
|
|
TraceClsFunc( "_FixObjectPath()\n" );
|
|
if ( !ppszNewObjectPath )
|
|
HRETURN(E_POINTER);
|
|
|
|
HRESULT hr;
|
|
LPWSTR psz = NULL;
|
|
|
|
*ppszNewObjectPath = NULL;
|
|
|
|
// Try to parse the string to connect to the same server as the DSADMIN
|
|
if ( _pszObjectName && StrCmpNI( _pszObjectName, L"LDAP://", 7 ) == 0 )
|
|
{
|
|
psz = _pszObjectName + 7;
|
|
}
|
|
else if ( _pszObjectName && StrCmpNI( _pszObjectName, L"GC://", 5 ) == 0 )
|
|
{
|
|
psz = _pszObjectName + 5;
|
|
}
|
|
|
|
if ( psz )
|
|
{
|
|
psz = StrChr( psz, L'/' );
|
|
psz++;
|
|
|
|
INT_PTR uLen = psz - _pszObjectName;
|
|
|
|
// get a chunk of memory, pre-zero'ed
|
|
psz = TraceAllocString( LPTR, (size_t) uLen + wcslen( pszOldObjectPath ) + 1 );
|
|
if ( !psz )
|
|
goto OutOfMemory;
|
|
|
|
MoveMemory( psz, _pszObjectName, uLen * sizeof(WCHAR) );
|
|
wcscat( psz, pszOldObjectPath);
|
|
*ppszNewObjectPath = psz;
|
|
}
|
|
else
|
|
{ // find another server
|
|
hr = THR( LDAPPrefix( pszOldObjectPath, ppszNewObjectPath ) );
|
|
}
|
|
|
|
Assert( ppszNewObjectPath || hr != S_OK );
|
|
|
|
HRETURN(hr);
|
|
OutOfMemory:
|
|
HRETURN(E_OUTOFMEMORY);
|
|
}
|
|
|
|
//
|
|
// GetDataObject( )
|
|
//
|
|
STDMETHODIMP
|
|
THISCLASS::GetDataObject(
|
|
LPDATAOBJECT * pDataObj
|
|
)
|
|
{
|
|
TraceClsFunc( "GetDataObject( ... )\n ");
|
|
|
|
if ( !pDataObj )
|
|
HRETURN(E_POINTER);
|
|
|
|
*pDataObj = _pDataObj;
|
|
_pDataObj->AddRef( );
|
|
|
|
HRETURN(S_OK);
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
STDMETHODIMP
|
|
THISCLASS::GetNotifyWindow(
|
|
HWND *phNotifyObj
|
|
)
|
|
{
|
|
TraceClsFunc( "GetNotifyWindow( ... )\n" );
|
|
|
|
if ( !phNotifyObj )
|
|
HRETURN(E_POINTER);
|
|
|
|
*phNotifyObj = _hwndNotify;
|
|
|
|
HRETURN(S_OK);
|
|
}
|