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.

674 lines
17 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. DWORD i;
  100. BOOLEAN RetVal = FALSE;
  101. GetTempPath(ARRAYSIZE(Path),Path);
  102. GetTempFileName( Path, L"ripr", 0, DestPath);
  103. wcscpy(Path, PathToSearch);
  104. wcscat(Path, L"\\setupreg.hiv");
  105. if (!CopyFile(Path,DestPath,FALSE)) {
  106. goto e0;
  107. }
  108. SetFileAttributes(DestPath,FILE_ATTRIBUTE_NORMAL);
  109. //
  110. // need SE_RESTORE_NAME priviledge to call this API!
  111. //
  112. pSetupEnablePrivilegeW( SE_RESTORE_NAME, TRUE );
  113. //
  114. // try to unload this first in case we faulted or something and the key is still loaded
  115. //
  116. RegUnLoadKey( HKEY_LOCAL_MACHINE, HIVENAME );
  117. rslt = RegLoadKey( HKEY_LOCAL_MACHINE, HIVENAME, DestPath );
  118. if (rslt != ERROR_SUCCESS) {
  119. goto e1;
  120. }
  121. rslt = RegOpenKey(HKEY_LOCAL_MACHINE,lpszSetupReg,&hKey);
  122. if (rslt != ERROR_SUCCESS) {
  123. goto e2;
  124. }
  125. rslt = RegQueryValueEx(hKey, NULL, NULL, &Type, (LPBYTE) Buffer, &BufferSize);
  126. if (rslt != ERROR_SUCCESS || Type != REG_BINARY) {
  127. goto e3;
  128. }
  129. *SuiteMask=Buffer[3];
  130. RetVal = TRUE;
  131. e3:
  132. RegCloseKey( hKey );
  133. e2:
  134. RegUnLoadKey( HKEY_LOCAL_MACHINE, HIVENAME );
  135. e1:
  136. if (GetFileAttributes(DestPath) != 0xFFFFFFFF) {
  137. SetFileAttributes(DestPath,FILE_ATTRIBUTE_NORMAL);
  138. DeleteFile(DestPath);
  139. wcscat(DestPath, L".LOG");
  140. SetFileAttributes(DestPath,FILE_ATTRIBUTE_NORMAL);
  141. DeleteFile(DestPath);
  142. }
  143. pSetupEnablePrivilegeW( SE_RESTORE_NAME, FALSE );
  144. e0:
  145. return(RetVal);
  146. }
  147. BOOLEAN
  148. GetProductTypeFromPath(
  149. OUT PDWORD ProductType,
  150. OUT PDWORD ProductSuite,
  151. IN PCWSTR PathToSearch )
  152. /*++
  153. Routine Description:
  154. retrieves the product type and suite by looking in txtsetup.sif
  155. Arguments:
  156. ProductType - receives a VER_NT_* constant.
  157. ProductSuite - receives a VER_SUITE_* mask for the system.
  158. PathToSearch - specifies the path to the txtsetup.sif to be searched
  159. Return Value:
  160. TRUE indicates success
  161. --*/
  162. {
  163. WCHAR Path[MAX_PATH];
  164. UINT DontCare;
  165. HINF hInf;
  166. WCHAR Type[20];
  167. BOOLEAN RetVal = TRUE;
  168. INFCONTEXT Context;
  169. wcscpy(Path, PathToSearch);
  170. wcscat(Path, L"\\txtsetup.sif");
  171. hInf = SetupOpenInfFile( Path, NULL, INF_STYLE_WIN4, &DontCare );
  172. if (hInf != INVALID_HANDLE_VALUE) {
  173. if (SetupFindFirstLine( hInf, L"SetupData", L"ProductType", &Context) &&
  174. SetupGetStringField( &Context, 1, Type, ARRAYSIZE(Type), NULL)) {
  175. switch (Type[0]) {
  176. case L'0':
  177. *ProductType = VER_NT_WORKSTATION;
  178. *ProductSuite = 0;
  179. break;
  180. case L'1':
  181. *ProductType = VER_NT_SERVER;
  182. //
  183. // HACK alert: we have to call this API because txtsetup.sif
  184. // didn't have the correct product type in it in win2k.
  185. // So we do it the hard way.
  186. //
  187. if (!GetSuiteMaskFromPath( PathToSearch, ProductSuite)) {
  188. *ProductSuite = 0;
  189. }
  190. break;
  191. case L'2':
  192. *ProductType = VER_NT_SERVER;
  193. *ProductSuite = VER_SUITE_ENTERPRISE;
  194. break;
  195. case L'3':
  196. *ProductType = VER_NT_SERVER;
  197. *ProductSuite = VER_SUITE_ENTERPRISE | VER_SUITE_DATACENTER;
  198. break;
  199. case L'4':
  200. *ProductType = VER_NT_WORKSTATION;
  201. *ProductSuite = VER_SUITE_PERSONAL;
  202. break;
  203. default:
  204. ASSERT( FALSE && L"Unknown type in txtsetup.sif ProductType" );
  205. RetVal = FALSE;
  206. break;
  207. }
  208. }
  209. SetupCloseInfFile(hInf);
  210. } else {
  211. RetVal = FALSE;
  212. }
  213. return(RetVal);
  214. }
  215. //
  216. // GetNtVersionInfo( )
  217. //
  218. // Retrieves the build version from the kernel
  219. //
  220. BOOLEAN
  221. GetNtVersionInfo(
  222. PULONGLONG Version,
  223. PWCHAR SearchDir
  224. )
  225. {
  226. DWORD Error = ERROR_SUCCESS;
  227. DWORD FileVersionInfoSize;
  228. DWORD VersionHandle;
  229. ULARGE_INTEGER TmpVersion;
  230. PVOID VersionInfo;
  231. VS_FIXEDFILEINFO * FixedFileInfo;
  232. UINT FixedFileInfoLength;
  233. WCHAR Path[MAX_PATH];
  234. BOOLEAN fResult = FALSE;
  235. TraceFunc("GetNtVersionInfo( )\n");
  236. // Resulting string should be something like:
  237. // "\\server\reminst\Setup\English\Images\nt50.wks\i386\ntoskrnl.exe"
  238. if (!SearchDir) {
  239. goto e0;
  240. }
  241. wcscpy(Path, SearchDir);
  242. wcscat(Path, L"\\ntoskrnl.exe");
  243. FileVersionInfoSize = GetFileVersionInfoSize(Path, &VersionHandle);
  244. if (FileVersionInfoSize == 0)
  245. goto e0;
  246. VersionInfo = LocalAlloc( LPTR, FileVersionInfoSize );
  247. if (VersionInfo == NULL)
  248. goto e0;
  249. if (!GetFileVersionInfo(
  250. Path,
  251. VersionHandle,
  252. FileVersionInfoSize,
  253. VersionInfo))
  254. goto e1;
  255. if (!VerQueryValue(
  256. VersionInfo,
  257. L"\\",
  258. (LPVOID*)&FixedFileInfo,
  259. &FixedFileInfoLength))
  260. goto e1;
  261. TmpVersion.HighPart = FixedFileInfo->dwFileVersionMS;
  262. TmpVersion.LowPart = FixedFileInfo->dwFileVersionLS;
  263. *Version = TmpVersion.QuadPart;
  264. fResult = TRUE;
  265. e1:
  266. LocalFree( VersionInfo );
  267. e0:
  268. RETURN(fResult);
  269. }
  270. //
  271. // VerifyMatchingFlatImage( )
  272. //
  273. BOOLEAN
  274. VerifyMatchingFlatImage(
  275. PULONGLONG VersionNeeded OPTIONAL
  276. )
  277. {
  278. TraceFunc( "VerifyMatchingFlatImage( )\n" );
  279. BOOLEAN fResult = FALSE; // assume failure
  280. DWORD dwLen;
  281. WCHAR szPath[ MAX_PATH ];
  282. WIN32_FIND_DATA fd;
  283. HANDLE hFind;
  284. ULONGLONG OurVersion;
  285. DWORD OurProductType = 0, OurProductSuiteMask = 0;
  286. GetSystemDirectory( szPath, ARRAYSIZE( szPath ));
  287. GetNtVersionInfo( &OurVersion, szPath );
  288. GetInstalledProductType( &OurProductType, &OurProductSuiteMask );
  289. if (VersionNeeded) {
  290. *VersionNeeded = OurVersion;
  291. }
  292. DebugMsg(
  293. "Our NTOSKRNL verion: %u.%u:%u.%u Type: %d Suite: %d\n",
  294. HIWORD(((PULARGE_INTEGER)&OurVersion)->HighPart),
  295. LOWORD(((PULARGE_INTEGER)&OurVersion)->HighPart),
  296. HIWORD(((PULARGE_INTEGER)&OurVersion)->LowPart),
  297. LOWORD(((PULARGE_INTEGER)&OurVersion)->LowPart),
  298. OurProductType,
  299. OurProductSuiteMask);
  300. wsprintf( szPath,
  301. L"\\\\%s\\REMINST\\Setup\\%s\\%s\\",
  302. g_ServerName,
  303. g_Language,
  304. REMOTE_INSTALL_IMAGE_DIR_W );
  305. dwLen = wcslen( szPath );
  306. wcscat( szPath, L"*" );
  307. hFind = FindFirstFile( szPath, &fd );
  308. if ( hFind != INVALID_HANDLE_VALUE )
  309. {
  310. do {
  311. if ( (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  312. && StrCmp( fd.cFileName, L"." ) != 0
  313. && StrCmp( fd.cFileName, L".." ) != 0 )
  314. {
  315. ULONGLONG Version;
  316. DWORD ProductType = 0, ProductSuiteMask = 0;
  317. wsprintf( &szPath[dwLen],
  318. L"%s\\%s",
  319. fd.cFileName,
  320. g_Architecture );
  321. if ( GetNtVersionInfo( &Version, szPath ) &&
  322. GetProductTypeFromPath(
  323. &ProductType,
  324. &ProductSuiteMask,
  325. szPath ))
  326. {
  327. DebugMsg(
  328. "%s's verion: %u.%u:%u.%u Type: %d Suite: %d\n",
  329. fd.cFileName,
  330. HIWORD(((PULARGE_INTEGER)&Version)->HighPart),
  331. LOWORD(((PULARGE_INTEGER)&Version)->HighPart),
  332. HIWORD(((PULARGE_INTEGER)&Version)->LowPart),
  333. LOWORD(((PULARGE_INTEGER)&Version)->LowPart),
  334. ProductType,
  335. ProductSuiteMask);
  336. if ( OurVersion == Version &&
  337. OurProductType == ProductType &&
  338. OurProductSuiteMask == ProductSuiteMask )
  339. {
  340. wcscpy( g_ImageName, szPath );
  341. fResult = TRUE;
  342. break;
  343. }
  344. }
  345. }
  346. } while ( FindNextFile( hFind, &fd ) );
  347. }
  348. FindClose( hFind );
  349. RETURN(fResult);
  350. }
  351. //
  352. // VerifyServerName( )
  353. //
  354. // Check to see if the server is a Remote Installation Server by
  355. // checking for the existance of the "REMINST" share.
  356. //
  357. DWORD
  358. VerifyServerName( )
  359. {
  360. TraceFunc( "VerifyServerName( )\n" );
  361. NET_API_STATUS netStatus;
  362. SHARE_INFO_0 * psi;
  363. HCURSOR oldCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
  364. netStatus = NetShareGetInfo( g_ServerName, L"REMINST", 0, (LPBYTE *) &psi );
  365. if ( netStatus == NERR_Success )
  366. {
  367. NetApiBufferFree( psi );
  368. }
  369. SetCursor( oldCursor );
  370. RETURN(netStatus);
  371. }
  372. BOOL
  373. VerifyServerAccess(
  374. PCWSTR ServerShareName,
  375. PCWSTR ServerLanguage
  376. )
  377. /*++
  378. Routine Description:
  379. Checks permissions on the RIPREP server machine by trying to create a file on the
  380. server. The temp file is then deleted.
  381. Arguments:
  382. ServerShareName - path that we want to check permissions on.
  383. ServerLanguage - indicates the language subdirectory to check for access in.
  384. Return value:
  385. TRUE if the user has access to the server, FALSE otherwise.
  386. --*/
  387. {
  388. TraceFunc( "VerifyServerAccess( )\n" );
  389. WCHAR FileName[MAX_PATH];
  390. WCHAR FilePath[MAX_PATH];
  391. BOOL RetVal;
  392. HCURSOR oldCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
  393. wsprintf(FilePath,
  394. L"\\\\%s\\reminst\\Setup\\%s\\Images",
  395. ServerShareName,
  396. ServerLanguage );
  397. RetVal = GetTempFileName( FilePath , L"ACC", 0, FileName );
  398. if (RetVal) {
  399. //
  400. // delete the file, we don't want to leave turds on the server
  401. //
  402. DeleteFile(FileName);
  403. RetVal = TRUE;
  404. } else if (GetLastError() == ERROR_ACCESS_DENIED) {
  405. RetVal = FALSE;
  406. } else {
  407. //
  408. // GetTempFileName failed, but not because of an access problem, so
  409. // return success
  410. //
  411. RetVal = TRUE;
  412. }
  413. SetCursor( oldCursor );
  414. RETURN(RetVal);
  415. }
  416. //
  417. // ServerDlgCheckNextButtonActivation( )
  418. //
  419. VOID
  420. ServerDlgCheckNextButtonActivation(
  421. HWND hDlg )
  422. {
  423. TraceFunc( "ServerDlgCheckNextButtonActivation( )\n" );
  424. WCHAR szName[ MAX_PATH ];
  425. GetDlgItemText( hDlg, IDC_E_SERVER, szName, ARRAYSIZE(szName));
  426. PropSheet_SetWizButtons( GetParent( hDlg ), PSWIZB_BACK | (wcslen(szName) ? PSWIZB_NEXT : 0 ) );
  427. TraceFuncExit( );
  428. }
  429. //
  430. // ServerDlgProc()
  431. //
  432. INT_PTR CALLBACK
  433. ServerDlgProc(
  434. HWND hDlg,
  435. UINT uMsg,
  436. WPARAM wParam,
  437. LPARAM lParam )
  438. {
  439. ULARGE_INTEGER ImageVersion;
  440. WCHAR szTemp[ 1024 ];
  441. WCHAR szCaption[ 1024 ];
  442. WCHAR ErrorText[ 1024 ];
  443. DWORD dw;
  444. switch (uMsg)
  445. {
  446. default:
  447. return FALSE;
  448. case WM_INITDIALOG:
  449. CenterDialog( GetParent( hDlg ) );
  450. return FALSE;
  451. case WM_COMMAND:
  452. switch ( LOWORD( wParam ) )
  453. {
  454. case IDC_E_SERVER:
  455. if ( HIWORD( wParam ) == EN_CHANGE )
  456. {
  457. ServerDlgCheckNextButtonActivation( hDlg );
  458. }
  459. break;
  460. }
  461. break;
  462. case WM_NOTIFY:
  463. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, FALSE );
  464. LPNMHDR lpnmhdr = (LPNMHDR) lParam;
  465. switch ( lpnmhdr->code )
  466. {
  467. case PSN_WIZNEXT:
  468. {
  469. GetDlgItemText( hDlg, IDC_E_SERVER, g_ServerName, ARRAYSIZE(g_ServerName) );
  470. //remove the wackwack if found
  471. if ( g_ServerName[0] == L'\\' && g_ServerName[1] == L'\\' )
  472. {
  473. wcscpy( g_ServerName, &g_ServerName[2] );
  474. }
  475. Assert( wcslen( g_ServerName ) );
  476. DWORD dwErr = VerifyServerName( );
  477. if ( dwErr != ERROR_SUCCESS )
  478. {
  479. switch (dwErr)
  480. {
  481. case NERR_NetNameNotFound:
  482. MessageBoxFromStrings( hDlg, IDS_NOT_A_BINL_SERVER_TITLE, IDS_NOT_A_BINL_SERVER_TEXT, MB_OK );
  483. break;
  484. default:
  485. dw = LoadString( g_hinstance, IDS_FAILED_TO_CONTACT_SERVER_TITLE, szTemp, ARRAYSIZE(szTemp) );
  486. Assert( dw );
  487. MessageBoxFromError( hDlg, szTemp, dwErr, NULL, MB_OK );
  488. break;
  489. }
  490. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, -1 ); // don't go on
  491. break;
  492. }
  493. BOOL fFoundMatchingFlatImage = VerifyMatchingFlatImage( (PULONGLONG)&ImageVersion );
  494. if ( !fFoundMatchingFlatImage )
  495. {
  496. dw = LoadString( g_hinstance, IDS_MISSING_BACKING_FLAT_IMAGE_TEXT, szTemp, ARRAYSIZE(szTemp) );
  497. ASSERT(dw);
  498. dw = LoadString( g_hinstance, IDS_MISSING_BACKING_FLAT_IMAGE_TITLE, szCaption, ARRAYSIZE(szCaption) );
  499. ASSERT(dw);
  500. wsprintf(
  501. ErrorText,
  502. szTemp,
  503. HIWORD(ImageVersion.HighPart),
  504. LOWORD(ImageVersion.HighPart),
  505. HIWORD(ImageVersion.LowPart),
  506. g_Language );
  507. MessageBox( hDlg, ErrorText, szCaption, MB_OK );
  508. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, -1 ); // don't go on
  509. break;
  510. }
  511. if (!VerifyServerAccess(g_ServerName,g_Language)) {
  512. dw = LoadString( g_hinstance, IDS_SERVER_ACCESS_DESC, ErrorText, ARRAYSIZE(ErrorText) );
  513. ASSERT(dw);
  514. dw = LoadString( g_hinstance, IDS_SERVER_ACCESS, szCaption, ARRAYSIZE(szCaption) );
  515. ASSERT(dw);
  516. MessageBox( hDlg, ErrorText, szCaption, MB_OK );
  517. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, -1 ); // don't go on
  518. break;
  519. }
  520. }
  521. break;
  522. case PSN_QUERYCANCEL:
  523. return VerifyCancel( hDlg );
  524. case PSN_SETACTIVE:
  525. SetDlgItemText( hDlg, IDC_E_SERVER, g_ServerName );
  526. ServerDlgCheckNextButtonActivation( hDlg );
  527. ClearMessageQueue( );
  528. break;
  529. }
  530. break;
  531. }
  532. return TRUE;
  533. }