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.

512 lines
15 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000.
  5. //
  6. // File: umi.cxx
  7. //
  8. // Contents: Contains miscellaneous UMI routines.
  9. //
  10. // History: 02-28-00 SivaramR Created.
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "winnt.hxx"
  14. //----------------------------------------------------------------------------
  15. // Function: IsPreDefinedErrorCode
  16. //
  17. // Synopsis: Returns TRUE if the error code passed in is a valid UMI error
  18. // code i.e one that can be returned by a UMI method. Returns
  19. // FALSE otherwise.
  20. //
  21. // Arguments: Self explanatory
  22. //
  23. // Returns: TRUE/FALSE as mentioned above
  24. //
  25. // Modifies: Nothing
  26. //
  27. //----------------------------------------------------------------------------
  28. BOOL IsPreDefinedErrorCode(HRESULT hr)
  29. {
  30. switch(hr) {
  31. case E_UNEXPECTED:
  32. case E_NOTIMPL:
  33. case E_OUTOFMEMORY:
  34. case E_INVALIDARG:
  35. case E_NOINTERFACE:
  36. case E_POINTER:
  37. case E_HANDLE:
  38. case E_ABORT:
  39. case E_FAIL:
  40. case E_ACCESSDENIED:
  41. case E_PENDING:
  42. case UMI_E_TYPE_MISMATCH:
  43. case UMI_E_NOT_FOUND:
  44. case UMI_E_INVALID_FLAGS:
  45. case UMI_E_UNSUPPORTED_OPERATION:
  46. case UMI_E_UNSUPPORTED_FLAGS:
  47. case UMI_E_SYNCHRONIZATION_REQUIRED:
  48. case UMI_E_UNBOUND_OBJECT:
  49. RRETURN(TRUE);
  50. default:
  51. RRETURN(FALSE);
  52. }
  53. }
  54. //----------------------------------------------------------------------------
  55. // Function: MapHrToUmiError
  56. //
  57. // Synopsis: This function returns the UMI error corresponding to a HRESULT
  58. // returned by the WinNT provider. The HRESULT can be retrieved
  59. // using GetLastStatus(), if required.
  60. //
  61. // Arguments: Self explanatory
  62. //
  63. // Returns: UMI error corresponding to the HRESULT
  64. //
  65. // Modifies: Nothing
  66. //
  67. //----------------------------------------------------------------------------
  68. HRESULT MapHrToUmiError(HRESULT hr)
  69. {
  70. if(SUCCEEDED(hr)) {
  71. if(S_FALSE == hr) // may be returned by end of cursor enumeration
  72. RRETURN(UMI_S_FALSE);
  73. else
  74. RRETURN(UMI_S_NO_ERROR);
  75. }
  76. // we had a failure
  77. if(TRUE == IsPreDefinedErrorCode(hr))
  78. RRETURN(hr); // OK to return this as a UMI error
  79. // Try to map ADSI errors to appropriate UMI errors. Default is to
  80. // map to E_FAIL.
  81. switch(hr) {
  82. case E_ADS_INVALID_DOMAIN_OBJECT:
  83. case E_ADS_INVALID_USER_OBJECT:
  84. case E_ADS_INVALID_COMPUTER_OBJECT:
  85. case E_ADS_UNKNOWN_OBJECT:
  86. RRETURN(UMI_E_OBJECT_NOT_FOUND);
  87. case E_ADS_PROPERTY_NOT_FOUND:
  88. RRETURN(UMI_E_PROPERTY_NOT_FOUND);
  89. case E_ADS_BAD_PARAMETER:
  90. RRETURN(UMI_E_INVALIDARG);
  91. case E_ADS_CANT_CONVERT_DATATYPE:
  92. RRETURN(UMI_E_TYPE_MISMATCH);
  93. case E_ADS_BAD_PATHNAME:
  94. RRETURN(UMI_E_INVALIDARG);
  95. case E_ADS_OBJECT_UNBOUND:
  96. RRETURN(UMI_E_UNBOUND_OBJECT);
  97. case HRESULT_FROM_WIN32(NERR_UserNotFound):
  98. case HRESULT_FROM_WIN32(NERR_GroupNotFound):
  99. case HRESULT_FROM_WIN32(ERROR_NO_SUCH_DOMAIN):
  100. case HRESULT_FROM_WIN32(ERROR_BAD_NETPATH):
  101. RRETURN(UMI_E_OBJECT_NOT_FOUND);
  102. default:
  103. RRETURN(UMI_E_FAIL);
  104. }
  105. }
  106. //----------------------------------------------------------------------------
  107. // Function: ValidateUrl
  108. //
  109. // Synopsis: This function checks to see if a UMI path has the correct
  110. // namespace and server.
  111. //
  112. // Arguments:
  113. //
  114. // pURL Pointer to URL interface containing the UMI path
  115. //
  116. // Returns: S_OK on success. Error code otherwise.
  117. //
  118. // Modifies: Nothing
  119. //
  120. //----------------------------------------------------------------------------
  121. static HRESULT ValidateUrl(
  122. IUmiURL *pURL
  123. )
  124. {
  125. HRESULT hr = S_OK;
  126. WCHAR pszTmpArray[MAX_URL+1];
  127. ULONG ulTmpArraySize = 0;
  128. ULONGLONG PathType = 0;
  129. hr = pURL->GetPathInfo(0, &PathType);
  130. BAIL_ON_FAILURE(hr);
  131. if(PathType & UMIPATH_INFO_RELATIVE_PATH)
  132. // relative paths cannot be converted to a WinNT path
  133. BAIL_ON_FAILURE(hr = UMI_E_INVALID_PATH);
  134. // Make sure server name is empty. WinNT does not support servername
  135. // in UMI path.
  136. ulTmpArraySize = MAX_URL;
  137. hr = pURL->GetLocator(
  138. &ulTmpArraySize,
  139. pszTmpArray
  140. );
  141. if(WBEM_E_BUFFER_TOO_SMALL == hr)
  142. // Locator is not an empty string
  143. hr = UMI_E_INVALID_PATH;
  144. BAIL_ON_FAILURE(hr);
  145. if(wcscmp(pszTmpArray, L""))
  146. BAIL_ON_FAILURE(hr = UMI_E_INVALID_PATH);
  147. // Make sure namespace is WinNT
  148. ulTmpArraySize = MAX_URL;
  149. hr = pURL->GetRootNamespace(
  150. &ulTmpArraySize,
  151. pszTmpArray
  152. );
  153. if(WBEM_E_BUFFER_TOO_SMALL == hr)
  154. // Namespace is not WinNT
  155. hr = UMI_E_INVALID_PATH;
  156. BAIL_ON_FAILURE(hr);
  157. if(_wcsicmp(pszTmpArray, L"WinNT"))
  158. BAIL_ON_FAILURE(hr = UMI_E_INVALID_PATH);
  159. error:
  160. RRETURN(hr);
  161. }
  162. //----------------------------------------------------------------------------
  163. // Function: UmiToWinNTPath
  164. //
  165. // Synopsis: This function converts a UMI path into a native path.
  166. //
  167. // Arguments:
  168. //
  169. // pURL Pointer to URL interface containing the UMI path
  170. // ppszWinNTPath Returns the WinNT path
  171. // pdwNumComps Returns the number of components in the UMI path
  172. // pppszClasses Returns the class of each component in the UMI path
  173. //
  174. // Returns: S_OK on success. Error code otherwise.
  175. //
  176. // Modifies: *ppszWinNTPath to return the WinNT path
  177. // *pdwNumComps to return the number of components
  178. // *pppszClasses to return the class of each component
  179. //
  180. //----------------------------------------------------------------------------
  181. HRESULT UmiToWinNTPath(
  182. IUmiURL *pURL,
  183. WCHAR **ppszWinNTPath,
  184. DWORD *pdwNumComps,
  185. LPWSTR **pppszClasses
  186. )
  187. {
  188. HRESULT hr = S_OK;
  189. WCHAR *pszWinNTPath = NULL;
  190. WCHAR pszTmpArray[MAX_URL+1], pszValueArray[MAX_URL+1];
  191. WCHAR *pszValuePtr = NULL, pszClassArray[MAX_URL+1];
  192. ULONG ulTmpArraySize = 0, ulNumComponents = 0, ulIndex = 0;
  193. ULONG ulKeyCount = 0, ulValueArraySize = 0, ulClassArraySize = 0;
  194. IUmiURLKeyList *pKeyList = NULL;
  195. LPWSTR *ppszClasses = NULL;
  196. ADsAssert( (pURL != NULL) && (ppszWinNTPath != NULL) &&
  197. (pdwNumComps != NULL) && (pppszClasses != NULL) );
  198. *ppszWinNTPath = NULL;
  199. *pdwNumComps = 0;
  200. *pppszClasses = NULL;
  201. hr = ValidateUrl(pURL);
  202. BAIL_ON_FAILURE(hr);
  203. // Get the total length needed for the WinNT path
  204. ulTmpArraySize = MAX_URL;
  205. hr = pURL->Get(0, &ulTmpArraySize, pszTmpArray);
  206. if(hr != WBEM_E_BUFFER_TOO_SMALL)
  207. BAIL_ON_FAILURE(hr);
  208. pszWinNTPath = (WCHAR *) AllocADsMem(ulTmpArraySize * sizeof(WCHAR));
  209. if(NULL == pszWinNTPath)
  210. BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
  211. wsprintf(pszWinNTPath, L"%s", L"WinNT:");
  212. hr = pURL->GetComponentCount(&ulNumComponents);
  213. BAIL_ON_FAILURE(hr);
  214. if(0 == ulNumComponents) {
  215. // umi:///winnt translates to WinNT: . Nothing more to do
  216. *ppszWinNTPath = pszWinNTPath;
  217. RRETURN(S_OK);
  218. }
  219. ppszClasses = (LPWSTR *) AllocADsMem(ulNumComponents * sizeof(LPWSTR *));
  220. if(NULL == ppszClasses) {
  221. BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
  222. }
  223. memset(ppszClasses, 0, ulNumComponents * sizeof(LPWSTR *));
  224. // we have at least one component in the path
  225. wcscat(pszWinNTPath, L"/");
  226. for(ulIndex = 0; ulIndex < ulNumComponents; ulIndex++) {
  227. ulClassArraySize = MAX_URL;
  228. pKeyList = NULL;
  229. hr = pURL->GetComponent(
  230. ulIndex,
  231. &ulClassArraySize,
  232. pszClassArray,
  233. &pKeyList
  234. );
  235. if(WBEM_E_BUFFER_TOO_SMALL == hr)
  236. // none of the WinNT classes is so long, so this has to be a bad path.
  237. hr = UMI_E_INVALID_PATH;
  238. BAIL_ON_FAILURE(hr);
  239. // WinNT does not supports components with an empty class name
  240. if(!wcscmp(pszClassArray, L""))
  241. BAIL_ON_FAILURE(hr = UMI_E_INVALID_PATH);
  242. ppszClasses[ulIndex] = AllocADsStr(pszClassArray);
  243. if(NULL == ppszClasses[ulIndex]) {
  244. BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
  245. }
  246. ADsAssert(pKeyList != NULL);
  247. // make sure there is only one key
  248. hr = pKeyList->GetCount(&ulKeyCount);
  249. BAIL_ON_FAILURE(hr);
  250. if(ulKeyCount != 1)
  251. BAIL_ON_FAILURE(hr = UMI_E_INVALID_PATH);
  252. ulValueArraySize = MAX_URL;
  253. ulTmpArraySize = MAX_URL;
  254. pszValuePtr = pszValueArray;
  255. hr = pKeyList->GetKey(
  256. 0,
  257. 0,
  258. &ulTmpArraySize,
  259. pszTmpArray,
  260. &ulValueArraySize,
  261. pszValueArray
  262. );
  263. if( (WBEM_E_BUFFER_TOO_SMALL == hr) && (ulValueArraySize > MAX_URL) ) {
  264. pszValuePtr = (WCHAR *) AllocADsMem(ulValueArraySize);
  265. if(NULL == pszValuePtr)
  266. BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
  267. hr = pKeyList->GetKey(
  268. 0,
  269. 0,
  270. &ulTmpArraySize,
  271. pszTmpArray,
  272. &ulValueArraySize,
  273. pszValuePtr
  274. );
  275. }
  276. if(WBEM_E_BUFFER_TOO_SMALL == hr)
  277. // Key is always "Name" in WinNT. So, if the size required if so
  278. // high, it indicates a bad path
  279. hr = UMI_E_INVALID_PATH;
  280. BAIL_ON_FAILURE(hr);
  281. // Key has to be "Name" or empty in WinNT
  282. if( _wcsicmp(pszTmpArray, WINNT_KEY_NAME) && wcscmp(pszTmpArray, L"") )
  283. BAIL_ON_FAILURE(hr = UMI_E_INVALID_PATH);
  284. // append the value to the WinNT path
  285. wcscat(pszWinNTPath, L"/");
  286. wcscat(pszWinNTPath, pszValuePtr);
  287. if(pszValuePtr != pszValueArray)
  288. FreeADsMem(pszValuePtr);
  289. pKeyList->Release();
  290. } // for
  291. // append the class to the WInNT path
  292. wcscat(pszWinNTPath, L",");
  293. wcscat(pszWinNTPath, pszClassArray);
  294. *ppszWinNTPath = pszWinNTPath;
  295. *pdwNumComps = ulNumComponents;
  296. *pppszClasses = ppszClasses;
  297. RRETURN(S_OK);
  298. error:
  299. if(pszWinNTPath != NULL)
  300. FreeADsMem(pszWinNTPath);
  301. if( (pszValuePtr != NULL) && (pszValuePtr != pszValueArray) )
  302. FreeADsMem(pszValuePtr);
  303. if(ppszClasses != NULL) {
  304. for(ulIndex = 0; ulIndex < ulNumComponents; ulIndex++) {
  305. if(ppszClasses[ulIndex] != NULL)
  306. FreeADsStr(ppszClasses[ulIndex]);
  307. }
  308. FreeADsMem(ppszClasses);
  309. }
  310. if(pKeyList != NULL)
  311. pKeyList->Release();
  312. RRETURN(hr);
  313. }
  314. //----------------------------------------------------------------------------
  315. // Function: ADsToUmiPath
  316. //
  317. // Synopsis: This function converts an ADsPath to a UMI path (full, short or
  318. // relative depending on a flag).
  319. //
  320. // Arguments:
  321. //
  322. // bstrADsPath ADsPath to be converted
  323. // pObjectInfo Contains the values of each component in the ADsPath
  324. // CompClasses Array containing the classes of each component of the ADsPath
  325. // dwNumComponents Number of classes(components) in the ADsPath
  326. // dwUmiPathType Specifies the format of the UMI path to be returned
  327. // ppszUmiPath Returns UMI path in the requested format
  328. //
  329. // Returns: S_OK on success. Error code otherwise.
  330. //
  331. // Modifies: *ppszUmiPath to return the UMI path
  332. //
  333. //----------------------------------------------------------------------------
  334. HRESULT ADsToUmiPath(
  335. BSTR bstrADsPath,
  336. OBJECTINFO *pObjectInfo,
  337. LPWSTR CompClasses[],
  338. DWORD dwNumComponents,
  339. DWORD dwUmiPathType,
  340. LPWSTR *ppszUmiPath
  341. )
  342. {
  343. HRESULT hr = S_OK;
  344. DWORD dwBufferLen = 0, dwIndex = 0;
  345. LPWSTR pszUmiPath = NULL, *pszComponents = NULL;
  346. ADsAssert( (bstrADsPath != NULL) && (CompClasses != NULL) &&
  347. (pObjectInfo != NULL) && (ppszUmiPath != NULL) );
  348. *ppszUmiPath = NULL;
  349. // calculate approximate length of buffer required to return the UMI path
  350. // Each component is of the form "class.name=value". "value" is already
  351. // part of the ADSI path. Include the size of each class and add 6 to
  352. // account for "Name" and '.' and '='.
  353. dwBufferLen = wcslen(L"umi:///winnt/") + wcslen(bstrADsPath) +
  354. dwNumComponents * (MAX_CLASS + 6) + 1;
  355. pszUmiPath = (LPWSTR) AllocADsMem(dwBufferLen * sizeof(WCHAR));
  356. if(NULL == pszUmiPath)
  357. BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
  358. // if ADsPath is empty and it is not a namespace object, then this must be
  359. // a session, resource or printjob object. Return an empty path for these.
  360. // Namespace objects have no components in the ADsPath, but they have a
  361. // non-empty ADsPath ("WinNT:")
  362. if( (0 == dwNumComponents) && _wcsicmp(CompClasses[0], L"Namespace") ) {
  363. wcscpy(pszUmiPath, L"");
  364. *ppszUmiPath = pszUmiPath;
  365. RRETURN(S_OK);
  366. }
  367. if( (RELATIVE_UMI_PATH == dwUmiPathType) ||
  368. (FULL_RELATIVE_UMI_PATH == dwUmiPathType) ) {
  369. // return the last component, if any
  370. if(0 == dwNumComponents) {
  371. *pszUmiPath = '\0';
  372. }
  373. else {
  374. wcscpy(pszUmiPath,
  375. CompClasses[dwNumComponents - 1]
  376. );
  377. if(FULL_RELATIVE_UMI_PATH == dwUmiPathType)
  378. wcscat(pszUmiPath, L".Name=");
  379. else
  380. wcscat(pszUmiPath, L"=");
  381. pszComponents = pObjectInfo->DisplayComponentArray;
  382. wcscat(pszUmiPath, pszComponents[dwNumComponents - 1]);
  383. }
  384. *ppszUmiPath = pszUmiPath;
  385. RRETURN(S_OK);
  386. }
  387. wcscpy(pszUmiPath, L"umi:///winnt");
  388. // for namespace objects, there are no components and hence the umi path
  389. // is completely constructed at this point.
  390. if(0 == dwNumComponents) {
  391. *ppszUmiPath = pszUmiPath;
  392. RRETURN(S_OK);
  393. }
  394. wcscat(pszUmiPath, L"/");
  395. pszComponents = pObjectInfo->DisplayComponentArray;
  396. for(dwIndex = 0; dwIndex < dwNumComponents; dwIndex++) {
  397. wcscat(pszUmiPath, CompClasses[dwIndex]);
  398. if(FULL_UMI_PATH == dwUmiPathType)
  399. wcscat(pszUmiPath, L".Name=");
  400. else if(SHORT_UMI_PATH == dwUmiPathType)
  401. wcscat(pszUmiPath, L"=");
  402. wcscat(pszUmiPath, pszComponents[dwIndex]);
  403. if(dwIndex != (dwNumComponents - 1))
  404. wcscat(pszUmiPath, L"/");
  405. }
  406. *ppszUmiPath = pszUmiPath;
  407. RRETURN(S_OK);
  408. error:
  409. if(pszUmiPath != NULL)
  410. FreeADsMem(pszUmiPath);
  411. RRETURN(hr);
  412. }