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.

351 lines
7.5 KiB

  1. ///////////////////////////////////////////////////////////
  2. //
  3. // lasterr.cpp - Class which supports the HH_GET_LAST_ERROR function.
  4. // - Included here is the CProcessError class.
  5. //
  6. //
  7. ///////////////////////////////////////////////////////////
  8. //
  9. // Include files
  10. //
  11. // Global header
  12. #include "header.h"
  13. #include "hhctrl.h"
  14. // Our header
  15. #include "lasterr.h"
  16. ///////////////////////////////////////////////////////////
  17. //
  18. // Internal Classes
  19. //
  20. ///////////////////////////////////////////////////////////
  21. //
  22. // CProcessError
  23. //
  24. class CProcessError
  25. {
  26. public:
  27. CProcessError()
  28. : m_processid(0),
  29. m_hr(E_FAIL) // Assumes failure, because we never set it...
  30. {}
  31. // Process Id
  32. DWORD m_processid ;
  33. // Last error for this process id.
  34. HRESULT m_hr ;
  35. };
  36. ///////////////////////////////////////////////////////////
  37. //
  38. // CLastError
  39. //
  40. ///////////////////////////////////////////////////////////
  41. //
  42. // Constructor
  43. //
  44. CLastError::CLastError()
  45. : m_ProcessErrorArray(NULL),
  46. m_maxindex(0),
  47. m_lastindex(0)
  48. {
  49. }
  50. ///////////////////////////////////////////////////////////
  51. //
  52. // Destructor
  53. //
  54. CLastError::~CLastError()
  55. {
  56. // Delete the array.
  57. Finish() ;
  58. }
  59. ///////////////////////////////////////////////////////////
  60. //
  61. // Set the error
  62. //
  63. void
  64. CLastError::Set(HRESULT hr)
  65. {
  66. DWORD idProcess = 1 ; //TODO: REMOVE!!!
  67. if (idProcess) // The idProcess might be zero during the conversion process.
  68. {
  69. CProcessError* pProcessError = FindProcess(idProcess) ;
  70. ASSERT(pProcessError) ;
  71. // Set the fields.
  72. pProcessError->m_hr = hr ;
  73. pProcessError->m_processid = idProcess ;
  74. }
  75. }
  76. ///////////////////////////////////////////////////////////
  77. //
  78. // Get the error
  79. //
  80. void
  81. CLastError::Get(HRESULT* hr)
  82. {
  83. DWORD idProcess = 1 ; //TODO: REMOVE!!!
  84. if (idProcess)
  85. {
  86. CProcessError* pProcessError = FindProcess(idProcess) ;
  87. ASSERT(pProcessError) ;
  88. *hr = pProcessError->m_hr;
  89. }
  90. }
  91. ///////////////////////////////////////////////////////////
  92. //
  93. // Reset the error
  94. //
  95. void
  96. CLastError::Reset()
  97. {
  98. DWORD idProcess = 1 ; //TODO: REMOVE!!!
  99. if (idProcess)
  100. {
  101. CProcessError* pProcessError = FindProcess(idProcess) ;
  102. ASSERT(pProcessError) ;
  103. pProcessError->m_hr = E_FAIL ; // Only call if you have a NULL hwnd. S_OK ;
  104. }
  105. }
  106. ///////////////////////////////////////////////////////////
  107. //
  108. // Finish - The whole reason for this function is so we can clean
  109. // things up in DLL process detach.
  110. //
  111. void
  112. CLastError::Finish()
  113. {
  114. // Delete the array.
  115. DeallocateArray(m_ProcessErrorArray) ;
  116. // Set pointer to NULL.
  117. m_ProcessErrorArray = NULL ;
  118. // Reset the other variables.
  119. m_maxindex = 0 ;
  120. m_lastindex = 0 ;
  121. // Just like starting all over.
  122. }
  123. ///////////////////////////////////////////////////////////
  124. //
  125. // Internal Helpers
  126. //
  127. ///////////////////////////////////////////////////////////
  128. //
  129. // FindProcess - Gets the index number for the process id ;
  130. //
  131. CProcessError*
  132. CLastError::FindProcess(DWORD idProcess)
  133. {
  134. ASSERT( m_lastindex <= m_maxindex) ;
  135. CProcessError* p = m_ProcessErrorArray ;
  136. // Look for the process in the array.
  137. for (int i = 0 ; i < m_lastindex ; i++)
  138. {
  139. if (p->m_processid == idProcess)
  140. {
  141. // Found it!
  142. return p ;
  143. }
  144. p++ ;
  145. }
  146. // Okay, we didn't find the process id.
  147. // Add it on to the end.
  148. return AddProcess() ;
  149. }
  150. ///////////////////////////////////////////////////////////
  151. //
  152. // AddProcess - adds a process structure to the array.
  153. //
  154. CProcessError*
  155. CLastError::AddProcess()
  156. {
  157. CProcessError* p = NULL ;
  158. if (m_lastindex < m_maxindex)
  159. {
  160. // Don't need to grow. Just add it to the existing array.
  161. p = &m_ProcessErrorArray[m_lastindex] ;
  162. }
  163. else
  164. {
  165. // We have used up our slots, so we need to allocate more.
  166. int newmaxindex = m_maxindex + c_GrowBy;
  167. // Allocate a new array.
  168. p = AllocateArray(newmaxindex) ;
  169. // Copy existing entries.
  170. for (int i = 0 ; i < m_maxindex ; i++)
  171. {
  172. // Copy the pointers
  173. p[i] = m_ProcessErrorArray[i] ;
  174. }
  175. // Delete the original array.
  176. DeallocateArray(m_ProcessErrorArray) ;
  177. // Use the new array.
  178. m_ProcessErrorArray = p;
  179. // get the pointer.
  180. p = &m_ProcessErrorArray[m_lastindex] ;
  181. // reset the endpoint.
  182. m_maxindex = newmaxindex ;
  183. }
  184. // Increment the index ;
  185. m_lastindex++ ;
  186. // Post condition.
  187. ASSERT(p) ;
  188. return p ;
  189. }
  190. ///////////////////////////////////////////////////////////
  191. //
  192. // Allocate Array
  193. //
  194. CProcessError*
  195. CLastError::AllocateArray(int elements)
  196. {
  197. return new CProcessError[elements] ;
  198. }
  199. ///////////////////////////////////////////////////////////
  200. //
  201. // Deallocate Array
  202. //
  203. void
  204. CLastError::DeallocateArray(CProcessError* p)
  205. {
  206. // For some reason the heap management code in hhctrl allows memory leaks,
  207. // but doesn't allow global class variables to call delete in their constructors.
  208. if (p)
  209. {
  210. delete [] p ;
  211. }
  212. }
  213. ///////////////////////////////////////////////////////////
  214. //
  215. // Public globals.
  216. //
  217. CLastError g_LastError ;
  218. ///////////////////////////////////////////////////////////
  219. //
  220. // Global Functions
  221. //
  222. ///////////////////////////////////////////////////////////
  223. //
  224. // hhGetLastError
  225. //
  226. HRESULT hhGetLastError(HH_LAST_ERROR* pError)
  227. {
  228. if (!pError &&
  229. IsBadReadPtr((void*) pError, sizeof(HH_LAST_ERROR)) &&
  230. IsBadWritePtr((void*) pError, sizeof(HH_LAST_ERROR)) &&
  231. pError->cbStruct >= sizeof(HH_LAST_ERROR))
  232. {
  233. return E_FAIL;
  234. }
  235. // Get the last error.
  236. g_LastError.Get(&pError->hr) ;
  237. // We got the error, now get the string to go with it.
  238. GetStringFromHr(pError->hr, &pError->description) ;
  239. return S_OK ;
  240. }
  241. ///////////////////////////////////////////////////////////
  242. //
  243. // GetStringFromHr
  244. //
  245. HRESULT
  246. GetStringFromHr(HRESULT hr, BSTR* pDescription)
  247. {
  248. // Get the stringid for this error code.
  249. HRESULT hrReturn = E_FAIL ;
  250. *pDescription = NULL ;
  251. if (FAILED(hr))
  252. {
  253. // Currently we don't have any strings to return.
  254. int stringid = ErrorStringId(hr) ;
  255. if (stringid)
  256. {
  257. // Get the string from the resource table.
  258. PCSTR pstr = GetStringResource(stringid) ;
  259. if (pstr[0] != '\0')
  260. {
  261. // Convert to wide.
  262. CWStr wstrError(pstr) ;
  263. // Make it into a BSTR.
  264. *pDescription = ::SysAllocString(wstrError) ;
  265. hrReturn = S_OK ;
  266. }
  267. }
  268. else
  269. {
  270. *pDescription = NULL ;
  271. hrReturn = S_FALSE ;
  272. }
  273. }
  274. // Only return a description if the call failed.
  275. return hrReturn;
  276. }
  277. ///////////////////////////////////////////////////////////
  278. //
  279. // ErrorStringId - returns the resource id for a HRESULT.
  280. //
  281. int
  282. ErrorStringId(HRESULT hr)
  283. {
  284. int iReturn ;
  285. switch(hr)
  286. {
  287. case HH_E_NOCONTEXTIDS:
  288. iReturn = IDS_HH_E_NOCONTEXTIDS;
  289. break ;
  290. case HH_E_FILENOTFOUND:
  291. iReturn = IDS_HH_E_FILENOTFOUND;
  292. break ;
  293. case HH_E_INVALIDHELPFILE:
  294. iReturn = IDS_HH_E_INVALIDHELPFILE;
  295. break ;
  296. case HH_E_CONTEXTIDDOESNTEXIT:
  297. iReturn = IDS_HH_E_CONTEXTIDDOESNTEXIT;
  298. break ;
  299. default:
  300. iReturn = 0;
  301. break ;
  302. };
  303. return iReturn ;
  304. }