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.

570 lines
20 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. hashgen.cpp
  5. Abstract:
  6. Table Generator for hhead.cxx, which contains all known HTTP headers for wininet project.
  7. This is also the location where all known HTTP headers must be added.
  8. Author:
  9. Arthur Bierer (arthurbi) 12-Jan-1998
  10. Revision History:
  11. --*/
  12. //
  13. // Instructions for adding new HTTP header:
  14. // 1. Update wininet.w and rebuild wininet.h with new HTTP_QUERY_ code
  15. // 2. Add/Edit header to this file/program, hashgen.cpp with the
  16. // new header string (see Items[] array below)
  17. // 3. Compile new hashgen.exe, Execute with -o, write down a good seed
  18. // note that this may take all night to find a good seed which
  19. // give a nice smaller table size. (note this can be skipped if
  20. // you just need a quick table for dev purposes)
  21. // 4. Re-Execute hashgen.exe with -b# set with your seed to generate
  22. // hhead.cxx
  23. // 5. Transfer new hhead.cxx file to wininet\http
  24. // 6. Update const defines MAX_HEADER_HASH_SIZE and HEADER_HASH_SEED
  25. // from new hhead.cxx to wininet\http\headers.h
  26. // 7. Transfer and checkin hashgen.cpp, wininet.w, headers,h, hhead.cxx
  27. // in their appropriate directories.
  28. //
  29. //
  30. // Includes...
  31. //
  32. #include <windows.h>
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <search.h>
  36. #include <wininet.h>
  37. //
  38. // macros
  39. //
  40. #define IS_ARG(c) ((c) == '-')
  41. #define DIM(x) (sizeof(x) / sizeof(x[0]))
  42. #define ENUMDEF(x, y) ,x, #x, #y
  43. #define OUTPUT_CODE_FILE "hhead.cxx"
  44. #define MAX_SIZE_HASHARRAY_TO_ATTEMPT 600
  45. #define UNKNOWN_HASH_ENTRY 0 // character to put in array when when its not valid
  46. //
  47. // Items - This is the array that must be edited for Wininet to process new
  48. // HTTP headers
  49. //
  50. // Things to keep in mind before you add to this array
  51. // 1. Headers are Alphatized for convience sake
  52. // 2. All NULL entries MUST be at the end of the array
  53. // 3. All HTTP_QUERY_* codes in wininet.h MUST have an entry even if they are not strings
  54. // 4. Entries are as follows:
  55. // header string, HTTP_QUERY_* code in wininet.h, flags used in wininet\http\query.cxx
  56. // 5. All entries must be in lowercase.
  57. //
  58. struct Item
  59. {
  60. char *ptok;
  61. DWORD id;
  62. char *pidName;
  63. char *pFlagsName;
  64. } Items[] =
  65. {
  66. { "Accept" ENUMDEF(HTTP_QUERY_ACCEPT, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  67. { "Accept-Charset" ENUMDEF(HTTP_QUERY_ACCEPT_CHARSET, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  68. { "Accept-Encoding" ENUMDEF(HTTP_QUERY_ACCEPT_ENCODING, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  69. { "Accept-Language" ENUMDEF(HTTP_QUERY_ACCEPT_LANGUAGE, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  70. { "Accept-Ranges" ENUMDEF(HTTP_QUERY_ACCEPT_RANGES, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  71. { "Age" ENUMDEF(HTTP_QUERY_AGE, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  72. { "Allow" ENUMDEF(HTTP_QUERY_ALLOW, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  73. { "Authorization" ENUMDEF(HTTP_QUERY_AUTHORIZATION, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  74. { "Cache-Control" ENUMDEF(HTTP_QUERY_CACHE_CONTROL, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  75. { "Connection" ENUMDEF(HTTP_QUERY_CONNECTION, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  76. { "Content-Base" ENUMDEF(HTTP_QUERY_CONTENT_BASE, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  77. { "Content-Description" ENUMDEF(HTTP_QUERY_CONTENT_DESCRIPTION, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  78. { "Content-Disposition" ENUMDEF(HTTP_QUERY_CONTENT_DISPOSITION, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  79. { "Content-Encoding" ENUMDEF(HTTP_QUERY_CONTENT_ENCODING, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  80. { "Content-Id" ENUMDEF(HTTP_QUERY_CONTENT_ID, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  81. { "Content-Language" ENUMDEF(HTTP_QUERY_CONTENT_LANGUAGE, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  82. { "Content-Length" ENUMDEF(HTTP_QUERY_CONTENT_LENGTH, (HTTP_QUERY_FLAG_REQUEST_HEADERS | HTTP_QUERY_FLAG_NUMBER)) },
  83. { "Content-Location" ENUMDEF(HTTP_QUERY_CONTENT_LOCATION, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  84. { "Content-Md5" ENUMDEF(HTTP_QUERY_CONTENT_MD5, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  85. { "Content-Range" ENUMDEF(HTTP_QUERY_CONTENT_RANGE, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  86. { "Content-Transfer-Encoding" ENUMDEF(HTTP_QUERY_CONTENT_TRANSFER_ENCODING, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  87. { "Content-Type" ENUMDEF(HTTP_QUERY_CONTENT_TYPE, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  88. { "Cookie" ENUMDEF(HTTP_QUERY_COOKIE, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  89. { "Cost" ENUMDEF(HTTP_QUERY_COST, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  90. { "Date" ENUMDEF(HTTP_QUERY_DATE, (HTTP_QUERY_FLAG_REQUEST_HEADERS | HTTP_QUERY_FLAG_SYSTEMTIME)) },
  91. { "Derived-From" ENUMDEF(HTTP_QUERY_DERIVED_FROM, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  92. { "Etag" ENUMDEF(HTTP_QUERY_ETAG, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  93. { "Expect" ENUMDEF(HTTP_QUERY_EXPECT, (HTTP_QUERY_FLAG_REQUEST_HEADERS | HTTP_QUERY_FLAG_SYSTEMTIME)) },
  94. { "Expires" ENUMDEF(HTTP_QUERY_EXPIRES, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  95. { "Forwarded" ENUMDEF(HTTP_QUERY_FORWARDED, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  96. { "From" ENUMDEF(HTTP_QUERY_FROM, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  97. { "Host" ENUMDEF(HTTP_QUERY_HOST, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  98. { "If-Modified-Since" ENUMDEF(HTTP_QUERY_IF_MODIFIED_SINCE, (HTTP_QUERY_FLAG_REQUEST_HEADERS | HTTP_QUERY_FLAG_SYSTEMTIME)) },
  99. { "If-Match" ENUMDEF(HTTP_QUERY_IF_MATCH, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  100. { "If-None-Match" ENUMDEF(HTTP_QUERY_IF_NONE_MATCH, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  101. { "If-Range" ENUMDEF(HTTP_QUERY_IF_RANGE, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  102. { "If-Unmodified-Since" ENUMDEF(HTTP_QUERY_IF_UNMODIFIED_SINCE, (HTTP_QUERY_FLAG_REQUEST_HEADERS | HTTP_QUERY_FLAG_SYSTEMTIME)) },
  103. { "Last-Modified" ENUMDEF(HTTP_QUERY_LAST_MODIFIED, (HTTP_QUERY_FLAG_REQUEST_HEADERS | HTTP_QUERY_FLAG_SYSTEMTIME)) },
  104. { "Link" ENUMDEF(HTTP_QUERY_LINK, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  105. { "Location" ENUMDEF(HTTP_QUERY_LOCATION, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  106. { "Mime-Version" ENUMDEF(HTTP_QUERY_MIME_VERSION, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  107. { "Max-Forwards" ENUMDEF(HTTP_QUERY_MAX_FORWARDS, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  108. { "Message-id" ENUMDEF(HTTP_QUERY_MESSAGE_ID, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  109. { "Ms-Echo-Request" ENUMDEF(HTTP_QUERY_ECHO_REQUEST, 0) },
  110. { "Ms-Echo-Reply" ENUMDEF(HTTP_QUERY_ECHO_REPLY, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  111. { "Orig-Uri" ENUMDEF(HTTP_QUERY_ORIG_URI, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  112. { "Pragma" ENUMDEF(HTTP_QUERY_PRAGMA, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  113. { "Proxy-Authenticate" ENUMDEF(HTTP_QUERY_PROXY_AUTHENTICATE, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  114. { "Proxy-Authorization" ENUMDEF(HTTP_QUERY_PROXY_AUTHORIZATION, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  115. { "Proxy-Connection" ENUMDEF(HTTP_QUERY_PROXY_CONNECTION, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  116. { "Proxy-Support" ENUMDEF(HTTP_QUERY_PROXY_SUPPORT, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  117. { "Public" ENUMDEF(HTTP_QUERY_PUBLIC, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  118. { "Range" ENUMDEF(HTTP_QUERY_RANGE, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  119. { "Referer" ENUMDEF(HTTP_QUERY_REFERER, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  120. { "Refresh" ENUMDEF(HTTP_QUERY_REFRESH, 0) },
  121. { "Retry-After" ENUMDEF(HTTP_QUERY_RETRY_AFTER, (HTTP_QUERY_FLAG_REQUEST_HEADERS | HTTP_QUERY_FLAG_SYSTEMTIME)) },
  122. { "Server" ENUMDEF(HTTP_QUERY_SERVER, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  123. { "Set-Cookie" ENUMDEF(HTTP_QUERY_SET_COOKIE, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  124. { "Title" ENUMDEF(HTTP_QUERY_TITLE, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  125. { "Transfer-Encoding" ENUMDEF(HTTP_QUERY_TRANSFER_ENCODING, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  126. { "Unless-Modified-Since" ENUMDEF(HTTP_QUERY_UNLESS_MODIFIED_SINCE, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  127. { "Upgrade" ENUMDEF(HTTP_QUERY_UPGRADE, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  128. { "Uri" ENUMDEF(HTTP_QUERY_URI, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  129. { "User-Agent" ENUMDEF(HTTP_QUERY_USER_AGENT, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  130. { "Vary" ENUMDEF(HTTP_QUERY_VARY, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  131. { "Via" ENUMDEF(HTTP_QUERY_VIA, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  132. { "Warning" ENUMDEF(HTTP_QUERY_WARNING, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  133. { "WWW-Authenticate" ENUMDEF(HTTP_QUERY_WWW_AUTHENTICATE, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  134. { "Authentication-Info" ENUMDEF(HTTP_QUERY_AUTHENTICATION_INFO, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  135. { "PassportURLs" ENUMDEF(HTTP_QUERY_PASSPORT_URLS, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  136. { "PassportConfig" ENUMDEF(HTTP_QUERY_PASSPORT_CONFIG, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  137. // NULL strs must be in end of array
  138. { NULL ENUMDEF(HTTP_QUERY_VERSION, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  139. { NULL ENUMDEF(HTTP_QUERY_STATUS_CODE, HTTP_QUERY_FLAG_NUMBER) },
  140. { NULL ENUMDEF(HTTP_QUERY_STATUS_TEXT, 0) },
  141. { NULL ENUMDEF(HTTP_QUERY_RAW_HEADERS, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  142. { NULL ENUMDEF(HTTP_QUERY_RAW_HEADERS_CRLF, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  143. { NULL ENUMDEF(HTTP_QUERY_REQUEST_METHOD, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  144. { NULL ENUMDEF(HTTP_QUERY_ECHO_HEADERS, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  145. { NULL ENUMDEF(HTTP_QUERY_ECHO_HEADERS_CRLF, HTTP_QUERY_FLAG_REQUEST_HEADERS) },
  146. };
  147. //
  148. // Declarations of common strings used in creating output "C" file
  149. //
  150. char szFileHeader[] =
  151. {"/*++\n\n"
  152. "Copyright (c) 1997 Microsoft Corporation\n\n"
  153. "Module Name:\n\n"
  154. " "
  155. OUTPUT_CODE_FILE
  156. "\n\n"
  157. "Abstract:\n\n"
  158. " This file contains autogenerated table values of a perfect hash function\n"
  159. " DO NOT, DO NOT EDIT THIS FILE, TO ADD HEADERS SEE hashgen.cpp\n"
  160. " Contents:\n"
  161. " GlobalKnownHeaders\n"
  162. " GlobalHeaderHashs\n\n"
  163. "Author:\n\n"
  164. " Arthur Bierer (arthurbi) 19-Dec-1997 (AND) my code generator[hashgen.exe]\n\n"
  165. "Revision History:\n\n"
  166. "--*/\n\n\n" };
  167. char szComment1[] = {
  168. "//\n"
  169. "// GlobalHeaderHashs - array of precalculated hashes on case-sensetive set of known headers.\n"
  170. "// This array must be used with the same hash function used to generate it.\n"
  171. "// Note, all entries in this array are biased (++'ed) by 1 from HTTP_QUERY_ manifests in wininet.h.\n"
  172. "// 0-ed entries indicate error values\n"
  173. "//\n\n" };
  174. char szComment2[] = {
  175. "//\n"
  176. "// GlobalKnownHeaders - array of HTTP request and response headers that we understand.\n"
  177. "// This array must be in the same order as the HTTP_QUERY_ manifests in WININET.H\n"
  178. "//\n\n"
  179. "#define HEADER_ENTRY(String, Flags, HashVal) String, sizeof(String) - 1, Flags, HashVal\n\n" };
  180. char szDef1[] = {
  181. "#ifdef HEADER_HASH_SEED\n"
  182. "#if (HEADER_HASH_SEED != %u)\n"
  183. "#error HEADER_HASH_SEED has not been updated in the header file, please copy this number to the header\n"
  184. "#endif\n"
  185. "#else\n"
  186. "#define HEADER_HASH_SEED %u\n"
  187. "#endif\n\n" };
  188. char szDef2[] = {
  189. "#ifdef MAX_HEADER_HASH_SIZE\n"
  190. "#if (MAX_HEADER_HASH_SIZE != %u)\n"
  191. "#error MAX_HEADER_HASH_SIZE has not been updated in the header file, please copy this number to the header\n"
  192. "#endif\n"
  193. "#else\n"
  194. "#define MAX_HEADER_HASH_SIZE %u\n"
  195. "#endif\n\n" };
  196. char szDef3[] = {
  197. "#ifdef HTTP_QUERY_MAX\n"
  198. "#if (HTTP_QUERY_MAX != %u)\n"
  199. "#error HTTP_QUERY_MAX is not the same as the value used in wininet.h, this indicates mismatched headers, see hashgen.cpp\n"
  200. "#endif\n"
  201. "#endif\n\n" };
  202. char szIncludes[] = {
  203. "#include <wininetp.h>\n"
  204. "#include \"httpp.h\"\n\n" };
  205. //
  206. // Hash - function used to create table,
  207. // THIS FUNCTION MUST BE THE SAME AS THE ONE USED in WININET
  208. //
  209. DWORD Hash(char *pszName, DWORD j, DWORD seed)
  210. {
  211. DWORD hash = seed;
  212. while (*pszName)
  213. {
  214. hash += (hash << 5) + *pszName++;
  215. }
  216. return (j==0) ? hash : hash % j;
  217. }
  218. //
  219. // CompareItems - a util function for qsort-ing by ID for table creation
  220. // in the output file
  221. //
  222. int __cdecl CompareItems (const void *elem1, const void *elem2 )
  223. {
  224. const struct Item *pItem1, *pItem2;
  225. pItem1 = (struct Item *) elem1;
  226. pItem2 = (struct Item *) elem2;
  227. if ( pItem1->id < pItem2->id )
  228. {
  229. return -1;
  230. }
  231. else if ( pItem1->id > pItem2->id )
  232. {
  233. return 1;
  234. }
  235. return 0;
  236. }
  237. //
  238. // usage() - print out our usage instructions to command line
  239. //
  240. void usage() {
  241. fprintf(stderr,
  242. "\n"
  243. "usage: hashgen [-m[#]] [-b[#]] [-t[#]] [-o] [-p<path>] [-f<filename>]\n"
  244. "\n"
  245. "where: -m[#] = Max hash table size to test with, default = 600\n"
  246. " -b[#] = Starting hash seed, default = 0\n"
  247. " -t[#] = Threshold of table size to halt search at, default = 200\n"
  248. " -o = Enable optimal exhaustive search mode (can take 24+ hrs)\n"
  249. " -p = Path used for output generation\n"
  250. " -f = Output filename, \"hhead.cxx\" is assumed\n"
  251. "\n"
  252. "Instructions for adding new HTTP header:\n"
  253. "\t1. Update wininet.w and rebuild wininet.h with new HTTP_QUERY_ code\n"
  254. "\t2. Add/Edit this file/program, hashgen.cpp with the new header string\n"
  255. "\t3. Compile/Execute new hashgen.exe with -o, write down a good seed\n"
  256. "\t4. Re-Execute hashgen.exe with -b# set with your seed to generate\n"
  257. "\t hhead.cxx\n"
  258. "\t5. Transfer new hhead.cxx file to wininet\\http\n"
  259. "\t6. Update const defines MAX_HEADER_HASH_SIZE and HEADER_HASH_SEED\n"
  260. "\t from new hhead.cxx to wininet\\http\\headers.h\n"
  261. "\t7. Transfer and checkin hashgen.cpp, wininet.w, headers,h, hhead.cxx\n"
  262. );
  263. exit(1);
  264. }
  265. //
  266. // MakeMeLower - Makes a lower case string using a static 255 byte array
  267. //
  268. LPSTR
  269. MakeMeLower(
  270. IN LPSTR lpszMixedCaseStr
  271. )
  272. {
  273. static CHAR szLowerCased[256];
  274. if ( lstrlen(lpszMixedCaseStr) > 255 )
  275. {
  276. fprintf(stderr, "Internal error: an HTTP header is too long\n\n");
  277. return szLowerCased;
  278. }
  279. lstrcpy( szLowerCased, lpszMixedCaseStr );
  280. CharLower(szLowerCased);
  281. return szLowerCased;
  282. }
  283. //
  284. // main - where it all gets done !!!!
  285. //
  286. void
  287. __cdecl
  288. //_CRTAPI1
  289. main(
  290. int argc,
  291. char * argv[]
  292. )
  293. {
  294. DWORD nMax = MAX_SIZE_HASHARRAY_TO_ATTEMPT;
  295. DWORD dwBestNumber = 0, dwBestSeed = 0 /*349160*/ /*4458*//*202521*/;
  296. DWORD dwSearchThreshold = 200;
  297. BOOL bFoundOne = FALSE;
  298. BOOL bFindOptimalSeed = FALSE;
  299. LPSTR szPath = "";
  300. LPSTR szFileName = OUTPUT_CODE_FILE;
  301. DWORD i, j, k;
  302. DWORD dwValidStringsInArray = 0;
  303. DWORD *pHash = new DWORD[nMax];
  304. for (--argc, ++argv; argc; --argc, ++argv) {
  305. if (IS_ARG(**argv)) {
  306. switch (*++*argv) {
  307. case '?':
  308. usage();
  309. break;
  310. case 'm':
  311. nMax = (DWORD)atoi(++*argv);
  312. break;
  313. case 'b':
  314. dwBestSeed = (DWORD)atoi(++*argv);
  315. break;
  316. case 't':
  317. dwSearchThreshold = (DWORD)atoi(++*argv);
  318. break;
  319. case 'p':
  320. szPath = ++*argv;
  321. break;
  322. case 'f':
  323. szFileName = ++*argv;
  324. break;
  325. case 'o':
  326. bFindOptimalSeed = TRUE;
  327. break;
  328. default:
  329. fprintf(stderr,"error: unrecognized command line flag: '%c'\n", **argv);
  330. usage();
  331. }
  332. } else {
  333. fprintf(stderr,"error: unrecognized command line argument: \"%s\"\n", *argv);
  334. usage();
  335. }
  336. }
  337. //
  338. // Let the Work begin...
  339. //
  340. dwBestNumber = nMax;
  341. if (bFindOptimalSeed)
  342. {
  343. printf("This will take a while, perhaps all night(consider a Ctrl-C)...\n");
  344. }
  345. for (i = 0; i < DIM(Items); i++ )
  346. {
  347. if ( Items[i].ptok )
  348. dwValidStringsInArray++;
  349. }
  350. for (i = dwBestSeed; i < (~0); i++)
  351. {
  352. //printf("%d,\n", i);
  353. for (j = dwValidStringsInArray; j < nMax; j++)
  354. {
  355. memset (pHash, UNKNOWN_HASH_ENTRY, nMax * sizeof(DWORD));
  356. for (k = 0; k < dwValidStringsInArray; k++)
  357. {
  358. DWORD HashNow = Hash(MakeMeLower(Items[k].ptok), j, i) /*% j(table_size), i(seed)*/;
  359. if ( HashNow > j )
  360. {
  361. fprintf(stderr, "Error, Error - exceed table size, bad hash alg\n");
  362. break;
  363. }
  364. if (pHash[HashNow] != UNKNOWN_HASH_ENTRY)
  365. break;
  366. else
  367. {
  368. pHash[HashNow] = Items[k].id+1;
  369. }
  370. }
  371. if ( k == dwValidStringsInArray )
  372. {
  373. //printf( "Found one with hash_size=%d, seed=%u...\n", j,i );
  374. bFoundOne = TRUE;
  375. goto found_one;
  376. }
  377. }
  378. found_one:
  379. if ( bFoundOne )
  380. {
  381. if (j < dwBestNumber)
  382. {
  383. dwBestNumber = j;
  384. dwBestSeed = i;
  385. printf("Found a New One, hashtable_size=%d, seed=%u...\n", j ,i);
  386. if ( !bFindOptimalSeed && dwBestNumber < dwSearchThreshold )
  387. {
  388. goto stop_search;
  389. }
  390. }
  391. bFoundOne = FALSE;
  392. }
  393. }
  394. stop_search:
  395. if ( dwBestNumber < nMax && dwBestNumber == j)
  396. {
  397. printf("Generating %s which contains, perfect hash for known headers\n", OUTPUT_CODE_FILE);
  398. FILE *f;
  399. CHAR szOutputFileAndPath[512];
  400. strcpy(szOutputFileAndPath, szPath);
  401. strcat(szOutputFileAndPath, szFileName);
  402. f = fopen(szOutputFileAndPath, "w");
  403. if ( f == NULL )
  404. {
  405. fprintf(stderr, "Err: Could Not Open %s for writing\n", szOutputFileAndPath);
  406. exit(-1);
  407. }
  408. fprintf(f, szFileHeader); // print header
  409. fprintf(f, szIncludes); // includes
  410. fprintf(f, szDef1, dwBestSeed, dwBestSeed);
  411. fprintf(f, szDef2, dwBestNumber, dwBestNumber);
  412. fprintf(f, szDef3, HTTP_QUERY_MAX);
  413. fprintf(f, szComment1); // print comment
  414. if ( dwBestNumber < 255 )
  415. {
  416. fprintf(f, "const BYTE GlobalHeaderHashs[MAX_HEADER_HASH_SIZE] = {\n");
  417. }
  418. else
  419. {
  420. fprintf(f, "const WORD GlobalHeaderHashs[MAX_HEADER_HASH_SIZE] = {\n");
  421. }
  422. DWORD col = 0;
  423. //
  424. // spit our Nicely calculated perfect hash table..
  425. //
  426. for ( i = 0; i < dwBestNumber; i++ )
  427. {
  428. col++;
  429. if ( col == 1 )
  430. {
  431. fprintf(f, " ");
  432. }
  433. fprintf(f, "%3u, ", (BYTE) pHash[i]);
  434. if ( col == 6 )
  435. {
  436. fprintf(f, "\n");
  437. col = 0;
  438. }
  439. }
  440. fprintf(f, "\n };\n\n");
  441. //
  442. // Now spit our KnownHeader array...
  443. //
  444. qsort(Items, DIM(Items), sizeof(Items[0]), CompareItems);
  445. fprintf(f, szComment2);
  446. if ( DIM(Items) != (HTTP_QUERY_MAX+1) )
  447. {
  448. fprintf(stderr, "ERROR, HTTP_QUERY_MAX the wrong size,( different wininet.h's? )\n");
  449. return;
  450. }
  451. fprintf(f, "const struct KnownHeaderType GlobalKnownHeaders[HTTP_QUERY_MAX+1] = {\n");
  452. for (j = 0; j < DIM(Items); j++)
  453. {
  454. char szBuffer[256];
  455. DWORD dwHash = 0;
  456. sprintf(szBuffer, " HEADER_ENTRY(\"%s\",", (Items[j].ptok ? Items[j].ptok : "\0"));
  457. if ( Items[j].ptok )
  458. {
  459. dwHash = Hash(MakeMeLower(Items[j].ptok), 0, dwBestSeed);
  460. }
  461. fprintf(f, "%-45s %s, 0x%X),\n", szBuffer, Items[j].pFlagsName, dwHash);
  462. }
  463. fprintf(f," };\n\n\n");
  464. fclose(f);
  465. }
  466. else
  467. {
  468. fprintf(stderr, "Error, could not find an ideal number\n");
  469. }
  470. }