Leaked source code of windows server 2003
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.

249 lines
6.6 KiB

  1. /*++
  2. Copyright (C) 2001 Microsoft Corporation
  3. Module Name: ErrorObj
  4. Abstract: IErrorInfo support for the standard consumers
  5. History: 07/11/2001 - creation, HHance.
  6. --*/
  7. #include "precomp.h"
  8. //#include <stdio.h>
  9. #include <wbemutil.h>
  10. //#include <ArrTempl.h>
  11. //#include <lmaccess.h>
  12. #include <wbemdisp.h>
  13. //#include "ScriptKiller.h"
  14. //#include "script.h"
  15. //#include "ClassFac.h"
  16. //#include <GroupsForUser.h>
  17. #include <GenUtils.h>
  18. #include "ErrorObj.h"
  19. #include <strsafe.h>
  20. #define ClassName L"__ExtendedStatus"
  21. // no touch. Use GetErrorObj instead.
  22. ErrorObj StaticErrorObj;
  23. // so we can manage our component's lifetimes in the wunnerful world of COM, etc...
  24. // returns addref'd error object
  25. ErrorObj* ErrorObj::GetErrorObj()
  26. {
  27. StaticErrorObj.AddRef();
  28. return &StaticErrorObj;
  29. }
  30. // returns adref'd namespace ("root")
  31. IWbemServices* ErrorObj::GetMeANamespace()
  32. {
  33. IWbemServices* pNamespace = NULL;
  34. IWbemLocator* pLocator = NULL;
  35. if (SUCCEEDED(CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER,
  36. IID_IWbemLocator, (void**)&pLocator)))
  37. {
  38. BSTR bstrNamespace;
  39. bstrNamespace = SysAllocString(L"root");
  40. if (bstrNamespace)
  41. {
  42. pLocator->ConnectServer(bstrNamespace, NULL, NULL, NULL, 0, NULL, NULL, &pNamespace);
  43. SysFreeString(bstrNamespace);
  44. }
  45. pLocator->Release();
  46. }
  47. return pNamespace;
  48. }
  49. ULONG ErrorObj::AddRef()
  50. {
  51. // since we don't do a delete this
  52. // there is a chance that someone could sneak in and re-init while we're in the process
  53. // of shutting down. That would be bad.
  54. // Hence we use our own CS instead of interlockedXXrement.
  55. CInCritSec cs( &m_cs );
  56. ULONG count = ++m_lRef;
  57. return count;
  58. }
  59. // we do not do a 'delete this' here.
  60. // We just release the COM objects
  61. ULONG ErrorObj::Release()
  62. {
  63. // since we don't do a 'delete this'
  64. // there is a chance that someone could sneak in and re-init
  65. // while we're in the process of shutting down.
  66. // That would be bad.
  67. // Hence we use our own CS instead of interlockedXXrement.
  68. CInCritSec cs( &m_cs );
  69. ULONG count = --m_lRef;
  70. if (m_lRef == 0)
  71. {
  72. if (m_pErrorObject)
  73. {
  74. m_pErrorObject->Release();
  75. m_pErrorObject = NULL;
  76. }
  77. }
  78. return count;
  79. }
  80. // does the real work, creates the object, populates it, sends it off.
  81. // arguments map to __ExtendedStatus class.
  82. // void func - what are y'gonna do if you can't report an error? Report an error?
  83. // bFormat - will attempt to use FormatError to fill in the description if NULL.
  84. void ErrorObj::ReportError(const WCHAR* operation, const WCHAR* parameterInfo, const WCHAR* description, UINT statusCode, bool bFormat)
  85. {
  86. // a shiny new instance of __ExtendedStatus
  87. IWbemClassObject* pObj = GetObj();
  88. IErrorInfo* pEI = NULL;
  89. if (pObj && SUCCEEDED(pObj->QueryInterface(IID_IErrorInfo, (void**)&pEI)))
  90. {
  91. // theory: I'm going to try to set everything.
  92. // something might fail along the way. At this point
  93. // the biggest disaster would be that the user got partial info
  94. VARIANT v;
  95. VariantInit(&v);
  96. v.vt = VT_BSTR;
  97. // Operation
  98. if (operation)
  99. {
  100. v.bstrVal = SysAllocString(operation);
  101. if (v.bstrVal)
  102. {
  103. pObj->Put(L"Operation", 0, &v, 0);
  104. SysFreeString(v.bstrVal);
  105. }
  106. }
  107. // ParameterInfo
  108. if (parameterInfo)
  109. {
  110. v.bstrVal = SysAllocString(parameterInfo);
  111. if (v.bstrVal)
  112. {
  113. pObj->Put(L"ParameterInfo", 0, &v, 0);
  114. SysFreeString(v.bstrVal);
  115. }
  116. }
  117. // Description
  118. if (description)
  119. v.bstrVal = SysAllocString(description);
  120. else if (bFormat)
  121. {
  122. WCHAR* pMsg = NULL;
  123. if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
  124. NULL, statusCode, 0, (WCHAR*)&pMsg, 1, NULL) && pMsg)
  125. {
  126. v.bstrVal = SysAllocString(pMsg);
  127. LocalFree(pMsg);
  128. }
  129. else
  130. v.bstrVal = NULL;
  131. }
  132. else
  133. v.bstrVal = NULL;
  134. if (v.bstrVal)
  135. {
  136. pObj->Put(L"Description", 0, &v, 0);
  137. SysFreeString(v.bstrVal);
  138. }
  139. // StatusCode
  140. v.vt = VT_I4;
  141. v.lVal = statusCode;
  142. pObj->Put(L"StatusCode", 0, &v, 0);
  143. // do it to it
  144. SetErrorInfo(0, pEI);
  145. }
  146. if (pObj)
  147. pObj->Release();
  148. if (pEI)
  149. pEI->Release();
  150. }
  151. // spawn off an object to be populated
  152. // can't keep reusing same object as we have more than one thread going
  153. IWbemClassObject* ErrorObj::GetObj()
  154. {
  155. IWbemClassObject* pObj = NULL;
  156. // big CS -- need to guard against possibility of shut down
  157. // occuring during startup.
  158. CInCritSec cs( &m_cs );
  159. if (!m_pErrorObject)
  160. {
  161. IWbemServices* pNamespace = NULL;
  162. pNamespace = GetMeANamespace();
  163. if (pNamespace)
  164. {
  165. BSTR className;
  166. className = SysAllocString(ClassName);
  167. if (className)
  168. {
  169. IWbemClassObject* pClassObject = NULL;
  170. if (SUCCEEDED(pNamespace->GetObject(className, 0, NULL, &pClassObject, NULL)))
  171. {
  172. // okay, if it fails, then m_pErrorObject is still NULL. No problemo.
  173. pClassObject->SpawnInstance(0, &m_pErrorObject);
  174. pClassObject->Release();
  175. }
  176. SysFreeString(className);
  177. }
  178. pNamespace->Release();
  179. }
  180. }
  181. if (m_pErrorObject)
  182. m_pErrorObject->Clone(&pObj);
  183. return pObj;
  184. }
  185. /************************ a legacy before it's shipped...
  186. // must be called inside the CS.
  187. // must be called prior to ReportError (if you expect it to succeed, anyway...)
  188. void ErrorObj::SetNamespace(IWbemServices* pNamespace)
  189. {
  190. // first one in wins, after that it's static
  191. if (pNamespace && !m_pNamespace)
  192. {
  193. if (!m_pNamespace)
  194. {
  195. m_pNamespace = pNamespace;
  196. m_pNamespace->AddRef();
  197. }
  198. }
  199. }
  200. *************************/