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.

902 lines
24 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995 - 1995.
  5. //
  6. // File: util.cxx
  7. //
  8. // Contents: Misc helper functions
  9. //
  10. // History: 5-Apr-95 BruceFo Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "headers.hxx"
  14. #pragma hdrstop
  15. #include "resource.h"
  16. #include "util.hxx"
  17. #include <safeboot.h> // SAFEBOOT_* flags
  18. //////////////////////////////////////////////////////////////////////////////
  19. #define NETMSG_DLL TEXT("netmsg.dll")
  20. //////////////////////////////////////////////////////////////////////////////
  21. //+-------------------------------------------------------------------------
  22. //
  23. // Function: MyFormatMessageText
  24. //
  25. // Synopsis: Given a resource IDs, load strings from given instance
  26. // and format the string into a buffer
  27. //
  28. // History: 11-Aug-93 WilliamW Created.
  29. //
  30. //--------------------------------------------------------------------------
  31. DWORD
  32. MyFormatMessageText(
  33. IN HRESULT dwMsgId,
  34. IN PWSTR pszBuffer,
  35. IN DWORD cchBuffer,
  36. IN va_list * parglist
  37. )
  38. {
  39. //
  40. // get message from system or app msg file.
  41. //
  42. DWORD dwReturn = FormatMessage(
  43. FORMAT_MESSAGE_FROM_HMODULE,
  44. g_hInstance,
  45. dwMsgId,
  46. LANG_USER_DEFAULT,
  47. pszBuffer,
  48. cchBuffer,
  49. parglist);
  50. if (0 == dwReturn) // couldn't find message
  51. {
  52. appDebugOut((DEB_IERROR,
  53. "FormatMessage failed, 0x%08lx\n",
  54. GetLastError()));
  55. WCHAR szText[200];
  56. dwReturn = LoadString(g_hInstance, IDS_APP_MSG_NOT_FOUND, szText, ARRAYLEN(szText));
  57. if (0 != dwReturn)
  58. {
  59. int iReturn = wnsprintf(pszBuffer, cchBuffer, szText, dwMsgId);
  60. dwReturn = (iReturn < 0) ? 0 : iReturn;
  61. }
  62. }
  63. return dwReturn;
  64. }
  65. //+-------------------------------------------------------------------------
  66. //
  67. // Function: MyCommonDialog
  68. //
  69. // Synopsis: Common popup dialog routine - stole from diskadm directory
  70. //
  71. //--------------------------------------------------------------------------
  72. DWORD
  73. MyCommonDialog(
  74. IN HWND hwnd,
  75. IN HRESULT dwMsgCode,
  76. IN PWSTR pszCaption,
  77. IN DWORD dwFlags,
  78. IN va_list arglist
  79. )
  80. {
  81. WCHAR szMsgBuf[500];
  82. if (0 == MyFormatMessageText(dwMsgCode, szMsgBuf, ARRAYLEN(szMsgBuf), &arglist))
  83. {
  84. return 0;
  85. }
  86. return MessageBox(hwnd, szMsgBuf, pszCaption, dwFlags);
  87. }
  88. //+-------------------------------------------------------------------------
  89. //
  90. // Function: MyConfirmationDialog
  91. //
  92. // Synopsis: This routine retreives a message from the app or system
  93. // message file and displays it in a message box.
  94. //
  95. // Note: Stole from diskadm directory
  96. //
  97. //--------------------------------------------------------------------------
  98. DWORD
  99. MyConfirmationDialog(
  100. IN HWND hwnd,
  101. IN HRESULT dwMsgCode,
  102. IN DWORD dwFlags,
  103. ...
  104. )
  105. {
  106. WCHAR szCaption[100];
  107. DWORD dwReturn;
  108. va_list arglist;
  109. va_start(arglist, dwFlags);
  110. LoadString(g_hInstance, IDS_MSGTITLE, szCaption, ARRAYLEN(szCaption));
  111. dwReturn = MyCommonDialog(hwnd, dwMsgCode, szCaption, dwFlags, arglist);
  112. va_end(arglist);
  113. return dwReturn;
  114. }
  115. //+-------------------------------------------------------------------------
  116. //
  117. // Function: MyErrorDialog
  118. //
  119. // Synopsis: This routine retreives a message from the app or system
  120. // message file and displays it in a message box.
  121. //
  122. // Note: Stole from diskadm directory
  123. //
  124. //--------------------------------------------------------------------------
  125. VOID
  126. MyErrorDialog(
  127. IN HWND hwnd,
  128. IN HRESULT dwErrorCode,
  129. ...
  130. )
  131. {
  132. WCHAR szCaption[100];
  133. va_list arglist;
  134. va_start(arglist, dwErrorCode);
  135. LoadString(g_hInstance, IDS_MSGTITLE, szCaption, ARRAYLEN(szCaption));
  136. MyCommonDialog(hwnd, dwErrorCode, szCaption, MB_ICONSTOP | MB_OK, arglist);
  137. va_end(arglist);
  138. }
  139. //+---------------------------------------------------------------------------
  140. //
  141. // Function: NewDup
  142. //
  143. // Synopsis: Duplicate a string using '::new'
  144. //
  145. // History: 28-Dec-94 BruceFo Created
  146. //
  147. //----------------------------------------------------------------------------
  148. PWSTR
  149. NewDup(
  150. IN const WCHAR* psz
  151. )
  152. {
  153. if (NULL == psz)
  154. {
  155. appDebugOut((DEB_IERROR,"Illegal string to duplicate: NULL\n"));
  156. return NULL;
  157. }
  158. int cch = lstrlenW(psz) + 1;
  159. PWSTR pszRet = new WCHAR[cch];
  160. if (NULL == pszRet)
  161. {
  162. appDebugOut((DEB_ERROR,"OUT OF MEMORY\n"));
  163. return NULL;
  164. }
  165. lstrcpynW(pszRet, psz, cch);
  166. return pszRet;
  167. }
  168. //+-------------------------------------------------------------------------
  169. //
  170. // Member: CopySecurityDescriptor, public
  171. //
  172. // Synopsis: Copy an NT security descriptor. Delete the result
  173. // using LocalFree().
  174. //
  175. // History: 19-Apr-95 BruceFo Created
  176. //
  177. //--------------------------------------------------------------------------
  178. HRESULT
  179. CopySecurityDescriptor(
  180. IN PSECURITY_DESCRIPTOR pSecDesc,
  181. OUT PSECURITY_DESCRIPTOR *ppsdResult
  182. )
  183. {
  184. HRESULT hr = S_OK;
  185. PSECURITY_DESCRIPTOR pSelfSecDesc = NULL;
  186. appDebugOut((DEB_ITRACE, "CopySecurityDescriptor, pSecDesc = 0x%08lx\n", pSecDesc));
  187. if (NULL == ppsdResult)
  188. {
  189. return E_POINTER;
  190. }
  191. *ppsdResult = NULL;
  192. if (NULL == pSecDesc)
  193. {
  194. // nothing to do
  195. return S_OK;
  196. }
  197. if (!IsValidSecurityDescriptor(pSecDesc))
  198. {
  199. return E_INVALIDARG;
  200. }
  201. SECURITY_DESCRIPTOR_CONTROL sdc = 0;
  202. DWORD dwRevision = 0;
  203. if ( ::GetSecurityDescriptorControl( pSecDesc, &sdc, &dwRevision ) )
  204. {
  205. DWORD dwLen = GetSecurityDescriptorLength(pSecDesc);
  206. pSelfSecDesc = reinterpret_cast<PSECURITY_DESCRIPTOR>(::LocalAlloc(LPTR, dwLen));
  207. if (NULL != pSelfSecDesc)
  208. {
  209. // if the original is already self-relative, just copy it
  210. if ( sdc & SE_SELF_RELATIVE )
  211. {
  212. CopyMemory(pSelfSecDesc, pSecDesc, dwLen);
  213. }
  214. else if (!MakeSelfRelativeSD(pSecDesc, pSelfSecDesc, &dwLen))
  215. {
  216. appDebugOut((DEB_TRACE, "MakeSelfRelativeSD failed, 0x%08lx\n", GetLastError()));
  217. DWORD err = ::GetLastError();
  218. hr = HRESULT_FROM_WIN32( err );
  219. }
  220. if (SUCCEEDED(hr))
  221. {
  222. appAssert(IsValidSecurityDescriptor(pSelfSecDesc));
  223. *ppsdResult = pSelfSecDesc;
  224. }
  225. else
  226. {
  227. ::LocalFree(pSelfSecDesc);
  228. }
  229. }
  230. else
  231. {
  232. hr = E_OUTOFMEMORY;
  233. }
  234. }
  235. else
  236. {
  237. DWORD err = ::GetLastError();
  238. hr = HRESULT_FROM_WIN32( err );
  239. }
  240. return hr;
  241. }
  242. //+-------------------------------------------------------------------------
  243. //
  244. // Member: WarnDelShare, public
  245. //
  246. // Synopsis: Function to warn a user that a share will be deleted, and give
  247. // the user a chance to cancel.
  248. //
  249. // Arguments: [hwnd] - parent window handle for messages
  250. // [idMsg] - message ID to display (rmdir vs. move)
  251. // [pszShare] - share name
  252. // [pszPath] - path that share affects
  253. //
  254. // Returns: IDYES if share was deleted, IDNO if we don't want to delete,
  255. // but keep going, IDCANCEL to stop going.
  256. //
  257. // History: 19-Apr-95 BruceFo Created
  258. //
  259. //--------------------------------------------------------------------------
  260. UINT
  261. WarnDelShare(
  262. IN HWND hwnd,
  263. IN UINT idMsg,
  264. IN PWSTR pszShare,
  265. IN PWSTR pszPath
  266. )
  267. {
  268. DWORD id = MyConfirmationDialog(
  269. hwnd,
  270. idMsg,
  271. MB_YESNOCANCEL | MB_ICONEXCLAMATION,
  272. pszPath,
  273. pszShare);
  274. if (id != IDYES)
  275. {
  276. return id;
  277. }
  278. id = ConfirmStopShare(hwnd, MB_YESNOCANCEL, pszShare);
  279. if (id != IDYES)
  280. {
  281. return id;
  282. }
  283. UINT ret = NetShareDel(NULL, pszShare, 0);
  284. if (ret != NERR_Success)
  285. {
  286. DisplayError(hwnd, IERR_CANT_DEL_SHARE, ret, pszShare);
  287. return IDYES; // allow the stop anyway
  288. }
  289. return IDYES;
  290. }
  291. //+-------------------------------------------------------------------------
  292. //
  293. // Member: ConfirmStopShare, public
  294. //
  295. // Synopsis: Display the appropriate confirmations when stopping a share.
  296. //
  297. // Arguments: [hwnd] - parent window handle for messages
  298. // [uType] - either MB_YESNO or MB_YESNOCANCEL
  299. // [pszShare] - ptr to affected share name
  300. //
  301. // Returns: IDYES if share should be deleted, IDNO if we don't want to
  302. // delete, but keep going, IDCANCEL to stop going.
  303. //
  304. // History: 19-Apr-95 BruceFo Created
  305. //
  306. //--------------------------------------------------------------------------
  307. DWORD
  308. ConfirmStopShare(
  309. IN HWND hwnd,
  310. IN UINT uType,
  311. IN LPWSTR pszShare
  312. )
  313. {
  314. DWORD id = IDYES;
  315. DWORD cConns = 0;
  316. DWORD cOpens = 0;
  317. NET_API_STATUS err = ShareConnectionInfo(pszShare, &cConns, &cOpens);
  318. if (err != NERR_Success)
  319. {
  320. DisplayError(hwnd, IERR_CANT_DEL_SHARE, err, pszShare);
  321. // allow the stop anyway
  322. }
  323. else if (cConns != 0)
  324. {
  325. // If there are any open files, just give the more detailed
  326. // message about there being open files. Otherwise, just say how
  327. // many connections there are.
  328. if (cOpens != 0)
  329. {
  330. id = MyConfirmationDialog(
  331. hwnd,
  332. MSG_STOPSHAREOPENS,
  333. uType | MB_ICONEXCLAMATION,
  334. cOpens,
  335. cConns,
  336. pszShare);
  337. }
  338. else
  339. {
  340. id = MyConfirmationDialog(
  341. hwnd,
  342. MSG_STOPSHARECONNS,
  343. uType | MB_ICONEXCLAMATION,
  344. cConns,
  345. pszShare);
  346. }
  347. }
  348. // JonN 4/4/01 328512
  349. // Explorer Sharing Tab (NTSHRUI) should popup warning on deleting
  350. // SYSVOL,NETLOGON and C$, D$... shares
  351. //
  352. // No need to worry about IPC$, that won't turn up in NTSHRUI
  353. if (IDYES == id)
  354. {
  355. bool fSpecialShare = !lstrcmpi(pszShare,L"NETLOGON")
  356. || !lstrcmpi(pszShare,L"SYSVOL");
  357. if ( fSpecialShare
  358. || (lstrlen(pszShare) == 2 && L'$'== pszShare[1])
  359. )
  360. {
  361. id = MyConfirmationDialog(
  362. hwnd,
  363. (fSpecialShare) ? MSG_DELSPECIALSHARE
  364. : MSG_DELADMINSHARE,
  365. uType | MB_ICONEXCLAMATION,
  366. pszShare);
  367. }
  368. }
  369. return id;
  370. }
  371. //+-------------------------------------------------------------------------
  372. //
  373. // Member: ShareConnectionInfo, public
  374. //
  375. // Synopsis: Determine how many connections and file opens exist for a
  376. // share, for use by confirmation dialogs.
  377. //
  378. // Arguments: [pszShare] - ptr to affected share name
  379. // [pcConns] - *pcConns get the number of connections
  380. // [pcOpens] - *pcOpens get the number of file opens
  381. //
  382. // Returns: standard net api code, NERR_Success if everything ok.
  383. //
  384. // History: 19-Apr-95 BruceFo Stolen
  385. //
  386. //--------------------------------------------------------------------------
  387. NET_API_STATUS
  388. ShareConnectionInfo(
  389. IN LPWSTR pszShare,
  390. OUT LPDWORD pcConns,
  391. OUT LPDWORD pcOpens
  392. )
  393. {
  394. CONNECTION_INFO_1* pBuf;
  395. DWORD iEntry, iTotal;
  396. NET_API_STATUS err = NetConnectionEnum(
  397. NULL,
  398. pszShare,
  399. 1,
  400. (LPBYTE*)&pBuf,
  401. 0xffffffff, // no buffer limit; get them all!
  402. &iEntry,
  403. &iTotal,
  404. NULL);
  405. if ((err == NERR_Success) || (err == ERROR_MORE_DATA))
  406. {
  407. int iConnections = 0;
  408. for (DWORD i = 0; i < iEntry; i++)
  409. {
  410. iConnections += pBuf[i].coni1_num_opens;
  411. }
  412. *pcConns = iTotal;
  413. *pcOpens = iConnections;
  414. err = NERR_Success;
  415. }
  416. else
  417. {
  418. *pcConns = 0;
  419. *pcOpens = 0;
  420. }
  421. NetApiBufferFree(pBuf);
  422. appDebugOut((DEB_ITRACE,"Share '%ws' has %d connections and %d opens\n", pszShare, *pcConns, *pcOpens));
  423. return err;
  424. }
  425. //+-------------------------------------------------------------------------
  426. //
  427. // Function: DisplayError
  428. //
  429. // Synopsis: Display an error message
  430. //
  431. // History: 24-Apr-95 BruceFo Stolen
  432. //
  433. //--------------------------------------------------------------------------
  434. VOID
  435. DisplayError(
  436. IN HWND hwnd,
  437. IN HRESULT dwErrorCode, // message file number. not really an HRESULT
  438. IN NET_API_STATUS err,
  439. IN PWSTR pszShare
  440. )
  441. {
  442. if ( err < MIN_LANMAN_MESSAGE_ID
  443. || err > MAX_LANMAN_MESSAGE_ID
  444. )
  445. {
  446. // a Win32 error?
  447. WCHAR szMsg[500];
  448. DWORD dwReturn = FormatMessage(
  449. FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  450. NULL,
  451. err,
  452. LANG_USER_DEFAULT,
  453. szMsg,
  454. ARRAYLEN(szMsg),
  455. NULL);
  456. if (0 == dwReturn) // couldn't find message
  457. {
  458. appDebugOut((DEB_IERROR,
  459. "FormatMessage (from system) failed, 0x%08lx\n",
  460. GetLastError()));
  461. MyErrorDialog(hwnd, IERR_UNKNOWN, err);
  462. }
  463. else
  464. {
  465. MyErrorDialog(hwnd, dwErrorCode, pszShare, szMsg);
  466. }
  467. }
  468. else
  469. {
  470. DisplayLanmanError(hwnd, dwErrorCode, err, pszShare);
  471. }
  472. }
  473. //+-------------------------------------------------------------------------
  474. //
  475. // Function: DisplayLanmanError
  476. //
  477. // Synopsis: Display an error message from a LanMan error.
  478. //
  479. // History: 24-Apr-95 BruceFo Stolen
  480. //
  481. //--------------------------------------------------------------------------
  482. VOID
  483. DisplayLanmanError(
  484. IN HWND hwnd,
  485. IN HRESULT dwErrorCode, // message file number. not really an HRESULT
  486. IN NET_API_STATUS err,
  487. IN PWSTR pszShare
  488. )
  489. {
  490. if ( err < MIN_LANMAN_MESSAGE_ID
  491. || err > MAX_LANMAN_MESSAGE_ID
  492. )
  493. {
  494. MyErrorDialog(hwnd, IERR_UNKNOWN, err);
  495. return;
  496. }
  497. WCHAR szCaption[100];
  498. LoadString(g_hInstance, IDS_MSGTITLE, szCaption, ARRAYLEN(szCaption));
  499. //
  500. // get LanMan message from system message file.
  501. //
  502. WCHAR szNetMsg[500];
  503. WCHAR szBuf[500];
  504. HINSTANCE hInstanceNetMsg = LoadLibrary(NETMSG_DLL);
  505. if (NULL == hInstanceNetMsg)
  506. {
  507. appDebugOut((DEB_IERROR,
  508. "LoadLibrary(netmsg.dll) failed, 0x%08lx\n",
  509. GetLastError()));
  510. LoadString(g_hInstance, IDS_NO_NET_MSG, szBuf, ARRAYLEN(szBuf));
  511. MessageBox(hwnd, szBuf, szCaption, MB_ICONSTOP | MB_OK);
  512. return;
  513. }
  514. DWORD dwReturn = FormatMessage(
  515. FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS,
  516. hInstanceNetMsg,
  517. err,
  518. LANG_USER_DEFAULT,
  519. szNetMsg,
  520. ARRAYLEN(szNetMsg),
  521. NULL);
  522. if (0 == dwReturn) // couldn't find message
  523. {
  524. appDebugOut((DEB_IERROR,
  525. "FormatMessage failed, 0x%08lx\n",
  526. GetLastError()));
  527. if (LoadString(g_hInstance, IDS_NET_MSG_NOT_FOUND, szBuf, ARRAYLEN(szBuf)) &&
  528. wnsprintf(szNetMsg, ARRAYLEN(szNetMsg), szBuf, GetLastError()) > 0)
  529. {
  530. MessageBox(hwnd, szNetMsg, szCaption, MB_ICONSTOP | MB_OK);
  531. }
  532. }
  533. else
  534. {
  535. MyErrorDialog(hwnd, dwErrorCode, pszShare, szNetMsg);
  536. }
  537. FreeLibrary(hInstanceNetMsg);
  538. }
  539. //+-------------------------------------------------------------------------
  540. //
  541. // Function: IsValidShareName
  542. //
  543. // Synopsis: Checks if the proposed share name is valid or not. If not,
  544. // it will return a message id for the reason why.
  545. //
  546. // Arguments: [pszShareName] - Proposed share name
  547. // [puId] - If name is invalid, this will contain the reason why.
  548. //
  549. // Returns: TRUE if name is valid, else FALSE.
  550. //
  551. // History: 3-May-95 BruceFo Stolen
  552. //
  553. //--------------------------------------------------------------------------
  554. BOOL
  555. IsValidShareName(
  556. IN PCWSTR pszShareName,
  557. OUT HRESULT* uId
  558. )
  559. {
  560. if (NetpNameValidate(NULL, (PWSTR)pszShareName, NAMETYPE_SHARE, 0L) != NERR_Success)
  561. {
  562. *uId = IERR_InvalidShareName;
  563. return FALSE;
  564. }
  565. return TRUE;
  566. }
  567. //+-------------------------------------------------------------------------
  568. //
  569. // Function: IsValidWin9xShareLength
  570. //
  571. // Synopsis: Checks if the proposed share name is within the maximum length
  572. // that Win9x clients can use, which is LM20_NNLEN *bytes* for
  573. // the MBCS version of the name.
  574. //
  575. // Arguments: [pszShareName] - Proposed share name
  576. //
  577. // Returns: TRUE if name is valid, else FALSE.
  578. //
  579. // History: 07-Nov-01 JeffreyS Created
  580. //
  581. //--------------------------------------------------------------------------
  582. BOOL
  583. IsValidWin9xShareLength(
  584. IN PCWSTR pszShare
  585. )
  586. {
  587. char szBuf[LM20_NNLEN+1]; // +1 for '\0'
  588. // If WideCharToMultiByte fails with ERROR_INSUFFICIENT_BUFFER, then we
  589. // know the name is too long. There is no need to check the string
  590. // length on success.
  591. if (pszShare &&
  592. WideCharToMultiByte(CP_ACP, 0, pszShare, -1, szBuf, LM20_NNLEN+1, NULL, NULL))
  593. {
  594. return TRUE;
  595. }
  596. return FALSE;
  597. }
  598. //+-------------------------------------------------------------------------
  599. //
  600. // Function: SetErrorFocus
  601. //
  602. // Synopsis: Set focus to an edit control and select its text.
  603. //
  604. // Arguments: [hwnd] - dialog window
  605. // [idCtrl] - edit control to set focus to (and select)
  606. //
  607. // Returns: nothing
  608. //
  609. // History: 3-May-95 BruceFo Stolen
  610. //
  611. //--------------------------------------------------------------------------
  612. VOID
  613. SetErrorFocus(
  614. IN HWND hwnd,
  615. IN UINT idCtrl
  616. )
  617. {
  618. HWND hCtrl = ::GetDlgItem(hwnd, idCtrl);
  619. ::SetFocus(hCtrl);
  620. ::SendMessage(hCtrl, EM_SETSEL, 0, -1);
  621. }
  622. //+-------------------------------------------------------------------------
  623. //
  624. // Function: ConfirmReplaceShare
  625. //
  626. // Synopsis: Display confirmations for replacing an existing share
  627. //
  628. // Arguments: [hwnd] - dialog window
  629. // [pszShareName] - name of share being replaced
  630. // [pszOldPath] - current path for the share
  631. // [pszNewPath] - directory the user's trying to share
  632. //
  633. // Returns: Returns IDYES or IDNO
  634. //
  635. // History: 4-May-95 BruceFo Stolen
  636. //
  637. //--------------------------------------------------------------------------
  638. DWORD
  639. ConfirmReplaceShare(
  640. IN HWND hwnd,
  641. IN PCWSTR pszShareName,
  642. IN PCWSTR pszOldPath,
  643. IN PCWSTR pszNewPath
  644. )
  645. {
  646. DWORD id = MyConfirmationDialog(
  647. hwnd,
  648. MSG_RESHARENAMECONFIRM,
  649. MB_YESNO | MB_ICONEXCLAMATION,
  650. pszOldPath,
  651. pszShareName,
  652. pszNewPath);
  653. if (id != IDYES)
  654. {
  655. return id;
  656. }
  657. return ConfirmStopShare(hwnd, MB_YESNO, (PWSTR)pszShareName);
  658. }
  659. //+---------------------------------------------------------------------------
  660. //
  661. // Function: TrimLeadingAndTrailingSpaces
  662. //
  663. // Synopsis: Trims the leading and trailing spaces from a null-terminated string.
  664. // Used primarily for share names.
  665. //
  666. // History: 18-Jul-97 JonN Created
  667. //
  668. //----------------------------------------------------------------------------
  669. VOID
  670. TrimLeadingAndTrailingSpaces(
  671. IN OUT PWSTR psz
  672. )
  673. {
  674. int cchStrlen = ::wcslen(psz);
  675. int cchLeadingSpaces = 0;
  676. int cchTrailingSpaces = 0;
  677. while (L' ' == psz[cchLeadingSpaces])
  678. cchLeadingSpaces++;
  679. if (cchLeadingSpaces < cchStrlen)
  680. {
  681. while (L' ' == psz[cchStrlen-(cchTrailingSpaces+1)])
  682. cchTrailingSpaces++;
  683. }
  684. if ((cchLeadingSpaces+cchTrailingSpaces) > 0)
  685. {
  686. cchStrlen -= (cchLeadingSpaces+cchTrailingSpaces);
  687. (void)memmove( psz,
  688. psz+cchLeadingSpaces,
  689. cchStrlen*sizeof(WCHAR) );
  690. psz[cchStrlen] = L'\0';
  691. }
  692. }
  693. //+---------------------------------------------------------------------------
  694. //
  695. // Function: IsSafeMode
  696. //
  697. // Synopsis: Checks the registry to see if the system is in safe mode.
  698. //
  699. // History: 06-Oct-00 JeffreyS Created
  700. //
  701. //----------------------------------------------------------------------------
  702. BOOL
  703. IsSafeMode(
  704. VOID
  705. )
  706. {
  707. BOOL fIsSafeMode = FALSE;
  708. LONG ec;
  709. DWORD dwValue;
  710. DWORD dwValueSize = sizeof(dwValue);
  711. ec = SHRegGetValue(HKEY_LOCAL_MACHINE,
  712. TEXT("SYSTEM\\CurrentControlSet\\Control\\SafeBoot\\Option"),
  713. TEXT("OptionValue"),
  714. SRRF_RT_DWORD,
  715. NULL,
  716. &dwValue,
  717. &dwValueSize);
  718. if (ec == NO_ERROR)
  719. {
  720. fIsSafeMode = (dwValue == SAFEBOOT_MINIMAL || dwValue == SAFEBOOT_NETWORK);
  721. }
  722. return fIsSafeMode;
  723. }
  724. //+---------------------------------------------------------------------------
  725. //
  726. // Function: IsForcedGuestModeOn
  727. //
  728. // Synopsis: Checks the registry to see if the system is using the
  729. // Guest-only network access mode.
  730. //
  731. // History: 06-Oct-00 JeffreyS Created
  732. // 19-Apr-00 GPease Modified and changed name
  733. //
  734. //----------------------------------------------------------------------------
  735. BOOL
  736. IsForcedGuestModeOn(
  737. VOID
  738. )
  739. {
  740. BOOL fIsForcedGuestModeOn = FALSE;
  741. if (IsOS(OS_PERSONAL))
  742. {
  743. // Guest mode is always on for Personal
  744. fIsForcedGuestModeOn = TRUE;
  745. }
  746. else if (IsOS(OS_PROFESSIONAL) && !IsOS(OS_DOMAINMEMBER))
  747. {
  748. LONG ec;
  749. DWORD dwValue;
  750. DWORD dwValueSize = sizeof(dwValue);
  751. // Professional, not in a domain. Check the ForceGuest value.
  752. ec = SHRegGetValue(HKEY_LOCAL_MACHINE,
  753. TEXT("SYSTEM\\CurrentControlSet\\Control\\LSA"),
  754. TEXT("ForceGuest"),
  755. SRRF_RT_DWORD,
  756. NULL,
  757. &dwValue,
  758. &dwValueSize);
  759. if (ec == NO_ERROR && 1 == dwValue)
  760. {
  761. fIsForcedGuestModeOn = TRUE;
  762. }
  763. }
  764. return fIsForcedGuestModeOn;
  765. }
  766. //+---------------------------------------------------------------------------
  767. //
  768. // Function: IsSimpleUI
  769. //
  770. // Synopsis: Checks whether to show the simple version of the UI.
  771. //
  772. // History: 06-Oct-00 JeffreyS Created
  773. // 19-Apr-00 GPease Removed CTRL key check
  774. //
  775. //----------------------------------------------------------------------------
  776. BOOL
  777. IsSimpleUI(
  778. VOID
  779. )
  780. {
  781. // Show old UI in safe mode and anytime network access involves
  782. // true user identity (server, pro with GuestMode off).
  783. // Show simple UI anytime network access is done using the Guest
  784. // account (personal, pro with GuestMode on) except in safe mode.
  785. return (!IsSafeMode() && IsForcedGuestModeOn());
  786. }