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.

5203 lines
124 KiB

  1. #include "main.h"
  2. #include <schemamanager.h>
  3. #include "rsoputil.h"
  4. #include <initguid.h>
  5. typedef struct _GPOERRORINFO
  6. {
  7. DWORD dwError;
  8. LPTSTR lpMsg;
  9. } GPOERRORINFO, *LPGPOERRORINFO;
  10. typedef struct _DCOPTION
  11. {
  12. LPTSTR lpDomainName;
  13. INT iOption;
  14. struct _DCOPTION *pNext;
  15. } DCOPTION, *LPDCOPTION;
  16. LPDCOPTION g_DCInfo = NULL;
  17. //
  18. // Help ids
  19. //
  20. DWORD aErrorHelpIds[] =
  21. {
  22. 0, 0
  23. };
  24. DWORD aNoDCHelpIds[] =
  25. {
  26. IDC_NODC_PDC, IDH_DC_PDC,
  27. IDC_NODC_INHERIT, IDH_DC_INHERIT,
  28. IDC_NODC_ANYDC, IDH_DC_ANYDC,
  29. 0, 0
  30. };
  31. DEFINE_GUID(CLSID_WMIFilterManager,0xD86A8E9B,0xF53F,0x45AD,0x8C,0x49,0x0A,0x0A,0x52,0x30,0xDE,0x28);
  32. DEFINE_GUID(IID_IWMIFilterManager,0x64DCCA00,0x14A6,0x473C,0x90,0x06,0x5A,0xB7,0x9D,0xC6,0x84,0x91);
  33. //*************************************************************
  34. //
  35. // SetWaitCursor()
  36. //
  37. // Purpose: Sets the wait cursor
  38. //
  39. // Parameters: none
  40. //
  41. //
  42. // Return: void
  43. //
  44. //*************************************************************
  45. void SetWaitCursor (void)
  46. {
  47. SetCursor (LoadCursor(NULL, IDC_WAIT));
  48. }
  49. //*************************************************************
  50. //
  51. // ClearWaitCursor()
  52. //
  53. // Purpose: Resets the wait cursor
  54. //
  55. // Parameters: none
  56. //
  57. //
  58. // Return: void
  59. //
  60. //*************************************************************
  61. void ClearWaitCursor (void)
  62. {
  63. SetCursor (LoadCursor(NULL, IDC_ARROW));
  64. }
  65. //*************************************************************
  66. //
  67. // CheckSlash()
  68. //
  69. // Purpose: Checks for an ending slash and adds one if
  70. // it is missing.
  71. //
  72. // Parameters: lpDir - directory
  73. //
  74. // Return: Pointer to the end of the string
  75. //
  76. // Comments:
  77. //
  78. // History: Date Author Comment
  79. // 6/19/95 ericflo Created
  80. //
  81. //*************************************************************
  82. LPTSTR CheckSlash (LPTSTR lpDir)
  83. {
  84. LPTSTR lpEnd;
  85. lpEnd = lpDir + lstrlen(lpDir);
  86. if (*(lpEnd - 1) != TEXT('\\')) {
  87. *lpEnd = TEXT('\\');
  88. lpEnd++;
  89. *lpEnd = TEXT('\0');
  90. }
  91. return lpEnd;
  92. }
  93. //*************************************************************
  94. //
  95. // RegDelnodeRecurse()
  96. //
  97. // Purpose: Deletes a registry key and all it's subkeys / values.
  98. // Called by RegDelnode
  99. //
  100. // Parameters: hKeyRoot - Root key
  101. // lpSubKey - SubKey to delete
  102. //
  103. // Return: TRUE if successful
  104. // FALSE if an error occurs
  105. //
  106. // Comments:
  107. //
  108. // History: Date Author Comment
  109. // 10/3/95 ericflo Created
  110. //
  111. //*************************************************************
  112. BOOL RegDelnodeRecurse (HKEY hKeyRoot, LPTSTR lpSubKey)
  113. {
  114. LPTSTR lpEnd;
  115. LONG lResult;
  116. DWORD dwSize;
  117. TCHAR szName[MAX_PATH];
  118. HKEY hKey;
  119. FILETIME ftWrite;
  120. //
  121. // First, see if we can delete the key without having
  122. // to recurse.
  123. //
  124. lResult = RegDeleteKey(hKeyRoot, lpSubKey);
  125. if (lResult == ERROR_SUCCESS) {
  126. return TRUE;
  127. }
  128. lResult = RegOpenKeyEx (hKeyRoot, lpSubKey, 0, KEY_READ, &hKey);
  129. if (lResult != ERROR_SUCCESS) {
  130. return FALSE;
  131. }
  132. lpEnd = CheckSlash(lpSubKey);
  133. //
  134. // Enumerate the keys
  135. //
  136. dwSize = MAX_PATH;
  137. lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL,
  138. NULL, NULL, &ftWrite);
  139. if (lResult == ERROR_SUCCESS) {
  140. do {
  141. lstrcpy (lpEnd, szName);
  142. if (!RegDelnodeRecurse(hKeyRoot, lpSubKey)) {
  143. break;
  144. }
  145. //
  146. // Enumerate again
  147. //
  148. dwSize = MAX_PATH;
  149. lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL,
  150. NULL, NULL, &ftWrite);
  151. } while (lResult == ERROR_SUCCESS);
  152. }
  153. lpEnd--;
  154. *lpEnd = TEXT('\0');
  155. RegCloseKey (hKey);
  156. //
  157. // Try again to delete the key
  158. //
  159. lResult = RegDeleteKey(hKeyRoot, lpSubKey);
  160. if (lResult == ERROR_SUCCESS) {
  161. return TRUE;
  162. }
  163. return FALSE;
  164. }
  165. //*************************************************************
  166. //
  167. // RegDelnode()
  168. //
  169. // Purpose: Deletes a registry key and all it's subkeys / values
  170. //
  171. // Parameters: hKeyRoot - Root key
  172. // lpSubKey - SubKey to delete
  173. //
  174. // Return: TRUE if successful
  175. // FALSE if an error occurs
  176. //
  177. // Comments:
  178. //
  179. // History: Date Author Comment
  180. // 10/3/95 ericflo Created
  181. //
  182. //*************************************************************
  183. BOOL RegDelnode (HKEY hKeyRoot, LPTSTR lpSubKey)
  184. {
  185. TCHAR szDelKey[2 * MAX_PATH];
  186. lstrcpy (szDelKey, lpSubKey);
  187. return RegDelnodeRecurse(hKeyRoot, szDelKey);
  188. }
  189. //*************************************************************
  190. //
  191. // CreateNestedDirectory()
  192. //
  193. // Purpose: Creates a subdirectory and all it's parents
  194. // if necessary.
  195. //
  196. // Parameters: lpDirectory - Directory name
  197. // lpSecurityAttributes - Security Attributes
  198. //
  199. // Return: > 0 if successful
  200. // 0 if an error occurs
  201. //
  202. // Comments:
  203. //
  204. // History: Date Author Comment
  205. // 8/08/95 ericflo Created
  206. //
  207. //*************************************************************
  208. UINT CreateNestedDirectory(LPCTSTR lpDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
  209. {
  210. TCHAR szDirectory[MAX_PATH];
  211. LPTSTR lpEnd;
  212. //
  213. // Check for NULL pointer
  214. //
  215. if (!lpDirectory || !(*lpDirectory)) {
  216. DebugMsg((DM_WARNING, TEXT("CreateNestedDirectory: Received a NULL pointer.")));
  217. return 0;
  218. }
  219. //
  220. // First, see if we can create the directory without having
  221. // to build parent directories.
  222. //
  223. if (CreateDirectory (lpDirectory, lpSecurityAttributes)) {
  224. return 1;
  225. }
  226. //
  227. // If this directory exists already, this is OK too.
  228. //
  229. if (GetLastError() == ERROR_ALREADY_EXISTS) {
  230. return ERROR_ALREADY_EXISTS;
  231. }
  232. //
  233. // No luck, copy the string to a buffer we can munge
  234. //
  235. lstrcpy (szDirectory, lpDirectory);
  236. //
  237. // Find the first subdirectory name
  238. //
  239. lpEnd = szDirectory;
  240. if (szDirectory[1] == TEXT(':')) {
  241. lpEnd += 3;
  242. } else if (szDirectory[1] == TEXT('\\')) {
  243. //
  244. // Skip the first two slashes
  245. //
  246. lpEnd += 2;
  247. //
  248. // Find the slash between the server name and
  249. // the share name.
  250. //
  251. while (*lpEnd && *lpEnd != TEXT('\\')) {
  252. lpEnd++;
  253. }
  254. if (!(*lpEnd)) {
  255. return 0;
  256. }
  257. //
  258. // Skip the slash, and find the slash between
  259. // the share name and the directory name.
  260. //
  261. lpEnd++;
  262. while (*lpEnd && *lpEnd != TEXT('\\')) {
  263. lpEnd++;
  264. }
  265. if (!(*lpEnd)) {
  266. return 0;
  267. }
  268. //
  269. // Leave pointer at the beginning of the directory.
  270. //
  271. lpEnd++;
  272. } else if (szDirectory[0] == TEXT('\\')) {
  273. lpEnd++;
  274. }
  275. while (*lpEnd) {
  276. while (*lpEnd && *lpEnd != TEXT('\\')) {
  277. lpEnd++;
  278. }
  279. if (*lpEnd == TEXT('\\')) {
  280. *lpEnd = TEXT('\0');
  281. if (!CreateDirectory (szDirectory, NULL)) {
  282. if (GetLastError() != ERROR_ALREADY_EXISTS) {
  283. DebugMsg((DM_WARNING, TEXT("CreateNestedDirectory: CreateDirectory failed for %s with %d."),
  284. szDirectory, GetLastError()));
  285. return 0;
  286. }
  287. }
  288. *lpEnd = TEXT('\\');
  289. lpEnd++;
  290. }
  291. }
  292. //
  293. // Create the final directory
  294. //
  295. if (CreateDirectory (szDirectory, lpSecurityAttributes)) {
  296. return 1;
  297. }
  298. if (GetLastError() == ERROR_ALREADY_EXISTS) {
  299. return ERROR_ALREADY_EXISTS;
  300. }
  301. //
  302. // Failed
  303. //
  304. DebugMsg((DM_VERBOSE, TEXT("CreateNestedDirectory: Failed to create the directory with error %d."), GetLastError()));
  305. return 0;
  306. }
  307. VOID LoadMessage (DWORD dwID, LPTSTR lpBuffer, DWORD dwSize)
  308. {
  309. HINSTANCE hInstActiveDS;
  310. HINSTANCE hInstWMI;
  311. if (!FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
  312. NULL, dwID,
  313. MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
  314. lpBuffer, dwSize, NULL))
  315. {
  316. hInstActiveDS = LoadLibrary (TEXT("activeds.dll"));
  317. if (hInstActiveDS)
  318. {
  319. if (!FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE,
  320. hInstActiveDS, dwID,
  321. MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
  322. lpBuffer, dwSize, NULL))
  323. {
  324. hInstWMI = LoadLibrary (TEXT("wmiutils.dll"));
  325. if (hInstWMI)
  326. {
  327. if (!FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE,
  328. hInstWMI, dwID,
  329. MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
  330. lpBuffer, dwSize, NULL))
  331. {
  332. DebugMsg((DM_WARNING, TEXT("LoadMessage: Failed to query error message text for %d due to error %d"),
  333. dwID, GetLastError()));
  334. wsprintf (lpBuffer, TEXT("%d (0x%x)"), dwID, dwID);
  335. }
  336. FreeLibrary (hInstWMI);
  337. }
  338. }
  339. FreeLibrary (hInstActiveDS);
  340. }
  341. }
  342. }
  343. //*************************************************************
  344. //
  345. // ErrorDlgProc()
  346. //
  347. // Purpose: Dialog box procedure for errors
  348. //
  349. // Parameters:
  350. //
  351. //
  352. // Return: TRUE if successful
  353. // FALSE if an error occurs
  354. //
  355. //*************************************************************
  356. INT_PTR CALLBACK ErrorDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  357. {
  358. switch (message)
  359. {
  360. case WM_INITDIALOG:
  361. {
  362. TCHAR szError[MAX_PATH];
  363. LPGPOERRORINFO lpEI = (LPGPOERRORINFO) lParam;
  364. HICON hIcon;
  365. hIcon = LoadIcon (NULL, IDI_WARNING);
  366. if (hIcon)
  367. {
  368. SendDlgItemMessage (hDlg, IDC_ERROR_ICON, STM_SETICON, (WPARAM)hIcon, 0);
  369. }
  370. SetDlgItemText (hDlg, IDC_ERRORTEXT, lpEI->lpMsg);
  371. szError[0] = TEXT('\0');
  372. if (lpEI->dwError)
  373. {
  374. LoadMessage (lpEI->dwError, szError, ARRAYSIZE(szError));
  375. }
  376. if (szError[0] == TEXT('\0'))
  377. {
  378. LoadString (g_hInstance, IDS_NONE, szError, ARRAYSIZE(szError));
  379. }
  380. SetDlgItemText (hDlg, IDC_DETAILSTEXT, szError);
  381. return TRUE;
  382. }
  383. case WM_COMMAND:
  384. if (LOWORD(wParam) == IDCLOSE || LOWORD(wParam) == IDCANCEL)
  385. {
  386. EndDialog(hDlg, TRUE);
  387. return TRUE;
  388. }
  389. break;
  390. case WM_HELP: // F1
  391. WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, HELP_FILE, HELP_WM_HELP,
  392. (ULONG_PTR) (LPSTR) aErrorHelpIds);
  393. break;
  394. case WM_CONTEXTMENU: // right mouse click
  395. WinHelp((HWND) wParam, HELP_FILE, HELP_CONTEXTMENU,
  396. (ULONG_PTR) (LPSTR) aErrorHelpIds);
  397. return (TRUE);
  398. }
  399. return FALSE;
  400. }
  401. //*************************************************************
  402. //
  403. // ReportError()
  404. //
  405. // Purpose: Displays an error message to the user
  406. //
  407. // Parameters: hParent - Parent window handle
  408. // dwError - Error number
  409. // idMsg - Error message id
  410. //
  411. // Return: TRUE if successful
  412. // FALSE if an error occurs
  413. //
  414. // Comments:
  415. //
  416. // History: Date Author Comment
  417. // 7/18/95 ericflo Created
  418. //
  419. //*************************************************************
  420. BOOL ReportError (HWND hParent, DWORD dwError, UINT idMsg, ...)
  421. {
  422. GPOERRORINFO ei;
  423. TCHAR szMsg[MAX_PATH];
  424. TCHAR szErrorMsg[2*MAX_PATH+40];
  425. va_list marker;
  426. //
  427. // Load the error message
  428. //
  429. if (!LoadString (g_hInstance, idMsg, szMsg, MAX_PATH))
  430. {
  431. return FALSE;
  432. }
  433. //
  434. // Special case access denied errors with a custom message
  435. //
  436. if ((dwError == ERROR_ACCESS_DENIED) || (dwError == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)))
  437. {
  438. if ((idMsg != IDS_EXECFAILED_USER) && (idMsg != IDS_EXECFAILED_COMPUTER) &&
  439. (idMsg != IDS_EXECFAILED) && (idMsg != IDS_EXECFAILED_BOTH))
  440. {
  441. if (!LoadString (g_hInstance, IDS_ACCESSDENIED, szMsg, MAX_PATH))
  442. {
  443. return FALSE;
  444. }
  445. }
  446. }
  447. else if ( dwError == WBEM_E_INVALID_NAMESPACE )
  448. {
  449. if (!LoadString (g_hInstance, IDS_INVALID_NAMESPACE, szMsg, MAX_PATH))
  450. {
  451. return FALSE;
  452. }
  453. }
  454. //
  455. // Plug in the arguments
  456. //
  457. va_start(marker, idMsg);
  458. wvsprintf(szErrorMsg, szMsg, marker);
  459. va_end(marker);
  460. //
  461. // Display the message
  462. //
  463. ei.dwError = dwError;
  464. ei.lpMsg = szErrorMsg;
  465. DialogBoxParam (g_hInstance, MAKEINTRESOURCE(IDD_ERROR), hParent,
  466. ErrorDlgProc, (LPARAM) &ei);
  467. return TRUE;
  468. }
  469. //*************************************************************
  470. //
  471. // Delnode_Recurse()
  472. //
  473. // Purpose: Recursive delete function for Delnode
  474. //
  475. // Parameters: lpDir - Directory
  476. //
  477. // Return: TRUE if successful
  478. // FALSE if an error occurs
  479. //
  480. // Comments:
  481. //
  482. // History: Date Author Comment
  483. // 8/10/95 ericflo Created
  484. //
  485. //*************************************************************
  486. BOOL Delnode_Recurse (LPTSTR lpDir)
  487. {
  488. WIN32_FIND_DATA fd;
  489. HANDLE hFile;
  490. //
  491. // Verbose output
  492. //
  493. DebugMsg((DM_VERBOSE, TEXT("Delnode_Recurse: Entering, lpDir = <%s>"), lpDir));
  494. //
  495. // Setup the current working dir
  496. //
  497. if (!SetCurrentDirectory (lpDir)) {
  498. DebugMsg((DM_WARNING, TEXT("Delnode_Recurse: Failed to set current working directory. Error = %d"), GetLastError()));
  499. return FALSE;
  500. }
  501. //
  502. // Find the first file
  503. //
  504. hFile = FindFirstFile(TEXT("*.*"), &fd);
  505. if (hFile == INVALID_HANDLE_VALUE) {
  506. if (GetLastError() == ERROR_FILE_NOT_FOUND) {
  507. return TRUE;
  508. } else {
  509. DebugMsg((DM_WARNING, TEXT("Delnode_Recurse: FindFirstFile failed. Error = %d"),
  510. GetLastError()));
  511. return FALSE;
  512. }
  513. }
  514. do {
  515. //
  516. // Verbose output
  517. //
  518. DebugMsg((DM_VERBOSE, TEXT("Delnode_Recurse: FindFile found: <%s>"),
  519. fd.cFileName));
  520. //
  521. // Check for "." and ".."
  522. //
  523. if (!lstrcmpi(fd.cFileName, TEXT("."))) {
  524. continue;
  525. }
  526. if (!lstrcmpi(fd.cFileName, TEXT(".."))) {
  527. continue;
  528. }
  529. if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  530. //
  531. // Found a directory.
  532. //
  533. if (!Delnode_Recurse(fd.cFileName)) {
  534. FindClose(hFile);
  535. return FALSE;
  536. }
  537. if (fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
  538. fd.dwFileAttributes &= ~FILE_ATTRIBUTE_READONLY;
  539. SetFileAttributes (fd.cFileName, fd.dwFileAttributes);
  540. }
  541. if (!RemoveDirectory (fd.cFileName)) {
  542. DebugMsg((DM_WARNING, TEXT("Delnode_Recurse: Failed to delete directory <%s>. Error = %d"),
  543. fd.cFileName, GetLastError()));
  544. }
  545. } else {
  546. //
  547. // We found a file. Set the file attributes,
  548. // and try to delete it.
  549. //
  550. if ((fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ||
  551. (fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)) {
  552. SetFileAttributes (fd.cFileName, FILE_ATTRIBUTE_NORMAL);
  553. }
  554. if (!DeleteFile (fd.cFileName)) {
  555. DebugMsg((DM_WARNING, TEXT("Delnode_Recurse: Failed to delete <%s>. Error = %d"),
  556. fd.cFileName, GetLastError()));
  557. }
  558. }
  559. //
  560. // Find the next entry
  561. //
  562. } while (FindNextFile(hFile, &fd));
  563. //
  564. // Close the search handle
  565. //
  566. FindClose(hFile);
  567. //
  568. // Reset the working directory
  569. //
  570. if (!SetCurrentDirectory (TEXT(".."))) {
  571. DebugMsg((DM_WARNING, TEXT("Delnode_Recurse: Failed to reset current working directory. Error = %d"), GetLastError()));
  572. return FALSE;
  573. }
  574. //
  575. // Success.
  576. //
  577. DebugMsg((DM_VERBOSE, TEXT("Delnode_Recurse: Leaving <%s>"), lpDir));
  578. return TRUE;
  579. }
  580. //*************************************************************
  581. //
  582. // Delnode()
  583. //
  584. // Purpose: Recursive function that deletes files and
  585. // directories.
  586. //
  587. // Parameters: lpDir - Directory
  588. //
  589. // Return: TRUE if successful
  590. // FALSE if an error occurs
  591. //
  592. // Comments:
  593. //
  594. // History: Date Author Comment
  595. // 6/23/95 ericflo Created
  596. //
  597. //*************************************************************
  598. BOOL Delnode (LPTSTR lpDir)
  599. {
  600. TCHAR szCurWorkingDir[MAX_PATH];
  601. if (GetCurrentDirectory(MAX_PATH, szCurWorkingDir)) {
  602. Delnode_Recurse (lpDir);
  603. SetCurrentDirectory (szCurWorkingDir);
  604. if (!RemoveDirectory (lpDir)) {
  605. DebugMsg((DM_VERBOSE, TEXT("Delnode: Failed to delete directory <%s>. Error = %d"),
  606. lpDir, GetLastError()));
  607. return FALSE;
  608. }
  609. } else {
  610. DebugMsg((DM_WARNING, TEXT("Delnode: Failed to get current working directory. Error = %d"), GetLastError()));
  611. return FALSE;
  612. }
  613. return TRUE;
  614. }
  615. /*******************************************************************
  616. NAME: StringToNum
  617. SYNOPSIS: Converts string value to numeric value
  618. NOTES: Calls atoi() to do conversion, but first checks
  619. for non-numeric characters
  620. EXIT: Returns TRUE if successful, FALSE if invalid
  621. (non-numeric) characters
  622. ********************************************************************/
  623. BOOL StringToNum(TCHAR *pszStr,UINT * pnVal)
  624. {
  625. TCHAR *pTst = pszStr;
  626. if (!pszStr) return FALSE;
  627. // verify that all characters are numbers
  628. while (*pTst)
  629. {
  630. if (!(*pTst >= TEXT('0') && *pTst <= TEXT('9')))
  631. {
  632. if (*pTst != TEXT('-'))
  633. return FALSE;
  634. }
  635. pTst = CharNext(pTst);
  636. }
  637. *pnVal = _ttoi(pszStr);
  638. return TRUE;
  639. }
  640. //*************************************************************
  641. //
  642. // DSDelnodeRecurse()
  643. //
  644. // Purpose: Delnodes a tree in the DS
  645. //
  646. // Parameters: pADsContainer - IADSContainer interface
  647. //
  648. // Return: S_OK if successful
  649. //
  650. //*************************************************************
  651. HRESULT DSDelnodeRecurse (IADsContainer * pADsContainer)
  652. {
  653. HRESULT hr;
  654. BSTR bstrRelativeName;
  655. BSTR bstrClassName;
  656. IEnumVARIANT *pVar = NULL;
  657. IADsContainer * pADsChild = NULL;
  658. IADs * pDSObject = NULL;
  659. IDispatch * pDispatch;
  660. VARIANT var;
  661. ULONG ulResult;
  662. //
  663. // Enumerate the children and delete them first
  664. //
  665. hr = ADsBuildEnumerator (pADsContainer, &pVar);
  666. if (FAILED(hr)) {
  667. DebugMsg((DM_WARNING, TEXT("DSDelnodeRecurse: Failed to get enumerator with 0x%x"), hr));
  668. goto Exit;
  669. }
  670. while (TRUE)
  671. {
  672. VariantInit(&var);
  673. hr = ADsEnumerateNext(pVar, 1, &var, &ulResult);
  674. if (FAILED(hr))
  675. {
  676. DebugMsg((DM_VERBOSE, TEXT("DSDelnodeRecurse: Failed to enumerator with 0x%x"), hr));
  677. VariantClear (&var);
  678. break;
  679. }
  680. if (S_FALSE == hr)
  681. {
  682. VariantClear (&var);
  683. break;
  684. }
  685. //
  686. // If var.vt isn't VT_DISPATCH, we're finished.
  687. //
  688. if (var.vt != VT_DISPATCH)
  689. {
  690. VariantClear (&var);
  691. break;
  692. }
  693. //
  694. // We found something, get the IDispatch interface
  695. //
  696. pDispatch = var.pdispVal;
  697. if (!pDispatch)
  698. {
  699. VariantClear (&var);
  700. goto Exit;
  701. }
  702. //
  703. // Now query for the IADsContainer interface so we can recurse
  704. // if necessary. Note it is ok if this fails because not
  705. // everything is a container.
  706. //
  707. hr = pDispatch->QueryInterface(IID_IADsContainer, (LPVOID *)&pADsChild);
  708. if (SUCCEEDED(hr)) {
  709. hr = DSDelnodeRecurse (pADsChild);
  710. if (FAILED(hr)) {
  711. goto Exit;
  712. }
  713. pADsChild->Release();
  714. }
  715. //
  716. // Now query for the IADs interface so we can get some
  717. // properties from this object
  718. //
  719. hr = pDispatch->QueryInterface(IID_IADs, (LPVOID *)&pDSObject);
  720. if (FAILED(hr)) {
  721. DebugMsg((DM_WARNING, TEXT("AddGPOsForDomain: QI for IADs failed with 0x%x"), hr));
  722. VariantClear (&var);
  723. goto Exit;
  724. }
  725. //
  726. // Get the relative and class names
  727. //
  728. hr = pDSObject->get_Name (&bstrRelativeName);
  729. if (FAILED(hr))
  730. {
  731. DebugMsg((DM_WARNING, TEXT("DSDelnodeRecurse: Failed get relative name with 0x%x"), hr));
  732. pDSObject->Release();
  733. VariantClear (&var);
  734. goto Exit;
  735. }
  736. hr = pDSObject->get_Class (&bstrClassName);
  737. if (FAILED(hr))
  738. {
  739. DebugMsg((DM_WARNING, TEXT("DSDelnodeRecurse: Failed get class name with 0x%x"), hr));
  740. SysFreeString (bstrRelativeName);
  741. pDSObject->Release();
  742. VariantClear (&var);
  743. goto Exit;
  744. }
  745. pDSObject->Release();
  746. //
  747. // Delete the object
  748. //
  749. hr = pADsContainer->Delete (bstrClassName,
  750. bstrRelativeName);
  751. if (FAILED(hr))
  752. {
  753. DebugMsg((DM_WARNING, TEXT("DSDelnodeRecurse: Failed to delete object with 0x%x"), hr));
  754. SysFreeString (bstrRelativeName);
  755. SysFreeString (bstrClassName);
  756. VariantClear (&var);
  757. goto Exit;
  758. }
  759. SysFreeString (bstrRelativeName);
  760. SysFreeString (bstrClassName);
  761. VariantClear (&var);
  762. }
  763. Exit:
  764. if (pVar)
  765. {
  766. ADsFreeEnumerator (pVar);
  767. }
  768. return hr;
  769. }
  770. //*************************************************************
  771. //
  772. // DSDelnodeRecurse()
  773. //
  774. // Purpose: Delnodes a tree in the DS
  775. //
  776. // Parameters: lpDSPath - Path of DS object to delete
  777. //
  778. // Return: S_OK if successful
  779. //
  780. //*************************************************************
  781. HRESULT DSDelnode (LPTSTR lpDSPath)
  782. {
  783. HRESULT hr;
  784. BSTR bstrParent = NULL;
  785. BSTR bstrRelativeName = NULL;
  786. BSTR bstrClassName = NULL;
  787. IADsContainer * pADsContainer = NULL;
  788. IADs * pDSObject = NULL;
  789. VARIANT var;
  790. ULONG ulResult;
  791. //
  792. // Enumerate the children and delete them first
  793. //
  794. hr = OpenDSObject(lpDSPath, IID_IADsContainer, (void **)&pADsContainer);
  795. if (FAILED(hr)) {
  796. DebugMsg((DM_WARNING, TEXT("DSDelnode: Failed to get gpo container interface with 0x%x"), hr));
  797. goto Exit;
  798. }
  799. hr = DSDelnodeRecurse (pADsContainer);
  800. if (FAILED(hr)) {
  801. DebugMsg((DM_WARNING, TEXT("DSDelnode: Failed to delete children with 0x%x"), hr));
  802. goto Exit;
  803. }
  804. pADsContainer->Release();
  805. pADsContainer = NULL;
  806. //
  807. // Bind to the object
  808. //
  809. hr = OpenDSObject (lpDSPath, IID_IADs, (void **)&pDSObject);
  810. if (FAILED(hr))
  811. {
  812. DebugMsg((DM_WARNING, TEXT("DSDelnode: Failed bind to the object %s with 0x%x"),
  813. lpDSPath, hr));
  814. goto Exit;
  815. }
  816. //
  817. // Get the parent's name
  818. //
  819. hr = pDSObject->get_Parent (&bstrParent);
  820. if (FAILED(hr))
  821. {
  822. DebugMsg((DM_WARNING, TEXT("DSDelnode: Failed get parent's name with 0x%x"), hr));
  823. goto Exit;
  824. }
  825. //
  826. // Get this object's relative and class names
  827. //
  828. hr = pDSObject->get_Name (&bstrRelativeName);
  829. if (FAILED(hr))
  830. {
  831. DebugMsg((DM_WARNING, TEXT("DSDelnode: Failed get relative name with 0x%x"), hr));
  832. goto Exit;
  833. }
  834. hr = pDSObject->get_Class (&bstrClassName);
  835. if (FAILED(hr))
  836. {
  837. DebugMsg((DM_WARNING, TEXT("DSDelnode: Failed get class name with 0x%x"), hr));
  838. goto Exit;
  839. }
  840. pDSObject->Release();
  841. pDSObject = NULL;
  842. //
  843. // Bind to the parent object
  844. //
  845. hr = OpenDSObject(bstrParent, IID_IADsContainer, (void **)&pADsContainer);
  846. if (FAILED(hr)) {
  847. DebugMsg((DM_WARNING, TEXT("DSDelnode: Failed to get parent container interface with 0x%x"), hr));
  848. goto Exit;
  849. }
  850. //
  851. // Delete the object
  852. //
  853. hr = pADsContainer->Delete (bstrClassName,
  854. bstrRelativeName);
  855. if (FAILED(hr))
  856. {
  857. DebugMsg((DM_WARNING, TEXT("DSDelnode: Failed to delete object with 0x%x"), hr));
  858. goto Exit;
  859. }
  860. Exit:
  861. if (pADsContainer)
  862. {
  863. pADsContainer->Release();
  864. }
  865. if (pDSObject)
  866. {
  867. pDSObject->Release();
  868. }
  869. if (bstrParent)
  870. {
  871. SysFreeString (bstrParent);
  872. }
  873. if (bstrRelativeName)
  874. {
  875. SysFreeString (bstrRelativeName);
  876. }
  877. if (bstrClassName)
  878. {
  879. SysFreeString (bstrClassName);
  880. }
  881. return hr;
  882. }
  883. //+--------------------------------------------------------------------------
  884. //
  885. // Function: CreateGPOLink
  886. //
  887. // Synopsis: Creates a GPO link for a domain, site or OU
  888. //
  889. // Arguments: [lpGPO] - LDAP path to the GPO
  890. // [lpContainer] - LDAP path to the container object
  891. // [fHighPriority] - FALSE (default) - adds GPO to the bottom
  892. // of the prioritized list
  893. // TRUE - adds GPO to the top of the list
  894. //
  895. // Returns: S_OK on success
  896. //
  897. // History: 5-08-1998 stevebl Created
  898. //
  899. //---------------------------------------------------------------------------
  900. HRESULT CreateGPOLink(LPOLESTR lpGPO, LPOLESTR lpContainer, BOOL fHighPriority)
  901. {
  902. IADs * pADs = NULL;
  903. LPTSTR lpNamelessGPO;
  904. HRESULT hr;
  905. lpNamelessGPO = MakeNamelessPath (lpGPO);
  906. if (lpNamelessGPO)
  907. {
  908. hr = OpenDSObject(lpContainer, IID_IADs, (void **)&pADs);
  909. if (SUCCEEDED(hr))
  910. {
  911. VARIANT var;
  912. BSTR bstr = NULL;
  913. LPOLESTR szLink = new OLECHAR[1 + wcslen(lpNamelessGPO) + 3 + 1];
  914. if (szLink)
  915. {
  916. wcscpy(szLink, L"[");
  917. wcscat(szLink, lpNamelessGPO);
  918. wcscat(szLink, L";0]");
  919. VariantInit(&var);
  920. bstr = SysAllocString(GPM_LINK_PROPERTY);
  921. if (bstr)
  922. {
  923. hr = pADs->Get(bstr, &var);
  924. if (SUCCEEDED(hr))
  925. {
  926. LPOLESTR szTemp = new OLECHAR[wcslen(var.bstrVal) + wcslen(szLink) + 1];
  927. if (szTemp)
  928. {
  929. if (fHighPriority)
  930. {
  931. // Highest priority is at the END of the list
  932. wcscpy(szTemp, var.bstrVal);
  933. wcscat(szTemp, szLink);
  934. }
  935. else
  936. {
  937. wcscpy(szTemp, szLink);
  938. wcscat(szTemp, var.bstrVal);
  939. }
  940. delete [] szLink;
  941. szLink = szTemp;
  942. }
  943. else
  944. {
  945. hr = ERROR_OUTOFMEMORY;
  946. goto Cleanup;
  947. }
  948. }
  949. else
  950. {
  951. if (hr != E_ADS_PROPERTY_NOT_FOUND)
  952. {
  953. goto Cleanup;
  954. }
  955. }
  956. }
  957. else
  958. {
  959. hr = ERROR_OUTOFMEMORY;
  960. goto Cleanup;
  961. }
  962. VariantClear(&var);
  963. VariantInit(&var);
  964. var.vt = VT_BSTR;
  965. var.bstrVal = SysAllocString(szLink);
  966. if (var.bstrVal)
  967. {
  968. hr = pADs->Put(bstr, var);
  969. if (SUCCEEDED(hr))
  970. {
  971. hr = pADs->SetInfo();
  972. }
  973. }
  974. else
  975. {
  976. hr = ERROR_OUTOFMEMORY;
  977. }
  978. Cleanup:
  979. VariantClear(&var);
  980. if (bstr)
  981. {
  982. SysFreeString(bstr);
  983. }
  984. delete [] szLink;
  985. }
  986. else
  987. hr = ERROR_OUTOFMEMORY;
  988. pADs->Release();
  989. }
  990. LocalFree (lpNamelessGPO);
  991. }
  992. else
  993. {
  994. hr = ERROR_OUTOFMEMORY;
  995. }
  996. return hr;
  997. }
  998. //+--------------------------------------------------------------------------
  999. //
  1000. // Function: DeleteAllGPOLinks
  1001. //
  1002. // Synopsis: Deletes all GPO links for a domain, OU or site
  1003. //
  1004. // Arguments: [lpContainer] - LDAP to the container object
  1005. //
  1006. // Returns: S_OK on success
  1007. //
  1008. // History: 5-08-1998 stevebl Created
  1009. //
  1010. //---------------------------------------------------------------------------
  1011. HRESULT DeleteAllGPOLinks(LPOLESTR lpContainer)
  1012. {
  1013. IADs * pADs = NULL;
  1014. HRESULT hr = OpenDSObject(lpContainer, IID_IADs, (void **)&pADs);
  1015. if (SUCCEEDED(hr))
  1016. {
  1017. VARIANT var;
  1018. BSTR bstr;
  1019. bstr = SysAllocString(GPM_LINK_PROPERTY);
  1020. if (bstr)
  1021. {
  1022. VariantInit(&var);
  1023. var.vt = VT_BSTR;
  1024. var.bstrVal = SysAllocString(L" ");
  1025. if (var.bstrVal)
  1026. {
  1027. hr = pADs->Put(bstr, var);
  1028. if (SUCCEEDED(hr))
  1029. {
  1030. pADs->SetInfo();
  1031. }
  1032. }
  1033. else
  1034. {
  1035. hr = ERROR_OUTOFMEMORY;
  1036. }
  1037. VariantClear(&var);
  1038. SysFreeString(bstr);
  1039. }
  1040. else
  1041. {
  1042. hr = ERROR_OUTOFMEMORY;
  1043. }
  1044. pADs->Release();
  1045. }
  1046. return hr;
  1047. }
  1048. //+--------------------------------------------------------------------------
  1049. //
  1050. // Function: DeleteGPOLink
  1051. //
  1052. // Synopsis: Deletes a GPO link from a domain, OU or site
  1053. // (if there is one).
  1054. //
  1055. // Arguments: [lpGPO] - LDAP to the GPO
  1056. // [lpContainer] - LDAP to the container object
  1057. //
  1058. // Returns: S_OK - success
  1059. //
  1060. // History: 5-08-1998 stevebl Created
  1061. //
  1062. // Notes: If a GPO is linked more than once, this will remove
  1063. // only the first link.
  1064. //
  1065. // If a GPO is NOT linked with this object, then this
  1066. // routine will still return S_OK.
  1067. //
  1068. //---------------------------------------------------------------------------
  1069. HRESULT DeleteGPOLink(LPOLESTR lpGPO, LPOLESTR lpContainer)
  1070. {
  1071. IADs * pADs = NULL;
  1072. HRESULT hr = OpenDSObject(lpContainer, IID_IADs, (void **)&pADs);
  1073. if (SUCCEEDED(hr))
  1074. {
  1075. VARIANT var;
  1076. BSTR bstr;
  1077. // Build the substring to look for.
  1078. // This is the first part of the link, the link ends with ]
  1079. LPOLESTR szLink = new OLECHAR[1 + wcslen(lpGPO) + 1];
  1080. if (szLink)
  1081. {
  1082. wcscpy(szLink, L"[");
  1083. wcscat(szLink, lpGPO);
  1084. bstr = SysAllocString(GPM_LINK_PROPERTY);
  1085. if (bstr)
  1086. {
  1087. VariantInit(&var);
  1088. hr = pADs->Get(bstr, &var);
  1089. if (SUCCEEDED(hr))
  1090. {
  1091. // find the link and remove it
  1092. LPOLESTR sz = new OLECHAR[wcslen(var.bstrVal)+1];
  1093. if (sz)
  1094. {
  1095. wcscpy(sz, var.bstrVal);
  1096. OLECHAR * pch = wcsstr(sz, szLink);
  1097. if (pch)
  1098. {
  1099. OLECHAR * pchEnd = pch;
  1100. // look for the ']'
  1101. while (*pchEnd && (*pchEnd != L']'))
  1102. pchEnd++;
  1103. // skip it
  1104. if (*pchEnd)
  1105. pchEnd++;
  1106. // copy over the rest of the string
  1107. while (*pchEnd)
  1108. *pch++ = *pchEnd++;
  1109. *pch = L'\0';
  1110. VariantClear(&var);
  1111. VariantInit(&var);
  1112. var.vt = VT_BSTR;
  1113. if (wcslen(sz))
  1114. {
  1115. var.bstrVal = SysAllocString(sz);
  1116. }
  1117. else
  1118. {
  1119. // Put will gag if this is an empty string
  1120. // so we need to put a space here if we've
  1121. // deleted all the entries.
  1122. var.bstrVal = SysAllocString(L" ");
  1123. }
  1124. if (var.bstrVal)
  1125. {
  1126. // set the link property again
  1127. hr = pADs->Put(bstr, var);
  1128. if (SUCCEEDED(hr))
  1129. {
  1130. hr = pADs->SetInfo();
  1131. }
  1132. }
  1133. else
  1134. {
  1135. hr = ERROR_OUTOFMEMORY;
  1136. }
  1137. }
  1138. delete [] sz;
  1139. }
  1140. else
  1141. {
  1142. hr = ERROR_OUTOFMEMORY;
  1143. }
  1144. }
  1145. VariantClear(&var);
  1146. SysFreeString(bstr);
  1147. }
  1148. else
  1149. {
  1150. hr = ERROR_OUTOFMEMORY;
  1151. }
  1152. delete [] szLink;
  1153. }
  1154. else
  1155. hr = ERROR_OUTOFMEMORY;
  1156. pADs->Release();
  1157. }
  1158. return hr;
  1159. }
  1160. //*************************************************************
  1161. //
  1162. // CreateSecureDirectory()
  1163. //
  1164. // Purpose: Creates a secure directory that only domain admins
  1165. // and the OS have read / write access. Everyone else has
  1166. // read access only.
  1167. //
  1168. // Parameters: lpDirectory - Directory name
  1169. //
  1170. // Return: > 0 if successful
  1171. // 0 if an error occurs
  1172. //
  1173. // Comments:
  1174. //
  1175. // History: Date Author Comment
  1176. // 5/28/98 ericflo Created
  1177. //
  1178. //*************************************************************
  1179. UINT CreateSecureDirectory (LPTSTR lpDirectory)
  1180. {
  1181. SECURITY_DESCRIPTOR sd;
  1182. SECURITY_ATTRIBUTES sa;
  1183. SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  1184. PACL pAcl = NULL;
  1185. PSID psidSystem = NULL, psidAdmin = NULL, psidAuthUsers = NULL;
  1186. DWORD cbAcl, aceIndex;
  1187. ACE_HEADER * lpAceHeader;
  1188. UINT uRet = 0;
  1189. //
  1190. // Get the system sid
  1191. //
  1192. if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
  1193. 0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
  1194. DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to initialize system sid. Error = %d"), GetLastError()));
  1195. goto Exit;
  1196. }
  1197. //
  1198. // Get the Admin sid
  1199. //
  1200. if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  1201. DOMAIN_ALIAS_RID_ADMINS, 0, 0,
  1202. 0, 0, 0, 0, &psidAdmin)) {
  1203. DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to initialize admin sid. Error = %d"), GetLastError()));
  1204. goto Exit;
  1205. }
  1206. //
  1207. // Get the authenticated users sid
  1208. //
  1209. if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_AUTHENTICATED_USER_RID,
  1210. 0, 0, 0, 0, 0, 0, 0, &psidAuthUsers)) {
  1211. DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to initialize world sid. Error = %d"), GetLastError()));
  1212. goto Exit;
  1213. }
  1214. //
  1215. // Allocate space for the ACL
  1216. //
  1217. cbAcl = (2 * GetLengthSid (psidAuthUsers)) + (2 * GetLengthSid (psidSystem)) +
  1218. (2 * GetLengthSid (psidAdmin)) + sizeof(ACL) +
  1219. (6 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  1220. pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
  1221. if (!pAcl) {
  1222. goto Exit;
  1223. }
  1224. if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
  1225. DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to initialize acl. Error = %d"), GetLastError()));
  1226. goto Exit;
  1227. }
  1228. //
  1229. // Add Aces. Non-inheritable ACEs first
  1230. //
  1231. aceIndex = 0;
  1232. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidSystem)) {
  1233. DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
  1234. goto Exit;
  1235. }
  1236. aceIndex++;
  1237. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidAdmin)) {
  1238. DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
  1239. goto Exit;
  1240. }
  1241. aceIndex++;
  1242. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_READ | GENERIC_EXECUTE, psidAuthUsers)) {
  1243. DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
  1244. goto Exit;
  1245. }
  1246. //
  1247. // Now the inheritable ACEs
  1248. //
  1249. aceIndex++;
  1250. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) {
  1251. DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
  1252. goto Exit;
  1253. }
  1254. if (!GetAce(pAcl, aceIndex, (LPVOID *)&lpAceHeader)) {
  1255. DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to get ace (%d). Error = %d"), aceIndex, GetLastError()));
  1256. goto Exit;
  1257. }
  1258. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  1259. aceIndex++;
  1260. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) {
  1261. DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
  1262. goto Exit;
  1263. }
  1264. if (!GetAce(pAcl, aceIndex, (LPVOID *)&lpAceHeader)) {
  1265. DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to get ace (%d). Error = %d"), aceIndex, GetLastError()));
  1266. goto Exit;
  1267. }
  1268. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  1269. aceIndex++;
  1270. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_READ | GENERIC_EXECUTE, psidAuthUsers)) {
  1271. DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
  1272. goto Exit;
  1273. }
  1274. if (!GetAce(pAcl, aceIndex, (LPVOID *)&lpAceHeader)) {
  1275. DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to get ace (%d). Error = %d"), aceIndex, GetLastError()));
  1276. goto Exit;
  1277. }
  1278. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  1279. //
  1280. // Put together the security descriptor
  1281. //
  1282. if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
  1283. DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to initialize security descriptor. Error = %d"), GetLastError()));
  1284. goto Exit;
  1285. }
  1286. if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
  1287. DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to set security descriptor dacl. Error = %d"), GetLastError()));
  1288. goto Exit;
  1289. }
  1290. //
  1291. // Add the security descriptor to the sa structure
  1292. //
  1293. sa.nLength = sizeof(sa);
  1294. sa.lpSecurityDescriptor = &sd;
  1295. sa.bInheritHandle = FALSE;
  1296. //
  1297. // Attempt to create the directory
  1298. //
  1299. uRet = CreateNestedDirectory(lpDirectory, &sa);
  1300. if ( uRet ) {
  1301. DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Created the directory <%s>"), lpDirectory));
  1302. } else {
  1303. DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to created the directory <%s>"), lpDirectory));
  1304. }
  1305. Exit:
  1306. if (psidSystem) {
  1307. FreeSid(psidSystem);
  1308. }
  1309. if (psidAdmin) {
  1310. FreeSid(psidAdmin);
  1311. }
  1312. if (psidAuthUsers) {
  1313. FreeSid(psidAuthUsers);
  1314. }
  1315. if (pAcl) {
  1316. GlobalFree (pAcl);
  1317. }
  1318. return uRet;
  1319. }
  1320. //*************************************************************
  1321. //
  1322. // ConvertToDotStyle()
  1323. //
  1324. // Purpose: Converts an LDAP path to a DN path
  1325. //
  1326. // Parameters: lpName - LDAP name
  1327. // lpResult - pointer to a buffer with the DN name
  1328. //
  1329. // Return: TRUE if successful
  1330. // FALSE if an error occurs
  1331. //
  1332. //*************************************************************
  1333. HRESULT ConvertToDotStyle (LPOLESTR lpName, LPOLESTR *lpResult)
  1334. {
  1335. LPTSTR lpNewName;
  1336. LPTSTR lpSrc, lpDest;
  1337. TCHAR lpProvider[] = TEXT("LDAP://");
  1338. DWORD dwStrLen = lstrlen (lpProvider);
  1339. lpNewName = (LPTSTR) LocalAlloc (LPTR, (lstrlen(lpName) + 1) * sizeof(TCHAR));
  1340. if (!lpNewName)
  1341. {
  1342. DebugMsg((DM_WARNING, TEXT("ConvertToDotStyle: Failed to allocate memory with 0x%x"),
  1343. GetLastError()));
  1344. return E_FAIL;
  1345. }
  1346. lpSrc = lpName;
  1347. lpDest = lpNewName;
  1348. LPTSTR lpStopChecking = (lstrlen(lpSrc) - 2) + lpSrc;
  1349. //
  1350. // Skip the LDAP:// if found
  1351. //
  1352. if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE | NORM_STOP_ON_NULL,
  1353. lpProvider, dwStrLen, lpSrc, dwStrLen) == CSTR_EQUAL)
  1354. {
  1355. lpSrc += dwStrLen;
  1356. }
  1357. //
  1358. // Parse through the name replacing all the XX= with .
  1359. // Skip server name (if any)
  1360. //
  1361. BOOL fMightFindServer = TRUE;
  1362. while (*lpSrc)
  1363. {
  1364. if (lpSrc < lpStopChecking)
  1365. {
  1366. if (*(lpSrc+2) == TEXT('='))
  1367. {
  1368. lpSrc += 3;
  1369. // no need to look for a server name any more because we've found an XX= string
  1370. fMightFindServer = FALSE;
  1371. }
  1372. }
  1373. while (*lpSrc && (*lpSrc != TEXT(',')))
  1374. {
  1375. *lpDest++ = *lpSrc++;
  1376. if (fMightFindServer && TEXT('/') == *(lpSrc-1))
  1377. {
  1378. // Found a server name
  1379. // reset lpDest so the rest gets put in the front of the buffer (leaving off the server name)
  1380. lpDest = lpNewName;
  1381. break;
  1382. }
  1383. }
  1384. fMightFindServer = FALSE; // don't check any more
  1385. if (*lpSrc == TEXT(','))
  1386. {
  1387. *lpDest++ = TEXT('.');
  1388. lpSrc++;
  1389. }
  1390. }
  1391. *lpDest = 0;
  1392. *lpResult = lpNewName;
  1393. return S_OK;
  1394. }
  1395. //+--------------------------------------------------------------------------
  1396. //
  1397. // Function: GetDomainFromLDAPPath
  1398. //
  1399. // Synopsis: returns a freshly allocated string containing the LDAP path
  1400. // to the domain name contained with an arbitrary LDAP path.
  1401. //
  1402. // Arguments: [szIn] - LDAP path to the initial object
  1403. //
  1404. // Returns: NULL - if no domain could be found or if OOM
  1405. //
  1406. // History: 5-06-1998 stevebl Created
  1407. // 10-20-1998 stevebl modified to preserve server names
  1408. //
  1409. // Notes: This routine works by repeatedly removing leaf elements from
  1410. // the LDAP path until an element with the "DC=" prefix is
  1411. // found, indicating that a domain name has been located. If a
  1412. // path is given that is not rooted in a domain (is that even
  1413. // possible?) then NULL would be returned.
  1414. //
  1415. // The caller must free this path using the standard c++ delete
  1416. // operation. (I/E this isn't an exportable function.)
  1417. //
  1418. //---------------------------------------------------------------------------
  1419. LPOLESTR GetDomainFromLDAPPath(LPOLESTR szIn)
  1420. {
  1421. LPOLESTR sz = NULL;
  1422. IADsPathname * pADsPathname = NULL;
  1423. HRESULT hr = CoCreateInstance(CLSID_Pathname,
  1424. NULL,
  1425. CLSCTX_INPROC_SERVER,
  1426. IID_IADsPathname,
  1427. (LPVOID*)&pADsPathname);
  1428. if (SUCCEEDED(hr))
  1429. {
  1430. hr = pADsPathname->Set(szIn, ADS_SETTYPE_FULL);
  1431. if (SUCCEEDED(hr))
  1432. {
  1433. BSTR bstr;
  1434. BOOL fStop = FALSE;
  1435. while (!fStop)
  1436. {
  1437. hr = pADsPathname->Retrieve(ADS_FORMAT_LEAF, &bstr);
  1438. if (SUCCEEDED(hr))
  1439. {
  1440. // keep peeling them off until we find something
  1441. // that is a domain name
  1442. fStop = (0 == _wcsnicmp(L"DC=", bstr, 3));
  1443. SysFreeString(bstr);
  1444. }
  1445. else
  1446. {
  1447. DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to retrieve leaf with 0x%x."), hr));
  1448. }
  1449. if (!fStop)
  1450. {
  1451. hr = pADsPathname->RemoveLeafElement();
  1452. if (FAILED(hr))
  1453. {
  1454. DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to remove leaf with 0x%x."), hr));
  1455. fStop = TRUE;
  1456. }
  1457. }
  1458. }
  1459. hr = pADsPathname->Retrieve(ADS_FORMAT_X500, &bstr);
  1460. if (SUCCEEDED(hr))
  1461. {
  1462. sz = new OLECHAR[wcslen(bstr)+1];
  1463. if (sz)
  1464. {
  1465. wcscpy(sz, bstr);
  1466. }
  1467. SysFreeString(bstr);
  1468. }
  1469. else
  1470. {
  1471. DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to retrieve full path with 0x%x."), hr));
  1472. }
  1473. }
  1474. else
  1475. {
  1476. DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to set pathname with 0x%x."), hr));
  1477. }
  1478. pADsPathname->Release();
  1479. }
  1480. else
  1481. {
  1482. DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to CoCreateInstance for IID_IADsPathname with 0x%x."), hr));
  1483. }
  1484. return sz;
  1485. }
  1486. //+--------------------------------------------------------------------------
  1487. //
  1488. // Function: GetContainerFromLDAPPath
  1489. //
  1490. // Synopsis: returns a the container name from an LDAP path
  1491. //
  1492. // Arguments: [szIn] - LDAP path to the initial object
  1493. //
  1494. // Returns: NULL - if no domain could be found or if OOM
  1495. //
  1496. // History: 3-17-2000 ericflo Created
  1497. //
  1498. // The caller must free this path using the standard c++ delete
  1499. // operation. (I/E this isn't an exportable function.)
  1500. //
  1501. //---------------------------------------------------------------------------
  1502. LPOLESTR GetContainerFromLDAPPath(LPOLESTR szIn)
  1503. {
  1504. LPOLESTR sz = NULL;
  1505. IADsPathname * pADsPathname = NULL;
  1506. HRESULT hr = CoCreateInstance(CLSID_Pathname,
  1507. NULL,
  1508. CLSCTX_INPROC_SERVER,
  1509. IID_IADsPathname,
  1510. (LPVOID*)&pADsPathname);
  1511. if (SUCCEEDED(hr))
  1512. {
  1513. hr = pADsPathname->Set(szIn, ADS_SETTYPE_DN);
  1514. if (SUCCEEDED(hr))
  1515. {
  1516. BSTR bstr;
  1517. BOOL fStop = FALSE;
  1518. hr = pADsPathname->Retrieve(ADS_FORMAT_LEAF, &bstr);
  1519. if (SUCCEEDED(hr))
  1520. {
  1521. sz = new OLECHAR[wcslen(bstr)+1];
  1522. if (sz)
  1523. {
  1524. wcscpy(sz, (bstr+3));
  1525. }
  1526. SysFreeString(bstr);
  1527. }
  1528. else
  1529. {
  1530. DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to retrieve leaf with 0x%x."), hr));
  1531. }
  1532. }
  1533. else
  1534. {
  1535. DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to set pathname with 0x%x."), hr));
  1536. }
  1537. pADsPathname->Release();
  1538. }
  1539. else
  1540. {
  1541. DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to CoCreateInstance for IID_IADsPathname with 0x%x."), hr));
  1542. }
  1543. return sz;
  1544. }
  1545. //*************************************************************
  1546. //
  1547. // DCDlgProc()
  1548. //
  1549. // Purpose: Dialog box procedure for DC selection
  1550. //
  1551. // Parameters:
  1552. //
  1553. //
  1554. // Return: TRUE if successful
  1555. // FALSE if an error occurs
  1556. //
  1557. //*************************************************************
  1558. INT_PTR CALLBACK DCDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1559. {
  1560. switch (message)
  1561. {
  1562. case WM_INITDIALOG:
  1563. {
  1564. TCHAR szTitle[100];
  1565. TCHAR szBuffer[350];
  1566. LPDCSELINFO lpSelInfo = (LPDCSELINFO) lParam;
  1567. HICON hIcon;
  1568. if (lpSelInfo->bError)
  1569. {
  1570. hIcon = LoadIcon (NULL, IDI_ERROR);
  1571. if (hIcon)
  1572. {
  1573. SendDlgItemMessage (hDlg, IDC_NODC_ERROR, STM_SETICON, (WPARAM)hIcon, 0);
  1574. }
  1575. LoadString (g_hInstance, IDS_NODC_ERROR_TEXT, szBuffer, ARRAYSIZE(szBuffer));
  1576. SetDlgItemText (hDlg, IDC_NODC_TEXT, szBuffer);
  1577. LoadString (g_hInstance, IDS_NODC_ERROR_TITLE, szTitle, ARRAYSIZE(szTitle));
  1578. wsprintf (szBuffer, szTitle, lpSelInfo->lpDomainName);
  1579. SetWindowText (hDlg, szBuffer);
  1580. }
  1581. else
  1582. {
  1583. LoadString (g_hInstance, IDS_NODC_OPTIONS_TEXT, szBuffer, ARRAYSIZE(szBuffer));
  1584. SetDlgItemText (hDlg, IDC_NODC_TEXT, szBuffer);
  1585. LoadString (g_hInstance, IDS_NODC_OPTIONS_TITLE, szBuffer, ARRAYSIZE(szBuffer));
  1586. SetWindowText (hDlg, szBuffer);
  1587. }
  1588. if (!lpSelInfo->bAllowInherit)
  1589. {
  1590. EnableWindow (GetDlgItem(hDlg, IDC_NODC_INHERIT), FALSE);
  1591. }
  1592. if (lpSelInfo->iDefault == 2)
  1593. {
  1594. if (lpSelInfo->bAllowInherit)
  1595. {
  1596. CheckDlgButton (hDlg, IDC_NODC_INHERIT, BST_CHECKED);
  1597. }
  1598. else
  1599. {
  1600. CheckDlgButton (hDlg, IDC_NODC_PDC, BST_CHECKED);
  1601. }
  1602. }
  1603. else if (lpSelInfo->iDefault == 3)
  1604. {
  1605. CheckDlgButton (hDlg, IDC_NODC_ANYDC, BST_CHECKED);
  1606. }
  1607. else
  1608. {
  1609. CheckDlgButton (hDlg, IDC_NODC_PDC, BST_CHECKED);
  1610. }
  1611. return TRUE;
  1612. }
  1613. case WM_COMMAND:
  1614. if (LOWORD(wParam) == IDOK)
  1615. {
  1616. if (IsDlgButtonChecked (hDlg, IDC_NODC_PDC) == BST_CHECKED)
  1617. {
  1618. EndDialog(hDlg, 1);
  1619. }
  1620. else if (IsDlgButtonChecked (hDlg, IDC_NODC_INHERIT) == BST_CHECKED)
  1621. {
  1622. EndDialog(hDlg, 2);
  1623. }
  1624. else
  1625. {
  1626. EndDialog(hDlg, 3);
  1627. }
  1628. return TRUE;
  1629. }
  1630. if (LOWORD(wParam) == IDCANCEL)
  1631. {
  1632. EndDialog(hDlg, 0);
  1633. return TRUE;
  1634. }
  1635. break;
  1636. case WM_HELP: // F1
  1637. WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, HELP_FILE, HELP_WM_HELP,
  1638. (ULONG_PTR) (LPSTR) aNoDCHelpIds);
  1639. break;
  1640. case WM_CONTEXTMENU: // right mouse click
  1641. WinHelp((HWND) wParam, HELP_FILE, HELP_CONTEXTMENU,
  1642. (ULONG_PTR) (LPSTR) aNoDCHelpIds);
  1643. return (TRUE);
  1644. }
  1645. return FALSE;
  1646. }
  1647. //*************************************************************
  1648. //
  1649. // AddDCSelection()
  1650. //
  1651. // Purpose: Adds a DC selection to the array
  1652. //
  1653. // Parameters: lpDomainName - Domain name
  1654. // iOption - Option
  1655. //
  1656. //
  1657. // Return: TRUE if successful
  1658. // FALSE if an error occurs
  1659. //
  1660. //*************************************************************
  1661. BOOL AddDCSelection (LPTSTR lpDomainName, INT iOption)
  1662. {
  1663. LPDCOPTION lpTemp;
  1664. UINT uiSize;
  1665. //
  1666. // Check to see if we already have an entry first
  1667. //
  1668. EnterCriticalSection(&g_DCCS);
  1669. lpTemp = g_DCInfo;
  1670. while (lpTemp)
  1671. {
  1672. if (!lstrcmpi(lpDomainName, lpTemp->lpDomainName))
  1673. {
  1674. lpTemp->iOption = iOption;
  1675. LeaveCriticalSection(&g_DCCS);
  1676. return TRUE;
  1677. }
  1678. lpTemp = lpTemp->pNext;
  1679. }
  1680. //
  1681. // Add a new entry
  1682. //
  1683. uiSize = sizeof(DCOPTION);
  1684. uiSize += ((lstrlen(lpDomainName) + 1) * sizeof(TCHAR));
  1685. lpTemp = (LPDCOPTION) LocalAlloc (LPTR, uiSize);
  1686. if (!lpTemp)
  1687. {
  1688. DebugMsg((DM_WARNING, TEXT("AddDCSelection: Failed to allocate memory with %d"),
  1689. GetLastError()));
  1690. LeaveCriticalSection(&g_DCCS);
  1691. return FALSE;
  1692. }
  1693. lpTemp->lpDomainName = (LPTSTR)((LPBYTE) lpTemp + sizeof(DCOPTION));
  1694. lstrcpy (lpTemp->lpDomainName, lpDomainName);
  1695. lpTemp->iOption = iOption;
  1696. if (g_DCInfo)
  1697. {
  1698. lpTemp->pNext = g_DCInfo;
  1699. g_DCInfo = lpTemp;
  1700. }
  1701. else
  1702. {
  1703. g_DCInfo = lpTemp;
  1704. }
  1705. LeaveCriticalSection(&g_DCCS);
  1706. return TRUE;
  1707. }
  1708. //*************************************************************
  1709. //
  1710. // FreeDCSelections()
  1711. //
  1712. // Purpose: Frees the cached DC selections
  1713. //
  1714. // Parameters: none
  1715. //
  1716. //
  1717. // Return: TRUE if successful
  1718. // FALSE if an error occurs
  1719. //
  1720. //*************************************************************
  1721. VOID FreeDCSelections (void)
  1722. {
  1723. LPDCOPTION lpTemp, lpNext;
  1724. EnterCriticalSection(&g_DCCS);
  1725. lpTemp = g_DCInfo;
  1726. while (lpTemp)
  1727. {
  1728. lpNext = lpTemp->pNext;
  1729. LocalFree (lpTemp);
  1730. lpTemp = lpNext;
  1731. }
  1732. g_DCInfo = NULL;
  1733. LeaveCriticalSection(&g_DCCS);
  1734. }
  1735. //*************************************************************
  1736. //
  1737. // CheckForCachedDCSelection()
  1738. //
  1739. // Purpose: Checks if the DC selection for this domain is in
  1740. // the cache
  1741. //
  1742. // Parameters: lpDomainName - Domain name
  1743. //
  1744. //
  1745. // Return: TRUE if successful
  1746. // FALSE if an error occurs
  1747. //
  1748. //*************************************************************
  1749. INT CheckForCachedDCSelection (LPTSTR lpDomainName)
  1750. {
  1751. INT iResult = 0;
  1752. LPDCOPTION lpTemp;
  1753. EnterCriticalSection(&g_DCCS);
  1754. lpTemp = g_DCInfo;
  1755. while (lpTemp)
  1756. {
  1757. if (!lstrcmpi(lpDomainName, lpTemp->lpDomainName))
  1758. {
  1759. iResult = lpTemp->iOption;
  1760. break;
  1761. }
  1762. lpTemp = lpTemp->pNext;
  1763. }
  1764. LeaveCriticalSection(&g_DCCS);
  1765. return iResult;
  1766. }
  1767. //*************************************************************
  1768. //
  1769. // ValidateInheritServer()
  1770. //
  1771. // Purpose: Tests if the given DC name is in the given domain
  1772. //
  1773. // Parameters: lpDomainName -- Domain name
  1774. // lpDCName -- Domain controller name
  1775. //
  1776. //
  1777. // Return: ERROR_SUCCESS if successful
  1778. // Error code otherwise
  1779. //
  1780. //*************************************************************
  1781. DWORD ValidateInheritServer (LPTSTR lpDomainName, LPTSTR lpDCName)
  1782. {
  1783. PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pBasic;
  1784. DWORD dwResult;
  1785. dwResult = DsRoleGetPrimaryDomainInformation (lpDCName, DsRolePrimaryDomainInfoBasic,
  1786. (LPBYTE *) &pBasic);
  1787. if (dwResult == ERROR_SUCCESS) {
  1788. if (lstrcmpi(lpDomainName, pBasic->DomainNameDns))
  1789. {
  1790. dwResult = ERROR_NO_SUCH_DOMAIN;
  1791. DebugMsg((DM_VERBOSE, TEXT("ValidateInheritServer: DC %s is not part of domain %s, it is part of %s. This server will not be used for inheritance."),
  1792. lpDCName, lpDomainName, pBasic->DomainNameDns));
  1793. }
  1794. DsRoleFreeMemory (pBasic);
  1795. }
  1796. return dwResult;
  1797. }
  1798. //*************************************************************
  1799. //
  1800. // TestDC()
  1801. //
  1802. // Purpose: Tests if a DC is available
  1803. //
  1804. // Parameters:
  1805. //
  1806. //
  1807. // Return: ERROR_SUCCESS if successful
  1808. // Error code otherwise
  1809. //
  1810. //*************************************************************
  1811. DWORD TestDC (LPTSTR lpDCName)
  1812. {
  1813. LPTSTR lpTest;
  1814. HANDLE hFile;
  1815. WIN32_FIND_DATA fd;
  1816. BOOL bResult = FALSE;
  1817. lpTest = (LPTSTR) LocalAlloc (LPTR, (lstrlen(lpDCName) + 25) * sizeof(TCHAR));
  1818. if (!lpTest)
  1819. {
  1820. DebugMsg((DM_WARNING, TEXT("TestDC: Failed to allocate memory with %d"),
  1821. GetLastError()));
  1822. return GetLastError();
  1823. }
  1824. lstrcpy (lpTest, TEXT("\\\\"));
  1825. lstrcat (lpTest, lpDCName);
  1826. lstrcat (lpTest, TEXT("\\sysvol\\*.*"));
  1827. hFile = FindFirstFile (lpTest, &fd);
  1828. if (hFile == INVALID_HANDLE_VALUE)
  1829. {
  1830. DebugMsg((DM_WARNING, TEXT("TestDC: Failed to access <%s> with %d"),
  1831. lpTest, GetLastError()));
  1832. LocalFree (lpTest);
  1833. return GetLastError();
  1834. }
  1835. FindClose (hFile);
  1836. LocalFree (lpTest);
  1837. return ERROR_SUCCESS;
  1838. }
  1839. //*************************************************************
  1840. //
  1841. // QueryForForestName()
  1842. //
  1843. // Purpose: Queries for a domain controller name
  1844. //
  1845. // Parameters:
  1846. //
  1847. //
  1848. // Return: ERROR_SUCCESS if successful
  1849. // Error code otherwise
  1850. //
  1851. //*************************************************************
  1852. DWORD QueryForForestName (LPTSTR lpServerName, LPTSTR lpDomainName, ULONG ulFlags, LPTSTR *lpForestFound)
  1853. {
  1854. PDOMAIN_CONTROLLER_INFO pDCI;
  1855. DWORD dwResult;
  1856. LPTSTR lpTemp, lpEnd;
  1857. //
  1858. // Call for a DC name
  1859. //
  1860. dwResult = DsGetDcName (lpServerName, lpDomainName, NULL, NULL,
  1861. ulFlags,
  1862. &pDCI);
  1863. if (dwResult != ERROR_SUCCESS)
  1864. {
  1865. DebugMsg((DM_WARNING, TEXT("QueryForForestName: Failed to query <%s> for a DC name with %d"),
  1866. lpDomainName, dwResult));
  1867. return dwResult;
  1868. }
  1869. if (!(pDCI->Flags & DS_DS_FLAG))
  1870. {
  1871. DebugMsg((DM_WARNING, TEXT("QueryForForestName: %s doesn't have Active Directory support (downlevel domain)"),
  1872. lpDomainName));
  1873. NetApiBufferFree(pDCI);
  1874. return ERROR_DS_UNAVAILABLE;
  1875. }
  1876. lpTemp = (LPTSTR) LocalAlloc (LPTR, (lstrlen(pDCI->DnsForestName) + 1) * sizeof(TCHAR));
  1877. if (!lpTemp)
  1878. {
  1879. dwResult = GetLastError();
  1880. DebugMsg((DM_WARNING, TEXT("QueryForForestName: Failed to allocate memory for forest name with %d"),
  1881. dwResult));
  1882. NetApiBufferFree(pDCI);
  1883. return dwResult;
  1884. }
  1885. lstrcpy(lpTemp, pDCI->DnsForestName);
  1886. NetApiBufferFree(pDCI);
  1887. LocalFree(*lpForestFound);
  1888. *lpForestFound = lpTemp;
  1889. return ERROR_SUCCESS;
  1890. }
  1891. //*************************************************************
  1892. //
  1893. // QueryForDCName()
  1894. //
  1895. // Purpose: Queries for a domain controller name
  1896. //
  1897. // Parameters:
  1898. //
  1899. //
  1900. // Return: ERROR_SUCCESS if successful
  1901. // Error code otherwise
  1902. //
  1903. //*************************************************************
  1904. DWORD QueryForDCName (LPTSTR lpDomainName, ULONG ulFlags, LPTSTR *lpDCName)
  1905. {
  1906. PDOMAIN_CONTROLLER_INFO pDCI;
  1907. DWORD dwResult;
  1908. LPTSTR lpTemp, lpEnd;
  1909. //
  1910. // Call for a DC name
  1911. //
  1912. dwResult = DsGetDcName (NULL, lpDomainName, NULL, NULL,
  1913. ulFlags, &pDCI);
  1914. if (dwResult != ERROR_SUCCESS)
  1915. {
  1916. DebugMsg((DM_WARNING, TEXT("QueryForDCName: Failed to query <%s> for a DC name with %d"),
  1917. lpDomainName, dwResult));
  1918. return dwResult;
  1919. }
  1920. if (!(pDCI->Flags & DS_DS_FLAG))
  1921. {
  1922. DebugMsg((DM_WARNING, TEXT("QueryForDCName: %s doesn't not have Active Directory support (downlevel domain)"),
  1923. lpDomainName));
  1924. return ERROR_DS_UNAVAILABLE;
  1925. }
  1926. //
  1927. // Save the DC name
  1928. //
  1929. lpTemp = (LPTSTR) LocalAlloc (LPTR, (lstrlen (pDCI->DomainControllerName) + 1) * sizeof(TCHAR));
  1930. if (!lpTemp)
  1931. {
  1932. dwResult = GetLastError();
  1933. DebugMsg((DM_WARNING, TEXT("QueryForDCName: Failed to allocate memory for DC name with %d"),
  1934. dwResult));
  1935. NetApiBufferFree(pDCI);
  1936. return dwResult;
  1937. }
  1938. lstrcpy (lpTemp, (pDCI->DomainControllerName + 2));
  1939. //
  1940. // Remove the trailing .
  1941. //
  1942. lpEnd = lpTemp + lstrlen(lpTemp) - 1;
  1943. if (*lpEnd == TEXT('.'))
  1944. {
  1945. *lpEnd = TEXT('\0');
  1946. }
  1947. *lpDCName = lpTemp;
  1948. NetApiBufferFree(pDCI);
  1949. return ERROR_SUCCESS;
  1950. }
  1951. //*************************************************************
  1952. //
  1953. // GetDCHelper()
  1954. //
  1955. // Purpose: Queries for a domain controller based upon
  1956. // the flags and then rediscovers if necessary
  1957. //
  1958. // Parameters:
  1959. //
  1960. //
  1961. // Return: TRUE if successful
  1962. // FALSE if an error occurs
  1963. //
  1964. //*************************************************************
  1965. DWORD GetDCHelper (LPTSTR lpDomainName, ULONG ulFlags, LPTSTR *lpDCName)
  1966. {
  1967. DWORD dwError;
  1968. //
  1969. // Query for a DC name
  1970. //
  1971. SetWaitCursor();
  1972. ulFlags |= DS_DIRECTORY_SERVICE_PREFERRED;
  1973. dwError = QueryForDCName (lpDomainName, ulFlags, lpDCName);
  1974. if (dwError == ERROR_SUCCESS)
  1975. {
  1976. //
  1977. // Test if the DC is available
  1978. //
  1979. dwError = TestDC (*lpDCName);
  1980. if (dwError != ERROR_SUCCESS)
  1981. {
  1982. //
  1983. // The DC isn't available. Query for another one
  1984. //
  1985. LocalFree (*lpDCName);
  1986. ulFlags |= DS_FORCE_REDISCOVERY;
  1987. dwError = QueryForDCName (lpDomainName, ulFlags, lpDCName);
  1988. if (dwError == ERROR_SUCCESS)
  1989. {
  1990. //
  1991. // Test if this DC is available
  1992. //
  1993. dwError = TestDC (*lpDCName);
  1994. if (dwError != ERROR_SUCCESS)
  1995. {
  1996. LocalFree (*lpDCName);
  1997. }
  1998. }
  1999. }
  2000. }
  2001. ClearWaitCursor();
  2002. return dwError;
  2003. }
  2004. //*************************************************************
  2005. //
  2006. // GetDCName()
  2007. //
  2008. // Purpose: Gets a domain controller name
  2009. //
  2010. // Parameters: lpDomainName - Domain name
  2011. // lpInheritServer - Inheritable server name
  2012. // hParent - Parent window handle for prompt dialog
  2013. // bAllowUI - Displaying UI is ok
  2014. //
  2015. // Return: TRUE if successful
  2016. // FALSE if an error occurs
  2017. //
  2018. // Notes: DC Option values in the registry
  2019. //
  2020. // Not specified 0
  2021. // PDC 1
  2022. // Inherit 2
  2023. // Any Writable 3
  2024. //
  2025. // Rules for finding a DC:
  2026. // Inherit
  2027. // Preference Policy DC Avail Result
  2028. // ========== ====== ======== ======
  2029. // Undefined Undefined 1) PDC 2) Prompt
  2030. // PDC Undefined 1) PDC 2) Prompt
  2031. // Inherit Undefined Yes Inhert
  2032. // Inherit Undefined No Any DC
  2033. // Any Undefined Any DC
  2034. //
  2035. // n/a PDC PDC only
  2036. // n/a Inherit Yes Inhert
  2037. // n/a Inherit No Any DC
  2038. // n/a Any Any DC
  2039. //
  2040. //
  2041. //*************************************************************
  2042. LPTSTR GetDCName (LPTSTR lpDomainName, LPTSTR lpInheritServer,
  2043. HWND hParent, BOOL bAllowUI, DWORD dwFlags, ULONG ulRetFlags)
  2044. {
  2045. LPTSTR lpDCName;
  2046. ULONG ulFlags;
  2047. DWORD dwDCPref = 1;
  2048. DWORD dwDCPolicy = 0;
  2049. HKEY hKey;
  2050. DWORD dwSize, dwType, dwError;
  2051. dwError = ERROR_SUCCESS;
  2052. DCSELINFO SelInfo;
  2053. INT iResult;
  2054. ulFlags = ulRetFlags;
  2055. DebugMsg((DM_VERBOSE, TEXT("GetDCName: Entering for: %s"), lpDomainName));
  2056. DebugMsg((DM_VERBOSE, TEXT("GetDCName: lpInheritServer is: %s"), lpInheritServer));
  2057. if (-1 == CheckForCachedDCSelection (lpDomainName))
  2058. {
  2059. DebugMsg((DM_VERBOSE, TEXT("GetDCName: Known dead domain. Exiting.")));
  2060. return NULL;
  2061. }
  2062. //
  2063. // Check for a user DC preference
  2064. //
  2065. if (RegOpenKeyEx (HKEY_CURRENT_USER, GPE_KEY, 0,
  2066. KEY_READ, &hKey) == ERROR_SUCCESS)
  2067. {
  2068. dwSize = sizeof(dwDCPref);
  2069. RegQueryValueEx (hKey, DCOPTION_VALUE, NULL, &dwType,
  2070. (LPBYTE) &dwDCPref, &dwSize);
  2071. if (dwDCPref > 3)
  2072. {
  2073. dwDCPref = 1;
  2074. }
  2075. RegCloseKey (hKey);
  2076. }
  2077. //
  2078. // Check for a user DC policy
  2079. //
  2080. if (RegOpenKeyEx (HKEY_CURRENT_USER, GPE_POLICIES_KEY, 0,
  2081. KEY_READ, &hKey) == ERROR_SUCCESS)
  2082. {
  2083. dwSize = sizeof(dwDCPolicy);
  2084. RegQueryValueEx (hKey, DCOPTION_VALUE, NULL, &dwType,
  2085. (LPBYTE) &dwDCPolicy, &dwSize);
  2086. if (dwDCPolicy > 3)
  2087. {
  2088. dwDCPolicy = 1;
  2089. }
  2090. RegCloseKey (hKey);
  2091. }
  2092. DebugMsg((DM_VERBOSE, TEXT("GetDCName: User preference is: %d"), dwDCPref));
  2093. DebugMsg((DM_VERBOSE, TEXT("GetDCName: User policy is: %d"), dwDCPolicy));
  2094. //
  2095. // Validate that the inherit DC name is part of the domain name
  2096. //
  2097. if (lpInheritServer && (dwFlags & VALIDATE_INHERIT_DC))
  2098. {
  2099. if (ValidateInheritServer (lpDomainName, lpInheritServer) != ERROR_SUCCESS)
  2100. {
  2101. lpInheritServer = NULL;
  2102. }
  2103. }
  2104. //
  2105. // Based upon the rules, try to get a DC name
  2106. //
  2107. if (dwDCPolicy == 0)
  2108. {
  2109. //
  2110. // The user doesn't have a preference or they have
  2111. // a preference of using the PDC
  2112. //
  2113. if ((dwDCPref == 0) || (dwDCPref == 1))
  2114. {
  2115. ulFlags = DS_PDC_REQUIRED | ulRetFlags;
  2116. dwError = GetDCHelper (lpDomainName, ulFlags, &lpDCName);
  2117. if (dwError == ERROR_SUCCESS)
  2118. {
  2119. DebugMsg((DM_VERBOSE, TEXT("GetDCName: Domain controller is: %s"), lpDCName));
  2120. return lpDCName;
  2121. }
  2122. }
  2123. //
  2124. // The user has a preference of inheriting
  2125. //
  2126. else if (dwDCPref == 2)
  2127. {
  2128. if (lpInheritServer)
  2129. {
  2130. lpDCName = (LPTSTR) LocalAlloc (LPTR, (lstrlen (lpInheritServer) + 1) * sizeof(TCHAR));
  2131. if (!lpDCName)
  2132. {
  2133. DebugMsg((DM_WARNING, TEXT("GetDCName: Failed to allocate memory for DC name with %d"),
  2134. GetLastError()));
  2135. return NULL;
  2136. }
  2137. lstrcpy (lpDCName, lpInheritServer);
  2138. dwError = TestDC (lpDCName);
  2139. if (dwError == ERROR_SUCCESS)
  2140. {
  2141. DebugMsg((DM_VERBOSE, TEXT("GetDCName: Domain controller is: %s"), lpDCName));
  2142. return lpDCName;
  2143. }
  2144. LocalFree (lpDCName);
  2145. }
  2146. else
  2147. {
  2148. ulFlags = ulRetFlags;
  2149. dwError = GetDCHelper (lpDomainName, ulFlags, &lpDCName);
  2150. if (dwError == ERROR_SUCCESS)
  2151. {
  2152. DebugMsg((DM_VERBOSE, TEXT("GetDCName: Domain controller is: %s"), lpDCName));
  2153. return lpDCName;
  2154. }
  2155. }
  2156. }
  2157. //
  2158. // The user has a preference of using any DC
  2159. //
  2160. else if (dwDCPref == 3)
  2161. {
  2162. ulFlags = ulRetFlags;
  2163. dwError = GetDCHelper (lpDomainName, ulFlags, &lpDCName);
  2164. if (dwError == ERROR_SUCCESS)
  2165. {
  2166. DebugMsg((DM_VERBOSE, TEXT("GetDCName: Domain controller is: %s"), lpDCName));
  2167. return lpDCName;
  2168. }
  2169. }
  2170. }
  2171. else
  2172. {
  2173. //
  2174. // Policy says to use PDC
  2175. //
  2176. if (dwDCPolicy == 1)
  2177. {
  2178. ulFlags = DS_PDC_REQUIRED | ulRetFlags;
  2179. dwError = GetDCHelper (lpDomainName, ulFlags, &lpDCName);
  2180. if (dwError == ERROR_SUCCESS)
  2181. {
  2182. DebugMsg((DM_VERBOSE, TEXT("GetDCName: Domain controller is: %s"), lpDCName));
  2183. return lpDCName;
  2184. }
  2185. }
  2186. //
  2187. // Policy says to inherit
  2188. //
  2189. else if (dwDCPolicy == 2)
  2190. {
  2191. if (lpInheritServer)
  2192. {
  2193. lpDCName = (LPTSTR) LocalAlloc (LPTR, (lstrlen (lpInheritServer) + 1) * sizeof(TCHAR));
  2194. if (!lpDCName)
  2195. {
  2196. DebugMsg((DM_WARNING, TEXT("GetDCName: Failed to allocate memory for DC name with %d"),
  2197. GetLastError()));
  2198. return NULL;
  2199. }
  2200. lstrcpy (lpDCName, lpInheritServer);
  2201. dwError = TestDC (lpDCName);
  2202. if (dwError == ERROR_SUCCESS)
  2203. {
  2204. DebugMsg((DM_VERBOSE, TEXT("GetDCName: Domain controller is: %s"), lpDCName));
  2205. return lpDCName;
  2206. }
  2207. LocalFree (lpDCName);
  2208. }
  2209. else
  2210. {
  2211. ulFlags = ulRetFlags;
  2212. dwError = GetDCHelper (lpDomainName, ulFlags, &lpDCName);
  2213. if (dwError == ERROR_SUCCESS)
  2214. {
  2215. DebugMsg((DM_VERBOSE, TEXT("GetDCName: Domain controller is: %s"), lpDCName));
  2216. return lpDCName;
  2217. }
  2218. }
  2219. }
  2220. //
  2221. // Policy says to use any DC
  2222. //
  2223. else if (dwDCPolicy == 3)
  2224. {
  2225. ulFlags = ulRetFlags;
  2226. dwError = GetDCHelper (lpDomainName, ulFlags, &lpDCName);
  2227. if (dwError == ERROR_SUCCESS)
  2228. {
  2229. DebugMsg((DM_VERBOSE, TEXT("GetDCName: Domain controller is: %s"), lpDCName));
  2230. return lpDCName;
  2231. }
  2232. }
  2233. }
  2234. DebugMsg((DM_VERBOSE, TEXT("GetDCName: First attempt at DC name failed with %d"), dwError));
  2235. //
  2236. // The first attempt at getting a DC name failed
  2237. //
  2238. // In 2 cases, we will prompt the user for what to do and try again.
  2239. //
  2240. if (bAllowUI && (dwError != ERROR_DS_UNAVAILABLE) && (dwDCPolicy == 0) && ((dwDCPref == 0) || (dwDCPref == 1)))
  2241. {
  2242. iResult = CheckForCachedDCSelection (lpDomainName);
  2243. if (iResult == 0)
  2244. {
  2245. //
  2246. // Display the message
  2247. //
  2248. SelInfo.bError = TRUE;
  2249. SelInfo.bAllowInherit = (lpInheritServer != NULL) ? TRUE : FALSE;
  2250. SelInfo.iDefault = 1;
  2251. SelInfo.lpDomainName = lpDomainName;
  2252. iResult = (INT)DialogBoxParam (g_hInstance, MAKEINTRESOURCE(IDD_NODC), hParent,
  2253. DCDlgProc, (LPARAM) &SelInfo);
  2254. }
  2255. //
  2256. // Based upon the return value, try for another DC
  2257. //
  2258. if (iResult == 1)
  2259. {
  2260. ulFlags = DS_PDC_REQUIRED | ulRetFlags;
  2261. dwError = GetDCHelper (lpDomainName, ulFlags, &lpDCName);
  2262. if (dwError == ERROR_SUCCESS)
  2263. {
  2264. DebugMsg((DM_VERBOSE, TEXT("GetDCName: Domain controller is: %s"), lpDCName));
  2265. AddDCSelection (lpDomainName, iResult);
  2266. return lpDCName;
  2267. }
  2268. else
  2269. {
  2270. AddDCSelection (lpDomainName, -1);
  2271. }
  2272. }
  2273. else if (iResult == 2)
  2274. {
  2275. lpDCName = (LPTSTR) LocalAlloc (LPTR, (lstrlen (lpInheritServer) + 1) * sizeof(TCHAR));
  2276. if (!lpDCName)
  2277. {
  2278. DebugMsg((DM_WARNING, TEXT("GetDCName: Failed to allocate memory for DC name with %d"),
  2279. GetLastError()));
  2280. return NULL;
  2281. }
  2282. lstrcpy (lpDCName, lpInheritServer);
  2283. dwError = TestDC (lpDCName);
  2284. if (dwError == ERROR_SUCCESS)
  2285. {
  2286. DebugMsg((DM_VERBOSE, TEXT("GetDCName: Domain controller is: %s"), lpDCName));
  2287. AddDCSelection (lpDomainName, iResult);
  2288. return lpDCName;
  2289. }
  2290. else
  2291. {
  2292. AddDCSelection (lpDomainName, -1);
  2293. }
  2294. LocalFree (lpDCName);
  2295. }
  2296. else if (iResult == 3)
  2297. {
  2298. ulFlags = 0 | ulRetFlags;
  2299. dwError = GetDCHelper (lpDomainName, ulFlags, &lpDCName);
  2300. if (dwError == ERROR_SUCCESS)
  2301. {
  2302. DebugMsg((DM_VERBOSE, TEXT("GetDCName: Domain controller is: %s"), lpDCName));
  2303. AddDCSelection (lpDomainName, iResult);
  2304. return lpDCName;
  2305. }
  2306. else
  2307. {
  2308. AddDCSelection (lpDomainName, -1);
  2309. }
  2310. }
  2311. else
  2312. {
  2313. DebugMsg((DM_VERBOSE, TEXT("GetDCName: User cancelled the dialog box")));
  2314. return NULL;
  2315. }
  2316. }
  2317. DebugMsg((DM_WARNING, TEXT("GetDCName: Failed to find a domain controller")));
  2318. if (bAllowUI)
  2319. {
  2320. if (dwError == ERROR_DS_UNAVAILABLE)
  2321. {
  2322. ReportError(NULL, dwError, IDS_NODSDC, lpDomainName);
  2323. }
  2324. else
  2325. {
  2326. ReportError(NULL, dwError, IDS_NODC);
  2327. }
  2328. }
  2329. SetLastError(dwError);
  2330. return NULL;
  2331. }
  2332. //*************************************************************
  2333. //
  2334. // MyGetUserName()
  2335. //
  2336. // Purpose: Gets the user name in the requested format
  2337. //
  2338. // Parameters: NameFormat - GetUserNameEx naming format
  2339. //
  2340. // Return: lpUserName if successful
  2341. // NULL if an error occurs
  2342. //
  2343. //*************************************************************
  2344. LPTSTR MyGetUserName (EXTENDED_NAME_FORMAT NameFormat)
  2345. {
  2346. DWORD dwError = ERROR_SUCCESS;
  2347. LPTSTR lpUserName = NULL, lpTemp;
  2348. ULONG ulUserNameSize;
  2349. //
  2350. // Allocate a buffer for the user name
  2351. //
  2352. ulUserNameSize = 75;
  2353. if (NameFormat == NameFullyQualifiedDN) {
  2354. ulUserNameSize = 200;
  2355. }
  2356. lpUserName = (LPTSTR) LocalAlloc (LPTR, ulUserNameSize * sizeof(TCHAR));
  2357. if (!lpUserName) {
  2358. dwError = GetLastError();
  2359. DebugMsg((DM_WARNING, TEXT("MyGetUserName: Failed to allocate memory with %d"),
  2360. dwError));
  2361. goto Exit;
  2362. }
  2363. //
  2364. // Special case NameUnknown to just get the simple user logon name
  2365. //
  2366. if (NameFormat == NameUnknown)
  2367. {
  2368. if (!GetUserName (lpUserName, &ulUserNameSize))
  2369. {
  2370. dwError = GetLastError();
  2371. DebugMsg((DM_WARNING, TEXT("MyGetUserName: GetUserName failed with %d"),
  2372. dwError));
  2373. LocalFree (lpUserName);
  2374. lpUserName = NULL;
  2375. }
  2376. goto Exit;
  2377. }
  2378. //
  2379. // Get the username in the requested format
  2380. //
  2381. if (!GetUserNameEx (NameFormat, lpUserName, &ulUserNameSize)) {
  2382. //
  2383. // If the call failed due to insufficient memory, realloc
  2384. // the buffer and try again. Otherwise, exit now.
  2385. //
  2386. dwError = GetLastError();
  2387. if (dwError != ERROR_INSUFFICIENT_BUFFER) {
  2388. DebugMsg((DM_WARNING, TEXT("MyGetUserName: GetUserNameEx failed with %d"),
  2389. dwError));
  2390. LocalFree (lpUserName);
  2391. lpUserName = NULL;
  2392. goto Exit;
  2393. }
  2394. lpTemp = (LPTSTR) LocalReAlloc (lpUserName, (ulUserNameSize * sizeof(TCHAR)),
  2395. LMEM_MOVEABLE);
  2396. if (!lpTemp) {
  2397. dwError = GetLastError();
  2398. DebugMsg((DM_WARNING, TEXT("MyGetUserName: Failed to realloc memory with %d"),
  2399. dwError));
  2400. LocalFree (lpUserName);
  2401. lpUserName = NULL;
  2402. goto Exit;
  2403. }
  2404. lpUserName = lpTemp;
  2405. if (!GetUserNameEx (NameFormat, lpUserName, &ulUserNameSize)) {
  2406. dwError = GetLastError();
  2407. DebugMsg((DM_WARNING, TEXT("MyGetUserName: GetUserNameEx failed with %d"),
  2408. dwError));
  2409. LocalFree (lpUserName);
  2410. lpUserName = NULL;
  2411. goto Exit;
  2412. }
  2413. dwError = ERROR_SUCCESS;
  2414. }
  2415. Exit:
  2416. SetLastError(dwError);
  2417. return lpUserName;
  2418. }
  2419. //*************************************************************
  2420. //
  2421. // GuidToString, StringToGuid, ValidateGuid
  2422. //
  2423. // Purpose: Guid utility routines
  2424. //
  2425. //*************************************************************
  2426. void GuidToString( GUID *pGuid, TCHAR * szValue )
  2427. {
  2428. wsprintf( szValue,
  2429. TEXT("{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"),
  2430. pGuid->Data1,
  2431. pGuid->Data2,
  2432. pGuid->Data3,
  2433. pGuid->Data4[0], pGuid->Data4[1],
  2434. pGuid->Data4[2], pGuid->Data4[3],
  2435. pGuid->Data4[4], pGuid->Data4[5],
  2436. pGuid->Data4[6], pGuid->Data4[7] );
  2437. }
  2438. void StringToGuid( TCHAR * szValue, GUID * pGuid )
  2439. {
  2440. WCHAR wc;
  2441. INT i;
  2442. //
  2443. // If the first character is a '{', skip it
  2444. //
  2445. if ( szValue[0] == L'{' )
  2446. szValue++;
  2447. //
  2448. // Since szValue may be used again, no permanent modification to
  2449. // it is be made.
  2450. //
  2451. wc = szValue[8];
  2452. szValue[8] = 0;
  2453. pGuid->Data1 = wcstoul( &szValue[0], 0, 16 );
  2454. szValue[8] = wc;
  2455. wc = szValue[13];
  2456. szValue[13] = 0;
  2457. pGuid->Data2 = (USHORT)wcstoul( &szValue[9], 0, 16 );
  2458. szValue[13] = wc;
  2459. wc = szValue[18];
  2460. szValue[18] = 0;
  2461. pGuid->Data3 = (USHORT)wcstoul( &szValue[14], 0, 16 );
  2462. szValue[18] = wc;
  2463. wc = szValue[21];
  2464. szValue[21] = 0;
  2465. pGuid->Data4[0] = (unsigned char)wcstoul( &szValue[19], 0, 16 );
  2466. szValue[21] = wc;
  2467. wc = szValue[23];
  2468. szValue[23] = 0;
  2469. pGuid->Data4[1] = (unsigned char)wcstoul( &szValue[21], 0, 16 );
  2470. szValue[23] = wc;
  2471. for ( i = 0; i < 6; i++ )
  2472. {
  2473. wc = szValue[26+i*2];
  2474. szValue[26+i*2] = 0;
  2475. pGuid->Data4[2+i] = (unsigned char)wcstoul( &szValue[24+i*2], 0, 16 );
  2476. szValue[26+i*2] = wc;
  2477. }
  2478. }
  2479. BOOL ValidateGuid( TCHAR *szValue )
  2480. {
  2481. //
  2482. // Check if szValue is of form {19e02dd6-79d2-11d2-a89d-00c04fbbcfa2}
  2483. //
  2484. if ( lstrlen(szValue) < GUID_LENGTH )
  2485. return FALSE;
  2486. if ( szValue[0] != TEXT('{')
  2487. || szValue[9] != TEXT('-')
  2488. || szValue[14] != TEXT('-')
  2489. || szValue[19] != TEXT('-')
  2490. || szValue[24] != TEXT('-')
  2491. || szValue[37] != TEXT('}') )
  2492. {
  2493. return FALSE;
  2494. }
  2495. return TRUE;
  2496. }
  2497. INT CompareGuid( GUID * pGuid1, GUID * pGuid2 )
  2498. {
  2499. INT i;
  2500. if ( pGuid1->Data1 != pGuid2->Data1 )
  2501. return ( pGuid1->Data1 < pGuid2->Data1 ? -1 : 1 );
  2502. if ( pGuid1->Data2 != pGuid2->Data2 )
  2503. return ( pGuid1->Data2 < pGuid2->Data2 ? -1 : 1 );
  2504. if ( pGuid1->Data3 != pGuid2->Data3 )
  2505. return ( pGuid1->Data3 < pGuid2->Data3 ? -1 : 1 );
  2506. for ( i = 0; i < 8; i++ )
  2507. {
  2508. if ( pGuid1->Data4[i] != pGuid2->Data4[i] )
  2509. return ( pGuid1->Data4[i] < pGuid2->Data4[i] ? -1 : 1 );
  2510. }
  2511. return 0;
  2512. }
  2513. BOOL IsNullGUID (GUID *pguid)
  2514. {
  2515. return ( (pguid->Data1 == 0) &&
  2516. (pguid->Data2 == 0) &&
  2517. (pguid->Data3 == 0) &&
  2518. (pguid->Data4[0] == 0) &&
  2519. (pguid->Data4[1] == 0) &&
  2520. (pguid->Data4[2] == 0) &&
  2521. (pguid->Data4[3] == 0) &&
  2522. (pguid->Data4[4] == 0) &&
  2523. (pguid->Data4[5] == 0) &&
  2524. (pguid->Data4[6] == 0) &&
  2525. (pguid->Data4[7] == 0) );
  2526. }
  2527. //*************************************************************
  2528. //
  2529. // SpawnGPE()
  2530. //
  2531. // Purpose: Spawns GPE for a GPO
  2532. //
  2533. // Parameters: lpGPO - ADSI path to the GPO
  2534. // gpHint - GPO hint type
  2535. // lpDC - GPO DC name to use (or NULL)
  2536. // hParent - Parent window handle
  2537. //
  2538. // Return: TRUE if successful
  2539. // FALSE if an error occurs
  2540. //
  2541. //*************************************************************
  2542. BOOL SpawnGPE (LPTSTR lpGPO, GROUP_POLICY_HINT_TYPE gpHint, LPTSTR lpDC, HWND hParent)
  2543. {
  2544. LPTSTR lpArgs, lpFullPath, lpDomainName, lpGPODCName;
  2545. UINT uiSize;
  2546. SHELLEXECUTEINFO ExecInfo;
  2547. LPOLESTR pszDomain;
  2548. HRESULT hr;
  2549. //
  2550. // If a DC was given, we need to build a full path to the GPO on that DC.
  2551. // If a DC was not given, then we need to query for a DC and then build a
  2552. // full path.
  2553. //
  2554. if (lpDC)
  2555. {
  2556. //
  2557. // Make the full path
  2558. //
  2559. lpFullPath = MakeFullPath (lpGPO, lpDC);
  2560. if (!lpFullPath)
  2561. {
  2562. DebugMsg((DM_WARNING, TEXT("SpawnGPE: Failed to build new DS object path")));
  2563. return FALSE;
  2564. }
  2565. }
  2566. else
  2567. {
  2568. //
  2569. // Get the friendly domain name
  2570. //
  2571. pszDomain = GetDomainFromLDAPPath(lpGPO);
  2572. if (!pszDomain)
  2573. {
  2574. DebugMsg((DM_WARNING, TEXT("SpawnGPE: Failed to get domain name")));
  2575. return FALSE;
  2576. }
  2577. //
  2578. // Convert LDAP to dot (DN) style
  2579. //
  2580. hr = ConvertToDotStyle (pszDomain, &lpDomainName);
  2581. delete [] pszDomain;
  2582. if (FAILED(hr))
  2583. {
  2584. DebugMsg((DM_WARNING, TEXT("CGroupPolicyObject::CreatePropertyPages: Failed to convert domain name with 0x%x"), hr));
  2585. return FALSE;
  2586. }
  2587. //
  2588. // Get the GPO DC for this domain
  2589. //
  2590. lpGPODCName = GetDCName (lpDomainName, lpDC, hParent, TRUE, VALIDATE_INHERIT_DC);
  2591. if (!lpGPODCName)
  2592. {
  2593. DebugMsg((DM_WARNING, TEXT("SpawnGPE: Failed to get DC name for %s"),
  2594. lpDomainName));
  2595. LocalFree (lpDomainName);
  2596. return FALSE;
  2597. }
  2598. LocalFree (lpDomainName);
  2599. //
  2600. // Make the full path
  2601. //
  2602. lpFullPath = MakeFullPath (lpGPO, lpGPODCName);
  2603. LocalFree (lpGPODCName);
  2604. if (!lpFullPath)
  2605. {
  2606. DebugMsg((DM_WARNING, TEXT("SpawnGPE: Failed to build new DS object path")));
  2607. return FALSE;
  2608. }
  2609. }
  2610. uiSize = lstrlen (lpFullPath) + 30;
  2611. lpArgs = (LPTSTR) LocalAlloc (LPTR, uiSize * sizeof(TCHAR));
  2612. if (!lpArgs)
  2613. {
  2614. DebugMsg((DM_WARNING, TEXT("SpawnGPE: Failed to allocate memory with %d"),
  2615. GetLastError()));
  2616. return FALSE;
  2617. }
  2618. //
  2619. // Build the command line arguments
  2620. //
  2621. wsprintf (lpArgs, TEXT("/s /gphint:%d /gpobject:\"%s\""), gpHint, lpFullPath);
  2622. DebugMsg((DM_VERBOSE, TEXT("SpawnGPE: Starting GPE with %s"), lpArgs));
  2623. ZeroMemory (&ExecInfo, sizeof(ExecInfo));
  2624. ExecInfo.cbSize = sizeof(ExecInfo);
  2625. ExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
  2626. ExecInfo.lpVerb = TEXT("open");
  2627. ExecInfo.lpFile = TEXT("gpedit.msc");
  2628. ExecInfo.lpParameters = lpArgs;
  2629. ExecInfo.nShow = SW_SHOWNORMAL;
  2630. if (ShellExecuteEx (&ExecInfo))
  2631. {
  2632. SetWaitCursor();
  2633. WaitForInputIdle (ExecInfo.hProcess, 10000);
  2634. ClearWaitCursor();
  2635. CloseHandle (ExecInfo.hProcess);
  2636. }
  2637. else
  2638. {
  2639. DebugMsg((DM_WARNING, TEXT("SpawnGPE: ShellExecuteEx failed with %d"),
  2640. GetLastError()));
  2641. ReportError(NULL, ( (GetLastError() == -1) ? 0 : GetLastError()), IDS_SPAWNGPEFAILED);
  2642. LocalFree (lpArgs);
  2643. return FALSE;
  2644. }
  2645. LocalFree (lpArgs);
  2646. LocalFree (lpFullPath);
  2647. return TRUE;
  2648. }
  2649. //*************************************************************
  2650. //
  2651. // MakeFullPath()
  2652. //
  2653. // Purpose: Builds a fully qualified ADSI path consisting
  2654. // of server and DN name
  2655. //
  2656. // Parameters: lpDN - DN path, must start with LDAP://
  2657. // lpServer - Server name
  2658. //
  2659. // Return: lpFullPath if success
  2660. // NULL if an error occurs
  2661. //
  2662. //*************************************************************
  2663. LPTSTR MakeFullPath (LPTSTR lpDN, LPTSTR lpServer)
  2664. {
  2665. IADsPathname * pADsPathname;
  2666. LPTSTR lpFullPath;
  2667. BSTR bstr;
  2668. HRESULT hr;
  2669. //
  2670. // Make sure the incoming path is nameless first
  2671. //
  2672. hr = CoCreateInstance(CLSID_Pathname,
  2673. NULL,
  2674. CLSCTX_INPROC_SERVER,
  2675. IID_IADsPathname,
  2676. (LPVOID*)&pADsPathname);
  2677. if (FAILED(hr))
  2678. {
  2679. DebugMsg((DM_WARNING, TEXT("MakeFullPath: Failed to create IAdsPathName object with = 0x%x"), hr));
  2680. SetLastError(hr);
  2681. return NULL;
  2682. }
  2683. hr = pADsPathname->Set(lpDN, ADS_SETTYPE_FULL);
  2684. if (FAILED(hr))
  2685. {
  2686. DebugMsg((DM_WARNING, TEXT("MakeFullPath: Failed to set <%s> in IAdsPathName object with = 0x%x"),
  2687. lpDN, hr));
  2688. pADsPathname->Release();
  2689. SetLastError(hr);
  2690. return NULL;
  2691. }
  2692. hr = pADsPathname->Retrieve(ADS_FORMAT_X500_NO_SERVER, &bstr);
  2693. pADsPathname->Release();
  2694. if (FAILED(hr))
  2695. {
  2696. DebugMsg((DM_WARNING, TEXT("MakeFullPath: Failed to retrieve pathname with = 0x%x"), hr));
  2697. SetLastError(hr);
  2698. return NULL;
  2699. }
  2700. //
  2701. // Allocate a new buffer for the named path including LDAP://
  2702. //
  2703. lpFullPath = (LPTSTR) LocalAlloc (LPTR, (7 + lstrlen(bstr) +
  2704. (lpServer ? lstrlen(lpServer) : 0) + 3) * sizeof(TCHAR));
  2705. if (!lpFullPath)
  2706. {
  2707. DebugMsg((DM_WARNING, TEXT("MakeFullPath: Failed to allocate memory with = %d"), GetLastError()));
  2708. SysFreeString (bstr);
  2709. return NULL;
  2710. }
  2711. lstrcpy (lpFullPath, TEXT("LDAP://"));
  2712. if (lpServer)
  2713. {
  2714. lstrcat (lpFullPath, lpServer);
  2715. lstrcat (lpFullPath, TEXT("/"));
  2716. }
  2717. lstrcat (lpFullPath, (LPTSTR)(bstr + 7));
  2718. SysFreeString (bstr);
  2719. return lpFullPath;
  2720. }
  2721. //*************************************************************
  2722. //
  2723. // MakeNamelessPath()
  2724. //
  2725. // Purpose: Builds a server nameless ADSI path
  2726. //
  2727. // Parameters: lpDN - DN path, must start with LDAP://
  2728. //
  2729. // Return: lpPath if success
  2730. // NULL if an error occurs
  2731. //
  2732. //*************************************************************
  2733. LPTSTR MakeNamelessPath (LPTSTR lpDN)
  2734. {
  2735. IADsPathname * pADsPathname;
  2736. LPTSTR lpPath;
  2737. BSTR bstr;
  2738. HRESULT hr;
  2739. //
  2740. // Create a pathname object to work with
  2741. //
  2742. hr = CoCreateInstance(CLSID_Pathname,
  2743. NULL,
  2744. CLSCTX_INPROC_SERVER,
  2745. IID_IADsPathname,
  2746. (LPVOID*)&pADsPathname);
  2747. if (FAILED(hr))
  2748. {
  2749. DebugMsg((DM_WARNING, TEXT("MakeNamelessPath: Failed to create IAdsPathName object with = 0x%x"), hr));
  2750. return NULL;
  2751. }
  2752. hr = pADsPathname->Set(lpDN, ADS_SETTYPE_FULL);
  2753. if (FAILED(hr))
  2754. {
  2755. DebugMsg((DM_WARNING, TEXT("MakeNamelessPath: Failed to set <%s> in IAdsPathName object with = 0x%x"),
  2756. lpDN, hr));
  2757. pADsPathname->Release();
  2758. return NULL;
  2759. }
  2760. hr = pADsPathname->Retrieve(ADS_FORMAT_X500_NO_SERVER, &bstr);
  2761. pADsPathname->Release();
  2762. if (FAILED(hr))
  2763. {
  2764. DebugMsg((DM_WARNING, TEXT("MakeNamelessPath: Failed to retrieve pathname with = 0x%x"), hr));
  2765. return NULL;
  2766. }
  2767. //
  2768. // Allocate a new buffer for the path
  2769. //
  2770. lpPath = (LPTSTR) LocalAlloc (LPTR, (lstrlen(bstr) + 1) * sizeof(TCHAR));
  2771. if (!lpPath)
  2772. {
  2773. DebugMsg((DM_WARNING, TEXT("MakeNamelessPath: Failed to allocate memory with = %d"), GetLastError()));
  2774. SysFreeString (bstr);
  2775. return NULL;
  2776. }
  2777. lstrcpy (lpPath, bstr);
  2778. SysFreeString (bstr);
  2779. return lpPath;
  2780. }
  2781. //*************************************************************
  2782. //
  2783. // ExtractServerName()
  2784. //
  2785. // Purpose: Extracts the server name from a ADSI path
  2786. //
  2787. // Parameters: lpPath - ADSI path, must start with LDAP://
  2788. //
  2789. // Return: lpServerName if successful
  2790. // NULL if an error occurs
  2791. //
  2792. //*************************************************************
  2793. LPTSTR ExtractServerName (LPTSTR lpPath)
  2794. {
  2795. LPTSTR lpServerName = NULL;
  2796. LPTSTR lpEnd, lpTemp;
  2797. //
  2798. // Check the path to see if it has a server name
  2799. //
  2800. if (*(lpPath + 9) != TEXT('='))
  2801. {
  2802. //
  2803. // Allocate memory for the server name
  2804. //
  2805. lpServerName = (LPTSTR) LocalAlloc (LPTR, (lstrlen(lpPath) + 1) * sizeof(TCHAR));
  2806. if (!lpServerName)
  2807. {
  2808. DebugMsg((DM_WARNING, TEXT("ExtractServerName: Failed to allocate memory for name with 0xd"),
  2809. GetLastError()));
  2810. return NULL;
  2811. }
  2812. lpTemp = (lpPath + 7);
  2813. lpEnd = lpServerName;
  2814. while (*lpTemp && (*lpTemp != TEXT('/')) && (*lpTemp != TEXT(',')))
  2815. {
  2816. *lpEnd = *lpTemp;
  2817. lpEnd++;
  2818. lpTemp++;
  2819. }
  2820. if (*lpTemp != TEXT('/'))
  2821. {
  2822. DebugMsg((DM_WARNING, TEXT("ExtractServerName: Failed to parse server name from ADSI path")));
  2823. LocalFree (lpServerName);
  2824. lpServerName = NULL;
  2825. }
  2826. }
  2827. return lpServerName;
  2828. }
  2829. //*************************************************************
  2830. //
  2831. // DoesPathContainAServerName()
  2832. //
  2833. // Purpose: Checks the given ADSI path to see if it
  2834. // contains a server name
  2835. //
  2836. // Parameters: lpPath - ADSI path
  2837. //
  2838. // Return: True if the path contains a server name
  2839. // FALSE if not
  2840. //
  2841. //*************************************************************
  2842. BOOL DoesPathContainAServerName (LPTSTR lpPath)
  2843. {
  2844. BOOL bResult = FALSE;
  2845. //
  2846. // Skip over LDAP:// if found
  2847. //
  2848. if ( CompareString( LOCALE_USER_DEFAULT, NORM_IGNORECASE | NORM_STOP_ON_NULL,
  2849. lpPath, 7, L"LDAP://", 7 ) == CSTR_EQUAL )
  2850. {
  2851. lpPath += 7;
  2852. }
  2853. //
  2854. // Check if the 3rd character in the path is an equal sign.
  2855. // If so, this path does not contain a server name
  2856. //
  2857. if ((lstrlen(lpPath) > 2) && (*(lpPath + 3) != TEXT('=')))
  2858. {
  2859. bResult = TRUE;
  2860. }
  2861. return bResult;
  2862. }
  2863. //*************************************************************
  2864. //
  2865. // OpenDSObject()
  2866. //
  2867. // Purpose: Checks the given ADSI path to see if it
  2868. // contains a server name
  2869. //
  2870. // Parameters: lpPath - ADSI path
  2871. //
  2872. // Return: True if the path contains a server name
  2873. // FALSE if not
  2874. //
  2875. //*************************************************************
  2876. HRESULT OpenDSObject (LPTSTR lpPath, REFIID riid, void FAR * FAR * ppObject)
  2877. {
  2878. DWORD dwFlags = ADS_SECURE_AUTHENTICATION;
  2879. if (DoesPathContainAServerName (lpPath))
  2880. {
  2881. dwFlags |= ADS_SERVER_BIND;
  2882. }
  2883. return (ADsOpenObject(lpPath, NULL, NULL, dwFlags,
  2884. riid, ppObject));
  2885. }
  2886. HRESULT CheckDSWriteAccess (LPUNKNOWN punk, LPTSTR lpProperty)
  2887. {
  2888. HRESULT hr;
  2889. IDirectoryObject *pDO = NULL;
  2890. PADS_ATTR_INFO pAE = NULL;
  2891. LPWSTR lpAttributeNames[2];
  2892. DWORD dwResult, dwIndex;
  2893. //
  2894. // Get the IDirectoryObject interface
  2895. //
  2896. hr = punk->QueryInterface(IID_IDirectoryObject, (void**)&pDO);
  2897. if (FAILED(hr)) {
  2898. DebugMsg((DM_WARNING, TEXT("CheckDSWriteAccess: Failed to get the IDirectoryObject interface with 0x%x"), hr));
  2899. goto Exit;
  2900. }
  2901. //
  2902. // Get the property value
  2903. //
  2904. lpAttributeNames[0] = L"allowedAttributesEffective";
  2905. hr = pDO->GetObjectAttributes(lpAttributeNames, 1, &pAE, &dwResult);
  2906. if (FAILED(hr))
  2907. {
  2908. DebugMsg((DM_WARNING, TEXT("CheckDSWriteAccess: Failed to get object attributes with 0x%x"), hr));
  2909. goto Exit;
  2910. }
  2911. //
  2912. // Set the default return value
  2913. //
  2914. hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  2915. //
  2916. // Go through the list of effective attributes
  2917. //
  2918. if (dwResult != 0) {
  2919. for (dwIndex = 0; dwIndex < pAE[0].dwNumValues; dwIndex++)
  2920. {
  2921. if (lstrcmpi(pAE[0].pADsValues[dwIndex].CaseIgnoreString,
  2922. lpProperty) == 0)
  2923. {
  2924. hr = HRESULT_FROM_WIN32(ERROR_SUCCESS);
  2925. }
  2926. }
  2927. }
  2928. else {
  2929. DebugMsg((DM_VERBOSE, TEXT("CheckDSWriteAccess: Couldn't get allowedAttributesEffective")));
  2930. }
  2931. Exit:
  2932. if (pAE)
  2933. {
  2934. FreeADsMem (pAE);
  2935. }
  2936. if (pDO)
  2937. {
  2938. pDO->Release();
  2939. }
  2940. return hr;
  2941. }
  2942. LPTSTR GetFullGPOPath (LPTSTR lpGPO, HWND hParent)
  2943. {
  2944. LPTSTR lpFullPath = NULL, lpDomainName = NULL;
  2945. LPTSTR lpGPODCName;
  2946. LPOLESTR pszDomain;
  2947. HRESULT hr;
  2948. //
  2949. // Get the friendly domain name
  2950. //
  2951. pszDomain = GetDomainFromLDAPPath(lpGPO);
  2952. if (!pszDomain)
  2953. {
  2954. DebugMsg((DM_WARNING, TEXT("GetFullGPOPath: Failed to get domain name")));
  2955. return NULL;
  2956. }
  2957. //
  2958. // Convert LDAP to dot (DN) style
  2959. //
  2960. hr = ConvertToDotStyle (pszDomain, &lpDomainName);
  2961. delete [] pszDomain;
  2962. if (FAILED(hr))
  2963. {
  2964. DebugMsg((DM_WARNING, TEXT("CGroupPolicyObject::CreatePropertyPages: Failed to convert domain name with 0x%x"), hr));
  2965. return NULL;
  2966. }
  2967. //
  2968. // Get the GPO DC for this domain
  2969. //
  2970. lpGPODCName = GetDCName (lpDomainName, NULL, hParent, TRUE, 0);
  2971. if (!lpGPODCName)
  2972. {
  2973. DebugMsg((DM_WARNING, TEXT("GetFullGPOPath: Failed to get DC name for %s"),
  2974. lpDomainName));
  2975. goto Exit;
  2976. }
  2977. //
  2978. // Make the full path
  2979. //
  2980. lpFullPath = MakeFullPath (lpGPO, lpGPODCName);
  2981. LocalFree (lpGPODCName);
  2982. if (!lpFullPath)
  2983. {
  2984. DebugMsg((DM_WARNING, TEXT("GetFullGPOPath: Failed to build new DS object path")));
  2985. goto Exit;
  2986. }
  2987. Exit:
  2988. if (lpDomainName)
  2989. {
  2990. LocalFree (lpDomainName);
  2991. }
  2992. return lpFullPath;
  2993. }
  2994. //*************************************************************
  2995. //
  2996. // ConvertName()
  2997. //
  2998. // Purpose: Converts the user / computer name from SAM style
  2999. // to fully qualified DN
  3000. //
  3001. // Parameters: lpName - name in sam style
  3002. //
  3003. //
  3004. // Return: lpDNName if successful
  3005. // NULL if an error occurs
  3006. //
  3007. //*************************************************************
  3008. LPTSTR ConvertName (LPTSTR lpName)
  3009. {
  3010. LPTSTR lpDNName = NULL, lpSAMName = NULL;
  3011. LPTSTR lpTemp, lpDCName = NULL;
  3012. DWORD dwResult;
  3013. HANDLE hDS = NULL;
  3014. PDS_NAME_RESULT pNameResult = NULL;
  3015. PDS_NAME_RESULT_ITEM pNameResultItem;
  3016. //
  3017. // Check the argument
  3018. //
  3019. if (!lpName)
  3020. {
  3021. DebugMsg((DM_WARNING, TEXT("ConvertName: lpName is null")));
  3022. SetLastError(ERROR_INVALID_DATA);
  3023. goto Exit;
  3024. }
  3025. //
  3026. // Make a copy of the name so we can edit it
  3027. //
  3028. lpSAMName = new TCHAR[(lstrlen(lpName) + 1)];
  3029. if (!lpSAMName)
  3030. {
  3031. DebugMsg((DM_WARNING, TEXT("ConvertName: Failed to allocate memory with %d"), GetLastError()));
  3032. goto Exit;
  3033. }
  3034. lstrcpy (lpSAMName, lpName);
  3035. //
  3036. // Find the slash between the domain name and the account name and replace
  3037. // it with a null
  3038. //
  3039. lpTemp = lpSAMName;
  3040. while (*lpTemp && (*lpTemp != TEXT('\\')))
  3041. {
  3042. lpTemp++;
  3043. }
  3044. if (!(*lpTemp))
  3045. {
  3046. DebugMsg((DM_WARNING, TEXT("ConvertName: Failed to find backslash in %s"), lpSAMName));
  3047. SetLastError(ERROR_INVALID_DATA);
  3048. goto Exit;
  3049. }
  3050. *lpTemp = TEXT('\0');
  3051. //
  3052. // Call DsGetDcName to convert the netbios name to a FQDN name
  3053. //
  3054. dwResult = GetDCHelper (lpSAMName, DS_IS_FLAT_NAME | DS_RETURN_DNS_NAME, &lpDCName);
  3055. if (dwResult != ERROR_SUCCESS)
  3056. {
  3057. DebugMsg((DM_WARNING, TEXT("ConvertName: GetDCHelper failed with %d"), dwResult));
  3058. SetLastError(dwResult);
  3059. goto Exit;
  3060. }
  3061. //
  3062. // Bind to the domain controller
  3063. //
  3064. dwResult = DsBind (lpDCName, NULL, &hDS);
  3065. if (dwResult != ERROR_SUCCESS)
  3066. {
  3067. DebugMsg((DM_WARNING, TEXT("ConvertName: DsBind failed with %d"), dwResult));
  3068. SetLastError(dwResult);
  3069. goto Exit;
  3070. }
  3071. //
  3072. // Use DsCrackNames to convert the name FQDN
  3073. //
  3074. dwResult = DsCrackNames (hDS, DS_NAME_NO_FLAGS, DS_NT4_ACCOUNT_NAME, DS_FQDN_1779_NAME,
  3075. 1, &lpName, &pNameResult);
  3076. if (dwResult != ERROR_SUCCESS)
  3077. {
  3078. DebugMsg((DM_WARNING, TEXT("ConvertName: DsCrackNames failed with %d"), dwResult));
  3079. SetLastError(dwResult);
  3080. goto Exit;
  3081. }
  3082. //
  3083. // Setup a pointer to the first item
  3084. //
  3085. pNameResultItem = &pNameResult->rItems[0];
  3086. if (pNameResultItem->status != DS_NAME_NO_ERROR)
  3087. {
  3088. DebugMsg((DM_WARNING, TEXT("ConvertName: DsCrackNames failed to convert name with %d"), pNameResultItem->status));
  3089. SetLastError(pNameResultItem->status);
  3090. goto Exit;
  3091. }
  3092. //
  3093. // Save the name in a new buffer so it can returned
  3094. //
  3095. lpDNName = new TCHAR[(lstrlen(pNameResultItem->pName) + 1)];
  3096. if (!lpDNName)
  3097. {
  3098. DebugMsg((DM_WARNING, TEXT("ConvertName: Failed to allocate memory with %d"), GetLastError()));
  3099. goto Exit;
  3100. }
  3101. lstrcpy (lpDNName, pNameResultItem->pName);
  3102. Exit:
  3103. if (pNameResult)
  3104. {
  3105. DsFreeNameResult (pNameResult);
  3106. }
  3107. if (hDS)
  3108. {
  3109. DsUnBind (&hDS);
  3110. }
  3111. if (lpDCName)
  3112. {
  3113. LocalFree (lpDCName);
  3114. }
  3115. if (lpSAMName)
  3116. {
  3117. delete [] lpSAMName;
  3118. }
  3119. return lpDNName;
  3120. }
  3121. //*************************************************************
  3122. //
  3123. // CreateTempFile()
  3124. //
  3125. // Purpose: Creates a temp file
  3126. //
  3127. // Parameters: void
  3128. //
  3129. // Return: filename if successful
  3130. // NULL if an error occurs
  3131. //
  3132. //*************************************************************
  3133. LPTSTR CreateTempFile (void)
  3134. {
  3135. TCHAR szTempDir[MAX_PATH];
  3136. TCHAR szTempFile[MAX_PATH];
  3137. LPTSTR lpFileName;
  3138. //
  3139. // Query for the temp directory
  3140. //
  3141. if (!GetTempPath (MAX_PATH, szTempDir))
  3142. {
  3143. DebugMsg((DM_WARNING, TEXT("CRSOPComponentData::CreateTempFile: GetTempPath failed with %d"), GetLastError()));
  3144. return NULL;
  3145. }
  3146. //
  3147. // Query for a temp filename
  3148. //
  3149. if (!GetTempFileName (szTempDir, TEXT("RSP"), 0, szTempFile))
  3150. {
  3151. DebugMsg((DM_WARNING, TEXT("CRSOPComponentData::CreateTempFile: GetTempFile failed with %d"), GetLastError()));
  3152. return NULL;
  3153. }
  3154. //
  3155. // Allocate a new buffer for the filename
  3156. //
  3157. lpFileName = new TCHAR[(lstrlen(szTempFile) + 1)];
  3158. if (!lpFileName)
  3159. {
  3160. DebugMsg((DM_WARNING, TEXT("CRSOPComponentData::CreateTempFile: Failed to allocate memory for temp filename with %d"), GetLastError()));
  3161. return NULL;
  3162. }
  3163. lstrcpy (lpFileName, szTempFile);
  3164. return lpFileName;
  3165. }
  3166. //+--------------------------------------------------------------------------
  3167. //
  3168. // Function: NameToPath
  3169. //
  3170. // Synopsis: converts a dot-format domain name to an LDAP:// style path
  3171. //
  3172. // Arguments: [szPath] - (out) buffer to hold the path
  3173. // [szName] - (in) dot-format domain name
  3174. // [cch] - (in) size of the out buffer
  3175. //
  3176. // History: 10-15-1998 stevebl Created
  3177. //
  3178. // Note: Currently, this routine will truncate if it doesn't get a
  3179. // large enough buffer so you'd better be sure your
  3180. // buffer's large enough. (The formula is string size + 10 + 3
  3181. // for each dot in the string.)
  3182. //
  3183. // That's good enough to avoid an AV but could have some really
  3184. // wierd side effects so beware.
  3185. //
  3186. //---------------------------------------------------------------------------
  3187. void NameToPath(WCHAR * szPath, WCHAR *szName, UINT cch)
  3188. {
  3189. WCHAR * szOut = szPath;
  3190. WCHAR * szIn = szName;
  3191. wcscpy(szOut, TEXT("LDAP://DC="));
  3192. szOut += 10;
  3193. while ((*szIn) && (szOut + 1 < szPath + cch))
  3194. {
  3195. if (*szIn == TEXT('.') && (szOut + 4 < szPath + cch))
  3196. {
  3197. ++szIn;
  3198. if (*szIn && *szIn != TEXT('.'))
  3199. {
  3200. *szOut = TEXT(',');
  3201. ++szOut;
  3202. *szOut = TEXT('D');
  3203. ++szOut;
  3204. *szOut = TEXT('C');
  3205. ++szOut;
  3206. *szOut = TEXT('=');
  3207. ++szOut;
  3208. }
  3209. }
  3210. else
  3211. {
  3212. *szOut = *szIn;
  3213. ++szOut;
  3214. ++szIn;
  3215. }
  3216. }
  3217. *szOut = TEXT('\0');
  3218. }
  3219. //+--------------------------------------------------------------------------
  3220. //
  3221. // Function: GetPathToForest
  3222. //
  3223. // Synopsis: given a domain, return a pointer to its forest
  3224. //
  3225. // Arguments: [szServer] - DOT style path to a server (may be NULL)
  3226. //
  3227. // Returns: LDAP style path to the forest's Configuration container
  3228. //
  3229. // History: 03-31-2000 stevebl Created
  3230. //
  3231. // Notes: return value is allocated with new
  3232. //
  3233. //---------------------------------------------------------------------------
  3234. LPTSTR GetPathToForest(LPOLESTR szServer)
  3235. {
  3236. LPOLESTR szReturn = NULL;
  3237. LPOLESTR lpForest = NULL;
  3238. LPOLESTR lpTemp = NULL;
  3239. LPOLESTR lpDCName = NULL;
  3240. IADsPathname * pADsPathname = NULL;
  3241. BSTR bstrForest = NULL;
  3242. HRESULT hr = 0;
  3243. int cch, n;
  3244. DWORD dwResult = QueryForForestName(szServer,
  3245. NULL,
  3246. DS_PDC_REQUIRED | DS_RETURN_DNS_NAME,
  3247. &lpTemp);
  3248. if (dwResult != ERROR_SUCCESS)
  3249. {
  3250. DebugMsg((DM_WARNING, TEXT("GetPathToForest: QueryForestName failed for domain name %s with %d"),
  3251. szServer, dwResult));
  3252. hr = HRESULT_FROM_WIN32(dwResult);
  3253. goto Exit;
  3254. }
  3255. cch = 0;
  3256. n = 0;
  3257. // count the dots in lpTemp;
  3258. while (lpTemp[n])
  3259. {
  3260. if (L'.' == lpTemp[n])
  3261. {
  3262. cch++;
  3263. }
  3264. n++;
  3265. }
  3266. cch *= 3; // multiply the number of dots by 3;
  3267. cch += 11; // add 10 + 1 (for the null)
  3268. cch += n; // add the string size;
  3269. lpForest = (LPTSTR) LocalAlloc(LPTR, sizeof(WCHAR) * cch);
  3270. if (!lpForest)
  3271. {
  3272. DebugMsg((DM_WARNING, TEXT("GetPathToForest: Failed to allocate memory for forest name with %d"),
  3273. GetLastError()));
  3274. hr = HRESULT_FROM_WIN32(GetLastError());
  3275. goto Exit;
  3276. }
  3277. NameToPath(lpForest, lpTemp, cch);
  3278. LocalFree(lpTemp);
  3279. lpTemp = NULL;
  3280. // See if we need to put a specific server on this.
  3281. //
  3282. if (szServer)
  3283. {
  3284. // we have a path to a specific DC
  3285. // need to prepend it to the forest name
  3286. lpTemp = MakeFullPath(lpForest, szServer);
  3287. if (!lpTemp)
  3288. {
  3289. DebugMsg((DM_WARNING, TEXT("GetPathToForest: Failed to combine server name with Forest path")));
  3290. hr = HRESULT_FROM_WIN32(GetLastError());
  3291. goto Exit;
  3292. }
  3293. // clean up the variables we just borrowed so they can be used later
  3294. LocalFree(lpForest);
  3295. lpForest = lpTemp;
  3296. lpTemp = NULL;
  3297. }
  3298. // at this point we have the path to the forest's DC in lpForest
  3299. // we still need to add "CN=Configuration" to this
  3300. //
  3301. // Create a pathname object we can work with
  3302. //
  3303. hr = CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER,
  3304. IID_IADsPathname, (LPVOID*)&pADsPathname);
  3305. if (FAILED(hr))
  3306. {
  3307. DebugMsg((DM_WARNING, TEXT("GetPathToForest: Failed to create adspathname instance with 0x%x"), hr));
  3308. goto Exit;
  3309. }
  3310. //
  3311. // Add the domain name
  3312. //
  3313. hr = pADsPathname->Set (lpForest, ADS_SETTYPE_FULL);
  3314. if (FAILED(hr))
  3315. {
  3316. DebugMsg((DM_WARNING, TEXT("GetPathToForest: Failed to set pathname with 0x%x"), hr));
  3317. goto Exit;
  3318. }
  3319. //
  3320. // Add the Configuration folder to the path
  3321. //
  3322. hr = pADsPathname->AddLeafElement (TEXT("CN=Configuration"));
  3323. if (FAILED(hr))
  3324. {
  3325. DebugMsg((DM_WARNING, TEXT("GetPathToForest: Failed to add configuration folder with 0x%x"), hr));
  3326. goto Exit;
  3327. }
  3328. //
  3329. // Retreive the GPC path
  3330. //
  3331. hr = pADsPathname->Retrieve (ADS_FORMAT_X500, &bstrForest);
  3332. if (FAILED(hr))
  3333. {
  3334. DebugMsg((DM_WARNING, TEXT("GetPathToForest: Failed to retreive container path with 0x%x"), hr));
  3335. goto Exit;
  3336. }
  3337. DebugMsg((DM_VERBOSE, TEXT("GetPathToForest: conatiner path is: %s"), bstrForest));
  3338. szReturn = new OLECHAR[SysStringLen(bstrForest)+1];
  3339. lstrcpy(szReturn, bstrForest);
  3340. Exit:
  3341. if (bstrForest)
  3342. {
  3343. SysFreeString(bstrForest);
  3344. }
  3345. if (pADsPathname)
  3346. {
  3347. pADsPathname->Release();
  3348. }
  3349. if (lpForest)
  3350. {
  3351. LocalFree(lpForest);
  3352. }
  3353. if (lpDCName)
  3354. {
  3355. LocalFree(lpDCName);
  3356. }
  3357. if (lpTemp)
  3358. {
  3359. LocalFree(lpTemp);
  3360. }
  3361. if (!szReturn)
  3362. {
  3363. SetLastError(hr);
  3364. }
  3365. return szReturn;
  3366. }
  3367. BOOL IsForest(LPOLESTR szLDAPPath)
  3368. {
  3369. #if FGPO_SUPPORT
  3370. return ((StrStrI(szLDAPPath, TEXT("CN=Configuration"))) ? TRUE : FALSE);
  3371. #else
  3372. return FALSE;
  3373. #endif
  3374. }
  3375. //*************************************************************
  3376. //
  3377. // IsStandaloneComputer()
  3378. //
  3379. // Purpose: Determines if the computer is not a member of a domain
  3380. //
  3381. // Parameters: none
  3382. //
  3383. //
  3384. // Return: TRUE if the computer is running standalone
  3385. // FALSE if not
  3386. //
  3387. //*************************************************************
  3388. BOOL IsStandaloneComputer (VOID)
  3389. {
  3390. PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pBasic;
  3391. DWORD dwResult;
  3392. BOOL bRetVal = FALSE;
  3393. //
  3394. // Ask for the role of this machine
  3395. //
  3396. dwResult = DsRoleGetPrimaryDomainInformation(NULL, DsRolePrimaryDomainInfoBasic,
  3397. (PBYTE *)&pBasic);
  3398. if (dwResult == ERROR_SUCCESS)
  3399. {
  3400. //
  3401. // Check for standalone flags
  3402. //
  3403. if ((pBasic->MachineRole == DsRole_RoleStandaloneWorkstation) ||
  3404. (pBasic->MachineRole == DsRole_RoleStandaloneServer))
  3405. {
  3406. bRetVal = TRUE;
  3407. }
  3408. DsRoleFreeMemory (pBasic);
  3409. }
  3410. else
  3411. {
  3412. DebugMsg((DM_WARNING, TEXT("IsStandaloneComputer: DsRoleGetPrimaryDomainInformation failed with %d."),
  3413. dwResult));
  3414. }
  3415. return bRetVal;
  3416. }
  3417. //*************************************************************
  3418. //
  3419. // GetNewGPODisplayName()
  3420. //
  3421. // Purpose: Gets the new GPO display name
  3422. //
  3423. // Parameters: lpDisplayName - Receives the display name
  3424. // dwDisplayNameSize - Size of lpDisplayName
  3425. //
  3426. //
  3427. // Return: TRUE if successful
  3428. // FALSE if an error occurs
  3429. //
  3430. //*************************************************************
  3431. BOOL GetNewGPODisplayName (LPTSTR lpDisplayName, DWORD dwDisplayNameSize)
  3432. {
  3433. TCHAR szName[256];
  3434. LONG lResult;
  3435. HKEY hKey;
  3436. DWORD dwSize, dwType;
  3437. //
  3438. // Load the default string
  3439. //
  3440. LoadString(g_hInstance, IDS_NEWGPO, szName, ARRAYSIZE(szName));
  3441. //
  3442. // Check for a user preference
  3443. //
  3444. lResult = RegOpenKeyEx (HKEY_CURRENT_USER, GPE_KEY, 0, KEY_READ, &hKey);
  3445. if (lResult == ERROR_SUCCESS)
  3446. {
  3447. dwSize = sizeof(szName);
  3448. RegQueryValueEx (hKey, GPO_DISPLAY_NAME_VALUE, NULL, &dwType,
  3449. (LPBYTE) szName, &dwSize);
  3450. RegCloseKey (hKey);
  3451. }
  3452. //
  3453. // Check for a user policy
  3454. //
  3455. lResult = RegOpenKeyEx (HKEY_CURRENT_USER, GPE_POLICIES_KEY, 0, KEY_READ, &hKey);
  3456. if (lResult == ERROR_SUCCESS)
  3457. {
  3458. dwSize = sizeof(szName);
  3459. RegQueryValueEx (hKey, GPO_DISPLAY_NAME_VALUE, NULL, &dwType,
  3460. (LPBYTE) szName, &dwSize);
  3461. RegCloseKey (hKey);
  3462. }
  3463. //
  3464. // Expand the string to resolve any environment variables
  3465. //
  3466. if (!ExpandEnvironmentStrings (szName, lpDisplayName, dwDisplayNameSize))
  3467. {
  3468. return FALSE;
  3469. }
  3470. return TRUE;
  3471. }
  3472. HRESULT GetWMIFilterName (LPTSTR lpFilter, BOOL bDSFormat, BOOL bRetRsopFormat, LPTSTR *lpName)
  3473. {
  3474. IWbemLocator * pLocator = NULL;
  3475. IWbemServices * pNamespace = NULL;
  3476. IWbemClassObject *pObject = NULL;
  3477. BSTR bstrParam = NULL;
  3478. BSTR bstrObject = NULL;
  3479. HRESULT hr;
  3480. LPTSTR lpID, lpDSPath, lpTemp, lpFullFilter = NULL, lpObject = NULL;
  3481. LPTSTR lpDomain = NULL;
  3482. *lpName = NULL;
  3483. hr = E_OUTOFMEMORY;
  3484. if (bDSFormat)
  3485. {
  3486. //
  3487. // Parse the filter path
  3488. //
  3489. lpFullFilter = new TCHAR [lstrlen(lpFilter) + 1];
  3490. if (!lpFullFilter)
  3491. {
  3492. DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: Failed to alloc memory for full filter path")));
  3493. goto Cleanup;
  3494. }
  3495. lstrcpy (lpFullFilter, lpFilter);
  3496. lpTemp = lpFullFilter;
  3497. //
  3498. // Skip over the opening [ character
  3499. //
  3500. lpTemp++;
  3501. lpDSPath = lpTemp;
  3502. //
  3503. // Find the semi-colon. This is the end of the DS Path
  3504. //
  3505. while (*lpTemp && (*lpTemp != TEXT(';')))
  3506. lpTemp++;
  3507. if (!(*lpTemp))
  3508. {
  3509. DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: Filter parsing problem")));
  3510. goto Cleanup;
  3511. }
  3512. *lpTemp = TEXT('\0');
  3513. lpTemp++;
  3514. //
  3515. // Next is the ID (a guid). Find the next semi-colon and the ID is complete
  3516. //
  3517. lpID = lpTemp;
  3518. while (*lpTemp && (*lpTemp != TEXT(';')))
  3519. lpTemp++;
  3520. if (!(*lpTemp))
  3521. {
  3522. DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: Filter parsing problem")));
  3523. goto Cleanup;
  3524. }
  3525. *lpTemp = TEXT('\0');
  3526. //
  3527. // Now build the query
  3528. //
  3529. lpObject = new TCHAR [lstrlen(lpDSPath) + lstrlen(lpID) + 50];
  3530. if (!lpObject)
  3531. {
  3532. DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: Failed to alloc memory for object path")));
  3533. goto Cleanup;
  3534. }
  3535. wsprintf (lpObject, TEXT("MSFT_SomFilter.ID=\"%s\",Domain=\"%s\""), lpID, lpDSPath);
  3536. }
  3537. else
  3538. {
  3539. //
  3540. // The filter is already in the correct format. Just dup it and go.
  3541. //
  3542. lpObject = new TCHAR [lstrlen(lpFilter) + 1];
  3543. if (!lpObject)
  3544. {
  3545. DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: Failed to alloc memory for object path")));
  3546. goto Cleanup;
  3547. }
  3548. lstrcpy (lpObject, lpFilter);
  3549. }
  3550. //
  3551. // Get a locator instance
  3552. //
  3553. hr = CoCreateInstance(CLSID_WbemLocator,
  3554. 0,
  3555. CLSCTX_INPROC_SERVER,
  3556. IID_IWbemLocator,
  3557. (LPVOID *) &pLocator);
  3558. if (FAILED(hr))
  3559. {
  3560. DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: CoCreateInstance failed with 0x%x"), hr));
  3561. goto Cleanup;
  3562. }
  3563. //
  3564. // Build a path to the policy provider
  3565. //
  3566. bstrParam = SysAllocString(TEXT("\\\\.\\root\\policy"));
  3567. if (!bstrParam)
  3568. {
  3569. DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: Failed to allocate bstr for namespace path")));
  3570. goto Cleanup;
  3571. }
  3572. //
  3573. // Connect to the namespace
  3574. //
  3575. hr = pLocator->ConnectServer(bstrParam,
  3576. NULL,
  3577. NULL,
  3578. NULL,
  3579. 0,
  3580. NULL,
  3581. NULL,
  3582. &pNamespace);
  3583. if (FAILED(hr))
  3584. {
  3585. DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: ConnectServer failed with 0x%x"), hr));
  3586. goto Cleanup;
  3587. }
  3588. //
  3589. // Set the proper security to prevent the GetObject call from failing
  3590. //
  3591. hr = CoSetProxyBlanket(pNamespace,
  3592. RPC_C_AUTHN_DEFAULT,
  3593. RPC_C_AUTHZ_DEFAULT,
  3594. COLE_DEFAULT_PRINCIPAL,
  3595. RPC_C_AUTHN_LEVEL_CALL,
  3596. RPC_C_IMP_LEVEL_IMPERSONATE,
  3597. NULL,
  3598. 0);
  3599. if (FAILED(hr))
  3600. {
  3601. DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: CoSetProxyBlanket failed with 0x%x"), hr));
  3602. goto Cleanup;
  3603. }
  3604. bstrObject = SysAllocString(lpObject);
  3605. if (!bstrObject)
  3606. {
  3607. DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: Failed to allocate bstr for namespace path")));
  3608. goto Cleanup;
  3609. }
  3610. hr = pNamespace->GetObject(bstrObject,
  3611. WBEM_FLAG_RETURN_WBEM_COMPLETE,
  3612. NULL,
  3613. &pObject,
  3614. NULL);
  3615. if (FAILED(hr))
  3616. {
  3617. TCHAR szDefault[100];
  3618. DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: GetObject for %s failed with 0x%x"), bstrObject, hr));
  3619. goto Cleanup;
  3620. }
  3621. hr = GetParameter(pObject, TEXT("Name"), *lpName);
  3622. if (FAILED(hr))
  3623. {
  3624. DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: GetParameter failed with 0x%x"), hr));
  3625. }
  3626. if (bRetRsopFormat) {
  3627. LPTSTR lpTemp1;
  3628. TCHAR szRsopQueryFormat[200];
  3629. hr = GetParameter(pObject, TEXT("Domain"), lpDomain);
  3630. if (FAILED(hr))
  3631. {
  3632. DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: GetParameter failed with 0x%x"), hr));
  3633. }
  3634. if (lpDomain) {
  3635. szRsopQueryFormat[0] = TEXT('\0');
  3636. LoadString(g_hInstance, IDS_RSOPWMIQRYFMT, szRsopQueryFormat, ARRAYSIZE(szRsopQueryFormat));
  3637. lpTemp1 = new TCHAR[lstrlen(szRsopQueryFormat)+lstrlen(*lpName)+
  3638. lstrlen(lpDomain)+2];
  3639. if (!lpTemp1) {
  3640. hr = HRESULT_FROM_WIN32(GetLastError());
  3641. delete [] *lpName;
  3642. *lpName = NULL;
  3643. DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: Failed to allocate memory with 0x%x"), hr));
  3644. goto Cleanup;
  3645. }
  3646. wsprintf(lpTemp1, szRsopQueryFormat, *lpName, lpDomain);
  3647. delete [] *lpName;
  3648. *lpName = lpTemp1;
  3649. delete [] lpDomain;
  3650. }
  3651. }
  3652. Cleanup:
  3653. SysFreeString(bstrParam);
  3654. if (pObject)
  3655. {
  3656. pObject->Release();
  3657. }
  3658. if (pNamespace)
  3659. {
  3660. pNamespace->Release();
  3661. }
  3662. if (pLocator)
  3663. {
  3664. pLocator->Release();
  3665. }
  3666. if (bstrParam)
  3667. {
  3668. SysFreeString (bstrParam);
  3669. }
  3670. if (bstrObject)
  3671. {
  3672. SysFreeString (bstrParam);
  3673. }
  3674. if (lpFullFilter)
  3675. {
  3676. delete [] lpFullFilter;
  3677. }
  3678. if (lpObject)
  3679. {
  3680. delete [] lpObject;
  3681. }
  3682. return hr;
  3683. }
  3684. //*************************************************************
  3685. //
  3686. // GetWMIFilter()
  3687. //
  3688. // Purpose: Displays the WMI filter UI and returns back a dspath, id,
  3689. // and friendly display name if the user selects OK.
  3690. //
  3691. // Parameters: bBrowser - Browser or full manager.
  3692. // hwndParent - Hwnd of parent window
  3693. // bDSFormat - Boolean that states DS vs WMI format
  3694. // lpDisplayName - Address of pointer to friendly display name
  3695. // lpFilter - Address of pointer to filter
  3696. //
  3697. //
  3698. // Return: TRUE if successful
  3699. // FALSE if an error occurs
  3700. //
  3701. // Notes: The filter is returned in either DS or WMI format.
  3702. // The DS format is: [DSPath;id;flags] flags is always 0
  3703. // The WMI format is: MSFT_SomFilter.ID="<id>",Domain="<context>"
  3704. //
  3705. //*************************************************************
  3706. BOOL GetWMIFilter( BOOL bBrowser,
  3707. HWND hwndParent,
  3708. BOOL bDSFormat,
  3709. LPTSTR *lpDisplayName,
  3710. LPTSTR * lpFilter,
  3711. BSTR bstrDomain )
  3712. {
  3713. HRESULT hr;
  3714. VARIANT var;
  3715. IWMIFilterManager * pWMIFilterManager;
  3716. IWbemClassObject * pFilter;
  3717. LPTSTR lpName = NULL, lpDSPath = NULL, lpID = NULL;
  3718. VariantInit (&var);
  3719. //
  3720. // Display the appropriate WMI filter UI
  3721. //
  3722. hr = CoCreateInstance (CLSID_WMIFilterManager, NULL,
  3723. CLSCTX_SERVER, IID_IWMIFilterManager,
  3724. (void**)&pWMIFilterManager);
  3725. if (FAILED(hr))
  3726. {
  3727. DebugMsg((DM_WARNING, TEXT("GetWMIFilter: CoCreateInstance failed with 0x%x."),hr));
  3728. return FALSE;
  3729. }
  3730. if (bBrowser)
  3731. {
  3732. hr = pWMIFilterManager->RunBrowser( hwndParent,
  3733. bstrDomain,
  3734. &var );
  3735. }
  3736. else
  3737. {
  3738. hr = pWMIFilterManager->RunManager( hwndParent,
  3739. bstrDomain,
  3740. &var);
  3741. }
  3742. pWMIFilterManager->Release();
  3743. if (FAILED(hr))
  3744. {
  3745. DebugMsg((DM_WARNING, TEXT("GetWMIFilter: RunBrowser / RunManager failed with 0x%x."),hr));
  3746. return FALSE;
  3747. }
  3748. if (hr == S_FALSE)
  3749. {
  3750. if (*lpFilter) {
  3751. hr = GetWMIFilterName (*lpFilter, TRUE, FALSE, lpDisplayName);
  3752. if (!(*lpDisplayName)) {
  3753. DebugMsg((DM_VERBOSE, TEXT("GetWMIFilter: Currently attached WMI filter doesn't exist.")));
  3754. if (hwndParent)
  3755. {
  3756. ReportError(hwndParent, 0, IDS_WMIFILTERFORCEDNONE);
  3757. }
  3758. delete [] *lpFilter;
  3759. *lpFilter = NULL;
  3760. }
  3761. }
  3762. return TRUE;
  3763. }
  3764. if (var.vt != VT_UNKNOWN)
  3765. {
  3766. DebugMsg((DM_WARNING, TEXT("GetWMIFilter: variant isn't of type VT_UNKNOWN.")));
  3767. VariantClear (&var);
  3768. return FALSE;
  3769. }
  3770. //
  3771. // Get the IWbemClassobject interface pointer
  3772. //
  3773. hr = var.punkVal->QueryInterface (IID_IWbemClassObject, (void**)&pFilter);
  3774. if (FAILED(hr))
  3775. {
  3776. DebugMsg((DM_WARNING, TEXT("GetWMIFilter: QueryInterface failed with 0x%x."),hr));
  3777. VariantClear (&var);
  3778. return FALSE;
  3779. }
  3780. //
  3781. // Get the display name
  3782. //
  3783. hr = GetParameter (pFilter, TEXT("Name"), lpName);
  3784. if (FAILED(hr))
  3785. {
  3786. DebugMsg((DM_WARNING, TEXT("GetWMIFilter: GetParameter for Name failed with 0x%x."),hr));
  3787. pFilter->Release();
  3788. VariantClear (&var);
  3789. return FALSE;
  3790. }
  3791. //
  3792. // Get the DS Path (Domain)
  3793. //
  3794. hr = GetParameter (pFilter, TEXT("Domain"), lpDSPath);
  3795. if (FAILED(hr))
  3796. {
  3797. DebugMsg((DM_WARNING, TEXT("GetWMIFilter: GetParameter for DsContext failed with 0x%x."),hr));
  3798. delete [] lpName;
  3799. pFilter->Release();
  3800. VariantClear (&var);
  3801. return FALSE;
  3802. }
  3803. //
  3804. // Get the ID
  3805. //
  3806. hr = GetParameter (pFilter, TEXT("ID"), lpID);
  3807. if (FAILED(hr))
  3808. {
  3809. DebugMsg((DM_WARNING, TEXT("GetWMIFilter: GetParameter for ID failed with 0x%x."),hr));
  3810. delete [] lpDSPath;
  3811. delete [] lpName;
  3812. pFilter->Release();
  3813. VariantClear (&var);
  3814. return FALSE;
  3815. }
  3816. //
  3817. // Put the path together
  3818. //
  3819. LPTSTR lpTemp = NULL;
  3820. lpTemp = new TCHAR[lstrlen(lpDSPath) + lstrlen(lpID) + 50];
  3821. if (!lpTemp)
  3822. {
  3823. DebugMsg((DM_WARNING, TEXT("GetWMIFilter: New failed")));
  3824. delete [] lpID;
  3825. delete [] lpDSPath;
  3826. delete [] lpName;
  3827. pFilter->Release();
  3828. VariantClear (&var);
  3829. return FALSE;
  3830. }
  3831. delete [] *lpFilter;
  3832. *lpFilter = lpTemp;
  3833. if (bDSFormat)
  3834. {
  3835. wsprintf (*lpFilter, TEXT("[%s;%s;0]"), lpDSPath, lpID);
  3836. }
  3837. else
  3838. {
  3839. wsprintf (*lpFilter, TEXT("MSFT_SomFilter.ID=\"%s\",Domain=\"%s\""), lpID, lpDSPath);
  3840. }
  3841. //
  3842. // Save the display name
  3843. //
  3844. *lpDisplayName = lpName;
  3845. delete [] lpID;
  3846. delete [] lpDSPath;
  3847. pFilter->Release();
  3848. VariantClear (&var);
  3849. DebugMsg((DM_VERBOSE, TEXT("GetWMIFilter: Name: %s Filter: %s"), *lpDisplayName, *lpFilter));
  3850. return TRUE;
  3851. }
  3852. //*************************************************************
  3853. //
  3854. // GetWMIFilterDisplayName()
  3855. //
  3856. // Purpose: Gets the friendly display name for the specified
  3857. // WMI filter link
  3858. //
  3859. // Parameters: lpFilter - filter string
  3860. // bDSFormat - in ds format or wmi format
  3861. //
  3862. //
  3863. // Return: Pointer to display name if successful
  3864. // NULL if an error occurs
  3865. //
  3866. //*************************************************************
  3867. LPTSTR GetWMIFilterDisplayName (HWND hParent, LPTSTR lpFilter, BOOL bDSFormat, BOOL bRetRsopFormat)
  3868. {
  3869. LPTSTR lpName = NULL;
  3870. HRESULT hr;
  3871. hr = GetWMIFilterName(lpFilter, bDSFormat, bRetRsopFormat, &lpName);
  3872. if (FAILED(hr) || ((*lpName) == NULL)) {
  3873. TCHAR szDefault[100];
  3874. DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: GetObject for %s failed with 0x%x"), lpFilter, hr));
  3875. if (hParent)
  3876. {
  3877. ReportError(hParent, hr, IDS_WMIFILTERMISSING);
  3878. }
  3879. LoadString(g_hInstance, IDS_MISSINGFILTER, szDefault, ARRAYSIZE(szDefault));
  3880. lpName = new TCHAR [lstrlen(szDefault) + 1];
  3881. if (!lpName)
  3882. {
  3883. DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: Failed to alloc memory for default name")));
  3884. goto Cleanup;
  3885. }
  3886. lstrcpy (lpName, szDefault);
  3887. }
  3888. Cleanup:
  3889. return lpName;
  3890. }
  3891. //*************************************************************
  3892. //
  3893. // SaveString()
  3894. //
  3895. // Purpose: Saves the given string to the stream
  3896. //
  3897. // Parameters:
  3898. //
  3899. //
  3900. // Return: TRUE if successful
  3901. // FALSE if an error occurs
  3902. //
  3903. //*************************************************************
  3904. HRESULT SaveString(IStream *pStm, LPTSTR lpString)
  3905. {
  3906. ULONG nBytesWritten;
  3907. DWORD dwTemp;
  3908. HRESULT hr;
  3909. //
  3910. // Save the string length
  3911. //
  3912. dwTemp = lstrlen (lpString);
  3913. if (dwTemp)
  3914. {
  3915. dwTemp = (dwTemp + 1) * sizeof (TCHAR);
  3916. }
  3917. hr = pStm->Write(&dwTemp, sizeof(dwTemp), &nBytesWritten);
  3918. if ((hr != S_OK) || (nBytesWritten != sizeof(dwTemp)))
  3919. {
  3920. DebugMsg((DM_WARNING, TEXT("SaveString: Failed to write string length with %d."), hr));
  3921. goto Exit;
  3922. }
  3923. //
  3924. // Save the string
  3925. //
  3926. if (dwTemp)
  3927. {
  3928. hr = pStm->Write(lpString, dwTemp, &nBytesWritten);
  3929. if ((hr != S_OK) || (nBytesWritten != dwTemp))
  3930. {
  3931. DebugMsg((DM_WARNING, TEXT("SaveString: Failed to write string with %d."), hr));
  3932. goto Exit;
  3933. }
  3934. }
  3935. Exit:
  3936. return hr;
  3937. }
  3938. HRESULT ReadString(IStream *pStm, LPTSTR *lpString)
  3939. {
  3940. HRESULT hr;
  3941. DWORD dwStringLen;
  3942. ULONG nBytesRead;
  3943. //
  3944. // Read in the string length (including null terminator)
  3945. //
  3946. hr = pStm->Read(&dwStringLen, sizeof(dwStringLen), &nBytesRead);
  3947. if ((hr != S_OK) || (nBytesRead != sizeof(dwStringLen)))
  3948. {
  3949. DebugMsg((DM_WARNING, TEXT("ReadString: Failed to read string size with 0x%x."), hr));
  3950. hr = E_FAIL;
  3951. goto Exit;
  3952. }
  3953. //
  3954. // Read in the string if there is one
  3955. //
  3956. if (dwStringLen > 0)
  3957. {
  3958. *lpString = new TCHAR[(dwStringLen/sizeof(TCHAR))];
  3959. if (!(*lpString))
  3960. {
  3961. DebugMsg((DM_WARNING, TEXT("ReadString: Failed to allocate memory with %d."),
  3962. GetLastError()));
  3963. hr = E_FAIL;
  3964. goto Exit;
  3965. }
  3966. hr = pStm->Read(*lpString, dwStringLen, &nBytesRead);
  3967. if ((hr != S_OK) || (nBytesRead != dwStringLen))
  3968. {
  3969. DebugMsg((DM_WARNING, TEXT("ReadString: Failed to read String with 0x%x."), hr));
  3970. hr = E_FAIL;
  3971. goto Exit;
  3972. }
  3973. DebugMsg((DM_VERBOSE, TEXT("ReadString: String is: <%s>"), *lpString));
  3974. }
  3975. Exit:
  3976. return hr;
  3977. }
  3978. //*************************************************************
  3979. //
  3980. // GetSiteFriendlyName()
  3981. //
  3982. // Purpose: Returns the sites friendly name
  3983. //
  3984. // Parameters:
  3985. //
  3986. // szSitePath - Path to the site
  3987. // pszSiteName - Friendly name of the site
  3988. //
  3989. // Return: currently it always returns true, if it
  3990. // couldn't get the sitename, returns itself
  3991. //
  3992. //*************************************************************
  3993. BOOL GetSiteFriendlyName (LPWSTR szSitePath, LPWSTR *pszSiteName)
  3994. {
  3995. *pszSiteName = new WCHAR[wcslen(szSitePath)+1];
  3996. if (!*pszSiteName) {
  3997. return FALSE;
  3998. }
  3999. LPWSTR szData;
  4000. //
  4001. // Build the LDAP path (serverless)
  4002. //
  4003. szData = new WCHAR[wcslen(szSitePath)+1+7];
  4004. if (szData)
  4005. {
  4006. wcscpy(szData, TEXT("LDAP://"));
  4007. wcscat(szData, szSitePath);
  4008. //
  4009. // Setup the default friendly name
  4010. //
  4011. if (*pszSiteName)
  4012. {
  4013. wcscpy(*pszSiteName, szSitePath);
  4014. }
  4015. //
  4016. // Bind to the site object in the DS to try and get the
  4017. // real friendly name
  4018. //
  4019. IADs * pADs = NULL;
  4020. HRESULT hr = OpenDSObject(szData, IID_IADs, (void **)&pADs);
  4021. if (SUCCEEDED(hr))
  4022. {
  4023. VARIANT varName;
  4024. BSTR bstrNameProp;
  4025. VariantInit(&varName);
  4026. bstrNameProp = SysAllocString(SITE_NAME_PROPERTY);
  4027. if (bstrNameProp)
  4028. {
  4029. hr = pADs->Get(bstrNameProp, &varName);
  4030. if (SUCCEEDED(hr))
  4031. {
  4032. LPOLESTR sz = new OLECHAR[wcslen(varName.bstrVal) + 1];
  4033. if (sz)
  4034. {
  4035. wcscpy(sz, varName.bstrVal);
  4036. if (*pszSiteName)
  4037. {
  4038. delete [] *pszSiteName;
  4039. }
  4040. *pszSiteName = sz;
  4041. }
  4042. }
  4043. SysFreeString(bstrNameProp);
  4044. }
  4045. VariantClear(&varName);
  4046. pADs->Release();
  4047. }
  4048. delete [] szData;
  4049. }
  4050. return TRUE;
  4051. }