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.

688 lines
18 KiB

  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include "stampinf.h"
  5. DRIVER_VER_DATA dvdata;
  6. BOOLEAN HaveDate = FALSE;
  7. BOOLEAN HaveVersion = FALSE;
  8. int _cdecl main (int argc, char **argv)
  9. {
  10. char *StampInfEnv;
  11. //
  12. // Zero out our main data structure
  13. //
  14. ZeroMemory (&dvdata, sizeof (DRIVER_VER_DATA));
  15. //
  16. // Process and validate the arguments
  17. //
  18. lstrcpy (dvdata.SectionName, "Version");
  19. if (StampInfEnv = getenv("STAMPINF_DATE")) {
  20. if (ValidateDate (StampInfEnv)) {
  21. lstrcpy (dvdata.DateString, StampInfEnv);
  22. HaveDate = TRUE;
  23. }
  24. else printf ("Date error\n");
  25. }
  26. if (StampInfEnv = getenv("STAMPINF_VERSION")) {
  27. lstrcpyn (dvdata.VersionString, StampInfEnv, 20);
  28. HaveVersion = TRUE;
  29. }
  30. if (!GetArgs (argc, argv)) {
  31. DisplayHelp ();
  32. return 1;
  33. }
  34. //
  35. // Write the DriverVer key to the inf
  36. //
  37. if (!StampInf ()) {
  38. printf ("Error writing to inf!\n");
  39. return 1;
  40. }
  41. return 0;
  42. }
  43. BOOLEAN GetArgs (int argc, char **argv)
  44. {
  45. int args;
  46. char *arg;
  47. ARGTYPE argtype = ArgSwitch;
  48. //
  49. // Loop through the arguments, the filename is required
  50. // but version and date are optional.
  51. //
  52. for (args = 1; args < argc; args++) {
  53. arg = argv[args];
  54. //
  55. // switch based on the type of argument
  56. // we are expecting.
  57. //
  58. switch (argtype) {
  59. case ArgSwitch:
  60. //
  61. // better be a switch prefix
  62. //
  63. if (*arg != '-') return FALSE;
  64. else arg++;
  65. switch (toupper(*arg)) {
  66. case 'F':
  67. argtype = ArgFileName;
  68. break;
  69. case 'D':
  70. argtype = ArgDate;
  71. break;
  72. case 'V':
  73. argtype = ArgVersion;
  74. break;
  75. case 'S':
  76. argtype = ArgSection;
  77. break;
  78. default:
  79. printf ("Invalid argument %s\n", arg);
  80. }
  81. break;
  82. case ArgFileName:
  83. //
  84. // See if the provided filename includes any
  85. // path separators. If it doesn't prepend .\
  86. // because the WritePrivateProfile api
  87. // defaults to the Windows dir unless
  88. // you specify a path.
  89. //
  90. if (strchr (arg, '\\') == NULL) {
  91. lstrcpy (dvdata.InfName, ".\\");
  92. }
  93. //
  94. // concatenate the actual file name
  95. //
  96. lstrcat (dvdata.InfName, arg);
  97. argtype = ArgSwitch;
  98. break;
  99. case ArgDate:
  100. //
  101. // If the user specified a date, do some basic validation.
  102. //
  103. if (ValidateDate (arg)) {
  104. lstrcpy (dvdata.DateString, arg);
  105. HaveDate = TRUE;
  106. }
  107. else printf ("Date error\n");
  108. argtype = ArgSwitch;
  109. break;
  110. case ArgVersion:
  111. //
  112. // If the user specified a version override, use it.
  113. //
  114. lstrcpyn (dvdata.VersionString, arg, 20);
  115. argtype = ArgSwitch;
  116. HaveVersion = TRUE;
  117. break;
  118. case ArgSection:
  119. lstrcpyn (dvdata.SectionName, arg, 64);
  120. argtype = ArgSwitch;
  121. break;
  122. }
  123. }
  124. if (!HaveDate) {
  125. //
  126. // Get the date in xx/yy/zzzz format.
  127. //
  128. GetDateFormat (LOCALE_SYSTEM_DEFAULT, 0, NULL, "MM'/'dd'/'yyyy", dvdata.DateString, 11);
  129. }
  130. if (!HaveVersion) {
  131. //
  132. // If the user didn't provide a version override, then open and read
  133. // ntverp.h and figure out what the version stamp should be.
  134. //
  135. if (!ProcessNtVerP (dvdata.VersionString)) {
  136. return FALSE;
  137. }
  138. }
  139. //
  140. // Must have a name.
  141. //
  142. return (dvdata.InfName[0] != '\0');
  143. }
  144. BOOLEAN ValidateDate (char *datestring)
  145. {
  146. ULONG Month, Day, Year;
  147. if (lstrlen (datestring) != 10) return FALSE;
  148. Month = atoi(&datestring[0]);
  149. if (Month < 1 || Month > 12) return FALSE;
  150. Day = atoi (&datestring[3]);
  151. if (Day < 1 || Day > 31) return FALSE;
  152. Year = atoi (&datestring[6]);
  153. if (Year < 1980 || Year > 2099) return FALSE;
  154. return TRUE;
  155. }
  156. ULONG GetLengthOfLine (WCHAR *Pos, WCHAR *LastChar)
  157. {
  158. ULONG Length=0;
  159. if (Pos == NULL) return 0;
  160. while ( (Pos < LastChar) && (*Pos != 0x00D) ) {
  161. Pos++;
  162. Length++;
  163. }
  164. if (Pos < LastChar) Length+=2;
  165. return Length;
  166. }
  167. WCHAR *GetNextLine (WCHAR *CurPos, WCHAR *LastChar)
  168. {
  169. LastChar--;
  170. for (;CurPos < LastChar;CurPos++) {
  171. if ( (CurPos[0] == 0x00D) && (CurPos[1] == 0x00A) ) break;
  172. }
  173. return ( (&(CurPos[2]) <= LastChar) ? &(CurPos[2]) : NULL );
  174. }
  175. BOOLEAN DoesLineMatch (WCHAR *Target, WCHAR *Sample, WCHAR *LastChar)
  176. {
  177. USHORT LineLength = 0;
  178. WCHAR *Pos = Sample;
  179. WCHAR *buffer;
  180. BOOLEAN result;
  181. ULONG TargetLength;
  182. if (Pos == NULL) return FALSE;
  183. while ( (Pos <= LastChar) && (*Pos != 0x00D) ) {
  184. LineLength++;
  185. Pos++;
  186. }
  187. TargetLength = lstrlenW (Target);
  188. if (TargetLength > LineLength) {
  189. return FALSE;
  190. }
  191. return (BOOLEAN)(!memcmp (Target, Sample, TargetLength));
  192. }
  193. USHORT FindEntry (WCHAR *FileStart, WCHAR *FileEnd, WCHAR *SectionNameW, WCHAR **Entry)
  194. {
  195. WCHAR *FilePos=FileStart;
  196. WCHAR FixedSectionNameW[64+2];
  197. BOOLEAN FoundMatch = FALSE;
  198. ULONG iter = 0;
  199. wsprintfW (FixedSectionNameW, L"[%s]", SectionNameW);
  200. for (FilePos = FileStart; FilePos; FilePos = GetNextLine (FilePos, FileEnd)) {
  201. if (DoesLineMatch (FixedSectionNameW, FilePos, FileEnd)) {
  202. FoundMatch = TRUE;
  203. break;
  204. }
  205. }
  206. if (FoundMatch) {
  207. FoundMatch = FALSE;
  208. while ( ((FilePos = GetNextLine (FilePos, FileEnd)) != NULL) && (*FilePos != L'[') ) {
  209. if (DoesLineMatch (L"DriverVer", FilePos, FileEnd)) {
  210. FoundMatch = TRUE;
  211. break;
  212. }
  213. }
  214. if (FoundMatch) {
  215. *Entry = FilePos;
  216. return FOUND_ENTRY;
  217. }
  218. if (FilePos) {
  219. *Entry = FilePos;
  220. return FOUND_SECTION;
  221. }
  222. }
  223. *Entry = NULL;
  224. return FOUND_NOTHING;
  225. }
  226. UINT UniWPPS (char *SectionName, char *Stamp, char *InfName)
  227. {
  228. WCHAR SectionNameW [64];
  229. WCHAR *NextLinePtr;
  230. WCHAR NewEntryW [64];
  231. WCHAR StampW [32];
  232. WCHAR InfNameW [MAX_PATH];
  233. HANDLE hFile, hMapping;
  234. WCHAR *MappedBuffer;
  235. ULONG filesize;
  236. WCHAR *LastChar;
  237. WCHAR *Entry = NULL;
  238. ULONG result;
  239. ULONG StampLength;
  240. ULONG numwritten;
  241. ULONG deleted;
  242. MultiByteToWideChar (CP_ACP,
  243. MB_PRECOMPOSED,
  244. SectionName,
  245. (int)-1,
  246. SectionNameW,
  247. 64);
  248. MultiByteToWideChar (CP_ACP,
  249. MB_PRECOMPOSED,
  250. Stamp,
  251. (int)-1,
  252. StampW,
  253. 32);
  254. MultiByteToWideChar (CP_ACP,
  255. MB_PRECOMPOSED,
  256. InfName,
  257. (int)-1,
  258. InfNameW,
  259. MAX_PATH);
  260. StampLength = lstrlenW (StampW);
  261. hFile = CreateFile (InfName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  262. if (hFile == INVALID_HANDLE_VALUE) {
  263. printf ("Create file failed!\n");
  264. return 0;
  265. }
  266. filesize = GetFileSize (hFile, NULL);
  267. hMapping = CreateFileMapping (hFile, NULL, PAGE_READWRITE, 0, filesize+128, NULL);
  268. if (!hMapping) {
  269. printf ("Map file failed!\n");
  270. CloseHandle (hFile);
  271. return 0;
  272. }
  273. MappedBuffer = MapViewOfFile (hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
  274. if (!MappedBuffer) {
  275. printf ("MapView Failed!\n");
  276. CloseHandle (hMapping);
  277. CloseHandle (hFile);
  278. return 0;
  279. }
  280. LastChar = (WCHAR *)((ULONG_PTR)MappedBuffer+filesize-sizeof(WCHAR));
  281. result = FindEntry (MappedBuffer, LastChar, SectionNameW, &Entry);
  282. wsprintfW (NewEntryW, L"DriverVer=%s\r\n",StampW);
  283. StampLength = lstrlenW (NewEntryW);
  284. switch (result) {
  285. case FOUND_SECTION:
  286. MoveMemory ((WCHAR *)((ULONG_PTR)Entry+(StampLength*sizeof(WCHAR))), Entry, (ULONG_PTR)LastChar-(ULONG_PTR)Entry+sizeof(WCHAR));
  287. CopyMemory (Entry, NewEntryW, StampLength*sizeof(WCHAR));
  288. UnmapViewOfFile (MappedBuffer);
  289. CloseHandle (hMapping);
  290. SetFilePointer (hFile, filesize+StampLength*sizeof(WCHAR), NULL, FILE_BEGIN);
  291. SetEndOfFile (hFile);
  292. break;
  293. case FOUND_ENTRY:
  294. deleted = GetLengthOfLine (Entry, LastChar);
  295. deleted *=sizeof(WCHAR);
  296. NextLinePtr = GetNextLine (Entry, LastChar);
  297. MoveMemory ((WCHAR *)((ULONG_PTR)Entry+(StampLength*sizeof(WCHAR))), NextLinePtr, (ULONG_PTR)LastChar-(ULONG_PTR)NextLinePtr+sizeof(WCHAR));
  298. CopyMemory (Entry, NewEntryW, StampLength*sizeof(WCHAR));
  299. UnmapViewOfFile (MappedBuffer);
  300. CloseHandle (hMapping);
  301. SetFilePointer (hFile, filesize+StampLength*sizeof(WCHAR)-deleted, NULL, FILE_BEGIN);
  302. SetEndOfFile (hFile);
  303. break;
  304. case FOUND_NOTHING:
  305. UnmapViewOfFile (MappedBuffer);
  306. CloseHandle (hMapping);
  307. SetFilePointer (hFile, filesize, NULL, FILE_BEGIN);
  308. SetEndOfFile (hFile);
  309. break;
  310. }
  311. CloseHandle (hFile);
  312. return 1;
  313. }
  314. BOOLEAN IsInfUnicode (VOID)
  315. {
  316. HANDLE hFile, hMapping;
  317. char *MappedBuffer;
  318. ULONG filesize;
  319. BOOLEAN unicode = FALSE;
  320. hFile = CreateFile (dvdata.InfName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  321. if (hFile == INVALID_HANDLE_VALUE) {
  322. printf ("Create file failed!\n");
  323. return FALSE;
  324. }
  325. hMapping = CreateFileMapping (hFile, NULL, PAGE_READONLY, 0, 0, NULL);
  326. if (!hMapping) {
  327. printf ("Map file failed!\n");
  328. CloseHandle (hFile);
  329. return FALSE;
  330. }
  331. MappedBuffer = MapViewOfFile (hMapping, FILE_MAP_READ, 0, 0, 0);
  332. if (!MappedBuffer) {
  333. printf ("MapView Failed!\n");
  334. CloseHandle (hMapping);
  335. CloseHandle (hFile);
  336. return FALSE;
  337. }
  338. filesize = GetFileSize (hFile, NULL);
  339. if (filesize < sizeof (WCHAR)) return 0;
  340. if ( *((WCHAR *)MappedBuffer) == 0xFEFF ) {
  341. unicode = TRUE;
  342. }
  343. if ( IsTextUnicode (MappedBuffer, filesize, NULL) ) {
  344. unicode = TRUE;
  345. }
  346. UnmapViewOfFile (MappedBuffer);
  347. CloseHandle (hMapping);
  348. CloseHandle (hFile);
  349. return unicode;
  350. }
  351. BOOLEAN StampInf (VOID)
  352. {
  353. char DateVerStamp[32];
  354. wsprintf (DateVerStamp, "%s,%s",dvdata.DateString,dvdata.VersionString);
  355. printf ("Stamping %s [%s] section with DriverVer=%s\n",dvdata.InfName, dvdata.SectionName, DateVerStamp);
  356. //
  357. // Let WritePrivateProfile do all of our work!
  358. //
  359. if (IsInfUnicode()) {
  360. printf ("Unicode Inf Detected\n");
  361. if (UniWPPS (dvdata.SectionName, DateVerStamp, dvdata.InfName) == 0) {
  362. printf ("Error\n");
  363. return FALSE;
  364. }
  365. }
  366. else {
  367. if (WritePrivateProfileString (dvdata.SectionName, "DriverVer", DateVerStamp, dvdata.InfName) == 0) {
  368. printf ("Error\n");
  369. return FALSE;
  370. }
  371. }
  372. return TRUE;
  373. }
  374. VOID DisplayHelp (VOID)
  375. {
  376. printf ("\tUSAGE:\n");
  377. printf ("\tstampinf -f filename [-s section] [-d xx/yy/zzzz] [-v w.x.y.z]\n");
  378. }
  379. DWORD NextInterestingCharacter (DWORD CurFilePos, DWORD Size, char *MappedBuffer)
  380. {
  381. char thischar;
  382. DWORD NewPos;
  383. //
  384. // Find the next character that is not whitespace, EOL, or within a comment block.
  385. // Return the offset into the buffer for that character, or Size if there is no
  386. // such character.
  387. //
  388. while (CurFilePos < Size) {
  389. thischar = MappedBuffer[CurFilePos];
  390. if ( (thischar == 0x0A) || (thischar == 0x0D) || (thischar == ' ') ) {
  391. CurFilePos++;
  392. continue;
  393. }
  394. if (CurFilePos == Size-1)
  395. break;
  396. if ( (thischar == '/') && (MappedBuffer[CurFilePos+1] == '*') ) {
  397. //
  398. // Skip past the comment char's and search for the end of the comment block
  399. //
  400. NewPos = CurFilePos+2;
  401. while (NewPos < (Size-1)) {
  402. if ( (MappedBuffer[NewPos] == '*') && (MappedBuffer[NewPos+1] == '/') ) {
  403. CurFilePos = NewPos+1;
  404. break;
  405. }
  406. NewPos++;
  407. }
  408. }
  409. else if ( (thischar == '/') && (MappedBuffer[CurFilePos+1] == '/') ) {
  410. // Search for newline or EOF
  411. CurFilePos += 2;
  412. while (CurFilePos < (Size-1)) {
  413. if ( (MappedBuffer[CurFilePos] == 0x0A) || (MappedBuffer[CurFilePos] == 0x0D)) {
  414. break;
  415. }
  416. CurFilePos++;
  417. }
  418. }
  419. else {
  420. break;
  421. }
  422. CurFilePos++;
  423. }
  424. return CurFilePos;
  425. }
  426. DWORD FindLengthOfInterestingCharacters (DWORD CurFilePos, DWORD Size, char *MappedBuffer)
  427. {
  428. DWORD Pos = CurFilePos;
  429. char thischar;
  430. //
  431. // Find the length of a string. Return the length.
  432. //
  433. while (Pos < Size) {
  434. thischar = MappedBuffer[Pos];
  435. if ( (thischar == 0x0A) || (thischar == 0x0D) || (thischar == ' ') || (thischar == '/') ) {
  436. return (Pos-CurFilePos);
  437. }
  438. Pos++;
  439. }
  440. printf ("How did we get here?\n");
  441. return 0;
  442. }
  443. BOOLEAN ProcessNtVerP (char *VersionString)
  444. {
  445. HANDLE hFile, hMapping;
  446. char *MappedBuffer, *location;
  447. DWORD pos;
  448. DWORD qfelen,buildlen,majorverlen,minorverlen;
  449. char qfe[5]={'0','0','0','0',0};
  450. char build[5]={'0','0','0','0',0};
  451. char majorversion[5]={'0','0','0','0',0};
  452. char minorversion[5]={'0','0','0','0',0};
  453. DWORD filesize;
  454. char *p;
  455. TCHAR ntroot[MAX_PATH];
  456. if ( GetEnvironmentVariable ("_NTDRIVE", ntroot, 3) == 0 ) {
  457. printf ("Unable to evaluate _NTDRIVE!\n");
  458. return FALSE;
  459. }
  460. if ( GetEnvironmentVariable ("_NTROOT", &(ntroot[2]), MAX_PATH-2) == 0 ) {
  461. printf ("Unable to evaluate _NTROOT!\n");
  462. return FALSE;
  463. }
  464. lstrcat (ntroot, "\\public\\sdk\\inc\\ntverp.h");
  465. printf ("Using version information from %s\n",ntroot);
  466. //
  467. // Create a memory mapped image of ntverp.h
  468. //
  469. hFile = CreateFile (ntroot, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  470. if (hFile == INVALID_HANDLE_VALUE) {
  471. printf ("Create file failed!\n");
  472. return FALSE;
  473. }
  474. filesize = GetFileSize (hFile, NULL);
  475. hMapping = CreateFileMapping (hFile, NULL, PAGE_READONLY, 0, 0, NULL);
  476. if (!hMapping) {
  477. printf ("Map file failed!\n");
  478. CloseHandle (hFile);
  479. return FALSE;
  480. }
  481. MappedBuffer = MapViewOfFile (hMapping, FILE_MAP_READ, 0, 0, 0);
  482. if (!MappedBuffer) {
  483. printf ("MapView Failed!\n");
  484. CloseHandle (hMapping);
  485. CloseHandle (hFile);
  486. return FALSE;
  487. }
  488. //
  489. // The version is made up of a.b.c.d where a.b is the Product Version.
  490. // c is the Build and d is the QFE level. (e.g. 5.0.1922.1)
  491. //
  492. location = strstr (MappedBuffer, "#define VER_PRODUCTMAJORVERSION ");
  493. pos = NextInterestingCharacter ((DWORD)(location-MappedBuffer+32), filesize, MappedBuffer);
  494. majorverlen = FindLengthOfInterestingCharacters (pos, filesize, MappedBuffer);
  495. lstrcpyn (majorversion, &(MappedBuffer[pos]), majorverlen+1);
  496. location = strstr (MappedBuffer, "#define VER_PRODUCTMINORVERSION ");
  497. pos = NextInterestingCharacter ((DWORD)(location-MappedBuffer+32), filesize, MappedBuffer);
  498. minorverlen = FindLengthOfInterestingCharacters (pos, filesize, MappedBuffer);
  499. lstrcpyn (minorversion, &(MappedBuffer[pos]), minorverlen+1);
  500. location = strstr (MappedBuffer, "#define VER_PRODUCTBUILD ");
  501. pos = NextInterestingCharacter ((DWORD)(location-MappedBuffer+25), filesize, MappedBuffer);
  502. buildlen = FindLengthOfInterestingCharacters (pos, filesize, MappedBuffer);
  503. lstrcpyn (build, &(MappedBuffer[pos]), buildlen+1);
  504. location = strstr (MappedBuffer, "#define VER_PRODUCTBUILD_QFE ");
  505. pos = NextInterestingCharacter ((DWORD)(location-MappedBuffer+29), filesize, MappedBuffer);
  506. qfelen = FindLengthOfInterestingCharacters (pos, filesize, MappedBuffer);
  507. lstrcpyn (qfe, &(MappedBuffer[pos]), qfelen+1);
  508. wsprintf (VersionString, "%s.%s.%s.%s",majorversion, minorversion, build, qfe);
  509. UnmapViewOfFile (MappedBuffer);
  510. CloseHandle (hMapping);
  511. CloseHandle (hFile);
  512. return TRUE;
  513. }