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.

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