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

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