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.

1291 lines
33 KiB

  1. /************************************************************************
  2. Copyright (c) Microsoft Corporation 1997-1999
  3. All rights reserved
  4. ***************************************************************************/
  5. //
  6. // UTILS.CPP - Common non-class specific utility calls.
  7. //
  8. #include "pch.h"
  9. #include <dsgetdc.h>
  10. #include <lm.h>
  11. #include "cenumsif.h"
  12. #include "utils.h"
  13. #include <dsadmin.h>
  14. DEFINE_MODULE("IMADMUI")
  15. #define SMALL_BUFFER_SIZE 256
  16. #define OSVERSION_SIZE 30
  17. #define IMAGETYPE_SIZE 30
  18. #define FILTER_GUID_QUERY L"(&(objectClass=computer)(netbootGUID=%ws))"
  19. WCHAR g_wszLDAPPrefix[] = L"LDAP://";
  20. const LONG SIZEOF_g_wszLDAPPrefix = sizeof(g_wszLDAPPrefix);
  21. //
  22. // AddPagesEx()
  23. //
  24. // Creates and adds a property page.
  25. //
  26. HRESULT
  27. AddPagesEx(
  28. ITab ** pTab,
  29. LPCREATEINST pfnCreateInstance,
  30. LPFNADDPROPSHEETPAGE lpfnAddPage,
  31. LPARAM lParam,
  32. LPUNKNOWN punk )
  33. {
  34. TraceFunc( "AddPagesEx( ... )\n" );
  35. HRESULT hr = S_OK;
  36. ITab * lpv;
  37. if ( pTab == NULL )
  38. {
  39. pTab = &lpv;
  40. }
  41. *pTab = (LPTAB) pfnCreateInstance( );
  42. if ( !*pTab )
  43. {
  44. hr = E_OUTOFMEMORY;
  45. goto Error;
  46. }
  47. hr = THR( (*pTab)->AddPages( lpfnAddPage, lParam, punk ) );
  48. if (FAILED(hr)) {
  49. goto Error;
  50. }
  51. Cleanup:
  52. RETURN(hr);
  53. Error:
  54. if ( *pTab )
  55. {
  56. delete *pTab;
  57. *pTab = NULL;
  58. }
  59. goto Cleanup;
  60. }
  61. //
  62. // CheckClipboardFormats( )
  63. //
  64. HRESULT
  65. CheckClipboardFormats( )
  66. {
  67. TraceFunc( "CheckClipboardFormats( )\n" );
  68. HRESULT hr = S_OK;
  69. if ( !g_cfDsObjectNames )
  70. {
  71. g_cfDsObjectNames = RegisterClipboardFormat( CFSTR_DSOBJECTNAMES );
  72. if ( !g_cfDsObjectNames )
  73. {
  74. hr = E_FAIL;
  75. }
  76. }
  77. if ( !g_cfDsDisplaySpecOptions && hr == S_OK )
  78. {
  79. g_cfDsDisplaySpecOptions = RegisterClipboardFormat( CFSTR_DS_DISPLAY_SPEC_OPTIONS );
  80. if ( !g_cfDsDisplaySpecOptions )
  81. {
  82. hr = E_FAIL;
  83. }
  84. }
  85. if ( !g_cfDsPropetyPageInfo && hr == S_OK )
  86. {
  87. g_cfDsPropetyPageInfo = RegisterClipboardFormat( CFSTR_DSPROPERTYPAGEINFO );
  88. if ( !g_cfDsObjectNames )
  89. {
  90. hr = E_FAIL;
  91. }
  92. }
  93. if ( !g_cfMMCGetNodeType && hr == S_OK )
  94. {
  95. g_cfMMCGetNodeType = RegisterClipboardFormat( CCF_NODETYPE );
  96. if ( !g_cfMMCGetNodeType )
  97. {
  98. hr = E_FAIL;
  99. }
  100. }
  101. RETURN(hr);
  102. }
  103. //
  104. // DNtoFQDN( )
  105. //
  106. // Changes a MAO DN to and FQDN.
  107. //
  108. // Input: pszDN - string e.g cn=HP,cn=computers,dc=GPEASE,dc=DOM
  109. //
  110. // Output: *pszFQDN - LocalAlloc'ed string with the generated FQDN
  111. //
  112. HRESULT
  113. DNtoFQDN(
  114. IN LPWSTR pszDN,
  115. OUT LPWSTR * pszFQDN )
  116. {
  117. TraceFunc( "DNtoFQDN( " );
  118. TraceMsg( TF_FUNC, "pszDN = '%s', *pszFQDN = 0x%08x )\n", pszDN, (pszFQDN ? *pszFQDN : NULL) );
  119. HRESULT hr = S_OK;
  120. LPWSTR pszNext;
  121. LPWSTR psz;
  122. if (0 != StrCmpNI( pszDN, L"cn=", 3 ) ||
  123. NULL == StrStrI( pszDN, L"dc=" )) {
  124. Assert( pszDN ); // this shouldn't happen
  125. hr = THR(E_INVALIDARG);
  126. goto Error;
  127. }
  128. // skip the "cn=" and duplicate
  129. *pszFQDN = (LPWSTR) TraceStrDup( &pszDN[3] );
  130. if ( !*pszFQDN )
  131. {
  132. hr = THR(E_OUTOFMEMORY);
  133. goto Error;
  134. }
  135. pszNext = *pszFQDN;
  136. while ( pszNext && *pszNext )
  137. {
  138. psz = StrChr( pszNext, L',' );
  139. if ( !psz ) {
  140. break;
  141. }
  142. *psz = L'.';
  143. pszNext = psz;
  144. pszNext++;
  145. psz = StrStrI( pszNext, L"dc=" );
  146. Assert( psz ); // this shouldn't happen
  147. if (!psz) {
  148. break;
  149. }
  150. psz += 3;
  151. StrCpy( pszNext, psz );
  152. }
  153. Error:
  154. HRETURN(hr);
  155. }
  156. HRESULT
  157. DNtoFQDNEx(
  158. LPWSTR pszDN,
  159. LPWSTR * pszFQDN )
  160. /*++
  161. Routine Description:
  162. Given a DN for the RIS SCP, figure out the FQDN of the
  163. RIS server. We do this by querying the DN for the
  164. "dNSHostName" attribute. The caller can get the DN for the object
  165. by reading the netbootserver attribute from the SCP.
  166. Arguments:
  167. pszDN - The server DN.
  168. pszFQDN - receives the FQDN of the server. Must be freed via
  169. TraceFree();
  170. Return Value:
  171. HRESULT indicating outcome.
  172. --*/
  173. {
  174. PLDAP LdapHandle = NULL;
  175. PWCHAR * Base;
  176. DWORD LdapError;
  177. DWORD entryCount;
  178. HRESULT hresult = S_OK;
  179. PLDAPMessage LdapMessage;
  180. PWCHAR * DnsName;
  181. PLDAPMessage CurrentEntry;
  182. WCHAR Filter[128];
  183. // Paramters we want from the Computer Object
  184. PWCHAR ComputerAttrs[2];
  185. //
  186. // all we care about is the dNSHostName attribute.
  187. //
  188. ComputerAttrs[0] = &L"dNSHostName";
  189. ComputerAttrs[1] = NULL;
  190. //
  191. // just computer objects
  192. //
  193. wsprintf( Filter, L"(objectClass=computer)" );
  194. //
  195. // initialize a valid ldap handle
  196. //
  197. LdapHandle = ldap_init( NULL, LDAP_PORT);
  198. if (!LdapHandle ||
  199. (LDAP_SUCCESS != ldap_connect(LdapHandle,0)) ||
  200. (LDAP_SUCCESS != ldap_bind_s(LdapHandle, NULL, NULL, LDAP_AUTH_NEGOTIATE))) {
  201. goto e0;
  202. }
  203. //
  204. // search from the passed in DN.
  205. //
  206. LdapError = ldap_search_s(LdapHandle,
  207. pszDN,
  208. LDAP_SCOPE_BASE,
  209. Filter,
  210. ComputerAttrs,
  211. FALSE,
  212. &LdapMessage);
  213. if ( LdapError != LDAP_SUCCESS ) {
  214. hresult=E_FAIL;
  215. goto e1;
  216. }
  217. // Did we get a Computer Object?
  218. entryCount = ldap_count_entries( LdapHandle, LdapMessage );
  219. if ( entryCount == 0 ) {
  220. hresult=E_FAIL;
  221. goto e1;
  222. }
  223. //
  224. // we should really only get one hit, but... if we get more than more
  225. // entry back, we will use only the first one.
  226. //
  227. CurrentEntry = ldap_first_entry( LdapHandle, LdapMessage );
  228. //
  229. // retreive the value.
  230. //
  231. DnsName = ldap_get_values( LdapHandle, CurrentEntry, L"dNSHostName");
  232. if ( DnsName ) {
  233. *pszFQDN = (LPWSTR) TraceStrDup( (LPWSTR)*DnsName );
  234. if (!*pszFQDN) {
  235. hresult=E_FAIL;
  236. }
  237. ldap_value_free( DnsName );
  238. }
  239. //
  240. // cleanup and return
  241. //
  242. e1:
  243. ldap_msgfree( LdapMessage );
  244. e0:
  245. if (LdapHandle) {
  246. ldap_unbind_s(LdapHandle);
  247. }
  248. return(hresult);
  249. }
  250. HRESULT
  251. GetDomainDN(
  252. LPWSTR pszDN,
  253. LPWSTR * pszDomainDn)
  254. /*++
  255. Routine Description:
  256. Given a server name, we retrive the DN of the domain that machine
  257. is in. This is done just by moving the the dc portion of the DN.
  258. Arguments:
  259. pszDN - the source DN
  260. pszDomainDn - receives the domain DN. Must be freed via TraceFree().
  261. Return Value:
  262. HRESULT indicating outcome.
  263. --*/
  264. {
  265. TraceFunc( "GetDomainDN( " );
  266. TraceMsg( TF_FUNC, "pszDN = '%s', *pszFQDN = 0x%08x )\n", pszDN, (pszDomainDn ? *pszDomainDn : NULL) );
  267. HRESULT hr = S_OK;
  268. LPWSTR pszNext = StrStrI(pszDN, L"dc=");
  269. if (pszNext) {
  270. *pszDomainDn = (LPWSTR) TraceStrDup( pszNext );
  271. if (!*pszDomainDn) {
  272. hr = THR(E_OUTOFMEMORY);
  273. }
  274. } else {
  275. hr = THR(E_INVALIDARG);
  276. }
  277. HRETURN(hr);
  278. }
  279. //
  280. // PopulateListView( )
  281. //
  282. HRESULT
  283. PopulateListView(
  284. HWND hwndList,
  285. IEnumIMSIFs * penum )
  286. {
  287. TraceFunc( "PopulateListView( ... )\n" );
  288. HRESULT hr = S_OK;
  289. INT iCount;
  290. LV_ITEM lvI;
  291. if ( !penum )
  292. HRETURN(E_POINTER);
  293. lvI.mask = LVIF_TEXT | LVIF_PARAM;
  294. lvI.iSubItem = 0;
  295. lvI.cchTextMax = REMOTE_INSTALL_MAX_DESCRIPTION_CHAR_COUNT;
  296. ListView_DeleteAllItems( hwndList );
  297. iCount = 0;
  298. while ( hr == S_OK )
  299. {
  300. WIN32_FILE_ATTRIBUTE_DATA fda;
  301. WCHAR szBuf[ MAX_PATH ];
  302. LPSIFINFO pSIF;
  303. LPWSTR pszFilePath;
  304. LPWSTR pszBegin;
  305. INT i; // general purpose
  306. hr = penum->Next( 1, &pszFilePath, NULL );
  307. if ( hr != S_OK )
  308. {
  309. if ( pszFilePath ) {
  310. TraceFree( pszFilePath );
  311. pszFilePath = NULL;
  312. }
  313. break; // abort
  314. }
  315. // Create private storage structure
  316. pSIF = (LPSIFINFO) TraceAlloc( LPTR, sizeof(SIFINFO) );
  317. if ( !pSIF )
  318. {
  319. if ( pszFilePath ) {
  320. TraceFree( pszFilePath );
  321. pszFilePath = NULL;
  322. }
  323. continue; // oh well, try again next OS
  324. }
  325. // Save this
  326. pSIF->pszFilePath = pszFilePath;
  327. // Get the description
  328. pSIF->pszDescription = (LPWSTR) TraceAllocString( LMEM_FIXED, REMOTE_INSTALL_MAX_DESCRIPTION_CHAR_COUNT );
  329. if ( !pSIF->pszDescription ) {
  330. goto Cleanup;
  331. }
  332. GetPrivateProfileString( OSCHOOSER_SIF_SECTION,
  333. OSCHOOSER_DESCRIPTION_ENTRY,
  334. L"??",
  335. pSIF->pszDescription,
  336. REMOTE_INSTALL_MAX_DESCRIPTION_CHAR_COUNT, // doesn't need -1
  337. pszFilePath );
  338. // Grab any help text
  339. pSIF->pszHelpText = (LPWSTR) TraceAllocString( LMEM_FIXED, REMOTE_INSTALL_MAX_HELPTEXT_CHAR_COUNT );
  340. if ( !pSIF->pszHelpText ) {
  341. goto Cleanup;
  342. }
  343. GetPrivateProfileString( OSCHOOSER_SIF_SECTION,
  344. OSCHOOSER_HELPTEXT_ENTRY,
  345. L"",
  346. pSIF->pszHelpText,
  347. REMOTE_INSTALL_MAX_HELPTEXT_CHAR_COUNT, // doesn't need -1
  348. pszFilePath );
  349. // Grab the OS Version
  350. pSIF->pszVersion= (LPWSTR) TraceAllocString( LMEM_FIXED, OSVERSION_SIZE );
  351. if ( !pSIF->pszVersion ) {
  352. goto Cleanup;
  353. }
  354. GetPrivateProfileString( OSCHOOSER_SIF_SECTION,
  355. OSCHOOSER_VERSION_ENTRY,
  356. L"",
  357. pSIF->pszVersion,
  358. OSVERSION_SIZE,
  359. pszFilePath );
  360. // Grab the last modified Time/Date stamp
  361. if ( GetFileAttributesEx( pszFilePath, GetFileExInfoStandard, &fda ) )
  362. {
  363. pSIF->ftLastWrite = fda.ftLastWriteTime;
  364. } else {
  365. ZeroMemory( &pSIF->ftLastWrite, sizeof(pSIF->ftLastWrite) );
  366. }
  367. // Figure out the language and architecture.
  368. // These are retrieved from the FilePath.
  369. // \\machine\REMINST\Setup\English\Images\nt50.wks\i386\templates\rbstndrd.sif
  370. pszBegin = pSIF->pszFilePath;
  371. for( i = 0; i < 5; i ++ )
  372. {
  373. pszBegin = StrChr( pszBegin, L'\\' );
  374. if ( !pszBegin ) {
  375. break;
  376. }
  377. pszBegin++;
  378. }
  379. if ( pszBegin )
  380. {
  381. LPWSTR pszEnd = StrChr( pszBegin, L'\\' );
  382. if ( pszEnd ) {
  383. *pszEnd = L'\0'; // terminate
  384. //
  385. // it's not fatal if we don't find this, but if we fail to
  386. // allocate memory for it, it is fatal
  387. //
  388. pSIF->pszLanguage = (LPWSTR) TraceStrDup( pszBegin );
  389. *pszEnd = L'\\'; // restore
  390. if ( !pSIF->pszLanguage ) {
  391. goto Cleanup;
  392. }
  393. }
  394. }
  395. Assert( pSIF->pszLanguage );
  396. for( ; i < 7; i ++ )
  397. {
  398. pszBegin = StrChr( pszBegin, L'\\' );
  399. if ( !pszBegin ) {
  400. break;
  401. }
  402. pszBegin++;
  403. }
  404. if ( pszBegin )
  405. {
  406. LPWSTR pszEnd = StrChr( pszBegin, L'\\' );
  407. if ( pszEnd )
  408. {
  409. *pszEnd = L'\0';
  410. //
  411. // it's not fatal if we don't find this, but if we fail to
  412. // allocate memory for it, it is fatal
  413. //
  414. pSIF->pszDirectory = (LPWSTR) TraceStrDup( pszBegin );
  415. *pszEnd = L'\\';
  416. if ( !pSIF->pszDirectory ) {
  417. goto Cleanup;
  418. }
  419. }
  420. }
  421. Assert( pSIF->pszDirectory );
  422. for( ; i < 8; i ++ )
  423. {
  424. pszBegin = StrChr( pszBegin, L'\\' );
  425. if ( !pszBegin ) {
  426. break;
  427. }
  428. pszBegin++;
  429. }
  430. if ( pszBegin )
  431. {
  432. LPWSTR pszEnd = StrChr( pszBegin, L'\\' );
  433. if ( pszEnd )
  434. {
  435. *pszEnd = L'\0';
  436. //
  437. // it's not fatal if we don't find this, but if we fail to
  438. // allocate memory for it, it is fatal
  439. //
  440. pSIF->pszArchitecture = (LPWSTR) TraceStrDup( pszBegin );
  441. *pszEnd = L'\\';
  442. if ( !pSIF->pszArchitecture ) {
  443. goto Cleanup;
  444. }
  445. }
  446. }
  447. // Figure out what kind of image it is
  448. pSIF->pszImageType = (LPWSTR) TraceAllocString( LMEM_FIXED, IMAGETYPE_SIZE );
  449. if ( !pSIF->pszImageType ) {
  450. goto Cleanup;
  451. }
  452. GetPrivateProfileString( OSCHOOSER_SIF_SECTION,
  453. OSCHOOSER_IMAGETYPE_ENTRY,
  454. L"??",
  455. pSIF->pszImageType,
  456. IMAGETYPE_SIZE,
  457. pszFilePath );
  458. // Figure out what image it uses
  459. GetPrivateProfileString( OSCHOOSER_SIF_SECTION,
  460. OSCHOOSER_LAUNCHFILE_ENTRY,
  461. L"??",
  462. szBuf,
  463. ARRAYSIZE( szBuf ),
  464. pszFilePath );
  465. pszBegin = StrRChr( szBuf, &szBuf[wcslen(szBuf)], L'\\' );
  466. if ( pszBegin )
  467. {
  468. pszBegin++;
  469. pSIF->pszImageFile = (LPWSTR) TraceStrDup( pszBegin );
  470. if (!pSIF->pszImageFile) {
  471. goto Cleanup;
  472. }
  473. }
  474. // Add the item to list view
  475. lvI.lParam = (LPARAM) pSIF;
  476. lvI.iItem = iCount;
  477. lvI.pszText = pSIF->pszDescription;
  478. iCount = ListView_InsertItem( hwndList, &lvI );
  479. Assert( iCount != -1 );
  480. if ( iCount == -1 )
  481. goto Cleanup;
  482. if ( pSIF->pszArchitecture )
  483. {
  484. ListView_SetItemText( hwndList, iCount, 1, pSIF->pszArchitecture );
  485. }
  486. if ( pSIF->pszLanguage )
  487. {
  488. ListView_SetItemText( hwndList, iCount, 2, pSIF->pszLanguage );
  489. }
  490. if ( pSIF->pszVersion )
  491. {
  492. ListView_SetItemText( hwndList, iCount, 3, pSIF->pszVersion );
  493. }
  494. continue; // next!
  495. Cleanup:
  496. if ( pSIF )
  497. {
  498. if (pSIF->pszDescription != NULL) {
  499. TraceFree( pSIF->pszDescription );
  500. pSIF->pszDescription = NULL;
  501. }
  502. TraceFree( pSIF->pszFilePath );
  503. pSIF->pszFilePath = NULL;
  504. if (pSIF->pszHelpText != NULL) {
  505. TraceFree( pSIF->pszHelpText );
  506. pSIF->pszHelpText = NULL;
  507. }
  508. if (pSIF->pszImageType != NULL) {
  509. TraceFree( pSIF->pszImageType );
  510. pSIF->pszImageType = NULL;
  511. }
  512. TraceFree( pSIF->pszLanguage );
  513. pSIF->pszLanguage = NULL;
  514. if (pSIF->pszVersion != NULL) {
  515. TraceFree( pSIF->pszVersion );
  516. pSIF->pszVersion = NULL;
  517. }
  518. if (pSIF->pszImageFile) {
  519. TraceFree( pSIF->pszImageFile );
  520. pSIF->pszImageFile = NULL;
  521. }
  522. TraceFree( pSIF );
  523. pSIF = NULL;
  524. }
  525. }
  526. HRETURN(hr);
  527. }
  528. //
  529. // LDAPPrefix( )
  530. //
  531. // Returns:
  532. // E_OUTOFMEMORY - if out of memory
  533. // S_OK - added LDAP:// to the pszObjDN
  534. // S_FALSE - didn't have to add anything and copied the pszObjDN
  535. // into ppszObjLDAPPath
  536. HRESULT
  537. LDAPPrefix(
  538. PWSTR pszObjDN,
  539. PWSTR * ppszObjLDAPPath)
  540. {
  541. TraceFunc( "LDAPPrefix( ... )\n" );
  542. HRESULT hr;
  543. const ULONG cchPrefix = ARRAYSIZE(g_wszLDAPPrefix) - 1;
  544. ULONG cch = wcslen(pszObjDN);
  545. if (wcsncmp(pszObjDN, g_wszLDAPPrefix, cchPrefix))
  546. {
  547. LPWSTR psz;
  548. psz = (LPWSTR) TraceAllocString( LPTR, cch + cchPrefix + 1 );
  549. if ( !psz ) {
  550. hr = E_OUTOFMEMORY;
  551. goto Error;
  552. }
  553. wcscpy(psz, g_wszLDAPPrefix);
  554. wcscat(psz, pszObjDN);
  555. *ppszObjLDAPPath = psz;
  556. hr = S_OK;
  557. }
  558. else
  559. {
  560. *ppszObjLDAPPath = pszObjDN;
  561. hr = S_FALSE;
  562. }
  563. Error:
  564. HRETURN(hr);
  565. }
  566. //
  567. // _FixObjectPath( )
  568. //
  569. HRESULT
  570. FixObjectPath(
  571. LPWSTR Object,
  572. LPWSTR pszOldObjectPath,
  573. LPWSTR *ppszNewObjectPath )
  574. {
  575. TraceFunc( "FixObjectPath()\n" );
  576. HRESULT hr;
  577. LPWSTR psz = NULL;
  578. *ppszNewObjectPath = NULL;
  579. // Try to parse the string to connect to the same server as the DSADMIN
  580. if ( Object && StrCmpNI( Object, L"LDAP://", 7 ) == 0 )
  581. {
  582. psz = Object + 7;
  583. }
  584. else if ( Object && StrCmpNI( Object, L"GC://", 5 ) == 0 )
  585. {
  586. psz = Object + 5;
  587. }
  588. if ( psz )
  589. {
  590. psz = StrChr( psz, L'/' );
  591. psz++;
  592. INT_PTR uLen = psz - Object;
  593. // get a chunk of memory, pre-zero'ed
  594. psz = TraceAllocString( LPTR, (size_t) uLen + wcslen( pszOldObjectPath ) + 1 );
  595. if ( !psz ) {
  596. hr = E_OUTOFMEMORY;
  597. goto Exit;
  598. }
  599. MoveMemory( psz, Object, uLen * sizeof(WCHAR) );
  600. wcscat( psz, pszOldObjectPath);
  601. *ppszNewObjectPath = psz;
  602. }
  603. else
  604. { // find another server
  605. hr = THR( LDAPPrefix( pszOldObjectPath, ppszNewObjectPath ) );
  606. }
  607. Assert( ppszNewObjectPath || hr != S_OK );
  608. Exit:
  609. HRETURN(hr);
  610. }
  611. //
  612. // Create a message box from resource strings.
  613. //
  614. int
  615. MessageBoxFromStrings(
  616. HWND hParent,
  617. UINT idsCaption,
  618. UINT idsText,
  619. UINT uType )
  620. {
  621. WCHAR szText[ SMALL_BUFFER_SIZE * 2 ];
  622. WCHAR szCaption[ SMALL_BUFFER_SIZE ];
  623. DWORD dw;
  624. szCaption[0] = L'\0';
  625. szText[0] = L'\0';
  626. dw = LoadString( g_hInstance, idsCaption, szCaption, ARRAYSIZE(szCaption) );
  627. Assert( dw );
  628. dw = LoadString( g_hInstance, idsText, szText, ARRAYSIZE(szText));
  629. Assert( dw );
  630. return MessageBox( hParent, szText, szCaption, uType );
  631. }
  632. //
  633. // MessageBoxFromError( )
  634. //
  635. // Creates a error message box
  636. //
  637. void
  638. MessageBoxFromError(
  639. HWND hParent,
  640. UINT idsCaption,
  641. DWORD dwErr )
  642. {
  643. WCHAR szTitle[ SMALL_BUFFER_SIZE ];
  644. LPWSTR lpMsgBuf = NULL;
  645. DWORD dw;
  646. if ( dwErr == ERROR_SUCCESS ) {
  647. AssertMsg( dwErr, "Why was MessageBoxFromError() called when the dwErr == ERROR_SUCCES?" );
  648. return;
  649. }
  650. if ( !idsCaption ) {
  651. idsCaption = IDS_ERROR;
  652. }
  653. szTitle[0] = L'\0';
  654. dw = LoadString( g_hInstance, idsCaption, szTitle, ARRAYSIZE(szTitle) );
  655. Assert( dw );
  656. FormatMessage(
  657. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  658. NULL,
  659. dwErr,
  660. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  661. (LPWSTR) &lpMsgBuf,
  662. 0,
  663. NULL
  664. );
  665. if (lpMsgBuf == NULL) {
  666. AssertMsg( (lpMsgBuf != NULL), "MessageBoxFromError() called with unknown message." );
  667. return;
  668. }
  669. MessageBox( hParent, lpMsgBuf, szTitle, MB_OK | MB_ICONERROR );
  670. LocalFree( lpMsgBuf );
  671. }
  672. //
  673. // MessageBoxFromError( )
  674. //
  675. // Creates a error message box
  676. //
  677. void
  678. MessageBoxFromHResult(
  679. HWND hParent,
  680. UINT idsCaption,
  681. HRESULT hr )
  682. {
  683. WCHAR szTitle[ SMALL_BUFFER_SIZE ];
  684. LPWSTR lpMsgBuf = NULL;
  685. DWORD dw;
  686. if ( SUCCEEDED( hr ) ) {
  687. AssertMsg( SUCCEEDED( hr ), "Why was MessageBoxFromHResult() called when the HR succeeded?" );
  688. return;
  689. }
  690. if ( !idsCaption ) {
  691. idsCaption = IDS_ERROR;
  692. }
  693. szTitle[0] = L'\0';
  694. dw = LoadString( g_hInstance, idsCaption, szTitle, ARRAYSIZE(szTitle) );
  695. Assert( dw );
  696. FormatMessage(
  697. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  698. NULL,
  699. hr,
  700. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  701. (LPWSTR) &lpMsgBuf,
  702. 0,
  703. NULL
  704. );
  705. if (lpMsgBuf == NULL) {
  706. AssertMsg( (lpMsgBuf != NULL), "MessageBoxFromHResult() called with unknown message." );
  707. return;
  708. }
  709. MessageBox( hParent, lpMsgBuf, szTitle, MB_OK | MB_ICONERROR );
  710. LocalFree( lpMsgBuf );
  711. }
  712. //
  713. // VerifySIFText( )
  714. //
  715. BOOL
  716. VerifySIFText(
  717. LPWSTR pszText )
  718. {
  719. TraceFunc( "VerifySIFText()\n" );
  720. BOOL fReturn = FALSE;
  721. while ( *pszText >= 32 && *pszText < 128 ) {
  722. pszText++;
  723. }
  724. if ( *pszText == L'\0' )
  725. {
  726. fReturn = TRUE;
  727. }
  728. RETURN(fReturn);
  729. }
  730. //bugbug is this compiled or not?
  731. #ifndef ADSI_DNS_SEARCH
  732. //
  733. // Ldap_InitializeConnection( )
  734. //
  735. DWORD
  736. Ldap_InitializeConnection(
  737. PLDAP * LdapHandle )
  738. {
  739. TraceFunc( "Ldap_InitializeConnection( ... )\n" );
  740. PLDAPMessage OperationalAttributeLdapMessage;
  741. PLDAPMessage CurrentEntry;
  742. DWORD LdapError = LDAP_SUCCESS;
  743. if ( !( *LdapHandle ) ) {
  744. ULONG temp = DS_DIRECTORY_SERVICE_REQUIRED |
  745. DS_IP_REQUIRED |
  746. DS_GC_SERVER_REQUIRED;
  747. *LdapHandle = ldap_init( NULL, LDAP_GC_PORT);
  748. if ( !*LdapHandle )
  749. {
  750. LdapError = LDAP_UNAVAILABLE;
  751. goto e0;
  752. }
  753. ldap_set_option( *LdapHandle, LDAP_OPT_GETDSNAME_FLAGS, &temp );
  754. temp = LDAP_VERSION3;
  755. ldap_set_option( *LdapHandle, LDAP_OPT_VERSION, &temp );
  756. LdapError = ldap_connect( *LdapHandle, 0 );
  757. if ( LdapError != LDAP_SUCCESS )
  758. goto e1;
  759. LdapError = ldap_bind_s( *LdapHandle, NULL, NULL, LDAP_AUTH_SSPI );
  760. if ( LdapError != LDAP_SUCCESS )
  761. goto e1;
  762. }
  763. e0:
  764. RETURN( LdapError );
  765. e1:
  766. ldap_unbind( *LdapHandle );
  767. *LdapHandle = NULL;
  768. goto e0;
  769. }
  770. #endif // ADSI_DNS_SEARCH
  771. //
  772. // ValidateGuid( )
  773. //
  774. // Returns: S_OK if a complete, valid GUID is in pszGuid.
  775. // S_FALSE if an valid but incomplete GUID is in pszGuid. "Valid but
  776. // incomplete" is defined below.
  777. // E_FAIL if an invalid character is encountered while parsing.
  778. //
  779. // Valid characters are 0-9, A-F, a-f and "{-}"s. All spaces are ignored.
  780. // The GUID must appear in one of the following forms:
  781. //
  782. // 1. 00112233445566778899aabbccddeeff
  783. // This corresponds to the actual in-memory storage order of a GUID.
  784. // For example, it is the order in which GUID bytes appear in a
  785. // network trace.
  786. //
  787. // 2. {33221100-5544-7766-8899-aabbccddeeff}
  788. // This corresponds to the "standard" way of printing GUIDs. Note
  789. // that the "pretty" GUID shown here is the same as the GUID shown
  790. // above.
  791. //
  792. // Note that the DEFINE_GUID macro (see sdk\inc\objbase.h) for the above
  793. // GUID would look like this:
  794. // DEFINE_GUID(name,0x33221100,0x5544,0x7766,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff)
  795. //
  796. // "Valid but incomplete" means that the input consists of an even number
  797. // of hex characters (no lone nibbles), and if the input is in "pretty"
  798. // format, the input must terminate at one of the dashes or after the
  799. // second-to-the-last dash.
  800. //
  801. // The following are valid but incomplete entries:
  802. // 001122
  803. // {33221100
  804. // {33221100-5544
  805. // {33221100-5544-7766-88
  806. //
  807. // The following are invalid incomplete entries:
  808. // 00112
  809. // {332211
  810. // {33221100-5544-77
  811. //
  812. //
  813. // In the xxxGuidCharacters arrays, values [0,31] indicate nibble positions within
  814. // the in-memory representation of the GUID. Value 32 indicates the end of the
  815. // GUID string. Values 33 and up indicate special characters (nul,'-','{','}') and
  816. // are used to index into an array containing those characters.
  817. //
  818. #define VG_DONE 32
  819. #define VG_NULL 33
  820. #define VG_DASH 34
  821. #define VG_LBRACK 35
  822. #define VG_RBRACK 36
  823. CHAR InMemoryFormatGuidCharacters[] = {
  824. 1, 0, 3, 2, 5, 4, 7, 6,
  825. 9, 8, 11, 10, 13, 12, 15, 14,
  826. 17, 16, 19, 18, 21, 20, 23, 22,
  827. 25, 24, 27, 26, 29, 28, 31, 30,
  828. VG_NULL, VG_DONE };
  829. CHAR PrettyFormatGuidCharacters[] = {
  830. VG_LBRACK, 7, 6, 5, 4, 3, 2, 1,
  831. 0, VG_DASH, 11, 10, 9, 8, VG_DASH, 15,
  832. 14, 13, 12, VG_DASH, 17, 16, 19, 18,
  833. VG_DASH, 21, 20, 23, 22, 25, 24, 27,
  834. 26, 29, 28, 31, 30, VG_RBRACK, VG_NULL, VG_DONE };
  835. WCHAR SpecialCharacters[] = {
  836. 0, // VG_NULL
  837. L'-', // VG_DASH
  838. L'{', // VG_LBRACK
  839. L'}', // VG_RBRACK
  840. };
  841. PWSTR ByteToHex = L"0123456789ABCDEF";
  842. HRESULT
  843. ValidateGuid(
  844. IN LPWSTR pszGuid,
  845. OUT LPGUID Guid OPTIONAL,
  846. OUT LPDWORD puGuidLength OPTIONAL )
  847. {
  848. TraceFunc( "ValidateGuid( " );
  849. TraceMsg( TF_FUNC, "pszGuid = '%s'\n", pszGuid );
  850. HRESULT hr;
  851. LPBYTE uGuid = (LPBYTE)Guid;
  852. PCHAR expectedCharacter;
  853. CHAR e;
  854. WCHAR g;
  855. BOOL parsingPrettyFormat;
  856. DWORD numberOfHexDigitsParsed;
  857. #ifdef DEBUG
  858. if ( uGuid != NULL ) {
  859. for ( e = 0; e < 16; e++ ) {
  860. uGuid[e] = 0;
  861. }
  862. }
  863. #endif
  864. if ( *pszGuid == L'{' ) {
  865. expectedCharacter = PrettyFormatGuidCharacters;
  866. parsingPrettyFormat = TRUE;
  867. } else {
  868. expectedCharacter = InMemoryFormatGuidCharacters;
  869. parsingPrettyFormat = FALSE;
  870. }
  871. numberOfHexDigitsParsed = 0;
  872. do {
  873. e = *expectedCharacter++;
  874. do {
  875. g = *pszGuid++;
  876. } while (iswspace(g));
  877. switch ( e ) {
  878. case VG_NULL:
  879. case VG_DASH:
  880. case VG_LBRACK:
  881. case VG_RBRACK:
  882. if ( g != SpecialCharacters[e - VG_NULL] ) {
  883. if ( g == 0 ) {
  884. // valid but incomplete
  885. hr = S_FALSE;
  886. } else {
  887. hr = E_FAIL;
  888. }
  889. goto done;
  890. }
  891. break;
  892. default:
  893. Assert( (e >= 0) && (e < VG_DONE) );
  894. g = towlower( g );
  895. if ( ((g >= L'0') && (g <= L'9')) ||
  896. ((g >= L'a') && (g <= L'f')) ) {
  897. if ( uGuid != NULL ) {
  898. BYTE n = (BYTE)((g > L'9') ? (g - L'a' + 10) : (g - '0'));
  899. if ( e & 1 ) {
  900. Assert( uGuid[e/2] == 0 );
  901. uGuid[e/2] = n << 4;
  902. } else {
  903. uGuid[e/2] += n;
  904. }
  905. }
  906. numberOfHexDigitsParsed++;
  907. } else {
  908. if ( (g == 0) &&
  909. (!parsingPrettyFormat ||
  910. (parsingPrettyFormat && (numberOfHexDigitsParsed >= 16))) ) {
  911. hr = S_FALSE;
  912. } else {
  913. hr = E_FAIL;
  914. }
  915. goto done;
  916. }
  917. break;
  918. }
  919. } while ( *expectedCharacter != VG_DONE );
  920. hr = S_OK;
  921. done:
  922. if ( puGuidLength != NULL ) {
  923. *puGuidLength = numberOfHexDigitsParsed / 2;
  924. }
  925. HRETURN(hr);
  926. }
  927. //
  928. // PrettyPrintGuid( )
  929. //
  930. LPWSTR
  931. PrettyPrintGuid(
  932. LPGUID pGuid )
  933. {
  934. TraceFunc( "PrettyPrintGuid( " );
  935. LPBYTE uGuid = (LPBYTE)pGuid;
  936. LPWSTR pszPrettyString = (LPWSTR) TraceAlloc( LMEM_FIXED, PRETTY_GUID_STRING_BUFFER_SIZE );
  937. if ( pszPrettyString )
  938. {
  939. PCHAR characterType = PrettyFormatGuidCharacters;
  940. LPWSTR pszDest = pszPrettyString;
  941. CHAR ct;
  942. BYTE n;
  943. do {
  944. ct = *characterType++;
  945. switch ( ct ) {
  946. case VG_NULL:
  947. case VG_DASH:
  948. case VG_LBRACK:
  949. case VG_RBRACK:
  950. *pszDest = SpecialCharacters[ct - VG_NULL];
  951. break;
  952. default:
  953. if ( ct & 1 ) {
  954. n = uGuid[ct/2] >> 4;
  955. } else {
  956. n = uGuid[ct/2] & 0xf;
  957. }
  958. *pszDest = ByteToHex[n];
  959. break;
  960. }
  961. pszDest++;
  962. } while ( *characterType != VG_DONE );
  963. }
  964. RETURN(pszPrettyString);
  965. }
  966. //
  967. // CheckForDuplicateGuid( )
  968. //
  969. // Returns: S_OK if no duplicates found
  970. // S_FALSE if a duplicate was found
  971. // E_FAIL if the query failed
  972. //
  973. HRESULT
  974. CheckForDuplicateGuid(
  975. LPGUID pGuid )
  976. {
  977. TraceFunc( "CheckForDuplicateGuid( " );
  978. HRESULT hr = S_OK;
  979. WCHAR szGuid[ MAX_INPUT_GUID_STRING * 2 ]; // room for escaped GUID
  980. WCHAR szFilter[ARRAYSIZE(szGuid)+ARRAYSIZE(FILTER_GUID_QUERY)];
  981. PLDAP LdapHandle = NULL;
  982. LPWSTR ComputerAttrs[2];
  983. DWORD LdapError;
  984. DWORD count;
  985. PLDAPMessage LdapMessage = NULL;
  986. LdapError = Ldap_InitializeConnection( &LdapHandle );
  987. Assert( LdapError == LDAP_SUCCESS );
  988. if ( LdapError != LDAP_SUCCESS )
  989. {
  990. hr = THR( HRESULT_FROM_WIN32( LdapMapErrorToWin32( LdapError ) ) );
  991. goto e0;
  992. }
  993. ZeroMemory( szGuid, sizeof(szGuid) );
  994. ldap_escape_filter_element( (PCHAR)pGuid, sizeof(GUID), szGuid, sizeof(szGuid) );
  995. wsprintf( szFilter, FILTER_GUID_QUERY, szGuid );
  996. DebugMsg( "Dup Guid Filter: %s\n", szFilter );
  997. ComputerAttrs[0] = DISTINGUISHEDNAME;
  998. ComputerAttrs[1] = NULL;
  999. LdapError = ldap_search_ext_s( LdapHandle,
  1000. NULL,
  1001. LDAP_SCOPE_SUBTREE,
  1002. szFilter,
  1003. ComputerAttrs,
  1004. FALSE,
  1005. NULL,
  1006. NULL,
  1007. NULL,
  1008. 0,
  1009. &LdapMessage);
  1010. Assert( LdapError == LDAP_SUCCESS );
  1011. if ( LdapError != LDAP_SUCCESS )
  1012. {
  1013. hr = THR( HRESULT_FROM_WIN32( LdapMapErrorToWin32( LdapError ) ) );
  1014. goto e1;
  1015. }
  1016. count = ldap_count_entries( LdapHandle, LdapMessage );
  1017. if ( count != 0 )
  1018. {
  1019. hr = S_FALSE;
  1020. }
  1021. else
  1022. {
  1023. hr = S_OK;
  1024. }
  1025. e1:
  1026. if (LdapMessage) {
  1027. ldap_msgfree( LdapMessage );
  1028. }
  1029. Assert( LdapHandle );
  1030. ldap_unbind( LdapHandle );
  1031. e0:
  1032. HRETURN(hr);
  1033. }
  1034. //
  1035. // AddWizardPage( )
  1036. //
  1037. // Adds a page to the wizard.
  1038. //
  1039. void
  1040. AddWizardPage(
  1041. LPPROPSHEETHEADER ppsh,
  1042. UINT id,
  1043. DLGPROC pfn,
  1044. UINT idTitle,
  1045. UINT idSubtitle,
  1046. LPARAM lParam )
  1047. {
  1048. PROPSHEETPAGE psp;
  1049. WCHAR szTitle[ SMALL_BUFFER_SIZE ];
  1050. WCHAR szSubTitle[ SMALL_BUFFER_SIZE ];
  1051. ZeroMemory( &psp, sizeof(psp) );
  1052. psp.dwSize = sizeof(psp);
  1053. psp.dwFlags = PSP_DEFAULT | PSP_USETITLE;
  1054. psp.pszTitle = MAKEINTRESOURCE( IDS_ADD_DOT_DOT_DOT );
  1055. psp.hInstance = ppsh->hInstance;
  1056. psp.pszTemplate = MAKEINTRESOURCE(id);
  1057. psp.pfnDlgProc = pfn;
  1058. psp.lParam = lParam;
  1059. psp.pszHeaderTitle = NULL;
  1060. if ( idTitle &&
  1061. LoadString( g_hInstance, idTitle, szTitle, ARRAYSIZE(szTitle))) {
  1062. psp.pszHeaderTitle = szTitle;
  1063. psp.dwFlags |= PSP_USEHEADERTITLE;
  1064. }
  1065. psp.pszHeaderSubTitle = NULL;
  1066. if ( idSubtitle &&
  1067. LoadString( g_hInstance, idSubtitle , szSubTitle, ARRAYSIZE(szSubTitle))) {
  1068. psp.pszHeaderSubTitle = szSubTitle;
  1069. psp.dwFlags |= PSP_USEHEADERSUBTITLE;
  1070. }
  1071. ppsh->phpage[ ppsh->nPages ] = CreatePropertySheetPage( &psp );
  1072. if ( ppsh->phpage[ ppsh->nPages ] ) {
  1073. ppsh->nPages++;
  1074. }
  1075. }