windows-nt/Source/XPSP1/NT/termsrv/license/tlserver/esetup/publish.cpp

788 lines
19 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*
** Copyright (c) 1998 Microsoft Corporation
** All Rights Reserved
**
*/
#include <windows.h>
#include <wchar.h>
#include <objbase.h>
#include <winbase.h>
// Required by SSPI.H
#define SECURITY_WIN32
#include <sspi.h>
#include <dsgetdc.h>
#include <ntdsapi.h>
#include <lmcons.h>
#include <lmapibuf.h>
#include <activeds.h>
#define CWSTR_SIZE(x) (sizeof(x) - (sizeof(WCHAR) * 2))
#define DWSTR_SIZE(x) ((wcslen(x) + 1) * sizeof(WCHAR))
#define LICENSE_SETTINGS L"TS-Enterprise-License-Server"
#define LICENSE_SETTINGS2 L"CN=TS-Enterprise-License-Server"
#define LICENSE_SETTINGS_OBJECT_CLASS L"LicensingSiteSettings"
#define LICENSE_SETTINGS_FORMAT L"LDAP://CN=%ws,CN=%ws,CN=%ws,%ws"
#define LICENSE_SETTINGS_SIZE CWSTR_SIZE(LICENSE_SETTINGS)
#define LICENSE_SETTINGS_FORMAT_SIZE CWSTR_SIZE(LICENSE_SETTINGS_FORMAT)
#define SITES L"sites"
#define SITES_SIZE CWSTR_SIZE(SITES)
#define SITE_SERVER L"siteServer"
#define SITE_FORMAT L"LDAP://CN=%ws,CN=%ws,%ws"
#define SITE_FORMAT_SIZE CWSTR_SIZE(SITE_FORMAT)
#define CONFIG_CNTNR L"ConfigurationNamingContext"
#define ROOT_DSE_PATH L"LDAP://RootDSE"
HRESULT GetLicenseSettingsObjectP(VARIANT *pvar,
LPWSTR *ppwszLicenseSettings,
LPWSTR *ppwszSiteName,
IADs **ppADs)
{
HRESULT hr;
DWORD dwErr;
LPWSTR pwszConfigContainer;
IADs * pADs = NULL;
VariantInit(pvar);
dwErr = DsGetSiteName(NULL, ppwszSiteName);
if (dwErr != 0)
{
#ifdef PRIVATEDEBUG
wprintf(L"DsGetSiteName failed %d - 0x%x\n",dwErr,HRESULT_FROM_WIN32(dwErr));
#endif
return HRESULT_FROM_WIN32(dwErr);
}
//
// Obtain the path to the configuration container.
//
hr = ADsGetObject(ROOT_DSE_PATH, IID_IADs, (void **)&pADs);
if (FAILED(hr)) {
#ifdef PRIVATEDEBUG
wprintf(L"ADsGetObject (%ws) failed 0x%x \n",ROOT_DSE_PATH,dwErr);
#endif
goto CleanExit;
}
hr = pADs->Get(CONFIG_CNTNR, pvar);
if (FAILED(hr)) {
#ifdef PRIVATEDEBUG
wprintf(L"Get (%ws) failed 0x%x \n",CONFIG_CNTNR,hr);
#endif
goto CleanExit;
}
if (V_VT(pvar) != VT_BSTR) {
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
#ifdef PRIVATEDEBUG
wprintf(L"Bad pvar 0x%x \n",hr);
#endif
goto CleanExit;
}
pwszConfigContainer = pvar->bstrVal; // For sake of readability.
//
// Build the X.500 path to the LicenseSettings object.
//
*ppwszLicenseSettings = (LPWSTR)LocalAlloc(
LPTR,
LICENSE_SETTINGS_FORMAT_SIZE
+ LICENSE_SETTINGS_SIZE
+ DWSTR_SIZE(*ppwszSiteName)
+ SITES_SIZE
+ DWSTR_SIZE(pwszConfigContainer)
+ sizeof(WCHAR));
if (*ppwszLicenseSettings == NULL) {
hr = E_OUTOFMEMORY;
#ifdef PRIVATEDEBUG
wprintf(L"LocalAlloc failed 0x%x \n",hr);
#endif
goto CleanExit;
}
wsprintf(*ppwszLicenseSettings,
LICENSE_SETTINGS_FORMAT,
LICENSE_SETTINGS,
*ppwszSiteName,
SITES,
pwszConfigContainer);
hr = ADsGetObject(*ppwszLicenseSettings, IID_IADs, (void **)ppADs);
CleanExit:
#ifdef PRIVATEDEBUG
wprintf(L"ADsGetObject (%ws) failed? 0x%x \n",*ppwszLicenseSettings,hr);
#endif
if (NULL != pADs) {
pADs->Release();
}
return hr;
}
HRESULT
GetServerPos(IADs *pADs,
VARIANT *pvar,
LONG *plLower,
LONG *plUpper,
LONG *plPos,
WCHAR *ComputerName
)
{
HRESULT hr;
VARIANT var;
SAFEARRAY *psaServers;
VariantInit(&var);
hr = pADs->GetEx(SITE_SERVER,pvar);
if (FAILED(hr))
{
hr = S_FALSE; // already gone
goto CleanExit;
}
psaServers = V_ARRAY(pvar);
if (NULL == psaServers)
{
hr = S_FALSE; // already gone
goto CleanExit;
}
hr= SafeArrayGetLBound( psaServers, 1, plLower );
if (FAILED(hr))
{
goto CleanExit;
}
hr= SafeArrayGetUBound( psaServers, 1, plUpper );
if (FAILED(hr))
{
goto CleanExit;
}
for( *plPos = *plLower; *plPos <= *plUpper; *plPos++ )
{
VariantClear( &var );
hr = SafeArrayGetElement( psaServers, plPos, &var );
if (SUCCEEDED(hr) && (V_VT(&var) == VT_BSTR) && (V_BSTR(&var) != NULL))
{
if (0 == lstrcmpi(V_BSTR(&var),ComputerName))
{
hr = S_OK;
goto CleanExit;
}
}
}
hr = S_FALSE;
CleanExit:
VariantClear(&var);
return hr;
}
extern "C"
HRESULT
PublishEnterpriseServer()
{
LPWSTR pwszSiteName = NULL;
DWORD dwErr;
LPWSTR pwszConfigContainer;
IADs * pADs = NULL;
IADs * pADs2 = NULL;
IADsContainer * pADsContainer = NULL;
VARIANT var;
VARIANT var2;
VARIANT var3;
VARIANT var4;
LPWSTR pwszLicenseSettings = NULL;
LPWSTR pwszSite = NULL;
IDispatch * pDisp = NULL;
WCHAR ComputerName[MAX_PATH+1];
ULONG ulen;
BOOL br;
HRESULT hr;
LONG lLower,lUpper,lPos;
SAFEARRAYBOUND sabServers;
LPWSTR pwszDN = NULL;
DS_NAME_RESULT * pDsResult = NULL;
HANDLE hDS;
LPWSTR rgpwszNames[2];
DOMAIN_CONTROLLER_INFO *pDCInfo = NULL;
LPWSTR pwszDomain;
WCHAR wszName[MAX_PATH + 1];
//
// We're going to use ADSI, so initialize COM. We don't
// care about OLE 1.0 so disable OLE 1 DDE
//
hr = CoInitializeEx(NULL,COINIT_MULTITHREADED| COINIT_DISABLE_OLE1DDE);
if (FAILED(hr))
{
#ifdef PRIVATEDEBUG
wprintf(L"CoInitializeEx failed 0x%lx\n",hr);
#endif
return hr;
}
VariantInit(&var);
VariantInit(&var2);
VariantInit(&var3);
VariantInit(&var4);
// Get the computer name of the local computer.
ulen = sizeof(ComputerName) / sizeof(TCHAR);
br = GetComputerName(ComputerName, &ulen);
if (!br)
{
hr = HRESULT_FROM_WIN32(GetLastError());
#ifdef PRIVATEDEBUG
wprintf(L"GetComputerName failed 0x%lx\n",hr);
#endif
goto CleanExit;
}
//
// Get domain name
//
hr = DsGetDcName(NULL,
NULL,
NULL,
NULL,
DS_DIRECTORY_SERVICE_PREFERRED | DS_RETURN_FLAT_NAME,
&pDCInfo);
if (hr != ERROR_SUCCESS) {
#ifdef PRIVATEDEBUG
wprintf(L"DsGetDcName failed 0x%lx\n",hr);
#endif
goto CleanExit;
}
pwszDomain = pDCInfo->DomainName;
//
// Bind to the DS (get a handle for use with DsCrackNames).
//
hr = DsBind(NULL, pwszDomain, &hDS);
if (hr != ERROR_SUCCESS) {
#ifdef PRIVATEDEBUG
wprintf(L"DsBind failed 0x%lx\n",hr);
#endif
goto CleanExit;
}
//
// Request the DS-DN of this server's computer object.
//
if (lstrlen(pwszDomain) + lstrlen(ComputerName) + 3 > sizeof(wszName) / sizeof(WCHAR))
{
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
#ifdef PRIVATEDEBUG
wprintf(L"Domain or ComputerName too long\n",hr);
#endif
goto CleanExit;
}
wsprintf(wszName,
L"%ws\\%ws$",
pwszDomain,
ComputerName);
rgpwszNames[0] = wszName;
rgpwszNames[1] = NULL;
hr = DsCrackNames(hDS,
DS_NAME_NO_FLAGS,
DS_UNKNOWN_NAME,
DS_FQDN_1779_NAME,
1,
&rgpwszNames[0],
&pDsResult);
DsUnBind(&hDS);
if (hr != ERROR_SUCCESS)
{
#ifdef PRIVATEDEBUG
wprintf(L"DsCrackNames failed 0x%lx\n",hr);
#endif
goto CleanExit;
}
if (pDsResult->rItems[0].status != DS_NAME_NO_ERROR) {
if (pDsResult->rItems[0].status == DS_NAME_ERROR_RESOLVING) {
hr = ERROR_PATH_NOT_FOUND;
}
else {
hr = pDsResult->rItems[0].status;
}
#ifdef PRIVATEDEBUG
wprintf(L"DsCrackNames (%ws) result bad 0x%lx\n",ComputerName,hr);
#endif
goto CleanExit;
}
V_VT(&var3) = VT_BSTR;
pwszDN = pDsResult->rItems[0].pName;
V_BSTR(&var3) = SysAllocString(pwszDN);
if (NULL == V_BSTR(&var3))
{
hr = E_OUTOFMEMORY;
goto CleanExit;
}
hr = GetLicenseSettingsObjectP(&var,
&pwszLicenseSettings,
&pwszSiteName,
&pADs);
pwszConfigContainer = var.bstrVal;
if (hr == HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT))
{
// Doesn't yet exist, create it
//
// Build the X.500 path to the Site object.
//
pwszSite = (LPWSTR)LocalAlloc(LPTR,
SITE_FORMAT_SIZE
+ DWSTR_SIZE(pwszSiteName)
+ SITES_SIZE
+ DWSTR_SIZE(pwszConfigContainer)
+ sizeof(WCHAR));
if (pwszSite == NULL) {
hr = E_OUTOFMEMORY;
goto CleanExit;
}
wsprintf(pwszSite,
SITE_FORMAT,
pwszSiteName,
SITES,
pwszConfigContainer);
hr = ADsGetObject(pwszSite,
IID_IADsContainer,
(void **)&pADsContainer);
if (FAILED(hr)) {
#ifdef PRIVATEDEBUG
wprintf(L"ADsGetObject (%ws) failed 0x%lx\n",pwszSite,hr);
#endif
goto CleanExit;
}
#ifdef PRIVATEDEBUG
wprintf(L"Got container (%ws)\n",pwszSite);
#endif
//
// Create the license settings leaf object.
//
hr = pADsContainer->Create(LICENSE_SETTINGS_OBJECT_CLASS,
LICENSE_SETTINGS2,
&pDisp);
if (FAILED(hr)) {
#ifdef PRIVATEDEBUG
wprintf(L"Create (LICENSE_SETTINGS) failed 0x%lx\n",hr);
#endif
goto CleanExit;
}
#ifdef PRIVATEDEBUG
wprintf(L"Created (%ws)\n",LICENSE_SETTINGS2);
#endif
hr = pDisp->QueryInterface(IID_IADs,
(void **)&pADs2);
if (FAILED(hr)) {
#ifdef PRIVATEDEBUG
wprintf(L"QueryInterface failed 0x%lx\n",hr);
#endif
goto CleanExit;
}
hr = pADs2->Put(SITE_SERVER,var3);
if (FAILED(hr)) {
#ifdef PRIVATEDEBUG
wprintf(L"Put (%ws) failed 0x%lx\n",SITE_SERVER,hr);
#endif
goto CleanExit;
}
//
// Persist the change via SetInfo.
//
hr = pADs2->SetInfo();
if (FAILED(hr)) {
#ifdef PRIVATEDEBUG
wprintf(L"SetInfo (%ws)=(%ws) failed 0x%lx\n",SITE_SERVER,V_BSTR(&var3),hr);
#endif
goto CleanExit;
}
} else if (SUCCEEDED(hr))
{
// Already exists; update it
hr = GetServerPos(pADs,&var2,&lLower,&lUpper,&lPos,pwszDN);
if (FAILED(hr) || (hr == S_OK))
{
#ifdef PRIVATEDEBUG
wprintf(L"GetServerPos failed ? 0x%lx\n",hr);
#endif
goto CleanExit;
}
hr = ADsBuildVarArrayStr( &(V_BSTR(&var3)), 1, &var4);
if (FAILED(hr)) {
#ifdef PRIVATEDEBUG
wprintf(L"ADsBuildVarArrayStr (%ws) failed 0x%lx\n",V_BSTR(&var3),hr);
#endif
goto CleanExit;
}
hr = pADs->PutEx(ADS_PROPERTY_APPEND,SITE_SERVER,var4);
if (FAILED(hr)) {
#ifdef PRIVATEDEBUG
wprintf(L"PutEx (%ws)=(%ws) failed 0x%lx\n",SITE_SERVER,V_BSTR(&var3),hr);
#endif
goto CleanExit;
}
hr = pADs->SetInfo();
if (FAILED(hr)) {
#ifdef PRIVATEDEBUG
wprintf(L"SetInfo 2 failed 0x%lx\n",hr);
#endif
goto CleanExit;
}
} else
{
#ifdef PRIVATEDEBUG
wprintf(L"GetLicenseSettingsObject failed 0x%lx\n",hr);
#endif
goto CleanExit;
}
CleanExit:
VariantClear(&var);
VariantClear(&var2);
VariantClear(&var3);
VariantClear(&var4);
if (pwszSiteName != NULL) { // Allocated from DsGetSiteName
NetApiBufferFree(pwszSiteName);
}
if (pwszLicenseSettings != NULL) {
LocalFree(pwszLicenseSettings);
}
if (pwszSite != NULL) {
LocalFree(pwszSite);
}
if (NULL != pADs) {
pADs->Release();
}
if (NULL != pADs2) {
pADs2->Release();
}
if (NULL != pDisp) {
pDisp->Release();
}
if (NULL != pADsContainer) {
pADsContainer->Release();
}
if (pDsResult != NULL) {
DsFreeNameResult(pDsResult);
}
if (pDCInfo != NULL) {
NetApiBufferFree(pDCInfo); // Allocated from DsGetDcName
}
CoUninitialize();
return hr;
}
extern "C"
HRESULT
UnpublishEnterpriseServer()
{
IADs * pADs = NULL;
HRESULT hr;
LPWSTR pwszLicenseSettings = NULL;
LPWSTR pwszSiteName = NULL;
VARIANT var;
VARIANT var2;
VARIANT var3;
SAFEARRAYBOUND sabServers;
WCHAR ComputerName[MAX_PATH+1];
ULONG ulen;
BOOL br;
LONG lPos,lLower, lUpper;
DS_NAME_RESULT * pDsResult = NULL;
HANDLE hDS;
LPWSTR rgpwszNames[2];
LPWSTR pwszDN;
DOMAIN_CONTROLLER_INFO *pDCInfo = NULL;
LPWSTR pwszDomain;
WCHAR wszName[MAX_PATH + 1];
// We're going to use ADSI, so initialize COM. We don't
// care about OLE 1.0 so disable OLE 1 DDE
hr = CoInitializeEx(NULL,COINIT_MULTITHREADED| COINIT_DISABLE_OLE1DDE);
if (FAILED(hr))
{
return hr;
}
VariantInit(&var);
VariantInit(&var2);
VariantInit(&var3);
// Get the computer name of the local computer.
ulen = sizeof(ComputerName) / sizeof(TCHAR);
br=GetComputerName(ComputerName,
&ulen);
if (!br)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto CleanExit;
}
//
// Get domain name
//
hr = DsGetDcName(NULL,
NULL,
NULL,
NULL,
DS_DIRECTORY_SERVICE_PREFERRED | DS_RETURN_FLAT_NAME,
&pDCInfo);
if (hr != ERROR_SUCCESS) {
#ifdef PRIVATEDEBUG
wprintf(L"DsGetDcName failed 0x%lx\n",hr);
#endif
goto CleanExit;
}
pwszDomain = pDCInfo->DomainName;
//
// Bind to the DS (get a handle for use with DsCrackNames).
//
hr = DsBind(NULL, pwszDomain, &hDS);
if (hr != ERROR_SUCCESS) {
#ifdef PRIVATEDEBUG
wprintf(L"DsBind failed 0x%lx\n",hr);
#endif
goto CleanExit;
}
//
// Request the DS-DN of this server's computer object.
//
if (lstrlen(pwszDomain) + lstrlen(ComputerName) + 3 > sizeof(wszName) / sizeof(WCHAR))
{
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
#ifdef PRIVATEDEBUG
wprintf(L"Domain or ComputerName too long\n",hr);
#endif
goto CleanExit;
}
wsprintf(wszName,
L"%ws\\%ws$",
pwszDomain,
ComputerName);
rgpwszNames[0] = wszName;
rgpwszNames[1] = NULL;
hr = DsCrackNames(hDS,
DS_NAME_NO_FLAGS,
DS_UNKNOWN_NAME,
DS_FQDN_1779_NAME,
1,
&rgpwszNames[0],
&pDsResult);
DsUnBind(&hDS);
if (hr != ERROR_SUCCESS)
{
#ifdef PRIVATEDEBUG
wprintf(L"DsCrackNames failed 0x%lx\n",hr);
#endif
goto CleanExit;
}
if (pDsResult->rItems[0].status != DS_NAME_NO_ERROR) {
if (pDsResult->rItems[0].status == DS_NAME_ERROR_RESOLVING) {
hr = ERROR_PATH_NOT_FOUND;
}
else {
hr = pDsResult->rItems[0].status;
}
#ifdef PRIVATEDEBUG
wprintf(L"DsCrackNames result bad 0x%lx\n",hr);
#endif
goto CleanExit;
}
V_VT(&var3) = VT_BSTR;
pwszDN = pDsResult->rItems[0].pName;
V_BSTR(&var3) = SysAllocString(pwszDN);
if (NULL == V_BSTR(&var3))
{
hr = E_OUTOFMEMORY;
goto CleanExit;
}
hr = GetLicenseSettingsObjectP(&var,
&pwszLicenseSettings,
&pwszSiteName,
&pADs);
if (hr == HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT))
{
hr = S_OK; // already gone
goto CleanExit;
}
if (FAILED(hr))
{
goto CleanExit;
}
#ifdef PRIVATEDEBUG
wprintf(L"pADs %ws NULL \n",(pADs == NULL) ? L"==" : L"!=");
if (NULL == pADs)
{
goto CleanExit;
}
#endif
hr = GetServerPos(pADs,&var2,&lLower,&lUpper,&lPos,pwszDN);
if (FAILED(hr))
{
goto CleanExit;
}
if (hr == S_FALSE)
{
hr = S_OK; // Already gone
goto CleanExit;
}
if (lLower == lUpper)
{
// only one element, delete
hr = pADs->PutEx(ADS_PROPERTY_CLEAR,SITE_SERVER,var2);
if (FAILED(hr)) {
goto CleanExit;
}
}
else
{
if (lPos != lUpper)
{
// move the last element here
SafeArrayGetElement(V_ARRAY(&var2),&lUpper,&var3);
SafeArrayPutElement(V_ARRAY(&var2),&lPos,&var3);
}
sabServers.lLbound = lLower;
sabServers.cElements = lUpper-lLower;
SafeArrayRedim(V_ARRAY(&var2),&sabServers);
hr = pADs->Put(SITE_SERVER,var2);
if (FAILED(hr)) {
goto CleanExit;
}
}
hr = pADs->SetInfo();
if (FAILED(hr)) {
goto CleanExit;
}
CleanExit:
VariantClear(&var);
VariantClear(&var2);
VariantClear(&var3);
if (pwszSiteName != NULL) { // Allocated from DsGetSiteName
NetApiBufferFree(pwszSiteName);
}
if (pwszLicenseSettings != NULL) {
LocalFree(pwszLicenseSettings);
}
if (NULL != pADs) {
pADs->Release();
}
if (pDCInfo != NULL) {
NetApiBufferFree(pDCInfo); // Allocated from DsGetDcName
}
CoUninitialize();
return hr;
}