//--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1995 // // File: ccomp.cxx // // Contents: // // History: 11-1-96 t-ptam Created. // //---------------------------------------------------------------------------- #include "NWCOMPAT.hxx" #pragma hdrstop DEFINE_IDispatch_Implementation(CNWCOMPATComputer) DEFINE_IADs_TempImplementation(CNWCOMPATComputer) DEFINE_IADs_PutGetImplementation(CNWCOMPATComputer, ComputerClass,gdwComputerTableSize) DEFINE_IADsPropertyList_Implementation(CNWCOMPATComputer, ComputerClass, gdwComputerTableSize) //---------------------------------------------------------------------------- // // Function: CNWCOMPATComputer::CNWCOMPATComputer // // Synopsis: // //---------------------------------------------------------------------------- CNWCOMPATComputer::CNWCOMPATComputer(): _pDispMgr(NULL), _pPropertyCache(NULL), _hConn(NULL) { VariantInit(&_vFilter); ENLIST_TRACKING(CNWCOMPATComputer); } //---------------------------------------------------------------------------- // // Function: CNWCOMPATComputer::~CNWCOMPATComputer // // Synopsis: // //---------------------------------------------------------------------------- CNWCOMPATComputer::~CNWCOMPATComputer( ) { if (_pDispMgr) delete _pDispMgr; if (_pPropertyCache) delete _pPropertyCache; if (_hConn) { NWApiReleaseBinderyHandle(_hConn); } VariantClear(&_vFilter); } //---------------------------------------------------------------------------- // // Function: CNWCOMPATComputer::CreateComputer // // Synopsis: // //---------------------------------------------------------------------------- HRESULT CNWCOMPATComputer::CreateComputer( BSTR bstrParent, BSTR bstrComputerName, CCredentials &Credentials, DWORD dwObjectState, REFIID riid, void **ppvObj ) { CNWCOMPATComputer FAR * pComputer = NULL; HRESULT hr = S_OK; hr = AllocateComputerObject( &pComputer ); BAIL_ON_FAILURE(hr); hr = pComputer->InitializeCoreObject( bstrParent, bstrComputerName, L"computer", COMPUTER_SCHEMA_NAME, CLSID_NWCOMPATComputer, dwObjectState ); BAIL_ON_FAILURE(hr); pComputer->_Credentials = Credentials; hr = pComputer->QueryInterface(riid, ppvObj); BAIL_ON_FAILURE(hr); pComputer->Release(); RRETURN(hr); error: delete pComputer; NW_RRETURN_EXP_IF_ERR(hr); } //---------------------------------------------------------------------------- // // Function: // // Synopsis: // //---------------------------------------------------------------------------- STDMETHODIMP CNWCOMPATComputer::QueryInterface( REFIID iid, LPVOID FAR* ppv ) { if (!ppv) { RRETURN(E_POINTER); } // // Query. // if (IsEqualIID(iid, IID_IUnknown)) { *ppv = (IADsComputer FAR *) this; } else if (IsEqualIID(iid, IID_IADsComputer)) { *ppv = (IADsComputer FAR *) this; } else if (IsEqualIID(iid, IID_IADsContainer)) { *ppv = (IADsContainer FAR *) this; } else if (IsEqualIID(iid, IID_IADs)) { *ppv = (IADsComputer FAR *) this; } else if (IsEqualIID(iid, IID_IDispatch)) { *ppv = (IADsComputer FAR *) this; } else if (IsEqualIID(iid, IID_ISupportErrorInfo)) { *ppv = (ISupportErrorInfo FAR *) this; } else if (IsEqualIID(iid, IID_IADsComputerOperations)) { *ppv = (IADsComputerOperations FAR *) this; } else if (IsEqualIID(iid, IID_IADsPropertyList)) { *ppv = (IADsPropertyList FAR *) this; } else { *ppv = NULL; return E_NOINTERFACE; } AddRef(); return NOERROR; } // // ISupportErrorInfo method // STDMETHODIMP CNWCOMPATComputer::InterfaceSupportsErrorInfo( THIS_ REFIID riid ) { if (IsEqualIID(riid, IID_IADs) || IsEqualIID(riid, IID_IADsComputer) || IsEqualIID(riid, IID_IADsComputerOperations) || IsEqualIID(riid, IID_IADsContainer) || IsEqualIID(riid, IID_IADsPropertyList)) { RRETURN(S_OK); } else { RRETURN(S_FALSE); } } // // IADsContainer methods // //---------------------------------------------------------------------------- // // Function: CNWCOMPATComputer::get_Count // // Synopsis: // //---------------------------------------------------------------------------- STDMETHODIMP CNWCOMPATComputer::get_Count(long FAR* retval) { // // Too expensive to implement in term of computer execution time. // NW_RRETURN_EXP_IF_ERR(E_NOTIMPL); } //---------------------------------------------------------------------------- // // Function: CNWCOMPATComputer::get_Filter // // Synopsis: // //---------------------------------------------------------------------------- STDMETHODIMP CNWCOMPATComputer::get_Filter(THIS_ VARIANT FAR* pVar) { HRESULT hr; VariantInit(pVar); hr = VariantCopy(pVar, &_vFilter); NW_RRETURN_EXP_IF_ERR(hr); } //---------------------------------------------------------------------------- // // Function: CNWCOMPATComputer::put_Filter // // Synopsis: // //---------------------------------------------------------------------------- STDMETHODIMP CNWCOMPATComputer::put_Filter(THIS_ VARIANT Var) { HRESULT hr; hr = VariantCopy(&_vFilter, &Var); NW_RRETURN_EXP_IF_ERR(hr); } STDMETHODIMP CNWCOMPATComputer::put_Hints(THIS_ VARIANT Var) { NW_RRETURN_EXP_IF_ERR( E_NOTIMPL); } STDMETHODIMP CNWCOMPATComputer::get_Hints(THIS_ VARIANT FAR* pVar) { NW_RRETURN_EXP_IF_ERR(E_NOTIMPL); } //---------------------------------------------------------------------------- // // Function: CNWCOMPATComputer::GetObject // // Synopsis: // //---------------------------------------------------------------------------- STDMETHODIMP CNWCOMPATComputer::GetObject( THIS_ BSTR ClassName, BSTR RelativeName, IDispatch * FAR* ppObject ) { WCHAR szBuffer[MAX_PATH]; HRESULT hr = S_OK; if (!RelativeName || !*RelativeName) { NW_RRETURN_EXP_IF_ERR(E_ADS_UNKNOWN_OBJECT); } wcscpy(szBuffer, _ADsPath); wcscat(szBuffer, L"/"); wcscat(szBuffer, RelativeName); if (ClassName && *ClassName) { wcscat(szBuffer,L","); wcscat(szBuffer, ClassName); } hr = ::GetObject( szBuffer, _Credentials, (LPVOID *)ppObject ); BAIL_ON_FAILURE(hr); error: NW_RRETURN_EXP_IF_ERR(hr); } //---------------------------------------------------------------------------- // // Function: CNWCOMPATComputer::get__NewEnum // // Synopsis: // //---------------------------------------------------------------------------- STDMETHODIMP CNWCOMPATComputer::get__NewEnum(THIS_ IUnknown * FAR* retval) { HRESULT hr; IEnumVARIANT * penum = NULL; if (!retval) { NW_RRETURN_EXP_IF_ERR(E_POINTER); } *retval = NULL; hr = CNWCOMPATComputerEnum::Create( (CNWCOMPATComputerEnum **)&penum, _ADsPath, _Name, _Credentials, _vFilter ); BAIL_ON_FAILURE(hr); hr = penum->QueryInterface( IID_IUnknown, (VOID FAR* FAR*)retval ); BAIL_ON_FAILURE(hr); if (penum) { penum->Release(); } RRETURN(NOERROR); error: if (penum) { delete penum; } NW_RRETURN_EXP_IF_ERR(hr); } //---------------------------------------------------------------------------- // // Function: CNWCOMPATComputer::Create // // Synopsis: // //---------------------------------------------------------------------------- STDMETHODIMP CNWCOMPATComputer::Create( THIS_ BSTR ClassName, BSTR RelativeName, IDispatch * FAR* ppObject ) { ULONG ObjectType = 0; HRESULT hr = S_OK; POBJECTINFO pObjectInfo = NULL; // // Translate ClassName into object type. // hr = GetObjectType( gpFilters, gdwMaxFilters, ClassName, (PDWORD)&ObjectType ); BAIL_ON_FAILURE(hr); // // Build object info structure. // hr = BuildObjectInfo( _ADsPath, RelativeName, &pObjectInfo ); BAIL_ON_FAILURE(hr); // // Create the object. // switch (ObjectType) { case NWCOMPAT_USER_ID: hr = CNWCOMPATUser::CreateUser( _ADsPath, NWCOMPAT_COMPUTER_ID, _Name, RelativeName, _Credentials, ADS_OBJECT_UNBOUND, IID_IDispatch, (void **)ppObject ); BAIL_ON_FAILURE(hr); break; case NWCOMPAT_GROUP_ID: hr = CNWCOMPATGroup::CreateGroup( _ADsPath, NWCOMPAT_COMPUTER_ID, _Name, RelativeName, _Credentials, ADS_OBJECT_UNBOUND, IID_IDispatch, (void **)ppObject ); BAIL_ON_FAILURE(hr); break; case NWCOMPAT_PRINTER_ID: hr = NWApiCreatePrinter( pObjectInfo, _Credentials ); BAIL_ON_FAILURE(hr); hr = CNWCOMPATPrintQueue::CreatePrintQueue( _ADsPath, pObjectInfo->ComponentArray[1], _Credentials, ADS_OBJECT_BOUND, IID_IDispatch, (void **)ppObject ); BAIL_ON_FAILURE(hr); break; default: hr = E_ADS_UNKNOWN_OBJECT; BAIL_ON_FAILURE(hr); } error: FreeObjectInfo(pObjectInfo); NW_RRETURN_EXP_IF_ERR(hr); } //---------------------------------------------------------------------------- // // Function: CNWCOMPATComputer::Delete // // Synopsis: // //---------------------------------------------------------------------------- STDMETHODIMP CNWCOMPATComputer::Delete( THIS_ BSTR bstrClassName, BSTR bstrRelativeName) { ULONG ObjectType = 0; POBJECTINFO pObjectInfo = NULL; HRESULT hr = S_OK; // // Translate ClassName into object type. // hr = GetObjectType( gpFilters, gdwMaxFilters, bstrClassName, (PDWORD)&ObjectType ); BAIL_ON_FAILURE(hr); // // Build object info structure. // hr = BuildObjectInfo( _ADsPath, bstrRelativeName, &pObjectInfo ); BAIL_ON_FAILURE(hr); // // Delete the object. // switch (ObjectType) { case NWCOMPAT_USER_ID: hr = NWApiDeleteUser( pObjectInfo, _Credentials ); BAIL_ON_FAILURE(hr); break; case NWCOMPAT_GROUP_ID: hr = NWApiDeleteGroup( pObjectInfo, _Credentials ); BAIL_ON_FAILURE(hr); break; case NWCOMPAT_PRINTER_ID: hr = NWApiDeletePrinter( pObjectInfo, _Credentials ); BAIL_ON_FAILURE(hr); break; default: hr = E_ADS_UNKNOWN_OBJECT; BAIL_ON_FAILURE(hr); } error: FreeObjectInfo(pObjectInfo); NW_RRETURN_EXP_IF_ERR(hr); } //---------------------------------------------------------------------------- // // Function: CNWCOMPATComputer::CopyHere // // Synopsis: // //---------------------------------------------------------------------------- STDMETHODIMP CNWCOMPATComputer::CopyHere( THIS_ BSTR SourceName, BSTR NewName, IDispatch * FAR* ppObject ) { NW_RRETURN_EXP_IF_ERR(E_NOTIMPL); } //---------------------------------------------------------------------------- // // Function: CNWCOMPATComputer::MoveHere // // Synopsis: // //---------------------------------------------------------------------------- STDMETHODIMP CNWCOMPATComputer::MoveHere( THIS_ BSTR SourceName, BSTR NewName, IDispatch * FAR* ppObject ) { POBJECTINFO pObjectInfoSource = NULL; POBJECTINFO pObjectInfoTarget = NULL; NWCONN_HANDLE hConn = NULL; DWORD dwResumeId = 0xffffffff; BSTR pADsPathTarget = NULL; HRESULT hr = S_OK; // Bindery only supports renames, not moves if (!NewName) BAIL_ON_FAILURE(hr = E_NOTIMPL); // // Build object info structure. // hr = BuildObjectInfo( SourceName, &pObjectInfoSource ); BAIL_ON_FAILURE(hr); hr = BuildObjectInfo( _ADsPath, NewName, &pObjectInfoTarget ); BAIL_ON_FAILURE(hr); // Can't rename to a child or parent, or to a different bindery if ( (pObjectInfoSource->NumComponents != 2) || (pObjectInfoTarget->NumComponents != 2) ) BAIL_ON_FAILURE(hr = E_INVALIDARG); if (_wcsicmp(pObjectInfoSource->ComponentArray[0], pObjectInfoTarget->ComponentArray[0])) BAIL_ON_FAILURE(hr = E_INVALIDARG); // // Rename the object. We need to know the object type, but this unfortunately isn't // passed to us, unlike Delete. So we try to validate the object as each type until // we hit one that works. // hr = NWApiGetBinderyHandle( &hConn, pObjectInfoSource->ComponentArray[0], _Credentials); BAIL_ON_FAILURE(hr); // Netware wants the names uppercase _wcsupr(pObjectInfoSource->ComponentArray[1]); _wcsupr(pObjectInfoTarget->ComponentArray[1]); // Is object a User? hr = NWApiValidateObject( hConn, OT_USER, pObjectInfoSource->ComponentArray[1], &dwResumeId ); if (SUCCEEDED(hr)) { hr = NWApiRenameObject( pObjectInfoSource, pObjectInfoTarget, OT_USER, _Credentials ); BAIL_ON_FAILURE(hr); } else { // Is object a Group? hr = NWApiValidateObject( hConn, OT_USER_GROUP, pObjectInfoSource->ComponentArray[1], &dwResumeId ); if (SUCCEEDED(hr)) { hr = NWApiRenameObject( pObjectInfoSource, pObjectInfoTarget, OT_USER_GROUP, _Credentials ); BAIL_ON_FAILURE(hr); } else { // Is object a Print Queue? hr = NWApiValidateObject( hConn, OT_PRINT_QUEUE, pObjectInfoSource->ComponentArray[1], &dwResumeId ); if (SUCCEEDED(hr)) { hr = NWApiRenameObject( pObjectInfoSource, pObjectInfoTarget, OT_PRINT_QUEUE, _Credentials ); BAIL_ON_FAILURE(hr); } else { // No such object, or not a type that we support hr = E_ADS_UNKNOWN_OBJECT; BAIL_ON_FAILURE(hr); } } } // get the IDispatch pointer if (ppObject) { hr = BuildADsPath( _ADsPath, NewName, &pADsPathTarget ); BAIL_ON_FAILURE(hr); hr = ::GetObject( pADsPathTarget, _Credentials, (LPVOID *)ppObject ); BAIL_ON_FAILURE(hr); } error: if (pADsPathTarget) ADsFreeString(pADsPathTarget); NWApiReleaseBinderyHandle(hConn); FreeObjectInfo(pObjectInfoSource); FreeObjectInfo(pObjectInfoTarget); NW_RRETURN_EXP_IF_ERR(hr); } // // IADs methods // //---------------------------------------------------------------------------- // // Function: CNWCOMPATComputer::SetInfo // // Synopsis: // //---------------------------------------------------------------------------- STDMETHODIMP CNWCOMPATComputer::SetInfo(THIS) { // // BUGBUG - should this be changed to E_NOTSUPPORTED if it is verified that // no properties on this object can be set. // NW_RRETURN_EXP_IF_ERR(E_NOTIMPL); } //---------------------------------------------------------------------------- // // Function: CNWCOMPATComputer::GetInfo // // Synopsis: // //---------------------------------------------------------------------------- STDMETHODIMP CNWCOMPATComputer::GetInfo(THIS) { _pPropertyCache->flushpropcache(); RRETURN(GetInfo( TRUE, COMP_WILD_CARD_ID )); } // // IADsComputer methods // //---------------------------------------------------------------------------- // // Function: CNWCOMPATComputer::AllocateComputerObject // // Synopsis: // //---------------------------------------------------------------------------- HRESULT CNWCOMPATComputer::AllocateComputerObject( CNWCOMPATComputer ** ppComputer ) { CNWCOMPATComputer FAR * pComputer = NULL; CDispatchMgr FAR * pDispMgr = NULL; CPropertyCache FAR * pPropertyCache = NULL; HRESULT hr = S_OK; // // Allocate memory for a computer object. // pComputer = new CNWCOMPATComputer(); if (pComputer == NULL) { hr = E_OUTOFMEMORY; } BAIL_ON_FAILURE(hr); // // Create a Dispatch Manager object. // pDispMgr = new CDispatchMgr; if (pDispMgr == NULL) { hr = E_OUTOFMEMORY; } BAIL_ON_FAILURE(hr); // // Load type info. // hr = LoadTypeInfoEntry( pDispMgr, LIBID_ADs, IID_IADsComputer, (IADsComputer *)pComputer, DISPID_REGULAR ); BAIL_ON_FAILURE(hr); hr = LoadTypeInfoEntry( pDispMgr, LIBID_ADs, IID_IADsContainer, (IADsContainer *)pComputer, DISPID_NEWENUM ); BAIL_ON_FAILURE(hr); hr = LoadTypeInfoEntry( pDispMgr, LIBID_ADs, IID_IADsPropertyList, (IADsPropertyList *)pComputer, DISPID_VALUE ); BAIL_ON_FAILURE(hr); // // Create property cache // hr = CPropertyCache::createpropertycache( ComputerClass, gdwComputerTableSize, (CCoreADsObject *)pComputer, &pPropertyCache ); BAIL_ON_FAILURE(hr); pComputer->_pPropertyCache = pPropertyCache; pComputer->_pDispMgr = pDispMgr; *ppComputer = pComputer; RRETURN(hr); error: // // Note: pComputer->_pPropertyCache & pComputer->_pDispMgr are NULL // if (pComputer) delete pComputer; if (pPropertyCache) delete pPropertyCache; if (pDispMgr) delete pDispMgr; RRETURN(hr); } //---------------------------------------------------------------------------- // // Function: CNWCOMPATComputer::CreateObject // // Synopsis: // //---------------------------------------------------------------------------- HRESULT CNWCOMPATComputer::CreateObject( ) { RRETURN(S_OK); } //---------------------------------------------------------------------------- // // Function: CNWCOMPATComputer::GetInfo // // Synopsis: // //---------------------------------------------------------------------------- STDMETHODIMP CNWCOMPATComputer::GetInfo( BOOL fExplicit, DWORD dwPropertyID ) { HRESULT hr = S_OK; if (GetObjectState() == ADS_OBJECT_UNBOUND) { NW_RRETURN_EXP_IF_ERR(E_ADS_OBJECT_UNBOUND); } // // Get a handle to the bindery this computer object represents, // if we haven't previously obtained one // if (!_hConn) { hr = NWApiGetBinderyHandle( &_hConn, _Name, _Credentials ); BAIL_ON_FAILURE(hr); } // // Fill in all property caches with values - explicit, or return the // indicated property - implicit. // if (fExplicit) { hr = ExplicitGetInfo(_hConn, fExplicit); BAIL_ON_FAILURE(hr); } else { hr = ImplicitGetInfo(_hConn, dwPropertyID, fExplicit); BAIL_ON_FAILURE(hr); } error: NW_RRETURN_EXP_IF_ERR(hr); } //---------------------------------------------------------------------------- // // Function: CNWCOMPATComputer::ExplicitGetInfo // // Synopsis: // //---------------------------------------------------------------------------- HRESULT CNWCOMPATComputer::ExplicitGetInfo( NWCONN_HANDLE hConn, BOOL fExplicit ) { HRESULT hr = S_OK; hr = GetProperty_Addresses(hConn, fExplicit); if (hr == E_ADS_PROPERTY_NOT_FOUND) { // not a real failure, we ignore it and treat it as a missing attrib hr = S_OK; } BAIL_ON_FAILURE(hr); hr = GetProperty_OperatingSystem(fExplicit); if (hr == E_ADS_PROPERTY_NOT_FOUND) { // not a real failure, we ignore it and treat it as a missing attrib hr = S_OK; } BAIL_ON_FAILURE(hr); hr = GetProperty_OperatingSystemVersion(hConn, fExplicit); if (hr == E_ADS_PROPERTY_NOT_FOUND) { // not a real failure, we ignore it and treat it as a missing attrib hr = S_OK; } BAIL_ON_FAILURE(hr); error: RRETURN(hr); } //---------------------------------------------------------------------------- // // Function: CNWCOMPATComputer::ImplicitGetInfo // // Synopsis: // //---------------------------------------------------------------------------- HRESULT CNWCOMPATComputer::ImplicitGetInfo( NWCONN_HANDLE hConn, DWORD dwPropertyID, BOOL fExplicit ) { HRESULT hr = S_OK; switch (dwPropertyID) { case COMP_ADDRESSES_ID: hr = GetProperty_Addresses(hConn, fExplicit); break; case COMP_OPERATINGSYSTEM_ID: hr = GetProperty_OperatingSystem(fExplicit); break; case COMP_OPERATINGSYSTEMVERSION_ID: hr = GetProperty_OperatingSystemVersion(hConn, fExplicit); break; } RRETURN(hr); } //---------------------------------------------------------------------------- // // Function: CNWCOMPATComputer::GetProperty_Addresses // // Synopsis: // //---------------------------------------------------------------------------- HRESULT CNWCOMPATComputer::GetProperty_Addresses( NWCONN_HANDLE hConn, BOOL fExplicit ) { BSTR bstrBuffer = NULL; DWORD dwNumSegment; HRESULT hr = S_OK; LP_RPLY_SGMT_LST lpReplySegment = NULL; LP_RPLY_SGMT_LST lpTemp = NULL; // Used by DELETE_LIST macro below LPWSTR lpszBuffer = NULL; VARIANT vData; // // Get ADDRESSES. // hr = NWApiGetProperty( _Name, NW_PROP_NET_ADDRESS, OT_FILE_SERVER, hConn, &lpReplySegment, &dwNumSegment ); BAIL_ON_FAILURE(hr); // // Put the addresses obtained in the format described in spec. // hr = NWApiConvertToAddressFormat( lpReplySegment, &lpszBuffer ); BAIL_ON_FAILURE(hr); bstrBuffer = SysAllocString(lpszBuffer); if (!bstrBuffer) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } // // BUGBUG - for now, Addresses is treated as a BSTR Variant instead of a // variant array of bstr, as described in the spec. // VariantInit(&vData); V_VT(&vData) = VT_BSTR; V_BSTR(&vData) = bstrBuffer; // // Unmarshall. // // // BugBug - KrishnaG figure out how we're going to map this property // // // UM_PUT_VARIANT_PROPERTY(vData, _pGenInfo, Addresses, FALSE); // VariantClear(&vData); error: if (lpReplySegment) { DELETE_LIST(lpReplySegment); } if (lpszBuffer) { FreeADsMem(lpszBuffer); } RRETURN(hr); } //---------------------------------------------------------------------------- // // Function: CNWCOMPATComputer::GetProperty_OperatingSystem // // Synopsis: // //---------------------------------------------------------------------------- HRESULT CNWCOMPATComputer::GetProperty_OperatingSystem( BOOL fExplicit ) { HRESULT hr = S_OK; // // BUGBUG - bstrComputerOperatingSystem is HARDCODED. // hr = SetLPTSTRPropertyInCache( _pPropertyCache, TEXT("OperatingSystem"), bstrComputerOperatingSystem, fExplicit ); RRETURN(hr); } //---------------------------------------------------------------------------- // // Function: CNWCOMPATComputer::GetProperty_OperatingSystemVersion // // Synopsis: // //---------------------------------------------------------------------------- HRESULT CNWCOMPATComputer::GetProperty_OperatingSystemVersion( NWCONN_HANDLE hConn, BOOL fExplicit ) { LPWSTR pszBuffer = NULL; CHAR ch; HRESULT hr = S_OK; NW_VERSION_INFO VersionInfo; // // Get Version Information of a bindery. // hr = NWApiGetFileServerVersionInfo( hConn, &VersionInfo ); BAIL_ON_FAILURE(hr); // // Put Version & SubVersion in X.X format. // pszBuffer = (LPWSTR) AllocADsMem( (OS_VERSION_NUM_CHAR+1) * sizeof(WCHAR) ); if (!pszBuffer) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } wsprintf( pszBuffer, L"%i.%02i", (WORD) VersionInfo.Version, (WORD) VersionInfo.SubVersion ); // // Unmarshall. // hr = SetLPTSTRPropertyInCache( _pPropertyCache, TEXT("OperatingSystemVersion"), pszBuffer, fExplicit ); error: if (pszBuffer) { FreeADsMem(pszBuffer); } RRETURN(hr); } STDMETHODIMP CNWCOMPATComputer::Status( IDispatch * FAR * ppObject ) { NW_RRETURN_EXP_IF_ERR(E_NOTIMPL); } STDMETHODIMP CNWCOMPATComputer::Shutdown( VARIANT_BOOL bReboot ) { NW_RRETURN_EXP_IF_ERR(E_NOTIMPL); }