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.

608 lines
12 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. custerr.cxx
  5. Abstract:
  6. Custom Error Utility
  7. Author:
  8. Keith Moore (keithmo) 04-Sep-1997
  9. Revision History:
  10. --*/
  11. #include "precomp.hxx"
  12. #pragma hdrstop
  13. //
  14. // Private constants.
  15. //
  16. #define TEST_HRESULT(api,hr,fatal) \
  17. if( FAILED(hr) ) { \
  18. \
  19. wprintf( \
  20. L"%S:%lu failed, error %lx %S\n", \
  21. (api), \
  22. __LINE__, \
  23. (result), \
  24. (fatal) \
  25. ? "ABORTING" \
  26. : "CONTINUING" \
  27. ); \
  28. \
  29. if( fatal ) { \
  30. \
  31. goto cleanup; \
  32. \
  33. } \
  34. \
  35. } else
  36. #define ALLOC( cb ) (PVOID)LocalAlloc( LPTR, (cb) )
  37. #define FREE( ptr ) (VOID)LocalFree( (HLOCAL)(ptr) )
  38. //
  39. // Private types.
  40. //
  41. //
  42. // Private globals.
  43. //
  44. //
  45. // Private prototypes.
  46. //
  47. VOID
  48. Usage(
  49. VOID
  50. );
  51. VOID
  52. SetCustomError(
  53. IMSAdminBase * AdmCom,
  54. LPWSTR MetaPath,
  55. LPWSTR FileName
  56. );
  57. VOID
  58. DumpCustomError(
  59. IMSAdminBase * AdmCom,
  60. LPWSTR MetaPath
  61. );
  62. //
  63. // Public functions.
  64. //
  65. INT
  66. __cdecl
  67. wmain(
  68. INT argc,
  69. LPWSTR argv[]
  70. )
  71. {
  72. HRESULT result;
  73. IMSAdminBase * admCom;
  74. LPWSTR metaPath;
  75. LPWSTR fileName;
  76. LPWSTR arg;
  77. INT i;
  78. //
  79. // Setup locals so we know how to cleanup on exit.
  80. //
  81. admCom = NULL;
  82. //
  83. // Establish defaults.
  84. //
  85. metaPath = L"w3svc";
  86. fileName = NULL;
  87. //
  88. // Validate the command line arguments.
  89. //
  90. for( i = 1 ; i < argc ; i++ ) {
  91. arg = argv[i];
  92. if( arg[0] != L'-' ||
  93. arg[1] == L'\0' ||
  94. arg[2] != L':' ||
  95. arg[3] == L'\0' ) {
  96. Usage();
  97. return 1;
  98. }
  99. switch( arg[1] ) {
  100. case L'h' :
  101. case L'H' :
  102. case L'?' :
  103. Usage();
  104. return 1;
  105. case L'p' :
  106. case L'P' :
  107. metaPath = arg + 3;
  108. break;
  109. case L'f' :
  110. case L'F' :
  111. fileName = arg + 3;
  112. break;
  113. default :
  114. Usage();
  115. return 1;
  116. }
  117. }
  118. //
  119. // Initialize COM.
  120. //
  121. result = CoInitializeEx(
  122. NULL,
  123. COINIT_MULTITHREADED
  124. );
  125. TEST_HRESULT( "CoInitializeEx()", result, TRUE );
  126. //
  127. // Get the admin object.
  128. //
  129. result = MdGetAdminObject( &admCom );
  130. TEST_HRESULT( "MdGetAdminObject()", result, TRUE );
  131. //
  132. // Do it.
  133. //
  134. if( fileName == NULL ) {
  135. DumpCustomError( admCom, metaPath );
  136. } else {
  137. SetCustomError( admCom, metaPath, fileName );
  138. }
  139. cleanup:
  140. //
  141. // Release the admin object.
  142. //
  143. if( admCom != NULL ) {
  144. result = MdReleaseAdminObject( admCom );
  145. TEST_HRESULT( "MdReleaseAdminObject()", result, FALSE );
  146. }
  147. //
  148. // Shutdown COM.
  149. //
  150. CoUninitialize();
  151. return 0;
  152. } // main
  153. //
  154. // Private functions.
  155. //
  156. VOID
  157. Usage(
  158. VOID
  159. )
  160. {
  161. wprintf(
  162. L"use: custerr [options]\n"
  163. L"\n"
  164. L"valid options are:\n"
  165. L"\n"
  166. L" -p:meta_path\n"
  167. L" -f:error_file\n"
  168. L"\n"
  169. );
  170. } // Usage
  171. VOID
  172. SetCustomError(
  173. IMSAdminBase * AdmCom,
  174. LPWSTR MetaPath,
  175. LPWSTR FileName
  176. )
  177. {
  178. HANDLE fileHandle;
  179. DWORD length;
  180. DWORD lengthHigh;
  181. DWORD bytesRemaining;
  182. HANDLE mappingHandle;
  183. PCHAR view;
  184. PCHAR viewScan;
  185. PWCHAR multiSz;
  186. PWCHAR multiSzScan;
  187. HRESULT result;
  188. BOOL gotOne;
  189. METADATA_HANDLE metaHandle;
  190. METADATA_RECORD metaRecord;
  191. DWORD err;
  192. CHAR ansiFileName[MAX_PATH];
  193. WCHAR fullMetaPath[MAX_PATH];
  194. //
  195. // Setup locals so we know how to cleanup on exit.
  196. //
  197. fileHandle = INVALID_HANDLE_VALUE;
  198. mappingHandle = NULL;
  199. view = NULL;
  200. multiSz = NULL;
  201. metaHandle = 0;
  202. //
  203. // Open the file, get its length.
  204. //
  205. sprintf(
  206. ansiFileName,
  207. "%S",
  208. FileName
  209. );
  210. fileHandle = CreateFileA(
  211. ansiFileName,
  212. GENERIC_READ,
  213. FILE_SHARE_READ,
  214. NULL,
  215. OPEN_EXISTING,
  216. FILE_ATTRIBUTE_NORMAL,
  217. NULL
  218. );
  219. if( fileHandle == INVALID_HANDLE_VALUE ) {
  220. err = GetLastError();
  221. wprintf(
  222. L"custerr: cannot open %s, error %lu\n",
  223. FileName,
  224. err
  225. );
  226. goto cleanup;
  227. }
  228. length = GetFileSize( fileHandle, &lengthHigh );
  229. if( length == 0xFFFFFFFF || lengthHigh > 0 ) {
  230. err = GetLastError();
  231. wprintf(
  232. L"custerr: cannot read %s, error %lu\n",
  233. FileName,
  234. err
  235. );
  236. goto cleanup;
  237. }
  238. //
  239. // Map it in.
  240. //
  241. mappingHandle = CreateFileMapping(
  242. fileHandle,
  243. NULL,
  244. PAGE_READONLY,
  245. 0,
  246. 0,
  247. NULL
  248. );
  249. if( mappingHandle == NULL ) {
  250. err = GetLastError();
  251. wprintf(
  252. L"custerr: cannot read %s, error %lu\n",
  253. FileName,
  254. err
  255. );
  256. goto cleanup;
  257. }
  258. view = (PCHAR)MapViewOfFile(
  259. mappingHandle,
  260. FILE_MAP_READ,
  261. 0,
  262. 0,
  263. 0
  264. );
  265. if( view == NULL ) {
  266. err = GetLastError();
  267. wprintf(
  268. L"custerr: cannot read %s, error %lu\n",
  269. FileName,
  270. err
  271. );
  272. goto cleanup;
  273. }
  274. //
  275. // Allocate the multisz buffer. Assume it will be roughly the same
  276. // size as the file.
  277. //
  278. multiSz = (PWCHAR) ALLOC( length * sizeof(WCHAR) );
  279. if( multiSz == NULL ) {
  280. wprintf(
  281. L"custerr: not enough memory\n"
  282. );
  283. goto cleanup;
  284. }
  285. //
  286. // Build the multisz.
  287. //
  288. viewScan = view;
  289. multiSzScan = multiSz;
  290. bytesRemaining = length;
  291. while( bytesRemaining > 0 ) {
  292. //
  293. // Skip leading whitespace.
  294. //
  295. while( bytesRemaining > 0 &&
  296. ( *viewScan == ' ' || *viewScan == '\t' ||
  297. *viewScan == '\r' || *viewScan == '\n' ) ) {
  298. bytesRemaining--;
  299. viewScan++;
  300. }
  301. //
  302. // Copy it over, collapse embedded whitespace, perform
  303. // cheesy ANSI-to-UNICODE conversion.
  304. //
  305. gotOne = FALSE;
  306. while( bytesRemaining > 0 &&
  307. ( *viewScan != '\r' && *viewScan != '\n' ) ) {
  308. bytesRemaining--;
  309. if( *viewScan != ' ' && *viewScan != '\t' ) {
  310. *multiSzScan++ = (WCHAR)*viewScan;
  311. gotOne = TRUE;
  312. }
  313. viewScan++;
  314. }
  315. if( gotOne ) {
  316. *multiSzScan++ = L'\0';
  317. }
  318. }
  319. *multiSzScan++ = L'\0';
  320. //
  321. // Open the metabase.
  322. //
  323. swprintf(
  324. fullMetaPath,
  325. L"/%S/%s",
  326. IIS_MD_LOCAL_MACHINE_PATH,
  327. MetaPath
  328. );
  329. result = AdmCom->OpenKey(
  330. METADATA_MASTER_ROOT_HANDLE,
  331. fullMetaPath,
  332. METADATA_PERMISSION_WRITE,
  333. METABASE_OPEN_TIMEOUT,
  334. &metaHandle
  335. );
  336. TEST_HRESULT( "AdmCom->OpenKey()", result, TRUE );
  337. //
  338. // Write the new custom error value.
  339. //
  340. length = ( multiSzScan - multiSz ) * sizeof(WCHAR);
  341. INITIALIZE_METADATA_RECORD(
  342. &metaRecord,
  343. MD_CUSTOM_ERROR,
  344. METADATA_INHERIT,
  345. IIS_MD_UT_SERVER,
  346. MULTISZ_METADATA,
  347. length,
  348. multiSz
  349. );
  350. result = AdmCom->SetData(
  351. metaHandle,
  352. L"",
  353. &metaRecord
  354. );
  355. TEST_HRESULT( "AdmCom->SetData()", result, TRUE );
  356. cleanup:
  357. if( metaHandle != 0 ) {
  358. AdmCom->CloseKey( metaHandle );
  359. }
  360. if( multiSz != NULL ) {
  361. FREE( multiSz );
  362. }
  363. if( view != NULL ) {
  364. UnmapViewOfFile( view );
  365. }
  366. if( mappingHandle != NULL ) {
  367. CloseHandle( mappingHandle );
  368. }
  369. if( fileHandle != INVALID_HANDLE_VALUE ) {
  370. CloseHandle( fileHandle );
  371. }
  372. } // SetCustomError
  373. VOID
  374. DumpCustomError(
  375. IMSAdminBase * AdmCom,
  376. LPWSTR MetaPath
  377. )
  378. {
  379. HRESULT result;
  380. METADATA_HANDLE metaHandle;
  381. METADATA_RECORD metaRecord;
  382. DWORD bytesRequired;
  383. PWCHAR buffer;
  384. PWCHAR bufferScan;
  385. WCHAR fullMetaPath[MAX_PATH];
  386. //
  387. // Setup locals so we know how to cleanup on exit.
  388. //
  389. metaHandle = 0;
  390. buffer = NULL;
  391. //
  392. // Open the metabase.
  393. //
  394. swprintf(
  395. fullMetaPath,
  396. L"/%S/%s",
  397. IIS_MD_LOCAL_MACHINE_PATH,
  398. MetaPath
  399. );
  400. result = AdmCom->OpenKey(
  401. METADATA_MASTER_ROOT_HANDLE,
  402. fullMetaPath,
  403. METADATA_PERMISSION_READ,
  404. METABASE_OPEN_TIMEOUT,
  405. &metaHandle
  406. );
  407. TEST_HRESULT( "AdmCom->OpenKey()", result, TRUE );
  408. //
  409. // Get the data size.
  410. //
  411. INITIALIZE_METADATA_RECORD(
  412. &metaRecord,
  413. MD_CUSTOM_ERROR,
  414. METADATA_INHERIT,
  415. IIS_MD_UT_SERVER,
  416. MULTISZ_METADATA,
  417. 2,
  418. L""
  419. );
  420. result = AdmCom->GetData(
  421. metaHandle,
  422. L"",
  423. &metaRecord,
  424. &bytesRequired
  425. );
  426. if( result != RETURNCODETOHRESULT( ERROR_INSUFFICIENT_BUFFER ) ) {
  427. TEST_HRESULT( "AdmCom->GetData()", result, TRUE );
  428. }
  429. //
  430. // Allocate our data buffer.
  431. //
  432. buffer = (PWCHAR)ALLOC( bytesRequired );
  433. if( buffer == NULL ) {
  434. wprintf(
  435. L"custerr: not enough memory\n"
  436. );
  437. goto cleanup;
  438. }
  439. //
  440. // Now actually read it.
  441. //
  442. INITIALIZE_METADATA_RECORD(
  443. &metaRecord,
  444. MD_CUSTOM_ERROR,
  445. METADATA_INHERIT,
  446. IIS_MD_UT_SERVER,
  447. MULTISZ_METADATA,
  448. bytesRequired,
  449. buffer
  450. );
  451. result = AdmCom->GetData(
  452. metaHandle,
  453. L"",
  454. &metaRecord,
  455. &bytesRequired
  456. );
  457. TEST_HRESULT( "AdmCom->GetData()", result, TRUE );
  458. //
  459. // Print it.
  460. //
  461. bufferScan = buffer;
  462. while( *bufferScan != L'\0' ) {
  463. wprintf( L"%s\n", bufferScan );
  464. bufferScan += wcslen( bufferScan ) + 1;
  465. }
  466. cleanup:
  467. if( buffer != NULL ) {
  468. FREE( buffer );
  469. }
  470. if( metaHandle != 0 ) {
  471. AdmCom->CloseKey( metaHandle );
  472. }
  473. } // DumpCustomError