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.

1842 lines
47 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1994 - 1998.
  5. //
  6. // File: util.cxx
  7. //
  8. // Contents: utility functions
  9. //
  10. //
  11. // History: 12-05-1997 SusiA
  12. //
  13. //---------------------------------------------------------------------------
  14. #include "lib.h"
  15. #ifndef SECURITY_WIN32
  16. #define SECURITY_WIN32
  17. #endif
  18. #include "security.h"
  19. extern "C" CRITICAL_SECTION g_CritSectCommonLib; // initialized by InitCommonLib
  20. extern OSVERSIONINFOA g_OSVersionInfo; // osVersionInfo.
  21. typedef BOOLEAN (APIENTRY *PFNGETUSERNAMEEX) (EXTENDED_NAME_FORMAT NameFormat,
  22. LPWSTR lpNameBuffer, PULONG nSize );
  23. STRING_FILENAME(szSecur32Dll, "SECUR32.DLL");
  24. STRING_INTERFACE(szGetUserNameEx,"GetUserNameExW");
  25. BOOL g_fLoadedSecur32 = FALSE;
  26. HINSTANCE g_hinstSecur32 = NULL;
  27. PFNGETUSERNAMEEX g_pfGetUserNameEx = NULL;
  28. //--------------------------------------------------------------------------------
  29. //
  30. // FUNCTION: RegGetCurrentUser(LPTSTR pszName, LPDWORD pdwCount)
  31. //
  32. // PURPOSE: Gets the currently logged on user name from the Reg
  33. //
  34. //--------------------------------------------------------------------------------
  35. BOOL RegGetCurrentUser(LPTSTR pszName, LPDWORD pdwCount)
  36. {
  37. HRESULT hr = ERROR_SUCCESS;
  38. HKEY hkeyUser;
  39. DWORD dwDataSize = *pdwCount * sizeof(TCHAR);
  40. DWORD dwType = REG_SZ;
  41. // Get the current user name from the reg
  42. if (ERROR_SUCCESS == (hr = RegOpenKeyExXp(HKEY_CURRENT_USER,
  43. TOPLEVEL_REGKEY,0,KEY_QUERY_VALUE,&hkeyUser,FALSE /*fSetSecurity*/)))
  44. {
  45. hr = RegQueryValueEx(hkeyUser,TEXT("CurrentUserName"),
  46. NULL, &dwType ,
  47. (LPBYTE) pszName,
  48. &dwDataSize);
  49. *pdwCount = dwDataSize;
  50. RegCloseKey(hkeyUser);
  51. }
  52. if (ERROR_SUCCESS == hr)
  53. {
  54. return TRUE;
  55. }
  56. else
  57. {
  58. return FALSE;
  59. }
  60. }
  61. //--------------------------------------------------------------------------------
  62. //
  63. // FUNCTION: RegSetCurrentUser(LPTSTR pszName)
  64. //
  65. // PURPOSE: sets the current user name in the reg
  66. //
  67. //--------------------------------------------------------------------------------
  68. BOOL RegSetCurrentUser(LPTSTR pszName)
  69. {
  70. HRESULT hr = ERROR_SUCCESS;
  71. HKEY hkeyUser;
  72. // write out the Handler to the Registry.
  73. if (ERROR_SUCCESS == (hr = RegCreateKeyEx(HKEY_CURRENT_USER,
  74. TOPLEVEL_REGKEY,0,NULL, REG_OPTION_NON_VOLATILE,
  75. KEY_READ | KEY_WRITE | KEY_CREATE_SUB_KEY,
  76. NULL,&hkeyUser, NULL)))
  77. {
  78. hr = RegSetValueEx(hkeyUser,TEXT("CurrentUserName"),
  79. NULL, REG_SZ ,
  80. (LPBYTE) pszName,
  81. UNLEN + 1);
  82. RegCloseKey(hkeyUser);
  83. }
  84. if (ERROR_SUCCESS == hr)
  85. {
  86. return TRUE;
  87. }
  88. else
  89. {
  90. return FALSE;
  91. }
  92. }
  93. //+---------------------------------------------------------------------------
  94. //
  95. // Function: CenterDialog
  96. //
  97. // Synopsis: Helper to center a dialog on screen.
  98. //
  99. // Arguments: [hDlg] -- Dialog handle.
  100. //
  101. // Returns: None.
  102. //
  103. // Notes: None.
  104. //
  105. //----------------------------------------------------------------------------
  106. void
  107. CenterDialog(HWND hDlg)
  108. {
  109. RECT rc;
  110. GetWindowRect(hDlg, &rc);
  111. SetWindowPos(hDlg,
  112. NULL,
  113. ((GetSystemMetrics(SM_CXSCREEN) - (rc.right - rc.left)) / 2),
  114. ((GetSystemMetrics(SM_CYSCREEN) - (rc.bottom - rc.top)) / 2),
  115. 0,
  116. 0,
  117. SWP_NOSIZE | SWP_NOACTIVATE);
  118. }
  119. //+--------------------------------------------------------------------------
  120. //
  121. // Function: GetDomainAndMachineName
  122. //
  123. // Synopsis: Fill [ptszDomainAndMachineName] with "domain\machine" string
  124. //
  125. // Arguments: [ptszDomainAndMachineName] - buffer to receive string
  126. // [cchBuf] - should be at least UNLEN
  127. //
  128. // Modifies: *[ptszDomainAndMachineName].
  129. //
  130. // History: 01-12-1998 SusiA Created
  131. //
  132. // Notes: If an error occurs while retrieving the domain name, only
  133. // the machine name is returned. If even that cannot be
  134. // retrieved, the buffer is set to an empty string.
  135. //
  136. //---------------------------------------------------------------------------
  137. VOID
  138. GetDomainAndMachineName(
  139. LPTSTR ptszDomainAndMachineName,
  140. ULONG cchBuf)
  141. {
  142. HRESULT hr = E_FAIL;
  143. LONG lr;
  144. HKEY hkWinlogon = NULL;
  145. ULONG cchRemain = cchBuf;
  146. do
  147. {
  148. //
  149. // Get the domain name of the currently logged on user. Open the
  150. // winlogon key.
  151. //
  152. lr = RegOpenKeyExXp(HKEY_LOCAL_MACHINE,
  153. REGSTR_WINLOGON,
  154. 0,
  155. KEY_QUERY_VALUE,
  156. &hkWinlogon,FALSE /*fSetSecurity*/);
  157. if (lr != ERROR_SUCCESS)
  158. {
  159. break;
  160. }
  161. //
  162. // Query for the default domain, which is what the user logged on to.
  163. //
  164. ULONG cbBuf = cchBuf * sizeof(TCHAR);
  165. DWORD dwType;
  166. lr = RegQueryValueEx(hkWinlogon,
  167. REGSTR_DEFAULT_DOMAIN,
  168. NULL,
  169. &dwType,
  170. (LPBYTE) ptszDomainAndMachineName,
  171. &cbBuf);
  172. if (lr != ERROR_SUCCESS)
  173. {
  174. break;
  175. }
  176. Assert(dwType == REG_SZ);
  177. //
  178. // Account for the characters used up by the domain name, but
  179. // don't count the trailing NULL.
  180. //
  181. cchRemain -= (cbBuf / sizeof(TCHAR)) - 1;
  182. if (cchRemain < 2)
  183. {
  184. break;
  185. }
  186. lstrcat(ptszDomainAndMachineName, TEXT("/"));
  187. cchRemain--;
  188. hr = S_OK;
  189. } while (0);
  190. //
  191. // If there was any problem with the domain name, put only the user name
  192. // in the buffer.
  193. //
  194. if (FAILED(hr))
  195. {
  196. *ptszDomainAndMachineName = TEXT('\0');
  197. cchRemain = cchBuf;
  198. }
  199. //
  200. // Get the machine name, which is going either at the start of the buffer
  201. // or just after the backslash appended to the domain name.
  202. //
  203. lr = GetComputerName(&ptszDomainAndMachineName[cchBuf - cchRemain], &cchRemain);
  204. if (!lr)
  205. {
  206. *ptszDomainAndMachineName = TEXT('\0');
  207. }
  208. if (hkWinlogon)
  209. {
  210. RegCloseKey(hkWinlogon);
  211. }
  212. }
  213. void LoadSecur32Dll()
  214. {
  215. if (g_fLoadedSecur32)
  216. return;
  217. CCriticalSection cCritSect(&g_CritSectCommonLib,GetCurrentThreadId());
  218. cCritSect.Enter();
  219. // make sure not loaded again in case someone took lock first
  220. if (!g_fLoadedSecur32)
  221. {
  222. g_hinstSecur32 = LoadLibrary(szSecur32Dll);
  223. if (g_hinstSecur32)
  224. {
  225. g_pfGetUserNameEx = (PFNGETUSERNAMEEX) GetProcAddress(g_hinstSecur32, szGetUserNameEx);
  226. // won't get the export on NT 4.0
  227. }
  228. g_fLoadedSecur32 = TRUE;
  229. }
  230. cCritSect.Leave();
  231. }
  232. //+--------------------------------------------------------------------------
  233. //
  234. // Function: GetNT4UserDomainName
  235. //
  236. // Synopsis: Fill [ptszDomainAndUserName] with "domain\user" string
  237. //
  238. // Arguments: [ptszDomainAndUserName] - buffer to receive string
  239. // [cchBuf] - should be at least UNLEN
  240. //
  241. // Modifies: *[ptszDomainAndUserName].
  242. //
  243. // History: 06-03-1997 DavidMun Created
  244. //
  245. // Notes: If an error occurs while retrieving the domain name, only
  246. // the user name is returned. If even that cannot be
  247. // retrieved, the buffer is set to an empty string.
  248. //
  249. //---------------------------------------------------------------------------
  250. BOOL GetNT4UserDomainName(LPTSTR ptszDomainAndUserName,
  251. LPTSTR ptszSeparator,
  252. ULONG cchBuf)
  253. {
  254. HKEY hkWinlogon = NULL;
  255. ULONG cchRemain = cchBuf;
  256. HRESULT hr = E_FAIL;
  257. LONG lr;
  258. ULONG cchTemp = UNLEN + DNLEN + 1;
  259. do
  260. {
  261. //
  262. // Get the domain name of the currently logged on user. Open the
  263. // winlogon key.
  264. //
  265. lr = RegOpenKeyExXp(HKEY_LOCAL_MACHINE,
  266. REGSTR_WINLOGON,
  267. 0,
  268. KEY_QUERY_VALUE,
  269. &hkWinlogon,FALSE /*fSetSecurity*/);
  270. if (lr != ERROR_SUCCESS)
  271. {
  272. break;
  273. }
  274. //
  275. // Query for the default domain, which is what the user logged on to.
  276. //
  277. ULONG cbBuf = cchBuf * sizeof(TCHAR);
  278. DWORD dwType;
  279. lr = RegQueryValueEx(hkWinlogon,
  280. REGSTR_DEFAULT_DOMAIN,
  281. NULL,
  282. &dwType,
  283. (LPBYTE) ptszDomainAndUserName,
  284. &cbBuf);
  285. if (lr != ERROR_SUCCESS)
  286. {
  287. break;
  288. }
  289. Assert(dwType == REG_SZ);
  290. //
  291. // Account for the characters used up by the domain name, but
  292. // don't count the trailing NULL.
  293. //
  294. cchRemain -= (cbBuf / sizeof(TCHAR)) - 1;
  295. if (cchRemain < 2)
  296. {
  297. break;
  298. }
  299. lstrcat(ptszDomainAndUserName, ptszSeparator);
  300. cchRemain--;
  301. hr = S_OK;
  302. } while (0);
  303. //
  304. // If there was any problem with the domain name, put only the user name
  305. // in the buffer.
  306. //
  307. if (FAILED(hr))
  308. {
  309. *ptszDomainAndUserName = TEXT('\0');
  310. cchRemain = cchBuf;
  311. }
  312. //
  313. // Get the user name, which is going either at the start of the buffer
  314. // or just after the backslash appended to the domain name.
  315. //
  316. cchTemp = cchRemain;
  317. lr = GetUserName(&ptszDomainAndUserName[cchBuf - cchTemp], &cchTemp);
  318. if (hkWinlogon)
  319. {
  320. RegCloseKey(hkWinlogon);
  321. }
  322. return (S_OK == hr) ? TRUE: FALSE;
  323. }
  324. //+--------------------------------------------------------------------------
  325. //
  326. // Function: GetDefaultDomainAndUserName
  327. //
  328. // Synopsis: Fill [ptszDomainAndUserName] with "domain\user" string
  329. //
  330. // Arguments: [ptszDomainAndUserName] - buffer to receive string
  331. // [cchBuf] - should be at least UNLEN
  332. //
  333. // Modifies: *[ptszDomainAndUserName].
  334. //
  335. // History: 06-03-1997 DavidMun Created
  336. //
  337. // Notes: If an error occurs while retrieving the domain name, only
  338. // the user name is returned. If even that cannot be
  339. // retrieved, the buffer is set to an empty string.
  340. //
  341. //---------------------------------------------------------------------------
  342. // if output buffer is too small it gets truncated.
  343. VOID
  344. GetDefaultDomainAndUserName(
  345. LPTSTR ptszDomainAndUserName,
  346. LPTSTR ptszSeparator,
  347. ULONG cchBuf)
  348. {
  349. HRESULT hr = E_FAIL;
  350. LONG lr = 0;
  351. ULONG cchTemp = UNLEN + DNLEN + 1;
  352. BOOL fIsNT = (g_OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
  353. if (fIsNT)
  354. {
  355. LoadSecur32Dll();
  356. if (g_pfGetUserNameEx)
  357. {
  358. lr = g_pfGetUserNameEx(NameSamCompatible,ptszDomainAndUserName, &cchTemp);
  359. if (lr)
  360. {
  361. LPTSTR ptszWorker = ptszDomainAndUserName;
  362. while ( (TEXT('\0') != *ptszWorker) && *ptszWorker != TEXT('\\'))
  363. {
  364. ptszWorker++;
  365. }
  366. if ( TEXT('\0') != *ptszWorker)
  367. {
  368. *ptszWorker = ptszSeparator[0];
  369. }
  370. }
  371. }
  372. if ((NULL == g_pfGetUserNameEx) || (0 == lr))
  373. {
  374. GetNT4UserDomainName(ptszDomainAndUserName,ptszSeparator,cchBuf);
  375. }
  376. }
  377. else
  378. {
  379. // Win9x Stuff.
  380. cchTemp = cchBuf;
  381. if (!(lr = RegGetCurrentUser(ptszDomainAndUserName, &cchTemp)))
  382. {
  383. cchTemp = cchBuf;
  384. lr = GetUserName(ptszDomainAndUserName,&cchTemp);
  385. if (!lr || (*ptszDomainAndUserName == NULL))
  386. {
  387. // on Win9x user can work without a user Name in this case
  388. // or any other GetUserName file the user is forced
  389. // to be called Default
  390. Assert(lstrlen(SZ_DEFAULTDOMAINANDUSERNAME) < cchBuf);
  391. lstrcpy(ptszDomainAndUserName,SZ_DEFAULTDOMAINANDUSERNAME);
  392. }
  393. // write out currentUser setting so can use next time.
  394. RegSetCurrentUser(ptszDomainAndUserName);
  395. }
  396. }
  397. Assert(NULL != *ptszDomainAndUserName);
  398. return;
  399. }
  400. //+-------------------------------------------------------------------------------
  401. //
  402. // FUNCTION: BOOL ConvertString(LPTSTR pszOut, LPWSTR pwszIn, DWORD dwSize)
  403. //
  404. // PURPOSE: utility function for ANSI/UNICODE conversion
  405. //
  406. // RETURN VALUE: return TRUE if we process it ok.
  407. //
  408. //+-------------------------------------------------------------------------------
  409. BOOL ConvertString(char * pszOut, LPWSTR pwszIn, DWORD dwSize)
  410. {
  411. if(WideCharToMultiByte( CP_ACP,0,pwszIn,-1,pszOut,dwSize,NULL,NULL))
  412. {
  413. return TRUE;
  414. }
  415. return FALSE;
  416. }
  417. //+-------------------------------------------------------------------------------
  418. //
  419. // FUNCTION: BOOL ConvertString(LPWSTR pwszOut, LPTSTR pszIn, DWORD dwSize)
  420. //
  421. // PURPOSE: utility function for ANSI/UNICODE conversion
  422. //
  423. // RETURN VALUE: return TRUE if we process it ok.
  424. //
  425. //+-------------------------------------------------------------------------------
  426. BOOL ConvertString(LPWSTR pwszOut,char * pszIn, DWORD dwSize)
  427. {
  428. if(MultiByteToWideChar( CP_ACP,0,pszIn,-1,pwszOut,dwSize))
  429. {
  430. return TRUE;
  431. }
  432. return FALSE;
  433. }
  434. //+-------------------------------------------------------------------------------
  435. //
  436. // FUNCTION: Bogus function temporary until get transitioned to unicode
  437. // so I don't have to fix up every existing converstring call.
  438. //
  439. // PURPOSE: utility function for ANSI/UNICODE conversion
  440. //
  441. // RETURN VALUE: return TRUE if we process it ok.
  442. //
  443. //+-------------------------------------------------------------------------------
  444. BOOL ConvertString(LPWSTR pszOut, LPWSTR pwszIn, DWORD dwSize)
  445. {
  446. #ifdef _UNICODE
  447. lstrcpy(pszOut,pwszIn);
  448. #else
  449. AssertSz(0,"Shouldn't be called in ASCII mode");
  450. #endif // _UNICODE
  451. return TRUE;
  452. }
  453. //+-------------------------------------------------------------------------------
  454. //
  455. // Function: ConvertMultiByteToWideChar
  456. //
  457. // Synopsis: Converts multibyte strings to Unicode
  458. //
  459. /// Arguments: [pszBufIn] -- Input multibyte string
  460. // [cbBufIn] -- Count of chars/bytes in input buffer
  461. // [xwszBufOut] -- Smart pointer to output Unicode string
  462. // [fOem] -- If true use CP_OEMCP
  463. //
  464. // Returns: TRUE if we process it ok
  465. //
  466. // History: 14-Jul-98 SitaramR Created
  467. //
  468. //+-------------------------------------------------------------------------------
  469. BOOL ConvertMultiByteToWideChar( const char *pszBufIn,
  470. ULONG cbBufIn,
  471. XArray<WCHAR>& xwszBufOut,
  472. BOOL fOem )
  473. {
  474. Assert( pszBufIn != 0 );
  475. if ( 0 == cbBufIn )
  476. {
  477. xwszBufOut[0] = 0;
  478. return TRUE;
  479. }
  480. BOOL fOk;
  481. if ( xwszBufOut.Get() == 0 )
  482. {
  483. ULONG cbBufOut;
  484. cbBufOut = (-1 == cbBufIn) ? lstrlenA(pszBufIn) + 1: cbBufIn;
  485. cbBufOut += 6; // give it a little extra room
  486. fOk = xwszBufOut.Init(cbBufOut);
  487. if ( !fOk )
  488. return FALSE;
  489. }
  490. UINT codePage = CP_ACP;
  491. if ( fOem && !AreFileApisANSI() )
  492. codePage = CP_OEMCP;
  493. ULONG cwcBufOut = (ULONG)xwszBufOut.Count();
  494. ULONG cwcConvert = 0;
  495. do
  496. {
  497. cwcConvert = MultiByteToWideChar( codePage,
  498. MB_PRECOMPOSED,
  499. pszBufIn,
  500. cbBufIn,
  501. xwszBufOut.Get(),
  502. cwcBufOut - 1 );
  503. if ( 0 == cwcConvert )
  504. {
  505. if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
  506. {
  507. //
  508. // Double buffer size and then retry
  509. //
  510. delete xwszBufOut.Acquire();
  511. cwcBufOut *= 2;
  512. fOk = xwszBufOut.Init( cwcBufOut );
  513. if ( !fOk )
  514. return FALSE;
  515. }
  516. else
  517. {
  518. //
  519. // Error during conversion
  520. //
  521. Assert( FALSE );
  522. return FALSE;
  523. }
  524. }
  525. else
  526. xwszBufOut[cwcConvert] = 0;
  527. } while ( 0 == cwcConvert );
  528. return TRUE;
  529. }
  530. //+-------------------------------------------------------------------------------
  531. //
  532. // Function: ConvertMultiByteToWideChar
  533. //
  534. // Synopsis: Converts multibyte strings to Unicode
  535. //
  536. /// Arguments: [pszBufIn] -- Input to null terminated multibyte string
  537. // [xwszBufOut] -- Smart pointer to output Unicode string
  538. // [fOem] -- If true use CP_OEMCP
  539. //
  540. // Returns: TRUE if we process it ok
  541. //
  542. // History: 14-Jul-98 SitaramR Created
  543. //
  544. //+-------------------------------------------------------------------------------
  545. BOOL ConvertMultiByteToWideChar( const char *pszBufIn,
  546. XArray<WCHAR>& xwszBufOut,
  547. BOOL fOem )
  548. {
  549. if ( pszBufIn == 0)
  550. {
  551. void *pBuf;
  552. if (pBuf = xwszBufOut.Acquire())
  553. {
  554. delete pBuf;
  555. }
  556. return TRUE;
  557. }
  558. BOOL fRet = ConvertMultiByteToWideChar( pszBufIn,
  559. -1 /* lstrlenA(pszBufIn) + 1 */,
  560. xwszBufOut,
  561. fOem );
  562. return fRet;
  563. }
  564. //+-------------------------------------------------------------------------------
  565. //
  566. // Function: ConvertWideCharToMultiByte
  567. //
  568. // Synopsis: Converts Unicode to multibyte strings
  569. //
  570. /// Arguments: [pwszBufIn] -- Input Unicode string
  571. // [cwcBufIn] -- Count of wide chars in input buffer
  572. // [xwszBufOut] -- Smart pointer to output multibyte string
  573. // [fOem] -- If true use CP_OEMCP
  574. //
  575. // Returns: TRUE if we process it ok
  576. //
  577. // History: 14-Jul-98 SitaramR Created
  578. //
  579. //+-------------------------------------------------------------------------------
  580. BOOL ConvertWideCharToMultiByte( const WCHAR *pwszBufIn,
  581. ULONG cwcBufIn,
  582. XArray<char>& xszBufOut,
  583. BOOL fOem )
  584. {
  585. Assert( pwszBufIn != 0 );
  586. if ( 0 == cwcBufIn )
  587. {
  588. xszBufOut[0] = 0;
  589. return TRUE;
  590. }
  591. BOOL fOk;
  592. if ( xszBufOut.Get() == 0 )
  593. {
  594. ULONG cbBufOut;
  595. cbBufOut = (-1 == cwcBufIn) ? lstrlenX(pwszBufIn) + 1: cwcBufIn;
  596. cbBufOut += 6; // give it a little extra room.
  597. fOk = xszBufOut.Init(cbBufOut);
  598. if ( !fOk )
  599. return FALSE;
  600. }
  601. UINT codePage = CP_ACP;
  602. if ( fOem && !AreFileApisANSI() )
  603. codePage = CP_OEMCP;
  604. ULONG cbConvert;
  605. ULONG cbBufOut = (ULONG)xszBufOut.Count();
  606. do
  607. {
  608. cbConvert = WideCharToMultiByte( codePage,
  609. WC_COMPOSITECHECK,
  610. pwszBufIn,
  611. cwcBufIn,
  612. xszBufOut.Get(),
  613. cbBufOut - 1,
  614. NULL,
  615. NULL );
  616. if ( 0 == cbConvert )
  617. {
  618. if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
  619. {
  620. //
  621. // Double buffer size and then retry
  622. //
  623. delete xszBufOut.Acquire();
  624. cbBufOut *= 2;
  625. fOk = xszBufOut.Init( cbBufOut );
  626. if ( !fOk )
  627. return FALSE;
  628. }
  629. else
  630. {
  631. //
  632. // Error during conversion
  633. //
  634. Assert( FALSE );
  635. return FALSE;
  636. }
  637. }
  638. else
  639. xszBufOut[cbConvert] = 0;
  640. } while ( 0 == cbConvert );
  641. return TRUE;
  642. }
  643. //+-------------------------------------------------------------------------------
  644. //
  645. // Function: ConvertWideCharToMultiByte
  646. //
  647. // Synopsis: Converts Unicode to multibyte strings
  648. //
  649. /// Arguments: [pwszBufIn] -- Input to null terminated Unicode string
  650. // [xwszBufOut] -- Smart pointer to output multibyte string
  651. // [fOem] -- If true use CP_OEMCP
  652. //
  653. // Returns: TRUE if we process it ok
  654. //
  655. // History: 14-Jul-98 SitaramR Created
  656. //
  657. //+-------------------------------------------------------------------------------
  658. BOOL ConvertWideCharToMultiByte( const WCHAR *pwszBufIn,
  659. XArray<char>& xszBufOut,
  660. BOOL fOem )
  661. {
  662. if ( pwszBufIn == 0)
  663. {
  664. void *pBuf;
  665. if (pBuf = xszBufOut.Acquire())
  666. {
  667. delete pBuf;
  668. }
  669. return TRUE;
  670. }
  671. BOOL fRet = ConvertWideCharToMultiByte( pwszBufIn,
  672. lstrlenX(pwszBufIn) + 1,
  673. xszBufOut,
  674. fOem );
  675. return fRet;
  676. }
  677. //
  678. // Local constants
  679. //
  680. // DEFAULT_TIME_FORMAT - what to use if there's a problem getting format
  681. // from system.
  682. //
  683. #define ARRAYLEN(a) (sizeof(a) / sizeof((a)[0]))
  684. #define DEFAULT_TIME_FORMAT TEXT("hh:mm tt")
  685. #define GET_LOCALE_INFO(lcid) \
  686. { \
  687. cch = GetLocaleInfo(LOCALE_USER_DEFAULT, \
  688. (lcid), \
  689. tszScratch, \
  690. ARRAYLEN(tszScratch)); \
  691. if (!cch) \
  692. { \
  693. break; \
  694. } \
  695. }
  696. //+--------------------------------------------------------------------------
  697. //
  698. // Function: UpdateTimeFormat
  699. //
  700. // Synopsis: Construct a time format containing hour and minute for use
  701. // with the date picker control.
  702. //
  703. // Arguments: [tszTimeFormat] - buffer to fill with time format
  704. // [cchTimeFormat] - size in chars of buffer
  705. //
  706. // Modifies: *[tszTimeFormat]
  707. //
  708. // History: 11-18-1996 DavidMun Created
  709. //
  710. // Notes: This is called on initialization and for wininichange
  711. // processing.
  712. //
  713. //---------------------------------------------------------------------------
  714. void
  715. UpdateTimeFormat(
  716. LPTSTR tszTimeFormat,
  717. ULONG cchTimeFormat)
  718. {
  719. ULONG cch;
  720. TCHAR tszScratch[80];
  721. BOOL fAmPm;
  722. BOOL fAmPmPrefixes;
  723. BOOL fLeadingZero;
  724. do
  725. {
  726. GET_LOCALE_INFO(LOCALE_ITIME);
  727. fAmPm = (*tszScratch == TEXT('0'));
  728. if (fAmPm)
  729. {
  730. GET_LOCALE_INFO(LOCALE_ITIMEMARKPOSN);
  731. fAmPmPrefixes = (*tszScratch == TEXT('1'));
  732. }
  733. GET_LOCALE_INFO(LOCALE_ITLZERO);
  734. fLeadingZero = (*tszScratch == TEXT('1'));
  735. GET_LOCALE_INFO(LOCALE_STIME);
  736. //
  737. // See if there's enough room in destination string
  738. //
  739. cch = 1 + // terminating nul
  740. 1 + // first hour digit specifier "h"
  741. 2 + // minutes specifier "mm"
  742. (fLeadingZero != 0) + // leading hour digit specifier "h"
  743. lstrlen(tszScratch) + // separator string
  744. (fAmPm ? 3 : 0); // space and "tt" for AM/PM
  745. if (cch > cchTimeFormat)
  746. {
  747. cch = 0; // signal error
  748. }
  749. } while (0);
  750. //
  751. // If there was a problem in getting locale info for building time string
  752. // just use the default and bail.
  753. //
  754. if (!cch)
  755. {
  756. lstrcpy(tszTimeFormat, DEFAULT_TIME_FORMAT);
  757. return;
  758. }
  759. //
  760. // Build a time string that has hours and minutes but no seconds.
  761. //
  762. tszTimeFormat[0] = TEXT('\0');
  763. if (fAmPm)
  764. {
  765. if (fAmPmPrefixes)
  766. {
  767. lstrcpy(tszTimeFormat, TEXT("tt "));
  768. }
  769. lstrcat(tszTimeFormat, TEXT("h"));
  770. if (fLeadingZero)
  771. {
  772. lstrcat(tszTimeFormat, TEXT("h"));
  773. }
  774. }
  775. else
  776. {
  777. lstrcat(tszTimeFormat, TEXT("H"));
  778. if (fLeadingZero)
  779. {
  780. lstrcat(tszTimeFormat, TEXT("H"));
  781. }
  782. }
  783. lstrcat(tszTimeFormat, tszScratch); // separator
  784. lstrcat(tszTimeFormat, TEXT("mm"));
  785. if (fAmPm && !fAmPmPrefixes)
  786. {
  787. lstrcat(tszTimeFormat, TEXT(" tt"));
  788. }
  789. }
  790. //+--------------------------------------------------------------------------
  791. //
  792. // Function: FillInStartDateTime
  793. //
  794. // Synopsis: Fill [pTrigger]'s starting date and time values from the
  795. // values in the date/time picker controls.
  796. //
  797. // Arguments: [hwndDatePick] - handle to control with start date
  798. // [hwndTimePick] - handle to control with start time
  799. // [pTrigger] - trigger to init
  800. //
  801. // Modifies: *[pTrigger]
  802. //
  803. // History: 12-08-1997 SusiA Stole from task scheduler
  804. //
  805. //---------------------------------------------------------------------------
  806. VOID FillInStartDateTime( HWND hwndDatePick, HWND hwndTimePick,TASK_TRIGGER *pTrigger)
  807. {
  808. SYSTEMTIME st;
  809. DateTime_GetSystemtime(hwndDatePick, &st);
  810. pTrigger->wBeginYear = st.wYear;
  811. pTrigger->wBeginMonth = st.wMonth;
  812. pTrigger->wBeginDay = st.wDay;
  813. DateTime_GetSystemtime(hwndTimePick, &st);
  814. pTrigger->wStartHour = st.wHour;
  815. pTrigger->wStartMinute = st.wMinute;
  816. }
  817. //+---------------------------------------------------------------------------
  818. //
  819. // function: InsertListViewColumn, private
  820. //
  821. // Synopsis: Inserts a column into the ListView..
  822. //
  823. // Arguments:
  824. //
  825. // Returns:
  826. //
  827. // Modifies:
  828. //
  829. // History: 30-Jul-98 rogerg Created.
  830. //
  831. //----------------------------------------------------------------------------
  832. BOOL InsertListViewColumn(CListView *pListView,int iColumnId,LPWSTR pszText,int fmt,int cx)
  833. {
  834. LV_COLUMN columnInfo;
  835. columnInfo.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
  836. columnInfo.fmt = fmt;
  837. columnInfo.cx = cx;
  838. columnInfo.pszText = pszText;
  839. columnInfo.iSubItem = 0;
  840. return pListView->InsertColumn(iColumnId,&columnInfo);
  841. }
  842. //+--------------------------------------------------------------------------
  843. //
  844. // Function: InitResizeItem
  845. //
  846. // Synopsis: Setups the ResizeInfo Structure.
  847. //
  848. // !!Can either pass in a ParentScreenRect or
  849. // function will calculate. If passing in
  850. // make sure you don't include the NC area
  851. // of the window. See code below GetClientRect on parent
  852. // then ClientToScreen.
  853. //
  854. // Arguments:
  855. //
  856. // Modifies:
  857. //
  858. // History: 30-07-1998 rogerg
  859. //
  860. //---------------------------------------------------------------------------
  861. BOOL InitResizeItem(int iCtrlId,DWORD dlgResizeFlags,HWND hwndParent,
  862. LPRECT pParentClientRect,DLGRESIZEINFO *pDlgResizeInfo)
  863. {
  864. RECT rectCtrl;
  865. RECT rectLocalParentScreenRect;
  866. Assert(pDlgResizeInfo);
  867. Assert(0 == pParentClientRect->left); // catch any case not handing in ClientRect.
  868. pDlgResizeInfo->iCtrlId = -1; // set ctrlId to -1 so GetDlgItem will fail in resize
  869. // if dont' have parentScreenRect get it ourselves
  870. if (!pParentClientRect)
  871. {
  872. pParentClientRect = &rectLocalParentScreenRect;
  873. if (!GetClientRect(hwndParent,&rectLocalParentScreenRect))
  874. {
  875. AssertSz(0,"Unable to get Parent Rects");
  876. return FALSE;
  877. }
  878. }
  879. Assert(pParentClientRect);
  880. if (!GetWindowRect(GetDlgItem(hwndParent,iCtrlId),&rectCtrl))
  881. {
  882. AssertSz(0,"Failed to GetWindowRect");
  883. return FALSE;
  884. }
  885. MapWindowPoints(NULL,hwndParent,(LPPOINT) &rectCtrl,2);
  886. pDlgResizeInfo->iCtrlId = iCtrlId;
  887. pDlgResizeInfo->hwndParent = hwndParent;
  888. pDlgResizeInfo->dlgResizeFlags = dlgResizeFlags;
  889. // calc the offsets
  890. pDlgResizeInfo->rectParentOffsets.left = rectCtrl.left - pParentClientRect->left;
  891. pDlgResizeInfo->rectParentOffsets.top = rectCtrl.top - pParentClientRect->top;
  892. pDlgResizeInfo->rectParentOffsets.right = pParentClientRect->right - rectCtrl.right;
  893. pDlgResizeInfo->rectParentOffsets.bottom = pParentClientRect->bottom - rectCtrl.bottom;
  894. return TRUE;
  895. }
  896. //+--------------------------------------------------------------------------
  897. //
  898. // Function: ResizeItems
  899. //
  900. // Synopsis: Resizes the Item.
  901. //
  902. //
  903. // Arguments:
  904. //
  905. // Modifies:
  906. //
  907. // History: 30-07-1998 rogerg
  908. //
  909. //---------------------------------------------------------------------------
  910. void ResizeItems(ULONG cbNumItems,DLGRESIZEINFO *pDlgResizeInfo)
  911. {
  912. RECT rectLocalParentClientCoord; // used if caller doesn't pass in parent coords.
  913. DWORD dlgResizeFlags;
  914. LPRECT prectOffsets;
  915. RECT rectClient;
  916. HWND hwndCtrl;
  917. HWND hwndLastParent = NULL;
  918. LPRECT prectParentClientCoords = NULL;
  919. ULONG ulCount;
  920. DLGRESIZEINFO *pCurDlgResizeInfo;
  921. int x,y,cx,cy;
  922. if (!pDlgResizeInfo)
  923. {
  924. Assert(pDlgResizeInfo);
  925. }
  926. for (ulCount = 0; ulCount < cbNumItems; ulCount++)
  927. {
  928. pCurDlgResizeInfo = &(pDlgResizeInfo[ulCount]);
  929. dlgResizeFlags = pCurDlgResizeInfo->dlgResizeFlags;
  930. prectOffsets = &(pCurDlgResizeInfo->rectParentOffsets);
  931. // if not pinright or pin bottom there is nothing
  932. // to do.
  933. if (!(dlgResizeFlags & DLGRESIZEFLAG_PINRIGHT) &&
  934. !(dlgResizeFlags & DLGRESIZEFLAG_PINBOTTOM) )
  935. {
  936. continue;
  937. }
  938. if (NULL == prectParentClientCoords || (hwndLastParent != pCurDlgResizeInfo->hwndParent))
  939. {
  940. prectParentClientCoords = &rectLocalParentClientCoord;
  941. if (!GetClientRect(pCurDlgResizeInfo->hwndParent,&rectLocalParentClientCoord))
  942. {
  943. prectParentClientCoords = NULL; // if GetClientRect failed for a recalc on next item
  944. continue;
  945. }
  946. hwndLastParent = pCurDlgResizeInfo->hwndParent; // set lastparent now that we calc'd the rect.
  947. }
  948. Assert(prectParentClientCoords);
  949. hwndCtrl = GetDlgItem(pCurDlgResizeInfo->hwndParent,pCurDlgResizeInfo->iCtrlId);
  950. if ( (NULL == hwndCtrl) || !(GetWindowRect(hwndCtrl,&rectClient)) )
  951. {
  952. continue;
  953. }
  954. // get current values
  955. x = (prectParentClientCoords->left + prectOffsets->left);
  956. y = (prectParentClientCoords->top + prectOffsets->top);
  957. cx = WIDTH(rectClient);
  958. cy = HEIGHT(rectClient);
  959. // if pinned both right and left adjust the width
  960. if ((dlgResizeFlags & DLGRESIZEFLAG_PINLEFT)
  961. && (dlgResizeFlags & DLGRESIZEFLAG_PINRIGHT))
  962. {
  963. cx = prectParentClientCoords->right - (prectOffsets->right + prectOffsets->left);
  964. }
  965. // if pinned both top and bottom adjust height
  966. if ((dlgResizeFlags & DLGRESIZEFLAG_PINTOP)
  967. && (dlgResizeFlags & DLGRESIZEFLAG_PINBOTTOM))
  968. {
  969. cy = prectParentClientCoords->bottom - (prectOffsets->bottom + prectOffsets->top);
  970. }
  971. // adjust the x position if pin right
  972. if (dlgResizeFlags & DLGRESIZEFLAG_PINRIGHT)
  973. {
  974. x = (prectParentClientCoords->right - prectOffsets->right) - cx;
  975. }
  976. // adjust the y position if pin bottom
  977. if (dlgResizeFlags & DLGRESIZEFLAG_PINBOTTOM)
  978. {
  979. y = (prectParentClientCoords->bottom - prectOffsets->bottom) - cy;
  980. }
  981. SetWindowPos(hwndCtrl, 0,x,y,cx,cy,SWP_NOZORDER | SWP_NOACTIVATE);
  982. }
  983. // now that the items are moved, loop through them again invalidating
  984. // any items with the nocopy bits flag set
  985. for (ulCount = 0; ulCount < cbNumItems; ulCount++)
  986. {
  987. pCurDlgResizeInfo = &(pDlgResizeInfo[ulCount]);
  988. if (pCurDlgResizeInfo->dlgResizeFlags & DLGRESIZEFLAG_NOCOPYBITS)
  989. {
  990. hwndCtrl = GetDlgItem(pCurDlgResizeInfo->hwndParent,pCurDlgResizeInfo->iCtrlId);
  991. if (hwndCtrl && GetClientRect(hwndCtrl,&rectClient))
  992. {
  993. InvalidateRect(hwndCtrl,&rectClient,FALSE);
  994. }
  995. }
  996. }
  997. }
  998. //+--------------------------------------------------------------------------
  999. //
  1000. // Function: CalcListViewWidth
  1001. //
  1002. // Synopsis: Calcs width of listview - scroll bars
  1003. //
  1004. //
  1005. // Arguments:
  1006. //
  1007. // Modifies:
  1008. //
  1009. // History: 30-07-1998 rogerg
  1010. //
  1011. //---------------------------------------------------------------------------
  1012. int CalcListViewWidth(HWND hwndList,int iDefault)
  1013. {
  1014. NONCLIENTMETRICSA metrics;
  1015. RECT rcClientRect;
  1016. metrics.cbSize = sizeof(metrics);
  1017. // explicitly ask for ANSI version of SystemParametersInfo since we just
  1018. // care about the ScrollWidth and don't want to conver the LOGFONT info.
  1019. if (GetClientRect(hwndList,&rcClientRect)
  1020. && SystemParametersInfoA(SPI_GETNONCLIENTMETRICS,sizeof(metrics),(PVOID) &metrics,0))
  1021. {
  1022. // subtract off scroll bar distance
  1023. rcClientRect.right -= (metrics.iScrollWidth);
  1024. }
  1025. else
  1026. {
  1027. rcClientRect.right = iDefault; // if fail, use default
  1028. }
  1029. return rcClientRect.right;
  1030. }
  1031. //+--------------------------------------------------------------------------
  1032. //
  1033. // Function: SetCtrlFont
  1034. //
  1035. // Synopsis: Sets the appropriate font on the hwnd
  1036. // based on the platform and langID passed in.
  1037. //
  1038. //
  1039. // Arguments:
  1040. //
  1041. // Modifies:
  1042. //
  1043. // History: 25-09-1998 rogerg
  1044. //
  1045. //---------------------------------------------------------------------------
  1046. // Example: SetCtrlFont(hwndList,g_OSVersionInfo.dwPlatformId,g_LangIdSystem);
  1047. void SetCtrlFont(HWND hwnd,DWORD dwPlatformID,LANGID langId)
  1048. {
  1049. // IE is in the process of cleaning up their controls as
  1050. // of 8/27/98 the controls we would need to set the font on are
  1051. // Edit,Static and ListBox (listView is okay). Haven't tested the Combo Box
  1052. // If want to turn this on need to make sure all the proper controls
  1053. // are wrapped for now we don't do anything
  1054. #if _SETFONTOURSELF
  1055. // if on Win95J platform need to do font substitution ourselfs.
  1056. // Review what we do on Win98
  1057. if ((VER_PLATFORM_WIN32_WINDOWS == dwPlatformID)
  1058. && (LANG_JAPANESE == PRIMARYLANGID(langId)) )
  1059. {
  1060. SendMessage(hwnd,WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT),0);
  1061. }
  1062. #endif // _SETFONTOURSELF
  1063. return;
  1064. }
  1065. //+--------------------------------------------------------------------------
  1066. //
  1067. // Function: IsHwndRightToLeft
  1068. //
  1069. // Synopsis: determine if hwnd is right to left.
  1070. //
  1071. //
  1072. // Arguments:
  1073. //
  1074. // Modifies:
  1075. //
  1076. // History: 04-02-1999 rogerg
  1077. //
  1078. //---------------------------------------------------------------------------
  1079. BOOL IsHwndRightToLeft(HWND hwnd)
  1080. {
  1081. LONG_PTR ExStyles;
  1082. if (NULL == hwnd)
  1083. {
  1084. Assert(hwnd);
  1085. return FALSE;
  1086. }
  1087. ExStyles = GetWindowLongPtr(hwnd,GWL_EXSTYLE);
  1088. if (WS_EX_LAYOUTRTL & ExStyles)
  1089. {
  1090. // this is righ to left
  1091. return TRUE;
  1092. }
  1093. return FALSE;
  1094. }
  1095. //+--------------------------------------------------------------------------
  1096. //
  1097. // Function: GetDateFormatReadingFlags
  1098. //
  1099. // Synopsis: returns necessary flags settings for passing proper
  1100. // Reading order flags to GetDateFormat()
  1101. //
  1102. //
  1103. // Arguments:
  1104. //
  1105. // Modifies:
  1106. //
  1107. // History: 09-07-1999 rogerg
  1108. //
  1109. //---------------------------------------------------------------------------
  1110. DWORD GetDateFormatReadingFlags(HWND hwnd)
  1111. {
  1112. DWORD dwDateReadingFlags = 0;
  1113. LCID locale = GetUserDefaultLCID();
  1114. // only set on NT 5.0 or higher.
  1115. if ( (VER_PLATFORM_WIN32_NT == g_OSVersionInfo.dwPlatformId)
  1116. && ( 5 <= g_OSVersionInfo.dwMajorVersion) )
  1117. {
  1118. if ((PRIMARYLANGID(LANGIDFROMLCID(locale)) == LANG_ARABIC)
  1119. || (PRIMARYLANGID(LANGIDFROMLCID(locale)) == LANG_HEBREW))
  1120. {
  1121. LONG_PTR dwExStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
  1122. if ((!!(dwExStyle & WS_EX_RTLREADING)) != (!!(dwExStyle & WS_EX_LAYOUTRTL)))
  1123. {
  1124. dwDateReadingFlags = DATE_RTLREADING;
  1125. }
  1126. else
  1127. {
  1128. dwDateReadingFlags = DATE_LTRREADING;
  1129. }
  1130. }
  1131. }
  1132. return dwDateReadingFlags;
  1133. }
  1134. #ifdef _SETSECURITY
  1135. //+--------------------------------------------------------------------------
  1136. //
  1137. // Function: SetRegKeySecurityEveryone
  1138. //
  1139. // Synopsis: Gives Everyone all access to the specified RegKey.
  1140. //
  1141. //
  1142. // Arguments:
  1143. //
  1144. // Modifies:
  1145. //
  1146. // History: 01-19-1999 rogerg
  1147. //
  1148. //---------------------------------------------------------------------------
  1149. BOOL SetRegKeySecurityEveryone(HKEY hKeyParent,LPCWSTR lpSubKey)
  1150. {
  1151. BOOL fResult = FALSE;
  1152. HKEY hKey = NULL;
  1153. if (VER_PLATFORM_WIN32_NT != g_OSVersionInfo.dwPlatformId)
  1154. {
  1155. return TRUE;
  1156. }
  1157. // key must be openned with WRITE_DAC
  1158. if (ERROR_SUCCESS != RegOpenKeyExXp(hKeyParent,
  1159. lpSubKey,
  1160. REG_OPTION_OPEN_LINK, WRITE_DAC,&hKey,FALSE /*fSetSecurity*/) )
  1161. {
  1162. hKey = NULL;
  1163. }
  1164. if (hKey)
  1165. {
  1166. SECURITY_DESCRIPTOR SecurityDescriptor;
  1167. // Initialize an empty security descriptor and use this to set DACL. Since
  1168. // no DACL list in new Security Descriptor everyone will get access to the Key.
  1169. if (InitializeSecurityDescriptor(&SecurityDescriptor,SECURITY_DESCRIPTOR_REVISION))
  1170. {
  1171. if (ERROR_SUCCESS == RegSetKeySecurity(hKey,
  1172. (SECURITY_INFORMATION) DACL_SECURITY_INFORMATION,
  1173. &SecurityDescriptor) )
  1174. {
  1175. fResult = TRUE;
  1176. }
  1177. }
  1178. RegCloseKey(hKey);
  1179. }
  1180. Assert(TRUE == fResult); // debugging lets find out when this fails.
  1181. return fResult;
  1182. }
  1183. #endif // _SETSECURITY
  1184. //+--------------------------------------------------------------------------
  1185. //
  1186. // Function: QueryHandleException
  1187. //
  1188. // Synopsis: in debug prompts user how to handle the exception
  1189. // return always handle.
  1190. //
  1191. //
  1192. // Arguments:
  1193. //
  1194. // Modifies:
  1195. //
  1196. // History: 01-04-1999 rogerg
  1197. //
  1198. //---------------------------------------------------------------------------
  1199. extern DWORD g_dwDebugLogAsserts; // conform to logAsserts
  1200. BOOL QueryHandleException(void)
  1201. {
  1202. #ifndef _DEBUG
  1203. return EXCEPTION_EXECUTE_HANDLER;
  1204. #else // _DEBUG
  1205. int iMsgResult = 0;
  1206. BOOL fQueryResult = EXCEPTION_EXECUTE_HANDLER;
  1207. // if logging asserts just execute the handler
  1208. if (g_dwDebugLogAsserts)
  1209. {
  1210. return EXCEPTION_EXECUTE_HANDLER;
  1211. }
  1212. iMsgResult = MessageBoxA(NULL,
  1213. "An Exception Occured.\nWould you like to Debug this Exception?",
  1214. "Exception Failure.",
  1215. MB_YESNO | MB_SYSTEMMODAL);
  1216. if (iMsgResult == IDYES)
  1217. {
  1218. fQueryResult = EXCEPTION_CONTINUE_SEARCH;
  1219. }
  1220. // ask the User what they want to do
  1221. return fQueryResult;
  1222. #endif // _DEBUG
  1223. }
  1224. // convert a hex char to an int - used by str to guid conversion
  1225. // we wrote our own, since the ole one is slow, and requires ole32.dll
  1226. // we use ansi strings here, since guids won't get internationalized
  1227. int GetDigit(LPSTR lpstr)
  1228. {
  1229. char ch = *lpstr;
  1230. if (ch >= '0' && ch <= '9')
  1231. return(ch - '0');
  1232. if (ch >= 'a' && ch <= 'f')
  1233. return(ch - 'a' + 10);
  1234. if (ch >= 'A' && ch <= 'F')
  1235. return(ch - 'A' + 10);
  1236. return(0);
  1237. }
  1238. // walk the string, writing pairs of bytes into the byte stream (guid)
  1239. // we need to write the bytes into the byte stream from right to left
  1240. // or left to right as indicated by fRightToLeft
  1241. void ConvertField(LPBYTE lpByte,LPSTR * ppStr,int iFieldSize,BOOL fRightToLeft)
  1242. {
  1243. int i;
  1244. for (i=0;i<iFieldSize ;i++ )
  1245. {
  1246. // don't barf on the field separators
  1247. if ('-' == **ppStr) (*ppStr)++;
  1248. if (fRightToLeft == TRUE)
  1249. {
  1250. // work from right to left within the byte stream
  1251. *(lpByte + iFieldSize - (i+1)) = 16*GetDigit(*ppStr) + GetDigit((*ppStr)+1);
  1252. }
  1253. else
  1254. {
  1255. // work from left to right within the byte stream
  1256. *(lpByte + i) = 16*GetDigit(*ppStr) + GetDigit((*ppStr)+1);
  1257. }
  1258. *ppStr+=2; // get next two digit pair
  1259. }
  1260. } // ConvertField
  1261. int WideToAnsi(LPSTR lpStr,LPWSTR lpWStr,int cchStr)
  1262. {
  1263. int rval;
  1264. BOOL bDefault;
  1265. // use the default code page (CP_ACP)
  1266. // -1 indicates WStr must be null terminated
  1267. rval = WideCharToMultiByte(CP_ACP,0,lpWStr,-1,lpStr,cchStr,"-",&bDefault);
  1268. return rval;
  1269. } // WideToAnsi
  1270. int AnsiToWide(LPWSTR lpWStr,LPSTR lpStr,int cchWStr)
  1271. {
  1272. int rval;
  1273. rval = MultiByteToWideChar(CP_ACP,0,lpStr,-1,lpWStr,cchWStr);
  1274. return rval;
  1275. } // AnsiToWide
  1276. // convert the passed in string to a real GUID
  1277. // walk the guid, setting each byte in the guid to the two digit hex pair in the
  1278. // passed string
  1279. HRESULT GUIDFromString(LPWSTR lpWStr, GUID * pGuid)
  1280. {
  1281. BYTE * lpByte; // byte index into guid
  1282. int iFieldSize; // size of current field we're converting
  1283. // since its a guid, we can do a "brute force" conversion
  1284. char lpTemp[GUID_STRING_SIZE];
  1285. char *lpStr = lpTemp;
  1286. WideToAnsi(lpStr,lpWStr,GUID_STRING_SIZE);
  1287. // make sure we have a {xxxx-...} type guid
  1288. if ('{' != *lpStr) return E_FAIL;
  1289. lpStr++;
  1290. lpByte = (BYTE *)pGuid;
  1291. // data 1
  1292. iFieldSize = sizeof(unsigned long);
  1293. ConvertField(lpByte,&lpStr,iFieldSize,TRUE);
  1294. lpByte += iFieldSize;
  1295. // data 2
  1296. iFieldSize = sizeof(unsigned short);
  1297. ConvertField(lpByte,&lpStr,iFieldSize,TRUE);
  1298. lpByte += iFieldSize;
  1299. // data 3
  1300. iFieldSize = sizeof(unsigned short);
  1301. ConvertField(lpByte,&lpStr,iFieldSize,TRUE);
  1302. lpByte += iFieldSize;
  1303. // data 4
  1304. iFieldSize = 8*sizeof(unsigned char);
  1305. ConvertField(lpByte,&lpStr,iFieldSize,FALSE);
  1306. lpByte += iFieldSize;
  1307. // make sure we ended in the right place
  1308. if ('}' != *lpStr)
  1309. {
  1310. memset(pGuid,0,sizeof(GUID));
  1311. return E_FAIL;
  1312. }
  1313. return S_OK;
  1314. }// GUIDFromString
  1315. // following are routines for calling sens service directly to write HKLM data
  1316. // for us on a locked down machine
  1317. #define _SENSCALLS
  1318. #define _SENSINTERNAL
  1319. #ifdef _SENSCALLS
  1320. #include "notify.h"
  1321. // may or may not need depending on if in sensapip.h
  1322. DWORD SyncMgrExecCmd(DWORD nCmdID, DWORD nCmdOpt);
  1323. typedef enum SYNCMGRCMDEXECID
  1324. {
  1325. SYNCMGRCMDEXECID_UPDATERUNKEY = 1,
  1326. SYNCMGRCMDEXECID_RESETREGSECURITY = 2,
  1327. } SYNCMGRCMDEXECID;
  1328. #ifdef _SENSINTERNAL
  1329. // functions for if want to call sens internal without
  1330. // dependency on sensapip.lib
  1331. // these defines are from Sens common.h
  1332. #define SENS_PROTSEQ TEXT("ncalrpc")
  1333. #define SENS_ENDPOINT TEXT("senssvc")
  1334. RPC_STATUS GetSensNotifyBindHandle(RPC_BINDING_HANDLE *phSensNotify)
  1335. {
  1336. RPC_STATUS status = RPC_S_OK;
  1337. WCHAR * BindingString = NULL;
  1338. status = RpcStringBindingCompose(
  1339. NULL, // NULL ObjUuid
  1340. SENS_PROTSEQ,
  1341. NULL, // Local machine
  1342. SENS_ENDPOINT,
  1343. NULL, // No Options
  1344. &BindingString
  1345. );
  1346. if (BindingString != NULL)
  1347. {
  1348. *phSensNotify = NULL;
  1349. status = RpcBindingFromStringBinding(BindingString,phSensNotify);
  1350. if (status == RPC_S_OK)
  1351. {
  1352. RPC_SECURITY_QOS RpcSecQos;
  1353. RpcSecQos.Version= RPC_C_SECURITY_QOS_VERSION_1;
  1354. RpcSecQos.ImpersonationType= RPC_C_IMP_LEVEL_IMPERSONATE;
  1355. RpcSecQos.IdentityTracking= RPC_C_QOS_IDENTITY_DYNAMIC;
  1356. RpcSecQos.Capabilities= RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH;
  1357. status= RpcBindingSetAuthInfoEx(*phSensNotify,
  1358. L"NT Authority\\System",
  1359. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  1360. RPC_C_AUTHN_WINNT,
  1361. NULL,
  1362. RPC_C_AUTHZ_NONE,
  1363. (RPC_SECURITY_QOS *)&RpcSecQos);
  1364. if (RPC_S_OK != status)
  1365. {
  1366. RpcBindingFree(phSensNotify);
  1367. *phSensNotify = NULL;
  1368. }
  1369. }
  1370. RpcStringFree(&BindingString);
  1371. }
  1372. return (status);
  1373. }
  1374. RPC_STATUS SyncMgrExecCmdInternal(DWORD nCmdID, DWORD nCmdOpt)
  1375. {
  1376. RPC_STATUS status;
  1377. RPC_BINDING_HANDLE hSensNotify;
  1378. status = GetSensNotifyBindHandle(&hSensNotify);
  1379. if (RPC_S_OK != status)
  1380. {
  1381. return status;
  1382. }
  1383. status = RPC_SyncMgrExecCmd(hSensNotify,nCmdID,nCmdOpt);
  1384. RpcBindingFree(&hSensNotify);
  1385. return status;
  1386. }
  1387. #endif // _SENSINTERNAL
  1388. //+--------------------------------------------------------------------------
  1389. //
  1390. // Function: SyncMgrExecCmdp
  1391. //
  1392. // Synopsis: helper function that actually calls into sensapip.lib
  1393. //
  1394. //
  1395. // Arguments:
  1396. //
  1397. // Modifies:
  1398. //
  1399. // History: 03-11-99 rogerg created
  1400. //
  1401. //---------------------------------------------------------------------------
  1402. BOOL SyncMgrExecCmdp(DWORD nCmdID, DWORD nCmdOpt)
  1403. {
  1404. RPC_STATUS RpcStatus;
  1405. HRESULT hr;
  1406. BOOL fReturn = FALSE;
  1407. __try
  1408. {
  1409. #ifdef _SENSINTERNAL
  1410. RpcStatus = SyncMgrExecCmdInternal(nCmdID,nCmdOpt);
  1411. #else
  1412. RpcStatus = SyncMgrExecCmd(nCmdID,nCmdOpt);
  1413. #endif // _SENSINTERNAL
  1414. fReturn = (RPC_S_OK == RpcStatus ) ? TRUE: FALSE;
  1415. }
  1416. __except(QueryHandleException())
  1417. {
  1418. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  1419. AssertSz(0,"Exception Calling SensApip_SyncMgrExecCmd");
  1420. }
  1421. return fReturn;
  1422. }
  1423. #endif // _SENSCALLS
  1424. //+--------------------------------------------------------------------------
  1425. //
  1426. // Function: SyncMgrExecCmd_UpdateRunKey
  1427. //
  1428. // Synopsis: Calls SENS Service to write or remove the run Key
  1429. //
  1430. //
  1431. // Arguments:
  1432. //
  1433. // Modifies:
  1434. //
  1435. // History: 03-11-99 rogerg created
  1436. //
  1437. //---------------------------------------------------------------------------
  1438. BOOL SyncMgrExecCmd_UpdateRunKey(BOOL fSet)
  1439. {
  1440. BOOL fReturn = FALSE;
  1441. CCriticalSection cCritSect(&g_CritSectCommonLib,GetCurrentThreadId());
  1442. // IF NOT NT 5.0 or higher just return
  1443. if ( (g_OSVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
  1444. || (g_OSVersionInfo.dwMajorVersion < 5))
  1445. {
  1446. return FALSE;
  1447. }
  1448. cCritSect.Enter(); // DoRpcSetup in Sensapip is not thread safe.
  1449. #ifdef _SENSCALLS
  1450. fReturn = SyncMgrExecCmdp(
  1451. SYNCMGRCMDEXECID_UPDATERUNKEY,fSet ? 1 : 0);
  1452. #endif // _SENSCALLS
  1453. cCritSect.Leave();
  1454. return fReturn;
  1455. }
  1456. //+--------------------------------------------------------------------------
  1457. //
  1458. // Function: SyncMgrExecCmd_ResetRegSecurity
  1459. //
  1460. // Synopsis: Calls SENS Service to reset the security on regkeys
  1461. // to everyone.
  1462. //
  1463. //
  1464. // Arguments:
  1465. //
  1466. // Modifies:
  1467. //
  1468. // History: 03-11-99 rogerg created
  1469. //
  1470. //---------------------------------------------------------------------------
  1471. BOOL SyncMgrExecCmd_ResetRegSecurity(void)
  1472. {
  1473. BOOL fReturn = FALSE;
  1474. CCriticalSection cCritSect(&g_CritSectCommonLib,GetCurrentThreadId());
  1475. // IF NOT NT 5.0 or higher just return
  1476. if ( (g_OSVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
  1477. || (g_OSVersionInfo.dwMajorVersion < 5))
  1478. {
  1479. return FALSE;
  1480. }
  1481. cCritSect.Enter(); // DoRpcSetup in Sensapip is not thread safe.
  1482. #ifdef _SENSCALLS
  1483. fReturn = SyncMgrExecCmdp(SYNCMGRCMDEXECID_RESETREGSECURITY,0);
  1484. #endif // _SENSCALLS
  1485. cCritSect.Leave();
  1486. return fReturn;
  1487. }