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.

1827 lines
57 KiB

  1. #include "StdAfx.h"
  2. #include "resource.h"
  3. #include "errno.h"
  4. #include "aclapi.h"
  5. #include "Wsb.h"
  6. #include "rpfilt.h"
  7. // File/Directory
  8. // Create a directory and all the parent directories necessary for this directory to
  9. // exist.
  10. HRESULT WsbCreateAllDirectories(OLECHAR* path) {
  11. HRESULT hr = S_OK;
  12. CWsbBstrPtr win32Path;
  13. CWsbBstrPtr parentPath;
  14. try {
  15. // Convert the path to the win32 style path (to handle long file names), and
  16. // then try to create the directory.
  17. WsbAffirmHr(WsbGetWin32PathAsBstr(path, &win32Path));
  18. if (CreateDirectory(win32Path, 0) == 0) {
  19. hr = HRESULT_FROM_WIN32(GetLastError());
  20. }
  21. // There are 4 possibilities:
  22. // 1) it worked (we are done)
  23. // 2) the directory already exists (we are done)
  24. // 3) the directory doesn't exist, so try again after creating the parent
  25. // 4) some other error occurred, so quit
  26. if (FAILED(hr)) {
  27. if ((HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) == hr) || (HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) == hr) || (HRESULT_FROM_WIN32(ERROR_FILE_EXISTS) == hr)) {
  28. hr = S_OK;
  29. } else if ((HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr) || (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)) {
  30. // Create the parent directory and try again.
  31. WsbAffirmHr(WsbCreateAllDirectoriesForFile(path));
  32. if (CreateDirectory(win32Path, 0) == 0) {
  33. hr = HRESULT_FROM_WIN32(GetLastError());
  34. if ((HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) == hr) || (HRESULT_FROM_WIN32(ERROR_FILE_EXISTS) == hr)) {
  35. hr = S_OK;
  36. }
  37. } else {
  38. hr = S_OK;
  39. }
  40. }
  41. }
  42. } WsbCatch(hr);
  43. return(hr);
  44. }
  45. // Create a all the parent directories necessary for this file to exist.
  46. HRESULT WsbCreateAllDirectoriesForFile(OLECHAR* path) {
  47. HRESULT hr = S_OK;
  48. CWsbBstrPtr parentPath;
  49. OLECHAR* slashPtr = 0;
  50. OLECHAR* pathStart = 0;
  51. try {
  52. // Find out where the relative portion of the path starts, since we don't need to try
  53. // to create the root directory.
  54. parentPath = path;
  55. if ((parentPath[0] == L'\\') && (parentPath[1] == L'\\')) {
  56. pathStart = wcschr(&parentPath[2], L'\\');
  57. WsbAffirm(pathStart != 0, E_INVALIDARG);
  58. pathStart = wcschr(++pathStart, L'\\');
  59. WsbAffirm(pathStart != 0, E_INVALIDARG);
  60. } else if (parentPath[1] == L':') {
  61. pathStart = &parentPath[2];
  62. } else {
  63. WsbAssert(FALSE, E_INVALIDARG);
  64. }
  65. WsbAffirm(*pathStart != 0, E_INVALIDARG);
  66. // Create the path to the parent directory and use the create all to create it.
  67. slashPtr = wcsrchr(pathStart, L'\\');
  68. if ((slashPtr != 0) && (slashPtr != pathStart)) {
  69. *slashPtr = 0;
  70. WsbAffirmHr(WsbCreateAllDirectories(parentPath));
  71. }
  72. } WsbCatch(hr);
  73. return(hr);
  74. }
  75. // Convert a normal path (UNC or drive letter) to the internal format that is needed by
  76. // win32 to deal with long paths and special characters.
  77. HRESULT WsbGetWin32PathAsBstr(OLECHAR* path, BSTR* pWin32Path)
  78. {
  79. HRESULT hr = S_OK;
  80. CWsbBstrPtr win32Path;
  81. try {
  82. WsbAssert(0 != pWin32Path, E_POINTER);
  83. // Is it a UNC or a drive letter base path?
  84. if ((path[0] == L'\\') && (path[1] == L'\\')) {
  85. // UNC Paths must be preceeded with '\\?\UNC', but the then should only be
  86. // followed by one '\' not two.
  87. win32Path = L"\\\\?\\UNC";
  88. WsbAffirmHr(win32Path.Append(&path[1]));
  89. } else if (path[1] == L':') {
  90. // Drive letter based paths need to be preceeded by \\?\.
  91. win32Path = L"\\\\?\\";
  92. WsbAffirmHr(win32Path.Append(path));
  93. } else {
  94. WsbThrow(E_INVALIDARG);
  95. }
  96. WsbAffirmHr(win32Path.CopyToBstr(pWin32Path));
  97. } WsbCatch(hr);
  98. return(hr);
  99. }
  100. // Convert the internal format that is needed by win32 to deal with long paths and
  101. // special characters to a normal path (UNC or drive letter).
  102. HRESULT WsbGetPathFromWin32AsBstr(OLECHAR* win32Path, BSTR* pPath)
  103. {
  104. HRESULT hr = S_OK;
  105. CWsbBstrPtr path;
  106. try {
  107. WsbAssert(0 != pPath, E_POINTER);
  108. // Is it a UNC or a drive letter base path?
  109. if (_wcsnicmp(win32Path, L"\\\\?\\", 4) == 0) {
  110. path = &win32Path[4];
  111. } else if (_wcsnicmp(win32Path, L"\\\\?\\UNC", 7) == 0) {
  112. path = "\\";
  113. WsbAffirmHr(path.Append(&path[7]));
  114. } else {
  115. WsbThrow(E_INVALIDARG);
  116. }
  117. WsbAffirmHr(path.CopyToBstr(pPath));
  118. } WsbCatch(hr);
  119. return(hr);
  120. }
  121. // String & Buffer Copy
  122. HRESULT WsbGetComBuffer(OLECHAR** pDest, ULONG requestedSize, ULONG neededSize, BOOL* pWasAllocated) {
  123. HRESULT hr = S_OK;
  124. // If they didn't give us a buffer, then let them know that we
  125. // had to allocate one for them.
  126. if (pWasAllocated != NULL) {
  127. if (*pDest == NULL) {
  128. *pWasAllocated = TRUE;
  129. }
  130. else {
  131. *pWasAllocated = FALSE;
  132. }
  133. }
  134. // If they gave us the size they wanted (or have) for the
  135. // buffer, then it better be big enough.
  136. if (requestedSize != 0) {
  137. if (requestedSize < neededSize) {
  138. hr = E_INVALIDARG;
  139. }
  140. else if (*pDest == NULL) {
  141. *pDest = (OLECHAR*)WsbAlloc(requestedSize);
  142. if (*pDest == NULL) {
  143. hr = E_OUTOFMEMORY;
  144. }
  145. }
  146. }
  147. // If we control the size of the buffer, then make sure it is
  148. // the right size.
  149. //
  150. // NOTE: This may move the buffer!
  151. else {
  152. LPVOID pTemp = WsbRealloc(*pDest, neededSize);
  153. if (pTemp == NULL) {
  154. hr = E_OUTOFMEMORY;
  155. } else {
  156. *pDest = (OLECHAR *) pTemp;
  157. }
  158. }
  159. return(hr);
  160. }
  161. HRESULT WsbAllocAndCopyComString(OLECHAR** pszDest, OLECHAR* szSrc, ULONG bufferSize) {
  162. return(WsbAllocAndCopyComString2(pszDest, szSrc, bufferSize, TRUE));
  163. }
  164. HRESULT WsbAllocAndCopyComString2(OLECHAR** pszDest, OLECHAR* szSrc, ULONG bufferSize, BOOL bInOrder) {
  165. HRESULT hr = S_OK;
  166. ULONG ulStringSize;
  167. BOOL bWasAllocated;
  168. BOOL bCopyFailed = FALSE;
  169. // Determine how big a buffer we need to store the string.
  170. // NOTE: If we given a NULL pointer, then assume a "" will
  171. // be created.
  172. if (szSrc == NULL) {
  173. ulStringSize = sizeof(OLECHAR);
  174. }
  175. else {
  176. ulStringSize = (wcslen(szSrc) + 1) * sizeof(OLECHAR);
  177. }
  178. // Make sure that we have a buffer that we can use, and also
  179. // remember if we created it (so that we can free it on failure).
  180. hr = WsbGetComBuffer(pszDest, bufferSize, ulStringSize, &bWasAllocated);
  181. // If we have a valid buffer, then copy the string.
  182. if (SUCCEEDED(hr)) {
  183. if (szSrc == NULL) {
  184. *pszDest[0] = 0;
  185. }
  186. else if (bInOrder) {
  187. if (wcscpy(*pszDest, szSrc) != *pszDest) {
  188. bCopyFailed = TRUE;
  189. }
  190. }
  191. else {
  192. int i,j;
  193. for (i = 0, j = (ulStringSize / sizeof(OLECHAR)) - 2; j >= 0; i++, j--) {
  194. (*pszDest)[i] = szSrc[j];
  195. }
  196. (*pszDest)[i] = OLECHAR( '\0' );
  197. }
  198. if (bCopyFailed) {
  199. // If the copy failed then free the buffer and
  200. // return an error.
  201. if (bWasAllocated) {
  202. WsbFree(*pszDest);
  203. *pszDest = NULL;
  204. }
  205. hr = E_FAIL;
  206. }
  207. }
  208. return(hr);
  209. }
  210. HRESULT WsbLoadComString(HINSTANCE hInstance, UINT uID, OLECHAR** pszDest, ULONG bufferSize) {
  211. HRESULT hr = S_OK;
  212. HRSRC hResource;
  213. ULONG ulStringSize;
  214. BOOL bWasAllocated = FALSE;
  215. // Find the resource requested. This requires converting the resource
  216. // identifier into a string.
  217. //
  218. // NOTE: Strings are not number individually, but in groups of 16!! This throws
  219. // off the latter size calculation, and some other strategy might be better
  220. // here (e.g. load to a fixed size and then allocate again if too small).
  221. hResource = FindResource(hInstance, MAKEINTRESOURCE((uID/16) + 1), RT_STRING);
  222. if (hResource == NULL) {
  223. hr = E_FAIL;
  224. }
  225. else {
  226. // How big is the string?
  227. ulStringSize = SizeofResource(hInstance, hResource);
  228. if (ulStringSize == 0) {
  229. hr = E_FAIL;
  230. }
  231. else {
  232. // Get the right sized buffer.
  233. hr = WsbGetComBuffer(pszDest, bufferSize, ulStringSize, &bWasAllocated);
  234. if (SUCCEEDED(hr)) {
  235. // Load the string into the buffer.
  236. if (LoadString(hInstance, uID, (LPTSTR) *pszDest, ulStringSize) == 0) {
  237. // If we couldn't load the string, then free the buffer that
  238. // if we allocated it.
  239. if (bWasAllocated) {
  240. WsbFree(*pszDest);
  241. }
  242. hr = E_FAIL;
  243. }
  244. }
  245. }
  246. }
  247. return(hr);
  248. }
  249. HRESULT WsbMatchComString(OLECHAR* szEnd, UINT uId, USHORT usChecks, UINT* uIdMatch) {
  250. HRESULT hr = S_FALSE;
  251. HRESULT hr2;
  252. OLECHAR* szDest = NULL;
  253. // Initialize the return value.
  254. *uIdMatch = 0;
  255. // Check each resource string mention and see if it is the same as
  256. // the string provided.
  257. for (UINT uIdTest = uId; ((uIdTest < (uId + usChecks)) && (hr == S_FALSE)); uIdTest++) {
  258. hr2 = WsbLoadComString(_Module.m_hInst, uIdTest, &szDest, 0);
  259. if (SUCCEEDED(hr2)) {
  260. if (wcscmp(szDest, szEnd) == 0) {
  261. *uIdMatch = uIdTest;
  262. }
  263. }
  264. else {
  265. hr =hr2;
  266. }
  267. }
  268. // If we allocated a buffer, then we need to free it.
  269. if (szDest != NULL) {
  270. WsbFree(szDest);
  271. }
  272. return(hr);
  273. }
  274. // Type Conversion
  275. void WsbLLtoHL(LONGLONG ll, LONG* pHigh, LONG* pLow) {
  276. *pHigh = (DWORD) (ll >> 32);
  277. *pLow = (DWORD) (ll & 0x00000000ffffffff);
  278. }
  279. LONGLONG WsbHLtoLL(LONG high, LONG low) {
  280. LONGLONG ll;
  281. ll = ((LONGLONG) high) << 32;
  282. ll += (LONGLONG) (ULONG) low;
  283. return(ll);
  284. }
  285. FILETIME WsbLLtoFT(LONGLONG ll) {
  286. FILETIME ft;
  287. WsbLLtoHL(ll, (LONG*) &ft.dwHighDateTime, (LONG*) &ft.dwLowDateTime);
  288. return(ft);
  289. }
  290. LONGLONG WsbFTtoLL(FILETIME ft) {
  291. LONGLONG ll;
  292. ll = WsbHLtoLL((LONG) ft.dwHighDateTime, (LONG) ft.dwLowDateTime);
  293. return(ll);
  294. }
  295. HRESULT WsbFTtoWCS(BOOL isRelative, FILETIME ft, OLECHAR** pszA, ULONG bufferSize) {
  296. SYSTEMTIME st;
  297. HRESULT hr = S_OK;
  298. BOOL bWasAllocated = FALSE;
  299. LONGLONG llIn = WsbFTtoLL(ft);
  300. WsbTraceIn(OLESTR("WsbFTtoWCS"), OLESTR("isRelative = %ls, ft = %I64x"),
  301. WsbQuickString(WsbBoolAsString(isRelative)), ft);
  302. // If this is a relative time, then FT is just ticks.
  303. if (isRelative) {
  304. LONGLONG llTicks=0;
  305. UINT uId=0;
  306. // Try to find a scale that works (i.e. the largest one with
  307. // no remainder.
  308. if (llIn == 0) {
  309. llTicks = 0;
  310. uId = IDS_WSB_FT_TYPE_SECOND;
  311. }
  312. else if ((llIn % WSB_FT_TICKS_PER_YEAR) == 0) {
  313. llTicks = llIn / WSB_FT_TICKS_PER_YEAR;
  314. uId = IDS_WSB_FT_TYPE_YEAR;
  315. }
  316. else if ((llIn % WSB_FT_TICKS_PER_MONTH) == 0) {
  317. llTicks = llIn / WSB_FT_TICKS_PER_MONTH;
  318. uId = IDS_WSB_FT_TYPE_MONTH;
  319. }
  320. else if ((llIn % WSB_FT_TICKS_PER_DAY) == 0) {
  321. llTicks = llIn / WSB_FT_TICKS_PER_DAY;
  322. uId = IDS_WSB_FT_TYPE_DAY;
  323. }
  324. else if ((llIn % WSB_FT_TICKS_PER_HOUR) == 0) {
  325. llTicks = llIn / WSB_FT_TICKS_PER_HOUR;
  326. uId = IDS_WSB_FT_TYPE_HOUR;
  327. }
  328. else if ((llIn % WSB_FT_TICKS_PER_MINUTE) == 0) {
  329. llTicks = llIn / WSB_FT_TICKS_PER_MINUTE;
  330. uId = IDS_WSB_FT_TYPE_MINUTE;
  331. }
  332. else if ((llIn % WSB_FT_TICKS_PER_SECOND) == 0) {
  333. llTicks = llIn / WSB_FT_TICKS_PER_SECOND;
  334. uId = IDS_WSB_FT_TYPE_SECOND;
  335. }
  336. else {
  337. hr = E_INVALIDARG;
  338. }
  339. // If we found a scale, then form the proper string.
  340. if (SUCCEEDED(hr)) {
  341. OLECHAR* szTmp1 = NULL;
  342. OLECHAR* szTmp2 = NULL;
  343. // Get the string corresponding to the time period selected.
  344. hr = WsbLoadComString(_Module.m_hInst, uId, &szTmp1, 0);
  345. if (SUCCEEDED(hr)) {
  346. hr = WsbLLtoWCS(llTicks, &szTmp2, 0);
  347. if (SUCCEEDED(hr)) {
  348. hr = WsbGetComBuffer(pszA, bufferSize, (wcslen(szTmp1) + wcslen(szTmp2) + 2) * sizeof(OLECHAR), NULL);
  349. if (SUCCEEDED(hr)) {
  350. swprintf( *pszA, OLESTR("%ls %ls"), szTmp2, szTmp1);
  351. }
  352. WsbFree(szTmp2);
  353. }
  354. WsbFree(szTmp1);
  355. }
  356. }
  357. }
  358. // Otherwise it is absolute and converts to a specific date and time.
  359. else {
  360. // Convert the filetime to a system time.
  361. if (!FileTimeToSystemTime(&ft, &st)) {
  362. hr = E_FAIL;
  363. }
  364. else {
  365. // Get a buffer for the time string.
  366. hr = WsbGetComBuffer(pszA, bufferSize, WSB_FT_TO_WCS_ABS_STRLEN * sizeof(OLECHAR), &bWasAllocated);
  367. if (SUCCEEDED(hr)) {
  368. // Print the time in the buffer according to the standard
  369. // format mm/dd/yy @ hh:mm:ss.
  370. swprintf( *pszA, OLESTR("%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d"), st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute, st.wSecond);
  371. }
  372. }
  373. }
  374. WsbTraceOut(OLESTR("WsbFTtoWCS"), OLESTR("pszA = %ls"), *pszA);
  375. return(hr);
  376. }
  377. HRESULT WsbLLtoWCS(LONGLONG ll, OLECHAR** pszA, ULONG bufferSize) {
  378. OLECHAR szTmp[80];
  379. HRESULT hr = S_OK;
  380. int i = 0;
  381. LONGLONG value = ll;
  382. BOOL bIsNegative = FALSE;
  383. // First check to see if ll is negative
  384. if (value < 0) {
  385. bIsNegative = TRUE;
  386. value *= -1;
  387. }
  388. // This builds the string in reverse, but we'll change the order
  389. // again we we copy it to a buffer.
  390. do {
  391. szTmp[i++] = (OLECHAR) ('0' + (value % 10));
  392. value /= 10;
  393. } while (value > 0);
  394. // Add the negative symbol is negative just before terminating NULL
  395. if (bIsNegative) {
  396. szTmp[i] = OLECHAR('-');
  397. i++;
  398. }
  399. // Add a terminating NULL
  400. szTmp[i] = OLECHAR( '\0' );
  401. // Now vopy the string into the target buffer.
  402. hr = WsbAllocAndCopyComString2(pszA, szTmp, bufferSize, FALSE);
  403. return(hr);
  404. }
  405. HRESULT WsbWCStoFT(OLECHAR* szA, BOOL* pisRelative, FILETIME* pft) {
  406. HRESULT hr = S_OK;
  407. OLECHAR* szEnd;
  408. // Is this an absolute time (i.e. a date and time) or a relative
  409. // time (e.g. 6 days, ...). This is determined by seeing a / in the
  410. // string, which should only be present in absolute times. (Input
  411. // format expected for an absolute time is either "mm/dd/yyyy hh:mm:ss"
  412. // or "mm/dd/yyyy". If no time is input for an absolute time (i.e.,
  413. // the "mm/dd/yyyy" format), then the current local time will be
  414. // filled in for the user.
  415. // Note that no millisecond info is to be included, since we supply
  416. // a 'ticks' field as a separate parameter whenever we work at the
  417. // millisecond/fraction of millisecond level.)
  418. szEnd = wcschr(szA, '/');
  419. // Is it a relative time (i.e. no '/')?
  420. if (szEnd == NULL) {
  421. LONGLONG llValue;
  422. *pisRelative = TRUE;
  423. // The first token should be a number, so convert the string to
  424. // a number.
  425. llValue = wcstoul(szA, &szEnd, 10);
  426. if (errno == ERANGE) {
  427. hr = E_INVALIDARG;
  428. }
  429. else {
  430. UINT uId;
  431. // The second token should be a type (i.e. second, hour, minute, ...).
  432. hr = WsbMatchComString(szEnd, IDS_WSB_FT_TYPE_YEAR, WSB_FT_TYPES_MAX, &uId);
  433. if (S_OK == hr) {
  434. switch (uId) {
  435. case IDS_WSB_FT_TYPE_YEAR:
  436. *pft = WsbLLtoFT(llValue * WSB_FT_TICKS_PER_YEAR);
  437. break;
  438. case IDS_WSB_FT_TYPE_MONTH:
  439. *pft = WsbLLtoFT(llValue * WSB_FT_TICKS_PER_MONTH);
  440. break;
  441. case IDS_WSB_FT_TYPE_WEEK:
  442. *pft = WsbLLtoFT(llValue * WSB_FT_TICKS_PER_WEEK);
  443. break;
  444. case IDS_WSB_FT_TYPE_DAY:
  445. *pft = WsbLLtoFT(llValue * WSB_FT_TICKS_PER_DAY);
  446. break;
  447. case IDS_WSB_FT_TYPE_HOUR:
  448. *pft = WsbLLtoFT(llValue * WSB_FT_TICKS_PER_HOUR);
  449. break;
  450. case IDS_WSB_FT_TYPE_MINUTE:
  451. *pft = WsbLLtoFT(llValue * WSB_FT_TICKS_PER_MINUTE);
  452. break;
  453. case IDS_WSB_FT_TYPE_SECOND:
  454. *pft = WsbLLtoFT(llValue * WSB_FT_TICKS_PER_SECOND);
  455. break;
  456. default:
  457. hr = E_INVALIDARG;
  458. break;
  459. }
  460. }
  461. }
  462. }
  463. // It is an absolute time.
  464. else {
  465. SYSTEMTIME st;
  466. BOOL timeWasInput = TRUE;
  467. OLECHAR* szSearchString;
  468. // The first number should represent the month.
  469. st.wMonth = (USHORT) wcstoul(szA, &szEnd, 10);
  470. // test resultant month within range, and that the format of the input
  471. // absolute date/time is valid (i.e., the character which stopped the
  472. // above conversion is the slash between the month and day digits)
  473. if ((st.wMonth < 1) || (st.wMonth > 12) || (*szEnd != ((OLECHAR) '/'))) {
  474. hr = E_INVALIDARG;
  475. }
  476. // The next number should represent the day.
  477. if (SUCCEEDED(hr)) {
  478. // set szSearchString to 1 character beyond the character that
  479. // stopped the above 'wcstoul' conversion
  480. szSearchString = szEnd + 1;
  481. st.wDay = (USHORT) wcstoul(szSearchString, &szEnd, 10);
  482. if ((st.wDay < 1) || (st.wDay > 31) || (*szEnd != ((OLECHAR) '/'))) {
  483. hr = E_INVALIDARG;
  484. }
  485. }
  486. // The next number should represent the year.
  487. if (SUCCEEDED(hr)) {
  488. szSearchString = szEnd + 1;
  489. st.wYear = (USHORT) wcstoul(szSearchString, &szEnd, 10);
  490. // test resultant year equal to at least 1601, since NT records
  491. // time and date starting from 12:00am, January 1, 1601. This
  492. // test also is used to enforce that a 4 digit year was entered.
  493. if ((st.wYear < 1601) || (*szEnd != ((OLECHAR) ' '))) {
  494. if (( st.wYear >= 1601 ) && ( szEnd[0] == 0 )) {
  495. SYSTEMTIME now;
  496. GetLocalTime ( &now );
  497. st.wHour = now.wHour;
  498. st.wMinute = now.wMinute;
  499. st.wSecond = now.wSecond;
  500. timeWasInput = FALSE;
  501. }
  502. else {
  503. hr = E_INVALIDARG;
  504. }
  505. }
  506. }
  507. // The next number should represent the hour.
  508. if ( timeWasInput ) {
  509. if (SUCCEEDED(hr)) {
  510. szSearchString = szEnd + 1;
  511. st.wHour = (USHORT) wcstoul(szSearchString, &szEnd, 10);
  512. if ((st.wHour > 23) || (*szEnd != ((OLECHAR) ':'))) {
  513. hr = E_INVALIDARG;
  514. }
  515. }
  516. }
  517. // The next number should represent the minutes.
  518. if ( timeWasInput ) {
  519. if (SUCCEEDED(hr)) {
  520. szSearchString = szEnd + 1;
  521. st.wMinute = (USHORT) wcstoul(szSearchString, &szEnd, 10);
  522. if ((st.wMinute > 59) || (*szEnd != ((OLECHAR) ':'))) {
  523. hr = E_INVALIDARG;
  524. }
  525. }
  526. }
  527. // The next number should represent the seconds.
  528. if ( timeWasInput ) {
  529. if (SUCCEEDED(hr)) {
  530. szSearchString = szEnd + 1;
  531. st.wSecond = (USHORT) wcstoul(szSearchString, &szEnd, 10);
  532. if ((st.wSecond > 59) || (szEnd[0] != 0)) {
  533. hr = E_INVALIDARG;
  534. }
  535. }
  536. }
  537. // NOTE: Although the SYSTEMTIME structure contains a milliseconds field,
  538. // it can only express milliseconds as whole numbers, so this function
  539. // does not support any way to specify the number of milliseconds. If
  540. // millisecond/fraction of milliseconds are necessary, after this function
  541. // returns add in the NT-supported 'number of 100 nanosecond 'ticks'' to
  542. // the FILETIME result output by this function. The number of
  543. // ticks is used to represent both milliseconds and fractions thereof.
  544. // initialize the millisecond field before converting SystemTime to FileTime
  545. st.wMilliseconds = 0;
  546. // If we properly converted the string, then convert the
  547. // system time into a file time.
  548. if (SUCCEEDED(hr)) {
  549. if ( SystemTimeToFileTime(&st, pft) == FALSE) {
  550. hr = E_FAIL;
  551. }
  552. }
  553. }
  554. return(hr);
  555. }
  556. HRESULT WsbWCStoLL(OLECHAR* szA, LONGLONG* pll) {
  557. HRESULT hr = S_OK;
  558. LONGLONG llFactor = 1;
  559. size_t ulLength = wcslen(szA);
  560. // It is an error not to have any digits.
  561. if (ulLength == 0) {
  562. hr = E_INVALIDARG;
  563. }
  564. else {
  565. int i;
  566. // Step through character by character.
  567. for (i = ulLength, *pll = 0; ((i > 0) && (SUCCEEDED(hr))); i--) {
  568. if (iswalpha(szA[i-1])) {
  569. (*pll) += llFactor * ((LONGLONG) (szA[i-1] - ((OLECHAR) '0')));
  570. llFactor *= 10;
  571. }
  572. else {
  573. hr = E_INVALIDARG;
  574. }
  575. }
  576. }
  577. return(hr);
  578. }
  579. HRESULT WsbDatetoFT(DATE date, LONG ticks, FILETIME* pFt)
  580. {
  581. HRESULT hr = S_OK;
  582. SYSTEMTIME st;
  583. try {
  584. WsbAssert(0 != pFt, E_POINTER);
  585. // Do the basic date conversion
  586. WsbAffirmHr(VariantTimeToSystemTime(date, &st));
  587. WsbAffirmStatus(SystemTimeToFileTime(&st, pFt));
  588. // Variant DATE field only tracks time and date down to seconds.
  589. // FILETIMEs are kept using a 64 bit value specifying the number
  590. // of 100-nanosecond intervals that have elapsed since 12:00am
  591. // January 1, 1601. Since our 'ticks' value represents milliseconds
  592. // and fractions of milliseconds using the same 100-nanosecond interval
  593. // units, to add in milliseconds add in the ticks. But since FILETIME
  594. // is actually a structure of 2 DWORDs, we must use some conversions.
  595. LONGLONG FTasLL;
  596. FTasLL = WsbFTtoLL ( *pFt );
  597. FTasLL += (LONGLONG) ticks;
  598. *pFt = WsbLLtoFT ( FTasLL );
  599. } WsbCatch(hr);
  600. return(hr);
  601. }
  602. HRESULT WsbFTtoDate(FILETIME ft, DATE* pDate, LONG* pTicks)
  603. {
  604. HRESULT hr = S_OK;
  605. SYSTEMTIME st;
  606. FILETIME ft2;
  607. try {
  608. WsbAssert(0 != pDate, E_POINTER);
  609. WsbAssert(0 != pTicks, E_POINTER);
  610. // Do the basic time conversion.
  611. WsbAffirmStatus(FileTimeToSystemTime(&ft, &st));
  612. WsbAffirmStatus(SystemTimeToVariantTime(&st, pDate));
  613. // Now convert back what we have and figure out how many ticks got lost.
  614. WsbAffirmHr(WsbDatetoFT(*pDate, 0, &ft2));
  615. *pTicks = (LONG) (WsbFTtoLL(ft) - WsbFTtoLL(ft2));
  616. } WsbCatch(hr)
  617. return(hr);
  618. }
  619. HRESULT WsbLocalDateTicktoUTCFT(DATE date, LONG ticks, FILETIME* pFT)
  620. {
  621. // This routine converts a VARIANT DATE field (expressed in local time)
  622. // and a 'number of 100 nanosecond intervals' ticks field to a FILETIME
  623. // in UTC format. This is the format that file timestamps are kept in.
  624. // The result of this call is suitable for use in setting a file's timestamp.
  625. HRESULT hr = S_OK;
  626. FILETIME localFTHolder;
  627. try {
  628. WsbAssert(0 != pFT, E_POINTER);
  629. // Do the basic date conversion which yields a FILETIME in local time
  630. WsbAffirmHr(WsbDatetoFT(date, ticks, &localFTHolder));
  631. // Now convert the local time to UTC format FILETIME
  632. WsbAffirmStatus(LocalFileTimeToFileTime(&localFTHolder, pFT));
  633. } WsbCatch(hr);
  634. return(hr);
  635. }
  636. HRESULT WsbUTCFTtoLocalDateTick(FILETIME ft, DATE* pDate, LONG* pTicks)
  637. {
  638. // This routine converts a FILETIME field (expressed in UTC format - which
  639. // is the format file timestamps are stored in) to a VARIANT DATE field
  640. // (expressed in local time) and a Ticks field. The Ticks field represents
  641. // a 'number of 100 nanosecond intervals' which represents the 'milliseconds
  642. // and fractions of a millisecond' that was contained in the UTC formatted
  643. // FILETIME.
  644. HRESULT hr = S_OK;
  645. FILETIME localFT;
  646. try {
  647. WsbAssert(0 != pDate, E_POINTER);
  648. WsbAssert(0 != pTicks, E_POINTER);
  649. // First convert the UTC format FILETIME to one in Local Time
  650. WsbAffirmStatus(FileTimeToLocalFileTime(&ft, &localFT));
  651. // Do the basic time conversion.
  652. WsbAffirmHr(WsbFTtoDate(localFT, pDate, pTicks));
  653. } WsbCatch(hr)
  654. return(hr);
  655. }
  656. HRESULT WsbDateToString(DATE date, OLECHAR** string) {
  657. // NOTE: the caller owns the memory occupied by 'string' when this
  658. // helper function returns. Since 'string''s buffer is allocated
  659. // by WsbAlloc/Realloc(), memory needs to be freed via
  660. // WsbFree()
  661. HRESULT hr = S_OK;
  662. SYSTEMTIME systime;
  663. BOOL wasBufferAllocated;
  664. try {
  665. // convert the VARIANT Date to a system time
  666. WsbAffirmHr ( VariantTimeToSystemTime ( date, &systime ) );
  667. // create a COM buffer (meaning it was allocated with
  668. // WsbAlloc/Realloc()) to hold the date/time string which this method
  669. // will return. The buffer, passed back as 'string', will need to be freed
  670. // with WsbFree() by the caller. Note that passing a 'requested size'
  671. // (2nd arg) of zero forces a realloc of the 'string' buffer.
  672. WsbAffirmHr ( WsbGetComBuffer ( string, 0,
  673. (WSB_VDATE_TO_WCS_ABS_STRLEN * sizeof (OLECHAR)),
  674. &wasBufferAllocated ) );
  675. // load the buffer with the date and time using the standard
  676. // format: mm/dd/yyyy hh:mm:ss. Note that milliseconds are
  677. // not represented since a VARIANT Date field can only track
  678. // time to second granularity.
  679. swprintf ( *string, L"%2.2d/%2.2d/%2.4d %2.2d:%2.2d:%2.2d",
  680. systime.wMonth, systime.wDay, systime.wYear,
  681. systime.wHour, systime.wMinute, systime.wSecond );
  682. } WsbCatch ( hr )
  683. return ( hr );
  684. }
  685. HRESULT WsbStringToDate(OLECHAR* string, DATE* date)
  686. {
  687. HRESULT conversionHR = S_OK;
  688. BOOL isRelative;
  689. FILETIME holdFT;
  690. SYSTEMTIME holdST;
  691. try {
  692. // convert input wide char string to a FILETIME. Throw hr as
  693. // exception if not successful.
  694. WsbAffirmHr ( WsbWCStoFT ( string, &isRelative, &holdFT ) );
  695. // convert FILETIME result from above to SYSTEMTIME. If this
  696. // Boolean call fails, get Last Error, convert to hr and throw it.
  697. WsbAffirmStatus ( FileTimeToSystemTime ( &holdFT, &holdST ) );
  698. // finally, convert SYSTEMTIME result from above to VARIANT Date
  699. WsbAffirmHr ( SystemTimeToVariantTime ( &holdST, date ) );
  700. } WsbCatch ( conversionHR )
  701. return ( conversionHR );
  702. }
  703. // Filetime Manipulations
  704. FILETIME WsbFtSubFt(FILETIME ft1, FILETIME ft2)
  705. {
  706. return(WsbLLtoFT(WsbFTtoLL(ft1) - WsbFTtoLL(ft2)));
  707. }
  708. SHORT WsbCompareFileTimes(FILETIME ft1, FILETIME ft2, BOOL isRelative, BOOL isNewer)
  709. {
  710. SHORT result = 0;
  711. LONGLONG ll1;
  712. LONGLONG ll2;
  713. LONGLONG tmp;
  714. FILETIME ftNow;
  715. LONGLONG llNow;
  716. WsbTraceIn(OLESTR("WsbCompareFileTimes"), OLESTR("ft1 = %ls, ft2 = %ls, isRelative = %ls, isNewer = %ls"),
  717. WsbQuickString(WsbFiletimeAsString(FALSE, ft1)),
  718. WsbQuickString(WsbFiletimeAsString(isRelative, ft2)),
  719. WsbQuickString(WsbBoolAsString(isRelative)), WsbQuickString(WsbBoolAsString(isRelative)));
  720. ll1 = WsbFTtoLL(ft1);
  721. ll2 = WsbFTtoLL(ft2);
  722. if (isRelative) {
  723. GetSystemTimeAsFileTime(&ftNow);
  724. WsbTrace(OLESTR("WsbCompareFileTimes: ftNow = %ls\n"),
  725. WsbFiletimeAsString(FALSE, ftNow));
  726. llNow = WsbFTtoLL(ftNow);
  727. if (isNewer) {
  728. tmp = ll1 - llNow;
  729. } else {
  730. tmp = llNow - ll1;
  731. }
  732. if (tmp > ll2) {
  733. result = 1;
  734. } if (tmp < ll2) {
  735. result = -1;
  736. }
  737. }
  738. else {
  739. if (ll1 > ll2) {
  740. result = 1;
  741. } if (ll1 < ll2) {
  742. result = -1;
  743. }
  744. if (!isNewer) {
  745. result *= -1;
  746. }
  747. }
  748. WsbTraceOut(OLESTR("WsbCompareFileTimes"), OLESTR("result = %hd"), result);
  749. return(result);
  750. }
  751. // GUID Manipulations
  752. int WsbCompareGuid(REFGUID guid1, REFGUID guid2)
  753. {
  754. return(memcmp(&guid1, &guid2, sizeof(GUID)));
  755. }
  756. HRESULT WsbStringFromGuid(REFGUID rguid, OLECHAR* sz)
  757. {
  758. int returnCount = StringFromGUID2(rguid, sz, WSB_GUID_STRING_SIZE);
  759. return ( ( returnCount > 0) ? S_OK : E_FAIL );
  760. }
  761. HRESULT WsbGuidFromString(const OLECHAR* sz, GUID * pguid)
  762. {
  763. return CLSIDFromString((OLECHAR*)sz, pguid);
  764. }
  765. HRESULT WsbGetServiceId(OLECHAR* serviceName, GUID* pGuid )
  766. {
  767. HRESULT hr = S_OK;
  768. DWORD sizeGot;
  769. CWsbStringPtr outString;
  770. CWsbStringPtr tmpString;
  771. try {
  772. // Look in the registry to see if this service has already created itself and has
  773. // a GUID registered.
  774. tmpString = OLESTR("SYSTEM\\CurrentControlSet\\Services\\");
  775. WsbAffirmHr(WsbEnsureRegistryKeyExists(NULL, tmpString));
  776. WsbAffirmHr(tmpString.Append(serviceName));
  777. WsbAffirmHr(tmpString.Append(OLESTR("\\Parameters")));
  778. WsbAffirmHr(WsbEnsureRegistryKeyExists(NULL, tmpString));
  779. WsbAffirmHr(outString.Alloc(256));
  780. // if the SettingId value is there then we tell caller there is none
  781. // clean up the registry ?????
  782. if (WsbGetRegistryValueString(NULL, tmpString, OLESTR("SettingId"), outString, 256, &sizeGot) == S_OK) {
  783. // if the Id is there remove it first
  784. if (WsbGetRegistryValueString(NULL, tmpString, OLESTR("Id"), outString, 256, &sizeGot) == S_OK) {
  785. WsbAffirmHr( WsbRemoveRegistryValue(NULL, tmpString, OLESTR("Id") ) );
  786. }
  787. // Remove the SettingId value last
  788. WsbAffirmHr( WsbRemoveRegistryValue(NULL, tmpString, OLESTR("SettingId") ) );
  789. *pGuid = GUID_NULL ;
  790. WsbThrow( WSB_E_NOTFOUND );
  791. // if it is not there we return GUID_NULL
  792. } else if (WsbGetRegistryValueString(NULL, tmpString, OLESTR("Id"), outString, 256, &sizeGot) != S_OK) {
  793. *pGuid = GUID_NULL ;
  794. WsbThrow( WSB_E_NOTFOUND );
  795. // verify that the Id value is really there
  796. } else {
  797. WsbAffirmHr(IIDFromString(outString, (IID *)pGuid));
  798. }
  799. } WsbCatch(hr);
  800. return(hr);
  801. }
  802. HRESULT WsbSetServiceId(OLECHAR* serviceName, GUID guid )
  803. {
  804. HRESULT hr = S_OK;
  805. DWORD sizeGot;
  806. CWsbStringPtr outString;
  807. CWsbStringPtr tmpString;
  808. try {
  809. // Look in the registry to see if this service has already created itself and has
  810. // a GUID registered.
  811. tmpString = OLESTR("SYSTEM\\CurrentControlSet\\Services\\");
  812. WsbAffirmHr(WsbEnsureRegistryKeyExists(NULL, tmpString));
  813. WsbAffirmHr(tmpString.Append(serviceName));
  814. WsbAffirmHr(tmpString.Append(OLESTR("\\Parameters")));
  815. WsbAffirmHr(WsbEnsureRegistryKeyExists(NULL, tmpString));
  816. WsbAffirmHr(outString.Alloc(256));
  817. // If the Id string is not there then set it
  818. CWsbStringPtr strGuid;
  819. WsbAffirmHr(WsbSafeGuidAsString(guid, strGuid));
  820. if (WsbGetRegistryValueString(NULL, tmpString, OLESTR("Id"), outString, 256, &sizeGot) != S_OK) {
  821. // if there is a SettingId then we have something wrong in here so throw an error
  822. if (WsbGetRegistryValueString(NULL, tmpString, OLESTR("SettingId"), outString, 256, &sizeGot) == S_OK) {
  823. WsbThrow( WSB_E_INVALID_DATA );
  824. }
  825. WsbAffirmHr( WsbSetRegistryValueString(NULL, tmpString, OLESTR("Id"), strGuid ) );
  826. } else {
  827. // ID already exists so set it and blast the SettingId
  828. WsbAffirmHr( WsbSetRegistryValueString(NULL, tmpString, OLESTR("SettingId"), strGuid));
  829. WsbAffirmHr( WsbSetRegistryValueString(NULL, tmpString, OLESTR("Id"), strGuid));
  830. WsbAffirmHr( WsbRemoveRegistryValue(NULL, tmpString, OLESTR("SettingId") ) );
  831. }
  832. } WsbCatch(hr);
  833. return(hr);
  834. }
  835. HRESULT WsbCreateServiceId(OLECHAR* serviceName, GUID* pGuid )
  836. {
  837. HRESULT hr = S_OK;
  838. DWORD sizeGot;
  839. CWsbStringPtr outString;
  840. CWsbStringPtr tmpString;
  841. try {
  842. // Look in the registry to see if this service has already created itself and has
  843. // a GUID registered.
  844. tmpString = OLESTR("SYSTEM\\CurrentControlSet\\Services\\");
  845. WsbAffirmHr(WsbEnsureRegistryKeyExists(NULL, tmpString));
  846. WsbAffirmHr(tmpString.Append(serviceName));
  847. WsbAffirmHr(tmpString.Append(OLESTR("\\Parameters")));
  848. WsbAffirmHr(WsbEnsureRegistryKeyExists(NULL, tmpString));
  849. WsbAffirmHr(outString.Alloc(256));
  850. if (WsbGetRegistryValueString(NULL, tmpString, OLESTR("Id"), outString, 256, &sizeGot) != S_OK) {
  851. WsbAffirmHr(CoCreateGuid(pGuid));
  852. CWsbStringPtr strGuid;
  853. WsbAffirmHr(WsbSafeGuidAsString(*pGuid, strGuid));
  854. WsbAffirmHr(WsbSetRegistryValueString(NULL, tmpString, OLESTR("SettingId"), strGuid));
  855. WsbAffirmHr(WsbSetRegistryValueString(NULL, tmpString, OLESTR("Id"), strGuid));
  856. } else {
  857. WsbThrow( WSB_E_INVALID_DATA );
  858. }
  859. } WsbCatch(hr);
  860. return(hr);
  861. }
  862. HRESULT WsbConfirmServiceId(OLECHAR* serviceName, GUID guidConfirm )
  863. {
  864. HRESULT hr = S_OK;
  865. DWORD sizeGot;
  866. CWsbStringPtr outString;
  867. CWsbStringPtr tmpString;
  868. GUID guid;
  869. try {
  870. // Look in the registry to see if this service has already created itself and has
  871. // a GUID registered.
  872. tmpString = OLESTR("SYSTEM\\CurrentControlSet\\Services\\");
  873. WsbAffirmHr(WsbEnsureRegistryKeyExists(NULL, tmpString));
  874. WsbAffirmHr(tmpString.Append(serviceName));
  875. WsbAffirmHr(tmpString.Append(OLESTR("\\Parameters")));
  876. WsbAffirmHr(WsbEnsureRegistryKeyExists(NULL, tmpString));
  877. WsbAffirmHr(outString.Alloc(256));
  878. // verify that the Id value is really there
  879. WsbAffirmHr( WsbGetRegistryValueString(NULL, tmpString, OLESTR("Id"), outString, 256, &sizeGot) ) ;
  880. WsbAffirmHr( IIDFromString( outString, (IID *)&guid ) );
  881. WsbAffirm( guid == guidConfirm, WSB_E_INVALID_DATA );
  882. // verify that the SettingId value is really there and the same
  883. WsbAffirmHr( WsbGetRegistryValueString( NULL, tmpString, OLESTR("SettingId"), outString, 256, &sizeGot ) ) ;
  884. WsbAffirmHr( IIDFromString( outString, (IID *)&guid ) );
  885. WsbAffirm( guid == guidConfirm, WSB_E_INVALID_DATA );
  886. // remove the flag value
  887. WsbAffirmHr( WsbRemoveRegistryValue(NULL, tmpString, OLESTR("SettingId") ) );
  888. } WsbCatch(hr);
  889. return(hr);
  890. }
  891. HRESULT WsbGetMetaDataPath(OUT CWsbStringPtr & Path)
  892. {
  893. HRESULT hr = S_OK;
  894. DWORD sizeGot;
  895. try {
  896. // Find out where they have NT installed, and make sure that our subdirectory exists.
  897. WsbAffirmHr(Path.Alloc(256));
  898. //
  899. // Use the relocatable meta-data path if it's available,
  900. // otherwise default to the %SystemRoot%\System32\RemoteStorage
  901. //
  902. hr = WsbCheckIfRegistryKeyExists(NULL, WSB_CONTROL_REGISTRY_KEY);
  903. if (hr == S_OK) {
  904. WsbAffirmHr(WsbGetRegistryValueString(NULL, WSB_CONTROL_REGISTRY_KEY, WSB_METADATA_REGISTRY_VALUE, Path, 256, &sizeGot));
  905. } else {
  906. WsbAffirmHr(WsbEnsureRegistryKeyExists(NULL, WSB_CURRENT_VERSION_REGISTRY_KEY));
  907. WsbAffirmHr(WsbGetRegistryValueString(NULL, WSB_CURRENT_VERSION_REGISTRY_KEY, WSB_SYSTEM_ROOT_REGISTRY_VALUE, Path, 256, &sizeGot));
  908. WsbAffirmHr(Path.Append(OLESTR("\\system32\\RemoteStorage")));
  909. }
  910. } WsbCatchAndDo(hr,
  911. Path.Free();
  912. );
  913. return(hr);
  914. }
  915. HRESULT WsbGetServiceTraceDefaults(OLECHAR* serviceName, OLECHAR* traceFile, IUnknown* pUnk)
  916. {
  917. HRESULT hr = S_OK;
  918. DWORD sizeGot;
  919. CWsbStringPtr pathString;
  920. CWsbStringPtr outString;
  921. CWsbStringPtr rsPath;
  922. CWsbStringPtr tmpString;
  923. CComPtr<IWsbTrace> pTrace;
  924. OLECHAR* lastSlash;
  925. PSID pSystemSID = NULL;
  926. PSID pAdminSID = NULL;
  927. PSID pBackupOpSID = NULL;
  928. PACL pACL = NULL;
  929. #define METADATA_DIR_NUM_ACE 3
  930. EXPLICIT_ACCESS ea[METADATA_DIR_NUM_ACE];
  931. SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
  932. try {
  933. WsbAssertPointer(serviceName);
  934. WsbAffirmHr(WsbGetMetaDataPath(rsPath));
  935. // Create metadata directory
  936. tmpString = rsPath;
  937. WsbAffirmHr(tmpString.Prepend(OLESTR("\\\\?\\")));
  938. if (! CreateDirectory(tmpString, 0)) {
  939. // Directory already exists is expected
  940. DWORD status = GetLastError();
  941. if ((status == ERROR_ALREADY_EXISTS) || (status == ERROR_FILE_EXISTS)) {
  942. status = NO_ERROR;
  943. }
  944. WsbAffirmNoError(status);
  945. }
  946. // Set strong ACL on the RSS metadata directory
  947. // Note: In order to handle the upgrade case as well, we need to set the ACL even if
  948. // the directory exists. Another option would be:
  949. // 1. Set it here only if directory doesn't exist
  950. // 2. Then set ACL in CHsmServer::Load or in the Setup-upgrade code where there is
  951. // a dedicated code for the Win2K upgrade case
  952. // Prepare security attribute for admin only access:
  953. memset(ea, 0, sizeof(EXPLICIT_ACCESS) * METADATA_DIR_NUM_ACE);
  954. // Create a SID for the local system account
  955. WsbAssertStatus( AllocateAndInitializeSid( &SIDAuthNT, 1,
  956. SECURITY_LOCAL_SYSTEM_RID,
  957. 0, 0, 0, 0, 0, 0, 0,
  958. &pSystemSID) );
  959. // Initialize an EXPLICIT_ACCESS structure for an ACE.
  960. // The ACE allows the Administrators group full access to the directory
  961. ea[0].grfAccessPermissions = FILE_ALL_ACCESS;
  962. ea[0].grfAccessMode = SET_ACCESS;
  963. ea[0].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  964. ea[0].Trustee.pMultipleTrustee = NULL;
  965. ea[0].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
  966. ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  967. ea[0].Trustee.TrusteeType = TRUSTEE_IS_USER;
  968. ea[0].Trustee.ptstrName = (LPTSTR) pSystemSID;
  969. // Create a SID for the Administrators group.
  970. WsbAssertStatus( AllocateAndInitializeSid( &SIDAuthNT, 2,
  971. SECURITY_BUILTIN_DOMAIN_RID,
  972. DOMAIN_ALIAS_RID_ADMINS,
  973. 0, 0, 0, 0, 0, 0,
  974. &pAdminSID) );
  975. // Initialize an EXPLICIT_ACCESS structure for an ACE.
  976. // The ACE allows the Administrators group full access to the directory
  977. ea[1].grfAccessPermissions = FILE_ALL_ACCESS;
  978. ea[1].grfAccessMode = SET_ACCESS;
  979. ea[1].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  980. ea[1].Trustee.pMultipleTrustee = NULL;
  981. ea[1].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
  982. ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  983. ea[1].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
  984. ea[1].Trustee.ptstrName = (LPTSTR) pAdminSID;
  985. // Create a SID for the BackupOp group.
  986. WsbAssertStatus( AllocateAndInitializeSid( &SIDAuthNT, 2,
  987. SECURITY_BUILTIN_DOMAIN_RID,
  988. DOMAIN_ALIAS_RID_BACKUP_OPS,
  989. 0, 0, 0, 0, 0, 0,
  990. &pBackupOpSID) );
  991. // Initialize an EXPLICIT_ACCESS structure for an ACE.
  992. // The ACE allows the BackupOps group read access to the directory
  993. ea[2].grfAccessPermissions = (FILE_GENERIC_READ | FILE_TRAVERSE);
  994. ea[2].grfAccessMode = SET_ACCESS;
  995. ea[2].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  996. ea[2].Trustee.pMultipleTrustee = NULL;
  997. ea[2].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
  998. ea[2].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  999. ea[2].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
  1000. ea[2].Trustee.ptstrName = (LPTSTR) pBackupOpSID;
  1001. // Create a new ACL that contains the ACEs.
  1002. WsbAffirmNoError( SetEntriesInAcl(METADATA_DIR_NUM_ACE, ea, NULL, &pACL));
  1003. // Set the ACL on the directory
  1004. WsbAffirmWin32(SetNamedSecurityInfo(tmpString, SE_FILE_OBJECT,
  1005. (DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION),
  1006. NULL, NULL, pACL, NULL) );
  1007. // Look in the registry to see if this service has already created itself and has
  1008. // a GUID registered.
  1009. tmpString = OLESTR("SYSTEM\\CurrentControlSet\\Services\\");
  1010. WsbAffirmHr(WsbEnsureRegistryKeyExists(NULL, tmpString));
  1011. WsbAffirmHr(tmpString.Append(serviceName));
  1012. WsbAffirmHr(tmpString.Append(OLESTR("\\Parameters")));
  1013. WsbAffirmHr(WsbEnsureRegistryKeyExists(NULL, tmpString));
  1014. WsbAffirmHr(outString.Alloc(256));
  1015. // We also want to put the path where the trce file should go.
  1016. if (WsbGetRegistryValueString(NULL, tmpString, OLESTR("WsbTraceFileName"), outString, 256, &sizeGot) != S_OK) {
  1017. outString = rsPath;
  1018. WsbAffirmHr(outString.Append(OLESTR("\\Trace\\")));
  1019. WsbAffirmHr(outString.Append(traceFile));
  1020. WsbAffirmHr(WsbSetRegistryValueString(NULL, tmpString, OLESTR("WsbTraceFileName"), outString));
  1021. }
  1022. // Try a little to make sure the trace directory exists.
  1023. lastSlash = wcsrchr(outString, L'\\');
  1024. if ((0 != lastSlash) && (lastSlash != outString)) {
  1025. *lastSlash = 0;
  1026. CreateDirectory(outString, 0);
  1027. }
  1028. // Turn tracing on, if requested.
  1029. if (0 != pUnk) {
  1030. WsbAffirmHr(pUnk->QueryInterface(IID_IWsbTrace, (void**) &pTrace));
  1031. WsbAffirmHr(pTrace->SetRegistryEntry(tmpString));
  1032. WsbAffirmHr(pTrace->LoadFromRegistry());
  1033. }
  1034. } WsbCatch(hr);
  1035. // Cleanup security allocations
  1036. if (pSystemSID)
  1037. FreeSid(pSystemSID);
  1038. if (pAdminSID)
  1039. FreeSid(pAdminSID);
  1040. if (pBackupOpSID)
  1041. FreeSid(pBackupOpSID);
  1042. if (pACL)
  1043. LocalFree(pACL);
  1044. return(hr);
  1045. }
  1046. HRESULT
  1047. WsbRegisterEventLogSource(
  1048. IN const WCHAR * LogName,
  1049. IN const WCHAR * SourceName,
  1050. IN DWORD CategoryCount,
  1051. IN const WCHAR * CategoryMsgFile OPTIONAL,
  1052. IN const WCHAR * MsgFiles
  1053. )
  1054. /*++
  1055. Routine Description:
  1056. Registers the given event source in the event log.
  1057. We have to do the event log registration outside the rgs
  1058. files since event log viewer insists on REG_EXPAND_SZ type
  1059. values (which cannot be done via rgs).
  1060. Arguments:
  1061. None.
  1062. Return Value:
  1063. S_OK - Service Registered and everything is set
  1064. --*/
  1065. {
  1066. CWsbStringPtr rpPath;
  1067. HRESULT hr = S_OK;
  1068. try {
  1069. CWsbStringPtr regPath;
  1070. DWORD types = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
  1071. //
  1072. // Everything goes into HKLM\SYSTEM\CurrentControlSet\Services\EventLog\<LogName>\<SourceName>
  1073. //
  1074. regPath.Printf( OLESTR("%ls\\%ls\\%ls"), WSB_LOG_BASE, LogName, SourceName );
  1075. WsbAffirmHr( WsbEnsureRegistryKeyExists( 0, regPath ) );
  1076. //
  1077. // See if we have Categories within this source. Register if so
  1078. //
  1079. if( CategoryCount ) {
  1080. WsbAffirmHr( WsbSetRegistryValueDWORD( 0, regPath, WSB_LOG_CAT_COUNT, CategoryCount ) );
  1081. WsbAffirmHr( WsbSetRegistryValueString( 0, regPath, WSB_LOG_CAT_FILE, CategoryMsgFile, REG_EXPAND_SZ ) );
  1082. }
  1083. //
  1084. // Register the message source and types of events
  1085. //
  1086. WsbAffirmHr( WsbSetRegistryValueString( 0, regPath, WSB_LOG_MESSAGE_FILE, MsgFiles, REG_EXPAND_SZ ) );
  1087. WsbAffirmHr( WsbSetRegistryValueDWORD( 0, regPath, WSB_LOG_TYPES, types ) );
  1088. } WsbCatch( hr );
  1089. return ( hr );
  1090. }
  1091. HRESULT
  1092. WsbUnregisterEventLogSource(
  1093. IN const WCHAR * LogName,
  1094. IN const WCHAR * SourceName
  1095. )
  1096. /*++
  1097. Routine Description:
  1098. Registers the given event source in the event log.
  1099. Arguments:
  1100. None.
  1101. Return Value:
  1102. S_OK - Service Registered and everything is set
  1103. --*/
  1104. {
  1105. CWsbStringPtr rpPath;
  1106. HRESULT hr = S_OK;
  1107. try {
  1108. CWsbStringPtr regPath;
  1109. //
  1110. // Everything goes into HKLM\SYSTEM\CurrentControlSet\Services\EventLog\<LogName>\<SourceName>
  1111. //
  1112. regPath.Printf( OLESTR("%ls\\%ls\\%ls"), WSB_LOG_BASE, LogName, SourceName );
  1113. //
  1114. // Some of these may not exist, so don't check return value
  1115. //
  1116. WsbRemoveRegistryValue( 0, regPath, WSB_LOG_CAT_COUNT );
  1117. WsbRemoveRegistryValue( 0, regPath, WSB_LOG_CAT_FILE );
  1118. WsbRemoveRegistryValue( 0, regPath, WSB_LOG_MESSAGE_FILE );
  1119. WsbRemoveRegistryValue( 0, regPath, WSB_LOG_TYPES );
  1120. regPath.Printf( OLESTR("%ls\\%ls"), WSB_LOG_BASE, LogName );
  1121. WsbAffirmHr( WsbRemoveRegistryKey( 0, regPath, SourceName ) );
  1122. } WsbCatch( hr );
  1123. return ( hr );
  1124. }
  1125. HRESULT
  1126. WsbRegisterRsFilter (
  1127. BOOL bDisplay
  1128. )
  1129. /*++
  1130. Routine Description:
  1131. Registers the RsFilter for use by the system.
  1132. We assume that the filter is already in the system32\driver directory.
  1133. Arguments:
  1134. None.
  1135. Return Value:
  1136. S_OK - Service Registered and everything is set
  1137. ERROR_SERVICE_EXISTS - service already exists
  1138. ERROR_DUP_NAME - The display name already exists in teh SCM as a service name or a display name
  1139. --*/
  1140. {
  1141. CWsbStringPtr rpPath;
  1142. CWsbStringPtr rpDescription;
  1143. SC_HANDLE hService;
  1144. SC_HANDLE hSCM = NULL;
  1145. HRESULT hr = S_OK;
  1146. DWORD rpTag = 0;
  1147. try {
  1148. rpPath.Printf( OLESTR("%%SystemRoot%%\\System32\\drivers\\%ls%ls"), TEXT(RSFILTER_APPNAME), TEXT(RSFILTER_EXTENSION) );
  1149. //
  1150. // First make sure not already installed
  1151. //
  1152. hSCM = OpenSCManager( 0, 0, GENERIC_READ | GENERIC_WRITE );
  1153. WsbAffirmPointer( hSCM );
  1154. //
  1155. // and install it
  1156. //
  1157. hService = CreateService(
  1158. hSCM, // SCManager database
  1159. TEXT(RSFILTER_SERVICENAME), // Service name
  1160. TEXT(RSFILTER_DISPLAYNAME), // Display name
  1161. SERVICE_ALL_ACCESS, // desired access
  1162. SERVICE_FILE_SYSTEM_DRIVER, // service type
  1163. SERVICE_BOOT_START, // start type
  1164. SERVICE_ERROR_NORMAL, // error control type
  1165. rpPath, // Executable location
  1166. TEXT(RSFILTER_GROUP), // group
  1167. &rpTag, // Set tag to zero so we are loaded first in the filter group.
  1168. TEXT(RSFILTER_DEPENDENCIES),
  1169. NULL,
  1170. NULL);
  1171. WsbAffirmStatus( 0 != hService );
  1172. rpDescription.LoadFromRsc(_Module.m_hInst, IDS_WSBSVC_DESC );
  1173. SERVICE_DESCRIPTION svcDesc;
  1174. svcDesc.lpDescription = rpDescription;
  1175. ChangeServiceConfig2( hService, SERVICE_CONFIG_DESCRIPTION, &svcDesc );
  1176. CloseServiceHandle( hService );
  1177. //
  1178. // Add event logging entries
  1179. //
  1180. WsbAffirmHr( WsbRegisterEventLogSource(
  1181. WSB_LOG_SYS, WSB_LOG_FILTER_NAME, 0, 0, TEXT(RSFILTER_FULLPATH) ) );
  1182. //
  1183. // Make sure params Key exists
  1184. //
  1185. CWsbStringPtr regPath;
  1186. regPath.Printf( OLESTR("%ls\\%ls\\Parameters"), WSB_SVC_BASE, TEXT(RSFILTER_SERVICENAME) );
  1187. WsbAffirmHr( WsbEnsureRegistryKeyExists( 0, regPath ) );
  1188. } WsbCatchAndDo( hr,
  1189. // If the caller wants error messages then give a message
  1190. if ( bDisplay ) MessageBox(NULL, WsbHrAsString( hr ), WSB_FACILITY_PLATFORM_NAME, MB_OK);
  1191. );
  1192. if( hSCM ) {
  1193. CloseServiceHandle( hSCM );
  1194. hSCM = NULL;
  1195. }
  1196. return ( hr );
  1197. }
  1198. HRESULT
  1199. WsbUnregisterRsFilter (
  1200. BOOL bDisplay
  1201. )
  1202. /*++
  1203. Routine Description:
  1204. Registers the RsFilter for use by the system.
  1205. Arguments:
  1206. None.
  1207. Return Value:
  1208. S_OK - Service Registered and everything is set
  1209. ERROR_SERVICE_EXISTS - service already exists
  1210. ERROR_DUP_NAME - The display name already exists in teh SCM as a service name or a display name
  1211. --*/
  1212. {
  1213. SC_HANDLE hSCM = NULL;
  1214. SC_HANDLE hService = NULL;
  1215. HRESULT hr = S_OK;
  1216. try {
  1217. //
  1218. // First connect with the Service Control Manager
  1219. //
  1220. hSCM = OpenSCManager( 0, 0, GENERIC_READ | GENERIC_WRITE );
  1221. WsbAffirmPointer( hSCM );
  1222. //
  1223. // Open the service
  1224. //
  1225. hService = OpenService( hSCM, TEXT(RSFILTER_SERVICENAME), SERVICE_ALL_ACCESS );
  1226. //
  1227. // if the handle is NULL then there is a problem and need to call GetLastError to get error code
  1228. //
  1229. WsbAffirmStatus( 0 != hService );
  1230. //
  1231. // Delete the service - if it does not work then return the error
  1232. //
  1233. WsbAffirmStatus( DeleteService( hService ) );
  1234. //
  1235. // Remove the registry values
  1236. //
  1237. WsbAffirmHr( WsbUnregisterEventLogSource( WSB_LOG_SYS, WSB_LOG_FILTER_NAME ) );
  1238. } WsbCatchAndDo( hr,
  1239. // If the caller wants error messages then give a message
  1240. if ( bDisplay ) MessageBox(NULL, WsbHrAsString( hr ), WSB_FACILITY_PLATFORM_NAME, MB_OK);
  1241. );
  1242. if ( hService ){
  1243. CloseServiceHandle( hService );
  1244. hService = NULL;
  1245. }
  1246. if( hSCM ) {
  1247. CloseServiceHandle( hSCM );
  1248. hSCM = NULL;
  1249. }
  1250. return ( hr );
  1251. }
  1252. STDAPI
  1253. DllRegisterRsFilter (
  1254. void
  1255. )
  1256. {
  1257. return( WsbRegisterRsFilter( FALSE ) ) ;
  1258. }
  1259. STDAPI
  1260. DllUnregisterRsFilter (
  1261. void
  1262. )
  1263. {
  1264. return( WsbUnregisterRsFilter( FALSE ) ) ;
  1265. }
  1266. HRESULT
  1267. WsbCheckAccess(
  1268. WSB_ACCESS_TYPE AccessType
  1269. )
  1270. {
  1271. HRESULT hr = S_OK;
  1272. PSID psid = 0;
  1273. HANDLE hToken = NULL;
  1274. try {
  1275. //
  1276. // Set up the SID to check against
  1277. //
  1278. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  1279. switch( AccessType ) {
  1280. case WSB_ACCESS_TYPE_ADMINISTRATOR:
  1281. WsbAffirmStatus(
  1282. AllocateAndInitializeSid(
  1283. &siaNtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
  1284. DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psid ) );
  1285. break;
  1286. case WSB_ACCESS_TYPE_OPERATOR:
  1287. WsbAffirmStatus(
  1288. AllocateAndInitializeSid(
  1289. &siaNtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
  1290. DOMAIN_ALIAS_RID_SYSTEM_OPS, 0, 0, 0, 0, 0, 0, &psid ) );
  1291. break;
  1292. case WSB_ACCESS_TYPE_USER:
  1293. WsbAffirmStatus(
  1294. AllocateAndInitializeSid(
  1295. &siaNtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
  1296. DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &psid ) );
  1297. break;
  1298. case WSB_ACCESS_TYPE_ALL:
  1299. WsbThrow( S_OK );
  1300. break;
  1301. default:
  1302. WsbThrow( E_INVALIDARG );
  1303. }
  1304. //
  1305. // Check for membership
  1306. //
  1307. BOOL pMember = FALSE;
  1308. if (! CheckTokenMembership( 0, psid, &pMember ) ) {
  1309. // Check if this is an impersonation level problem, if so,
  1310. // get the thread impersonation token and try again
  1311. DWORD dwErr1 = GetLastError();
  1312. if (dwErr1 == ERROR_BAD_IMPERSONATION_LEVEL) {
  1313. // Get thread token
  1314. HANDLE hThread = GetCurrentThread(); // No need to call CloseHandle here
  1315. WsbAffirmStatus(OpenThreadToken(hThread, TOKEN_QUERY, TRUE, &hToken));
  1316. WsbAffirmStatus( CheckTokenMembership( hToken, psid, &pMember ) );
  1317. } else {
  1318. // Other error - throw
  1319. WsbAffirmNoError(dwErr1);
  1320. }
  1321. }
  1322. if( !pMember ) {
  1323. WsbThrow( E_ACCESSDENIED );
  1324. }
  1325. } WsbCatch( hr );
  1326. if( psid ) FreeSid( psid );
  1327. if (hToken != NULL)
  1328. CloseHandle(hToken);
  1329. return( hr );
  1330. }
  1331. HRESULT
  1332. CWsbSecurityDescriptor::AllowRid(
  1333. DWORD Rid,
  1334. DWORD dwAccessMask
  1335. )
  1336. {
  1337. HRESULT hr = S_OK;
  1338. PSID pSid = 0;
  1339. PACL newACL = 0;
  1340. try {
  1341. //
  1342. // First, create the SID from Rid
  1343. //
  1344. SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
  1345. WsbAffirmStatus( AllocateAndInitializeSid(
  1346. &sia,
  1347. 2,
  1348. SECURITY_BUILTIN_DOMAIN_RID,
  1349. Rid,
  1350. 0, 0, 0, 0, 0, 0,
  1351. &pSid
  1352. ) );
  1353. //
  1354. // Construct new ACL
  1355. //
  1356. ACL_SIZE_INFORMATION aclSizeInfo;
  1357. int aclSize;
  1358. PACL oldACL;
  1359. aclSizeInfo.AclBytesInUse = 0;
  1360. oldACL = m_pDACL;
  1361. if( oldACL ) {
  1362. WsbAffirmStatus(GetAclInformation( oldACL, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation ));
  1363. }
  1364. aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid( pSid ) - sizeof(DWORD);
  1365. WsbAffirmAlloc( newACL = (PACL)( new BYTE[aclSize] ) );
  1366. WsbAffirmStatus( InitializeAcl( newACL, aclSize, ACL_REVISION ) );
  1367. WsbAffirmHr( CopyACL( newACL, oldACL ) );
  1368. WsbAffirmStatus( AddAccessAllowedAce( newACL, ACL_REVISION2, dwAccessMask, pSid ) );
  1369. //
  1370. // Swap over to new ACL
  1371. //
  1372. m_pDACL = newACL;
  1373. newACL = 0;
  1374. if( oldACL ) {
  1375. delete( oldACL );
  1376. }
  1377. //
  1378. // Update the security descriptor
  1379. //
  1380. WsbAffirmStatus(SetSecurityDescriptorDacl( m_pSD, TRUE, m_pDACL, FALSE ));
  1381. } WsbCatch( hr );
  1382. if( pSid ) FreeSid( pSid );
  1383. if( newACL ) delete( newACL );
  1384. return( hr );
  1385. }
  1386. HRESULT
  1387. WsbGetResourceString(
  1388. ULONG id,
  1389. WCHAR **ppString
  1390. )
  1391. {
  1392. HRESULT hr = S_OK;
  1393. try {
  1394. WsbAssert(ppString != 0, E_INVALIDARG);
  1395. *ppString = NULL;
  1396. // Let our srting class to do the work...
  1397. CWsbStringPtr loader;
  1398. WsbAffirmHr(loader.LoadFromRsc(_Module.m_hInst, id));
  1399. *ppString = *(&loader);
  1400. *(&loader) = NULL;
  1401. } WsbCatch( hr );
  1402. return( hr );
  1403. }