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.

516 lines
13 KiB

  1. // DsctlObj.cpp : Implementation of CdsctlApp and DLL registration.
  2. #include "stdafx.h"
  3. #include <wininet.h>
  4. #include "dsctl.h"
  5. #include "DsctlObj.h"
  6. #include <activeds.h>
  7. TCHAR DebugOut[MAX_PATH];
  8. /////////////////////////////////////////////////////////////////////////////
  9. //
  10. STDMETHODIMP CDsctlObject::InterfaceSupportsErrorInfo(REFIID riid)
  11. {
  12. if (riid == IID_IDsctl)
  13. return S_OK;
  14. return S_FALSE;
  15. }
  16. //+----------------------------------------------------------------------------
  17. //
  18. // Method: CDsctlObject::DSGetObject
  19. //
  20. // Synopsis: Returns a DS object.
  21. //
  22. //-----------------------------------------------------------------------------
  23. STDMETHODIMP
  24. CDsctlObject::DSGetObject(VARIANT ADsPath, VARIANT * pRetVar)
  25. {
  26. HRESULT hr;
  27. VariantInit(pRetVar);
  28. // DebugBreak();
  29. if (ADsPath.vt != VT_BSTR)
  30. {
  31. #ifdef DBG
  32. OutputDebugString(TEXT("DSctl::DsGetObject not passed a string!\n"));
  33. #endif
  34. pRetVar->vt = VT_ERROR;
  35. pRetVar->scode = E_INVALIDARG;
  36. return E_INVALIDARG;
  37. }
  38. m_Path = SysAllocString(ADsPath.bstrVal);
  39. if (m_Path == NULL)
  40. {
  41. #ifdef DBG
  42. OutputDebugString(TEXT("DSctl::DsGetObject allocation failed!\n"));
  43. #endif
  44. pRetVar->vt = VT_ERROR;
  45. pRetVar->scode = E_OUTOFMEMORY;
  46. return E_OUTOFMEMORY;
  47. }
  48. #ifdef DBG
  49. wsprintf(DebugOut, TEXT("DSctl::DsGetObject: Path to object is: %ws\n"),
  50. m_Path);
  51. OutputDebugString(DebugOut);
  52. #endif
  53. hr = ADsGetObject(m_Path, IID_IDispatch, (void **)&pRetVar->pdispVal);
  54. if (FAILED(hr))
  55. {
  56. #ifdef DBG
  57. wsprintf(DebugOut,
  58. TEXT("DSctl::DsGetObject: ADsGetObject returned: %lx\n"), hr);
  59. OutputDebugString(DebugOut);
  60. #endif
  61. pRetVar->vt = VT_ERROR;
  62. pRetVar->scode = E_FAIL;
  63. return E_FAIL;
  64. }
  65. #ifdef DBG
  66. wsprintf(DebugOut,
  67. TEXT("DSctl::DsGetObject - Returning Object: 0x%x\n\n"),
  68. pRetVar->pdispVal);
  69. OutputDebugString(DebugOut);
  70. #endif
  71. pRetVar->vt = VT_DISPATCH;
  72. return S_OK;
  73. }
  74. //+----------------------------------------------------------------------------
  75. //
  76. // Method: CDsctlObject::DSGetEnum
  77. //
  78. // Synopsis: Returns a container enumerator
  79. //
  80. //-----------------------------------------------------------------------------
  81. STDMETHODIMP
  82. CDsctlObject::DSGetEnum(VARIANT ADsPath, VARIANT* retval)
  83. {
  84. HRESULT hr;
  85. VARIANT vaResult;
  86. IADsContainer *pCont;
  87. VariantInit(&vaResult);
  88. if (ADsPath.vt == VT_BSTR) {
  89. m_Path = SysAllocString(ADsPath.bstrVal);
  90. } else {
  91. vaResult.vt = VT_ERROR;
  92. vaResult.scode = E_FAIL;
  93. #ifdef DBG
  94. OutputDebugString(TEXT("DSctl: DSGetEnum not passed a string path\n"));
  95. #endif
  96. *retval = vaResult;
  97. return S_OK;
  98. }
  99. // DebugBreak();
  100. #ifdef DBG
  101. OutputDebugString(TEXT("DSctl: GetEnum entered...\n"));
  102. wsprintf (DebugOut, TEXT("DSctl: ptr to object is: %lx\n"), &ADsPath);
  103. OutputDebugString(DebugOut);
  104. wsprintf (DebugOut, TEXT("DSctl: Path to object is: %ws\n"), ADsPath.bstrVal);
  105. OutputDebugString(DebugOut);
  106. #endif
  107. hr = ADsGetObject(m_Path, IID_IADsContainer,(void **)&pCont);
  108. if (SUCCEEDED(hr)) {
  109. hr = ADsBuildEnumerator(pCont,(IEnumVARIANT**)&vaResult.punkVal);
  110. if (SUCCEEDED(hr))
  111. vaResult.vt = VT_UNKNOWN;
  112. else {
  113. vaResult.vt = VT_ERROR;
  114. vaResult.scode = E_FAIL;
  115. #ifdef DBG
  116. wsprintf(DebugOut,
  117. TEXT("DSctl: OleDSBuildEnumerator returned: %lx\n"), hr);
  118. OutputDebugString(DebugOut);
  119. #endif
  120. }
  121. } else {
  122. vaResult.vt = VT_ERROR;
  123. vaResult.scode = E_FAIL;
  124. #ifdef DBG
  125. wsprintf (DebugOut, TEXT("DSctl: OleDSGetObject returned: %lx\n"), hr);
  126. OutputDebugString(DebugOut);
  127. #endif
  128. }
  129. *retval = vaResult;
  130. return S_OK;
  131. }
  132. //+----------------------------------------------------------------------------
  133. //
  134. // Method: CDsctlObject::DSGetMemberEnum
  135. //
  136. // Synopsis: Returns a members (group) object enumerator
  137. //
  138. //-----------------------------------------------------------------------------
  139. STDMETHODIMP
  140. CDsctlObject::DSGetMemberEnum(VARIANT ObjectPtr, VARIANT* retval)
  141. {
  142. #ifdef DBG
  143. OutputDebugString(TEXT("DSctl: GetMemberEnum entered...\n"));
  144. #endif
  145. VARIANT vaResult;
  146. VariantInit(&vaResult);
  147. IUnknown * pDisp;
  148. //
  149. // Get the DS object pointer.
  150. //
  151. if (ObjectPtr.vt == VT_DISPATCH || ObjectPtr.vt == VT_UNKNOWN)
  152. {
  153. pDisp = ObjectPtr.pdispVal;
  154. }
  155. else
  156. {
  157. if (ObjectPtr.vt == (VT_BYREF | VT_VARIANT))
  158. {
  159. if ((ObjectPtr.pvarVal)->vt == VT_DISPATCH ||
  160. (ObjectPtr.pvarVal)->vt == VT_UNKNOWN)
  161. {
  162. pDisp = (ObjectPtr.pvarVal)->pdispVal;
  163. }
  164. else
  165. {
  166. vaResult.vt = VT_ERROR;
  167. vaResult.scode = E_FAIL;
  168. *retval = vaResult;
  169. return S_OK;
  170. }
  171. }
  172. }
  173. IADsMembers * pDsMembers;
  174. HRESULT hr = pDisp->QueryInterface(IID_IADsMembers, (void **)&pDsMembers);
  175. if (FAILED(hr))
  176. {
  177. vaResult.vt = VT_ERROR;
  178. vaResult.scode = E_FAIL;
  179. *retval = vaResult;
  180. return S_OK;
  181. }
  182. hr = pDsMembers->get__NewEnum((IUnknown **)&vaResult.punkVal);
  183. if (SUCCEEDED(hr)) {
  184. vaResult.vt = VT_UNKNOWN;
  185. } else {
  186. vaResult.vt = VT_ERROR;
  187. vaResult.scode = E_FAIL;
  188. #ifdef DBG
  189. wsprintf(DebugOut,
  190. TEXT("DSctl: OleDSBuildEnumerator returned: %lx\n"), hr);
  191. OutputDebugString(DebugOut);
  192. #endif
  193. }
  194. pDsMembers->Release();
  195. *retval = vaResult;
  196. return S_OK;
  197. }
  198. //+----------------------------------------------------------------------------
  199. //
  200. // Method: CDsctlObject::DSEnumNext
  201. //
  202. // Synopsis: Iterates through the enumeration sequence
  203. //
  204. //-----------------------------------------------------------------------------
  205. STDMETHODIMP
  206. CDsctlObject::DSEnumNext(VARIANT Enum, VARIANT* retval)
  207. {
  208. HRESULT hr;
  209. VARIANT vaResult;
  210. ULONG iCount;
  211. VariantInit(&vaResult);
  212. if (Enum.punkVal == NULL) {
  213. vaResult.vt = VT_ERROR;
  214. vaResult.scode = E_FAIL;
  215. } else {
  216. //DebugBreak();
  217. hr = ADsEnumerateNext((IEnumVARIANT*)Enum.punkVal,1,&vaResult,&iCount);
  218. if (!SUCCEEDED(hr)) {
  219. ADsFreeEnumerator((IEnumVARIANT*)Enum.punkVal);
  220. vaResult.vt = VT_ERROR;
  221. vaResult.scode = E_FAIL;
  222. }
  223. }
  224. *retval = vaResult;
  225. return S_OK;
  226. }
  227. //+----------------------------------------------------------------------------
  228. //
  229. // Method: CDsctlObject::DSIsContainer
  230. //
  231. // Synopsis: Checks if the object is a container.
  232. //
  233. //-----------------------------------------------------------------------------
  234. STDMETHODIMP
  235. CDsctlObject::DSIsContainer(VARIANT ObjectPtr, VARIANT* retval)
  236. {
  237. VARIANT vaResult;
  238. #ifdef DBG
  239. OutputDebugString(TEXT("Entering CDsctlObject::DSIsContainer.\n"));
  240. #endif
  241. VariantInit(&vaResult);
  242. vaResult.vt = VT_BOOL;
  243. vaResult.boolVal = VARIANT_FALSE;
  244. IUnknown * pDisp;
  245. //
  246. // Get the DS object pointer.
  247. //
  248. if (ObjectPtr.vt == VT_DISPATCH || ObjectPtr.vt == VT_UNKNOWN)
  249. {
  250. pDisp = ObjectPtr.pdispVal;
  251. }
  252. else
  253. {
  254. if (ObjectPtr.vt == (VT_BYREF | VT_VARIANT))
  255. {
  256. if ((ObjectPtr.pvarVal)->vt == VT_DISPATCH ||
  257. (ObjectPtr.pvarVal)->vt == VT_UNKNOWN)
  258. {
  259. pDisp = (ObjectPtr.pvarVal)->pdispVal;
  260. }
  261. else
  262. {
  263. //
  264. // If we don't know what sort of argument we received, then
  265. // just return FALSE.
  266. //
  267. #ifdef DBG
  268. OutputDebugString(TEXT("DSIsContainer - can't make sense of argument!\n"));
  269. #endif
  270. *retval = vaResult;
  271. return S_OK;
  272. }
  273. }
  274. }
  275. IADs * pDsObject;
  276. HRESULT hr = pDisp->QueryInterface(IID_IADs, (void **)&pDsObject);
  277. if (SUCCEEDED(hr))
  278. {
  279. //pDisp->Release();
  280. }
  281. else
  282. {
  283. #ifdef DBG
  284. OutputDebugString(TEXT("DSIsContainer - QI for IID_IADs failed!\n"));
  285. #endif
  286. *retval = vaResult;
  287. return S_OK;
  288. }
  289. BSTR bstrSchema;
  290. IADsClass * pDsClass;
  291. VARIANT_BOOL bIsContainer;
  292. //
  293. // Objects are containers if their schema says they are containers...
  294. //
  295. if (SUCCEEDED(pDsObject->get_Schema( &bstrSchema )))
  296. {
  297. if (SUCCEEDED(ADsGetObject(bstrSchema, IID_IADsClass, (LPVOID *)&pDsClass)))
  298. {
  299. if (SUCCEEDED(pDsClass->get_Container(&bIsContainer)))
  300. {
  301. vaResult.boolVal = bIsContainer;
  302. #ifdef DBG
  303. wsprintf(DebugOut, TEXT("DSIsContainer returned: %lx\n"),
  304. bIsContainer);
  305. OutputDebugString(DebugOut);
  306. #endif
  307. }
  308. pDsClass->Release();
  309. }
  310. SysFreeString(bstrSchema);
  311. }
  312. else
  313. {
  314. // If the get_Schema fails, we can assume it's a container (says yihsins)
  315. vaResult.boolVal = VARIANT_TRUE;
  316. #ifdef DBG
  317. OutputDebugString(TEXT("DSIsContainer returning TRUE because get_Schema failed.\n"));
  318. #endif
  319. }
  320. pDsObject->Release();
  321. *retval = vaResult;
  322. #ifdef DBG
  323. OutputDebugString(TEXT("Exiting CDsctlObject::DSIsContainer\n"));
  324. #endif
  325. return S_OK;
  326. }
  327. //+----------------------------------------------------------------------------
  328. //
  329. // Method: CDsctlObject::DSGetLastError
  330. //
  331. // Synopsis: Checks ADs extended error.
  332. //
  333. //-----------------------------------------------------------------------------
  334. STDMETHODIMP
  335. CDsctlObject::DSGetLastError(VARIANT* retval)
  336. {
  337. VARIANT vaResult;
  338. #ifdef DBG
  339. OutputDebugString(TEXT("Entering CDsctlObject::DSGetLastError.\n"));
  340. #endif
  341. VariantInit(&vaResult);
  342. vaResult.vt = VT_EMPTY;
  343. vaResult.vt = VT_BSTR;
  344. *retval = vaResult;
  345. //
  346. // There doesn't seem to be a way to detect if the returned string is
  347. // truncated. Hopefully, this size will be large enough (the function
  348. // header, in oleds\router\oledserr.cxx, says that 256 bytes is the
  349. // recommended minimum for the error buffer and that the returned string
  350. // will always be null terminated).
  351. //
  352. # define ERRBUFSIZE 512
  353. DWORD dwErr;
  354. WCHAR wszErrBuf[ERRBUFSIZE];
  355. HRESULT hr = ADsGetLastError(&dwErr,
  356. wszErrBuf,
  357. ERRBUFSIZE,
  358. NULL,
  359. 0);
  360. if (FAILED(hr))
  361. {
  362. #ifdef DBG
  363. wsprintf(DebugOut, TEXT("DSctl: ADsGetLastError returned: %lx\n"), hr);
  364. OutputDebugString(DebugOut);
  365. #endif
  366. return hr;
  367. }
  368. wsprintf(DebugOut, TEXT("DSctl::ADsGetLastError: error = 0x%lx, errstr = %S\n"),
  369. dwErr, wszErrBuf);
  370. OutputDebugString(DebugOut);
  371. BSTR bstr = SysAllocString(wszErrBuf);
  372. if (bstr == NULL)
  373. {
  374. return E_OUTOFMEMORY;
  375. }
  376. vaResult.vt = VT_BSTR;
  377. vaResult.bstrVal = bstr;
  378. *retval = vaResult;
  379. return S_OK;
  380. }
  381. //+----------------------------------------------------------------------------
  382. //
  383. // Method: CDsctlObject::DecodeURL
  384. //
  385. // Synopsis: Returns the decoded URL.
  386. //
  387. //-----------------------------------------------------------------------------
  388. STDMETHODIMP
  389. CDsctlObject::DecodeURL(VARIANT EncodedURL, VARIANT * pRetVar)
  390. {
  391. #ifdef DBG
  392. wsprintf(DebugOut, TEXT("\nDSctl::DecodeURL: in param address: %x\n"),
  393. &EncodedURL);
  394. OutputDebugString(DebugOut);
  395. #endif
  396. //DebugBreak();
  397. VariantInit(pRetVar);
  398. if (EncodedURL.vt != VT_BSTR)
  399. {
  400. #ifdef DBG
  401. OutputDebugString(TEXT("DSctl::DecodeURL not passed a string\n"));
  402. #endif
  403. pRetVar->vt = VT_ERROR;
  404. pRetVar->scode = E_INVALIDARG;
  405. return E_INVALIDARG;
  406. }
  407. #ifdef DBG
  408. wsprintf(DebugOut, TEXT("DSctl::DecodeURL: input is %ws\n"),
  409. EncodedURL.bstrVal);
  410. OutputDebugString(DebugOut);
  411. #endif
  412. //
  413. // DeURLize path
  414. //
  415. TCHAR szDecodedURL[INTERNET_MAX_URL_LENGTH];
  416. DWORD dwLen = INTERNET_MAX_URL_LENGTH;
  417. if (!InternetCanonicalizeUrl(EncodedURL.bstrVal, szDecodedURL, &dwLen,
  418. ICU_DECODE | ICU_NO_ENCODE))
  419. {
  420. pRetVar->vt = VT_ERROR;
  421. pRetVar->scode = E_FAIL;
  422. #ifdef DBG
  423. wsprintf(DebugOut,
  424. TEXT("DSctl: InternetCanonicalizeUrl returned: %lx!\n"),
  425. GetLastError());
  426. OutputDebugString(DebugOut);
  427. #endif
  428. return E_FAIL;
  429. }
  430. if (_tcsstr(szDecodedURL, TEXT("ldap")) != NULL)
  431. {
  432. //
  433. // Convert the protocol sequence to upper case.
  434. //
  435. _tcsncpy(szDecodedURL, TEXT("LDAP"), 4);
  436. }
  437. pRetVar->vt = VT_BSTR;
  438. pRetVar->bstrVal = SysAllocString(szDecodedURL);
  439. if (pRetVar->bstrVal == NULL)
  440. {
  441. #ifdef DBG
  442. OutputDebugString(TEXT("DSctl::DecodeURL: allocation failed!\n"));
  443. #endif
  444. pRetVar->vt = VT_ERROR;
  445. pRetVar->scode = E_OUTOFMEMORY;
  446. return E_OUTOFMEMORY;
  447. }
  448. #ifdef DBG
  449. wsprintf(DebugOut, TEXT("DSctl::DecodeURL: decoded URL is: %ws\n\n"),
  450. pRetVar->bstrVal);
  451. OutputDebugString(DebugOut);
  452. #endif
  453. return S_OK;
  454. }