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.

362 lines
12 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1997-1998, Microsoft Corporation.
  4. //
  5. // File: ixserror.cxx
  6. //
  7. // Contents: SSO Error class
  8. //
  9. // History: 04 Apr 1997 Alanw Created
  10. //
  11. //----------------------------------------------------------------------------
  12. #include "pch.cxx"
  13. #pragma hdrstop
  14. //-----------------------------------------------------------------------------
  15. // Include Files
  16. //-----------------------------------------------------------------------------
  17. // debugging macros
  18. #include "ssodebug.hxx"
  19. // class declaration
  20. #include "ixserror.hxx"
  21. //-----------------------------------------------------------------------------
  22. //
  23. // Member: CixssoError::SetError - private
  24. //
  25. // Synopsis: Save error information
  26. //
  27. // Arguments: [scError] - Error code
  28. // [iLine] - (optional) line number where error occurred
  29. // [pwszFile] - (optional) file name where error occurred
  30. // [pwszLoc] - Location from which error was generated
  31. // [eErrClass] - error class, indicates error message file
  32. //
  33. // Notes:
  34. //
  35. // History: 07 Jan 1997 Alanw Created
  36. //
  37. //-----------------------------------------------------------------------------
  38. extern HINSTANCE g_hInst;
  39. extern WCHAR * g_pwszErrorMsgFile;
  40. #define ERROR_MESSAGE_SIZE 512
  41. void CixssoError::SetError(
  42. SCODE scError,
  43. ULONG iLine,
  44. WCHAR const * pwszFile,
  45. WCHAR const * pwszLoc,
  46. unsigned eErrClass,
  47. LCID lcid)
  48. {
  49. // Has the error already been handled? If so, return.
  50. if ( _sc != 0)
  51. return;
  52. if ( QUERY_E_DUPLICATE_OUTPUT_COLUMN == scError )
  53. {
  54. scError = MSG_IXSSO_DUPLICATE_COLUMN;
  55. eErrClass = eIxssoError;
  56. }
  57. else if ( QUERY_E_INVALID_OUTPUT_COLUMN == scError )
  58. {
  59. scError = MSG_IXSSO_NO_SUCH_COLUMN_PROPERTY;
  60. eErrClass = eIxssoError;
  61. }
  62. // Does this error (possibly transalted) already exist on the error stack?
  63. // If it does, and it has a description, we shouldn't be doing anything else.
  64. if (FALSE == NeedToSetError(scError))
  65. return;
  66. ixssoDebugOut(( DEB_ITRACE, "SetError: sc = %x, loc = %ws\n", scError, pwszLoc ));
  67. WCHAR awcsErrorMessage[ERROR_MESSAGE_SIZE];
  68. WCHAR *pwszErrorMessage = awcsErrorMessage;
  69. ULONG cchAvailMessage = ERROR_MESSAGE_SIZE;
  70. //
  71. // Generate the Win32 error code by removing the facility code (7) and
  72. // the error bit.
  73. //
  74. ULONG Win32status = scError;
  75. if ( (Win32status & (FACILITY_WIN32 << 16)) == (FACILITY_WIN32 << 16) )
  76. {
  77. Win32status &= ~( 0x80000000 | (FACILITY_WIN32 << 16) );
  78. }
  79. //
  80. // Don't pass a specific lang id to FormatMessage since it will
  81. // fail if there's no message in that language. Instead set
  82. // the thread locale, which will get FormatMessage to use a search
  83. // algorithm to find a message of the appropriate language or
  84. // use a reasonable fallback msg if there's none.
  85. //
  86. LCID SaveLCID = GetThreadLocale();
  87. SetThreadLocale(lcid);
  88. // Precede the error message by the file/line if passed.
  89. if (pwszFile != 0)
  90. {
  91. UINT_PTR args [] = {
  92. (UINT_PTR) pwszFile,
  93. (UINT_PTR) iLine,
  94. };
  95. NTSTATUS MsgNum = MSG_IXSSO_FILE_MESSAGE;
  96. if (iLine != 0)
  97. {
  98. MsgNum = MSG_IXSSO_FILE_LINE_MESSAGE;
  99. }
  100. ULONG cchMsg = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE |
  101. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  102. g_hInst,
  103. MsgNum,
  104. 0,
  105. pwszErrorMessage,
  106. cchAvailMessage,
  107. (va_list *) args );
  108. pwszErrorMessage += cchMsg;
  109. cchAvailMessage -= cchMsg;
  110. }
  111. BOOL fSystemError = FALSE;
  112. switch (eErrClass)
  113. {
  114. case eIxssoError:
  115. if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE,
  116. g_hInst,
  117. scError,
  118. 0,
  119. pwszErrorMessage,
  120. cchAvailMessage,
  121. 0 ) )
  122. {
  123. ixssoDebugOut(( DEB_ERROR, "Format message failed with error 0x%x\n", GetLastError() ));
  124. swprintf( pwszErrorMessage,
  125. L"Error 0x%x caught while processing query\n",
  126. scError );
  127. }
  128. break;
  129. case ePlistError:
  130. case eParseError:
  131. if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE,
  132. GetModuleHandle(g_pwszErrorMsgFile),
  133. scError,
  134. 0,
  135. pwszErrorMessage,
  136. cchAvailMessage,
  137. 0 ) )
  138. {
  139. ixssoDebugOut(( DEB_ERROR, "Format message failed with error 0x%x\n", GetLastError() ));
  140. swprintf( pwszErrorMessage,
  141. L"Error 0x%x caught while parsing query or other fields\n",
  142. scError );
  143. }
  144. break;
  145. case eDefaultError:
  146. if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE,
  147. g_hInst,
  148. scError,
  149. 0,
  150. pwszErrorMessage,
  151. cchAvailMessage,
  152. 0 ) )
  153. {
  154. if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE,
  155. GetModuleHandle(g_pwszErrorMsgFile),
  156. scError,
  157. 0,
  158. pwszErrorMessage,
  159. cchAvailMessage,
  160. 0 ) )
  161. {
  162. //
  163. // Try looking up the error in the Win32 list of error codes
  164. //
  165. if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE,
  166. GetModuleHandle(L"kernel32.dll"),
  167. Win32status,
  168. 0,
  169. pwszErrorMessage,
  170. cchAvailMessage,
  171. 0 ) )
  172. {
  173. ixssoDebugOut(( DEB_ERROR, "Format message failed with error 0x%x\n", GetLastError() ));
  174. swprintf( pwszErrorMessage,
  175. L"Error 0x%x caught while processing query\n",
  176. scError );
  177. }
  178. else
  179. {
  180. fSystemError = TRUE;
  181. }
  182. }
  183. }
  184. break;
  185. default:
  186. Win4Assert( !"Unrecognized error class" );
  187. break;
  188. }
  189. SetThreadLocale(SaveLCID);
  190. SetError( scError, pwszLoc, awcsErrorMessage );
  191. }
  192. //-----------------------------------------------------------------------------
  193. //
  194. // Member: CixssoError::SetError - private
  195. //
  196. // Synopsis: Save error information
  197. //
  198. // Arguments: [scError] - Error code
  199. // [pwszLoc] - Location from which error was generated
  200. // [pwszDescription] - Error description
  201. //
  202. // Notes:
  203. //
  204. // History: 06 May 1997 KrishnaN Created
  205. //
  206. //-----------------------------------------------------------------------------
  207. void CixssoError::SetError( SCODE scError,
  208. WCHAR const * pwszLoc,
  209. WCHAR const * pwszDescription)
  210. {
  211. // Has the error on this object already been set?
  212. if (_sc != 0)
  213. return;
  214. // We should be here only if an error has NOT already been set.
  215. Win4Assert(NeedToSetError(scError));
  216. Win4Assert(pwszLoc && pwszDescription);
  217. ixssoDebugOut(( DEB_ITRACE,
  218. "SetError: sc = %x, loc = %ws,\n\tdescription = %ws\n",
  219. scError, pwszLoc, pwszDescription ));
  220. _fErr = TRUE;
  221. _sc = scError;
  222. //
  223. // Create an error info object giving the error message
  224. //
  225. ICreateErrorInfo * pErrorInfo;
  226. SCODE sc = CreateErrorInfo( &pErrorInfo );
  227. if (SUCCEEDED( sc ))
  228. {
  229. XInterface<ICreateErrorInfo> pErr(pErrorInfo);
  230. pErrorInfo = 0;
  231. pErr->SetDescription( (LPWSTR) pwszDescription );
  232. pErr->SetGUID( _iid );
  233. pErr->SetSource( (LPWSTR) pwszLoc ); // Cast ok. Never touched by anyone.
  234. IErrorInfo * pErrInfo = 0;
  235. sc = pErr->QueryInterface( IID_IErrorInfo, (void **)&pErrInfo);
  236. if (SUCCEEDED(sc))
  237. {
  238. SetErrorInfo(0, pErrInfo);
  239. pErrInfo->Release();
  240. }
  241. }
  242. }
  243. //-----------------------------------------------------------------------------
  244. //
  245. // Member: CixssoError::NeedToSetError - private
  246. //
  247. // Synopsis: Determine if error needs to be set.
  248. //
  249. // Arguments: [scError] - Error code to look for
  250. //
  251. // Returns: TRUE if the error needs to be set. FALSE, if it already
  252. // exists and has a valid description string.
  253. //
  254. // Notes:
  255. //
  256. // History: 15 Jan 1998 KrishnaN Created
  257. //
  258. //-----------------------------------------------------------------------------
  259. BOOL CixssoError::NeedToSetError(SCODE scError)
  260. {
  261. BOOL fFound = FALSE;
  262. //
  263. // Get the current error object. Return TRUE if none exists.
  264. //
  265. XInterface<IErrorInfo> xErrorInfo;
  266. SCODE sc = GetErrorInfo(0, (IErrorInfo **)xErrorInfo.GetQIPointer());
  267. if ( S_FALSE == sc )
  268. {
  269. Win4Assert(0 == xErrorInfo.GetPointer());
  270. return TRUE;
  271. }
  272. // Get the IErrorRecord interface and get the count of errors.
  273. XInterface<IErrorRecords> xErrorRecords;
  274. XBStr xDescription;
  275. BSTR pDescription = xDescription.GetPointer();
  276. sc = xErrorInfo->QueryInterface(IID_IErrorRecords, xErrorRecords.GetQIPointer());
  277. if (0 == xErrorRecords.GetPointer())
  278. {
  279. // No error records. Do we at least have the top level description set?
  280. // If so, that indicates an automation client called SetErrorInfo before us
  281. // and we should not overwrite them.
  282. xErrorInfo->GetDescription(&pDescription);
  283. fFound = ( pDescription != 0 ) ;
  284. }
  285. else
  286. {
  287. ULONG cErrRecords;
  288. sc = xErrorRecords->GetRecordCount(&cErrRecords);
  289. Win4Assert(!fFound);
  290. // look for the target error code. stop when one is found
  291. ERRORINFO ErrorInfo;
  292. for (ULONG i = 0; i < cErrRecords; i++)
  293. {
  294. sc = xErrorRecords->GetBasicErrorInfo(i, &ErrorInfo);
  295. Win4Assert(S_OK == sc);
  296. if (scError == ErrorInfo.hrError)
  297. {
  298. xErrorInfo->GetDescription(&pDescription);
  299. fFound = ( pDescription != 0 );
  300. break;
  301. }
  302. }
  303. }
  304. if (!fFound)
  305. return TRUE;
  306. // we found the error code and it has a description.
  307. // no need to set this error again, but we have to
  308. // put this error info back so the client can find it.
  309. SetErrorInfo(0, xErrorInfo.GetPointer());
  310. return FALSE;
  311. }