//-------------------------------------------------------------------- // DcInfo - implementation // Copyright (C) Microsoft Corporation, 1999 // // Created by: Louis Thomas (louisth), 7-8-99 // // Gather information about the DCs in a domain #include "pch.h" // precompiled headers #include "DcInfo.h" //#################################################################### // module private functions //-------------------------------------------------------------------- // Get a list of DCs in this domain from the DS on an up DC. MODULEPRIVATE HRESULT GetDcListFromDs(const WCHAR * wszDomainName, DcInfo ** prgDcs, unsigned int * pnDcs) { HRESULT hr; NET_API_STATUS dwNetStatus; DWORD dwDcCount; unsigned int nIndex; unsigned int nDcs; unsigned int nDcIndex; // varaibles that must be cleaned up DOMAIN_CONTROLLER_INFOW * pDcInfo=NULL; HANDLE hDs=NULL; DS_DOMAIN_CONTROLLER_INFO_1W * rgDsDcInfo=NULL; DcInfo * rgDcs=NULL; // initialize out variables *prgDcs=NULL; *pnDcs=0; // Get a DC to seed the algorithm with dwNetStatus=DsGetDcName( NULL, // computer name wszDomainName, // domain name NULL, // domain guid NULL, // site name DS_DIRECTORY_SERVICE_PREFERRED, // flags &pDcInfo); // DC info if (NO_ERROR!=dwNetStatus) { hr=HRESULT_FROM_WIN32(dwNetStatus); _JumpError(hr, error, "DsGetDcName"); } if (0==(pDcInfo->Flags&DS_DS_FLAG)) { hr=HRESULT_FROM_WIN32(ERROR_DS_DST_DOMAIN_NOT_NATIVE); // not an NT5 domain. _JumpError(hr, error, "DsGetDcName"); } // Bind to the target DS dwNetStatus=DsBind( pDcInfo->DomainControllerName, // DC Address NULL, // DNS domain name &hDs ); // DS handle if (NO_ERROR!=dwNetStatus) { hr=HRESULT_FROM_WIN32(dwNetStatus); _JumpError(hr, error, "DsBind"); } // Get the list of DCs from the target DS. dwNetStatus=DsGetDomainControllerInfo( hDs, // DS handle pDcInfo->DomainName, // domain name 1, // Info level &dwDcCount, // number of names returned (void **)&rgDsDcInfo); // array of names if (NO_ERROR!=dwNetStatus ) { hr=HRESULT_FROM_WIN32(dwNetStatus); _JumpError(hr, error, "DsGetDomainControllerInfo"); } // figure out how many DCs there are with DNS names nDcs=0; for (nIndex=0; nIndex=5) { nDcs++; } } if (nDcs=5) { // allocate and copy name rgDcs[nDcIndex].wszDnsName=(WCHAR *)LocalAlloc(LPTR, sizeof(WCHAR)*(wcslen(rgsiServerInfo[nIndex].sv101_name)+1)); _JumpIfOutOfMemory(hr, error, rgDcs[nDcIndex].wszDnsName); wcscpy(rgDcs[nDcIndex].wszDnsName, rgsiServerInfo[nIndex].sv101_name); // copy PDCness rgDcs[nDcIndex].bIsPdc=(rgsiServerInfo[nIndex].sv101_type&SV_TYPE_DOMAIN_CTRL)?true:false; nDcIndex++; } } // move the data to the out parameters *prgDcs=rgDcs; rgDcs=NULL; *pnDcs=nDcs; hr=S_OK; error: if (NULL!=rgDcs) { for (nIndex=0; nIndexwszDnsName); // initialize the search AFPROTOCOLS apInetUdp={AF_INET, IPPROTO_UDP}; GUID guidNtp=SVCID_NTP_UDP; WSAQUERYSETW qsSearch; ZeroMemory(&qsSearch, sizeof(qsSearch)); qsSearch.dwSize=sizeof(qsSearch); qsSearch.lpszServiceInstanceName=const_cast(pdi->wszDnsName); qsSearch.lpServiceClassId=&guidNtp; qsSearch.dwNameSpace=NS_ALL; qsSearch.dwNumberOfProtocols=1; qsSearch.lpafpProtocols=&apInetUdp; // begin the search if (SOCKET_ERROR==WSALookupServiceBegin(&qsSearch, LUP_RETURN_ADDR/*flags*/, &hSearch)) { hr=HRESULT_FROM_WIN32(WSAGetLastError()); _JumpError(hr, error, "WSALookupServiceBegin"); } // get the buffer size for the first result set //dwDataLen=1; //_Verify(SOCKET_ERROR==WSALookupServiceNext(hSearch, LUP_RETURN_ADDR/*flags*/, &dwDataLen, &qsSearch), hr, error); //hr=WSAGetLastError(); //if (WSAEFAULT!=hr) { // hr=HRESULT_FROM_WIN32(hr); // _JumpError(hr, error, "WSALookupServiceNext(1)"); //} dwDataLen=5*1024; // allocate the buffer pqsResult=(WSAQUERYSETW *)LocalAlloc(LPTR, dwDataLen); _JumpIfOutOfMemory(hr, error, pqsResult); // retrieve the result set if (SOCKET_ERROR==WSALookupServiceNext(hSearch, LUP_RETURN_ADDR/*flags*/, &dwDataLen, pqsResult)) { hr=HRESULT_FROM_WIN32(WSAGetLastError()); _JumpError(hr, error, "WSALookupServiceNext(2)"); } _Verify(0!=pqsResult->dwNumberOfCsAddrs, hr, error) ; // allocate room for the IP addresses rgiaLocalIpAddresses=(in_addr *)LocalAlloc(LPTR, sizeof(in_addr)*pqsResult->dwNumberOfCsAddrs); _JumpIfOutOfMemory(hr, error, rgiaLocalIpAddresses); rgiaRemoteIpAddresses=(in_addr *)LocalAlloc(LPTR, sizeof(in_addr)*pqsResult->dwNumberOfCsAddrs); _JumpIfOutOfMemory(hr, error, rgiaRemoteIpAddresses); // copy the IP addresses for (nIndex=0; nIndexdwNumberOfCsAddrs; nIndex++) { // copy local _Verify(sizeof(sockaddr)==pqsResult->lpcsaBuffer[nIndex].LocalAddr.iSockaddrLength, hr, error); _Verify(AF_INET==pqsResult->lpcsaBuffer[nIndex].LocalAddr.lpSockaddr->sa_family, hr, error); rgiaLocalIpAddresses[nIndex].S_un.S_addr=((sockaddr_in *)(pqsResult->lpcsaBuffer[nIndex].LocalAddr.lpSockaddr))->sin_addr.S_un.S_addr; // copy remote _Verify(sizeof(sockaddr)==pqsResult->lpcsaBuffer[nIndex].RemoteAddr.iSockaddrLength, hr, error); _Verify(AF_INET==pqsResult->lpcsaBuffer[nIndex].RemoteAddr.lpSockaddr->sa_family, hr, error); rgiaRemoteIpAddresses[nIndex].S_un.S_addr=((sockaddr_in *)(pqsResult->lpcsaBuffer[nIndex].RemoteAddr.lpSockaddr))->sin_addr.S_un.S_addr; } // move the data to the out parameters pdi->nIpAddresses=pqsResult->dwNumberOfCsAddrs; pdi->rgiaLocalIpAddresses=rgiaLocalIpAddresses; rgiaLocalIpAddresses=NULL; pdi->rgiaRemoteIpAddresses=rgiaRemoteIpAddresses; rgiaRemoteIpAddresses=NULL; hr=S_OK; error: if (NULL!=rgiaLocalIpAddresses) { LocalFree(rgiaLocalIpAddresses); } if (NULL!=rgiaRemoteIpAddresses) { LocalFree(rgiaRemoteIpAddresses); } if (NULL!=pqsResult) { LocalFree(pqsResult); } if (INVALID_HANDLE_VALUE!=hSearch) { if (SOCKET_ERROR==WSALookupServiceEnd(hSearch)) { HRESULT hr2=HRESULT_FROM_WIN32(WSAGetLastError()); _IgnoreError(hr2, "WSALookupServiceEnd"); } } return hr; } //#################################################################### // Globals //-------------------------------------------------------------------- void FreeDcInfo(DcInfo * pdci) { if (NULL!=pdci->wszDnsName) { LocalFree(pdci->wszDnsName); } if (NULL!=pdci->rgiaLocalIpAddresses) { LocalFree(pdci->rgiaLocalIpAddresses); } if (NULL!=pdci->rgiaRemoteIpAddresses) { LocalFree(pdci->rgiaRemoteIpAddresses); } } //-------------------------------------------------------------------- // Get a list of DCs in this domain HRESULT GetDcList(const WCHAR * wszDomainName, bool bGetIps, DcInfo ** prgDcs, unsigned int * pnDcs) { HRESULT hr; unsigned int nDcs; unsigned int nIndex; // varaibles that must be cleaned up DcInfo * rgDcs=NULL; // initialize out variables *prgDcs=NULL; *pnDcs=0; hr=GetDcListFromDs(wszDomainName, &rgDcs, &nDcs); if (FAILED(hr)) { _IgnoreError(hr, "GetDcListFromDs"); hr=GetDcListFromNetlogon(wszDomainName, &rgDcs, &nDcs); _JumpIfError(hr, error, "GetDcListFromNetlogon"); } if (bGetIps) { // get the info about the DCs for (nIndex=0; nIndex