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.

1681 lines
46 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. #include <spidgen.h>
  4. #include <pencrypt.h>
  5. #include "digpid.h"
  6. #define SETUP_TYPE_BUFFER_LEN 8
  7. #define MAX_PID30_SITE 3
  8. #define MAX_PID30_RPC 5
  9. TCHAR Pid30Rpc[7] = TEXT("00000");
  10. TCHAR Pid30Site[4];
  11. LONG SourceInstallType = RetailInstall;
  12. BOOL EulaComplete = TRUE;
  13. #ifdef PRERELEASE
  14. BOOL NoPid = FALSE;
  15. #endif
  16. //
  17. // global variable used for subclassing.
  18. //
  19. WNDPROC OldPidEditProc[5];
  20. WNDPROC OldEulaEditProc;
  21. static BOOL PidMatchesMedia;
  22. BOOL
  23. ValidatePid30(
  24. LPTSTR Edit1,
  25. LPTSTR Edit2,
  26. LPTSTR Edit3,
  27. LPTSTR Edit4,
  28. LPTSTR Edit5
  29. );
  30. void GetPID();
  31. VOID ShowPidBox();
  32. VOID
  33. GetSourceInstallType(
  34. OUT OPTIONAL LPDWORD InstallVariation
  35. )
  36. /*++
  37. Routine Description:
  38. Determines the installation type (by looking in setupp.ini in the source directory)
  39. Arguments:
  40. Installvaration - one of the install variations defined in compliance.h
  41. Returns:
  42. none. sets SourceInstallType global variable.
  43. --*/
  44. {
  45. TCHAR TypeBuffer[256];
  46. TCHAR FilePath[MAX_PATH];
  47. DWORD InstallVar = COMPLIANCE_INSTALLVAR_UNKNOWN;
  48. TCHAR MPCode[6] = { -1 };
  49. //
  50. // SourcePaths is guaranteed to be valid at this point, so just use it
  51. //
  52. lstrcpy(FilePath,NativeSourcePaths[0]);
  53. ConcatenatePaths (FilePath, SETUPP_INI, MAX_PATH );
  54. GetPrivateProfileString(PID_SECTION,
  55. PID_KEY,
  56. TEXT(""),
  57. TypeBuffer,
  58. sizeof(TypeBuffer)/sizeof(TCHAR),
  59. FilePath);
  60. if (lstrlen(TypeBuffer)==SETUP_TYPE_BUFFER_LEN) {
  61. if (lstrcmp(&TypeBuffer[5], OEM_INSTALL_RPC) == 0) {
  62. SourceInstallType = OEMInstall;
  63. InstallVar = COMPLIANCE_INSTALLVAR_OEM;
  64. } else if (lstrcmp(&TypeBuffer[5], SELECT_INSTALL_RPC) == 0) {
  65. SourceInstallType = SelectInstall;
  66. InstallVar = COMPLIANCE_INSTALLVAR_SELECT;
  67. // Since Select also requires a PID, don't zero the PID and call.
  68. /* // get/set the pid.
  69. {
  70. TCHAR Temp[5][ MAX_PID30_EDIT + 1 ];
  71. Temp[0][0] = TEXT('\0');
  72. ValidatePid30(Temp[0],Temp[1],Temp[2],Temp[3],Temp[4]);
  73. }*/
  74. } else if (lstrcmp(&TypeBuffer[5], MSDN_INSTALL_RPC) == 0) {
  75. SourceInstallType = RetailInstall;
  76. InstallVar = COMPLIANCE_INSTALLVAR_MSDN;
  77. } else {
  78. // defaulting
  79. SourceInstallType = RetailInstall;
  80. InstallVar = COMPLIANCE_INSTALLVAR_CDRETAIL;
  81. }
  82. lstrcpy(Pid30Site,&TypeBuffer[5]);
  83. lstrcpyn(Pid30Rpc, TypeBuffer, 6 );
  84. Pid30Rpc[MAX_PID30_RPC] = (TCHAR)0;
  85. } else {
  86. //
  87. // the retail install doesn't have an RPC code in the PID, so it's shorter in length
  88. //
  89. SourceInstallType = RetailInstall;
  90. InstallVar = COMPLIANCE_INSTALLVAR_CDRETAIL;
  91. }
  92. if (lstrlen(TypeBuffer) >= 5) {
  93. lstrcpyn(MPCode, TypeBuffer, 6);
  94. if (lstrcmp(MPCode, EVAL_MPC) == 0) {
  95. InstallVar = COMPLIANCE_INSTALLVAR_EVAL;
  96. } else if ((lstrcmp(MPCode, SRV_NFR_MPC) == 0) ||
  97. (lstrcmp(MPCode, ASRV_NFR_MPC) == 0)) {
  98. InstallVar = COMPLIANCE_INSTALLVAR_NFR;
  99. }
  100. }
  101. if (InstallVariation){
  102. *InstallVariation = InstallVar;
  103. }
  104. }
  105. BOOL
  106. SetPid30(
  107. HWND hdlg,
  108. LONG ExpectedPidType,
  109. LPTSTR pProductId
  110. )
  111. /*++
  112. Routine Description:
  113. sets the pid in the wizard page to the data specified in the answer file.
  114. Arguments:
  115. hdlg - window handle to pid dialog
  116. ExpectedPidType - InstallType enum identifying what sort of pid we're looking for.
  117. pProductId - string passed in from unattend file
  118. Returns:
  119. true on successfully setting the data, false means the data was missing or invalid.
  120. may set some the dialog text in the specified dialog
  121. --*/
  122. {
  123. TCHAR *ptr;
  124. TCHAR Temp[5][ MAX_PID30_EDIT + 1 ];
  125. UINT i;
  126. //
  127. // make sure we were provided with a product ID
  128. //
  129. if (!pProductId || !*pProductId) {
  130. return(FALSE);
  131. }
  132. if ( (ExpectedPidType != RetailInstall) &&
  133. (ExpectedPidType != OEMInstall) &&
  134. (ExpectedPidType != SelectInstall)
  135. ){
  136. return(FALSE);
  137. }
  138. //
  139. // OEM and cd retail are the same case
  140. // Check that the string specified on the unattended script file
  141. // represents a valid 25 digit product id:
  142. //
  143. // 1 2 3 4 5 - 1 2 3 4 5 - 1 2 3 4 5 - 1 2 3 4 5 - 1 2 3 4 5
  144. // 0 1 2 3 4 5 6 7 8 9 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2
  145. // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8
  146. //
  147. // As a first validation test, we verify that the length is correct,
  148. // then we check if the "-" characters are in the correct place
  149. //
  150. //
  151. if( ( lstrlen( pProductId ) != (4+ MAX_PID30_EDIT*5)) ||
  152. ( pProductId[5] != (TCHAR)TEXT('-') ) ||
  153. ( pProductId[11] != (TCHAR)TEXT('-') ) ||
  154. ( pProductId[17] != (TCHAR)TEXT('-') ) ||
  155. ( pProductId[23] != (TCHAR)TEXT('-') )
  156. ) {
  157. //
  158. // The Pid in the unattended script file is invalid.
  159. //
  160. return(FALSE);
  161. }
  162. for (i = 0;i<5;i++) {
  163. //
  164. // quintet i
  165. //
  166. ptr = &pProductId[i*(MAX_PID30_EDIT+1)];
  167. lstrcpyn(Temp[i], ptr, MAX_PID30_EDIT+1 );
  168. Temp[i][MAX_PID30_EDIT] = (TCHAR)'\0';
  169. }
  170. //
  171. // check with pid30 to make sure it's valid
  172. //
  173. if (!ValidatePid30(Temp[0],Temp[1],Temp[2],Temp[3],Temp[4])) {
  174. return(FALSE);
  175. }
  176. //
  177. // all of the specified pid items are valid, set the dialog text and return.
  178. //
  179. SetDlgItemText( hdlg,IDT_EDIT_PID1, Temp[0] );
  180. SetDlgItemText( hdlg,IDT_EDIT_PID2, Temp[1] );
  181. SetDlgItemText( hdlg,IDT_EDIT_PID3, Temp[2] );
  182. SetDlgItemText( hdlg,IDT_EDIT_PID4, Temp[3] );
  183. SetDlgItemText( hdlg,IDT_EDIT_PID5, Temp[4] );
  184. return(TRUE);
  185. }
  186. BOOL
  187. pGetCdKey (
  188. OUT PBYTE CdKey
  189. )
  190. {
  191. DIGITALPID dpid;
  192. DWORD type;
  193. DWORD rc;
  194. HKEY key;
  195. DWORD size = sizeof (dpid);
  196. BOOL b = FALSE;
  197. rc = RegOpenKey (HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), &key);
  198. if (rc == ERROR_SUCCESS) {
  199. rc = RegQueryValueEx (key, TEXT("DigitalProductId"), NULL, &type, (LPBYTE)&dpid, &size);
  200. if (rc == ERROR_SUCCESS && type == REG_BINARY) {
  201. CopyMemory (CdKey, &dpid.abCdKey, sizeof (dpid.abCdKey));
  202. b = TRUE;
  203. }
  204. RegCloseKey (key);
  205. }
  206. return b;
  207. }
  208. const unsigned int iBase = 24;
  209. //
  210. // obtained from Jim Harkins 11/27/2000
  211. //
  212. void EncodePid3g(
  213. TCHAR *pchCDKey3Chars, // [OUT] pointer to 29+1 character Secure Product key
  214. LPBYTE pbCDKey3) // [IN] pointer to 15-byte binary Secure Product Key
  215. {
  216. // Given the binary PID 3.0 we need to encode
  217. // it into ASCII characters. We're only allowed to
  218. // use 24 characters so we need to do a base 2 to
  219. // base 24 conversion. It's just like any other
  220. // base conversion execpt the numbers are bigger
  221. // so we have to do the long division ourselves.
  222. const TCHAR achDigits[] = TEXT("BCDFGHJKMPQRTVWXY2346789");
  223. int iCDKey3Chars = 29;
  224. int cGroup = 0;
  225. pchCDKey3Chars[iCDKey3Chars--] = TEXT('\0');
  226. while (0 <= iCDKey3Chars)
  227. {
  228. unsigned int i = 0; // accumulator
  229. int iCDKey3;
  230. for (iCDKey3 = 15-1; 0 <= iCDKey3; --iCDKey3)
  231. {
  232. i = (i * 256) + pbCDKey3[iCDKey3];
  233. pbCDKey3[iCDKey3] = (BYTE)(i / iBase);
  234. i %= iBase;
  235. }
  236. // i now contains the remainder, which is the current digit
  237. pchCDKey3Chars[iCDKey3Chars--] = achDigits[i];
  238. // add '-' between groups of 5 chars
  239. if (++cGroup % 5 == 0 && iCDKey3Chars > 0)
  240. {
  241. pchCDKey3Chars[iCDKey3Chars--] = TEXT('-');
  242. }
  243. }
  244. return;
  245. }
  246. LRESULT
  247. CALLBACK
  248. PidEditSubProc(
  249. IN HWND hwnd,
  250. IN UINT msg,
  251. IN WPARAM wParam,
  252. IN LPARAM lParam
  253. )
  254. /*++
  255. Routine Description:
  256. Edit control subclass routine, sets the focus to the correct edit box when the user enters text.
  257. This routine assumes that the pid controls ids are in sequential order.
  258. Arguments:
  259. Standard window proc arguments.
  260. Returns:
  261. Message-dependent value.
  262. --*/
  263. {
  264. DWORD len, id;
  265. //
  266. // eat spaces
  267. //
  268. if ((msg == WM_CHAR) && (wParam == VK_SPACE)) {
  269. return(0);
  270. }
  271. if ((msg == WM_CHAR)) {
  272. //
  273. // First override: if we have the max characters in the current edit
  274. // box, let's post the character to the next box and set focus to that
  275. // control.
  276. //
  277. if ( ( (len = (DWORD)SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0)) == MAX_PID30_EDIT) &&
  278. ((wParam != VK_DELETE) && (wParam != VK_BACK)) ) {
  279. //
  280. // set the focus to the next edit control and post the character
  281. // to that edit control
  282. //
  283. if ((id = GetDlgCtrlID(hwnd)) < IDT_EDIT_PID5 ) {
  284. DWORD start, end;
  285. SendMessage(hwnd, EM_GETSEL, (WPARAM)&start,(LPARAM)&end);
  286. if (start == end) {
  287. HWND hNext = GetDlgItem(GetParent(hwnd),id+1);
  288. SetFocus(hNext);
  289. SendMessage(hNext, EM_SETSEL, (WPARAM)-1,(LPARAM)-1);
  290. PostMessage( GetDlgItem(GetParent(hwnd),id+1), WM_CHAR, wParam, lParam );
  291. return(0);
  292. }
  293. }
  294. //
  295. // Second override: if the user hit's a delete key and they are at the
  296. // the start of an edit box, then post the delete to the previous edit
  297. // box.
  298. //
  299. } else if ( (len == 0) &&
  300. ((id = GetDlgCtrlID(hwnd)) > IDT_EDIT_PID1) &&
  301. ((wParam == VK_DELETE) || (wParam == VK_BACK) )) {
  302. //
  303. // set the focus to the previous edit control and post the command
  304. // to that edit control
  305. //
  306. HWND hPrev = GetDlgItem(GetParent(hwnd),id-1);
  307. SetFocus(hPrev);
  308. SendMessage(hPrev, EM_SETSEL, (WPARAM)MAX_PID30_EDIT-1,(LPARAM)MAX_PID30_EDIT);
  309. PostMessage( hPrev, WM_CHAR, wParam, lParam );
  310. return(0);
  311. //
  312. // Third override: if posting this message will give us the maximum
  313. // characters in our in the current edit box, let's post the character
  314. // to the next box and set focus to that control.
  315. //
  316. } else if ( (len == MAX_PID30_EDIT-1) &&
  317. ((wParam != VK_DELETE) && (wParam != VK_BACK)) &&
  318. ((id = GetDlgCtrlID(hwnd)) < IDT_EDIT_PID5) ) {
  319. DWORD start, end;
  320. SendMessage(hwnd, EM_GETSEL, (WPARAM)&start,(LPARAM)&end);
  321. if (start == end) {
  322. HWND hNext = GetDlgItem(GetParent(hwnd),id+1);
  323. //
  324. // post the message to the edit box
  325. //
  326. CallWindowProc(OldPidEditProc[GetDlgCtrlID(hwnd)-IDT_EDIT_PID1],hwnd,msg,wParam,lParam);
  327. //
  328. // now set the focus to the next edit control
  329. //
  330. SetFocus(hNext);
  331. SendMessage(hNext, EM_SETSEL, (WPARAM)-1,(LPARAM)-1);
  332. return(0);
  333. }
  334. }
  335. }
  336. return(CallWindowProc(OldPidEditProc[GetDlgCtrlID(hwnd)-IDT_EDIT_PID1],hwnd,msg,wParam,lParam));
  337. }
  338. LRESULT
  339. CALLBACK
  340. EulaEditSubProc(
  341. IN HWND hwnd,
  342. IN UINT msg,
  343. IN WPARAM wParam,
  344. IN LPARAM lParam
  345. )
  346. /*++
  347. Routine Description:
  348. Edit control subclass routine, to avoid highlighting text when user
  349. tabs to the edit control.
  350. Arguments:
  351. Standard window proc arguments.
  352. Returns:
  353. Message-dependent value.
  354. --*/
  355. {
  356. static BOOL firstTime = TRUE;
  357. //
  358. // For setsel messages, make start and end the same.
  359. //
  360. if((msg == EM_SETSEL) && ((LPARAM)wParam != lParam)) {
  361. lParam = wParam;
  362. }
  363. //
  364. // also, if the user hits tab, set focus to the correct radio button
  365. // after the first time, the tab starts working like we want it to
  366. //
  367. if ((msg == WM_KEYDOWN) && (wParam == VK_TAB) && firstTime) {
  368. firstTime = FALSE;
  369. if (! ((IsDlgButtonChecked(GetParent(hwnd), IDYES) == BST_CHECKED) ||
  370. (IsDlgButtonChecked(GetParent(hwnd), IDNO ) == BST_CHECKED))) {
  371. CheckDlgButton( GetParent(hwnd),IDYES, BST_CHECKED );
  372. PostMessage(GetParent(hwnd),WM_COMMAND,IDYES,0);
  373. SetFocus(GetDlgItem(GetParent(hwnd),IDYES));
  374. }
  375. }
  376. return(CallWindowProc(OldEulaEditProc,hwnd,msg,wParam,lParam));
  377. }
  378. LPTSTR
  379. DoInitializeEulaText(
  380. HWND EditControl,
  381. PBOOL TranslationProblem
  382. )
  383. /*++
  384. Routine Description:
  385. retrieves the text out of eula.txt, and sets up the eula subclass routine
  386. Arguments:
  387. EditControl - window handle for edit control
  388. TranslationProblem - if we fail, was is because we couldn't translate the
  389. text?
  390. Returns:
  391. pointer to eula text so that it can be freed, NULL on failure
  392. --*/
  393. {
  394. TCHAR EulaPath[MAX_PATH];
  395. DWORD err;
  396. HANDLE hFile, hFileMapping;
  397. DWORD FileSize;
  398. BYTE *pbFile;
  399. LPTSTR EulaText = NULL;
  400. int i;
  401. // HFONT hFont;
  402. // accoding to MSDN LOCALE_IDEFAULTANSICODEPAGE and LOCALE_IDEFAULTCODEPAGE
  403. // are a max of 6 characters. Unsure of whether or not this includes ending
  404. // null character, and we need a leading _T('.')
  405. TCHAR cpName[8];
  406. if (TranslationProblem) {
  407. *TranslationProblem = FALSE;
  408. }
  409. //
  410. // Map the file containing the licensing agreement.
  411. //
  412. lstrcpy(EulaPath, NativeSourcePaths[0]);
  413. ConcatenatePaths (EulaPath, TEXT("eula.txt"), MAX_PATH );
  414. //
  415. // Open and map the inf file.
  416. //
  417. err = MapFileForRead(EulaPath,&FileSize,&hFile,&hFileMapping,&pbFile);
  418. if(err != NO_ERROR) {
  419. goto c0;
  420. }
  421. if(FileSize == 0xFFFFFFFF) {
  422. goto c1;
  423. }
  424. EulaText = MALLOC((FileSize+1) * sizeof(TCHAR));
  425. if(EulaText == NULL) {
  426. goto c1;
  427. }
  428. #ifdef UNICODE
  429. // the Eula will be in the language of the build, so we should set out locale
  430. // to use the codepage that the source wants.
  431. if(!GetLocaleInfo(SourceNativeLangID,LOCALE_IDEFAULTANSICODEPAGE,&cpName[1],sizeof(cpName)/sizeof(TCHAR))){
  432. if(!GetLocaleInfo(SourceNativeLangID,LOCALE_IDEFAULTCODEPAGE,&cpName[1],sizeof(cpName)/sizeof(TCHAR))){
  433. FREE(EulaText);
  434. EulaText = NULL;
  435. if (TranslationProblem){
  436. *TranslationProblem = TRUE;
  437. }
  438. goto c1;
  439. }
  440. }
  441. cpName[0] = _T('.');
  442. _tsetlocale(LC_ALL,cpName);
  443. //
  444. // Translate the text from ANSI to Unicode.
  445. //
  446. if(!mbstowcs(EulaText,pbFile,FileSize)){
  447. FREE(EulaText);
  448. EulaText = NULL;
  449. if (TranslationProblem) {
  450. *TranslationProblem = TRUE;
  451. }
  452. goto c1;
  453. }
  454. _tsetlocale(LC_ALL,_T(""));
  455. /*
  456. // we use mbstowcs instead of MultiByteToWideChar because mbstowcs will
  457. // take into account the code page of the locale, which we've just set
  458. // to be in relation to the language of the build
  459. if (!MultiByteToWideChar (
  460. CP_ACP,
  461. MB_ERR_INVALID_CHARS,
  462. pbFile,
  463. FileSize,
  464. EulaText,
  465. (FileSize+1) * sizeof(WCHAR)
  466. ) ) {
  467. FREE( EulaText );
  468. EulaText = NULL;
  469. if (TranslationProblem) {
  470. *TranslationProblem = TRUE;
  471. }
  472. goto c1;
  473. }
  474. */
  475. #else
  476. CopyMemory(EulaText, pbFile, FileSize);
  477. #endif
  478. //
  479. // add the trailing NULL character
  480. //
  481. EulaText[FileSize] = 0;
  482. //
  483. // setup the eula subclass
  484. //
  485. OldEulaEditProc = (WNDPROC)GetWindowLongPtr(EditControl,GWLP_WNDPROC);
  486. SetWindowLongPtr(EditControl,GWLP_WNDPROC,(LONG_PTR)EulaEditSubProc);
  487. #if 0
  488. //
  489. // need a fixed width font for the EULA so it's formatted correctly for all resolutions
  490. //
  491. hFont = GetStockObject(SYSTEM_FIXED_FONT);
  492. if (hFont) {
  493. SendMessage( EditControl, WM_SETFONT, hFont, TRUE );
  494. }
  495. #endif
  496. //
  497. // set the actual text
  498. //
  499. SetWindowText(EditControl,(LPCTSTR)EulaText);
  500. c1:
  501. UnmapFile( hFileMapping, pbFile );
  502. CloseHandle( hFile );
  503. c0:
  504. return EulaText;
  505. }
  506. BOOL
  507. EulaWizPage(
  508. IN HWND hdlg,
  509. IN UINT msg,
  510. IN WPARAM wParam,
  511. IN LPARAM lParam
  512. )
  513. /*++
  514. Routine Description:
  515. Eula wizard page.
  516. Arguments:
  517. Standard window proc arguments.
  518. Returns:
  519. Message-dependent value.
  520. --*/
  521. {
  522. BOOL b;
  523. PPAGE_RUNTIME_DATA WizPage = (PPAGE_RUNTIME_DATA)GetWindowLongPtr(hdlg,DWLP_USER);
  524. static LPTSTR EulaText = NULL;
  525. static BOOL ShowEula = TRUE;
  526. BOOL TranslationProblem;
  527. CHECKUPGRADEONLY();
  528. switch(msg) {
  529. case WM_INITDIALOG:
  530. //
  531. // check if the current language and target language match
  532. //
  533. ShowEula = IsLanguageMatched;
  534. //
  535. // Set eula radio buttons.
  536. //
  537. CheckDlgButton( hdlg,IDYES, BST_UNCHECKED );
  538. CheckDlgButton( hdlg,IDNO, BST_UNCHECKED );
  539. //
  540. // setup the eula
  541. //
  542. EulaText = DoInitializeEulaText(
  543. GetDlgItem( hdlg, IDT_EULA_LIC_TEXT ),
  544. &TranslationProblem );
  545. //
  546. // if we couldn't read the eula, check if it was because of a translation problem,
  547. // in which case we defer to textmode setup
  548. //
  549. if (!EulaText && TranslationProblem == TRUE) {
  550. ShowEula = FALSE;
  551. }
  552. //
  553. // if this fails, only bail out if we were going to show the EULA in the first place.
  554. //
  555. if (!EulaText && ShowEula) {
  556. MessageBoxFromMessage(
  557. hdlg,
  558. MSG_EULA_FAILED,
  559. FALSE,
  560. AppTitleStringId,
  561. MB_OK | MB_ICONERROR | MB_TASKMODAL
  562. );
  563. Cancelled = TRUE;
  564. PropSheet_PressButton(GetParent(hdlg),PSBTN_CANCEL);
  565. b = FALSE;
  566. }
  567. PropSheet_SetWizButtons( GetParent(hdlg),
  568. WizPage->CommonData.Buttons & (~PSWIZB_NEXT)
  569. );
  570. //
  571. // Set focus to radio button
  572. //
  573. SetFocus(GetDlgItem(hdlg,IDYES));
  574. b = FALSE;
  575. break;
  576. case WM_COMMAND:
  577. if (wParam == IDYES) {
  578. PropSheet_SetWizButtons( GetParent(hdlg),
  579. WizPage->CommonData.Buttons | PSWIZB_NEXT
  580. );
  581. b = TRUE;
  582. } else if (wParam == IDNO) {
  583. PropSheet_SetWizButtons( GetParent(hdlg),
  584. WizPage->CommonData.Buttons | PSWIZB_NEXT
  585. );
  586. b = TRUE;
  587. }
  588. else
  589. b = FALSE;
  590. break;
  591. case WMX_ACTIVATEPAGE:
  592. b = TRUE;
  593. if(wParam) {
  594. //
  595. // don't activate the page in restart mode
  596. //
  597. if (Winnt32RestartedWithAF ()) {
  598. EulaComplete = TRUE;
  599. return FALSE;
  600. }
  601. //
  602. // activation
  603. //
  604. if (!ShowEula) {
  605. //
  606. // the target install language and the source language do not match up
  607. // since this means that we might not have fonts installed for the current
  608. // language, we'll just defer this to textmode setup where we know we have
  609. // the correct fonts
  610. //
  611. EulaComplete = FALSE;
  612. if (IsDlgButtonChecked(hdlg, IDYES) == BST_CHECKED) {
  613. PropSheet_PressButton(GetParent(hdlg),
  614. (lParam == PSN_WIZBACK) ? PSBTN_BACK : PSBTN_NEXT);
  615. } else {
  616. CheckDlgButton( hdlg,IDYES, BST_CHECKED );
  617. PropSheet_PressButton(GetParent(hdlg),PSBTN_NEXT);
  618. }
  619. return(b);
  620. }
  621. //
  622. // set state of next button if user has backed up and reentered this dialog
  623. //
  624. if ( (IsDlgButtonChecked(hdlg, IDYES) == BST_CHECKED) ||
  625. (IsDlgButtonChecked(hdlg, IDNO ) == BST_CHECKED) ) {
  626. PropSheet_SetWizButtons( GetParent(hdlg),
  627. WizPage->CommonData.Buttons | PSWIZB_NEXT
  628. );
  629. } else {
  630. SendMessage(GetParent(hdlg),
  631. PSM_SETWIZBUTTONS,
  632. 0, (LPARAM)WizPage->CommonData.Buttons & (~PSWIZB_NEXT));
  633. }
  634. //
  635. // Advance page in unattended case.
  636. //
  637. UNATTENDED(PSBTN_NEXT);
  638. } else {
  639. //
  640. // deactivation
  641. //
  642. if (EulaText) FREE( EulaText );
  643. EulaText = NULL;
  644. if (IsDlgButtonChecked(hdlg, IDNO ) == BST_CHECKED) {
  645. Cancelled = TRUE;
  646. PropSheet_PressButton(GetParent(hdlg),PSBTN_CANCEL);
  647. }
  648. }
  649. break;
  650. case WMX_UNATTENDED:
  651. //
  652. // necessary?
  653. //
  654. if (EulaText) FREE( EulaText );
  655. EulaText = NULL;
  656. b = FALSE;
  657. break;
  658. case WMX_I_AM_VISIBLE:
  659. //
  660. // Force repainting first to make sure the page is visible.
  661. //
  662. InvalidateRect(hdlg,NULL,FALSE);
  663. UpdateWindow(hdlg);
  664. b = TRUE;
  665. break;
  666. default:
  667. b = FALSE;
  668. break;
  669. }
  670. return(b);
  671. }
  672. BOOL
  673. SelectPid30WizPage(
  674. IN HWND hdlg,
  675. IN UINT msg,
  676. IN WPARAM wParam,
  677. IN LPARAM lParam
  678. )
  679. /*++
  680. Routine Description:
  681. OEM Pid wizard page. depends on SourceInstallType being set correctly.
  682. Arguments:
  683. Standard window proc arguments.
  684. Returns:
  685. Message-dependent value.
  686. --*/
  687. {
  688. BOOL b;
  689. PPAGE_RUNTIME_DATA WizPage = (PPAGE_RUNTIME_DATA)GetWindowLongPtr(hdlg,DWLP_USER);
  690. static BOOL bUnattendPid = FALSE;
  691. DWORD i;
  692. switch(msg) {
  693. case WM_INITDIALOG:
  694. GetPID();
  695. // Disable the IME on the PID edit controls
  696. for (i = 0; i < 5;i++)
  697. {
  698. ImmAssociateContext(GetDlgItem(hdlg, IDT_EDIT_PID1+i), (HIMC)NULL);
  699. }
  700. //
  701. // subclass the edit controls and limit the number of characters
  702. //
  703. for (i = 0; i < 5;i++) {
  704. SendDlgItemMessage(hdlg,IDT_EDIT_PID1+i,EM_LIMITTEXT,MAX_PID30_EDIT,0);
  705. OldPidEditProc[i] = (WNDPROC)GetWindowLongPtr(GetDlgItem(hdlg, IDT_EDIT_PID1+i),GWLP_WNDPROC);
  706. SetWindowLongPtr(GetDlgItem(hdlg, IDT_EDIT_PID1+i),GWLP_WNDPROC,(LONG_PTR)PidEditSubProc);
  707. }
  708. //
  709. // set focus to first pid entry
  710. //
  711. SetFocus(GetDlgItem(hdlg,IDT_EDIT_PID1));
  712. b = FALSE;
  713. break;
  714. case WMX_ACTIVATEPAGE:
  715. CHECKUPGRADEONLY();
  716. if (BuildCmdcons) {
  717. return(FALSE);
  718. }
  719. // If we have an ecrypted PID and don't have the right crypto installed
  720. // defer the PID validation until GUI mode
  721. if (g_bDeferPIDValidation)
  722. {
  723. return FALSE;
  724. }
  725. b = TRUE;
  726. if(wParam) {
  727. //
  728. // activation
  729. //
  730. #ifdef PRERELEASE
  731. if (NoPid) {
  732. //
  733. // don't show the page in this case
  734. //
  735. b = FALSE;
  736. break;
  737. }
  738. #endif
  739. if (SourceInstallType != SelectInstall) {
  740. //
  741. // don't show the page in this case
  742. //
  743. b = FALSE;
  744. break;
  745. }
  746. //
  747. // don't activate the page in restart mode
  748. //
  749. if (Winnt32RestartedWithAF ()) {
  750. if (GetPrivateProfileString (
  751. WINNT_USERDATA,
  752. WINNT_US_PRODUCTKEY,
  753. TEXT(""),
  754. ProductId,
  755. sizeof (ProductId) / sizeof (ProductId[0]),
  756. g_DynUpdtStatus->RestartAnswerFile
  757. )) {
  758. return FALSE;
  759. }
  760. }
  761. if (UnattendedOperation) {
  762. //
  763. // make sure the pid is specified in the unattend file else we should stop
  764. //
  765. ShowPidBox(hdlg, SW_HIDE);
  766. if (SetPid30(hdlg,SourceInstallType, (LPTSTR)&ProductId) ) {
  767. UNATTENDED(PSBTN_NEXT);
  768. } else {
  769. //
  770. // a hack so that the correct wizard page is active when we put up our message box
  771. //
  772. bUnattendPid = TRUE;
  773. ShowPidBox(hdlg, SW_SHOW);
  774. PostMessage(hdlg,WMX_I_AM_VISIBLE,0,0);
  775. }
  776. }
  777. } else {
  778. //
  779. // deactivation. don't verify anything if they are backing up
  780. //
  781. if (!Cancelled && lParam != PSN_WIZBACK) {
  782. TCHAR tmpBuffer1[6];
  783. TCHAR tmpBuffer2[6];
  784. TCHAR tmpBuffer3[6];
  785. TCHAR tmpBuffer4[6];
  786. TCHAR tmpBuffer5[6];
  787. GetDlgItemText(hdlg,IDT_EDIT_PID1,tmpBuffer1,sizeof(tmpBuffer1)/sizeof(TCHAR));
  788. GetDlgItemText(hdlg,IDT_EDIT_PID2,tmpBuffer2,sizeof(tmpBuffer2)/sizeof(TCHAR));
  789. GetDlgItemText(hdlg,IDT_EDIT_PID3,tmpBuffer3,sizeof(tmpBuffer3)/sizeof(TCHAR));
  790. GetDlgItemText(hdlg,IDT_EDIT_PID4,tmpBuffer4,sizeof(tmpBuffer4)/sizeof(TCHAR));
  791. GetDlgItemText(hdlg,IDT_EDIT_PID5,tmpBuffer5,sizeof(tmpBuffer5)/sizeof(TCHAR));
  792. b = ValidatePid30( tmpBuffer1,
  793. tmpBuffer2,
  794. tmpBuffer3,
  795. tmpBuffer4,
  796. tmpBuffer5
  797. );
  798. if (!b) {
  799. if (UnattendedOperation) {
  800. // We should not fail ValidatePid30 if we succeeded
  801. // in the SetPid30 above. If we failed in SetPid30 above
  802. // we should already be showing the pid boxes.
  803. ShowPidBox(hdlg, SW_SHOW);
  804. }
  805. MessageBoxFromMessage(hdlg,
  806. bUnattendPid ? MSG_UNATTEND_OEM_PID_IS_INVALID : MSG_OEM_PID_IS_INVALID,
  807. FALSE,AppTitleStringId,MB_OK|MB_ICONSTOP);
  808. SetFocus(GetDlgItem(hdlg,IDT_EDIT_PID1));
  809. b = FALSE;
  810. } else {
  811. //
  812. // user entered a valid PID, save it for later on.
  813. //
  814. wsprintf( ProductId,
  815. TEXT("%s-%s-%s-%s-%s"),
  816. tmpBuffer1,
  817. tmpBuffer2,
  818. tmpBuffer3,
  819. tmpBuffer4,
  820. tmpBuffer5
  821. );
  822. }
  823. }
  824. }
  825. break;
  826. case WMX_I_AM_VISIBLE:
  827. //
  828. // Force repainting first to make sure the page is visible.
  829. //
  830. InvalidateRect(hdlg,NULL,FALSE);
  831. UpdateWindow(hdlg);
  832. if (bUnattendPid) {
  833. MessageBoxFromMessage(hdlg,MSG_UNATTEND_OEM_PID_IS_INVALID,FALSE,AppTitleStringId,MB_OK|MB_ICONSTOP);
  834. bUnattendPid = FALSE;
  835. }
  836. b = TRUE;
  837. break;
  838. default:
  839. b = FALSE;
  840. break;
  841. }
  842. return(b);
  843. }
  844. BOOL
  845. OemPid30WizPage(
  846. IN HWND hdlg,
  847. IN UINT msg,
  848. IN WPARAM wParam,
  849. IN LPARAM lParam
  850. )
  851. /*++
  852. Routine Description:
  853. OEM Pid wizard page. depends on SourceInstallType being set correctly.
  854. Arguments:
  855. Standard window proc arguments.
  856. Returns:
  857. Message-dependent value.
  858. --*/
  859. {
  860. BOOL b;
  861. PPAGE_RUNTIME_DATA WizPage = (PPAGE_RUNTIME_DATA)GetWindowLongPtr(hdlg,DWLP_USER);
  862. static BOOL bUnattendPid = FALSE;
  863. DWORD i;
  864. // HFONT hFont;
  865. switch(msg) {
  866. case WM_INITDIALOG:
  867. GetPID();
  868. // hFont = GetStockObject(SYSTEM_FIXED_FONT);
  869. // Disable the IME on the PID edit controls
  870. for (i = 0; i < 5;i++)
  871. {
  872. ImmAssociateContext(GetDlgItem(hdlg, IDT_EDIT_PID1+i), (HIMC)NULL);
  873. }
  874. //
  875. // subclass the edit controls and limit the number of characters
  876. //
  877. for (i = 0; i < 5;i++) {
  878. SendDlgItemMessage(hdlg,IDT_EDIT_PID1+i,EM_LIMITTEXT,MAX_PID30_EDIT,0);
  879. // SendDlgItemMessage(hdlg, IDT_EDIT_PID1+i, WM_SETFONT, hFont, TRUE );
  880. OldPidEditProc[i] = (WNDPROC)GetWindowLongPtr(GetDlgItem(hdlg, IDT_EDIT_PID1+i),GWLP_WNDPROC);
  881. SetWindowLongPtr(GetDlgItem(hdlg, IDT_EDIT_PID1+i),GWLP_WNDPROC,(LONG_PTR)PidEditSubProc);
  882. }
  883. //
  884. // set focus to first pid entry
  885. //
  886. SetFocus(GetDlgItem(hdlg,IDT_EDIT_PID1));
  887. b = FALSE;
  888. break;
  889. case WM_COMMAND:
  890. b = FALSE;
  891. break;
  892. case WMX_ACTIVATEPAGE:
  893. CHECKUPGRADEONLY();
  894. if (BuildCmdcons) {
  895. return(FALSE);
  896. }
  897. // If we have an ecrypted PID and don't have the right crypto installed
  898. // defer the PID validation until GUI mode
  899. if (g_bDeferPIDValidation)
  900. {
  901. return FALSE;
  902. }
  903. b = TRUE;
  904. if(wParam) {
  905. //
  906. // activation
  907. //
  908. #ifdef PRERELEASE
  909. if (NoPid) {
  910. //
  911. // don't show the page in this case
  912. //
  913. b = FALSE;
  914. break;
  915. }
  916. #endif
  917. if (SourceInstallType != OEMInstall) {
  918. //
  919. // don't show the page in this case
  920. //
  921. b = FALSE;
  922. break;
  923. }
  924. //
  925. // don't activate the page in restart mode
  926. //
  927. if (Winnt32RestartedWithAF ()) {
  928. if (GetPrivateProfileString (
  929. WINNT_USERDATA,
  930. WINNT_US_PRODUCTKEY,
  931. TEXT(""),
  932. ProductId,
  933. sizeof (ProductId) / sizeof (ProductId[0]),
  934. g_DynUpdtStatus->RestartAnswerFile
  935. )) {
  936. return FALSE;
  937. }
  938. }
  939. if (UnattendedOperation) {
  940. //
  941. // make sure the pid is specified in the unattend file else we should stop
  942. //
  943. if (SetPid30(hdlg,SourceInstallType, (LPTSTR)&ProductId) ) {
  944. UNATTENDED(PSBTN_NEXT);
  945. } else {
  946. //
  947. // a hack so that the correct wizard page is active when we put up our message box
  948. //
  949. bUnattendPid = TRUE;
  950. PostMessage(hdlg,WMX_I_AM_VISIBLE,0,0);
  951. }
  952. }
  953. #if 0
  954. if (!Upgrade || (SourceInstallType != OEMInstall)) {
  955. //
  956. // don't show the page in this case
  957. //
  958. b = FALSE;
  959. break;
  960. } else {
  961. NOTHING;
  962. }
  963. #endif
  964. } else {
  965. //
  966. // deactivation. don't verify anything if they are backing up
  967. //
  968. if (!Cancelled && lParam != PSN_WIZBACK) {
  969. TCHAR tmpBuffer1[6];
  970. TCHAR tmpBuffer2[6];
  971. TCHAR tmpBuffer3[6];
  972. TCHAR tmpBuffer4[6];
  973. TCHAR tmpBuffer5[6];
  974. GetDlgItemText(hdlg,IDT_EDIT_PID1,tmpBuffer1,sizeof(tmpBuffer1)/sizeof(TCHAR));
  975. GetDlgItemText(hdlg,IDT_EDIT_PID2,tmpBuffer2,sizeof(tmpBuffer2)/sizeof(TCHAR));
  976. GetDlgItemText(hdlg,IDT_EDIT_PID3,tmpBuffer3,sizeof(tmpBuffer3)/sizeof(TCHAR));
  977. GetDlgItemText(hdlg,IDT_EDIT_PID4,tmpBuffer4,sizeof(tmpBuffer4)/sizeof(TCHAR));
  978. GetDlgItemText(hdlg,IDT_EDIT_PID5,tmpBuffer5,sizeof(tmpBuffer5)/sizeof(TCHAR));
  979. b = ValidatePid30( tmpBuffer1,
  980. tmpBuffer2,
  981. tmpBuffer3,
  982. tmpBuffer4,
  983. tmpBuffer5
  984. );
  985. if (!b) {
  986. MessageBoxFromMessage(hdlg,
  987. bUnattendPid ? MSG_UNATTEND_OEM_PID_IS_INVALID : MSG_OEM_PID_IS_INVALID,
  988. FALSE,AppTitleStringId,MB_OK|MB_ICONSTOP);
  989. SetFocus(GetDlgItem(hdlg,IDT_EDIT_PID1));
  990. b = FALSE;
  991. } else {
  992. //
  993. // user entered a valid PID, save it for later on.
  994. //
  995. wsprintf( ProductId,
  996. TEXT("%s-%s-%s-%s-%s"),
  997. tmpBuffer1,
  998. tmpBuffer2,
  999. tmpBuffer3,
  1000. tmpBuffer4,
  1001. tmpBuffer5
  1002. );
  1003. }
  1004. }
  1005. }
  1006. break;
  1007. case WMX_I_AM_VISIBLE:
  1008. //
  1009. // Force repainting first to make sure the page is visible.
  1010. //
  1011. InvalidateRect(hdlg,NULL,FALSE);
  1012. UpdateWindow(hdlg);
  1013. if (bUnattendPid) {
  1014. MessageBoxFromMessage(hdlg,MSG_UNATTEND_OEM_PID_IS_INVALID,FALSE,AppTitleStringId,MB_OK|MB_ICONSTOP);
  1015. bUnattendPid = FALSE;
  1016. }
  1017. b = TRUE;
  1018. break;
  1019. default:
  1020. b = FALSE;
  1021. break;
  1022. }
  1023. return(b);
  1024. }
  1025. BOOL
  1026. CdPid30WizPage(
  1027. IN HWND hdlg,
  1028. IN UINT msg,
  1029. IN WPARAM wParam,
  1030. IN LPARAM lParam
  1031. )
  1032. /*++
  1033. Routine Description:
  1034. CD Retail pid wizard page. depends on SourceInstallType being set correctly.
  1035. Arguments:
  1036. Standard window proc arguments.
  1037. Returns:
  1038. Message-dependent value.
  1039. --*/
  1040. {
  1041. BOOL b;
  1042. PPAGE_RUNTIME_DATA WizPage = (PPAGE_RUNTIME_DATA)GetWindowLongPtr(hdlg,DWLP_USER);
  1043. static BOOL bUnattendPid = FALSE;
  1044. DWORD i;
  1045. // HFONT hFont;
  1046. switch(msg) {
  1047. case WM_INITDIALOG:
  1048. GetPID();
  1049. // hFont = GetStockObject(SYSTEM_FIXED_FONT);
  1050. // Disable the IME on the PID edit controls
  1051. for (i = 0; i < 5;i++)
  1052. {
  1053. ImmAssociateContext(GetDlgItem(hdlg, IDT_EDIT_PID1+i), (HIMC)NULL);
  1054. }
  1055. //
  1056. // subclass the edit controls and limit the number of characters
  1057. //
  1058. for (i = 0; i < 5;i++) {
  1059. SendDlgItemMessage(hdlg,IDT_EDIT_PID1+i,EM_LIMITTEXT,MAX_PID30_EDIT,0);
  1060. // SendDlgItemMessage(hdlg, IDT_EDIT_PID1+i, WM_SETFONT, hFont, TRUE );
  1061. OldPidEditProc[i] = (WNDPROC)GetWindowLongPtr(GetDlgItem(hdlg, IDT_EDIT_PID1+i),GWLP_WNDPROC);
  1062. SetWindowLongPtr(GetDlgItem(hdlg, IDT_EDIT_PID1+i),GWLP_WNDPROC,(LONG_PTR)PidEditSubProc);
  1063. }
  1064. //
  1065. // set focus to first pid entry
  1066. //
  1067. SetFocus(GetDlgItem(hdlg,IDT_EDIT_PID1));
  1068. b = FALSE;
  1069. break;
  1070. case WM_COMMAND:
  1071. //
  1072. // nothing to do here
  1073. //
  1074. b = FALSE;
  1075. break;
  1076. case WMX_ACTIVATEPAGE:
  1077. CHECKUPGRADEONLY();
  1078. if (BuildCmdcons) {
  1079. return(FALSE);
  1080. }
  1081. // If we have an ecrypted PID and don't have the right crypto installed
  1082. // defer the PID validation until GUI mode
  1083. if (g_bDeferPIDValidation)
  1084. {
  1085. return FALSE;
  1086. }
  1087. b = TRUE;
  1088. if(wParam) {
  1089. //
  1090. // activation
  1091. //
  1092. #ifdef PRERELEASE
  1093. if (NoPid) {
  1094. //
  1095. // don't show the page in this case
  1096. //
  1097. b = FALSE;
  1098. break;
  1099. }
  1100. #endif
  1101. if (SourceInstallType != RetailInstall) {
  1102. //
  1103. // don't show the page in this case
  1104. //
  1105. b = FALSE;
  1106. break;
  1107. }
  1108. //
  1109. // don't activate the page in restart mode
  1110. //
  1111. if (Winnt32RestartedWithAF ()) {
  1112. if (GetPrivateProfileString (
  1113. WINNT_USERDATA,
  1114. WINNT_US_PRODUCTKEY,
  1115. TEXT(""),
  1116. ProductId,
  1117. sizeof (ProductId) / sizeof (ProductId[0]),
  1118. g_DynUpdtStatus->RestartAnswerFile
  1119. )) {
  1120. return FALSE;
  1121. }
  1122. }
  1123. if (UnattendedOperation) {
  1124. //
  1125. // make sure the pid is specified in the unattend file else we should stop
  1126. //
  1127. if (SetPid30(hdlg,SourceInstallType, (LPTSTR)&ProductId)) {
  1128. UNATTENDED(PSBTN_NEXT);
  1129. } else {
  1130. //
  1131. // a hack so that the correct wizard page is active when we put up our message box
  1132. //
  1133. bUnattendPid = TRUE;
  1134. PostMessage(hdlg,WMX_I_AM_VISIBLE,0,0);
  1135. }
  1136. }
  1137. } else {
  1138. //
  1139. // deactivation. don't verify anything if they are backing up
  1140. //
  1141. if ( !Cancelled && lParam != PSN_WIZBACK ) {
  1142. TCHAR tmpBuffer1[6];
  1143. TCHAR tmpBuffer2[6];
  1144. TCHAR tmpBuffer3[6];
  1145. TCHAR tmpBuffer4[6];
  1146. TCHAR tmpBuffer5[6];
  1147. GetDlgItemText(hdlg,IDT_EDIT_PID1,tmpBuffer1,sizeof(tmpBuffer1)/sizeof(TCHAR));
  1148. GetDlgItemText(hdlg,IDT_EDIT_PID2,tmpBuffer2,sizeof(tmpBuffer2)/sizeof(TCHAR));
  1149. GetDlgItemText(hdlg,IDT_EDIT_PID3,tmpBuffer3,sizeof(tmpBuffer3)/sizeof(TCHAR));
  1150. GetDlgItemText(hdlg,IDT_EDIT_PID4,tmpBuffer4,sizeof(tmpBuffer4)/sizeof(TCHAR));
  1151. GetDlgItemText(hdlg,IDT_EDIT_PID5,tmpBuffer5,sizeof(tmpBuffer5)/sizeof(TCHAR));
  1152. b = ValidatePid30( tmpBuffer1,
  1153. tmpBuffer2,
  1154. tmpBuffer3,
  1155. tmpBuffer4,
  1156. tmpBuffer5
  1157. );
  1158. if (!b) {
  1159. if (PidMatchesMedia){
  1160. MessageBoxFromMessage(hdlg,
  1161. bUnattendPid ? MSG_UNATTEND_CD_PID_IS_INVALID :MSG_CD_PID_IS_INVALID,
  1162. FALSE,AppTitleStringId,MB_OK|MB_ICONSTOP);
  1163. } else {
  1164. MessageBoxFromMessage(hdlg,
  1165. UpgradeOnly ? MSG_CCP_MEDIA_FPP_PID : MSG_FPP_MEDIA_CCP_PID,
  1166. FALSE,AppTitleStringId,MB_OK|MB_ICONSTOP);
  1167. }
  1168. SetFocus(GetDlgItem(hdlg,IDT_EDIT_PID1));
  1169. b = FALSE;
  1170. } else {
  1171. //
  1172. // user entered a valid PID, save it for later on.
  1173. //
  1174. wsprintf( ProductId,
  1175. TEXT("%s-%s-%s-%s-%s"),
  1176. tmpBuffer1,
  1177. tmpBuffer2,
  1178. tmpBuffer3,
  1179. tmpBuffer4,
  1180. tmpBuffer5
  1181. );
  1182. }
  1183. }
  1184. }
  1185. break;
  1186. case WMX_I_AM_VISIBLE:
  1187. //
  1188. // Force repainting first to make sure the page is visible.
  1189. //
  1190. InvalidateRect(hdlg,NULL,FALSE);
  1191. UpdateWindow(hdlg);
  1192. if (bUnattendPid) {
  1193. MessageBoxFromMessage(hdlg,MSG_UNATTEND_CD_PID_IS_INVALID,FALSE,AppTitleStringId,MB_OK|MB_ICONSTOP);
  1194. bUnattendPid = FALSE;
  1195. }
  1196. b = TRUE;
  1197. break;
  1198. default:
  1199. b = FALSE;
  1200. break;
  1201. }
  1202. return(b);
  1203. }
  1204. LPTSTR pSelectGpID[] = { TEXT("23"),
  1205. TEXT("26"),
  1206. NULL };
  1207. LPTSTR pSelectChID[] = { TEXT("080"),
  1208. TEXT("041"),
  1209. NULL };
  1210. BOOL IsSelect(LPTSTR Pid20)
  1211. {
  1212. LPTSTR pTmp;
  1213. BOOL bSelect = FALSE;
  1214. #if defined(UNICODE)
  1215. pTmp = wcsrchr(Pid20, L'-');
  1216. #else
  1217. pTmp = strrchr(Pid20, '-');
  1218. #endif
  1219. if (pTmp)
  1220. {
  1221. int i = 0;
  1222. TCHAR GpID[3];
  1223. pTmp++;
  1224. lstrcpyn(GpID, pTmp, 3);
  1225. while (!bSelect && pSelectGpID[i])
  1226. {
  1227. bSelect = (lstrcmp(GpID, pSelectGpID[i]) == 0);
  1228. i++;
  1229. }
  1230. }
  1231. if (!bSelect)
  1232. {
  1233. // If we did not determine that we are select. This could be beta VL key
  1234. #if defined(UNICODE)
  1235. pTmp = wcschr(Pid20, L'-');
  1236. #else
  1237. pTmp = strchr(Pid20, '-');
  1238. #endif
  1239. if (pTmp)
  1240. {
  1241. int i = 0;
  1242. // The channel ID is 3 character + termination
  1243. TCHAR ChID[4];
  1244. pTmp++;
  1245. lstrcpyn(ChID, pTmp, 4); // Copy 4 characters, includingt he NULL termination.
  1246. while (!bSelect && pSelectChID[i])
  1247. {
  1248. bSelect = (lstrcmp(ChID, pSelectChID[i]) == 0);
  1249. i++;
  1250. }
  1251. }
  1252. }
  1253. return bSelect;
  1254. }
  1255. BOOL
  1256. ValidatePidEx(LPTSTR PID, BOOL *pbStepup, BOOL *bSelect)
  1257. {
  1258. TCHAR Pid20Id[MAX_PATH];
  1259. BYTE Pid30[1024]={0};
  1260. TCHAR pszSkuCode[10];
  1261. BOOL fStepUp;
  1262. // it seems that sku code really doesn't matter in winnt32, only syssetup
  1263. lstrcpy(pszSkuCode,TEXT("1797XYZZY"));
  1264. #if 0
  1265. wsprintf(DebugBuffer,
  1266. TEXT("cd-key: %s\nRPC: %s\nOEM Key: %d"),
  1267. PID,
  1268. Pid30Rpc,
  1269. (SourceInstallType == OEMInstall)
  1270. );
  1271. OutputDebugString(DebugBuffer);
  1272. #endif
  1273. *(LPDWORD)Pid30 = sizeof(Pid30);
  1274. if (!SetupPIDGen(
  1275. PID, // [IN] 25-character Secure CD-Key (gets U-Cased)
  1276. Pid30Rpc, // [IN] 5-character Release Product Code
  1277. // note sku code is not kept around in winnt32, only syssetup.
  1278. pszSkuCode, // [IN] Stock Keeping Unit (formatted like 123-12345)
  1279. (SourceInstallType == OEMInstall), // [IN] is this an OEM install?
  1280. Pid20Id, // [OUT] PID 2.0, pass in ptr to 24 character array
  1281. Pid30, // [OUT] pointer to binary PID3 buffer. First DWORD is the length
  1282. pbStepup // [OUT] optional ptr to Compliance Checking flag (can be NULL)
  1283. )) {
  1284. if (g_EncryptedPID)
  1285. {
  1286. GlobalFree(g_EncryptedPID);
  1287. g_EncryptedPID = NULL;
  1288. }
  1289. return(FALSE);
  1290. }
  1291. // PID is valid,
  1292. // if the caller wants, return if this is a Volume License PID
  1293. if(bSelect)
  1294. {
  1295. *bSelect = IsSelect(Pid20Id);
  1296. }
  1297. return TRUE;
  1298. }
  1299. BOOL
  1300. ValidatePid30(
  1301. LPTSTR Edit1,
  1302. LPTSTR Edit2,
  1303. LPTSTR Edit3,
  1304. LPTSTR Edit4,
  1305. LPTSTR Edit5
  1306. )
  1307. {
  1308. TCHAR tmpProductId[MAX_PATH]={0};
  1309. TCHAR Pid20Id[MAX_PATH];
  1310. BYTE Pid30[1024]={0};
  1311. TCHAR pszSkuCode[10];
  1312. BOOL fStepUp;
  1313. //TCHAR DebugBuffer[1024];
  1314. // until we know better, assume the Pid matches the media type
  1315. PidMatchesMedia = TRUE;
  1316. if (!Edit1 || !Edit2 || !Edit3 || !Edit4 || !Edit5) {
  1317. return(FALSE);
  1318. }
  1319. // Since we now need a PID in the select case too, fill in the string.
  1320. /*
  1321. if (SourceInstallType == SelectInstall){
  1322. tmpProductId[0] = TEXT('\0');
  1323. }
  1324. else
  1325. */
  1326. {
  1327. wsprintf( tmpProductId,
  1328. TEXT("%s-%s-%s-%s-%s"),
  1329. Edit1,
  1330. Edit2,
  1331. Edit3,
  1332. Edit4,
  1333. Edit5 );
  1334. }
  1335. if (!ValidatePidEx(tmpProductId, &fStepUp, NULL))
  1336. {
  1337. return(FALSE);
  1338. }
  1339. if (SourceInstallType != OEMInstall){
  1340. // we want OEM FPP and CCP keys to be accepted by either media. It seems like
  1341. // there will be OEM CCP media, but only FPP keys, which is why we aren't
  1342. // checking to make sure they match, as it's broken by design.
  1343. if (UpgradeOnly != fStepUp){
  1344. // user is trying to do a clean install with upgrade only media. Bad user, bad.
  1345. PidMatchesMedia = FALSE;
  1346. return FALSE;
  1347. }
  1348. }
  1349. return(TRUE);
  1350. }
  1351. void GetPID()
  1352. {
  1353. if (!ProductId[0] && UnattendedOperation && !g_bDeferPIDValidation){
  1354. //
  1355. // On Whistler upgrades, reuse existing DPID
  1356. //
  1357. BYTE abCdKey[16];
  1358. BOOL bDontCare, bSelect;
  1359. if (Upgrade &&
  1360. ISNT() &&
  1361. OsVersion.dwMajorVersion == 5 && OsVersion.dwMinorVersion == 1 &&
  1362. pGetCdKey (abCdKey)
  1363. ) {
  1364. EncodePid3g (ProductId, abCdKey);
  1365. if (ValidatePidEx(ProductId, &bDontCare, &bSelect) && bSelect)
  1366. {
  1367. HRESULT hr;
  1368. if (g_EncryptedPID)
  1369. {
  1370. GlobalFree(g_EncryptedPID);
  1371. g_EncryptedPID = NULL;
  1372. }
  1373. // Prepare the encrypted PID so that we can write it to winnt.sif
  1374. hr = PrepareEncryptedPID(ProductId, 1, &g_EncryptedPID);
  1375. if (hr != S_OK)
  1376. {
  1377. DebugLog (Winnt32LogInformation, TEXT("PrepareEncryptedPID failed: <hr=0x%1!lX!>"), 0, hr);
  1378. }
  1379. }
  1380. }
  1381. }
  1382. }
  1383. VOID ShowPidBox(
  1384. IN HWND hdlg,
  1385. IN int nCmdShow
  1386. )
  1387. /*++
  1388. Routine Description:
  1389. shows or hide the pid boxes in the wizard page
  1390. Arguments:
  1391. hdlg - window handle to pid dialog
  1392. nCmdShow - SW_SHOW or SW_HIDE
  1393. --*/
  1394. {
  1395. int i;
  1396. for (i = 0; i<5; i++) {
  1397. ShowWindow(GetDlgItem(hdlg,IDT_EDIT_PID1+i), nCmdShow);
  1398. }
  1399. }