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.

401 lines
12 KiB

  1. /********************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. util.CPP
  5. Abstract:
  6. File containing utility classes
  7. Revision History:
  8. Ghim-Sim Chua (gschua) 04/27/99
  9. - Created
  10. Jim Martin (a-jammar) 04/30/99
  11. - Changed to use global IWbemServices pointer, and added
  12. GetWbemServices, CopyProperty, and GetCIMDataFile
  13. Ghim-Sim Chua (gschua) 05/01/99
  14. - Modified GetWbemServices, GetCIMDataFile
  15. Kalyani Narlanka (kalyanin) 05/11/99
  16. - Added the function GetCompletePath
  17. ********************************************************************/
  18. #include "pchealth.h"
  19. #define TRACE_ID DCID_UTIL
  20. //-----------------------------------------------------------------------------
  21. // Returns an IWbemServices pointer. The caller is responsible for releasing
  22. // the object.
  23. //-----------------------------------------------------------------------------
  24. HRESULT GetWbemServices(IWbemServices **ppServices)
  25. {
  26. TraceFunctEnter("::GetWbemServices");
  27. HRESULT hRes = S_OK;
  28. CComPtr<IWbemLocator> pWbemLocator;
  29. // If global variable already initialized, use it
  30. if (g_pWbemServices)
  31. {
  32. *ppServices = g_pWbemServices;
  33. (*ppServices)->AddRef();
  34. goto End;
  35. }
  36. // First we have the get the IWbemLocator object with a CoCreateInstance.
  37. hRes = CoCreateInstance(CLSID_WbemAdministrativeLocator, NULL,
  38. CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
  39. IID_IUnknown, (void **)&pWbemLocator);
  40. if (FAILED(hRes))
  41. {
  42. ErrorTrace(TRACE_ID, "CoCreateInstance failed to create IWbemAdministrativeLocator.");
  43. goto End;
  44. }
  45. // Then we connect to the WMI server for the local CIMV2 namespace.
  46. hRes = pWbemLocator->ConnectServer(CComBSTR(CIM_NAMESPACE), NULL, NULL, NULL, 0, NULL, NULL, ppServices);
  47. if (FAILED(hRes))
  48. {
  49. ErrorTrace(TRACE_ID, "ConnectServer failed to connect to cimv2 namespace.");
  50. goto End;
  51. }
  52. // Store it in the global variable
  53. g_pWbemServices = *ppServices;
  54. (*ppServices)->AddRef(); // CODEWORK: check out why this stops fault on NET STOP WINMGMT
  55. End :
  56. TraceFunctLeave();
  57. return hRes;
  58. }
  59. //-----------------------------------------------------------------------------
  60. // Executes the WQL query and returns the enumerated list
  61. //-----------------------------------------------------------------------------
  62. HRESULT ExecWQLQuery(IEnumWbemClassObject **ppEnumInst, BSTR bstrQuery)
  63. {
  64. TraceFunctEnter("::ExecWQLQuery");
  65. HRESULT hRes;
  66. CComPtr<IWbemServices> pWbemServices;
  67. // Get pointer to WbemServices
  68. hRes = GetWbemServices(&pWbemServices);
  69. if (FAILED(hRes))
  70. goto End;
  71. // execute the query
  72. hRes = pWbemServices->ExecQuery(
  73. CComBSTR("WQL"),
  74. bstrQuery,
  75. WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY,
  76. NULL,
  77. ppEnumInst);
  78. if (FAILED(hRes))
  79. {
  80. ErrorTrace(TRACE_ID, "ExecQuery failed.");
  81. goto End;
  82. }
  83. End:
  84. TraceFunctLeave();
  85. return hRes;
  86. }
  87. //-----------------------------------------------------------------------------
  88. // Copies the property named szFrom from pFrom to the property named szTo in
  89. // to CInstance object pTo.
  90. //-----------------------------------------------------------------------------
  91. HRESULT CopyProperty(IWbemClassObject *pFrom, LPCWSTR szFrom, CInstance *pTo, LPCWSTR szTo)
  92. {
  93. TraceFunctEnter("::CopyProperty");
  94. _ASSERT(pFrom && szFrom && pTo && szTo);
  95. HRESULT hRes = S_OK;
  96. CComVariant varValue;
  97. CComBSTR bstrFrom(szFrom);
  98. // First, get the property (as a variant) from the source class object.
  99. hRes = pFrom->Get(bstrFrom, 0, &varValue, NULL, NULL);
  100. if (FAILED(hRes))
  101. ErrorTrace(TRACE_ID, "GetVariant on %s field failed.", szFrom);
  102. else
  103. {
  104. // Then set the variant for the target CInstance object.
  105. if (!pTo->SetVariant(szTo, varValue))
  106. {
  107. ErrorTrace(TRACE_ID, "SetVariant on %s field failed.", szTo);
  108. hRes = WBEM_E_FAILED;
  109. }
  110. }
  111. TraceFunctLeave();
  112. return hRes;
  113. }
  114. //-----------------------------------------------------------------------------
  115. // Returns an IWbemClassObject pointer for the CIM_DataFile object represented
  116. // by the bstrFile parameter. The bstrFile parameter should contain the full
  117. // path to the file. If the pServices parameter is non-null, it is used to
  118. // retrieve the file info, otherwise a new (and temporary) services pointer is
  119. // created.
  120. //-----------------------------------------------------------------------------
  121. HRESULT GetCIMDataFile(BSTR bstrFile, IWbemClassObject ** ppFileObject, BOOL fHasDoubleSlashes)
  122. {
  123. TraceFunctEnter("::GetCIMDataFile");
  124. HRESULT hRes = S_OK;
  125. CComBSTR bstrObjectPath("\\\\.\\root\\cimv2:CIM_DataFile.Name=\"");
  126. wchar_t * pwch;
  127. UINT uLen;
  128. CComPtr<IWbemServices> pWbemServices;
  129. hRes = GetWbemServices(&pWbemServices);
  130. if (FAILED(hRes))
  131. goto END;
  132. if (bstrFile == NULL || ppFileObject == NULL)
  133. {
  134. ErrorTrace(TRACE_ID, "Parameter pointer is null.");
  135. hRes = WBEM_E_INVALID_PARAMETER;
  136. goto END;
  137. }
  138. // Construct the path for the file we are trying to get. Note, the path needs
  139. // the have double backslashes for the GetObject call to work. We scan through
  140. // the string and do this manually here.
  141. //
  142. // CODEWORK: there has to be a faster way to do this, although the Append is
  143. // probably not too expensive, since the BSTR length can be found without
  144. // scanning the string. Unless it's reallocating more memory as it goes.
  145. pwch = bstrFile;
  146. if (fHasDoubleSlashes)
  147. bstrObjectPath.Append(pwch, SysStringLen(bstrFile));
  148. else
  149. for (uLen = SysStringLen(bstrFile); uLen > 0; uLen--)
  150. {
  151. if (*pwch == L'\\')
  152. bstrObjectPath.Append("\\");
  153. bstrObjectPath.Append(pwch, 1);
  154. pwch++;
  155. }
  156. bstrObjectPath.Append("\"");
  157. // Make the call to get the CIM_DataFile object.
  158. hRes = pWbemServices->GetObject(bstrObjectPath, 0, NULL, ppFileObject, NULL);
  159. if (FAILED(hRes))
  160. ErrorTrace(TRACE_ID, "GetObject on CIM_DataFile failed.");
  161. END:
  162. TraceFunctLeave();
  163. return hRes;
  164. }
  165. //*****************************************************************************
  166. //
  167. // Function Name : getCompletePath
  168. //
  169. // Input Parameters : bstrFileName
  170. // CComBSTR which represents the file
  171. // whose complete path is required.
  172. // Output Parameters : bstrFileWithPathName
  173. // CComBSTR which represents the file
  174. // with the Path
  175. // Returns : BOOL
  176. // TRUE if bstrFileWithPathName can be set.
  177. // FALSE if bstrFileWithPathName cannot be set.
  178. //
  179. //
  180. // Synopsis : Given a file name (bstrFileName) this function
  181. // searches the "System" directory for the existence
  182. // of the file.
  183. //
  184. // If it finds the file it pre appends the directory
  185. // path to the input file and copies into the output
  186. // file (bstrFileWithPathName).
  187. //
  188. // If it doesnot find the file in "System" directory
  189. // searches for the file in "Windows" Directoy and does
  190. // the same as above.
  191. //
  192. //*****************************************************************************
  193. BOOL getCompletePath(CComBSTR bstrFileName, CComBSTR &bstrFileWithPathName)
  194. {
  195. // Return
  196. BOOL bFoundFile = FALSE;
  197. ULONG uiReturn;
  198. TCHAR szDirectory[MAX_PATH];
  199. TCHAR temp[MAX_PATH];
  200. TCHAR lpstrTemp[MAX_PATH];
  201. struct _stat filestat;
  202. CComVariant varValue = NULL;
  203. CComBSTR bstrDirectory;
  204. // Check for the File in the System Directory
  205. uiReturn = GetSystemDirectory(szDirectory, MAX_PATH);
  206. if (uiReturn != 0 && uiReturn < MAX_PATH)
  207. {
  208. bstrDirectory = szDirectory;
  209. bstrDirectory.Append("\\");
  210. bstrDirectory.Append(bstrFileName);
  211. USES_CONVERSION;
  212. int Result = _tstat(W2T(bstrDirectory), &filestat) ;
  213. if (Result == 0)
  214. {
  215. bstrFileWithPathName = bstrDirectory;
  216. bFoundFile = TRUE;
  217. }
  218. }
  219. // If not there, then check in the windows directory.
  220. if (!bFoundFile)
  221. {
  222. uiReturn = GetWindowsDirectory(szDirectory, MAX_PATH);
  223. if (uiReturn != 0 && uiReturn < MAX_PATH)
  224. {
  225. bstrDirectory = szDirectory;
  226. bstrDirectory.Append("\\");
  227. bstrDirectory.Append(bstrFileName);
  228. USES_CONVERSION;
  229. int Result = _tstat(W2T(bstrDirectory), &filestat) ;
  230. if (Result == 0)
  231. {
  232. bstrFileWithPathName = bstrDirectory;
  233. bFoundFile = TRUE;
  234. }
  235. }
  236. }
  237. return(bFoundFile);
  238. }
  239. // Used by GetCim32NetDll and FreeCim32NetDll.
  240. CCritSec g_csCim32Net;
  241. HINSTANCE s_Handle = NULL;
  242. // There is a problem with loading Cim32Net.dll over and over, so this code
  243. // makes sure we only load it once, then unloads it at exit.
  244. // these are used with GetCim32NetHandle
  245. void FreeCim32NetHandle()
  246. {
  247. if (s_Handle)
  248. {
  249. FreeLibrary(s_Handle);
  250. s_Handle = NULL;
  251. }
  252. }
  253. HINSTANCE GetCim32NetHandle()
  254. {
  255. // Have we ever loaded it before?
  256. if (s_Handle == NULL)
  257. {
  258. // Avoid contention on static
  259. g_csCim32Net.Enter();
  260. // Check for race condition
  261. if (s_Handle == NULL)
  262. {
  263. s_Handle = LoadLibrary(_T("Cim32Net.dll"));
  264. // Register to free the handle at exit
  265. // NO! bad....badddd juju... call from FlushAll instead (o.w., when
  266. // cimwin32.dll unloads this pointer is invalid, but atexit gets
  267. // called when framedyn.dll unloads)
  268. // atexit(FreeCim32NetHandle);
  269. }
  270. g_csCim32Net.Leave();
  271. }
  272. // By re-opening the handle, we ensure proper refcounting on the handle,
  273. // and facilitate leak checking.
  274. HINSTANCE hHandle = LoadLibrary(_T("Cim32Net.dll"));
  275. return hHandle;
  276. }
  277. //
  278. // Given a delimited string, convert tokens into strings and store them into an array
  279. // returns the number of tokens parsed. Caller is responsible for freeing up the memory
  280. // allocated using delete
  281. //
  282. #ifndef UNICODE
  283. int DelimitedStringToArray(LPWSTR strString, LPTSTR strDelimiter, LPTSTR apstrArray[], int iMaxArraySize)
  284. {
  285. USES_CONVERSION;
  286. LPTSTR szString = W2A(strString);
  287. return DelimitedStringToArray(szString, strDelimiter, apstrArray, iMaxArraySize);
  288. }
  289. #endif
  290. int DelimitedStringToArray(LPTSTR strString, LPTSTR strDelimiter, LPTSTR apstrArray[], int iMaxArraySize)
  291. {
  292. // make a copy of the string to begin parsing
  293. LPTSTR strDelimitedString = (TCHAR *) new TCHAR [_tcslen(strString) + 1];
  294. // if out of memory, just return error value -1
  295. if (!strDelimitedString)
  296. return -1;
  297. // copy the token into the new allocated string
  298. _tcscpy(strDelimitedString, strString);
  299. // initialize _tcstok
  300. LPTSTR strTok = _tcstok(strDelimitedString, strDelimiter);
  301. int iCount = 0;
  302. // loop through all tokens parsed
  303. while ((strTok) && (iCount < iMaxArraySize))
  304. {
  305. LPTSTR strNewTok = (TCHAR *) new TCHAR[_tcslen(strTok) + 1];
  306. // if out of memory, just return error value -1
  307. if (!strNewTok)
  308. return -1;
  309. // copy the token into the new allocated string
  310. _tcscpy(strNewTok, strTok);
  311. // save it in the array
  312. apstrArray[iCount] = strNewTok;
  313. // increment the index
  314. iCount++;
  315. // get the next token
  316. strTok = _tcstok(NULL, strDelimiter);
  317. }
  318. // free up the memory used
  319. delete [] strDelimitedString;
  320. return iCount;
  321. }