Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

277 lines
9.2 KiB

  1. /*---------------------------------------------------------------------------
  2. File: NetObjEnumerator.cpp
  3. Comments: Implementation of NetObjectEnumerator COM object.
  4. (c) Copyright 1999, Mission Critical Software, Inc., All Rights Reserved
  5. Proprietary and confidential to Mission Critical Software, Inc.
  6. REVISION LOG ENTRY
  7. Revision By: Sham Chauthani
  8. Revised on 07/02/99 12:40:00
  9. ---------------------------------------------------------------------------
  10. */
  11. #include "stdafx.h"
  12. #include "NetEnum.h"
  13. #include "ObjEnum.h"
  14. #include "Win2KDom.h"
  15. #include "NT4DOm.h"
  16. #include <lmaccess.h>
  17. #include <lmwksta.h>
  18. #include <lmapibuf.h>
  19. #include <dsgetdc.h>
  20. #ifdef _DEBUG
  21. #define new DEBUG_NEW
  22. #undef THIS_FILE
  23. static char THIS_FILE[] = __FILE__;
  24. #endif
  25. /////////////////////////////////////////////////////////////////////////////
  26. // CNetObjEnumerator
  27. typedef HRESULT (CALLBACK * DSGETDCNAME)(LPWSTR, LPWSTR, GUID*, LPWSTR, DWORD, PDOMAIN_CONTROLLER_INFO*);
  28. //---------------------------------------------------------------------------
  29. // GetContainerEnum: This function returns the enumeration of all objects
  30. // in a given container for a specified domain. It returns
  31. // all objects in an enumeration object.
  32. //---------------------------------------------------------------------------
  33. STDMETHODIMP CNetObjEnumerator::GetContainerEnum(
  34. BSTR sContainerName, //in -LDAP path to the container which we want to Enum
  35. BSTR sDomainName, //in -Domain name where we want to look
  36. IEnumVARIANT ** ppVarEnum //out -Enumeration object. It contains all members of
  37. // the container specified above.
  38. )
  39. {
  40. LPBYTE sTargetMachine;
  41. WKSTA_INFO_100 * pInfo;
  42. DWORD rc = NetGetDCName( NULL, sDomainName, &sTargetMachine);
  43. if ( !rc )
  44. {
  45. rc = NetWkstaGetInfo((unsigned short *)sTargetMachine,100,(LPBYTE*)&pInfo);
  46. if ( ! rc )
  47. {
  48. HRESULT hr;
  49. if ( pInfo->wki100_ver_major < 5 )
  50. {
  51. CNT4Dom dom;
  52. hr = dom.GetContainerEnum(sContainerName, sDomainName, ppVarEnum);
  53. }
  54. else
  55. {
  56. CWin2000Dom dom;
  57. hr = dom.GetContainerEnum(sContainerName, sDomainName, ppVarEnum);
  58. }
  59. NetApiBufferFree(pInfo);
  60. return hr;
  61. }
  62. NetApiBufferFree(sTargetMachine);
  63. }
  64. return S_FALSE;
  65. }
  66. //---------------------------------------------------------------------------
  67. // SetQuery: This function sets all the parameters necessary for a query
  68. // to be executed. User can not call Execute without first calling
  69. // this method.
  70. //---------------------------------------------------------------------------
  71. STDMETHODIMP CNetObjEnumerator::SetQuery(
  72. BSTR sContainer, //in -Container name
  73. BSTR sDomain, //in -Domain name
  74. BSTR sQuery, //in -Query in LDAP syntax
  75. long nSearchScope, //in -Scope of the search. ADS_ATTR_SUBTREE/ADS_ATTR_ONELEVEL
  76. long bMultiVal //in- Do we need to return multivalued properties?
  77. )
  78. {
  79. Cleanup();
  80. // Save all the settings in member variables.
  81. m_sDomain = sDomain;
  82. m_sContainer = sContainer;
  83. m_sQuery = sQuery;
  84. m_bSetQuery = true;
  85. m_bMultiVal = bMultiVal;
  86. if ( nSearchScope < 0 || nSearchScope > 2 )
  87. return E_INVALIDARG;
  88. prefInfo.dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
  89. prefInfo.vValue.dwType = ADSTYPE_INTEGER;
  90. prefInfo.vValue.Integer = nSearchScope;
  91. return S_OK;
  92. }
  93. //---------------------------------------------------------------------------
  94. // SetColumns: This function sets all the columns that the user wants to be
  95. // returned when query is executed.
  96. //---------------------------------------------------------------------------
  97. STDMETHODIMP CNetObjEnumerator::SetColumns(
  98. SAFEARRAY * colNames //in -Pointer to a SafeArray that contains all the columns
  99. )
  100. {
  101. // We require that the SetQuery method be called before SetColumns is called. Hence we will return E_FAIL
  102. // If we expose these interface we should document this.
  103. if (!m_bSetQuery)
  104. return E_FAIL;
  105. if ( m_bSetCols )
  106. {
  107. Cleanup();
  108. m_bSetQuery = true;
  109. }
  110. SAFEARRAY * pcolNames = colNames;
  111. long dwLB;
  112. long dwUB;
  113. BSTR HUGEP * pBSTR;
  114. HRESULT hr;
  115. // Get the bounds of the column Array
  116. hr = ::SafeArrayGetLBound(pcolNames, 1, &dwLB);
  117. if (FAILED(hr))
  118. return hr;
  119. hr = ::SafeArrayGetUBound(pcolNames, 1, &dwUB);
  120. if (FAILED(hr))
  121. return hr;
  122. m_nCols = dwUB-dwLB + 1;
  123. // We dont support empty columns request atleast one column.
  124. if ( m_nCols == 0 )
  125. return E_FAIL;
  126. hr = ::SafeArrayAccessData(pcolNames, (void **) &pBSTR);
  127. if ( FAILED(hr) )
  128. return hr;
  129. // Allocate space for the array. It is deallocated by Cleanup()
  130. m_pszAttr = new LPWSTR[m_nCols];
  131. if (m_pszAttr == NULL)
  132. {
  133. ::SafeArrayUnaccessData(pcolNames);
  134. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  135. }
  136. // Each column is now put into the Array
  137. for ( long dw = 0; dw < m_nCols; dw++)
  138. {
  139. m_pszAttr[dw] = SysAllocString(pBSTR[dw]);
  140. }
  141. hr = ::SafeArrayUnaccessData(pcolNames);
  142. m_bSetCols = true;
  143. return hr;
  144. }
  145. //---------------------------------------------------------------------------
  146. // Cleanup: This function cleans up all the allocations and the member vars.
  147. //---------------------------------------------------------------------------
  148. void CNetObjEnumerator::Cleanup()
  149. {
  150. if ( m_nCols > 0 )
  151. {
  152. if ( m_pszAttr )
  153. {
  154. // delete the contents of the array
  155. for ( int i = 0 ; i < m_nCols ; i++ )
  156. {
  157. SysFreeString(m_pszAttr[i]);
  158. }
  159. // Dealloc the array itself
  160. delete [] m_pszAttr;
  161. m_pszAttr = NULL;
  162. }
  163. // Reset all counts and flags.
  164. m_nCols = 0;
  165. m_bSetQuery = false;
  166. m_bSetCols = false;
  167. }
  168. }
  169. //---------------------------------------------------------------------------
  170. // Execute: This function actually executes the query and then builds an
  171. // enumerator object and returns it.
  172. //---------------------------------------------------------------------------
  173. STDMETHODIMP CNetObjEnumerator::Execute(
  174. IEnumVARIANT **pEnumerator //out -Pointer to the enumerator object.
  175. )
  176. {
  177. // This function will take the options set in SetQuery and SetColumns to enumerate objects
  178. // for the given domain. This could be a NT4 domain or a Win2K domain. Although at the moment
  179. // NT4 domains simply enumerate all objects in the given container, we could later implement
  180. // certain features to support queries etc.
  181. DOMAIN_CONTROLLER_INFO * pSrcDomCtrlInfo = NULL;
  182. if ( !m_bSetCols )
  183. return E_FAIL;
  184. CDomain * pDom;
  185. WKSTA_INFO_100 * pInfo = NULL;
  186. HRESULT hr = S_FALSE;
  187. *pEnumerator = NULL;
  188. // Load DsGetDcName dynamically
  189. DSGETDCNAME DsGetDcName = NULL;
  190. HMODULE hPro = LoadLibrary(L"NetApi32.dll");
  191. if ( hPro )
  192. DsGetDcName = (DSGETDCNAME)GetProcAddress(hPro, "DsGetDcNameW");
  193. if ( DsGetDcName )
  194. {
  195. DWORD rc = DsGetDcName(
  196. NULL ,// LPCTSTR ComputerName ?
  197. m_sDomain ,// LPCTSTR DomainName
  198. NULL ,// GUID *DomainGuid ?
  199. NULL ,// LPCTSTR SiteName ?
  200. 0 ,// ULONG Flags ?
  201. &pSrcDomCtrlInfo // PDOMAIN_CONTROLLER_INFO *DomainControllerInfo
  202. );
  203. if ( !rc )
  204. {
  205. rc = NetWkstaGetInfo(pSrcDomCtrlInfo->DomainControllerName,100,(LPBYTE*)&pInfo);
  206. if ( ! rc )
  207. {
  208. if ( pInfo->wki100_ver_major < 5 )
  209. pDom = new CNT4Dom();
  210. else
  211. pDom = new CWin2000Dom();
  212. if (!pDom)
  213. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  214. NetApiBufferFree(pInfo);
  215. try{
  216. hr = pDom->GetEnumeration(m_sContainer, m_sDomain, m_sQuery, m_nCols, m_pszAttr, prefInfo, m_bMultiVal, pEnumerator);
  217. }
  218. catch ( _com_error &e)
  219. {
  220. delete pDom;
  221. return e.Error();
  222. }
  223. delete pDom;
  224. }
  225. else
  226. {
  227. hr = HRESULT_FROM_WIN32(rc);
  228. }
  229. NetApiBufferFree(pSrcDomCtrlInfo);
  230. }
  231. else
  232. {
  233. hr = HRESULT_FROM_WIN32(rc);
  234. }
  235. }
  236. else
  237. {
  238. hr = HRESULT_FROM_WIN32(GetLastError());
  239. }
  240. if ( hPro )
  241. FreeLibrary(hPro);
  242. return hr;
  243. }