Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3641 lines
101 KiB

  1. /******************************************************************************
  2. *
  3. * Copyright (c) 2000 Microsoft Corporation
  4. *
  5. * Module Name:
  6. * utils.cpp
  7. *
  8. * Abstract:
  9. * Definitions of commonly used util functions.
  10. *
  11. * Revision History:
  12. * Brijesh Krishnaswami (brijeshk) 03/17/2000
  13. * created
  14. *
  15. *****************************************************************************/
  16. #include <nt.h>
  17. #include <ntrtl.h>
  18. #include <nturtl.h>
  19. #include <windows.h>
  20. #include <winioctl.h>
  21. #include "srdefs.h"
  22. #include "utils.h"
  23. #include <dbgtrace.h>
  24. #include <stdio.h>
  25. #include <objbase.h>
  26. #include <ntlsa.h>
  27. #include <accctrl.h>
  28. #include <aclapi.h>
  29. #include <malloc.h>
  30. #include <wchar.h>
  31. #include "srapi.h"
  32. #ifdef THIS_FILE
  33. #undef THIS_FILE
  34. #endif
  35. static char __szTraceSourceFile[] = __FILE__;
  36. #define THIS_FILE __szTraceSourceFile
  37. #define WBEM_DIRECTORY L"wbem"
  38. #define FRAMEDYN_DLL L"framedyn.dll"
  39. // forward declaration for Delnode_Recurse
  40. BOOL SRGetAltFileName( LPCWSTR cszPath, LPWSTR szAltName );
  41. #define TRACEID 1893
  42. // this function converts an ANSI string to UNICODE.
  43. // this also allocates the memory for the new string
  44. WCHAR * ConvertToUnicode(CHAR * pszString)
  45. {
  46. WCHAR * pwszUnicodeString = NULL;
  47. DWORD dwBytesNeeded = 0;
  48. TENTER("ConvertToUnicode");
  49. dwBytesNeeded = (lstrlenA(pszString) + 1) * sizeof(WCHAR);
  50. pwszUnicodeString = (PWCHAR) SRMemAlloc(dwBytesNeeded);
  51. if(NULL == pwszUnicodeString)
  52. {
  53. TRACE(0, "Not enough memory");
  54. goto cleanup;
  55. }
  56. // Convert filename to Unicode
  57. if (!MultiByteToWideChar(CP_ACP, // code page
  58. 0, // no options
  59. pszString, // ANSI string
  60. -1, // NULL terminated string
  61. pwszUnicodeString, // output buffer
  62. dwBytesNeeded/sizeof(WCHAR)))
  63. // size in wide chars
  64. {
  65. DWORD dwReturnCode;
  66. dwReturnCode=GetLastError();
  67. TRACE(0, "Failed to do conversion ec=%d", dwReturnCode);
  68. SRMemFree(pwszUnicodeString);
  69. goto cleanup;
  70. }
  71. cleanup:
  72. TLEAVE();
  73. return pwszUnicodeString;
  74. }
  75. // this function converts a UNICODE string to ANSI.
  76. // this also allocates the memory for the new string
  77. CHAR * ConvertToANSI(WCHAR * pwszString)
  78. {
  79. CHAR * pszANSIString = NULL;
  80. DWORD dwBytesNeeded = lstrlenW(pwszString) + sizeof(char);
  81. TENTER("ConvertToANSI");
  82. // note that the string may already be NULL terminated - however
  83. // we cannot assume this and will still allocate space to put a
  84. // NULL character in the end.
  85. pszANSIString = (PCHAR) SRMemAlloc(dwBytesNeeded);
  86. if(NULL == pszANSIString)
  87. {
  88. TRACE(0, "Not enough memory");
  89. goto cleanup;
  90. }
  91. // Convert filename to Unicode
  92. if (!WideCharToMultiByte(CP_ACP, // code page
  93. 0, // no options
  94. pwszString, // Wide char string
  95. dwBytesNeeded, // no of wchars
  96. pszANSIString, // output buffer
  97. dwBytesNeeded, // size of buffer
  98. NULL, // address of default for unmappable
  99. // characters
  100. NULL)) // address of flag set when default
  101. // char. used
  102. {
  103. DWORD dwReturnCode;
  104. dwReturnCode=GetLastError();
  105. TRACE(0, "Failed to do conversion ec=%d", dwReturnCode);
  106. SRMemFree(pszANSIString); //this sets pwszUnicodeString to NULL
  107. goto cleanup;
  108. }
  109. // set last char to NULL
  110. pszANSIString[dwBytesNeeded-1] = '\0';
  111. cleanup:
  112. TraceFunctLeave();
  113. return pszANSIString;
  114. }
  115. //+---------------------------------------------------------------------------
  116. //
  117. // Function: TakeOwn
  118. //
  119. // Synopsis: attempts to take ACL ownership of the file for deletion
  120. //
  121. // Arguments: [pwszFile] -- file name
  122. //
  123. // Returns: Win32 error code
  124. //
  125. // History: 12-Apr-2000 HenryLee Created
  126. //
  127. //----------------------------------------------------------------------------
  128. DWORD TakeOwn (const WCHAR *pwszFile)
  129. {
  130. SID * pSid = NULL;
  131. DWORD dwErr = ERROR_SUCCESS;
  132. SECURITY_DESCRIPTOR sd;
  133. InitializeSecurityDescriptor( &sd, SECURITY_DESCRIPTOR_REVISION );
  134. if (FALSE == SetSecurityDescriptorDacl (&sd, TRUE, NULL, FALSE ))
  135. {
  136. dwErr = GetLastError();
  137. goto Err;
  138. }
  139. if (FALSE == SetFileSecurity (pwszFile, DACL_SECURITY_INFORMATION, &sd))
  140. {
  141. dwErr = GetLastError();
  142. goto Err;
  143. }
  144. // Okay, that didn't work, try to make Administrator the owner
  145. if (dwErr != ERROR_SUCCESS)
  146. {
  147. SID_IDENTIFIER_AUTHORITY SepNtAuthority = SECURITY_NT_AUTHORITY;
  148. if (FALSE == AllocateAndInitializeSid(
  149. &SepNtAuthority, 2,
  150. SECURITY_BUILTIN_DOMAIN_RID,
  151. DOMAIN_ALIAS_RID_ADMINS,
  152. 0, 0, 0, 0, 0, 0, (void **) &pSid ))
  153. {
  154. dwErr = GetLastError();
  155. goto Err;
  156. }
  157. if (FALSE == SetSecurityDescriptorOwner (&sd, pSid, FALSE ))
  158. {
  159. dwErr = GetLastError();
  160. goto Err;
  161. }
  162. if (FALSE == SetFileSecurity(pwszFile, OWNER_SECURITY_INFORMATION, &sd))
  163. {
  164. dwErr = GetLastError();
  165. goto Err;
  166. }
  167. }
  168. Err:
  169. if (pSid != NULL)
  170. FreeSid (pSid);
  171. return dwErr;
  172. }
  173. //+---------------------------------------------------------------------------
  174. //
  175. // Function: CopyFile_Recurse
  176. //
  177. // Synopsis: attempt to copy disk space used by a file tree
  178. //
  179. // Arguments: [pwszSource] -- directory name
  180. // [pwszDest] -- destination directory name
  181. //
  182. // Returns: Win32 error code
  183. //
  184. // History: 12-Apr-2000 HenryLee Created
  185. //
  186. //----------------------------------------------------------------------------
  187. DWORD CopyFile_Recurse (const WCHAR *pwszSource, const WCHAR *pwszDest)
  188. {
  189. DWORD dwErr = ERROR_SUCCESS;
  190. WIN32_FIND_DATA fd;
  191. HANDLE hFile;
  192. WCHAR wcsPath[MAX_PATH];
  193. WCHAR wcsDest2[MAX_PATH];
  194. if (lstrlenW(pwszSource) + 4 >= MAX_PATH)
  195. return ERROR_SUCCESS;
  196. lstrcpy (wcsPath, pwszSource);
  197. lstrcat (wcsPath, TEXT("\\*.*"));
  198. hFile = FindFirstFile(wcsPath, &fd);
  199. if (hFile == INVALID_HANDLE_VALUE)
  200. {
  201. dwErr = GetLastError();
  202. return dwErr;
  203. }
  204. do
  205. {
  206. if (!lstrcmp(fd.cFileName, L".") || !lstrcmp(fd.cFileName, L".."))
  207. {
  208. continue;
  209. }
  210. if (lstrlenW(pwszSource) + lstrlenW(fd.cFileName) + 1 >= MAX_PATH ||
  211. lstrlenW(pwszDest) + lstrlenW(fd.cFileName) + 1 >= MAX_PATH)
  212. continue; // skip files with long paths
  213. lstrcpy (wcsPath, pwszSource); // construct the full path name
  214. lstrcat (wcsPath, TEXT("\\"));
  215. lstrcat (wcsPath, fd.cFileName);
  216. lstrcpy (wcsDest2, pwszDest); // construct the full path name
  217. lstrcat (wcsDest2, TEXT("\\"));
  218. lstrcat (wcsDest2, fd.cFileName);
  219. if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  220. {
  221. if (FALSE == CreateDirectoryW (wcsDest2, NULL))
  222. {
  223. dwErr = GetLastError();
  224. if (dwErr != ERROR_ALREADY_EXISTS)
  225. {
  226. FindClose (hFile);
  227. return dwErr;
  228. }
  229. else dwErr = ERROR_SUCCESS;
  230. }
  231. dwErr = CopyFile_Recurse (wcsPath, wcsDest2);
  232. if (dwErr != ERROR_SUCCESS)
  233. {
  234. FindClose (hFile);
  235. return dwErr;
  236. }
  237. }
  238. else
  239. {
  240. //
  241. // We found a file. Copy it.
  242. //
  243. if (FALSE == CopyFileW (wcsPath, wcsDest2, FALSE))
  244. {
  245. dwErr = GetLastError();
  246. FindClose (hFile);
  247. return dwErr;
  248. }
  249. }
  250. } while (FindNextFile(hFile, &fd)); // Find the next entry
  251. FindClose(hFile); // Close the search handle
  252. return ERROR_SUCCESS;
  253. }
  254. //+---------------------------------------------------------------------------
  255. //
  256. // Function: GetFileSize_Recurse
  257. //
  258. // Synopsis: attempt to count disk space used by a file tree
  259. //
  260. // Arguments: [pwszDir] -- directory name
  261. // [pllTotalBytes] -- output counter
  262. // [pfStop] -- TRUE if stop signalled
  263. //
  264. // Returns: Win32 error code
  265. //
  266. // History: 12-Apr-2000 HenryLee Created
  267. //
  268. //----------------------------------------------------------------------------
  269. DWORD GetFileSize_Recurse (const WCHAR *pwszDir,
  270. INT64 *pllTotalBytes,
  271. BOOL *pfStop)
  272. {
  273. DWORD dwErr = ERROR_SUCCESS;
  274. WIN32_FIND_DATA fd;
  275. HANDLE hFile;
  276. WCHAR wcsPath[MAX_PATH];
  277. if (lstrlenW(pwszDir) + 4 >= MAX_PATH) // skip paths too long
  278. return ERROR_SUCCESS;
  279. lstrcpy (wcsPath, pwszDir);
  280. lstrcat (wcsPath, TEXT("\\*.*"));
  281. hFile = FindFirstFile(wcsPath, &fd);
  282. if (hFile == INVALID_HANDLE_VALUE)
  283. {
  284. dwErr = GetLastError();
  285. return dwErr;
  286. }
  287. do
  288. {
  289. if (pfStop != NULL && TRUE == *pfStop)
  290. {
  291. FindClose (hFile);
  292. return ERROR_OPERATION_ABORTED;
  293. }
  294. if (!lstrcmp(fd.cFileName, L".") || !lstrcmp(fd.cFileName, L".."))
  295. {
  296. continue;
  297. }
  298. if (lstrlenW(pwszDir) + lstrlenW(fd.cFileName) + 1 >= MAX_PATH)
  299. continue; // skip files too long
  300. lstrcpy (wcsPath, pwszDir); // construct the full path name
  301. lstrcat (wcsPath, TEXT("\\"));
  302. lstrcat (wcsPath, fd.cFileName);
  303. if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  304. {
  305. //
  306. // Found a directory. Skip mount points
  307. //
  308. if (fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
  309. {
  310. continue;
  311. }
  312. dwErr = GetFileSize_Recurse(wcsPath, pllTotalBytes, pfStop);
  313. if (dwErr != ERROR_SUCCESS)
  314. {
  315. FindClose(hFile);
  316. return dwErr;
  317. }
  318. }
  319. else
  320. {
  321. //
  322. // We found a file. Update the counter
  323. //
  324. ULARGE_INTEGER ulTemp;
  325. ulTemp.LowPart = fd.nFileSizeLow;
  326. ulTemp.HighPart = fd.nFileSizeHigh;
  327. #if 0
  328. ulTemp.LowPart = GetCompressedFileSize (wcsPath, &ulTemp.HighPart);
  329. dwErr = (ulTemp.LowPart == 0xFFFFFFFF) ? GetLastError() :
  330. ERROR_SUCCESS;
  331. if (dwErr != ERROR_SUCCESS)
  332. {
  333. FindClose (hFile);
  334. return dwErr;
  335. }
  336. #endif
  337. *pllTotalBytes += ulTemp.QuadPart;
  338. // The file size does not contain the size of the
  339. // NTFS alternate data streams
  340. }
  341. } while (FindNextFile(hFile, &fd)); // Find the next entry
  342. FindClose(hFile); // Close the search handle
  343. return ERROR_SUCCESS;
  344. }
  345. //+---------------------------------------------------------------------------
  346. //
  347. // Function: CompressFile
  348. //
  349. // Synopsis: attempt to compress to decompress an NTFS file
  350. //
  351. // Arguments: [pwszPath] -- directory or file name
  352. // [fCompress] -- TRUE compress, FALSE decompress
  353. // [fDirectory] -- TRUE if directory, FALSE if file
  354. //
  355. // Returns: Win32 error code
  356. //
  357. // History: 12-Apr-2000 HenryLee Created
  358. //
  359. //----------------------------------------------------------------------------
  360. DWORD CompressFile (const WCHAR *pwszPath, BOOL fCompress, BOOL fDirectory)
  361. {
  362. DWORD dwErr = ERROR_SUCCESS;
  363. DWORD dwReturned = 0;
  364. TENTER("CompressFile");
  365. if (pwszPath == NULL)
  366. return ERROR_INVALID_PARAMETER;
  367. DWORD dwFileAttr = GetFileAttributes(pwszPath);
  368. if (dwFileAttr != 0xFFFFFFFF && (dwFileAttr & FILE_ATTRIBUTE_READONLY))
  369. {
  370. dwFileAttr &= ~FILE_ATTRIBUTE_READONLY;
  371. if (FALSE == SetFileAttributes (pwszPath, dwFileAttr))
  372. {
  373. TRACE(0, "SetFileAttributes ignoring %ld", GetLastError());
  374. }
  375. else dwFileAttr |= FILE_ATTRIBUTE_READONLY;
  376. }
  377. USHORT usFormat = fCompress ? COMPRESSION_FORMAT_DEFAULT :
  378. COMPRESSION_FORMAT_NONE;
  379. HANDLE hFile = CreateFile( pwszPath,
  380. GENERIC_READ | GENERIC_WRITE,
  381. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  382. NULL,
  383. OPEN_EXISTING,
  384. fDirectory ? FILE_FLAG_BACKUP_SEMANTICS : 0,
  385. NULL );
  386. if (hFile == INVALID_HANDLE_VALUE)
  387. {
  388. dwErr = GetLastError();
  389. TRACE(0, "CompressFile: cannot open %ld %ws", dwErr, pwszPath);
  390. return dwErr;
  391. }
  392. if (FALSE == DeviceIoControl (hFile,
  393. FSCTL_SET_COMPRESSION,
  394. &usFormat, sizeof(usFormat),
  395. NULL, 0, &dwReturned, NULL))
  396. {
  397. dwErr = GetLastError();
  398. TRACE(0, "CompressFile: cannot compress/uncompress %ld %ws", dwErr, pwszPath);
  399. }
  400. CloseHandle (hFile);
  401. if (dwFileAttr != 0xFFFFFFFF && (dwFileAttr & FILE_ATTRIBUTE_READONLY))
  402. {
  403. if (FALSE == SetFileAttributes (pwszPath, dwFileAttr))
  404. {
  405. TRACE(0, "SetFileAttributes failed ignoring %ld", GetLastError());
  406. }
  407. }
  408. TLEAVE();
  409. return dwErr;
  410. }
  411. // returns system drive - as L"C:\\" if C: is the system drive
  412. BOOL
  413. GetSystemDrive(LPWSTR pszDrive)
  414. {
  415. if (pszDrive)
  416. return ExpandEnvironmentStrings(L"%SystemDrive%\\", pszDrive, MAX_SYS_DRIVE);
  417. else
  418. return FALSE;
  419. }
  420. // BUGBUG - pszDrive should have driveletter in caps,
  421. // and needs to be of format L"C:\\" if C: is the system drive
  422. BOOL
  423. IsSystemDrive(LPWSTR pszDriveOrGuid)
  424. {
  425. WCHAR szSystemDrive[MAX_PATH];
  426. WCHAR szSystemGuid[MAX_PATH];
  427. if (pszDriveOrGuid)
  428. {
  429. if (0 == ExpandEnvironmentStrings(L"%SystemDrive%\\", szSystemDrive, sizeof(szSystemDrive)/sizeof(WCHAR)))
  430. {
  431. return FALSE;
  432. }
  433. if (0 == wcsncmp(pszDriveOrGuid, L"\\\\?\\Volume", 10)) // guid
  434. {
  435. if (! GetVolumeNameForVolumeMountPoint(szSystemDrive, szSystemGuid, MAX_PATH))
  436. {
  437. return FALSE;
  438. }
  439. return lstrcmpi(pszDriveOrGuid, szSystemGuid) ? FALSE : TRUE;
  440. }
  441. else // drive
  442. {
  443. return lstrcmpi(pszDriveOrGuid, szSystemDrive) ? FALSE : TRUE;
  444. }
  445. }
  446. else
  447. {
  448. return FALSE;
  449. }
  450. }
  451. DWORD
  452. RegReadDWORD(HKEY hKey, LPCWSTR pszName, PDWORD pdwValue)
  453. {
  454. DWORD dwType = REG_DWORD;
  455. DWORD dwSize = sizeof(DWORD);
  456. DWORD dwRc = RegQueryValueEx(hKey, pszName, 0, &dwType, (LPBYTE) pdwValue, &dwSize);
  457. return dwRc;
  458. }
  459. DWORD
  460. RegWriteDWORD(HKEY hKey, LPCWSTR pszName, PDWORD pdwValue)
  461. {
  462. DWORD dwType = REG_DWORD;
  463. DWORD dwSize = sizeof(DWORD);
  464. DWORD dwRc = RegSetValueEx(hKey, pszName, 0, dwType, (LPBYTE) pdwValue, dwSize);
  465. return dwRc;
  466. }
  467. // function that returns n where pszStr is of form <someprefix>n
  468. ULONG
  469. GetID(
  470. LPCWSTR pszStr)
  471. {
  472. ULONG ulID = 0;
  473. while (*pszStr && (*pszStr < L'0' || *pszStr > L'9'))
  474. pszStr++;
  475. ulID = (ULONG) _wtol(pszStr);
  476. return ulID;
  477. }
  478. LPWSTR
  479. GetMachineGuid()
  480. {
  481. HKEY hKey = NULL;
  482. static WCHAR s_szGuid[GUID_STRLEN] = L"";
  483. static LPWSTR s_pszGuid = NULL;
  484. if (! s_pszGuid) // first time
  485. {
  486. ULONG ulType, ulSize = sizeof(s_szGuid);
  487. DWORD dwErr;
  488. dwErr = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  489. s_cszSRCfgRegKey, 0,
  490. KEY_READ, &hKey);
  491. if (dwErr != ERROR_SUCCESS)
  492. goto Err;
  493. dwErr = RegQueryValueEx (hKey, s_cszSRMachineGuid,
  494. 0, &ulType, (BYTE *) &s_szGuid,
  495. &ulSize);
  496. if (dwErr != ERROR_SUCCESS)
  497. goto Err;
  498. s_pszGuid = (LPWSTR) s_szGuid;
  499. }
  500. Err:
  501. if (hKey)
  502. RegCloseKey(hKey);
  503. return s_pszGuid;
  504. }
  505. // util function to construct <pszDrive>_Restore.{MachineGuid}\\pszSuffix
  506. LPWSTR
  507. MakeRestorePath(LPWSTR pszDest, LPCWSTR pszDrive, LPCWSTR pszSuffix)
  508. {
  509. LPWSTR pszGuid = GetMachineGuid();
  510. wsprintf(pszDest,
  511. L"%s%s\\%s",
  512. pszDrive,
  513. s_cszSysVolInfo,
  514. s_cszRestoreDir);
  515. if (pszGuid)
  516. {
  517. // lstrcat(pszDest, L".");
  518. lstrcat(pszDest, pszGuid);
  519. }
  520. if (pszSuffix && lstrlen(pszSuffix) > 0)
  521. {
  522. lstrcat(pszDest, L"\\");
  523. lstrcat(pszDest, pszSuffix);
  524. }
  525. return pszDest;
  526. }
  527. // set start type of specified service directly in the registry
  528. DWORD
  529. SetServiceStartupRegistry(LPCWSTR pszName, DWORD dwStartType)
  530. {
  531. DWORD dwRc;
  532. HKEY hKey = NULL;
  533. WCHAR szKey[MAX_PATH];
  534. lstrcpy(szKey, L"System\\CurrentControlSet\\Services\\");
  535. lstrcat(szKey, pszName);
  536. dwRc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, KEY_WRITE, NULL, &hKey);
  537. if (ERROR_SUCCESS != dwRc)
  538. goto done;
  539. dwRc = RegWriteDWORD(hKey, L"Start", &dwStartType);
  540. done:
  541. if (hKey)
  542. RegCloseKey(hKey);
  543. return dwRc;
  544. }
  545. // get start type of specified service directly from the registry
  546. DWORD
  547. GetServiceStartupRegistry(LPCWSTR pszName, PDWORD pdwStartType)
  548. {
  549. DWORD dwRc;
  550. HKEY hKey = NULL;
  551. WCHAR szKey[MAX_PATH];
  552. lstrcpy(szKey, L"System\\CurrentControlSet\\Services\\");
  553. lstrcat(szKey, pszName);
  554. dwRc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, KEY_QUERY_VALUE, NULL, &hKey);
  555. if (ERROR_SUCCESS != dwRc)
  556. goto done;
  557. dwRc = RegReadDWORD(hKey, L"Start", pdwStartType);
  558. done:
  559. if (hKey)
  560. RegCloseKey(hKey);
  561. return dwRc;
  562. }
  563. DWORD
  564. SetServiceStartup(LPCWSTR pszName, DWORD dwStartType)
  565. {
  566. TraceFunctEnter("SetServiceStartup");
  567. DWORD dwError=ERROR_INTERNAL_ERROR;
  568. SC_HANDLE hService=NULL;
  569. SC_HANDLE hSCManager=NULL;
  570. hSCManager = OpenSCManager(NULL, // computer name - local machine
  571. NULL,//SCM DB name - SERVICES_ACTIVE_DATABASE
  572. SC_MANAGER_ALL_ACCESS); // access type
  573. if( NULL == hSCManager)
  574. {
  575. dwError = GetLastError();
  576. // file not found
  577. DebugTrace(TRACEID,"OpenSCManager failed 0x%x", dwError);
  578. goto done;
  579. }
  580. hService = OpenService(hSCManager, // handle to SCM database
  581. pszName, // service name
  582. SERVICE_CHANGE_CONFIG); // access
  583. if( NULL == hService)
  584. {
  585. dwError = GetLastError();
  586. // file not found
  587. DebugTrace(TRACEID,"OpenService failed 0x%x", dwError);
  588. goto done;
  589. }
  590. if (FALSE==ChangeServiceConfig( hService, // handle to service
  591. SERVICE_NO_CHANGE, // type of service
  592. dwStartType, // when to start service
  593. SERVICE_NO_CHANGE, // severity of start failure
  594. NULL, // service binary file name
  595. NULL, // load ordering group name
  596. NULL, // tag identifier
  597. NULL, // array of dependency names
  598. NULL, // account name
  599. NULL, // account password
  600. NULL)) // display name
  601. {
  602. dwError = GetLastError();
  603. // file not found
  604. DebugTrace(TRACEID,"ChangeServiceConfig failed 0x%x", dwError);
  605. goto done;
  606. }
  607. dwError = ERROR_SUCCESS;
  608. done:
  609. if (NULL != hService)
  610. {
  611. _VERIFY(CloseServiceHandle(hService)); // handle to service or
  612. // SCM object
  613. }
  614. if (NULL != hSCManager)
  615. {
  616. _VERIFY(CloseServiceHandle(hSCManager)); // handle to service or
  617. // SCM object
  618. }
  619. if ((dwError != ERROR_SUCCESS) && (dwError != ERROR_ACCESS_DENIED))
  620. {
  621. // service control methods failed. Just update the registry
  622. // directly
  623. dwError = SetServiceStartupRegistry(pszName, dwStartType);
  624. }
  625. TraceFunctLeave();
  626. return dwError;
  627. }
  628. DWORD
  629. GetServiceStartup(LPCWSTR pszName, PDWORD pdwStartType)
  630. {
  631. TraceFunctEnter("SetServiceStartup");
  632. DWORD dwError=ERROR_INTERNAL_ERROR;
  633. SC_HANDLE hService=NULL;
  634. SC_HANDLE hSCManager=NULL;
  635. QUERY_SERVICE_CONFIG *pconfig = NULL;
  636. DWORD cbBytes = 0, cbBytes2 = 0;
  637. hSCManager = OpenSCManager(NULL, // computer name - local machine
  638. NULL,//SCM DB name - SERVICES_ACTIVE_DATABASE
  639. SC_MANAGER_ALL_ACCESS); // access type
  640. if( NULL == hSCManager)
  641. {
  642. dwError = GetLastError();
  643. // file not found
  644. DebugTrace(TRACEID,"OpenSCManager failed 0x%x", dwError);
  645. goto done;
  646. }
  647. hService = OpenService(hSCManager, // handle to SCM database
  648. pszName, // service name
  649. SERVICE_QUERY_CONFIG); // access
  650. if( NULL == hService)
  651. {
  652. dwError = GetLastError();
  653. // file not found
  654. DebugTrace(TRACEID,"OpenService failed 0x%x", dwError);
  655. goto done;
  656. }
  657. if (FALSE==QueryServiceConfig( hService, // handle to service
  658. NULL,
  659. 0,
  660. &cbBytes ))
  661. {
  662. dwError = GetLastError();
  663. if (ERROR_INSUFFICIENT_BUFFER == dwError)
  664. {
  665. pconfig = (QUERY_SERVICE_CONFIG *) SRMemAlloc(cbBytes);
  666. if (!pconfig)
  667. {
  668. trace(TRACEID, "! SRMemAlloc");
  669. goto done;
  670. }
  671. if (FALSE==QueryServiceConfig( hService, // handle to service
  672. pconfig,
  673. cbBytes,
  674. &cbBytes2 ))
  675. {
  676. dwError = GetLastError();
  677. DebugTrace(TRACEID,"! QueryServiceConfig (second) : %ld", dwError);
  678. goto done;
  679. }
  680. if (pdwStartType)
  681. {
  682. *pdwStartType = pconfig->dwStartType;
  683. }
  684. dwError = ERROR_SUCCESS;
  685. }
  686. else
  687. {
  688. trace(TRACEID, "! QueryServiceConfig (first) : %ld", dwError);
  689. }
  690. }
  691. done:
  692. SRMemFree(pconfig);
  693. if (NULL != hService)
  694. {
  695. _VERIFY(CloseServiceHandle(hService)); // handle to service or
  696. // SCM object
  697. }
  698. if (NULL != hSCManager)
  699. {
  700. _VERIFY(CloseServiceHandle(hSCManager)); // handle to service or
  701. // SCM object
  702. }
  703. TraceFunctLeave();
  704. return dwError;
  705. }
  706. // this function returns whether the SR service is running
  707. BOOL IsSRServiceRunning()
  708. {
  709. TraceFunctEnter("IsSRServiceRunning");
  710. BOOL fReturn;
  711. DWORD dwError=ERROR_INTERNAL_ERROR;
  712. SC_HANDLE hService=NULL;
  713. SC_HANDLE hSCManager=NULL;
  714. SERVICE_STATUS ServiceStatus;
  715. // assume FALSE by default
  716. fReturn = FALSE;
  717. hSCManager = OpenSCManager(NULL, // computer name - local machine
  718. NULL,//SCM DB name - SERVICES_ACTIVE_DATABASE
  719. SC_MANAGER_ALL_ACCESS); // access type
  720. if( NULL == hSCManager)
  721. {
  722. dwError = GetLastError();
  723. DebugTrace(TRACEID,"OpenSCManager failed 0x%x", dwError);
  724. goto done;
  725. }
  726. hService = OpenService(hSCManager, // handle to SCM database
  727. s_cszServiceName, // service name
  728. SERVICE_QUERY_STATUS); // access
  729. if( NULL == hService)
  730. {
  731. dwError = GetLastError();
  732. DebugTrace(TRACEID,"OpenService failed 0x%x", dwError);
  733. goto done;
  734. }
  735. if (FALSE == QueryServiceStatus(hService, // handle to service
  736. &ServiceStatus)) // service status
  737. {
  738. dwError = GetLastError();
  739. DebugTrace(TRACEID,"QueryServiceStatus failed 0x%x", dwError);
  740. goto done;
  741. }
  742. if (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
  743. {
  744. fReturn = TRUE;
  745. }
  746. else
  747. {
  748. DebugTrace(TRACEID,"SR Service is not running");
  749. fReturn = FALSE;
  750. }
  751. done:
  752. if (NULL != hService)
  753. {
  754. _VERIFY(CloseServiceHandle(hService)); // handle to service or
  755. // SCM object
  756. }
  757. if (NULL != hSCManager)
  758. {
  759. _VERIFY(CloseServiceHandle(hSCManager)); // handle to service or
  760. // SCM object
  761. }
  762. TraceFunctLeave();
  763. return fReturn;
  764. }
  765. // this function returns whether the SR service is running
  766. BOOL IsSRServiceStopped(SC_HANDLE hService)
  767. {
  768. TraceFunctEnter("IsSRServiceStopped");
  769. SERVICE_STATUS ServiceStatus;
  770. BOOL fReturn;
  771. DWORD dwError;
  772. // assume FALSE by default
  773. fReturn = FALSE;
  774. if (FALSE == QueryServiceStatus(hService, // handle to service
  775. &ServiceStatus)) // service status
  776. {
  777. dwError = GetLastError();
  778. DebugTrace(TRACEID,"QueryServiceStatus failed 0x%x", dwError);
  779. goto done;
  780. }
  781. if (ServiceStatus.dwCurrentState == SERVICE_STOPPED)
  782. {
  783. DebugTrace(TRACEID,"SR Service is not running");
  784. fReturn = TRUE;
  785. }
  786. else
  787. {
  788. DebugTrace(TRACEID,"SR Service is running");
  789. fReturn = FALSE;
  790. }
  791. done:
  792. TraceFunctLeave();
  793. return fReturn;
  794. }
  795. // private function to stop the SR service
  796. // fWait - if TRUE : function is synchronous - waits till service is stopped completely
  797. // if FALSE : function is asynchronous - does not wait for service to complete stopping
  798. BOOL StopSRService(BOOL fWait)
  799. {
  800. TraceFunctEnter("StopSRService");
  801. BOOL fReturn=FALSE;
  802. SC_HANDLE hSCManager;
  803. SERVICE_STATUS ServiceStatus;
  804. SC_HANDLE hService=NULL;
  805. DWORD dwError;
  806. hSCManager = OpenSCManager(NULL, // computer name - local machine
  807. NULL,//SCM DB name - SERVICES_ACTIVE_DATABASE
  808. SC_MANAGER_ALL_ACCESS); // access type
  809. if (NULL == hSCManager)
  810. {
  811. dwError = GetLastError();
  812. DebugTrace(TRACEID,"OpenSCManager failed 0x%x", dwError);
  813. goto done;
  814. }
  815. hService = OpenService(hSCManager, // handle to SCM database
  816. s_cszServiceName, // service name
  817. SERVICE_ALL_ACCESS); // access
  818. if( NULL == hService)
  819. {
  820. dwError = GetLastError();
  821. DebugTrace(TRACEID,"OpenService failed 0x%x", dwError);
  822. goto done;
  823. }
  824. fReturn = ControlService(hService, // handle to service
  825. SERVICE_CONTROL_STOP, // control code
  826. &ServiceStatus); // status information
  827. if (FALSE == fReturn)
  828. {
  829. dwError = GetLastError();
  830. DebugTrace(TRACEID,"ControlService failed 0x%x", dwError);
  831. goto done;
  832. }
  833. if (fWait)
  834. {
  835. DWORD dwCount;
  836. //
  837. // query the service until it stops
  838. // try thrice
  839. //
  840. Sleep(500);
  841. for (dwCount=0; dwCount < 3; dwCount++)
  842. {
  843. if (TRUE == IsSRServiceStopped(hService))
  844. {
  845. break;
  846. }
  847. Sleep(2000);
  848. }
  849. if (dwCount == 3)
  850. {
  851. fReturn=IsSRServiceStopped(hService);
  852. }
  853. else
  854. {
  855. fReturn=TRUE;
  856. }
  857. }
  858. done:
  859. if (NULL != hService)
  860. {
  861. _VERIFY(CloseServiceHandle(hService)); // handle to service or
  862. // SCM object
  863. }
  864. if (NULL != hSCManager)
  865. {
  866. _VERIFY(CloseServiceHandle(hSCManager)); // handle to service or
  867. // SCM object
  868. }
  869. TraceFunctLeave();
  870. return fReturn;
  871. }
  872. //+---------------------------------------------------------------------------
  873. //
  874. // Function: GetLsaSecret
  875. //
  876. // Synopsis: obtains the LSA secret info as Unicode strings
  877. //
  878. // Arguments: [hPolicy] -- LSA policy object handle
  879. // [wszSecret] -- secret name
  880. // [ppusSecretValue] -- dynamically allocated value
  881. //
  882. // Returns: Win32 error code
  883. //
  884. // History: 12-Apr-2000 HenryLee Created
  885. //
  886. //----------------------------------------------------------------------------
  887. DWORD GetLsaSecret (LSA_HANDLE hPolicy, const WCHAR *wszSecret,
  888. UNICODE_STRING ** ppusSecretValue)
  889. {
  890. TENTER ("GetLsaSecret");
  891. LSA_HANDLE hSecret;
  892. UNICODE_STRING usSecretName;
  893. DWORD dwErr = ERROR_SUCCESS;
  894. RtlInitUnicodeString (&usSecretName, wszSecret);
  895. if (LSA_SUCCESS (LsaOpenSecret (hPolicy,
  896. &usSecretName,
  897. SECRET_QUERY_VALUE,
  898. &hSecret)))
  899. {
  900. if (!LSA_SUCCESS (LsaQuerySecret (hSecret,
  901. ppusSecretValue,
  902. NULL,
  903. NULL,
  904. NULL)))
  905. {
  906. *ppusSecretValue = NULL;
  907. TRACE(0, "Cannot query secret %ws", wszSecret);
  908. }
  909. LsaClose (hSecret);
  910. }
  911. TLEAVE();
  912. return dwErr;
  913. }
  914. //+---------------------------------------------------------------------------
  915. //
  916. // Function: SetLsaSecret
  917. //
  918. // Synopsis: sets the LSA secret info
  919. //
  920. // Arguments: [hPolicy] -- LSA policy object handle
  921. // [wszSecret] -- secret name
  922. // [wszSecretValue] -- secret value
  923. //
  924. // Returns: Win32 error code
  925. //
  926. // History: 12-Apr-2000 HenryLee Created
  927. //
  928. //----------------------------------------------------------------------------
  929. DWORD SetLsaSecret (PVOID hPolicy, const WCHAR *wszSecret,
  930. WCHAR * wszSecretValue)
  931. {
  932. TENTER ("SetLsaSecret");
  933. LSA_HANDLE hSecret;
  934. UNICODE_STRING usSecretName;
  935. UNICODE_STRING usSecretValue;
  936. DWORD dwErr = ERROR_SUCCESS;
  937. hPolicy = (LSA_HANDLE) hPolicy;
  938. RtlInitUnicodeString (&usSecretName, wszSecret);
  939. RtlInitUnicodeString (&usSecretValue, wszSecretValue);
  940. if (LSA_SUCCESS (LsaOpenSecret (hPolicy,
  941. &usSecretName,
  942. SECRET_SET_VALUE,
  943. &hSecret)))
  944. {
  945. if (!LSA_SUCCESS (LsaSetSecret (hSecret,
  946. &usSecretValue,
  947. NULL)))
  948. {
  949. TRACE(0, "Cannot set secret %ws", wszSecret);
  950. }
  951. LsaClose (hSecret);
  952. }
  953. TLEAVE();
  954. return dwErr;
  955. }
  956. //+---------------------------------------------------------------------------
  957. //
  958. // Function: WriteNtUnicodeString
  959. //
  960. // Synopsis: writes a NT unicode string to disk
  961. //
  962. // Arguments: [hFile] -- file handle
  963. // [pus] -- NT unicode string
  964. //
  965. // Returns: Win32 error code
  966. //
  967. // History: 12-Apr-2000 HenryLee Created
  968. //
  969. //----------------------------------------------------------------------------
  970. DWORD WriteNtUnicodeString (HANDLE hFile, UNICODE_STRING *pus)
  971. {
  972. DWORD dwErr = ERROR_SUCCESS;
  973. DWORD cb = 0;
  974. if (pus != NULL &&
  975. FALSE == WriteFile (hFile, (BYTE *)pus->Buffer, pus->Length, &cb, NULL))
  976. {
  977. dwErr = GetLastError();
  978. }
  979. else if (FALSE == WriteFile (hFile, (BYTE *) L"", sizeof(WCHAR), &cb, NULL))
  980. {
  981. dwErr = GetLastError();
  982. }
  983. return dwErr;
  984. }
  985. //+---------------------------------------------------------------------------
  986. //
  987. // Function: GetLsaRestoreState
  988. //
  989. // Synopsis: gets the LSA machine and autologon password
  990. //
  991. // Arguments: [hKeySoftware] -- Software registry key
  992. //
  993. // Returns: Win32 error code
  994. //
  995. // History: 12-Apr-2000 HenryLee Created
  996. //
  997. //----------------------------------------------------------------------------
  998. DWORD GetLsaRestoreState (HKEY hKeySoftware)
  999. {
  1000. TENTER ("GetLsaRestoreState");
  1001. HKEY hKey = NULL;
  1002. LSA_OBJECT_ATTRIBUTES loa;
  1003. LSA_HANDLE hLsa = NULL;
  1004. DWORD dwErr = ERROR_SUCCESS;
  1005. loa.Length = sizeof(LSA_OBJECT_ATTRIBUTES);
  1006. loa.RootDirectory = NULL;
  1007. loa.ObjectName = NULL;
  1008. loa.Attributes = 0;
  1009. loa.SecurityDescriptor = NULL;
  1010. loa.SecurityQualityOfService = NULL;
  1011. if (LSA_SUCCESS (LsaOpenPolicy(NULL, &loa,
  1012. POLICY_VIEW_LOCAL_INFORMATION, &hLsa)))
  1013. {
  1014. UNICODE_STRING * pusSecret = NULL;
  1015. dwErr = RegOpenKeyEx (hKeySoftware,
  1016. hKeySoftware == HKEY_LOCAL_MACHINE ? s_cszSRRegKey :
  1017. L"Microsoft\\Windows NT\\CurrentVersion\\SystemRestore", 0,
  1018. KEY_READ | KEY_WRITE, &hKey);
  1019. if (dwErr != ERROR_SUCCESS)
  1020. goto Err;
  1021. if (ERROR_SUCCESS==GetLsaSecret (hLsa, s_cszMachineSecret, &pusSecret))
  1022. {
  1023. if (pusSecret != NULL && pusSecret->Length > 0)
  1024. dwErr = RegSetValueEx (hKey, s_cszMachineSecret,
  1025. 0, REG_BINARY, (BYTE *) pusSecret->Buffer,
  1026. pusSecret->Length);
  1027. LsaFreeMemory (pusSecret);
  1028. pusSecret = NULL;
  1029. }
  1030. if (ERROR_SUCCESS==GetLsaSecret(hLsa, s_cszAutologonSecret, &pusSecret))
  1031. {
  1032. if (pusSecret != NULL && pusSecret->Length > 0)
  1033. dwErr = RegSetValueEx (hKey, s_cszAutologonSecret,
  1034. 0, REG_BINARY, (BYTE *) pusSecret->Buffer,
  1035. pusSecret->Length);
  1036. LsaFreeMemory (pusSecret);
  1037. pusSecret = NULL;
  1038. }
  1039. }
  1040. Err:
  1041. if (hLsa != NULL)
  1042. LsaClose (hLsa);
  1043. if (hKey != NULL)
  1044. RegCloseKey (hKey);
  1045. TLEAVE();
  1046. return dwErr;
  1047. }
  1048. //+---------------------------------------------------------------------------
  1049. //
  1050. // Function: GetDomainMembershipInfo
  1051. //
  1052. // Synopsis: writes current domain and computer name into a file
  1053. //
  1054. // Arguments: [pwszPath] -- file name
  1055. // [pwszzBuffer] -- output multistring buffer
  1056. //
  1057. // Returns: Win32 error code
  1058. //
  1059. // History: 12-Apr-2000 HenryLee Created
  1060. //
  1061. //----------------------------------------------------------------------------
  1062. DWORD GetDomainMembershipInfo (WCHAR *pwszPath, WCHAR *pwszzBuffer)
  1063. {
  1064. TENTER("GetDomainMembershipInfo");
  1065. POLICY_PRIMARY_DOMAIN_INFO* ppdi = NULL;
  1066. LSA_OBJECT_ATTRIBUTES loa;
  1067. LSA_HANDLE hLsa = NULL;
  1068. HANDLE hFile = INVALID_HANDLE_VALUE;
  1069. DWORD dwComputerLength = MAX_COMPUTERNAME_LENGTH + 1;
  1070. DWORD dwRc = ERROR_SUCCESS;
  1071. ULONG cbWritten;
  1072. WCHAR wszComputer[MAX_COMPUTERNAME_LENGTH+1];
  1073. loa.Length = sizeof(LSA_OBJECT_ATTRIBUTES);
  1074. loa.RootDirectory = NULL;
  1075. loa.ObjectName = NULL;
  1076. loa.Attributes = 0;
  1077. loa.SecurityDescriptor = NULL;
  1078. loa.SecurityQualityOfService = NULL;
  1079. if (FALSE == GetComputerNameW (wszComputer, &dwComputerLength))
  1080. {
  1081. dwRc = GetLastError();
  1082. trace(0, "! GetComputerNameW : %ld", dwRc);
  1083. return dwRc;
  1084. }
  1085. if (LSA_SUCCESS (LsaOpenPolicy(NULL, &loa,
  1086. POLICY_VIEW_LOCAL_INFORMATION, &hLsa)))
  1087. {
  1088. if (pwszPath != NULL)
  1089. {
  1090. hFile = CreateFileW ( pwszPath, // file name
  1091. GENERIC_WRITE, // file access
  1092. 0, // share mode
  1093. NULL, // SD
  1094. CREATE_ALWAYS, // how to create
  1095. 0, // file attributes
  1096. NULL); // handle to template file
  1097. if (INVALID_HANDLE_VALUE == hFile)
  1098. {
  1099. dwRc = GetLastError();
  1100. trace(0, "! CreateFileW : %ld", dwRc);
  1101. goto Err;
  1102. }
  1103. if (FALSE == WriteFile (hFile, (BYTE *) wszComputer,
  1104. (dwComputerLength+1)*sizeof(WCHAR), &cbWritten, NULL))
  1105. {
  1106. dwRc = GetLastError();
  1107. trace(0, "! WriteFile : %ld", dwRc);
  1108. goto Err;
  1109. }
  1110. }
  1111. if (pwszzBuffer != NULL)
  1112. {
  1113. lstrcpy (pwszzBuffer, wszComputer);
  1114. pwszzBuffer += dwComputerLength + 1;
  1115. }
  1116. if (LSA_SUCCESS (LsaQueryInformationPolicy( hLsa,
  1117. PolicyPrimaryDomainInformation,
  1118. (VOID **) &ppdi )))
  1119. {
  1120. const WCHAR *pwszFlag = (ppdi->Sid > 0) ? L"1" : L"0";
  1121. if (pwszPath != NULL)
  1122. {
  1123. dwRc = WriteNtUnicodeString (hFile, &ppdi->Name);
  1124. if (dwRc != ERROR_SUCCESS)
  1125. {
  1126. trace(0, "! WriteNtUnicodeString : %ld", dwRc);
  1127. }
  1128. if (FALSE == WriteFile (hFile, (BYTE *) pwszFlag,
  1129. (lstrlenW(pwszFlag)+1)*sizeof(WCHAR), &cbWritten, NULL))
  1130. {
  1131. dwRc = GetLastError();
  1132. trace(0, "! WriteFile : %ld", dwRc);
  1133. goto Err;
  1134. }
  1135. }
  1136. if (pwszzBuffer != NULL)
  1137. {
  1138. ULONG ul = ppdi->Name.Length / sizeof(WCHAR);
  1139. memcpy (pwszzBuffer, ppdi->Name.Buffer, ppdi->Name.Length);
  1140. pwszzBuffer [ul] = L'\0';
  1141. lstrcpy (&pwszzBuffer[ul+1], pwszFlag);
  1142. }
  1143. }
  1144. }
  1145. Err:
  1146. if (hLsa != NULL)
  1147. LsaClose (hLsa);
  1148. if (hFile != INVALID_HANDLE_VALUE)
  1149. CloseHandle (hFile);
  1150. TLEAVE();
  1151. return dwRc;
  1152. }
  1153. //++
  1154. //
  1155. // Method: DoesFileExist
  1156. //
  1157. // Synopsis: Checks if a file by the specified exists
  1158. //
  1159. // Arguments:[pszFileName] File name
  1160. //
  1161. // Returns: TRUE if the specified string is a file
  1162. // False otherwise
  1163. //
  1164. // History: AshishS Created 7/30/96
  1165. //
  1166. //--
  1167. BOOL DoesFileExist(const TCHAR * pszFileName)
  1168. {
  1169. DWORD dwFileAttr, dwError;
  1170. TraceFunctEnter("DoesFileExist");
  1171. DebugTrace(TRACEID, "Checking for %S", pszFileName);
  1172. dwFileAttr = GetFileAttributes(pszFileName);
  1173. if (dwFileAttr == 0xFFFFFFFF )
  1174. {
  1175. dwError = GetLastError();
  1176. // file not found
  1177. DebugTrace(TRACEID,"GetFileAttributes failed 0x%x", dwError);
  1178. TraceFunctLeave();
  1179. return FALSE ;
  1180. }
  1181. if (dwFileAttr & FILE_ATTRIBUTE_DIRECTORY)
  1182. {
  1183. DebugTrace(TRACEID, "It is a Directory ");
  1184. TraceFunctLeave();
  1185. return FALSE;
  1186. }
  1187. DebugTrace(TRACEID, "File exists");
  1188. TraceFunctLeave();
  1189. return TRUE;
  1190. }
  1191. //++
  1192. //
  1193. // Method: DoesDirExist
  1194. //
  1195. // Synopsis: Checks if the specified string is a directory
  1196. //
  1197. // Arguments: [pszFileName] Directory name
  1198. //
  1199. // Returns: TRUE if the specified string is a directory,
  1200. // False otherwise
  1201. //
  1202. // History: AshishS Created 7/30/96
  1203. //
  1204. //--
  1205. BOOL DoesDirExist(const TCHAR * pszFileName )
  1206. {
  1207. DWORD dwFileAttr;
  1208. TraceFunctEnter("DoesDirExist");
  1209. //DebugTrace(TRACEID, " Checking for %S", pszFileName);
  1210. dwFileAttr = GetFileAttributes(pszFileName);
  1211. if (dwFileAttr == 0xFFFFFFFF )
  1212. {
  1213. // file not found
  1214. //DebugTrace(TRACEID,"GetFileAttributes failed 0x%x",
  1215. //GetLastError());
  1216. TraceFunctLeave();
  1217. return FALSE ;
  1218. }
  1219. if (dwFileAttr & FILE_ATTRIBUTE_DIRECTORY)
  1220. {
  1221. //DebugTrace(TRACEID, "Directory exists ");
  1222. TraceFunctLeave();
  1223. return TRUE ;
  1224. }
  1225. //DebugTrace(TRACEID, "Directory does not exist");
  1226. TraceFunctLeave();
  1227. return FALSE;
  1228. }
  1229. // sets acl allowing specific access to LocalSystem/Admin
  1230. // and to everyone
  1231. DWORD
  1232. SetAclInObject(HANDLE hObject, DWORD dwObjectType, DWORD dwSystemMask, DWORD dwEveryoneMask, BOOL fInherit)
  1233. {
  1234. tenter("SetAclInObject");
  1235. DWORD dwRes, dwDisposition;
  1236. PSID pEveryoneSID = NULL, pAdminSID = NULL, pSystemSID = NULL;
  1237. PACL pACL = NULL;
  1238. PSECURITY_DESCRIPTOR pSD = NULL;
  1239. EXPLICIT_ACCESS ea[3];
  1240. SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
  1241. SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
  1242. LONG lRes;
  1243. // Create a well-known SID for the Everyone group.
  1244. if(! AllocateAndInitializeSid( &SIDAuthWorld, 1,
  1245. SECURITY_WORLD_RID,
  1246. 0, 0, 0, 0, 0, 0, 0,
  1247. &pEveryoneSID) )
  1248. {
  1249. dwRes = GetLastError();
  1250. trace(0, "AllocateAndInitializeSid Error %u\n", dwRes);
  1251. goto Cleanup;
  1252. }
  1253. // Initialize an EXPLICIT_ACCESS structure for an ACE.
  1254. // The ACE will allow Everyone read access to the key.
  1255. ZeroMemory(&ea, 3 * sizeof(EXPLICIT_ACCESS));
  1256. ea[0].grfAccessPermissions = dwEveryoneMask;
  1257. ea[0].grfAccessMode = SET_ACCESS;
  1258. ea[0].grfInheritance = fInherit ? SUB_CONTAINERS_AND_OBJECTS_INHERIT : NO_INHERITANCE;
  1259. ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  1260. ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
  1261. ea[0].Trustee.ptstrName = (LPTSTR) pEveryoneSID;
  1262. // Create a SID for the BUILTIN\Administrators group.
  1263. if(! AllocateAndInitializeSid( &SIDAuthNT, 2,
  1264. SECURITY_BUILTIN_DOMAIN_RID,
  1265. DOMAIN_ALIAS_RID_ADMINS,
  1266. 0, 0, 0, 0, 0, 0,
  1267. &pAdminSID) )
  1268. {
  1269. dwRes = GetLastError();
  1270. trace(0, "AllocateAndInitializeSid Error %u\n", dwRes);
  1271. goto Cleanup;
  1272. }
  1273. // Initialize an EXPLICIT_ACCESS structure for an ACE.
  1274. // The ACE will allow the Administrators group full access to the key.
  1275. ea[1].grfAccessPermissions = dwSystemMask;
  1276. ea[1].grfAccessMode = SET_ACCESS;
  1277. ea[1].grfInheritance= fInherit ? SUB_CONTAINERS_AND_OBJECTS_INHERIT : NO_INHERITANCE;
  1278. ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  1279. ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
  1280. ea[1].Trustee.ptstrName = (LPTSTR) pAdminSID;
  1281. // Create a SID for the LocalSystem account
  1282. if(! AllocateAndInitializeSid( &SIDAuthNT, 1,
  1283. SECURITY_LOCAL_SYSTEM_RID,
  1284. 0, 0, 0, 0, 0, 0, 0,
  1285. &pSystemSID) )
  1286. {
  1287. dwRes = GetLastError();
  1288. trace(0, "AllocateAndInitializeSid Error %u\n", dwRes );
  1289. goto Cleanup;
  1290. }
  1291. // Initialize an EXPLICIT_ACCESS structure for an ACE.
  1292. // The ACE will allow the LocalSystem full access to the key.
  1293. ea[2].grfAccessPermissions = dwSystemMask;
  1294. ea[2].grfAccessMode = SET_ACCESS;
  1295. ea[2].grfInheritance= fInherit ? SUB_CONTAINERS_AND_OBJECTS_INHERIT : NO_INHERITANCE;
  1296. ea[2].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  1297. ea[2].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
  1298. ea[2].Trustee.ptstrName = (LPTSTR) pSystemSID;
  1299. // Create a new ACL that contains the new ACEs.
  1300. dwRes = SetEntriesInAcl(3, ea, NULL, &pACL);
  1301. if (ERROR_SUCCESS != dwRes)
  1302. {
  1303. dwRes = GetLastError();
  1304. trace(0, "SetEntriesInAcl Error %u\n", dwRes );
  1305. goto Cleanup;
  1306. }
  1307. // Initialize a security descriptor.
  1308. pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR,
  1309. SECURITY_DESCRIPTOR_MIN_LENGTH);
  1310. if (pSD == NULL)
  1311. {
  1312. trace(0, "LocalAlloc Error %u\n", GetLastError() );
  1313. goto Cleanup;
  1314. }
  1315. if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
  1316. {
  1317. dwRes = GetLastError();
  1318. trace(0, "InitializeSecurityDescriptor Error %u\n",
  1319. dwRes );
  1320. goto Cleanup;
  1321. }
  1322. // Add the ACL to the security descriptor.
  1323. if (!SetSecurityDescriptorDacl(pSD,
  1324. TRUE, // fDaclPresent flag
  1325. pACL,
  1326. FALSE)) // not a default DACL
  1327. {
  1328. dwRes = GetLastError();
  1329. trace(0, "SetSecurityDescriptorDacl Error %u\n", dwRes );
  1330. goto Cleanup;
  1331. }
  1332. dwRes = SetSecurityInfo(hObject,
  1333. (SE_OBJECT_TYPE) dwObjectType,
  1334. DACL_SECURITY_INFORMATION |
  1335. PROTECTED_DACL_SECURITY_INFORMATION,
  1336. NULL,
  1337. NULL,
  1338. pACL,
  1339. NULL);
  1340. if (ERROR_SUCCESS != dwRes)
  1341. {
  1342. trace(0, "SetSecurityInfo Error %u\n", dwRes );
  1343. goto Cleanup;
  1344. }
  1345. Cleanup:
  1346. if (pEveryoneSID)
  1347. FreeSid(pEveryoneSID);
  1348. if (pAdminSID)
  1349. FreeSid(pAdminSID);
  1350. if (pSystemSID)
  1351. FreeSid(pSystemSID);
  1352. if (pACL)
  1353. LocalFree(pACL);
  1354. if (pSD)
  1355. LocalFree(pSD);
  1356. tleave();
  1357. return dwRes;
  1358. }
  1359. // sets acl to a named object allowing specific access to
  1360. // LocalSystem/Admin and to everyone
  1361. DWORD
  1362. SetAclInNamedObject(WCHAR * pszDirName, DWORD dwObjectType,
  1363. DWORD dwSystemMask, DWORD dwEveryoneMask,
  1364. DWORD dwSystemInherit, DWORD dwEveryOneInherit)
  1365. {
  1366. tenter("SetAclInNamedObject");
  1367. DWORD dwRes, dwDisposition;
  1368. PSID pEveryoneSID = NULL, pAdminSID = NULL;
  1369. PSID pSystemSID = NULL;
  1370. PACL pACL = NULL;
  1371. PSECURITY_DESCRIPTOR pSD = NULL;
  1372. EXPLICIT_ACCESS ea[3];
  1373. SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
  1374. SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
  1375. LONG lRes;
  1376. BOOL fReturn;
  1377. // Create a well-known SID for the Everyone group.
  1378. if(! AllocateAndInitializeSid( &SIDAuthWorld, 1,
  1379. SECURITY_WORLD_RID,
  1380. 0, 0, 0, 0, 0, 0, 0,
  1381. &pEveryoneSID) )
  1382. {
  1383. dwRes = GetLastError();
  1384. trace(0, "AllocateAndInitializeSid Error %u\n", dwRes);
  1385. goto Cleanup;
  1386. }
  1387. // Initialize an EXPLICIT_ACCESS structure for an ACE.
  1388. // The ACE will allow Everyone read access to the key.
  1389. ZeroMemory(ea, sizeof(ea));
  1390. ea[0].grfAccessPermissions = dwEveryoneMask;
  1391. ea[0].grfAccessMode = SET_ACCESS;
  1392. ea[0].grfInheritance = dwEveryOneInherit;
  1393. ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  1394. ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
  1395. ea[0].Trustee.ptstrName = (LPTSTR) pEveryoneSID;
  1396. // Create a SID for the BUILTIN\Administrators group.
  1397. if(! AllocateAndInitializeSid( &SIDAuthNT, 2,
  1398. SECURITY_BUILTIN_DOMAIN_RID,
  1399. DOMAIN_ALIAS_RID_ADMINS,
  1400. 0, 0, 0, 0, 0, 0,
  1401. &pAdminSID) )
  1402. {
  1403. dwRes = GetLastError();
  1404. trace(0, "AllocateAndInitializeSid Error %u\n", dwRes);
  1405. goto Cleanup;
  1406. }
  1407. // Initialize an EXPLICIT_ACCESS structure for an ACE.
  1408. // The ACE will allow the Administrators group full access to the key.
  1409. ea[1].grfAccessPermissions = dwSystemMask;
  1410. ea[1].grfAccessMode = SET_ACCESS;
  1411. ea[1].grfInheritance= dwSystemInherit;
  1412. ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  1413. ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
  1414. ea[1].Trustee.ptstrName = (LPTSTR) pAdminSID;
  1415. // Create a SID for the LocalSystem account
  1416. if(! AllocateAndInitializeSid( &SIDAuthNT, 1,
  1417. SECURITY_LOCAL_SYSTEM_RID,
  1418. 0, 0, 0, 0, 0, 0, 0,
  1419. &pSystemSID) )
  1420. {
  1421. dwRes = GetLastError();
  1422. trace(0, "AllocateAndInitializeSid Error %u\n", dwRes );
  1423. goto Cleanup;
  1424. }
  1425. // Initialize an EXPLICIT_ACCESS structure for an ACE.
  1426. // The ACE will allow the LocalSystem full access to the key.
  1427. ea[2].grfAccessPermissions = dwSystemMask;
  1428. ea[2].grfAccessMode = SET_ACCESS;
  1429. ea[2].grfInheritance= dwSystemInherit;
  1430. ea[2].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  1431. ea[2].Trustee.TrusteeType = TRUSTEE_IS_USER;
  1432. ea[2].Trustee.ptstrName = (LPTSTR) pSystemSID;
  1433. // Create a new ACL that contains the new ACEs.
  1434. dwRes = SetEntriesInAcl(3, ea, NULL, &pACL);
  1435. if (ERROR_SUCCESS != dwRes)
  1436. {
  1437. dwRes = GetLastError();
  1438. trace(0, "SetEntriesInAcl Error %u\n", dwRes );
  1439. goto Cleanup;
  1440. }
  1441. // Initialize a security descriptor.
  1442. pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR,
  1443. SECURITY_DESCRIPTOR_MIN_LENGTH);
  1444. if (pSD == NULL)
  1445. {
  1446. trace(0, "LocalAlloc Error %u\n", GetLastError() );
  1447. goto Cleanup;
  1448. }
  1449. if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
  1450. {
  1451. dwRes = GetLastError();
  1452. trace(0, "InitializeSecurityDescriptor Error %u\n",
  1453. dwRes );
  1454. goto Cleanup;
  1455. }
  1456. // Add the ACL to the security descriptor.
  1457. if (!SetSecurityDescriptorDacl(pSD,
  1458. TRUE, // fDaclPresent flag
  1459. pACL,
  1460. FALSE)) // not a default DACL
  1461. {
  1462. dwRes = GetLastError();
  1463. trace(0, "SetSecurityDescriptorDacl Error %u\n", dwRes );
  1464. goto Cleanup;
  1465. }
  1466. dwRes = SetNamedSecurityInfo(pszDirName,
  1467. (SE_OBJECT_TYPE) dwObjectType,
  1468. DACL_SECURITY_INFORMATION |
  1469. PROTECTED_DACL_SECURITY_INFORMATION,
  1470. NULL,
  1471. NULL,
  1472. pACL,
  1473. NULL);
  1474. if (ERROR_SUCCESS != dwRes)
  1475. {
  1476. trace(0, "SetSecurityInfo Error %u\n", dwRes );
  1477. goto Cleanup;
  1478. }
  1479. dwRes = ERROR_SUCCESS;
  1480. Cleanup:
  1481. if (pEveryoneSID)
  1482. FreeSid(pEveryoneSID);
  1483. if (pAdminSID)
  1484. FreeSid(pAdminSID);
  1485. if (pSystemSID)
  1486. FreeSid(pSystemSID);
  1487. if (pACL)
  1488. LocalFree(pACL);
  1489. if (pSD)
  1490. LocalFree(pSD);
  1491. tleave();
  1492. return dwRes;
  1493. }
  1494. DWORD SetCorrectACLOnDSRoot(WCHAR * wcsPath)
  1495. {
  1496. return SetAclInNamedObject(wcsPath, // restore dir name
  1497. SE_FILE_OBJECT,
  1498. STANDARD_RIGHTS_ALL | GENERIC_ALL,
  1499. // system and admin access
  1500. FILE_WRITE_DATA|SYNCHRONIZE,
  1501. // everyone - just the right
  1502. // to create a file in the directory
  1503. SUB_CONTAINERS_AND_OBJECTS_INHERIT,
  1504. // Inherit system and admin
  1505. // ACLs to children
  1506. SUB_CONTAINERS_ONLY_INHERIT);
  1507. //Inherit everyone ACL only
  1508. //to subcontainers
  1509. }
  1510. DWORD GetWorldEffectivePermissions(PACL pDacl,
  1511. ACCESS_MASK * pAccessMask)
  1512. {
  1513. TraceFunctEnter("GetWorldEffectivePermissions");
  1514. DWORD dwReturn;
  1515. TRUSTEE WorldTrustee;
  1516. SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
  1517. PSID pEveryoneSID = NULL;
  1518. // 1. build the trustee structure for World
  1519. // 1a Create a well-known SID for the Everyone group.
  1520. if(! AllocateAndInitializeSid( &SIDAuthWorld,
  1521. 1, // nSubAuthorityCount
  1522. SECURITY_WORLD_RID,
  1523. 0, 0, 0, 0, 0, 0, 0,
  1524. &pEveryoneSID) )
  1525. {
  1526. dwReturn = GetLastError();
  1527. trace(0, "AllocateAndInitializeSid Error %u\n", dwReturn);
  1528. goto cleanup;
  1529. }
  1530. ZeroMemory(&WorldTrustee, sizeof(WorldTrustee));
  1531. WorldTrustee.MultipleTrusteeOperation=NO_MULTIPLE_TRUSTEE;
  1532. WorldTrustee.TrusteeForm = TRUSTEE_IS_SID;
  1533. WorldTrustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
  1534. WorldTrustee.ptstrName = (LPTSTR) pEveryoneSID;
  1535. // call the API to get rights for World
  1536. dwReturn=GetEffectiveRightsFromAcl(pDacl, // ACL
  1537. &WorldTrustee,
  1538. pAccessMask);
  1539. cleanup:
  1540. if (pEveryoneSID)
  1541. FreeSid(pEveryoneSID);
  1542. TraceFunctLeave();
  1543. return dwReturn;
  1544. }
  1545. // returns if Everyone has write access to the directory
  1546. BOOL IsDirectoryWorldAccessible(WCHAR * pszObjectName)
  1547. {
  1548. TraceFunctEnter("IsDirectoryWorldAccessible");
  1549. BOOL fReturn=FALSE; // Assume FALSE by default
  1550. DWORD dwReturn;
  1551. PACL pDacl;
  1552. PSECURITY_DESCRIPTOR pSecurityDescriptor=NULL;
  1553. ACCESS_MASK AccessMask;
  1554. // Get Security Info from directory
  1555. dwReturn=GetNamedSecurityInfo(pszObjectName, // object name
  1556. SE_FILE_OBJECT, // object type
  1557. DACL_SECURITY_INFORMATION, //information type
  1558. NULL, // owner SID
  1559. NULL, // primary group SID
  1560. &pDacl, // DACL
  1561. NULL, // SACL
  1562. &pSecurityDescriptor);// SD
  1563. if (ERROR_SUCCESS != dwReturn)
  1564. {
  1565. ErrorTrace(0, "GetNamedSecurityInfo error %u\n", dwReturn);
  1566. pSecurityDescriptor=NULL;
  1567. goto cleanup;
  1568. }
  1569. // Get Effective permissions of World from this ACL
  1570. dwReturn=GetWorldEffectivePermissions(pDacl, &AccessMask);
  1571. if (ERROR_SUCCESS != dwReturn)
  1572. {
  1573. ErrorTrace(0, "GetWorldEffectPermissions error %u\n", dwReturn);
  1574. goto cleanup;
  1575. }
  1576. // Check if world has Access. We will just check for FILE_APPEND_DATA
  1577. // which is the right to create a subdirectory.
  1578. fReturn = (0 !=(AccessMask&FILE_APPEND_DATA));
  1579. cleanup:
  1580. // release memory
  1581. if (NULL!= pSecurityDescriptor)
  1582. {
  1583. _VERIFY(NULL==LocalFree(pSecurityDescriptor));
  1584. }
  1585. TraceFunctLeave();
  1586. return fReturn;
  1587. }
  1588. // This function compares given SID with administrators group and system
  1589. BOOL IsSidOfAdminOrSystem(PSID pSid)
  1590. {
  1591. TraceFunctEnter("IsFileOwnedByAdminOrSystem");
  1592. BOOL fReturn=FALSE; // Assume FALSE by default
  1593. PSID pAdminSID = NULL;
  1594. PSID pSystemSID = NULL;
  1595. SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
  1596. DWORD dwRes;
  1597. // create SIDs of Admins and System
  1598. // Create a SID for the BUILTIN\Administrators group.
  1599. if(! AllocateAndInitializeSid( &SIDAuthNT, 2,
  1600. SECURITY_BUILTIN_DOMAIN_RID,
  1601. DOMAIN_ALIAS_RID_ADMINS,
  1602. 0, 0, 0, 0, 0, 0,
  1603. &pAdminSID) )
  1604. {
  1605. dwRes = GetLastError();
  1606. trace(0, "AllocateAndInitializeSid Error %u", dwRes);
  1607. goto cleanup;
  1608. }
  1609. if (EqualSid(pAdminSID, pSid))
  1610. {
  1611. trace(0, "passed in SID is Admin SID");
  1612. fReturn=TRUE;
  1613. goto cleanup;
  1614. }
  1615. // Create a SID for the LocalSystem account
  1616. if(! AllocateAndInitializeSid( &SIDAuthNT, 1,
  1617. SECURITY_LOCAL_SYSTEM_RID,
  1618. 0, 0, 0, 0, 0, 0, 0,
  1619. &pSystemSID) )
  1620. {
  1621. dwRes = GetLastError();
  1622. trace(0, "AllocateAndInitializeSid Error %u\n", dwRes );
  1623. goto cleanup;
  1624. }
  1625. if (EqualSid(pSystemSID, pSid))
  1626. {
  1627. trace(0, "passed in SID is System SID");
  1628. fReturn=TRUE;
  1629. goto cleanup;
  1630. }
  1631. cleanup:
  1632. if (pAdminSID)
  1633. FreeSid(pAdminSID);
  1634. if (pSystemSID)
  1635. FreeSid(pSystemSID);
  1636. TraceFunctLeave();
  1637. return fReturn;
  1638. }
  1639. BOOL IsVolumeNTFS(WCHAR * pszFileName)
  1640. {
  1641. TENTER ("IsVolumeNTFS");
  1642. BOOL fReturn=FALSE;
  1643. DWORD dwErr = ERROR_SUCCESS;
  1644. WCHAR szFileNameCopy[2*MAX_PATH];
  1645. DWORD dwFsFlags;
  1646. WCHAR * pszVolumeNameEnd;
  1647. DWORD dwFileNameLength;
  1648. dwFileNameLength = lstrlen(pszFileName);
  1649. if ( (dwFileNameLength >= sizeof(szFileNameCopy)/sizeof(WCHAR)) ||
  1650. (dwFileNameLength < 4) )
  1651. {
  1652. // file name too long. Cannot be a valid changelog
  1653. TRACE(0, "Filename not of proper length %d", dwFileNameLength);
  1654. fReturn=FALSE; // assume not NTFS
  1655. goto cleanup;
  1656. }
  1657. lstrcpy(szFileNameCopy, pszFileName);
  1658. pszVolumeNameEnd=ReturnPastVolumeName(szFileNameCopy);
  1659. // NULL terminate after end of volume name to get just the volume name
  1660. *pszVolumeNameEnd=L'\0';
  1661. // Get the volume label and flags
  1662. if (TRUE == GetVolumeInformationW (szFileNameCopy,// root directory
  1663. NULL,// volume name buffer
  1664. 0, // length of name buffer
  1665. NULL, // volume serial number
  1666. NULL,// maximum file name length
  1667. &dwFsFlags,// file system options
  1668. NULL,// file system name buffer
  1669. 0))// length of file system name buffer
  1670. {
  1671. if (dwFsFlags & FS_PERSISTENT_ACLS)
  1672. {
  1673. fReturn=TRUE;
  1674. }
  1675. else
  1676. {
  1677. fReturn=FALSE;
  1678. }
  1679. }
  1680. else
  1681. {
  1682. dwErr = GetLastError();
  1683. TRACE(0, "GetVolumeInformation failed : %ld", dwErr);
  1684. fReturn=FALSE; // assume not NTFS
  1685. }
  1686. cleanup:
  1687. TLEAVE();
  1688. return fReturn;
  1689. }
  1690. // returns if the file is owned by the administrators group or system
  1691. BOOL IsFileOwnedByAdminOrSystem(WCHAR * pszObjectName)
  1692. {
  1693. TraceFunctEnter("IsFileOwnedByAdminOrSystem");
  1694. BOOL fReturn=FALSE; // Assume FALSE by default
  1695. DWORD dwReturn;
  1696. PSID pSidOwner=NULL;
  1697. PSECURITY_DESCRIPTOR pSecurityDescriptor=NULL;
  1698. ACCESS_MASK AccessMask;
  1699. if (FALSE == IsVolumeNTFS(pszObjectName))
  1700. {
  1701. // if the volume is not NTFS, return success
  1702. fReturn=TRUE;
  1703. goto cleanup;
  1704. }
  1705. // Get Security Info from directory
  1706. dwReturn=GetNamedSecurityInfo(pszObjectName, // object name
  1707. SE_FILE_OBJECT, // object type
  1708. OWNER_SECURITY_INFORMATION,//information type
  1709. &pSidOwner, // owner SID
  1710. NULL, // primary group SID
  1711. NULL, // DACL
  1712. NULL, // SACL
  1713. &pSecurityDescriptor);// SD
  1714. if (ERROR_SUCCESS != dwReturn)
  1715. {
  1716. ErrorTrace(0, "GetNamedSecurityInfo error %u\n", dwReturn);
  1717. pSecurityDescriptor=NULL;
  1718. goto cleanup;
  1719. }
  1720. // Compare SID with administrators group and system
  1721. fReturn=IsSidOfAdminOrSystem(pSidOwner);
  1722. cleanup:
  1723. // release memory
  1724. if (NULL!= pSecurityDescriptor)
  1725. {
  1726. _VERIFY(NULL==LocalFree(pSecurityDescriptor));
  1727. }
  1728. TraceFunctLeave();
  1729. return fReturn;
  1730. }
  1731. //+---------------------------------------------------------------------------
  1732. //
  1733. // Function: Delnode_Recurse
  1734. //
  1735. // Synopsis: attempt to delete a directory tree
  1736. //
  1737. // Arguments: [pwszDir] -- directory name
  1738. // [fIncludeRoot] -- delete top level directory and files
  1739. // [pfStop] -- TRUE if stop signaled
  1740. //
  1741. // Returns: Win32 error code
  1742. //
  1743. // History: 12-Apr-2000 HenryLee Created
  1744. //
  1745. //----------------------------------------------------------------------------
  1746. DWORD
  1747. Delnode_Recurse (const WCHAR *pwszDir, BOOL fDeleteRoot, BOOL *pfStop)
  1748. {
  1749. tenter("Delnode_Recurse");
  1750. DWORD dwErr = ERROR_SUCCESS;
  1751. WIN32_FIND_DATA *pfd = NULL;
  1752. HANDLE hFile = INVALID_HANDLE_VALUE;
  1753. WCHAR * pwcsPath = NULL;
  1754. if (lstrlenW (pwszDir) > MAX_PATH-5)
  1755. {
  1756. dwErr = ERROR_INVALID_PARAMETER;
  1757. trace (0, "Delnode_Recurse failed with %d", dwErr);
  1758. goto cleanup;
  1759. }
  1760. if (NULL == (pfd = new WIN32_FIND_DATA))
  1761. {
  1762. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1763. trace (0, "Delnode_Recurse failed with %d", dwErr);
  1764. goto cleanup;
  1765. }
  1766. if (NULL == (pwcsPath = new WCHAR[MAX_PATH]))
  1767. {
  1768. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1769. trace (0, "Delnode_Recurse failed with %d", dwErr);
  1770. goto cleanup;
  1771. }
  1772. lstrcpy (pwcsPath, pwszDir);
  1773. lstrcat (pwcsPath, TEXT("\\*.*"));
  1774. hFile = FindFirstFileW (pwcsPath, pfd);
  1775. if (hFile == INVALID_HANDLE_VALUE)
  1776. {
  1777. // if the directory does not exist, then return success
  1778. dwErr = ERROR_SUCCESS;
  1779. goto cleanup;
  1780. }
  1781. do
  1782. {
  1783. if (pfStop != NULL && TRUE == *pfStop)
  1784. {
  1785. dwErr = ERROR_OPERATION_ABORTED;
  1786. trace (0, "Delnode_Recurse failed with %d", dwErr);
  1787. goto cleanup;
  1788. }
  1789. if (!lstrcmp(pfd->cFileName, L".") || !lstrcmp(pfd->cFileName, L".."))
  1790. {
  1791. continue;
  1792. }
  1793. if (lstrlenW(pwszDir) + lstrlenW(pfd->cFileName) + 1 >= MAX_PATH)
  1794. continue; // ignore excessively long names
  1795. lstrcpy (pwcsPath, pwszDir); // construct the full path name
  1796. lstrcat (pwcsPath, TEXT("\\"));
  1797. lstrcat (pwcsPath, pfd->cFileName);
  1798. if (pfd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  1799. {
  1800. //
  1801. // Found a directory. Skip mount points
  1802. //
  1803. if (pfd->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
  1804. {
  1805. continue;
  1806. }
  1807. dwErr = Delnode_Recurse (pwcsPath, TRUE, pfStop);
  1808. if (dwErr != ERROR_SUCCESS)
  1809. {
  1810. trace (0, "Delnode_Recurse failed with %d, ignoring", dwErr);
  1811. dwErr = ERROR_SUCCESS; // try to delete more directories
  1812. }
  1813. }
  1814. else if (fDeleteRoot)
  1815. {
  1816. //
  1817. // We found a file. Set the file attributes,
  1818. // and try to delete it.
  1819. //
  1820. if ((pfd->dwFileAttributes & FILE_ATTRIBUTE_READONLY) ||
  1821. (pfd->dwFileAttributes & FILE_ATTRIBUTE_SYSTEM))
  1822. {
  1823. SetFileAttributesW (pwcsPath, FILE_ATTRIBUTE_NORMAL);
  1824. }
  1825. if (FALSE == DeleteFileW (pwcsPath))
  1826. {
  1827. if (ERROR_SUCCESS == (dwErr = TakeOwn (pwcsPath)))
  1828. {
  1829. if (FALSE == DeleteFileW (pwcsPath))
  1830. {
  1831. dwErr = GetLastError();
  1832. }
  1833. }
  1834. if (dwErr != ERROR_SUCCESS)
  1835. {
  1836. trace (0, "DeleteFile or TakeOwn failed with %d", dwErr);
  1837. goto cleanup;
  1838. }
  1839. }
  1840. }
  1841. } while (FindNextFile(hFile, pfd)); // Find the next entry
  1842. FindClose(hFile); // Close the search handle
  1843. hFile = INVALID_HANDLE_VALUE;
  1844. if (fDeleteRoot)
  1845. {
  1846. DWORD dwAttr = GetFileAttributes(pwszDir);
  1847. if (dwAttr != 0xFFFFFFFF && (dwAttr & FILE_ATTRIBUTE_READONLY))
  1848. {
  1849. dwAttr &= ~FILE_ATTRIBUTE_READONLY;
  1850. if (FALSE == SetFileAttributes (pwszDir, dwAttr))
  1851. {
  1852. TRACE(0, "SetFileAttributes ignoring %ld", GetLastError());
  1853. }
  1854. }
  1855. if (FALSE == RemoveDirectoryW (pwszDir))
  1856. {
  1857. if (ERROR_SUCCESS == (dwErr = TakeOwn (pwszDir)))
  1858. {
  1859. if (FALSE == RemoveDirectoryW (pwszDir))
  1860. {
  1861. LONG lLast = lstrlenW (pwszDir) - 1;
  1862. if (lLast < 0) lLast = 0;
  1863. dwErr = GetLastError();
  1864. if (pwszDir[lLast] != L')' && // already renamed
  1865. TRUE == SRGetAltFileName (pwszDir, pwcsPath) &&
  1866. TRUE == MoveFile (pwszDir, pwcsPath))
  1867. dwErr = ERROR_SUCCESS;
  1868. else
  1869. trace (0, "RemoveDirectory failed with %d", dwErr);
  1870. }
  1871. }
  1872. }
  1873. }
  1874. cleanup:
  1875. if (hFile != INVALID_HANDLE_VALUE)
  1876. FindClose (hFile);
  1877. if (NULL != pfd)
  1878. delete pfd;
  1879. if (NULL != pwcsPath)
  1880. delete [] pwcsPath;
  1881. tleave();
  1882. return dwErr;
  1883. }
  1884. //
  1885. // util function that checks the SR Stop event
  1886. // to see if it has been signalled or not
  1887. // will return TRUE if the event does not exist
  1888. //
  1889. BOOL
  1890. IsStopSignalled(HANDLE hEvent)
  1891. {
  1892. TENTER("IsStopSignalled");
  1893. BOOL fRet, fOpened = FALSE;
  1894. DWORD dwRc;
  1895. if (! hEvent)
  1896. {
  1897. hEvent = OpenEvent(SYNCHRONIZE, FALSE, s_cszSRStopEvent);
  1898. if (! hEvent)
  1899. {
  1900. // if cannot open, then assume that service is not stopped
  1901. // if client is running on different desktop than service (multiple user magic)
  1902. // then it cannot open the event, though service might be running
  1903. dwRc = GetLastError();
  1904. TRACE(0, "! OpenEvent : %ld", dwRc);
  1905. TLEAVE();
  1906. return FALSE;
  1907. }
  1908. fOpened = TRUE;
  1909. }
  1910. fRet = (WAIT_OBJECT_0 == WaitForSingleObject(hEvent, 0));
  1911. if (fOpened)
  1912. CloseHandle(hEvent);
  1913. TLEAVE();
  1914. return fRet;
  1915. }
  1916. void
  1917. PostTestMessage(UINT msg, WPARAM wp, LPARAM lp)
  1918. {
  1919. HWINSTA hwinstaUser;
  1920. HDESK hdeskUser = NULL;
  1921. DWORD dwThreadId;
  1922. HWINSTA hwinstaSave;
  1923. HDESK hdeskSave;
  1924. DWORD dwRc;
  1925. TENTER("PostTestMessage");
  1926. //
  1927. // save current values
  1928. //
  1929. GetDesktopWindow();
  1930. hwinstaSave = GetProcessWindowStation();
  1931. dwThreadId = GetCurrentThreadId();
  1932. hdeskSave = GetThreadDesktop(dwThreadId);
  1933. //
  1934. // change desktop and winstation to interactive user
  1935. //
  1936. hwinstaUser = OpenWindowStation(L"WinSta0", FALSE, MAXIMUM_ALLOWED);
  1937. if (hwinstaUser == NULL)
  1938. {
  1939. dwRc = GetLastError();
  1940. trace(0, "! OpenWindowStation : %ld", dwRc);
  1941. goto done;
  1942. }
  1943. SetProcessWindowStation(hwinstaUser);
  1944. hdeskUser = OpenDesktop(L"Default", 0, FALSE, MAXIMUM_ALLOWED);
  1945. if (hdeskUser == NULL)
  1946. {
  1947. dwRc = GetLastError();
  1948. trace(0, "! OpenDesktop : %ld", dwRc);
  1949. goto done;
  1950. }
  1951. SetThreadDesktop(hdeskUser);
  1952. if (FALSE == PostMessage(HWND_BROADCAST, msg, wp, lp))
  1953. {
  1954. trace(0, "! PostMessage");
  1955. }
  1956. done:
  1957. //
  1958. // restore old values
  1959. //
  1960. if (hdeskSave)
  1961. SetThreadDesktop(hdeskSave);
  1962. if (hwinstaSave)
  1963. SetProcessWindowStation(hwinstaSave);
  1964. //
  1965. // close opened handles
  1966. //
  1967. if (hdeskUser)
  1968. CloseDesktop(hdeskUser);
  1969. if (hwinstaUser)
  1970. CloseWindowStation(hwinstaUser);
  1971. TLEAVE();
  1972. }
  1973. //+-------------------------------------------------------------------------
  1974. //
  1975. // Function: RemoveTrailingFilename
  1976. //
  1977. // Synopsis: This function takes as input parameter a string which
  1978. // contains a filename. It removes the last filename (or
  1979. // directory ) from the string including the '\' or '/'
  1980. // before the last filename.
  1981. //
  1982. // Arguments: IN/OUT pszString - string to be modified.
  1983. // IN tchSlash - file name separator - must be '/' or'\'
  1984. //
  1985. //
  1986. // Returns: nothing
  1987. //
  1988. // History: AshishS Created 5/22/96
  1989. //
  1990. //------------------------------------------------------------------------
  1991. void RemoveTrailingFilename(WCHAR * pszString, WCHAR wchSlash)
  1992. {
  1993. WCHAR * pszStringStart;
  1994. DWORD dwStrlen;
  1995. pszStringStart = pszString;
  1996. dwStrlen = lstrlen ( pszString);
  1997. // first go the end of the string
  1998. pszString += dwStrlen ;
  1999. // now walk backwards till we see the first '\'
  2000. // also maintain a count of how many characters we have
  2001. // gone back.
  2002. while ( (*pszString != wchSlash) && ( dwStrlen) )
  2003. {
  2004. pszString--;
  2005. dwStrlen --;
  2006. }
  2007. *pszString = TEXT('\0');
  2008. }
  2009. // this function create the parent directory under the specified file
  2010. // name if it already does not exist
  2011. BOOL CreateParentDirectory(WCHAR * pszFileName)
  2012. {
  2013. TraceFunctEnter("CreateParentDirectory");
  2014. BOOL fReturn = FALSE;
  2015. DWORD dwError;
  2016. // get the parent directory
  2017. RemoveTrailingFilename(pszFileName, L'\\');
  2018. if (FALSE == DoesDirExist(pszFileName))
  2019. {
  2020. if (FALSE == CreateDirectory(pszFileName, // directory name
  2021. NULL)) // SD
  2022. {
  2023. dwError = GetLastError();
  2024. ErrorTrace(TRACEID, "Could not create directory %S ec=%d",
  2025. pszFileName, dwError);
  2026. goto cleanup;
  2027. }
  2028. }
  2029. fReturn = TRUE;
  2030. cleanup:
  2031. TraceFunctLeave();
  2032. return fReturn;
  2033. }
  2034. // this function creates all sub directories under the specified file
  2035. // name.
  2036. BOOL CreateBaseDirectory(const WCHAR * pszFileName)
  2037. {
  2038. BOOL fRetVal = FALSE;
  2039. DWORD dwCurIndex,dwBufReqd;
  2040. DWORD dwStrlen;
  2041. TraceFunctEnter("CreateBaseDirectory");
  2042. DWORD dwError;
  2043. WCHAR * pszFileNameCopy;
  2044. dwBufReqd = (lstrlen(pszFileName) + 1) * sizeof(WCHAR);
  2045. pszFileNameCopy = (WCHAR *) _alloca(dwBufReqd);
  2046. if (NULL == pszFileNameCopy)
  2047. {
  2048. ErrorTrace(0, "alloca for size %d failed", dwBufReqd);
  2049. goto cleanup;
  2050. }
  2051. lstrcpy(pszFileNameCopy, pszFileName);
  2052. // do a fast check to see if the parent directory exists
  2053. if (TRUE == CreateParentDirectory(pszFileNameCopy))
  2054. {
  2055. fRetVal = TRUE;
  2056. goto cleanup;
  2057. }
  2058. lstrcpy(pszFileNameCopy, pszFileName);
  2059. dwStrlen = lstrlen(pszFileNameCopy);
  2060. // check to see if this is a filename starting with the GUID
  2061. if (0==wcsncmp( pszFileNameCopy,
  2062. VOLUMENAME_FORMAT,
  2063. lstrlen(VOLUMENAME_FORMAT)))
  2064. {
  2065. // this is of the format \\?\Volume
  2066. // skip over the initial part
  2067. dwCurIndex = lstrlen(VOLUMENAME_FORMAT)+1;
  2068. // skip over the GUID part also
  2069. while (dwCurIndex < dwStrlen)
  2070. {
  2071. dwCurIndex++;
  2072. if (TEXT('\\') == pszFileNameCopy[dwCurIndex-1] )
  2073. {
  2074. break;
  2075. }
  2076. }
  2077. }
  2078. else
  2079. {
  2080. // the filename is of the regular format
  2081. // we start at index 1 and not at 0 because we want to handle
  2082. // path name like \foo\abc.txt
  2083. dwCurIndex = 1;
  2084. }
  2085. while (dwCurIndex < dwStrlen)
  2086. {
  2087. if (TEXT('\\') == pszFileNameCopy[dwCurIndex] )
  2088. {
  2089. // NULL terminate at the '\' to get the sub directory
  2090. // name.
  2091. pszFileNameCopy[dwCurIndex] = TEXT('\0');
  2092. if (FALSE == DoesDirExist(pszFileNameCopy))
  2093. {
  2094. if (FALSE == CreateDirectory(pszFileNameCopy, // directory name
  2095. NULL)) // SD
  2096. {
  2097. dwError = GetLastError();
  2098. ErrorTrace(TRACEID, "Could not create directory %S ec=%d",
  2099. pszFileNameCopy, dwError);
  2100. pszFileNameCopy[dwCurIndex] = TEXT('\\');
  2101. goto cleanup;
  2102. }
  2103. DebugTrace(TRACEID, "Created directory %S", pszFileNameCopy);
  2104. }
  2105. // restore the \ to get the file name again.
  2106. pszFileNameCopy[dwCurIndex] = TEXT('\\');
  2107. }
  2108. dwCurIndex ++;
  2109. }
  2110. fRetVal = TRUE;
  2111. cleanup:
  2112. TraceFunctLeave();
  2113. return fRetVal;
  2114. }
  2115. // The following function logs the name of a file in the DS. The
  2116. // problem right now is that the path of the DS is so long that the
  2117. // relevant information is thrown away from the trace buffer.
  2118. void LogDSFileTrace(DWORD dwTraceID,
  2119. const WCHAR * pszPrefix, // Initial message to be traced
  2120. const WCHAR * pszDSFile)
  2121. {
  2122. WCHAR * pszBeginName;
  2123. TraceQuietEnter("LogDSFileTrace");
  2124. // first see if the file is in the DS
  2125. pszBeginName = wcschr(pszDSFile, L'\\');
  2126. if (NULL == pszBeginName)
  2127. {
  2128. goto cleanup;
  2129. }
  2130. // skip over the first \ .
  2131. pszBeginName++;
  2132. // comapare if the first part is "system volume information"
  2133. if (0!=_wcsnicmp(s_cszSysVolInfo, pszBeginName,
  2134. lstrlen(s_cszSysVolInfo)))
  2135. {
  2136. goto cleanup;
  2137. }
  2138. // skip over the next \ .
  2139. pszBeginName = wcschr(pszBeginName, L'\\');
  2140. if (NULL == pszBeginName)
  2141. {
  2142. goto cleanup;
  2143. }
  2144. pszBeginName++;
  2145. // now skip over the _restore directory
  2146. // first see if the file is in the DS
  2147. pszBeginName = wcschr(pszBeginName, L'\\');
  2148. if (NULL == pszBeginName)
  2149. {
  2150. goto cleanup;
  2151. }
  2152. DebugTrace(dwTraceID, "%S %S", pszPrefix, pszBeginName);
  2153. cleanup:
  2154. // the file is not in the DS - or we are printing out the initial
  2155. // part for debugging purposes.
  2156. DebugTrace(dwTraceID, "%S%S", pszPrefix, pszDSFile);
  2157. return;
  2158. }
  2159. // the following function calls pfnMethod on all the files specified
  2160. // by the pszFindFileData filter.
  2161. DWORD ProcessGivenFiles(WCHAR * pszBaseDir,
  2162. PPROCESSFILEMETHOD pfnMethod,
  2163. WCHAR * pszFindFileData)
  2164. {
  2165. TraceFunctEnter("ProcessGivenFiles");
  2166. WIN32_FIND_DATA FindFileData;
  2167. HANDLE hFindFirstFile = INVALID_HANDLE_VALUE;
  2168. DWORD dwErr, dwReturn = ERROR_INTERNAL_ERROR;
  2169. BOOL fContinue;
  2170. LogDSFileTrace(0, L"FileData is ", pszFindFileData);
  2171. hFindFirstFile = FindFirstFile(pszFindFileData, &FindFileData);
  2172. DebugTrace(0, "FindFirstFile returned %d", hFindFirstFile);
  2173. if (INVALID_HANDLE_VALUE == hFindFirstFile)
  2174. {
  2175. dwErr = GetLastError();
  2176. DebugTrace(0, "FindFirstFile failed ec=%d. Filename is %S",
  2177. dwErr, pszFindFileData);
  2178. // what if even one file does not exist
  2179. if ( (ERROR_FILE_NOT_FOUND == dwErr) ||
  2180. (ERROR_PATH_NOT_FOUND == dwErr) ||
  2181. (ERROR_NO_MORE_FILES == dwErr))
  2182. {
  2183. // this is a success condition
  2184. dwReturn = ERROR_SUCCESS;
  2185. goto cleanup;
  2186. }
  2187. if (ERROR_SUCCESS != dwErr)
  2188. {
  2189. dwReturn = dwErr;
  2190. }
  2191. goto cleanup;
  2192. }
  2193. fContinue = TRUE;
  2194. while (TRUE==fContinue)
  2195. {
  2196. LogDSFileTrace(0, L"FileName is ", FindFileData.cFileName);
  2197. // now check to see if the file length is valid. This is
  2198. // becuase a hacker can introduce a file in the datastore
  2199. // that is too long and can cause us to overflow our buffers.
  2200. if ( MAX_PATH <= lstrlen(pszBaseDir) +lstrlen(s_cszRegHiveCopySuffix)+
  2201. lstrlen(FindFileData.cFileName) + 2 )
  2202. {
  2203. // Filename is too long. It cannot be a file created by
  2204. // system restore. It probably is a file created by a hacker.
  2205. // Ignore this file
  2206. ErrorTrace(0, "Ignoring long file %S", FindFileData.cFileName);
  2207. ErrorTrace(0, "Base dir %S", pszBaseDir );
  2208. dwErr = ERROR_SUCCESS;
  2209. }
  2210. else
  2211. {
  2212. dwErr = pfnMethod(pszBaseDir, FindFileData.cFileName);
  2213. if (ERROR_SUCCESS != dwErr)
  2214. {
  2215. ErrorTrace(0, "pfnMethod failed. ec=%d.file=%S ",
  2216. dwErr, FindFileData.cFileName);
  2217. goto cleanup;
  2218. }
  2219. }
  2220. fContinue = FindNextFile(hFindFirstFile, &FindFileData);
  2221. }
  2222. dwErr=GetLastError();
  2223. if (ERROR_NO_MORE_FILES != dwErr)
  2224. {
  2225. _ASSERT(0);
  2226. ErrorTrace(0, "dwErr != ERROR_NO_MORE_FILES. It is %d",
  2227. dwErr);
  2228. goto cleanup;
  2229. }
  2230. dwReturn = ERROR_SUCCESS;
  2231. cleanup:
  2232. if (INVALID_HANDLE_VALUE != hFindFirstFile)
  2233. {
  2234. _VERIFY(TRUE == FindClose(hFindFirstFile));
  2235. }
  2236. TraceFunctLeave();
  2237. return dwReturn;
  2238. }
  2239. DWORD DeleteGivenFile(WCHAR * pszBaseDir, // Base Directory
  2240. const WCHAR * pszFile)
  2241. // file to delete
  2242. {
  2243. TraceFunctEnter("DeleteGivenFile");
  2244. DWORD dwErr, dwReturn = ERROR_INTERNAL_ERROR;
  2245. WCHAR szDataFile[MAX_PATH];
  2246. // construct the path name of the file
  2247. wsprintf(szDataFile, L"%s\\%s", pszBaseDir, pszFile);
  2248. if (TRUE != DeleteFile(szDataFile))
  2249. {
  2250. dwErr = GetLastError();
  2251. if (ERROR_SUCCESS != dwErr)
  2252. {
  2253. dwReturn = dwErr;
  2254. }
  2255. ErrorTrace(0, "DeleteFile failed ec=%d", dwErr);
  2256. LogDSFileTrace(0,L"File was ", szDataFile);
  2257. goto cleanup;
  2258. }
  2259. dwReturn = ERROR_SUCCESS;
  2260. cleanup:
  2261. TraceFunctLeave();
  2262. return dwReturn;
  2263. }
  2264. //++-----------------------------------------------------------------------
  2265. //
  2266. // Function: WriteRegKey
  2267. //
  2268. // Synopsis: This function writes into a registry key. It also creates it
  2269. // if it does not exist.
  2270. //
  2271. // Arguments:
  2272. //
  2273. // Returns: TRUE no error
  2274. // FALSE a fatal error happened
  2275. //
  2276. // History: AshishS Created 5/22/96
  2277. //------------------------------------------------------------------------
  2278. BOOL WriteRegKey(BYTE * pbRegValue,
  2279. DWORD dwNumBytes,
  2280. const TCHAR * pszRegKey,
  2281. const TCHAR * pszRegValueName,
  2282. DWORD dwRegType)
  2283. {
  2284. HKEY hRegKey;
  2285. LONG lResult;
  2286. DWORD dwDisposition;
  2287. TraceFunctEnter("WriteRegKey");
  2288. //read registry to find out name of the file
  2289. if ( (lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  2290. pszRegKey, // address of subkey name
  2291. 0, // reserved
  2292. NULL, // address of class string
  2293. 0, // special options flag
  2294. KEY_WRITE, // samDesired
  2295. NULL, // address of key security structure
  2296. &hRegKey, // address of handle of open key
  2297. &dwDisposition // address of disposition value buffer
  2298. )) != ERROR_SUCCESS )
  2299. {
  2300. ErrorTrace(TRACEID, "RegCreateKeyEx error 0x%x", lResult);
  2301. _ASSERT(0);
  2302. goto cleanup;
  2303. }
  2304. if ( (lResult =RegSetValueEx( hRegKey,
  2305. pszRegValueName,
  2306. 0, // reserved
  2307. dwRegType,// flag for value type
  2308. pbRegValue, // address of value data
  2309. dwNumBytes // size of value data
  2310. )) != ERROR_SUCCESS )
  2311. {
  2312. ErrorTrace(TRACEID, "RegSetValueEx error 0x%x", lResult);
  2313. _ASSERT(0);
  2314. _VERIFY(RegCloseKey(hRegKey)==ERROR_SUCCESS);
  2315. goto cleanup;
  2316. }
  2317. _VERIFY(RegCloseKey(hRegKey)==ERROR_SUCCESS);
  2318. TraceFunctLeave();
  2319. return TRUE;
  2320. cleanup:
  2321. TraceFunctLeave();
  2322. return FALSE;
  2323. }
  2324. //++------------------------------------------------------------------------
  2325. //
  2326. // Function: ReadRegKey
  2327. //
  2328. // Synopsis: This function reads a registry key and creates it
  2329. // if it does not exist with the default value.
  2330. //
  2331. // Arguments:
  2332. //
  2333. // Returns: TRUE no error
  2334. // FALSE a fatal error happened
  2335. //
  2336. // History: AshishS Created 5/22/96
  2337. //------------------------------------------------------------------------
  2338. BOOL ReadRegKeyOrCreate(BYTE * pbRegValue, // The value of the reg key will be
  2339. // stored here
  2340. DWORD * pdwNumBytes, // Pointer to DWORD conataining
  2341. // the number of bytes in the above buffer - will be
  2342. // set to actual bytes stored.
  2343. const TCHAR * pszRegKey, // Reg Key to be opened
  2344. const TCHAR * pszRegValueName, // Reg Value to query
  2345. DWORD dwRegTypeExpected,
  2346. BYTE * pbDefaultValue, // default value
  2347. DWORD dwDefaultValueSize) // size of default value
  2348. {
  2349. if (!ReadRegKey(pbRegValue,//Buffer to store value
  2350. pdwNumBytes, // Length of above buffer
  2351. pszRegKey, // Reg Key name
  2352. pszRegValueName, // Value name
  2353. dwRegTypeExpected) ) // Type expected
  2354. {
  2355. // read reg key failed - use default value and create this
  2356. // key
  2357. return WriteRegKey(pbDefaultValue,
  2358. dwDefaultValueSize,
  2359. pszRegKey,
  2360. pszRegValueName,
  2361. dwRegTypeExpected);
  2362. }
  2363. return TRUE;
  2364. }
  2365. //++------------------------------------------------------------------------
  2366. //
  2367. // Function: ReadRegKey
  2368. //
  2369. // Synopsis: This function reads a registry key.
  2370. //
  2371. // Arguments:
  2372. //
  2373. // Returns: TRUE no error
  2374. // FALSE a fatal error happened
  2375. //
  2376. // History: AshishS Created 5/22/96
  2377. //------------------------------------------------------------------------
  2378. BOOL ReadRegKey(BYTE * pbRegValue, // The value of the reg key will be
  2379. // stored here
  2380. DWORD * pdwNumBytes, // Pointer to DWORD conataining
  2381. // the number of bytes in the above buffer - will be
  2382. // set to actual bytes stored.
  2383. const TCHAR * pszRegKey, // Reg Key to be opened
  2384. const TCHAR * pszRegValueName, // Reg Value to query
  2385. DWORD dwRegTypeExpected) // Expected type of Value
  2386. {
  2387. HKEY hRegKey;
  2388. DWORD dwRegType;
  2389. LONG lResult;
  2390. TraceFunctEnter("ReadRegKey");
  2391. DebugTrace(TRACEID, "Trying to open %S %S", pszRegKey, pszRegValueName);
  2392. //read registry to find out name of the file
  2393. if ( (lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  2394. pszRegKey, // address of subkey name
  2395. 0, // reserved
  2396. KEY_READ, // samDesired
  2397. &hRegKey
  2398. // address of handle of open key
  2399. )) != ERROR_SUCCESS )
  2400. {
  2401. ErrorTrace(TRACEID, "RegOpenKeyEx open error 0x%x", lResult);
  2402. goto cleanup;
  2403. }
  2404. if ( (lResult =RegQueryValueEx( hRegKey,
  2405. pszRegValueName,
  2406. 0, // reserved
  2407. &dwRegType,// address of buffer
  2408. // for value type
  2409. pbRegValue,
  2410. pdwNumBytes)) != ERROR_SUCCESS )
  2411. {
  2412. _VERIFY(RegCloseKey(hRegKey)==ERROR_SUCCESS);
  2413. ErrorTrace(TRACEID, "RegQueryValueEx failed error 0x%x",
  2414. lResult);
  2415. goto cleanup;
  2416. }
  2417. _VERIFY(RegCloseKey(hRegKey)==ERROR_SUCCESS);
  2418. if ( dwRegType != dwRegTypeExpected )
  2419. {
  2420. ErrorTrace(TRACEID, "RegType is %d, not %d", dwRegType,
  2421. dwRegTypeExpected);
  2422. goto cleanup;
  2423. }
  2424. TraceFunctLeave();
  2425. return TRUE;
  2426. cleanup:
  2427. TraceFunctLeave();
  2428. return FALSE;
  2429. }
  2430. // this function sets the error hit by restore in the registry
  2431. BOOL SetRestoreError(DWORD dwRestoreError)
  2432. {
  2433. TraceFunctEnter("SetDiskSpaceError");
  2434. DWORD dwNumBytes=sizeof(DWORD);
  2435. BOOL fResult=FALSE; // assume FALSE by default
  2436. DebugTrace(TRACEID, "Setting disk space error to %d", dwRestoreError);
  2437. if (FALSE== WriteRegKey((BYTE*)&dwRestoreError, // The value of the
  2438. // reg key will be set to this value
  2439. dwNumBytes, // Pointer to DWORD containing
  2440. // the number of bytes in the above buffer
  2441. s_cszSRRegKey, // Reg Key to be opened
  2442. s_cszRestoreDiskSpaceError, // Reg Value to query
  2443. REG_DWORD)) // Expected type of Value
  2444. {
  2445. fResult = FALSE;
  2446. goto cleanup;
  2447. }
  2448. fResult= TRUE;
  2449. cleanup:
  2450. TraceFunctLeave();
  2451. return fResult;
  2452. }
  2453. // this function checks to see of the restore failed because of disk space
  2454. BOOL CheckForDiskSpaceError()
  2455. {
  2456. TraceFunctEnter("CheckForDiskSpaceError");
  2457. DWORD dwRestoreError;
  2458. DWORD dwNumBytes=sizeof(DWORD);
  2459. BOOL fResult=FALSE; // assume FALSE by default
  2460. if (FALSE==ReadRegKey((BYTE*)&dwRestoreError, // The value of the
  2461. // reg key will be stored here
  2462. &dwNumBytes, // Pointer to DWORD containing
  2463. // the number of bytes in the above buffer - will be
  2464. // set to actual bytes stored.
  2465. s_cszSRRegKey, // Reg Key to be opened
  2466. s_cszRestoreDiskSpaceError, // Reg Value to query
  2467. REG_DWORD)) // Expected type of Value
  2468. {
  2469. fResult = FALSE;
  2470. }
  2471. if (dwRestoreError == ERROR_DISK_FULL)
  2472. {
  2473. DebugTrace(TRACEID,"Restore failed because of disk space");
  2474. fResult= TRUE;
  2475. }
  2476. TraceFunctLeave();
  2477. return fResult;
  2478. }
  2479. // this function sets the status whether restore was done in safe mode
  2480. BOOL SetRestoreSafeModeStatus(DWORD dwSafeModeStatus)
  2481. {
  2482. TraceFunctEnter("SetRestoreSafeModeStatus");
  2483. DWORD dwNumBytes=sizeof(DWORD);
  2484. BOOL fResult=FALSE; // assume FALSE by default
  2485. DebugTrace(TRACEID, "Setting restore safe mode status to %d",
  2486. dwSafeModeStatus);
  2487. if (FALSE== WriteRegKey((BYTE*)&dwSafeModeStatus, // The value of the
  2488. // reg key will be set to this value
  2489. dwNumBytes, // Pointer to DWORD containing
  2490. // the number of bytes in the above buffer
  2491. s_cszSRRegKey, // Reg Key to be opened
  2492. s_cszRestoreSafeModeStatus, // Reg Value to query
  2493. REG_DWORD)) // Expected type of Value
  2494. {
  2495. fResult = FALSE;
  2496. goto cleanup;
  2497. }
  2498. fResult= TRUE;
  2499. cleanup:
  2500. TraceFunctLeave();
  2501. return fResult;
  2502. }
  2503. // this function checks to see is the last restore was done in safe mode
  2504. BOOL WasLastRestoreInSafeMode()
  2505. {
  2506. TraceFunctEnter("WasLastRestoreInSafeMode");
  2507. DWORD dwRestoreSafeModeStatus;
  2508. DWORD dwNumBytes=sizeof(DWORD);
  2509. BOOL fResult=FALSE; // assume FALSE by default
  2510. if (FALSE==ReadRegKey((BYTE*)&dwRestoreSafeModeStatus, // The value of the
  2511. // reg key will be stored here
  2512. &dwNumBytes, // Pointer to DWORD containing
  2513. // the number of bytes in the above buffer - will be
  2514. // set to actual bytes stored.
  2515. s_cszSRRegKey, // Reg Key to be opened
  2516. s_cszRestoreSafeModeStatus, // Reg Value to query
  2517. REG_DWORD)) // Expected type of Value
  2518. {
  2519. fResult = FALSE;
  2520. }
  2521. if (dwRestoreSafeModeStatus != 0 )
  2522. {
  2523. DebugTrace(TRACEID,"Last restore was done in safe mode");
  2524. fResult= TRUE;
  2525. }
  2526. else
  2527. {
  2528. DebugTrace(TRACEID,"Last restore was not done in safe mode");
  2529. }
  2530. TraceFunctLeave();
  2531. return fResult;
  2532. }
  2533. #define MAX_LEN_SYSERR 1024
  2534. LPCWSTR GetSysErrStr()
  2535. {
  2536. LPCWSTR cszStr = GetSysErrStr( ::GetLastError() );
  2537. return( cszStr );
  2538. }
  2539. LPCWSTR GetSysErrStr( DWORD dwErr )
  2540. {
  2541. static WCHAR szErr[MAX_LEN_SYSERR+1];
  2542. ::FormatMessage(
  2543. FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  2544. NULL,
  2545. dwErr,
  2546. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  2547. szErr,
  2548. MAX_LEN_SYSERR,
  2549. NULL );
  2550. return( szErr );
  2551. }
  2552. /****************************************************************************/
  2553. LPWSTR SRGetRegMultiSz( HKEY hkRoot, LPCWSTR cszSubKey, LPCWSTR cszValue, LPDWORD pdwData )
  2554. {
  2555. TraceFunctEnter("SRGetRegMultiSz");
  2556. LPCWSTR cszErr;
  2557. DWORD dwRes;
  2558. HKEY hKey = NULL;
  2559. DWORD dwType;
  2560. DWORD cbData = 0;
  2561. LPWSTR szBuf = NULL;
  2562. dwRes = ::RegOpenKeyEx( hkRoot, cszSubKey, 0, KEY_ALL_ACCESS, &hKey );
  2563. if ( dwRes != ERROR_SUCCESS )
  2564. {
  2565. cszErr = ::GetSysErrStr( dwRes );
  2566. ErrorTrace(0, "::RegOpenKey() failed - %ls", cszErr);
  2567. goto Exit;
  2568. }
  2569. dwRes = ::RegQueryValueEx( hKey, cszValue, 0, &dwType, NULL, &cbData );
  2570. if ( dwRes != ERROR_SUCCESS )
  2571. {
  2572. cszErr = ::GetSysErrStr( dwRes );
  2573. ErrorTrace(0, "::RegQueryValueEx(len) failed - %ls", cszErr);
  2574. goto Exit;
  2575. }
  2576. if ( dwType != REG_MULTI_SZ )
  2577. {
  2578. ErrorTrace(0, "Type of '%ls' is %u (not REG_MULTI_SZ)...", cszValue, dwType);
  2579. goto Exit;
  2580. }
  2581. if ( cbData == 0 )
  2582. {
  2583. ErrorTrace(0, "Value '%ls' is empty...", cszValue);
  2584. goto Exit;
  2585. }
  2586. szBuf = new WCHAR[cbData+2];
  2587. if (! szBuf)
  2588. {
  2589. ErrorTrace(0, "Cannot allocate memory");
  2590. goto Exit;
  2591. }
  2592. dwRes = ::RegQueryValueEx( hKey, cszValue, 0, &dwType, (LPBYTE)szBuf, &cbData );
  2593. if ( dwRes != ERROR_SUCCESS )
  2594. {
  2595. cszErr = ::GetSysErrStr( dwRes );
  2596. ErrorTrace(0, "::RegQueryValueEx(data) failed - %ls", cszErr);
  2597. delete [] szBuf;
  2598. szBuf = NULL;
  2599. }
  2600. if ( pdwData != NULL )
  2601. *pdwData = cbData;
  2602. Exit:
  2603. if ( hKey != NULL )
  2604. ::RegCloseKey( hKey );
  2605. TraceFunctLeave();
  2606. return( szBuf );
  2607. }
  2608. /****************************************************************************/
  2609. BOOL SRSetRegMultiSz( HKEY hkRoot, LPCWSTR cszSubKey, LPCWSTR cszValue, LPCWSTR cszData, DWORD cbData )
  2610. {
  2611. TraceFunctEnter("SRSetRegMultiSz");
  2612. BOOL fRet = FALSE;
  2613. LPCWSTR cszErr;
  2614. DWORD dwRes;
  2615. HKEY hKey = NULL;
  2616. dwRes = ::RegOpenKeyEx( hkRoot, cszSubKey, 0, KEY_ALL_ACCESS, &hKey );
  2617. if ( dwRes != ERROR_SUCCESS )
  2618. {
  2619. cszErr = ::GetSysErrStr( dwRes );
  2620. ErrorTrace(0, "::RegOpenKey() failed - %ls", cszErr);
  2621. goto Exit;
  2622. }
  2623. dwRes = ::RegSetValueEx( hKey, cszValue, 0, REG_MULTI_SZ, (LPBYTE)cszData, cbData );
  2624. if ( dwRes != ERROR_SUCCESS )
  2625. {
  2626. cszErr = ::GetSysErrStr( dwRes );
  2627. ErrorTrace(0, "::RegSetValueEx() failed - %ls", cszErr);
  2628. goto Exit;
  2629. }
  2630. fRet = TRUE;
  2631. Exit:
  2632. if ( hKey != NULL )
  2633. ::RegCloseKey( hKey );
  2634. TraceFunctLeave();
  2635. return( fRet );
  2636. }
  2637. // this returns the name after the volume name
  2638. // For example input: c:\file output: file
  2639. // input \\?\Volume{GUID}\file1 output: file1
  2640. WCHAR * ReturnPastVolumeName(const WCHAR * pszFileName)
  2641. {
  2642. DWORD dwStrlen, dwCurIndex;
  2643. dwStrlen = lstrlen(pszFileName);
  2644. // check to see if this is a filename starting with the GUID
  2645. if (0==wcsncmp( pszFileName,
  2646. VOLUMENAME_FORMAT,
  2647. lstrlen(VOLUMENAME_FORMAT)))
  2648. {
  2649. // this is of the format \\?\Volume
  2650. // skip over the initial part
  2651. dwCurIndex = lstrlen(VOLUMENAME_FORMAT)+1;
  2652. // skip over the GUID part also
  2653. while (dwCurIndex < dwStrlen)
  2654. {
  2655. dwCurIndex++;
  2656. if (TEXT('\\') == pszFileName[dwCurIndex-1] )
  2657. {
  2658. break;
  2659. }
  2660. }
  2661. }
  2662. else
  2663. {
  2664. // the filename is of the regular format
  2665. dwCurIndex = 3;
  2666. }
  2667. return (WCHAR *)pszFileName + dwCurIndex;
  2668. }
  2669. void SRLogEvent (HANDLE hEventSource,
  2670. WORD wType,
  2671. DWORD dwID,
  2672. void * pRawData,
  2673. DWORD dwDataSize,
  2674. const WCHAR * pszS1,
  2675. const WCHAR * pszS2,
  2676. const WCHAR * pszS3)
  2677. {
  2678. const WCHAR* ps[3];
  2679. ps[0] = pszS1;
  2680. ps[1] = pszS2;
  2681. ps[2] = pszS3;
  2682. WORD iStr = 0;
  2683. for (int i = 0; i < 3; i++)
  2684. {
  2685. if (ps[i] != NULL) iStr++;
  2686. }
  2687. if (hEventSource)
  2688. {
  2689. ::ReportEvent(
  2690. hEventSource,
  2691. wType,
  2692. 0,
  2693. dwID,
  2694. NULL, // sid
  2695. iStr,
  2696. dwDataSize,
  2697. ps,
  2698. pRawData);
  2699. }
  2700. }
  2701. BOOL IsPowerUsers()
  2702. {
  2703. BOOL fReturn = FALSE;
  2704. PSID psidPowerUsers;
  2705. DWORD dwErr;
  2706. SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
  2707. TENTER("IsPowerUsers");
  2708. if ( AllocateAndInitializeSid (
  2709. &SystemSidAuthority,
  2710. 2,
  2711. SECURITY_BUILTIN_DOMAIN_RID,
  2712. DOMAIN_ALIAS_RID_POWER_USERS,
  2713. 0, 0, 0, 0, 0, 0, &psidPowerUsers))
  2714. {
  2715. if (! CheckTokenMembership(NULL, psidPowerUsers, &fReturn))
  2716. {
  2717. dwErr = GetLastError();
  2718. TRACE(0, "! CheckTokenMembership : %ld", dwErr);
  2719. }
  2720. FreeSid (psidPowerUsers);
  2721. }
  2722. else
  2723. {
  2724. dwErr = GetLastError();
  2725. TRACE(0, "! AllocateAndInitializeSid : %ld", dwErr);
  2726. }
  2727. TLEAVE();
  2728. return fReturn;
  2729. }
  2730. // function to check if caller is running in admin context
  2731. BOOL IsAdminOrSystem()
  2732. {
  2733. BOOL fReturn = FALSE;
  2734. PSID psidAdmin, psidSystem;
  2735. DWORD dwErr;
  2736. SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
  2737. TENTER("IsAdminOrSystem");
  2738. //
  2739. // check if caller is Admin
  2740. //
  2741. if ( AllocateAndInitializeSid (
  2742. &SystemSidAuthority,
  2743. 2,
  2744. SECURITY_BUILTIN_DOMAIN_RID,
  2745. DOMAIN_ALIAS_RID_ADMINS,
  2746. 0, 0, 0, 0, 0, 0, &psidAdmin) )
  2747. {
  2748. if (! CheckTokenMembership(NULL, psidAdmin, &fReturn))
  2749. {
  2750. dwErr = GetLastError();
  2751. TRACE(0, "! CheckTokenMembership : %ld", dwErr);
  2752. }
  2753. FreeSid (psidAdmin);
  2754. //
  2755. // if so, scoot
  2756. //
  2757. if (fReturn)
  2758. {
  2759. goto done;
  2760. }
  2761. //
  2762. // check if caller is localsystem
  2763. //
  2764. if ( AllocateAndInitializeSid (
  2765. &SystemSidAuthority,
  2766. 1,
  2767. SECURITY_LOCAL_SYSTEM_RID,
  2768. 0,
  2769. 0, 0, 0, 0, 0, 0, &psidSystem) )
  2770. { if (! CheckTokenMembership(NULL, psidSystem, &fReturn))
  2771. {
  2772. dwErr = GetLastError();
  2773. TRACE(0, "! CheckTokenMembership : %ld", dwErr);
  2774. }
  2775. FreeSid(psidSystem);
  2776. }
  2777. else
  2778. {
  2779. dwErr = GetLastError();
  2780. TRACE(0, "! AllocateAndInitializeSid : %ld", dwErr);
  2781. }
  2782. }
  2783. else
  2784. {
  2785. dwErr = GetLastError();
  2786. TRACE(0, "! AllocateAndInitializeSid : %ld", dwErr);
  2787. }
  2788. done:
  2789. TLEAVE();
  2790. return (fReturn);
  2791. }
  2792. DWORD
  2793. SRLoadString(LPCWSTR pszModule, DWORD dwStringId, LPWSTR pszString, DWORD cbBytes)
  2794. {
  2795. DWORD dwErr = ERROR_SUCCESS;
  2796. HINSTANCE hModule = NULL;
  2797. if (hModule = LoadLibraryEx(pszModule,
  2798. NULL,
  2799. DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE))
  2800. {
  2801. if (! LoadString(hModule, dwStringId, pszString, cbBytes))
  2802. {
  2803. dwErr = GetLastError();
  2804. }
  2805. FreeLibrary(hModule);
  2806. }
  2807. else dwErr = GetLastError();
  2808. return dwErr;
  2809. }
  2810. //
  2811. // replace CurrentControlSet in pszString with ControlSetxxx
  2812. //
  2813. void
  2814. ChangeCCS(HKEY hkMount, LPWSTR pszString)
  2815. {
  2816. tenter("ChangeCCS");
  2817. int nCS = lstrlen(L"CurrentControlSet");
  2818. if (_wcsnicmp(pszString, L"CurrentControlSet", nCS) == 0)
  2819. {
  2820. WCHAR szCS[20] = L"ControlSet001";
  2821. DWORD dwCurrent = 0;
  2822. HKEY hKey = NULL;
  2823. if (ERROR_SUCCESS == RegOpenKeyEx(hkMount, L"Select", 0, KEY_READ, &hKey))
  2824. {
  2825. if (ERROR_SUCCESS == RegReadDWORD(hKey, L"Current", &dwCurrent))
  2826. {
  2827. wsprintf(szCS, L"ControlSet%03d", (int) dwCurrent);
  2828. }
  2829. RegCloseKey(hKey);
  2830. }
  2831. else
  2832. {
  2833. trace(0, "! RegOpenKeyEx : %ld", GetLastError());
  2834. }
  2835. WCHAR szTemp[MAX_PATH];
  2836. lstrcpy(szTemp, &(pszString[nCS]));
  2837. wsprintf(pszString, L"%s%s", szCS, szTemp);
  2838. trace(0, "ChangeCCS: pszString = %S", pszString);
  2839. }
  2840. tleave();
  2841. }
  2842. WCHAR * SRPathFindExtension (WCHAR * pwszPath)
  2843. {
  2844. WCHAR *pwszDot = NULL;
  2845. if (pwszPath != NULL)
  2846. for (; *pwszPath; pwszPath++)
  2847. {
  2848. switch (*pwszPath)
  2849. {
  2850. case L'.':
  2851. pwszDot = pwszPath; // remember the last dot
  2852. break;
  2853. case L'\\':
  2854. case L' ':
  2855. pwszDot = NULL; // extensions can't have spaces
  2856. break; // forget last dot, it was in a directory
  2857. }
  2858. }
  2859. return pwszDot;
  2860. }
  2861. // In order to prevent endless loop in case of disk failure, try only up to
  2862. // a predefined number.
  2863. #define MAX_ALT_INDEX 1000
  2864. //
  2865. // This function makes an unique alternative name of given file name, keeping
  2866. // path and extension.
  2867. //
  2868. BOOL SRGetAltFileName( LPCWSTR cszPath, LPWSTR szAltName )
  2869. {
  2870. TraceFunctEnter("SRGetAltFileName");
  2871. BOOL fRet = FALSE;
  2872. WCHAR szNewPath[SR_MAX_FILENAME_LENGTH];
  2873. LPWSTR szExtPos;
  2874. WCHAR szExtBuf[SR_MAX_FILENAME_LENGTH];
  2875. int nAltIdx;
  2876. if (lstrlenW (cszPath) >= SR_MAX_FILENAME_LENGTH)
  2877. goto Exit;
  2878. ::lstrcpy( szNewPath, cszPath );
  2879. szExtPos = SRPathFindExtension( szNewPath );
  2880. if ( szExtPos != NULL )
  2881. {
  2882. ::lstrcpy( szExtBuf, szExtPos );
  2883. }
  2884. else
  2885. {
  2886. szExtBuf[0] = L'\0';
  2887. szExtPos = &szNewPath[ lstrlen(szNewPath) ]; // end of string
  2888. }
  2889. for ( nAltIdx = 2; nAltIdx < MAX_ALT_INDEX; nAltIdx++ )
  2890. {
  2891. ::wsprintf( szExtPos, L"(%d)%s", nAltIdx, szExtBuf );
  2892. if ( ::GetFileAttributes( szNewPath ) == 0xFFFFFFFF )
  2893. break;
  2894. }
  2895. if ( nAltIdx == MAX_ALT_INDEX )
  2896. {
  2897. ErrorTrace(0, "Couldn't get alternative name.");
  2898. goto Exit;
  2899. }
  2900. ::lstrcpy( szAltName, szNewPath );
  2901. fRet = TRUE;
  2902. Exit:
  2903. TraceFunctLeave();
  2904. return( fRet );
  2905. }
  2906. CSRClientLoader::CSRClientLoader()
  2907. {
  2908. m_hSRClient=NULL;
  2909. m_hFrameDyn=NULL;
  2910. }
  2911. CSRClientLoader::~CSRClientLoader()
  2912. {
  2913. // unload library here
  2914. if (m_hFrameDyn != NULL)
  2915. {
  2916. _VERIFY(FreeLibrary(m_hFrameDyn));
  2917. }
  2918. if (m_hSRClient != NULL)
  2919. {
  2920. _VERIFY(FreeLibrary(m_hSRClient));
  2921. }
  2922. }
  2923. BOOL CSRClientLoader::LoadFrameDyn()
  2924. {
  2925. TraceFunctEnter("LoadFrameDyn");
  2926. WCHAR szFrameDynPath[MAX_PATH+100];
  2927. DWORD dwCharsCopied, dwBufSize,dwError;
  2928. BOOL fReturn=FALSE;
  2929. m_hFrameDyn=LoadLibrary(FRAMEDYN_DLL); // file name of module
  2930. if (m_hFrameDyn != NULL)
  2931. {
  2932. // we are done.
  2933. fReturn = TRUE;
  2934. goto cleanup;
  2935. }
  2936. // framedyn.dll could not be loaded. Try to load framedyn.dll
  2937. // from the explicit path. (system32\wbem\framedyn.dll)
  2938. dwError = GetLastError();
  2939. ErrorTrace(0,"Failed to load framedyn.dll on first attempt. ec=%d",
  2940. dwError);
  2941. // get the windows system32 directory
  2942. // add wbem\framedyn.dll
  2943. // Call LoadLibrary on this path
  2944. dwBufSize = sizeof(szFrameDynPath)/sizeof(WCHAR);
  2945. dwCharsCopied=GetSystemDirectory(
  2946. szFrameDynPath, //buffer for system directory
  2947. dwBufSize); // size of directory buffer
  2948. if (dwCharsCopied == 0)
  2949. {
  2950. dwError = GetLastError();
  2951. ErrorTrace(0,"Failed to load system directory. ec=%d", dwError);
  2952. goto cleanup;
  2953. }
  2954. // check if buffer is big enough.
  2955. if (dwBufSize < dwCharsCopied + sizeof(FRAMEDYN_DLL)/sizeof(WCHAR) +
  2956. sizeof(WBEM_DIRECTORY)/sizeof(WCHAR)+ 3 )
  2957. {
  2958. ErrorTrace(0,"Buffer not big enough. WinSys is %d chars long",
  2959. dwCharsCopied);
  2960. goto cleanup;
  2961. }
  2962. lstrcat(szFrameDynPath, L"\\" WBEM_DIRECTORY L"\\" FRAMEDYN_DLL);
  2963. m_hFrameDyn=LoadLibrary(szFrameDynPath); // file name of module
  2964. if (m_hFrameDyn == NULL)
  2965. {
  2966. // we are done.
  2967. fReturn = FALSE;
  2968. dwError = GetLastError();
  2969. ErrorTrace(0,"Failed to load framedyn.dll on second attempt. ec=%d",
  2970. dwError);
  2971. goto cleanup;
  2972. }
  2973. fReturn=TRUE;
  2974. cleanup:
  2975. TraceFunctLeave();
  2976. return fReturn;
  2977. }
  2978. BOOL CSRClientLoader::LoadSrClient()
  2979. {
  2980. TraceFunctEnter("LoadSrClient");
  2981. DWORD dwError;
  2982. BOOL fReturn=FALSE;
  2983. if (m_hSRClient != NULL)
  2984. {
  2985. fReturn=TRUE;
  2986. goto cleanup;
  2987. }
  2988. // sometimes srclient.dll cannot be loaded because framedyn.dll
  2989. // cannot be loaded because of the PATH variable being messed up.
  2990. // Explicitly load framedyn.dll from %windir%\system32\wbem
  2991. // and then try again.
  2992. if (FALSE == LoadFrameDyn())
  2993. {
  2994. ErrorTrace(0,"Failed to load framedyn.dll");
  2995. // we can still try to load srclient.dll
  2996. }
  2997. m_hSRClient=LoadLibrary(L"srclient.dll"); // file name of module
  2998. if (m_hSRClient == NULL)
  2999. {
  3000. dwError = GetLastError();
  3001. ErrorTrace(0,"Failed to load srclient.dll. ec=%d", dwError);
  3002. goto cleanup;
  3003. }
  3004. fReturn=TRUE;
  3005. cleanup:
  3006. TraceFunctLeave();
  3007. return fReturn;
  3008. }