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.

1107 lines
28 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 (hr)
  49. goto Error;
  50. Cleanup:
  51. RETURN(hr);
  52. Error:
  53. if ( *pTab )
  54. {
  55. delete *pTab;
  56. *pTab = NULL;
  57. }
  58. goto Cleanup;
  59. }
  60. //
  61. // CheckClipboardFormats( )
  62. //
  63. HRESULT
  64. CheckClipboardFormats( )
  65. {
  66. TraceFunc( "CheckClipboardFormats( )\n" );
  67. HRESULT hr = S_OK;
  68. if ( !g_cfDsObjectNames && hr == S_OK )
  69. {
  70. g_cfDsObjectNames = RegisterClipboardFormat( CFSTR_DSOBJECTNAMES );
  71. if ( !g_cfDsObjectNames )
  72. {
  73. hr = E_FAIL;
  74. }
  75. }
  76. if ( !g_cfDsDisplaySpecOptions && hr == S_OK )
  77. {
  78. g_cfDsDisplaySpecOptions = RegisterClipboardFormat( CFSTR_DS_DISPLAY_SPEC_OPTIONS );
  79. if ( !g_cfDsDisplaySpecOptions )
  80. {
  81. hr = E_FAIL;
  82. }
  83. }
  84. if ( !g_cfDsPropetyPageInfo && hr == S_OK )
  85. {
  86. g_cfDsPropetyPageInfo = RegisterClipboardFormat( CFSTR_DSPROPERTYPAGEINFO );
  87. if ( !g_cfDsObjectNames )
  88. {
  89. hr = E_FAIL;
  90. }
  91. }
  92. if ( !g_cfMMCGetNodeType && hr == S_OK )
  93. {
  94. g_cfMMCGetNodeType = RegisterClipboardFormat( CCF_NODETYPE );
  95. if ( !g_cfMMCGetNodeType )
  96. {
  97. hr = E_FAIL;
  98. }
  99. }
  100. RETURN(hr);
  101. }
  102. //
  103. // DNtoFQDN( )
  104. //
  105. // Changes a MAO DN to and FQDN.
  106. //
  107. // Input: pszDN - string e.g cn=HP,cn=computers,dc=GPEASE,dc=DOM
  108. //
  109. // Output: *pszFQDN - LocalAlloc'ed string with the generated FQDN
  110. //
  111. HRESULT
  112. DNtoFQDN(
  113. LPWSTR pszDN,
  114. LPWSTR * pszFQDN )
  115. {
  116. TraceFunc( "DNtoFQDN( " );
  117. TraceMsg( TF_FUNC, "pszDN = '%s', *pszFQDN = 0x%08x )\n", pszDN, (pszFQDN ? *pszFQDN : NULL) );
  118. if ( !pszFQDN )
  119. RRETURN(E_POINTER);
  120. HRESULT hr = S_OK;
  121. LPWSTR pszNext;
  122. // skip the "cn=" and duplicate
  123. *pszFQDN = (LPWSTR) TraceStrDup( &pszDN[3] );
  124. if ( !*pszFQDN )
  125. {
  126. hr = THR(E_OUTOFMEMORY);
  127. goto Error;
  128. }
  129. pszNext = *pszFQDN;
  130. while ( pszNext && *pszNext )
  131. {
  132. LPWSTR psz;
  133. psz = StrChr( pszNext, L',' );
  134. if ( !psz )
  135. break;
  136. *psz = L'.';
  137. pszNext = psz;
  138. pszNext++;
  139. psz = StrStrI( pszNext, L"dc=" );
  140. Assert( psz ); // this shouldn't happen
  141. if (!psz)
  142. break;
  143. psz += 3;
  144. StrCpy( pszNext, psz );
  145. }
  146. Error:
  147. HRETURN(hr);
  148. }
  149. //
  150. // PopulateListView( )
  151. //
  152. HRESULT
  153. PopulateListView(
  154. HWND hwndList,
  155. IEnumIMSIFs * penum )
  156. {
  157. TraceFunc( "PopulateListView( ... )\n" );
  158. HRESULT hr = S_OK;
  159. INT iCount;
  160. LV_ITEM lvI;
  161. if ( !penum )
  162. HRETURN(E_POINTER);
  163. lvI.mask = LVIF_TEXT | LVIF_PARAM;
  164. lvI.iSubItem = 0;
  165. lvI.cchTextMax = REMOTE_INSTALL_MAX_DESCRIPTION_CHAR_COUNT;
  166. ListView_DeleteAllItems( hwndList );
  167. iCount = 0;
  168. while ( hr == S_OK )
  169. {
  170. WIN32_FILE_ATTRIBUTE_DATA fda;
  171. WCHAR szBuf[ MAX_PATH ];
  172. LPSIFINFO pSIF;
  173. LPWSTR pszFilePath;
  174. LPWSTR pszBegin;
  175. INT i; // general purpose
  176. hr = penum->Next( 1, &pszFilePath, NULL );
  177. if ( hr )
  178. {
  179. if ( pszFilePath )
  180. TraceFree( pszFilePath );
  181. break; // abort
  182. }
  183. // Create private storage structure
  184. pSIF = (LPSIFINFO) TraceAlloc( LPTR, sizeof(SIFINFO) );
  185. if ( !pSIF )
  186. {
  187. if ( pszFilePath )
  188. TraceFree( pszFilePath );
  189. continue; // oh well, try again next OS
  190. }
  191. // Save this
  192. pSIF->pszFilePath = pszFilePath;
  193. // Get the description
  194. pSIF->pszDescription = (LPWSTR) TraceAllocString( LMEM_FIXED, REMOTE_INSTALL_MAX_DESCRIPTION_CHAR_COUNT );
  195. if ( !pSIF->pszDescription )
  196. goto Cleanup;
  197. GetPrivateProfileString( OSCHOOSER_SIF_SECTION,
  198. OSCHOOSER_DESCRIPTION_ENTRY,
  199. L"??",
  200. pSIF->pszDescription,
  201. REMOTE_INSTALL_MAX_DESCRIPTION_CHAR_COUNT, // doesn't need -1
  202. pszFilePath );
  203. // Grab any help text
  204. pSIF->pszHelpText = (LPWSTR) TraceAllocString( LMEM_FIXED, REMOTE_INSTALL_MAX_HELPTEXT_CHAR_COUNT );
  205. if ( !pSIF->pszHelpText )
  206. goto Cleanup;
  207. GetPrivateProfileString( OSCHOOSER_SIF_SECTION,
  208. OSCHOOSER_HELPTEXT_ENTRY,
  209. L"",
  210. pSIF->pszHelpText,
  211. REMOTE_INSTALL_MAX_HELPTEXT_CHAR_COUNT, // doesn't need -1
  212. pszFilePath );
  213. // Grab the OS Version
  214. pSIF->pszVersion= (LPWSTR) TraceAllocString( LMEM_FIXED, OSVERSION_SIZE );
  215. if ( !pSIF->pszVersion )
  216. goto Cleanup;
  217. GetPrivateProfileString( OSCHOOSER_SIF_SECTION,
  218. OSCHOOSER_VERSION_ENTRY,
  219. L"",
  220. pSIF->pszVersion,
  221. OSVERSION_SIZE,
  222. pszFilePath );
  223. // Grab the last modified Time/Date stamp
  224. if ( GetFileAttributesEx( pszFilePath, GetFileExInfoStandard, &fda ) )
  225. {
  226. pSIF->ftLastWrite = fda.ftLastWriteTime;
  227. } else {
  228. ZeroMemory( &pSIF->ftLastWrite, sizeof(pSIF->ftLastWrite) );
  229. }
  230. // Figure out the language and architecture.
  231. // These are retrieved from the FilePath.
  232. // \\machine\REMINST\Setup\English\Images\nt50.wks\i386\templates\rbstndrd.sif
  233. pszBegin = pSIF->pszFilePath;
  234. for( i = 0; i < 5; i ++ )
  235. {
  236. pszBegin = StrChr( pszBegin, L'\\' );
  237. if ( !pszBegin )
  238. break;
  239. pszBegin++;
  240. }
  241. if ( pszBegin )
  242. {
  243. LPWSTR pszEnd = StrChr( pszBegin, L'\\' );
  244. if ( pszEnd )
  245. {
  246. *pszEnd = L'\0'; // terminate
  247. pSIF->pszLanguage = (LPWSTR) TraceStrDup( pszBegin );
  248. *pszEnd = L'\\'; // restore
  249. }
  250. }
  251. for( ; i < 7; i ++ )
  252. {
  253. pszBegin = StrChr( pszBegin, L'\\' );
  254. if ( !pszBegin )
  255. break;
  256. pszBegin++;
  257. }
  258. if ( pszBegin )
  259. {
  260. LPWSTR pszEnd = StrChr( pszBegin, L'\\' );
  261. if ( pszEnd )
  262. {
  263. *pszEnd = L'\0';
  264. pSIF->pszDirectory = (LPWSTR) TraceStrDup( pszBegin );
  265. *pszEnd = L'\\';
  266. }
  267. }
  268. for( ; i < 8; i ++ )
  269. {
  270. pszBegin = StrChr( pszBegin, L'\\' );
  271. if ( !pszBegin )
  272. break;
  273. pszBegin++;
  274. }
  275. if ( pszBegin )
  276. {
  277. LPWSTR pszEnd = StrChr( pszBegin, L'\\' );
  278. if ( pszEnd )
  279. {
  280. *pszEnd = L'\0';
  281. pSIF->pszArchitecture = (LPWSTR) TraceStrDup( pszBegin );
  282. *pszEnd = L'\\';
  283. }
  284. }
  285. // Figure out what kind of image it is
  286. pSIF->pszImageType = (LPWSTR) TraceAllocString( LMEM_FIXED, IMAGETYPE_SIZE );
  287. if ( !pSIF->pszImageType )
  288. goto Cleanup;
  289. GetPrivateProfileString( OSCHOOSER_SIF_SECTION,
  290. OSCHOOSER_IMAGETYPE_ENTRY,
  291. L"??",
  292. pSIF->pszImageType,
  293. IMAGETYPE_SIZE,
  294. pszFilePath );
  295. // Figure out what image it uses
  296. GetPrivateProfileString( OSCHOOSER_SIF_SECTION,
  297. OSCHOOSER_LAUNCHFILE_ENTRY,
  298. L"??",
  299. szBuf,
  300. ARRAYSIZE( szBuf ),
  301. pszFilePath );
  302. pszBegin = StrRChr( szBuf, &szBuf[wcslen(szBuf)], L'\\' );
  303. if ( pszBegin )
  304. {
  305. pszBegin++;
  306. pSIF->pszImageFile = (LPWSTR) TraceStrDup( pszBegin );
  307. }
  308. // Add the item to list view
  309. lvI.lParam = (LPARAM) pSIF;
  310. lvI.iItem = iCount;
  311. lvI.pszText = pSIF->pszDescription;
  312. iCount = ListView_InsertItem( hwndList, &lvI );
  313. Assert( iCount != -1 );
  314. if ( iCount == -1 )
  315. goto Cleanup;
  316. if ( pSIF->pszArchitecture )
  317. {
  318. ListView_SetItemText( hwndList, iCount, 1, pSIF->pszArchitecture );
  319. }
  320. if ( pSIF->pszLanguage )
  321. {
  322. ListView_SetItemText( hwndList, iCount, 2, pSIF->pszLanguage );
  323. }
  324. if ( pSIF->pszVersion )
  325. {
  326. ListView_SetItemText( hwndList, iCount, 3, pSIF->pszVersion );
  327. }
  328. continue; // next!
  329. Cleanup:
  330. if ( pSIF )
  331. {
  332. if (pSIF->pszDescription != NULL) {
  333. TraceFree( pSIF->pszDescription );
  334. }
  335. TraceFree( pSIF->pszFilePath );
  336. if (pSIF->pszHelpText != NULL) {
  337. TraceFree( pSIF->pszHelpText );
  338. }
  339. if (pSIF->pszImageType != NULL) {
  340. TraceFree( pSIF->pszImageType );
  341. }
  342. TraceFree( pSIF->pszLanguage );
  343. if (pSIF->pszVersion != NULL) {
  344. TraceFree( pSIF->pszVersion );
  345. }
  346. TraceFree( pSIF->pszImageFile );
  347. TraceFree( pSIF );
  348. }
  349. }
  350. HRETURN(hr);
  351. }
  352. //
  353. // LDAPPrefix( )
  354. //
  355. // Returns:
  356. // E_OUTOFMEMORY - if out of memory
  357. // S_OK - added LDAP:// to the pszObjDN
  358. // S_FALSE - didn't have to add anything and copied the pszObjDN
  359. // into ppszObjLDAPPath
  360. HRESULT
  361. LDAPPrefix(
  362. PWSTR pszObjDN,
  363. PWSTR * ppszObjLDAPPath)
  364. {
  365. TraceFunc( "LDAPPrefix( ... )\n" );
  366. if (pszObjDN == NULL)
  367. HRETURN(E_POINTER);
  368. HRESULT hr;
  369. const LONG cchPrefix = ARRAYSIZE(g_wszLDAPPrefix) - 1;
  370. LONG cch = wcslen(pszObjDN);
  371. if (wcsncmp(pszObjDN, g_wszLDAPPrefix, cchPrefix))
  372. {
  373. LPWSTR psz;
  374. psz = (LPWSTR) TraceAllocString( LPTR, cch + cchPrefix + 1 );
  375. if ( !psz ) {
  376. hr = E_OUTOFMEMORY;
  377. goto Error;
  378. }
  379. wcscpy(psz, g_wszLDAPPrefix);
  380. wcscat(psz, pszObjDN);
  381. *ppszObjLDAPPath = psz;
  382. hr = S_OK;
  383. }
  384. else
  385. {
  386. *ppszObjLDAPPath = pszObjDN;
  387. hr = S_FALSE;
  388. }
  389. Error:
  390. HRETURN(hr);
  391. }
  392. //
  393. // Create a message box from resource strings.
  394. //
  395. int
  396. MessageBoxFromStrings(
  397. HWND hParent,
  398. UINT idsCaption,
  399. UINT idsText,
  400. UINT uType )
  401. {
  402. TCHAR szText[ SMALL_BUFFER_SIZE * 2 ];
  403. TCHAR szCaption[ SMALL_BUFFER_SIZE ];
  404. DWORD dw;
  405. szCaption[0] = TEXT('\0');
  406. szText[0] = TEXT('\0');
  407. dw = LoadString( g_hInstance, idsCaption, szCaption, ARRAYSIZE(szCaption) );
  408. Assert( dw );
  409. dw = LoadString( g_hInstance, idsText, szText, ARRAYSIZE(szText));
  410. Assert( dw );
  411. return MessageBox( hParent, szText, szCaption, uType );
  412. }
  413. //
  414. // MessageBoxFromError( )
  415. //
  416. // Creates a error message box
  417. //
  418. void
  419. MessageBoxFromError(
  420. HWND hParent,
  421. UINT idsCaption,
  422. DWORD dwErr )
  423. {
  424. WCHAR szTitle[ SMALL_BUFFER_SIZE ];
  425. LPTSTR lpMsgBuf = NULL;
  426. DWORD dw;
  427. if ( dwErr == ERROR_SUCCESS ) {
  428. AssertMsg( dwErr, "Why was MessageBoxFromError() called when the dwErr == ERROR_SUCCES?" );
  429. return;
  430. }
  431. if ( !idsCaption ) {
  432. idsCaption = IDS_ERROR;
  433. }
  434. szTitle[0] = TEXT('\0');
  435. dw = LoadString( g_hInstance, idsCaption, szTitle, ARRAYSIZE(szTitle) );
  436. Assert( dw );
  437. FormatMessage(
  438. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  439. NULL,
  440. dwErr,
  441. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  442. (LPTSTR) &lpMsgBuf,
  443. 0,
  444. NULL
  445. );
  446. if (lpMsgBuf == NULL) {
  447. AssertMsg( (lpMsgBuf != NULL), "MessageBoxFromError() called with unknown message." );
  448. return;
  449. }
  450. MessageBox( hParent, lpMsgBuf, szTitle, MB_OK | MB_ICONERROR );
  451. LocalFree( lpMsgBuf );
  452. }
  453. //
  454. // MessageBoxFromError( )
  455. //
  456. // Creates a error message box
  457. //
  458. void
  459. MessageBoxFromHResult(
  460. HWND hParent,
  461. UINT idsCaption,
  462. HRESULT hr )
  463. {
  464. WCHAR szTitle[ SMALL_BUFFER_SIZE ];
  465. LPTSTR lpMsgBuf = NULL;
  466. DWORD dw;
  467. if ( SUCCEEDED( hr ) ) {
  468. AssertMsg( SUCCEEDED( hr ), "Why was MessageBoxFromHResult() called when the HR succeeded?" );
  469. return;
  470. }
  471. if ( !idsCaption ) {
  472. idsCaption = IDS_ERROR;
  473. }
  474. szTitle[0] = TEXT('\0');
  475. dw = LoadString( g_hInstance, idsCaption, szTitle, ARRAYSIZE(szTitle) );
  476. Assert( dw );
  477. FormatMessage(
  478. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  479. NULL,
  480. hr,
  481. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  482. (LPTSTR) &lpMsgBuf,
  483. 0,
  484. NULL
  485. );
  486. if (lpMsgBuf == NULL) {
  487. AssertMsg( (lpMsgBuf != NULL), "MessageBoxFromHResult() called with unknown message." );
  488. return;
  489. }
  490. MessageBox( hParent, lpMsgBuf, szTitle, MB_OK | MB_ICONERROR );
  491. LocalFree( lpMsgBuf );
  492. }
  493. //
  494. // VerifySIFText( )
  495. //
  496. BOOL
  497. VerifySIFText(
  498. LPWSTR pszText )
  499. {
  500. TraceFunc( "VerifySIFText()\n" );
  501. BOOL fReturn = FALSE;
  502. if ( !pszText )
  503. RETURN(fReturn);
  504. while ( *pszText >= 32 && *pszText < 128 )
  505. pszText++;
  506. if ( *pszText == L'\0' )
  507. {
  508. fReturn = TRUE;
  509. }
  510. RETURN(fReturn);
  511. }
  512. #ifndef ADSI_DNS_SEARCH
  513. //
  514. // Ldap_InitializeConnection( )
  515. //
  516. DWORD
  517. Ldap_InitializeConnection(
  518. PLDAP * LdapHandle )
  519. {
  520. TraceFunc( "Ldap_InitializeConnection( ... )\n" );
  521. PLDAPMessage OperationalAttributeLdapMessage;
  522. PLDAPMessage CurrentEntry;
  523. DWORD LdapError = LDAP_SUCCESS;
  524. if ( !( *LdapHandle ) ) {
  525. ULONG temp = DS_DIRECTORY_SERVICE_REQUIRED |
  526. DS_IP_REQUIRED |
  527. DS_GC_SERVER_REQUIRED;
  528. *LdapHandle = ldap_init( NULL, 3268);
  529. if ( !*LdapHandle )
  530. {
  531. LdapError = LDAP_UNAVAILABLE;
  532. goto e0;
  533. }
  534. ldap_set_option( *LdapHandle, LDAP_OPT_GETDSNAME_FLAGS, &temp );
  535. temp = LDAP_VERSION3;
  536. ldap_set_option( *LdapHandle, LDAP_OPT_VERSION, &temp );
  537. LdapError = ldap_connect( *LdapHandle, 0 );
  538. if ( LdapError != LDAP_SUCCESS )
  539. goto e1;
  540. LdapError = ldap_bind_s( *LdapHandle, NULL, NULL, LDAP_AUTH_SSPI );
  541. if ( LdapError != LDAP_SUCCESS )
  542. goto e1;
  543. }
  544. e0:
  545. RETURN( LdapError );
  546. e1:
  547. ldap_unbind( *LdapHandle );
  548. *LdapHandle = NULL;
  549. goto e0;
  550. }
  551. #endif // ADSI_DNS_SEARCH
  552. //
  553. // ValidateGuid( )
  554. //
  555. // Returns: S_OK if a complete, valid GUID is in pszGuid.
  556. // S_FALSE if an valid but incomplete GUID is in pszGuid. "Valid but
  557. // incomplete" is defined below.
  558. // E_FAIL if an invalid character is encountered while parsing.
  559. //
  560. // Valid characters are 0-9, A-F, a-f and "{-}"s. All spaces are ignored.
  561. // The GUID must appear in one of the following forms:
  562. //
  563. // 1. 00112233445566778899aabbccddeeff
  564. // This corresponds to the actual in-memory storage order of a GUID.
  565. // For example, it is the order in which GUID bytes appear in a
  566. // network trace.
  567. //
  568. // 2. {33221100-5544-7766-8899-aabbccddeeff}
  569. // This corresponds to the "standard" way of printing GUIDs. Note
  570. // that the "pretty" GUID shown here is the same as the GUID shown
  571. // above.
  572. //
  573. // Note that the DEFINE_GUID macro (see sdk\inc\objbase.h) for the above
  574. // GUID would look like this:
  575. // DEFINE_GUID(name,0x33221100,0x5544,0x7766,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff)
  576. //
  577. // "Valid but incomplete" means that the input consists of an even number
  578. // of hex characters (no lone nibbles), and if the input is in "pretty"
  579. // format, the input must terminate at one of the dashes or after the
  580. // second-to-the-last dash.
  581. //
  582. // The following are valid but incomplete entries:
  583. // 001122
  584. // {33221100
  585. // {33221100-5544
  586. // {33221100-5544-7766-88
  587. //
  588. // The following are invalid incomplete entries:
  589. // 00112
  590. // {332211
  591. // {33221100-5544-77
  592. //
  593. //
  594. // In the xxxGuidCharacters arrays, values [0,31] indicate nibble positions within
  595. // the in-memory representation of the GUID. Value 32 indicates the end of the
  596. // GUID string. Values 33 and up indicate special characters (nul,'-','{','}') and
  597. // are used to index into an array containing those characters.
  598. //
  599. #define VG_DONE 32
  600. #define VG_NULL 33
  601. #define VG_DASH 34
  602. #define VG_LBRACK 35
  603. #define VG_RBRACK 36
  604. CHAR InMemoryFormatGuidCharacters[] = {
  605. 1, 0, 3, 2, 5, 4, 7, 6,
  606. 9, 8, 11, 10, 13, 12, 15, 14,
  607. 17, 16, 19, 18, 21, 20, 23, 22,
  608. 25, 24, 27, 26, 29, 28, 31, 30,
  609. VG_NULL, VG_DONE };
  610. CHAR PrettyFormatGuidCharacters[] = {
  611. VG_LBRACK, 7, 6, 5, 4, 3, 2, 1,
  612. 0, VG_DASH, 11, 10, 9, 8, VG_DASH, 15,
  613. 14, 13, 12, VG_DASH, 17, 16, 19, 18,
  614. VG_DASH, 21, 20, 23, 22, 25, 24, 27,
  615. 26, 29, 28, 31, 30, VG_RBRACK, VG_NULL, VG_DONE };
  616. WCHAR SpecialCharacters[] = {
  617. 0, // VG_NULL
  618. L'-', // VG_DASH
  619. L'{', // VG_LBRACK
  620. L'}', // VG_RBRACK
  621. };
  622. PWSTR ByteToHex = L"0123456789ABCDEF";
  623. HRESULT
  624. ValidateGuid(
  625. IN LPWSTR pszGuid,
  626. OUT LPBYTE uGuid OPTIONAL,
  627. OUT LPDWORD puGuidLength OPTIONAL )
  628. {
  629. TraceFunc( "ValidateGuid( " );
  630. TraceMsg( TF_FUNC, "pszGuid = '%s'\n", pszGuid );
  631. HRESULT hr;
  632. PCHAR expectedCharacter;
  633. CHAR e;
  634. WCHAR g;
  635. BOOL parsingPrettyFormat;
  636. DWORD numberOfHexDigitsParsed;
  637. #ifdef DEBUG
  638. if ( uGuid != NULL ) {
  639. for ( e = 0; e < 16; e++ ) {
  640. uGuid[e] = 0;
  641. }
  642. }
  643. #endif
  644. if ( *pszGuid == L'{' ) {
  645. expectedCharacter = PrettyFormatGuidCharacters;
  646. parsingPrettyFormat = TRUE;
  647. } else {
  648. expectedCharacter = InMemoryFormatGuidCharacters;
  649. parsingPrettyFormat = FALSE;
  650. }
  651. numberOfHexDigitsParsed = 0;
  652. do {
  653. e = *expectedCharacter++;
  654. do {
  655. g = *pszGuid++;
  656. } while (iswspace(g));
  657. switch ( e ) {
  658. case VG_NULL:
  659. case VG_DASH:
  660. case VG_LBRACK:
  661. case VG_RBRACK:
  662. if ( g != SpecialCharacters[e - VG_NULL] ) {
  663. if ( g == 0 ) {
  664. // valid but incomplete
  665. hr = S_FALSE;
  666. } else {
  667. hr = E_FAIL;
  668. }
  669. goto done;
  670. }
  671. break;
  672. default:
  673. Assert( (e >= 0) && (e < VG_DONE) );
  674. g = towlower( g );
  675. if ( ((g >= L'0') && (g <= L'9')) ||
  676. ((g >= L'a') && (g <= L'f')) ) {
  677. if ( uGuid != NULL ) {
  678. BYTE n = (BYTE)((g > L'9') ? (g - L'a' + 10) : (g - '0'));
  679. if ( e & 1 ) {
  680. Assert( uGuid[e/2] == 0 );
  681. uGuid[e/2] = n << 4;
  682. } else {
  683. uGuid[e/2] += n;
  684. }
  685. }
  686. numberOfHexDigitsParsed++;
  687. } else {
  688. if ( (g == 0) &&
  689. (!parsingPrettyFormat ||
  690. (parsingPrettyFormat && (numberOfHexDigitsParsed >= 16))) ) {
  691. hr = S_FALSE;
  692. } else {
  693. hr = E_FAIL;
  694. }
  695. goto done;
  696. }
  697. break;
  698. }
  699. } while ( *expectedCharacter != VG_DONE );
  700. hr = S_OK;
  701. done:
  702. if ( puGuidLength != NULL ) {
  703. *puGuidLength = numberOfHexDigitsParsed / 2;
  704. }
  705. HRETURN(hr);
  706. }
  707. //
  708. // PrettyPrintGuid( )
  709. //
  710. LPWSTR
  711. PrettyPrintGuid(
  712. LPBYTE uGuid )
  713. {
  714. TraceFunc( "PrettyPrintGuid( " );
  715. LPWSTR pszPrettyString = (LPWSTR) TraceAlloc( LMEM_FIXED, PRETTY_GUID_STRING_BUFFER_SIZE );
  716. if ( pszPrettyString )
  717. {
  718. PCHAR characterType = PrettyFormatGuidCharacters;
  719. LPWSTR pszDest = pszPrettyString;
  720. CHAR ct;
  721. BYTE n;
  722. do {
  723. ct = *characterType++;
  724. switch ( ct ) {
  725. case VG_NULL:
  726. case VG_DASH:
  727. case VG_LBRACK:
  728. case VG_RBRACK:
  729. *pszDest = SpecialCharacters[ct - VG_NULL];
  730. break;
  731. default:
  732. if ( ct & 1 ) {
  733. n = uGuid[ct/2] >> 4;
  734. } else {
  735. n = uGuid[ct/2] & 0xf;
  736. }
  737. *pszDest = ByteToHex[n];
  738. break;
  739. }
  740. pszDest++;
  741. } while ( *characterType != VG_DONE );
  742. }
  743. RETURN(pszPrettyString);
  744. }
  745. //
  746. // CheckForDuplicateGuid( )
  747. //
  748. // Returns: S_OK if no duplicates found
  749. // S_FALSE if a duplicate was found
  750. // E_FAIL if the query failed
  751. //
  752. HRESULT
  753. CheckForDuplicateGuid(
  754. LPBYTE uGuid )
  755. {
  756. TraceFunc( "CheckForDuplicateGuid( " );
  757. HRESULT hr = S_OK;
  758. WCHAR szGuid[ MAX_INPUT_GUID_STRING * 2 ]; // room for escaped GUID
  759. WCHAR szFilter[ARRAYSIZE(szGuid)+ARRAYSIZE(FILTER_GUID_QUERY)];
  760. PLDAP LdapHandle = NULL;
  761. LPWSTR ComputerAttrs[2];
  762. DWORD LdapError;
  763. DWORD count;
  764. PLDAPMessage LdapMessage;
  765. LdapError = Ldap_InitializeConnection( &LdapHandle );
  766. Assert( LdapError == LDAP_SUCCESS );
  767. if ( LdapError != LDAP_SUCCESS )
  768. {
  769. hr = THR( HRESULT_FROM_WIN32( LdapMapErrorToWin32( LdapError ) ) );
  770. goto e0;
  771. }
  772. ZeroMemory( szGuid, sizeof(szGuid) );
  773. ldap_escape_filter_element( (PCHAR)uGuid, 16, szGuid, sizeof(szGuid) );
  774. wsprintf( szFilter, FILTER_GUID_QUERY, szGuid );
  775. DebugMsg( "Dup Guid Filter: %s\n", szFilter );
  776. ComputerAttrs[0] = DISTINGUISHEDNAME;
  777. ComputerAttrs[1] = NULL;
  778. LdapError = ldap_search_ext_s( LdapHandle,
  779. NULL,
  780. LDAP_SCOPE_SUBTREE,
  781. szFilter,
  782. ComputerAttrs,
  783. FALSE,
  784. NULL,
  785. NULL,
  786. NULL,
  787. 0,
  788. &LdapMessage);
  789. Assert( LdapError == LDAP_SUCCESS );
  790. if ( LdapError != LDAP_SUCCESS )
  791. {
  792. hr = THR( HRESULT_FROM_WIN32( LdapMapErrorToWin32( LdapError ) ) );
  793. goto e1;
  794. }
  795. count = ldap_count_entries( LdapHandle, LdapMessage );
  796. if ( count != 0 )
  797. {
  798. hr = S_FALSE;
  799. }
  800. else
  801. {
  802. hr = S_OK;
  803. }
  804. ldap_msgfree( LdapMessage );
  805. e1:
  806. ldap_unbind( LdapHandle );
  807. e0:
  808. HRETURN(hr);
  809. }
  810. //
  811. // AddWizardPage( )
  812. //
  813. // Adds a page to the wizard.
  814. //
  815. void
  816. AddWizardPage(
  817. LPPROPSHEETHEADER ppsh,
  818. UINT id,
  819. DLGPROC pfn,
  820. UINT idTitle,
  821. UINT idSubtitle,
  822. LPARAM lParam )
  823. {
  824. PROPSHEETPAGE psp;
  825. TCHAR szTitle[ SMALL_BUFFER_SIZE ];
  826. TCHAR szSubTitle[ SMALL_BUFFER_SIZE ];
  827. ZeroMemory( &psp, sizeof(psp) );
  828. psp.dwSize = sizeof(psp);
  829. psp.dwFlags = PSP_DEFAULT | PSP_USETITLE;
  830. psp.pszTitle = MAKEINTRESOURCE( IDS_ADD_DOT_DOT_DOT );
  831. psp.hInstance = ppsh->hInstance;
  832. psp.pszTemplate = MAKEINTRESOURCE(id);
  833. psp.pfnDlgProc = pfn;
  834. psp.lParam = lParam;
  835. if ( idTitle )
  836. {
  837. DWORD dw;
  838. dw = LoadString( g_hInstance, idTitle, szTitle, ARRAYSIZE(szTitle) );
  839. Assert( dw );
  840. psp.pszHeaderTitle = szTitle;
  841. psp.dwFlags |= PSP_USEHEADERTITLE;
  842. }
  843. else
  844. {
  845. psp.pszHeaderTitle = NULL;
  846. }
  847. if ( idSubtitle )
  848. {
  849. DWORD dw;
  850. dw = LoadString( g_hInstance, idSubtitle , szSubTitle, ARRAYSIZE(szSubTitle) );
  851. Assert( dw );
  852. psp.pszHeaderSubTitle = szSubTitle;
  853. psp.dwFlags |= PSP_USEHEADERSUBTITLE;
  854. }
  855. else
  856. {
  857. psp.pszHeaderSubTitle = NULL;
  858. }
  859. ppsh->phpage[ ppsh->nPages ] = CreatePropertySheetPage( &psp );
  860. if ( ppsh->phpage[ ppsh->nPages ] )
  861. ppsh->nPages++;
  862. }
  863. // borrowed from shell\inc\shsemip.h
  864. // unsafe macros
  865. #define _ILSkip(pidl, cb) ((LPITEMIDLIST)(((BYTE*)(pidl))+cb))
  866. #define _ILNext(pidl) _ILSkip(pidl, (pidl)->mkid.cb)
  867. //
  868. // BrowseForRIServersCallback( )
  869. //
  870. INT CALLBACK
  871. BrowseForRIServersCallback(
  872. HWND hwnd,
  873. UINT uMsg,
  874. LPARAM lParam,
  875. LPARAM lpData
  876. )
  877. {
  878. TraceFunc( "BrowseForRIServersCallback( ... )\n" );
  879. if ( uMsg == BFFM_SELCHANGED )
  880. {
  881. HRESULT hr;
  882. LPSHARE_INFO_1 psi;
  883. LPWSTR pszComputerName;
  884. WCHAR szStatusText[ 256 ]; // random
  885. LPITEMIDLIST pidl = (LPITEMIDLIST) lParam;
  886. IShellFolder * psf = NULL;
  887. DWORD dw;
  888. SHORT cbTmp;
  889. STRRET strret;
  890. dw = LoadString( g_hInstance, IDC_NOT_A_BINL_SERVER, szStatusText, ARRAYSIZE(szStatusText) );
  891. Assert( dw );
  892. if (!dw) {
  893. szStatusText[0] = '\0';
  894. }
  895. hr = THR( SHGetDesktopFolder( &psf ) );
  896. if ( FAILED(hr) )
  897. goto Error;
  898. hr = THR( psf->GetDisplayNameOf( pidl, SHGDN_NORMAL | SHGDN_FORPARSING, &strret ) );
  899. if ( FAILED(hr) )
  900. goto Error;
  901. switch( strret.uType )
  902. {
  903. case STRRET_WSTR:
  904. pszComputerName = strret.pOleStr;
  905. break;
  906. case STRRET_OFFSET:
  907. AssertMsg( 0, "I dunno if this is right!\n" );
  908. pszComputerName = (LPWSTR) ((LPBYTE) pidl) + strret.uOffset;
  909. break;
  910. case STRRET_CSTR:
  911. pszComputerName = (LPWSTR) &strret.cStr[0];
  912. break;
  913. }
  914. if ( pszComputerName[0] != L'\\' || pszComputerName[1] != L'\\' )
  915. goto Error;
  916. DebugMsg( "Checking Server: %s\n", pszComputerName );
  917. if ( NERR_Success == NetShareGetInfo( &pszComputerName[2],
  918. REMINST_SHARE,
  919. 1,
  920. (LPBYTE *) &psi ) )
  921. {
  922. szStatusText[0] = L'\0';
  923. NetApiBufferFree( psi );
  924. }
  925. Error:
  926. SendMessage(hwnd, BFFM_ENABLEOK, 0, (LPARAM)( szStatusText[0] == '\0' ) );
  927. SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM) szStatusText );
  928. }
  929. RETURN(0);
  930. }