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.

834 lines
24 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Copyright (c) 1997-1999 Microsoft Corporation
  4. // All rights reserved.
  5. //
  6. // File Name:
  7. // distfold.c
  8. //
  9. // Description:
  10. // This file contains the dialog proc for the IDD_DISTFOLD page.
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "pch.h"
  14. #include "resource.h"
  15. #include <lm.h>
  16. #include <winnetwk.h>
  17. static TCHAR *StrSelectDistFolder;
  18. static TCHAR *StrWindowsDistibFolder;
  19. //----------------------------------------------------------------------------
  20. //
  21. // Function: OnSetActiveDistFolder
  22. //
  23. // Purpose: Called when the page is about to display.
  24. //
  25. //----------------------------------------------------------------------------
  26. VOID
  27. OnSetActiveDistFolder(HWND hwnd)
  28. {
  29. SetDlgItemText(hwnd, IDT_DISTFOLDER, WizGlobals.DistFolder);
  30. SetDlgItemText(hwnd, IDT_SHARENAME, WizGlobals.DistShareName);
  31. WIZ_BUTTONS(hwnd, PSWIZB_BACK | PSWIZB_NEXT);
  32. }
  33. //----------------------------------------------------------------------------
  34. //
  35. // Function: ConvertRelativePathToUncPath
  36. //
  37. // Purpose: If the path is a local path or a network path, it is converted
  38. // to its UNC equivalent. If the path is already a UNC path then
  39. // it is just copied and returned. The output variable
  40. // UncDistFolder is assumed to be of MAX_PATH length.
  41. //
  42. // Arguments:
  43. //
  44. // Returns: BOOL
  45. // TRUE - on success,
  46. // FALSE - on failure
  47. //
  48. //----------------------------------------------------------------------------
  49. BOOL
  50. ConvertRelativePathToUncPath( IN const TCHAR *szRelativePath,
  51. OUT TCHAR *UncDistFolder,
  52. IN DWORD cbSize) {
  53. TCHAR szLocalName[MAX_PATH];
  54. TCHAR szDistribFolderDirPath[MAX_PATH];
  55. TCHAR szUncPath[MAX_PATH];
  56. const TCHAR *pDirString;
  57. DWORD dwReturnValue;
  58. DWORD dwSize;
  59. HRESULT hrPrintf;
  60. //
  61. // Check and see if it is already a UNC Path, just checking to see if it
  62. // begins with a \
  63. //
  64. if( szRelativePath[0] == _T('\\') ) {
  65. lstrcpyn( UncDistFolder, szRelativePath, cbSize );
  66. return( TRUE );
  67. }
  68. if( IsPathOnLocalDiskDrive( szRelativePath ) )
  69. {
  70. const TCHAR *pDirPath;
  71. TCHAR szLocalComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  72. HRESULT hrCat;
  73. dwSize = MAX_COMPUTERNAME_LENGTH + 1;
  74. if( ! GetComputerName( szLocalComputerName, &dwSize ) )
  75. {
  76. ReportErrorId( NULL,
  77. MSGTYPE_ERR | MSGTYPE_WIN32,
  78. IDS_ERR_CANNOT_GET_LOCAL_COMPNAME );
  79. return( FALSE );
  80. }
  81. hrPrintf=StringCchPrintf( UncDistFolder, cbSize, _T("\\\\%s\\"), szLocalComputerName );
  82. pDirPath = szRelativePath;
  83. //
  84. // Set the dir path to just past the first \
  85. //
  86. pDirPath = pDirPath + 3;
  87. hrCat=StringCchCat( UncDistFolder, cbSize, pDirPath );
  88. return( TRUE );
  89. }
  90. else
  91. {
  92. hrPrintf=StringCchPrintf( szLocalName, AS(szLocalName), _T("%c:"), szRelativePath[0] );
  93. pDirString = szRelativePath + 3;
  94. lstrcpyn( szDistribFolderDirPath, pDirString, AS(szDistribFolderDirPath) );
  95. dwSize = StrBuffSize( szUncPath );
  96. dwReturnValue = WNetGetConnection( szLocalName, szUncPath, &dwSize );
  97. if( dwReturnValue == NO_ERROR ) {
  98. lstrcpyn( UncDistFolder, szUncPath, cbSize );
  99. // Note:ConcatenatePaths will truncate to avoid buffer overrun
  100. ConcatenatePaths( UncDistFolder,
  101. szDistribFolderDirPath,
  102. NULL );
  103. return( TRUE );
  104. }
  105. else if( dwReturnValue == ERROR_BAD_DEVICE ) {
  106. ReportErrorId( NULL,
  107. MSGTYPE_ERR,
  108. IDS_ERR_NETWORK_BAD_DEVICE );
  109. }
  110. else if( dwReturnValue == ERROR_NOT_CONNECTED ) {
  111. ReportErrorId( NULL,
  112. MSGTYPE_ERR,
  113. IDS_ERR_NETWORK_NOT_CONNECTED );
  114. }
  115. else if( dwReturnValue == ERROR_CONNECTION_UNAVAIL ) {
  116. ReportErrorId( NULL,
  117. MSGTYPE_ERR,
  118. IDS_ERR_NETWORK_CONNECTION_UNAVAIL );
  119. }
  120. else if( dwReturnValue == ERROR_NO_NETWORK ) {
  121. ReportErrorId( NULL,
  122. MSGTYPE_ERR,
  123. IDS_ERR_NETWORK_NO_NETWORK );
  124. }
  125. else if( dwReturnValue == ERROR_NO_NET_OR_BAD_PATH ) {
  126. ReportErrorId( NULL,
  127. MSGTYPE_ERR,
  128. IDS_ERR_NETWORK_NO_NETWORK );
  129. }
  130. else if( dwReturnValue == ERROR_EXTENDED_ERROR ) {
  131. TCHAR szErrorString[MAX_STRING_LEN];
  132. TCHAR szProviderName[MAX_STRING_LEN];
  133. TCHAR szErrorCode[MAX_STRING_LEN];
  134. DWORD dwErrorCode;
  135. DWORD dwErrorSize = StrBuffSize( szErrorString );
  136. DWORD dwProviderSize = StrBuffSize( szProviderName );
  137. WNetGetLastError( &dwErrorCode,
  138. szErrorString,
  139. dwErrorSize,
  140. szProviderName,
  141. dwProviderSize );
  142. _itot( dwErrorCode, szErrorCode, 10 );
  143. ReportErrorId( NULL,
  144. MSGTYPE_ERR,
  145. IDS_ERR_NETWORK_EXTENDED_ERROR,
  146. szProviderName,
  147. szErrorCode,
  148. szErrorString );
  149. }
  150. else {
  151. //
  152. // Unknown error
  153. //
  154. ReportErrorId( NULL,
  155. MSGTYPE_ERR,
  156. IDS_ERR_NETWORK_UNKNOWN_ERROR );
  157. }
  158. return( FALSE );
  159. }
  160. }
  161. // NTRAID#NTBUG9-551874-2002/02/27-stelo,swamip - CreateDistFolder, ShareTheDistFolder should use the code from OEM mode, reduce attack surface
  162. //
  163. //----------------------------------------------------------------------------
  164. //
  165. // Function: CreateDistFolder
  166. //
  167. // Purpose: Creates the distribution folder and reports any error.
  168. //
  169. // Arguments:
  170. // HWND hwnd - current window
  171. //
  172. // Returns:
  173. // TRUE - all is ok
  174. // FALSE - the error was reported, stay on this page
  175. //
  176. //----------------------------------------------------------------------------
  177. BOOL
  178. CreateDistFolder(HWND hwnd)
  179. {
  180. //
  181. // Don't just CreateDir in case user says d:\foo\bar\fud and 'foo'
  182. // doesn't exist. We want to make foo and bar and fud for the user.
  183. //
  184. // On the other hand, if d:\foo\bar\fud already exists, we want to
  185. // report an error, because the user explicitly said "New Folder"
  186. // on the dialog.
  187. //
  188. // So, check if it's there first, then just go silently make everything
  189. // needed if it doesn't exist. EnsureDirExists() will be silent in
  190. // the case that d:\foo\bar\fud already exists.
  191. //
  192. if ( DoesPathExist(WizGlobals.DistFolder) ) {
  193. UINT iRet;
  194. iRet = ReportErrorId(hwnd,
  195. MSGTYPE_YESNO,
  196. IDS_ERR_DISTFOLD_EXISTS,
  197. WizGlobals.DistFolder);
  198. if ( iRet != IDYES )
  199. return FALSE;
  200. }
  201. if ( ! EnsureDirExists(WizGlobals.DistFolder) ) {
  202. ReportErrorId(hwnd,
  203. MSGTYPE_ERR | MSGTYPE_WIN32,
  204. IDS_ERR_CREATING_DISTFOLD,
  205. WizGlobals.DistFolder);
  206. return FALSE;
  207. }
  208. return TRUE;
  209. }
  210. //----------------------------------------------------------------------------
  211. //
  212. // Function: CheckDistFolder
  213. //
  214. // Purpose: This function is called only by OnWizNextDistFolder. It
  215. // assumes that WizGlobals.DistFolder is up to date. We
  216. // create a folder or check if one exists as the user asks.
  217. //
  218. // Returns:
  219. // FALSE - Problems, don't let wizard proceed
  220. // TRUE - All is cool, go to the next page
  221. //
  222. // Notes:
  223. // - This routine directly reports any errors and prompts the
  224. // user as needed.
  225. //
  226. //----------------------------------------------------------------------------
  227. BOOL
  228. CheckDistFolder(HWND hwnd)
  229. {
  230. TCHAR PathBuffer[MAX_PATH];
  231. //
  232. // If user selected a file instead of a folder, trap that now, (just
  233. // for a more informative error message).
  234. //
  235. if ( DoesFileExist(WizGlobals.DistFolder) ) {
  236. ReportErrorId(hwnd,
  237. MSGTYPE_ERR,
  238. IDS_ERR_FOLDER_IS_FILE,
  239. WizGlobals.DistFolder);
  240. return FALSE;
  241. }
  242. if ( ! WizGlobals.bCreateNewDistFolder ) {
  243. //
  244. // We're trying to edit an existing distfolder. Popup if
  245. //
  246. // 1. It doesn't exist OR
  247. // 2. Can't find dosnet.inf
  248. //
  249. // In the case of #1, make user change path or radio button.
  250. // In the case of #2, let user edit it anyway via YES/NO popup.
  251. //
  252. if ( ! DoesFolderExist(WizGlobals.DistFolder) ) {
  253. ReportErrorId(hwnd,
  254. MSGTYPE_ERR,
  255. IDS_ERR_FOLDER_NOT_EXIST,
  256. WizGlobals.DistFolder);
  257. return FALSE;
  258. }
  259. //
  260. // If dosnet.inf doesn't exist, this isn't a distribution folder.
  261. // Note, this is a really minimal check.
  262. //
  263. lstrcpyn(PathBuffer, WizGlobals.DistFolder, AS(PathBuffer));
  264. ConcatenatePaths(PathBuffer, WizGlobals.Architecture, _T("dosnet.inf"), NULL);
  265. if ( ! DoesFileExist(PathBuffer) ) {
  266. UINT iRet;
  267. iRet = ReportErrorId(
  268. hwnd,
  269. MSGTYPE_YESNO,
  270. IDS_ERR_NOT_VALID_DISTFOLD,
  271. WizGlobals.DistFolder);
  272. if ( iRet != IDYES )
  273. return FALSE;
  274. }
  275. } else {
  276. //
  277. // We're creating a new distfolder. Go do the work.
  278. //
  279. if ( ! CreateDistFolder(hwnd) )
  280. return FALSE;
  281. }
  282. return TRUE;
  283. }
  284. //--------------------------------------------------------------------------
  285. //
  286. // Function: ShareTheDistFolder
  287. //
  288. // Purpose: Called by the Next procedure to put up the share.
  289. //
  290. //--------------------------------------------------------------------------
  291. BOOL
  292. ShareTheDistFolder(HWND hwnd, TCHAR *UncDistFolder)
  293. {
  294. LPTSTR pszServerPath;
  295. TCHAR szServerName[MAX_PATH];
  296. NET_API_STATUS nas;
  297. SHARE_INFO_502 si502, *psi502;
  298. BOOL bStatus = TRUE;
  299. //
  300. // Query this computer for info about the sharename the user
  301. // just typed in.
  302. //
  303. nas = NetShareGetInfo(
  304. NULL, // this computer
  305. WizGlobals.DistShareName, // shrname
  306. 502, // amount of info
  307. (LPBYTE*) &psi502); // the info (output)
  308. //
  309. // If this sharename is in use, we have to look at the directory that
  310. // is being shared.
  311. //
  312. if ( nas == NERR_Success ) {
  313. TCHAR szUncPath[MAX_PATH + 1];
  314. //
  315. // All is ok if this sharename is for the DistFolder
  316. // We have to check both the relative and the UNC path
  317. //
  318. if( ! ConvertRelativePathToUncPath( psi502->shi502_path,
  319. szUncPath,
  320. AS(szUncPath)) )
  321. {
  322. lstrcpyn( szUncPath, psi502->shi502_path, AS(szUncPath) );
  323. }
  324. if ( lstrcmpi(WizGlobals.DistFolder, psi502->shi502_path) == 0 ||
  325. lstrcmpi(WizGlobals.DistFolder, szUncPath) == 0 ) {
  326. NetApiBufferFree(psi502);
  327. return TRUE;
  328. }
  329. //
  330. // The sharename is in use, however, it's being used by a
  331. // different directory. Report an error telling user to enter
  332. // a different sharename.
  333. //
  334. ReportErrorId(hwnd,
  335. MSGTYPE_ERR,
  336. IDS_ERR_SHARENAME_INUSE,
  337. WizGlobals.DistShareName);
  338. NetApiBufferFree(psi502);
  339. return FALSE;
  340. }
  341. //
  342. // Put up the share
  343. //
  344. si502.shi502_netname = WizGlobals.DistShareName;
  345. si502.shi502_type = STYPE_DISKTREE;
  346. si502.shi502_remark = StrWindowsDistibFolder;
  347. si502.shi502_permissions = 0;
  348. si502.shi502_max_uses = SHI_USES_UNLIMITED;
  349. si502.shi502_current_uses = 0;
  350. si502.shi502_path = WizGlobals.DistFolder;
  351. si502.shi502_passwd = NULL;
  352. si502.shi502_reserved = 0;
  353. si502.shi502_security_descriptor = NULL;
  354. //
  355. // Set the server path to NULL if it is on the local machine, or the
  356. // computer name if it is on a remote machine
  357. //
  358. if( IsPathOnLocalDiskDrive(WizGlobals.DistFolder) ) {
  359. pszServerPath = NULL;
  360. }
  361. else {
  362. GetComputerNameFromUnc( UncDistFolder,
  363. szServerName,
  364. AS(szServerName));
  365. pszServerPath = szServerName;
  366. }
  367. nas = NetShareAdd(pszServerPath,
  368. 502, // info-level
  369. (LPBYTE) &si502, // info-buffer
  370. NULL); // don't bother with parm
  371. //
  372. // If the NetShareAdd fails for some reason, report the error code
  373. // to the user and give the user a chance to continue the wizard
  374. // without enabling the share. The user might not have privelege
  375. // to do this.
  376. //
  377. //
  378. // ISSUE-2002/02/27-stelo - The Net apis don't set GetLastError(). So how is one
  379. // supposed to report the error message to the user, like
  380. // 'access denied'???
  381. //
  382. // Run this test: Logon to an account without admin privelege.
  383. // Now try to put up the share. I bet the error message is
  384. // useless. This is a common scenario and should be addressed.
  385. //
  386. if ( nas != NERR_Success ) {
  387. UINT iRet;
  388. iRet = ReportErrorId(hwnd, MSGTYPE_YESNO, IDS_ERR_ENABLE_SHARE, nas);
  389. if ( iRet != IDYES )
  390. return FALSE;
  391. }
  392. return TRUE;
  393. }
  394. //----------------------------------------------------------------------------
  395. //
  396. // Function: OnDistFolderInitDialog
  397. //
  398. // Purpose:
  399. //
  400. // Arguments: IN HWND hwnd - handle to the dialog
  401. //
  402. // Returns: VOID
  403. //
  404. //----------------------------------------------------------------------------
  405. static VOID
  406. OnDistFolderInitDialog( IN HWND hwnd )
  407. {
  408. //
  409. // Load text strings
  410. //
  411. StrSelectDistFolder = MyLoadString( IDS_SELECT_DISTRIB_FOLDER );
  412. StrWindowsDistibFolder = MyLoadString( IDS_WINDOWS_DISTRIB_FOLDER );
  413. //
  414. // Set the text limit on the edit boxes
  415. //
  416. SendDlgItemMessage( hwnd,
  417. IDT_DISTFOLDER,
  418. EM_LIMITTEXT,
  419. (WPARAM) MAX_DIST_FOLDER,
  420. (LPARAM) 0 );
  421. SendDlgItemMessage( hwnd,
  422. IDT_SHARENAME,
  423. EM_LIMITTEXT,
  424. (WPARAM) MAX_SHARENAME,
  425. (LPARAM) 0 );
  426. }
  427. //----------------------------------------------------------------------------
  428. //
  429. // Function: OnWizNextDistFolder
  430. //
  431. // Purpose: Called when user pushes the NEXT button
  432. //
  433. //----------------------------------------------------------------------------
  434. BOOL
  435. OnWizNextDistFolder(HWND hwnd)
  436. {
  437. BOOL bResult = TRUE;
  438. //
  439. // Get the control settings
  440. //
  441. GetDlgItemText(hwnd, IDT_DISTFOLDER, WizGlobals.DistFolder, MAX_DIST_FOLDER + 1);
  442. GetDlgItemText(hwnd,
  443. IDT_SHARENAME,
  444. WizGlobals.DistShareName,
  445. MAX_SHARENAME + 1);
  446. // ISSUE-2002/02/27-stelo - need to check they entered a valid distrib folder here, i.e. that it is a valid path (local or UNC)
  447. // which of these are valid?
  448. //
  449. // c
  450. // c:
  451. // c:\
  452. // c\sdjf
  453. // \somedir
  454. // //somename
  455. // asfdj
  456. //
  457. MyGetFullPath(WizGlobals.DistFolder);
  458. //
  459. // Make sure they filled in the edit boxes
  460. //
  461. if( WizGlobals.DistFolder[0] == _T('\0') ) {
  462. ReportErrorId( hwnd, MSGTYPE_ERR, IDS_ERR_ENTER_DIST_FOLDER );
  463. bResult = FALSE;
  464. }
  465. if( WizGlobals.DistShareName[0] == _T('\0') ) {
  466. ReportErrorId( hwnd, MSGTYPE_ERR, IDS_ERR_ENTER_SHARENAME );
  467. bResult = FALSE;
  468. }
  469. if( !bResult ) {
  470. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, -1);
  471. return bResult;
  472. }
  473. // ISSUE-2002/02/27-stelo - if they specified a network path, it may take a while for the
  474. // connection to restore if they haven't used it in a while, we should probably
  475. // do a pop-up here to tell them we are looking for it
  476. //
  477. // Do some checking for the dist fold, create it if necessary, etc...
  478. //
  479. if ( ! CheckDistFolder(hwnd) )
  480. bResult = FALSE;
  481. if( ! ConvertRelativePathToUncPath( WizGlobals.DistFolder,
  482. WizGlobals.UncDistFolder,
  483. AS(WizGlobals.UncDistFolder)) )
  484. {
  485. lstrcpyn( WizGlobals.UncDistFolder, WizGlobals.DistFolder, AS(WizGlobals.UncDistFolder) );
  486. }
  487. //
  488. // Share it out if we haven't already reported an error
  489. //
  490. if ( bResult ) {
  491. if ( ! ShareTheDistFolder( hwnd, WizGlobals.UncDistFolder ) ) {
  492. bResult = FALSE;
  493. }
  494. }
  495. //
  496. // If OemFilesPath doesn't have a value, give it one.
  497. //
  498. if ( bResult && WizGlobals.OemFilesPath[0] == _T('\0') ) {
  499. lstrcpyn( WizGlobals.OemFilesPath, WizGlobals.DistFolder, AS(WizGlobals.OemFilesPath) );
  500. //Note:ConcatenatePaths truncates to avoid buffer overrun
  501. ConcatenatePaths( WizGlobals.OemFilesPath,
  502. WizGlobals.Architecture,
  503. _T("$oem$"),
  504. NULL );
  505. }
  506. //
  507. // Force creation of the $oem$ dir (if it doesn't exist already)
  508. //
  509. if ( bResult && ! EnsureDirExists(WizGlobals.OemFilesPath) ) {
  510. ReportErrorId(hwnd,
  511. MSGTYPE_ERR | MSGTYPE_WIN32,
  512. IDS_ERR_CREATE_FOLDER,
  513. WizGlobals.OemFilesPath);
  514. bResult = FALSE;
  515. }
  516. //
  517. // Route to the next wizard page
  518. //
  519. return bResult;
  520. }
  521. //---------------------------------------------------------------------------
  522. //
  523. // Function: BrowseForDistFolder
  524. //
  525. // Purpose: Calls SHBrowseForFolder to allow user to browse for a
  526. // distribution folder.
  527. //
  528. // Arguments:
  529. // HWND hwnd - owning window
  530. // LPTSTR PathBuffer - MAX_PATH buffer to receive results
  531. //
  532. // Returns: BOOL - success
  533. //
  534. //---------------------------------------------------------------------------
  535. BOOL
  536. BrowseForDistFolder(HWND hwnd, LPTSTR PathBuffer)
  537. {
  538. BROWSEINFO BrowseInf;
  539. LPITEMIDLIST lpIdList;
  540. UINT ulFlags = BIF_EDITBOX |
  541. BIF_RETURNONLYFSDIRS;
  542. BrowseInf.hwndOwner = hwnd;
  543. BrowseInf.pidlRoot = NULL; // no initial root
  544. BrowseInf.pszDisplayName = PathBuffer; // output
  545. BrowseInf.lpszTitle = StrSelectDistFolder;
  546. BrowseInf.ulFlags = ulFlags;
  547. BrowseInf.lpfn = NULL;
  548. BrowseInf.lParam = (LPARAM) 0;
  549. BrowseInf.iImage = 0; // no image
  550. lpIdList = SHBrowseForFolder(&BrowseInf);
  551. //
  552. // Get the pathname out of this idlist returned and free up the memory
  553. //
  554. if ( lpIdList == NULL )
  555. return FALSE;
  556. SHGetPathFromIDList(lpIdList, PathBuffer);
  557. ILFreePriv(lpIdList);
  558. return TRUE;
  559. }
  560. //---------------------------------------------------------------------------
  561. //
  562. // Function: OnBrowseDistFolder
  563. //
  564. // Purpose: Called when user pushes the BROWSE button
  565. //
  566. //---------------------------------------------------------------------------
  567. VOID
  568. OnBrowseDistFolder(HWND hwnd)
  569. {
  570. //
  571. // NTRAID#NTBUG9-551874-2002/02/27-stelo,swamip - CreateDistFolder, ShareTheDistFolder should use the code from OEM mode, reduce attack surface
  572. //
  573. if ( BrowseForDistFolder(hwnd, WizGlobals.DistFolder) ) {
  574. SendDlgItemMessage(hwnd,
  575. IDT_DISTFOLDER,
  576. WM_SETTEXT,
  577. (WPARAM) MAX_PATH,
  578. (LPARAM) WizGlobals.DistFolder);
  579. }
  580. }
  581. //----------------------------------------------------------------------------
  582. //
  583. // Function: DlgDistFolderPage
  584. //
  585. // Purpose: This is the dialog procedure IDD_DISTFOLDER.
  586. //
  587. //----------------------------------------------------------------------------
  588. INT_PTR CALLBACK
  589. DlgDistFolderPage(
  590. IN HWND hwnd,
  591. IN UINT uMsg,
  592. IN WPARAM wParam,
  593. IN LPARAM lParam)
  594. {
  595. BOOL bStatus = TRUE;
  596. switch (uMsg) {
  597. case WM_INITDIALOG:
  598. OnDistFolderInitDialog( hwnd );
  599. break;
  600. case WM_COMMAND:
  601. {
  602. int nButtonId=LOWORD(wParam);
  603. switch ( nButtonId ) {
  604. case IDC_BROWSE:
  605. if ( HIWORD(wParam) == BN_CLICKED )
  606. OnBrowseDistFolder(hwnd);
  607. break;
  608. default:
  609. bStatus = FALSE;
  610. break;
  611. }
  612. }
  613. break;
  614. case WM_NOTIFY:
  615. {
  616. LPNMHDR pnmh = (LPNMHDR)lParam;
  617. // ISSUE-2002/02/27-stelo,swamip - should check for valid pointer (possible dereference)
  618. //
  619. switch( pnmh->code ) {
  620. case PSN_QUERYCANCEL:
  621. WIZ_CANCEL(hwnd);
  622. break;
  623. case PSN_SETACTIVE:
  624. g_App.dwCurrentHelp = IDH_DIST_FLDR;
  625. if ( (WizGlobals.iProductInstall != PRODUCT_UNATTENDED_INSTALL) ||
  626. WizGlobals.bStandAloneScript)
  627. WIZ_SKIP( hwnd );
  628. else
  629. OnSetActiveDistFolder(hwnd);
  630. break;
  631. case PSN_WIZBACK:
  632. bStatus = FALSE;
  633. break;
  634. case PSN_WIZNEXT:
  635. if ( !OnWizNextDistFolder(hwnd) )
  636. WIZ_SKIP(hwnd);
  637. else
  638. bStatus = FALSE;
  639. break;
  640. case PSN_HELP:
  641. WIZ_HELP();
  642. break;
  643. default:
  644. bStatus = FALSE;
  645. break;
  646. }
  647. }
  648. break;
  649. default:
  650. bStatus = FALSE;
  651. break;
  652. }
  653. return bStatus;
  654. }