Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

6131 lines
158 KiB

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