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.

802 lines
26 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 2000.
  5. //
  6. // File: errormsg.cxx
  7. //
  8. // Contents: Error messages for output/running queries
  9. //
  10. // History: 96/Mar/3 DwightKr Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include <pch.cxx>
  14. #pragma hdrstop
  15. #define ERROR_MESSAGE_SIZE 512
  16. //+---------------------------------------------------------------------------
  17. //
  18. // Function: GetErrorPageNoThrow - public
  19. //
  20. // Synposis: Generates an error page based on the error parameters passed.
  21. //
  22. // Arguments: [eErrorClass] - class of error (IDQ, HTX, restirction, etc)
  23. // [status] - error code generated
  24. // [ulErrorLine] - line on which the error occured
  25. // [wcsErrorFileName] - name of file which generated the error
  26. // [pVariableSet] - replaceable parameters which generated the error
  27. // [pOutputFormat] - format of dates & numbers
  28. // [locale] - locale of the browser
  29. // [webServer] - the web server
  30. // [vString] - virtual string to contain error code
  31. //
  32. // History: 96/Feb/29 DwightKr Created
  33. //
  34. //----------------------------------------------------------------------------
  35. void GetErrorPageNoThrow(
  36. int eErrorClass,
  37. NTSTATUS status,
  38. ULONG ulErrorLine,
  39. WCHAR const * wcsErrorFileName,
  40. CVariableSet * pVariableSet,
  41. COutputFormat * pOutputFormat,
  42. LCID locale,
  43. CWebServer & webServer,
  44. CVirtualString & vString )
  45. {
  46. //
  47. // If the error was caused by a failure to WRITE to the web server,
  48. // then don't bother trying to report an error, there is no one to
  49. // receive it.
  50. //
  51. if ( eWebServerWriteError == eErrorClass )
  52. {
  53. ciGibDebugOut(( DEB_IWARN, "Failed to write to the web server" ));
  54. return;
  55. }
  56. //
  57. // If the error was the result of an access denied problem, then simply
  58. // return a 401 error to the browser
  59. //
  60. WCHAR awcsErrorMessage[ERROR_MESSAGE_SIZE];
  61. WCHAR * pwszErrorMessage = awcsErrorMessage;
  62. ULONG cchAvailMessage = ERROR_MESSAGE_SIZE;
  63. //
  64. // Generate the Win32 error code by removing the facility code (7) and
  65. // the error bit.
  66. //
  67. ULONG Win32status = status;
  68. if ( (Win32status & (FACILITY_WIN32 << 16)) == (FACILITY_WIN32 << 16) )
  69. {
  70. Win32status &= ~( 0x80000000 | (FACILITY_WIN32 << 16) );
  71. }
  72. if ( (STATUS_ACCESS_DENIED == status) ||
  73. (STATUS_NETWORK_ACCESS_DENIED == status) ||
  74. (ERROR_ACCESS_DENIED == Win32status) ||
  75. (ERROR_INVALID_ACCESS == Win32status) ||
  76. (ERROR_NETWORK_ACCESS_DENIED == Win32status)
  77. )
  78. {
  79. ciGibDebugOut(( DEB_WARN, "mapping 0x%x to 401 access denied\n", status ));
  80. ReturnServerError( HTTP_STATUS_DENIED, webServer );
  81. return;
  82. }
  83. //
  84. // Map special error codes to their message equivalents.
  85. //
  86. if ( QUERY_E_DUPLICATE_OUTPUT_COLUMN == status )
  87. {
  88. status = MSG_CI_IDQ_DUPLICATE_COLUMN;
  89. }
  90. else if ( QUERY_E_INVALID_OUTPUT_COLUMN == status )
  91. {
  92. status = MSG_CI_IDQ_NO_SUCH_COLUMN_PROPERTY;
  93. }
  94. if ( 0 != wcsErrorFileName )
  95. {
  96. WCHAR *p = wcsrchr( wcsErrorFileName, L'\\' );
  97. if ( 0 == p )
  98. p = wcsrchr( wcsErrorFileName, L'/' );
  99. if ( 0 == p )
  100. p = wcsrchr( wcsErrorFileName, L':' );
  101. if ( 0 != p )
  102. wcsErrorFileName = p + 1;
  103. }
  104. //
  105. // Don't pass a specific lang id to FormatMessage since it will
  106. // fail if there's no message in that language. Instead set
  107. // the thread locale, which will get FormatMessage to use a search
  108. // algorithm to find a message of the appropriate language or
  109. // use a reasonable fallback msg if there's none.
  110. //
  111. LCID SaveLCID = GetThreadLocale();
  112. SetThreadLocale(locale);
  113. switch (eErrorClass)
  114. {
  115. case eIDQParseError:
  116. {
  117. //
  118. // These are errors encountered while parsing the IDQ file
  119. //
  120. DWORD_PTR args [] = {
  121. (DWORD_PTR) ulErrorLine,
  122. (DWORD_PTR) wcsErrorFileName
  123. };
  124. if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE |
  125. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  126. GetModuleHandle(L"idq.dll"),
  127. status,
  128. 0,
  129. pwszErrorMessage,
  130. cchAvailMessage,
  131. (va_list *) args ) )
  132. {
  133. ciGibDebugOut(( DEB_ERROR, "Format message failed with error 0x%x\n", GetLastError() ));
  134. swprintf( pwszErrorMessage,
  135. L"Processing of IDQ file %ls failed with error 0x%x\n",
  136. wcsErrorFileName,
  137. status );
  138. }
  139. }
  140. break;
  141. case eIDQPlistError:
  142. {
  143. //
  144. // These are errors encountered while parsing the [names] section
  145. //
  146. if (wcsErrorFileName != 0)
  147. {
  148. DWORD_PTR args [] = {
  149. (DWORD_PTR) wcsErrorFileName,
  150. (DWORD_PTR) ulErrorLine,
  151. };
  152. NTSTATUS MsgNum = MSG_IDQ_FILE_MESSAGE;
  153. if (ulErrorLine != 0)
  154. {
  155. MsgNum = MSG_IDQ_FILE_LINE_MESSAGE;
  156. }
  157. ULONG cchMsg = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE |
  158. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  159. GetModuleHandle(L"idq.dll"),
  160. MsgNum,
  161. 0,
  162. pwszErrorMessage,
  163. cchAvailMessage,
  164. (va_list *) args );
  165. pwszErrorMessage += cchMsg;
  166. cchAvailMessage -= cchMsg;
  167. }
  168. if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE,
  169. GetModuleHandle(L"query.dll"),
  170. status,
  171. 0,
  172. pwszErrorMessage,
  173. cchAvailMessage,
  174. 0 ) )
  175. {
  176. ciGibDebugOut(( DEB_ERROR, "Format message failed with error 0x%x\n", GetLastError() ));
  177. swprintf( pwszErrorMessage,
  178. L"Processing of IDQ file [names] failed with error 0x%x\n",
  179. status );
  180. }
  181. }
  182. break;
  183. case eHTXParseError:
  184. {
  185. //
  186. // These are errors encountered while parsing the IDQ file
  187. //
  188. DWORD_PTR args [] = {
  189. (DWORD_PTR) ulErrorLine,
  190. (DWORD_PTR) wcsErrorFileName
  191. };
  192. if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE |
  193. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  194. GetModuleHandle(L"idq.dll"),
  195. status,
  196. 0,
  197. pwszErrorMessage,
  198. cchAvailMessage,
  199. (va_list *) args ) )
  200. {
  201. ciGibDebugOut(( DEB_ERROR, "Format message failed with error 0x%x\n", GetLastError() ));
  202. swprintf( pwszErrorMessage,
  203. L"Error 0x%x occured while parsing in HTX file %ls\n",
  204. status,
  205. wcsErrorFileName );
  206. }
  207. }
  208. break;
  209. case eRestrictionParseError:
  210. {
  211. //
  212. // These are errors encountered while parsing the restriction
  213. //
  214. if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE,
  215. GetModuleHandle(L"query.dll"),
  216. status,
  217. 0,
  218. pwszErrorMessage,
  219. cchAvailMessage,
  220. 0 ) )
  221. {
  222. ciGibDebugOut(( DEB_ERROR, "Format message failed with error 0x%x\n", GetLastError() ));
  223. swprintf( pwszErrorMessage,
  224. L"Restriction parsing failed with error 0x%x\n",
  225. status );
  226. }
  227. }
  228. break;
  229. default:
  230. {
  231. //
  232. // All other errors; other major classes of errors are caught above.
  233. //
  234. DWORD_PTR args [] = {
  235. (DWORD_PTR) ulErrorLine,
  236. (DWORD_PTR) wcsErrorFileName
  237. };
  238. if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE |
  239. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  240. GetModuleHandle(L"idq.dll"),
  241. status,
  242. 0,
  243. pwszErrorMessage,
  244. cchAvailMessage,
  245. (va_list *) args ) )
  246. {
  247. if (wcsErrorFileName != 0)
  248. {
  249. NTSTATUS MsgNum = MSG_IDQ_FILE_MESSAGE;
  250. args[0] = (DWORD_PTR)wcsErrorFileName;
  251. if (ulErrorLine != 0)
  252. {
  253. args[1] = ulErrorLine;
  254. MsgNum = MSG_IDQ_FILE_LINE_MESSAGE;
  255. }
  256. ULONG cchMsg = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE |
  257. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  258. GetModuleHandle(L"idq.dll"),
  259. MsgNum,
  260. 0,
  261. pwszErrorMessage,
  262. cchAvailMessage,
  263. (va_list *) args );
  264. pwszErrorMessage += cchMsg;
  265. cchAvailMessage -= cchMsg;
  266. }
  267. if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE,
  268. GetModuleHandle(L"query.dll"),
  269. status,
  270. 0,
  271. pwszErrorMessage,
  272. cchAvailMessage,
  273. 0 ) )
  274. {
  275. //
  276. // Try looking up the error in the Win32 list of error codes
  277. //
  278. if ( ! FormatMessage( FORMAT_MESSAGE_FROM_HMODULE,
  279. GetModuleHandle(L"kernel32.dll"),
  280. Win32status,
  281. 0,
  282. pwszErrorMessage,
  283. cchAvailMessage,
  284. 0 ) )
  285. {
  286. ciGibDebugOut(( DEB_ERROR,
  287. "Format message failed with error 0x%x\n",
  288. GetLastError() ));
  289. swprintf( pwszErrorMessage,
  290. L"Error 0x%x caught while processing query\n",
  291. status );
  292. }
  293. }
  294. }
  295. }
  296. break;
  297. }
  298. SetThreadLocale(SaveLCID);
  299. BOOL fCaughtException = FALSE;
  300. //
  301. // Try to bind to language object by looking up registry and get
  302. // the error message HTX file associated with this class of error.
  303. //
  304. TRY
  305. {
  306. CWebLangLocator langreg( locale );
  307. WCHAR * wcsErrorFile = 0;
  308. if ( langreg.LocaleFound() )
  309. {
  310. //
  311. // If the locale was found in the registry, get the error message
  312. // file associated with this language.
  313. //
  314. switch (eErrorClass)
  315. {
  316. case eIDQParseError:
  317. case eIDQPlistError:
  318. wcsErrorFile = langreg.GetIDQErrorFile();
  319. break;
  320. case eHTXParseError:
  321. wcsErrorFile = langreg.GetHTXErrorFile();
  322. break;
  323. case eRestrictionParseError:
  324. wcsErrorFile = langreg.GetRestrictionErrorFile();
  325. break;
  326. default:
  327. wcsErrorFile = langreg.GetDefaultErrorFile();
  328. break;
  329. }
  330. }
  331. if ( ( 0 != pVariableSet ) &&
  332. ( 0 != pOutputFormat ) &&
  333. ( 0 != wcsErrorFile ) &&
  334. ( wcslen(wcsErrorFile) > 0 ) )
  335. {
  336. //
  337. // Set CiErrorMessage and CiErrorNumber.
  338. //
  339. // The variables won't own the memory for the strings;
  340. // the pointers will be reset later.
  341. //
  342. PROPVARIANT propVariant;
  343. propVariant.vt = VT_LPWSTR;
  344. propVariant.pwszVal = awcsErrorMessage;
  345. pVariableSet->SetVariable( ISAPI_CI_ERROR_MESSAGE,
  346. &propVariant,
  347. 0 );
  348. WCHAR achErrorNumber[11];
  349. swprintf( achErrorNumber, L"0x%8x", status );
  350. propVariant.pwszVal = achErrorNumber;
  351. pVariableSet->SetVariable( ISAPI_CI_ERROR_NUMBER,
  352. &propVariant,
  353. 0 );
  354. WCHAR wcsPhysicalPath[_MAX_PATH];
  355. ULONG cwcVirtualPath = wcslen(wcsErrorFile) + 1;
  356. XPtrST<WCHAR> wcsVirtualPath( new WCHAR[cwcVirtualPath] );
  357. //
  358. // We could have a virtual root or a physical root
  359. // All virtual roots begin with a "/".
  360. //
  361. if (wcsErrorFile[0] == L'/')
  362. {
  363. //
  364. // Ask the web server to convert the virtual path to our error
  365. // message file to a physical path.
  366. //
  367. webServer.GetPhysicalPath( wcsErrorFile, wcsPhysicalPath, _MAX_PATH );
  368. RtlCopyMemory( wcsVirtualPath.GetPointer(),
  369. wcsErrorFile,
  370. cwcVirtualPath*sizeof(WCHAR) );
  371. }
  372. else
  373. {
  374. // simply copy the path to physical path. It has to be a physical
  375. // path. If not, it will result in an error later.
  376. wcscpy(wcsPhysicalPath, wcsErrorFile);
  377. }
  378. CSecurityIdentity securityStub;
  379. CHTXFile htxFile( wcsVirtualPath,
  380. pOutputFormat->CodePage(),
  381. securityStub,
  382. pOutputFormat->GetServerInstance() );
  383. ciGibDebugOut((DEB_ITRACE, "File is: %ws\n", wcsPhysicalPath));
  384. htxFile.ParseFile( wcsPhysicalPath, *pVariableSet, webServer );
  385. htxFile.GetHeader( vString, *pVariableSet, *pOutputFormat );
  386. }
  387. else
  388. {
  389. vString.StrCat( L"<HTML>" );
  390. HTMLEscapeW( awcsErrorMessage,
  391. vString,
  392. pOutputFormat->CodePage() );
  393. }
  394. }
  395. CATCH ( CException, e )
  396. {
  397. fCaughtException = TRUE;
  398. }
  399. END_CATCH
  400. TRY
  401. {
  402. // Extending the vstring can fail
  403. if ( fCaughtException )
  404. {
  405. vString.StrCat( L"<HTML>" );
  406. HTMLEscapeW( awcsErrorMessage,
  407. vString,
  408. pOutputFormat->CodePage() );
  409. }
  410. // These can fail if the variable wasn't set above
  411. if ( pVariableSet )
  412. {
  413. PROPVARIANT propVariant;
  414. propVariant.vt = VT_EMPTY;
  415. pVariableSet->SetVariable( ISAPI_CI_ERROR_MESSAGE,
  416. &propVariant,
  417. 0 );
  418. pVariableSet->SetVariable( ISAPI_CI_ERROR_NUMBER,
  419. &propVariant,
  420. 0 );
  421. }
  422. }
  423. CATCH ( CException, e )
  424. {
  425. // give up
  426. }
  427. END_CATCH
  428. } //GetErrorPageNoThrow
  429. //+---------------------------------------------------------------------------
  430. //
  431. // Function: GetErrorPageNoThrow - public
  432. //
  433. // Synposis: Generates an error page based on the error parameters passed.
  434. // The error description is already available.
  435. //
  436. // Arguments: [scError] - error SCODE generated
  437. // [pwszErrorMessage] - description provided by ole-db error mechanism
  438. // [pVariableSet] - replaceable parameters which generated the error
  439. // [pOutputFormat] - format of dates & numbers
  440. // [locale] - locale of the browser
  441. // [webServer] - the web server
  442. // [vString] - virtual string to contain error code
  443. //
  444. // History: 08-May-97 KrishnaN Created
  445. //
  446. //----------------------------------------------------------------------------
  447. void GetErrorPageNoThrow( int eErrorClass,
  448. SCODE scError,
  449. WCHAR const * pwszErrorMessage,
  450. CVariableSet * pVariableSet,
  451. COutputFormat * pOutputFormat,
  452. LCID locale,
  453. CWebServer & webServer,
  454. CVirtualString & vString
  455. )
  456. {
  457. BOOL fCaughtException = FALSE;
  458. //
  459. // Try to bind to language object by looking up registry and get
  460. // the error message HTX file associated with this class of error.
  461. //
  462. TRY
  463. {
  464. //
  465. // If the error was the result of an access denied problem, then simply
  466. // return a 401 error to the browser
  467. //
  468. //
  469. // Generate the Win32 error code by removing the facility code (7) and
  470. // the error bit.
  471. //
  472. ULONG Win32status = scError;
  473. if ( (Win32status & (FACILITY_WIN32 << 16)) == (FACILITY_WIN32 << 16) )
  474. {
  475. Win32status &= ~( 0x80000000 | (FACILITY_WIN32 << 16) );
  476. }
  477. if ( (STATUS_ACCESS_DENIED == scError) ||
  478. (STATUS_NETWORK_ACCESS_DENIED == scError) ||
  479. (ERROR_ACCESS_DENIED == Win32status) ||
  480. (ERROR_INVALID_ACCESS == Win32status) ||
  481. (ERROR_NETWORK_ACCESS_DENIED == Win32status)
  482. )
  483. {
  484. ciGibDebugOut(( DEB_WARN, "mapping 0x%x to 401 access denied\n", scError ));
  485. ReturnServerError( HTTP_STATUS_DENIED, webServer );
  486. return;
  487. }
  488. CWebLangLocator langreg( locale );
  489. WCHAR * wcsErrorFile = 0;
  490. if ( langreg.LocaleFound() )
  491. {
  492. //
  493. // If the locale was found in the registry, get the error message
  494. // file associated with this language.
  495. //
  496. switch (eErrorClass)
  497. {
  498. case eIDQParseError:
  499. case eIDQPlistError:
  500. wcsErrorFile = langreg.GetIDQErrorFile();
  501. break;
  502. case eHTXParseError:
  503. wcsErrorFile = langreg.GetHTXErrorFile();
  504. break;
  505. case eRestrictionParseError:
  506. wcsErrorFile = langreg.GetRestrictionErrorFile();
  507. break;
  508. default:
  509. wcsErrorFile = langreg.GetDefaultErrorFile();
  510. break;
  511. }
  512. }
  513. if ( ( 0 != pVariableSet ) &&
  514. ( 0 != pOutputFormat ) &&
  515. ( 0 != wcsErrorFile ) &&
  516. ( wcslen(wcsErrorFile) > 0 ) )
  517. {
  518. //
  519. // Set CiErrorMessage and CiErrorNumber.
  520. //
  521. // The variables won't own the memory for the strings;
  522. // the pointers will be reset later.
  523. //
  524. PROPVARIANT propVariant;
  525. propVariant.vt = VT_LPWSTR;
  526. propVariant.pwszVal = (LPWSTR)pwszErrorMessage;
  527. pVariableSet->SetVariable( ISAPI_CI_ERROR_MESSAGE,
  528. &propVariant,
  529. 0 );
  530. WCHAR achErrorNumber[11];
  531. swprintf( achErrorNumber, L"0x%8x", scError );
  532. propVariant.pwszVal = achErrorNumber;
  533. pVariableSet->SetVariable( ISAPI_CI_ERROR_NUMBER,
  534. &propVariant,
  535. 0 );
  536. WCHAR wcsPhysicalPath[_MAX_PATH];
  537. ULONG cwcVirtualPath = wcslen(wcsErrorFile) + 1;
  538. XPtrST<WCHAR> wcsVirtualPath( new WCHAR[cwcVirtualPath] );
  539. //
  540. // We could have a virtual root or a physical root
  541. // All virtual roots begin with a "/".
  542. //
  543. if (wcsErrorFile[0] == L'/')
  544. {
  545. //
  546. // Ask the web server to convert the virtual path to our error
  547. // message file to a physical path.
  548. //
  549. webServer.GetPhysicalPath( wcsErrorFile, wcsPhysicalPath, _MAX_PATH );
  550. RtlCopyMemory( wcsVirtualPath.GetPointer(),
  551. wcsErrorFile,
  552. cwcVirtualPath*sizeof(WCHAR) );
  553. }
  554. else
  555. {
  556. // simply copy the path to physical path. It has to be a physical
  557. // path. If not, it will result in an error later.
  558. wcscpy(wcsPhysicalPath, wcsErrorFile);
  559. }
  560. CSecurityIdentity securityStub;
  561. CHTXFile htxFile( wcsVirtualPath,
  562. pOutputFormat->CodePage(),
  563. securityStub,
  564. pOutputFormat->GetServerInstance() );
  565. ciGibDebugOut((DEB_ITRACE, "File is: %ws\n", wcsPhysicalPath));
  566. htxFile.ParseFile( wcsPhysicalPath, *pVariableSet, webServer );
  567. htxFile.GetHeader( vString, *pVariableSet, *pOutputFormat );
  568. }
  569. else
  570. {
  571. vString.StrCat( L"<HTML>" );
  572. vString.StrCat( pwszErrorMessage );
  573. }
  574. }
  575. CATCH ( CException, e )
  576. {
  577. fCaughtException = TRUE;
  578. }
  579. END_CATCH
  580. TRY
  581. {
  582. // Extending the vstring can fail
  583. if ( fCaughtException )
  584. {
  585. vString.StrCat( L"<HTML>" );
  586. vString.StrCat( pwszErrorMessage );
  587. }
  588. // These can fail if the variable wasn't set above
  589. if ( pVariableSet )
  590. {
  591. PROPVARIANT propVariant;
  592. propVariant.vt = VT_EMPTY;
  593. pVariableSet->SetVariable( ISAPI_CI_ERROR_MESSAGE,
  594. &propVariant,
  595. 0 );
  596. pVariableSet->SetVariable( ISAPI_CI_ERROR_NUMBER,
  597. &propVariant,
  598. 0 );
  599. }
  600. }
  601. CATCH ( CException, e )
  602. {
  603. // give up
  604. }
  605. END_CATCH
  606. } //GetErrorPageNoThrow
  607. enum
  608. {
  609. eAccessDeniedMsg = 0,
  610. eServerBusyMsg,
  611. eServerErrorMsg,
  612. };
  613. #define MAX_SERVER_ERROR_MSGSIZE 100
  614. WCHAR g_awszServerErrorMsgs [3] [MAX_SERVER_ERROR_MSGSIZE] =
  615. {
  616. L"Access denied.\r\n",
  617. L"Server too busy.\r\n",
  618. L"Unexpected server error.\r\n",
  619. };
  620. //+---------------------------------------------------------------------------
  621. //
  622. // Function: ReturnServerError - public
  623. //
  624. // Synposis: Generates an error page for an HTTP error code.
  625. //
  626. // Arguments: [httpError] - the HTTP status code
  627. // [webServer] - the web server
  628. //
  629. // Notes: This is used when the server is too busy; it should be a
  630. // very low-overhead path.
  631. //
  632. // History: 12 Aug 1997 AlanW Created
  633. //
  634. //----------------------------------------------------------------------------
  635. void ReturnServerError( ULONG httpError,
  636. CWebServer & webServer )
  637. {
  638. char const * pszHeader = "";
  639. int iMessage = 0;
  640. switch (httpError)
  641. {
  642. case HTTP_STATUS_DENIED:
  643. pszHeader = "401 Access denied";
  644. iMessage = eAccessDeniedMsg;
  645. break;
  646. case HTTP_STATUS_SERVICE_UNAVAIL:
  647. pszHeader = "503 Server busy";
  648. iMessage = eServerBusyMsg;
  649. break;
  650. default:
  651. ciGibDebugOut(( DEB_ERROR, "unexpected server error status %d\n", httpError ));
  652. httpError = HTTP_STATUS_SERVER_ERROR;
  653. iMessage = eServerErrorMsg;
  654. break;
  655. }
  656. webServer.WriteHeader( 0, pszHeader );
  657. WCHAR * pwszMessage = g_awszServerErrorMsgs[iMessage];
  658. webServer.WriteClient( pwszMessage );
  659. webServer.SetHttpStatus( httpError );
  660. }
  661. //+---------------------------------------------------------------------------
  662. //
  663. // Function: LoadServerErrors - public
  664. //
  665. // Synposis: Load messages for server errors.
  666. //
  667. // Arguments: -NONE-
  668. //
  669. // Notes:
  670. //
  671. // History: 29 Sep 1997 AlanW Created
  672. //
  673. //----------------------------------------------------------------------------
  674. void LoadServerErrors( )
  675. {
  676. unsigned iMessage = eAccessDeniedMsg;
  677. SCODE scMessage = MSG_CI_ACCESS_DENIED;
  678. const unsigned cMessages = sizeof g_awszServerErrorMsgs /
  679. sizeof g_awszServerErrorMsgs[0];
  680. while (iMessage < cMessages)
  681. {
  682. FormatMessage( FORMAT_MESSAGE_FROM_HMODULE,
  683. GetModuleHandle(L"idq.dll"),
  684. scMessage,
  685. GetSystemDefaultLangID(),
  686. &g_awszServerErrorMsgs [iMessage][0],
  687. MAX_SERVER_ERROR_MSGSIZE,
  688. 0 );
  689. scMessage++;
  690. iMessage++;
  691. }
  692. }