//---------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 2000. // // File: umi.cxx // // Contents: Contains miscellaneous UMI routines. // // History: 02-28-00 SivaramR Created. // //---------------------------------------------------------------------------- #include "winnt.hxx" //---------------------------------------------------------------------------- // Function: IsPreDefinedErrorCode // // Synopsis: Returns TRUE if the error code passed in is a valid UMI error // code i.e one that can be returned by a UMI method. Returns // FALSE otherwise. // // Arguments: Self explanatory // // Returns: TRUE/FALSE as mentioned above // // Modifies: Nothing // //---------------------------------------------------------------------------- BOOL IsPreDefinedErrorCode(HRESULT hr) { switch(hr) { case E_UNEXPECTED: case E_NOTIMPL: case E_OUTOFMEMORY: case E_INVALIDARG: case E_NOINTERFACE: case E_POINTER: case E_HANDLE: case E_ABORT: case E_FAIL: case E_ACCESSDENIED: case E_PENDING: case UMI_E_TYPE_MISMATCH: case UMI_E_NOT_FOUND: case UMI_E_INVALID_FLAGS: case UMI_E_UNSUPPORTED_OPERATION: case UMI_E_UNSUPPORTED_FLAGS: case UMI_E_SYNCHRONIZATION_REQUIRED: case UMI_E_UNBOUND_OBJECT: RRETURN(TRUE); default: RRETURN(FALSE); } } //---------------------------------------------------------------------------- // Function: MapHrToUmiError // // Synopsis: This function returns the UMI error corresponding to a HRESULT // returned by the WinNT provider. The HRESULT can be retrieved // using GetLastStatus(), if required. // // Arguments: Self explanatory // // Returns: UMI error corresponding to the HRESULT // // Modifies: Nothing // //---------------------------------------------------------------------------- HRESULT MapHrToUmiError(HRESULT hr) { if(SUCCEEDED(hr)) { if(S_FALSE == hr) // may be returned by end of cursor enumeration RRETURN(UMI_S_FALSE); else RRETURN(UMI_S_NO_ERROR); } // we had a failure if(TRUE == IsPreDefinedErrorCode(hr)) RRETURN(hr); // OK to return this as a UMI error // Try to map ADSI errors to appropriate UMI errors. Default is to // map to E_FAIL. switch(hr) { case E_ADS_INVALID_DOMAIN_OBJECT: case E_ADS_INVALID_USER_OBJECT: case E_ADS_INVALID_COMPUTER_OBJECT: case E_ADS_UNKNOWN_OBJECT: RRETURN(UMI_E_OBJECT_NOT_FOUND); case E_ADS_PROPERTY_NOT_FOUND: RRETURN(UMI_E_PROPERTY_NOT_FOUND); case E_ADS_BAD_PARAMETER: RRETURN(UMI_E_INVALIDARG); case E_ADS_CANT_CONVERT_DATATYPE: RRETURN(UMI_E_TYPE_MISMATCH); case E_ADS_BAD_PATHNAME: RRETURN(UMI_E_INVALIDARG); case E_ADS_OBJECT_UNBOUND: RRETURN(UMI_E_UNBOUND_OBJECT); case HRESULT_FROM_WIN32(NERR_UserNotFound): case HRESULT_FROM_WIN32(NERR_GroupNotFound): case HRESULT_FROM_WIN32(ERROR_NO_SUCH_DOMAIN): case HRESULT_FROM_WIN32(ERROR_BAD_NETPATH): RRETURN(UMI_E_OBJECT_NOT_FOUND); default: RRETURN(UMI_E_FAIL); } } //---------------------------------------------------------------------------- // Function: ValidateUrl // // Synopsis: This function checks to see if a UMI path has the correct // namespace and server. // // Arguments: // // pURL Pointer to URL interface containing the UMI path // // Returns: S_OK on success. Error code otherwise. // // Modifies: Nothing // //---------------------------------------------------------------------------- static HRESULT ValidateUrl( IUmiURL *pURL ) { HRESULT hr = S_OK; WCHAR pszTmpArray[MAX_URL+1]; ULONG ulTmpArraySize = 0; ULONGLONG PathType = 0; hr = pURL->GetPathInfo(0, &PathType); BAIL_ON_FAILURE(hr); if(PathType & UMIPATH_INFO_RELATIVE_PATH) // relative paths cannot be converted to a WinNT path BAIL_ON_FAILURE(hr = UMI_E_INVALID_PATH); // Make sure server name is empty. WinNT does not support servername // in UMI path. ulTmpArraySize = MAX_URL; hr = pURL->GetLocator( &ulTmpArraySize, pszTmpArray ); if(WBEM_E_BUFFER_TOO_SMALL == hr) // Locator is not an empty string hr = UMI_E_INVALID_PATH; BAIL_ON_FAILURE(hr); if(wcscmp(pszTmpArray, L"")) BAIL_ON_FAILURE(hr = UMI_E_INVALID_PATH); // Make sure namespace is WinNT ulTmpArraySize = MAX_URL; hr = pURL->GetRootNamespace( &ulTmpArraySize, pszTmpArray ); if(WBEM_E_BUFFER_TOO_SMALL == hr) // Namespace is not WinNT hr = UMI_E_INVALID_PATH; BAIL_ON_FAILURE(hr); if(_wcsicmp(pszTmpArray, L"WinNT")) BAIL_ON_FAILURE(hr = UMI_E_INVALID_PATH); error: RRETURN(hr); } //---------------------------------------------------------------------------- // Function: UmiToWinNTPath // // Synopsis: This function converts a UMI path into a native path. // // Arguments: // // pURL Pointer to URL interface containing the UMI path // ppszWinNTPath Returns the WinNT path // pdwNumComps Returns the number of components in the UMI path // pppszClasses Returns the class of each component in the UMI path // // Returns: S_OK on success. Error code otherwise. // // Modifies: *ppszWinNTPath to return the WinNT path // *pdwNumComps to return the number of components // *pppszClasses to return the class of each component // //---------------------------------------------------------------------------- HRESULT UmiToWinNTPath( IUmiURL *pURL, WCHAR **ppszWinNTPath, DWORD *pdwNumComps, LPWSTR **pppszClasses ) { HRESULT hr = S_OK; WCHAR *pszWinNTPath = NULL; WCHAR pszTmpArray[MAX_URL+1], pszValueArray[MAX_URL+1]; WCHAR *pszValuePtr = NULL, pszClassArray[MAX_URL+1]; ULONG ulTmpArraySize = 0, ulNumComponents = 0, ulIndex = 0; ULONG ulKeyCount = 0, ulValueArraySize = 0, ulClassArraySize = 0; IUmiURLKeyList *pKeyList = NULL; LPWSTR *ppszClasses = NULL; ADsAssert( (pURL != NULL) && (ppszWinNTPath != NULL) && (pdwNumComps != NULL) && (pppszClasses != NULL) ); *ppszWinNTPath = NULL; *pdwNumComps = 0; *pppszClasses = NULL; hr = ValidateUrl(pURL); BAIL_ON_FAILURE(hr); // Get the total length needed for the WinNT path ulTmpArraySize = MAX_URL; hr = pURL->Get(0, &ulTmpArraySize, pszTmpArray); if(hr != WBEM_E_BUFFER_TOO_SMALL) BAIL_ON_FAILURE(hr); pszWinNTPath = (WCHAR *) AllocADsMem(ulTmpArraySize * sizeof(WCHAR)); if(NULL == pszWinNTPath) BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY); wsprintf(pszWinNTPath, L"%s", L"WinNT:"); hr = pURL->GetComponentCount(&ulNumComponents); BAIL_ON_FAILURE(hr); if(0 == ulNumComponents) { // umi:///winnt translates to WinNT: . Nothing more to do *ppszWinNTPath = pszWinNTPath; RRETURN(S_OK); } ppszClasses = (LPWSTR *) AllocADsMem(ulNumComponents * sizeof(LPWSTR *)); if(NULL == ppszClasses) { BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY); } memset(ppszClasses, 0, ulNumComponents * sizeof(LPWSTR *)); // we have at least one component in the path wcscat(pszWinNTPath, L"/"); for(ulIndex = 0; ulIndex < ulNumComponents; ulIndex++) { ulClassArraySize = MAX_URL; pKeyList = NULL; hr = pURL->GetComponent( ulIndex, &ulClassArraySize, pszClassArray, &pKeyList ); if(WBEM_E_BUFFER_TOO_SMALL == hr) // none of the WinNT classes is so long, so this has to be a bad path. hr = UMI_E_INVALID_PATH; BAIL_ON_FAILURE(hr); // WinNT does not supports components with an empty class name if(!wcscmp(pszClassArray, L"")) BAIL_ON_FAILURE(hr = UMI_E_INVALID_PATH); ppszClasses[ulIndex] = AllocADsStr(pszClassArray); if(NULL == ppszClasses[ulIndex]) { BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY); } ADsAssert(pKeyList != NULL); // make sure there is only one key hr = pKeyList->GetCount(&ulKeyCount); BAIL_ON_FAILURE(hr); if(ulKeyCount != 1) BAIL_ON_FAILURE(hr = UMI_E_INVALID_PATH); ulValueArraySize = MAX_URL; ulTmpArraySize = MAX_URL; pszValuePtr = pszValueArray; hr = pKeyList->GetKey( 0, 0, &ulTmpArraySize, pszTmpArray, &ulValueArraySize, pszValueArray ); if( (WBEM_E_BUFFER_TOO_SMALL == hr) && (ulValueArraySize > MAX_URL) ) { pszValuePtr = (WCHAR *) AllocADsMem(ulValueArraySize); if(NULL == pszValuePtr) BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY); hr = pKeyList->GetKey( 0, 0, &ulTmpArraySize, pszTmpArray, &ulValueArraySize, pszValuePtr ); } if(WBEM_E_BUFFER_TOO_SMALL == hr) // Key is always "Name" in WinNT. So, if the size required if so // high, it indicates a bad path hr = UMI_E_INVALID_PATH; BAIL_ON_FAILURE(hr); // Key has to be "Name" or empty in WinNT if( _wcsicmp(pszTmpArray, WINNT_KEY_NAME) && wcscmp(pszTmpArray, L"") ) BAIL_ON_FAILURE(hr = UMI_E_INVALID_PATH); // append the value to the WinNT path wcscat(pszWinNTPath, L"/"); wcscat(pszWinNTPath, pszValuePtr); if(pszValuePtr != pszValueArray) FreeADsMem(pszValuePtr); pKeyList->Release(); } // for // append the class to the WInNT path wcscat(pszWinNTPath, L","); wcscat(pszWinNTPath, pszClassArray); *ppszWinNTPath = pszWinNTPath; *pdwNumComps = ulNumComponents; *pppszClasses = ppszClasses; RRETURN(S_OK); error: if(pszWinNTPath != NULL) FreeADsMem(pszWinNTPath); if( (pszValuePtr != NULL) && (pszValuePtr != pszValueArray) ) FreeADsMem(pszValuePtr); if(ppszClasses != NULL) { for(ulIndex = 0; ulIndex < ulNumComponents; ulIndex++) { if(ppszClasses[ulIndex] != NULL) FreeADsStr(ppszClasses[ulIndex]); } FreeADsMem(ppszClasses); } if(pKeyList != NULL) pKeyList->Release(); RRETURN(hr); } //---------------------------------------------------------------------------- // Function: ADsToUmiPath // // Synopsis: This function converts an ADsPath to a UMI path (full, short or // relative depending on a flag). // // Arguments: // // bstrADsPath ADsPath to be converted // pObjectInfo Contains the values of each component in the ADsPath // CompClasses Array containing the classes of each component of the ADsPath // dwNumComponents Number of classes(components) in the ADsPath // dwUmiPathType Specifies the format of the UMI path to be returned // ppszUmiPath Returns UMI path in the requested format // // Returns: S_OK on success. Error code otherwise. // // Modifies: *ppszUmiPath to return the UMI path // //---------------------------------------------------------------------------- HRESULT ADsToUmiPath( BSTR bstrADsPath, OBJECTINFO *pObjectInfo, LPWSTR CompClasses[], DWORD dwNumComponents, DWORD dwUmiPathType, LPWSTR *ppszUmiPath ) { HRESULT hr = S_OK; DWORD dwBufferLen = 0, dwIndex = 0; LPWSTR pszUmiPath = NULL, *pszComponents = NULL; ADsAssert( (bstrADsPath != NULL) && (CompClasses != NULL) && (pObjectInfo != NULL) && (ppszUmiPath != NULL) ); *ppszUmiPath = NULL; // calculate approximate length of buffer required to return the UMI path // Each component is of the form "class.name=value". "value" is already // part of the ADSI path. Include the size of each class and add 6 to // account for "Name" and '.' and '='. dwBufferLen = wcslen(L"umi:///winnt/") + wcslen(bstrADsPath) + dwNumComponents * (MAX_CLASS + 6) + 1; pszUmiPath = (LPWSTR) AllocADsMem(dwBufferLen * sizeof(WCHAR)); if(NULL == pszUmiPath) BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY); // if ADsPath is empty and it is not a namespace object, then this must be // a session, resource or printjob object. Return an empty path for these. // Namespace objects have no components in the ADsPath, but they have a // non-empty ADsPath ("WinNT:") if( (0 == dwNumComponents) && _wcsicmp(CompClasses[0], L"Namespace") ) { wcscpy(pszUmiPath, L""); *ppszUmiPath = pszUmiPath; RRETURN(S_OK); } if( (RELATIVE_UMI_PATH == dwUmiPathType) || (FULL_RELATIVE_UMI_PATH == dwUmiPathType) ) { // return the last component, if any if(0 == dwNumComponents) { *pszUmiPath = '\0'; } else { wcscpy(pszUmiPath, CompClasses[dwNumComponents - 1] ); if(FULL_RELATIVE_UMI_PATH == dwUmiPathType) wcscat(pszUmiPath, L".Name="); else wcscat(pszUmiPath, L"="); pszComponents = pObjectInfo->DisplayComponentArray; wcscat(pszUmiPath, pszComponents[dwNumComponents - 1]); } *ppszUmiPath = pszUmiPath; RRETURN(S_OK); } wcscpy(pszUmiPath, L"umi:///winnt"); // for namespace objects, there are no components and hence the umi path // is completely constructed at this point. if(0 == dwNumComponents) { *ppszUmiPath = pszUmiPath; RRETURN(S_OK); } wcscat(pszUmiPath, L"/"); pszComponents = pObjectInfo->DisplayComponentArray; for(dwIndex = 0; dwIndex < dwNumComponents; dwIndex++) { wcscat(pszUmiPath, CompClasses[dwIndex]); if(FULL_UMI_PATH == dwUmiPathType) wcscat(pszUmiPath, L".Name="); else if(SHORT_UMI_PATH == dwUmiPathType) wcscat(pszUmiPath, L"="); wcscat(pszUmiPath, pszComponents[dwIndex]); if(dwIndex != (dwNumComponents - 1)) wcscat(pszUmiPath, L"/"); } *ppszUmiPath = pszUmiPath; RRETURN(S_OK); error: if(pszUmiPath != NULL) FreeADsMem(pszUmiPath); RRETURN(hr); }