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.

709 lines
19 KiB

  1. /****************************************************************************
  2. Copyright (c) Microsoft Corporation 1998
  3. All rights reserved
  4. File: SERVERDLG.CPP
  5. ***************************************************************************/
  6. #include "pch.h"
  7. #include "callback.h"
  8. #include "utils.h"
  9. #include <winver.h>
  10. #include <sputils.h>
  11. DEFINE_MODULE( "RIPREP" )
  12. BOOLEAN
  13. GetInstalledProductType(
  14. OUT PDWORD ProductType,
  15. OUT PDWORD ProductSuite
  16. )
  17. /*++
  18. Routine Description:
  19. retrieves the product type and suite from a running system
  20. Arguments:
  21. ProductType - receives a VER_NT_* constant.
  22. ProductSuite - receives a VER_SUITE_* mask for the system.
  23. Return Value:
  24. TRUE indicates success
  25. --*/
  26. {
  27. OSVERSIONINFOEX VersionInfo;
  28. VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo);
  29. if (GetVersionEx((OSVERSIONINFO *)&VersionInfo)) {
  30. //
  31. // make domain controllers and servers look the same
  32. //
  33. *ProductType = (VersionInfo.wProductType == VER_NT_DOMAIN_CONTROLLER)
  34. ? VER_NT_SERVER
  35. : VersionInfo.wProductType;
  36. //
  37. // we only care about suites that have a SKU associated with them.
  38. //
  39. *ProductSuite = (VersionInfo.wSuiteMask
  40. & (VER_SUITE_ENTERPRISE | VER_SUITE_DATACENTER | VER_SUITE_PERSONAL)) ;
  41. return(TRUE);
  42. }
  43. return(FALSE);
  44. }
  45. BOOL
  46. pSetupEnablePrivilegeW(
  47. IN PCWSTR PrivilegeName,
  48. IN BOOL Enable
  49. )
  50. /*++
  51. Routine Description:
  52. Enable or disable a given named privilege.
  53. Arguments:
  54. PrivilegeName - supplies the name of a system privilege.
  55. Enable - flag indicating whether to enable or disable the privilege.
  56. Return Value:
  57. Boolean value indicating whether the operation was successful.
  58. --*/
  59. {
  60. HANDLE Token;
  61. BOOL b;
  62. TOKEN_PRIVILEGES NewPrivileges;
  63. LUID Luid;
  64. if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&Token)) {
  65. return(FALSE);
  66. }
  67. if(!LookupPrivilegeValue(NULL,PrivilegeName,&Luid)) {
  68. CloseHandle(Token);
  69. return(FALSE);
  70. }
  71. NewPrivileges.PrivilegeCount = 1;
  72. NewPrivileges.Privileges[0].Luid = Luid;
  73. NewPrivileges.Privileges[0].Attributes = Enable ? SE_PRIVILEGE_ENABLED : 0;
  74. b = AdjustTokenPrivileges(
  75. Token,
  76. FALSE,
  77. &NewPrivileges,
  78. 0,
  79. NULL,
  80. NULL
  81. );
  82. CloseHandle(Token);
  83. return(b);
  84. }
  85. GetSuiteMaskFromPath(
  86. IN PCWSTR PathToSearch,
  87. OUT PDWORD SuiteMask
  88. )
  89. {
  90. #define HIVENAME L"riprepsetupreg"
  91. TCHAR lpszSetupReg[MAX_PATH] = HIVENAME L"\\ControlSet001\\Services\\setupdd";
  92. WCHAR Path[MAX_PATH];
  93. WCHAR DestPath[MAX_PATH];
  94. LONG rslt;
  95. HKEY hKey;
  96. DWORD Type;
  97. DWORD Buffer[4];
  98. DWORD BufferSize = sizeof(Buffer);
  99. BOOLEAN RetVal = FALSE;
  100. GetTempPath(ARRAYSIZE(Path),Path);
  101. GetTempFileName( Path, L"ripr", 0, DestPath);
  102. if (-1 == _snwprintf(
  103. Path,
  104. MAX_PATH,
  105. L"%ws\\setupreg.hiv",
  106. PathToSearch)) {
  107. goto e0;
  108. }
  109. TERMINATE_BUFFER(Path);
  110. if (!CopyFile(Path,DestPath,FALSE)) {
  111. goto e0;
  112. }
  113. SetFileAttributes(DestPath,FILE_ATTRIBUTE_NORMAL);
  114. //
  115. // need SE_RESTORE_NAME priviledge to call this API!
  116. //
  117. pSetupEnablePrivilegeW( SE_RESTORE_NAME, TRUE );
  118. //
  119. // try to unload this first in case we faulted or something and the key is still loaded
  120. //
  121. RegUnLoadKey( HKEY_LOCAL_MACHINE, HIVENAME );
  122. rslt = RegLoadKey( HKEY_LOCAL_MACHINE, HIVENAME, DestPath );
  123. if (rslt != ERROR_SUCCESS) {
  124. goto e1;
  125. }
  126. rslt = RegOpenKey(HKEY_LOCAL_MACHINE,lpszSetupReg,&hKey);
  127. if (rslt != ERROR_SUCCESS) {
  128. goto e2;
  129. }
  130. rslt = RegQueryValueEx(hKey, NULL, NULL, &Type, (LPBYTE) Buffer, &BufferSize);
  131. if (rslt != ERROR_SUCCESS || Type != REG_BINARY) {
  132. goto e3;
  133. }
  134. *SuiteMask=Buffer[3];
  135. RetVal = TRUE;
  136. e3:
  137. RegCloseKey( hKey );
  138. e2:
  139. RegUnLoadKey( HKEY_LOCAL_MACHINE, HIVENAME );
  140. e1:
  141. if (GetFileAttributes(DestPath) != 0xFFFFFFFF) {
  142. SetFileAttributes(DestPath,FILE_ATTRIBUTE_NORMAL);
  143. DeleteFile(DestPath);
  144. wcscat(DestPath, L".LOG");
  145. SetFileAttributes(DestPath,FILE_ATTRIBUTE_NORMAL);
  146. DeleteFile(DestPath);
  147. }
  148. pSetupEnablePrivilegeW( SE_RESTORE_NAME, FALSE );
  149. e0:
  150. return(RetVal);
  151. }
  152. BOOLEAN
  153. GetProductTypeFromPath(
  154. OUT PDWORD ProductType,
  155. OUT PDWORD ProductSuite,
  156. IN PCWSTR PathToSearch )
  157. /*++
  158. Routine Description:
  159. retrieves the product type and suite by looking in txtsetup.sif
  160. Arguments:
  161. ProductType - receives a VER_NT_* constant.
  162. ProductSuite - receives a VER_SUITE_* mask for the system.
  163. PathToSearch - specifies the path to the txtsetup.sif to be searched
  164. Return Value:
  165. TRUE indicates success
  166. --*/
  167. {
  168. WCHAR Path[MAX_PATH];
  169. UINT DontCare;
  170. HINF hInf;
  171. WCHAR Type[20];
  172. BOOLEAN RetVal = TRUE;
  173. INFCONTEXT Context;
  174. if (-1 == _snwprintf(
  175. Path,
  176. MAX_PATH,
  177. L"%ws\\txtsetup.sif",
  178. PathToSearch)) {
  179. RetVal = FALSE;
  180. goto e0;
  181. }
  182. TERMINATE_BUFFER(Path);
  183. hInf = SetupOpenInfFile( Path, NULL, INF_STYLE_WIN4, &DontCare );
  184. if (hInf == INVALID_HANDLE_VALUE) {
  185. RetVal = FALSE;
  186. goto e0;
  187. }
  188. if (SetupFindFirstLine( hInf, L"SetupData", L"ProductType", &Context) &&
  189. SetupGetStringField( &Context, 1, Type, ARRAYSIZE(Type), NULL)) {
  190. switch (Type[0]) {
  191. case L'0':
  192. *ProductType = VER_NT_WORKSTATION;
  193. *ProductSuite = 0;
  194. break;
  195. case L'1':
  196. *ProductType = VER_NT_SERVER;
  197. //
  198. // HACK alert: we have to call this API because txtsetup.sif
  199. // didn't have the correct product type in it in win2k.
  200. // So we do it the hard way.
  201. //
  202. if (!GetSuiteMaskFromPath( PathToSearch, ProductSuite)) {
  203. *ProductSuite = 0;
  204. }
  205. break;
  206. case L'2':
  207. *ProductType = VER_NT_SERVER;
  208. *ProductSuite = VER_SUITE_ENTERPRISE;
  209. break;
  210. case L'3':
  211. *ProductType = VER_NT_SERVER;
  212. *ProductSuite = VER_SUITE_ENTERPRISE | VER_SUITE_DATACENTER;
  213. break;
  214. case L'4':
  215. *ProductType = VER_NT_WORKSTATION;
  216. *ProductSuite = VER_SUITE_PERSONAL;
  217. break;
  218. default:
  219. ASSERT( FALSE && L"Unknown type in txtsetup.sif ProductType" );
  220. RetVal = FALSE;
  221. break;
  222. }
  223. }
  224. SetupCloseInfFile(hInf);
  225. e0:
  226. return(RetVal);
  227. }
  228. //
  229. // GetNtVersionInfo( )
  230. //
  231. // Retrieves the build version from the kernel
  232. //
  233. BOOLEAN
  234. GetNtVersionInfo(
  235. PULONGLONG Version,
  236. PWCHAR SearchDir
  237. )
  238. {
  239. DWORD FileVersionInfoSize;
  240. DWORD VersionHandle;
  241. ULARGE_INTEGER TmpVersion;
  242. PVOID VersionInfo;
  243. VS_FIXEDFILEINFO * FixedFileInfo;
  244. UINT FixedFileInfoLength;
  245. WCHAR Path[MAX_PATH];
  246. BOOLEAN fResult = FALSE;
  247. TraceFunc("GetNtVersionInfo( )\n");
  248. // Resulting string should be something like:
  249. // "\\server\reminst\Setup\English\Images\nt50.wks\i386\ntoskrnl.exe"
  250. if (!SearchDir) {
  251. goto e0;
  252. }
  253. lstrcpyn(Path, SearchDir, ARRAYSIZE(Path));
  254. wcsncat(Path, L"\\ntoskrnl.exe", ARRAYSIZE(Path) - lstrlen(Path));
  255. TERMINATE_BUFFER(Path);
  256. FileVersionInfoSize = GetFileVersionInfoSize(Path, &VersionHandle);
  257. if (FileVersionInfoSize == 0)
  258. goto e0;
  259. VersionInfo = LocalAlloc( LPTR, FileVersionInfoSize );
  260. if (VersionInfo == NULL)
  261. goto e0;
  262. if (!GetFileVersionInfo(
  263. Path,
  264. VersionHandle,
  265. FileVersionInfoSize,
  266. VersionInfo)) {
  267. goto e1;
  268. }
  269. if (!VerQueryValue(
  270. VersionInfo,
  271. L"\\",
  272. (LPVOID*)&FixedFileInfo,
  273. &FixedFileInfoLength)) {
  274. goto e1;
  275. }
  276. TmpVersion.HighPart = FixedFileInfo->dwFileVersionMS;
  277. TmpVersion.LowPart = FixedFileInfo->dwFileVersionLS;
  278. //
  279. // We need to whack the low 16 bits of the .LowPart so that
  280. // we ignore the service pack value. For example, WindowsXP has a
  281. // version number of 5.1.2600.0. XP-ServicePack1 has a version
  282. // number of 5.1.2600.1038. We'd like those to match, so just whack
  283. // the servicepack number portion.
  284. //
  285. TmpVersion.LowPart &= 0xFFFF0000;
  286. *Version = TmpVersion.QuadPart;
  287. fResult = TRUE;
  288. e1:
  289. LocalFree( VersionInfo );
  290. e0:
  291. RETURN(fResult);
  292. }
  293. //
  294. // VerifyMatchingFlatImage( )
  295. //
  296. BOOLEAN
  297. VerifyMatchingFlatImage(
  298. PULONGLONG VersionNeeded OPTIONAL
  299. )
  300. {
  301. TraceFunc( "VerifyMatchingFlatImage( )\n" );
  302. BOOLEAN fResult = FALSE; // assume failure
  303. DWORD dwLen;
  304. WCHAR szPath[ MAX_PATH ];
  305. WIN32_FIND_DATA fd;
  306. HANDLE hFind;
  307. ULONGLONG OurVersion;
  308. DWORD OurProductType = 0, OurProductSuiteMask = 0;
  309. GetSystemDirectory( szPath, ARRAYSIZE( szPath ));
  310. GetNtVersionInfo( &OurVersion, szPath );
  311. GetInstalledProductType( &OurProductType, &OurProductSuiteMask );
  312. if (VersionNeeded) {
  313. *VersionNeeded = OurVersion;
  314. }
  315. DebugMsg(
  316. "Our NTOSKRNL verion: %u.%u:%u.%u Type: %d Suite: %d\n",
  317. HIWORD(((PULARGE_INTEGER)&OurVersion)->HighPart),
  318. LOWORD(((PULARGE_INTEGER)&OurVersion)->HighPart),
  319. HIWORD(((PULARGE_INTEGER)&OurVersion)->LowPart),
  320. LOWORD(((PULARGE_INTEGER)&OurVersion)->LowPart),
  321. OurProductType,
  322. OurProductSuiteMask);
  323. _snwprintf( szPath,
  324. ARRAYSIZE(szPath),
  325. L"\\\\%s\\REMINST\\Setup\\%s\\%s\\",
  326. g_ServerName,
  327. g_Language,
  328. REMOTE_INSTALL_IMAGE_DIR_W );
  329. TERMINATE_BUFFER(szPath);
  330. dwLen = wcslen( szPath );
  331. wcsncat(szPath, L"*", ARRAYSIZE(szPath) - lstrlen(szPath));
  332. TERMINATE_BUFFER(szPath);
  333. hFind = FindFirstFile( szPath, &fd );
  334. if ( hFind != INVALID_HANDLE_VALUE )
  335. {
  336. do {
  337. if ( (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  338. && StrCmp( fd.cFileName, L"." ) != 0
  339. && StrCmp( fd.cFileName, L".." ) != 0 )
  340. {
  341. ULONGLONG Version;
  342. DWORD ProductType = 0, ProductSuiteMask = 0;
  343. _snwprintf( &szPath[dwLen],
  344. ARRAYSIZE(szPath) - dwLen,
  345. L"%s\\%s",
  346. fd.cFileName,
  347. g_Architecture );
  348. TERMINATE_BUFFER(szPath);
  349. if ( GetNtVersionInfo( &Version, szPath ) &&
  350. GetProductTypeFromPath(
  351. &ProductType,
  352. &ProductSuiteMask,
  353. szPath ))
  354. {
  355. DebugMsg(
  356. "%s's verion: %u.%u:%u.%u Type: %d Suite: %d\n",
  357. fd.cFileName,
  358. HIWORD(((PULARGE_INTEGER)&Version)->HighPart),
  359. LOWORD(((PULARGE_INTEGER)&Version)->HighPart),
  360. HIWORD(((PULARGE_INTEGER)&Version)->LowPart),
  361. LOWORD(((PULARGE_INTEGER)&Version)->LowPart),
  362. ProductType,
  363. ProductSuiteMask);
  364. if ( OurVersion == Version &&
  365. OurProductType == ProductType &&
  366. OurProductSuiteMask == ProductSuiteMask )
  367. {
  368. wcscpy( g_ImageName, szPath );
  369. fResult = TRUE;
  370. break;
  371. }
  372. }
  373. }
  374. } while ( FindNextFile( hFind, &fd ) );
  375. }
  376. FindClose( hFind );
  377. RETURN(fResult);
  378. }
  379. //
  380. // VerifyServerName( )
  381. //
  382. // Check to see if the server is a Remote Installation Server by
  383. // checking for the existance of the "REMINST" share.
  384. //
  385. DWORD
  386. VerifyServerName( )
  387. {
  388. TraceFunc( "VerifyServerName( )\n" );
  389. NET_API_STATUS netStatus;
  390. SHARE_INFO_0 * psi;
  391. HCURSOR oldCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
  392. netStatus = NetShareGetInfo( g_ServerName, L"REMINST", 0, (LPBYTE *) &psi );
  393. if ( netStatus == NERR_Success )
  394. {
  395. NetApiBufferFree( psi );
  396. }
  397. SetCursor( oldCursor );
  398. RETURN(netStatus);
  399. }
  400. BOOL
  401. VerifyServerAccess(
  402. PCWSTR ServerShareName,
  403. PCWSTR ServerLanguage
  404. )
  405. /*++
  406. Routine Description:
  407. Checks permissions on the RIPREP server machine by trying to create a file on the
  408. server. The temp file is then deleted.
  409. Arguments:
  410. ServerShareName - path that we want to check permissions on.
  411. ServerLanguage - indicates the language subdirectory to check for access in.
  412. Return value:
  413. TRUE if the user has access to the server, FALSE otherwise.
  414. --*/
  415. {
  416. TraceFunc( "VerifyServerAccess( )\n" );
  417. WCHAR FileName[MAX_PATH];
  418. WCHAR FilePath[MAX_PATH];
  419. BOOL RetVal;
  420. HCURSOR oldCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
  421. _snwprintf(FilePath,
  422. ARRAYSIZE(FilePath),
  423. L"\\\\%s\\reminst\\Setup\\%s\\Images",
  424. ServerShareName,
  425. ServerLanguage );
  426. TERMINATE_BUFFER(FilePath);
  427. RetVal = GetTempFileName( FilePath , L"ACC", 0, FileName );
  428. if (RetVal) {
  429. //
  430. // delete the file, we don't want to leave turds on the server
  431. //
  432. DeleteFile(FileName);
  433. RetVal = TRUE;
  434. } else if (GetLastError() == ERROR_ACCESS_DENIED) {
  435. RetVal = FALSE;
  436. } else {
  437. //
  438. // GetTempFileName failed, but not because of an access problem, so
  439. // return success
  440. //
  441. RetVal = TRUE;
  442. }
  443. SetCursor( oldCursor );
  444. RETURN(RetVal);
  445. }
  446. //
  447. // ServerDlgCheckNextButtonActivation( )
  448. //
  449. VOID
  450. ServerDlgCheckNextButtonActivation(
  451. HWND hDlg )
  452. {
  453. TraceFunc( "ServerDlgCheckNextButtonActivation( )\n" );
  454. WCHAR szName[ MAX_PATH ];
  455. GetDlgItemText( hDlg, IDC_E_SERVER, szName, ARRAYSIZE(szName));
  456. PropSheet_SetWizButtons( GetParent( hDlg ), PSWIZB_BACK | (wcslen(szName) ? PSWIZB_NEXT : 0 ) );
  457. TraceFuncExit( );
  458. }
  459. //
  460. // ServerDlgProc()
  461. //
  462. INT_PTR CALLBACK
  463. ServerDlgProc(
  464. HWND hDlg,
  465. UINT uMsg,
  466. WPARAM wParam,
  467. LPARAM lParam )
  468. {
  469. ULARGE_INTEGER ImageVersion;
  470. WCHAR szTemp[ 1024 ];
  471. WCHAR szCaption[ 1024 ];
  472. WCHAR ErrorText[ 1024 ];
  473. DWORD dw;
  474. switch (uMsg)
  475. {
  476. default:
  477. return FALSE;
  478. case WM_INITDIALOG:
  479. CenterDialog( GetParent( hDlg ) );
  480. return FALSE;
  481. case WM_COMMAND:
  482. switch ( LOWORD( wParam ) )
  483. {
  484. case IDC_E_SERVER:
  485. if ( HIWORD( wParam ) == EN_CHANGE )
  486. {
  487. ServerDlgCheckNextButtonActivation( hDlg );
  488. }
  489. break;
  490. }
  491. break;
  492. case WM_NOTIFY:
  493. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, FALSE );
  494. LPNMHDR lpnmhdr = (LPNMHDR) lParam;
  495. switch ( lpnmhdr->code )
  496. {
  497. case PSN_WIZNEXT:
  498. {
  499. GetDlgItemText( hDlg, IDC_E_SERVER, g_ServerName, ARRAYSIZE(g_ServerName) );
  500. //remove the wackwack if found
  501. if ( g_ServerName[0] == L'\\' && g_ServerName[1] == L'\\' )
  502. {
  503. wcscpy( g_ServerName, &g_ServerName[2] );
  504. }
  505. Assert( wcslen( g_ServerName ) );
  506. DWORD dwErr = VerifyServerName( );
  507. if ( dwErr != ERROR_SUCCESS )
  508. {
  509. switch (dwErr)
  510. {
  511. case NERR_NetNameNotFound:
  512. MessageBoxFromStrings( hDlg, IDS_NOT_A_BINL_SERVER_TITLE, IDS_NOT_A_BINL_SERVER_TEXT, MB_OK );
  513. break;
  514. default:
  515. dw = LoadString( g_hinstance, IDS_FAILED_TO_CONTACT_SERVER_TITLE, szTemp, ARRAYSIZE(szTemp) );
  516. Assert( dw );
  517. MessageBoxFromError( hDlg, szTemp, dwErr, NULL, MB_OK );
  518. break;
  519. }
  520. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, -1 ); // don't go on
  521. break;
  522. }
  523. BOOL fFoundMatchingFlatImage = VerifyMatchingFlatImage( (PULONGLONG)&ImageVersion );
  524. if ( !fFoundMatchingFlatImage )
  525. {
  526. dw = LoadString( g_hinstance, IDS_MISSING_BACKING_FLAT_IMAGE_TEXT, szTemp, ARRAYSIZE(szTemp) );
  527. ASSERT(dw);
  528. dw = LoadString( g_hinstance, IDS_MISSING_BACKING_FLAT_IMAGE_TITLE, szCaption, ARRAYSIZE(szCaption) );
  529. ASSERT(dw);
  530. _snwprintf(
  531. ErrorText,
  532. ARRAYSIZE(ErrorText),
  533. szTemp,
  534. HIWORD(ImageVersion.HighPart),
  535. LOWORD(ImageVersion.HighPart),
  536. HIWORD(ImageVersion.LowPart),
  537. g_Language );
  538. TERMINATE_BUFFER(ErrorText);
  539. MessageBox( hDlg, ErrorText, szCaption, MB_OK );
  540. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, -1 ); // don't go on
  541. break;
  542. }
  543. if (!VerifyServerAccess(g_ServerName,g_Language)) {
  544. dw = LoadString( g_hinstance, IDS_SERVER_ACCESS_DESC, ErrorText, ARRAYSIZE(ErrorText) );
  545. ASSERT(dw);
  546. dw = LoadString( g_hinstance, IDS_SERVER_ACCESS, szCaption, ARRAYSIZE(szCaption) );
  547. ASSERT(dw);
  548. MessageBox( hDlg, ErrorText, szCaption, MB_OK );
  549. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, -1 ); // don't go on
  550. break;
  551. }
  552. }
  553. break;
  554. case PSN_QUERYCANCEL:
  555. return VerifyCancel( hDlg );
  556. case PSN_SETACTIVE:
  557. SetDlgItemText( hDlg, IDC_E_SERVER, g_ServerName );
  558. ServerDlgCheckNextButtonActivation( hDlg );
  559. ClearMessageQueue( );
  560. break;
  561. }
  562. break;
  563. }
  564. return TRUE;
  565. }