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.

800 lines
18 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All Rights Reserved.
  3. Module Name:
  4. msoobci.c
  5. Abstract:
  6. Exception Pack installer helper DLL
  7. Can be used as a co-installer, or called via setup app, or RunDll32 stub
  8. This DLL is for internal distribution of exception packs to update
  9. OS components.
  10. Author:
  11. Jamie Hunter (jamiehun) 2001-11-27
  12. Revision History:
  13. Jamie Hunter (jamiehun) 2001-11-27
  14. Initial Version
  15. --*/
  16. #include "msoobcip.h"
  17. //
  18. // globals
  19. //
  20. HANDLE g_DllHandle;
  21. OSVERSIONINFOEX g_VerInfo;
  22. VOID
  23. DebugPrint(
  24. IN PCTSTR format,
  25. IN ... OPTIONAL
  26. )
  27. /*++
  28. Routine Description:
  29. Send a formatted string to the debugger.
  30. Arguments:
  31. format - standard printf format string.
  32. Return Value:
  33. NONE.
  34. --*/
  35. {
  36. TCHAR buf[1200]; // wvsprintf maxes at 1024.
  37. va_list arglist;
  38. va_start(arglist, format);
  39. lstrcpy(buf,TEXT("MSOOBCI: "));
  40. wvsprintf(buf+lstrlen(buf), format, arglist);
  41. lstrcat(buf,TEXT("\n"));
  42. OutputDebugString(buf);
  43. }
  44. //
  45. // Called by CRT when _DllMainCRTStartup is the DLL entry point
  46. //
  47. BOOL
  48. WINAPI
  49. DllMain(
  50. IN HANDLE DllHandle,
  51. IN DWORD Reason,
  52. IN LPVOID Reserved
  53. )
  54. {
  55. switch(Reason) {
  56. case DLL_PROCESS_ATTACH:
  57. //
  58. // global initialization
  59. // - make a note of DllHandle
  60. // - make a note of OS version
  61. //
  62. g_DllHandle = DllHandle;
  63. ZeroMemory(&g_VerInfo,sizeof(g_VerInfo));
  64. g_VerInfo.dwOSVersionInfoSize = sizeof(g_VerInfo);
  65. if(!GetVersionEx((LPOSVERSIONINFO)&g_VerInfo)) {
  66. g_VerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  67. if(!GetVersionEx((LPOSVERSIONINFO)&g_VerInfo)) {
  68. return FALSE;
  69. }
  70. }
  71. break;
  72. }
  73. return TRUE;
  74. }
  75. HRESULT
  76. GuidFromString(
  77. IN LPCTSTR GuidString,
  78. OUT GUID *GuidBinary
  79. )
  80. /*++
  81. Routine Description:
  82. Convert a GUID from String form to Binary form
  83. Arguments:
  84. GuidString - string form
  85. GuidBinary - filled with binary form
  86. Return Value:
  87. S_OK or E_INVALIDARG
  88. --*/
  89. {
  90. HRESULT res;
  91. TCHAR String[64];
  92. lstrcpyn(String,GuidString,ARRAY_SIZE(String));
  93. res = IIDFromString(String,GuidBinary);
  94. return res;
  95. }
  96. HRESULT
  97. StringFromGuid(
  98. IN GUID *GuidBinary,
  99. OUT LPTSTR GuidString,
  100. IN DWORD BufferSize
  101. )
  102. /*++
  103. Routine Description:
  104. Convert a GUID from Binary form to String form
  105. Arguments:
  106. GuidBinary - binary form
  107. GuidString - filled with string form
  108. BufferSize - length of GuidString buffer
  109. Return Value:
  110. S_OK or E_INVALIDARG
  111. --*/
  112. {
  113. int res;
  114. res = StringFromGUID2(GuidBinary,GuidString,(int)BufferSize);
  115. if(res == 0) {
  116. return E_INVALIDARG;
  117. }
  118. return S_OK;
  119. }
  120. HRESULT
  121. VersionFromString(
  122. IN LPCTSTR VerString,
  123. OUT INT * VerMajor,
  124. OUT INT * VerMinor,
  125. OUT INT * VerBuild,
  126. OUT INT * VerQFE
  127. )
  128. /*++
  129. Routine Description:
  130. Convert a high.low string to VerHigh and VerLow
  131. Arguments:
  132. VerString - string form
  133. VerMajor/VerMinor/VerBuild/VerQFE - components of version
  134. Return Value:
  135. S_OK or E_INVALIDARG
  136. --*/
  137. {
  138. HRESULT res;
  139. LPTSTR VerPtr;
  140. long val;
  141. *VerMajor = *VerMinor = *VerBuild = *VerQFE = 0;
  142. //
  143. // skip leading white space
  144. //
  145. while((VerString[0] == TEXT(' ')) ||
  146. (VerString[0] == TEXT('\t'))) {
  147. VerString++;
  148. }
  149. if(VerString[0] == TEXT('\0')) {
  150. //
  151. // wildcard
  152. //
  153. return S_FALSE;
  154. }
  155. //
  156. // get version major part (decimal)
  157. //
  158. if(!((VerString[0]>= TEXT('0')) &&
  159. (VerString[0]<= TEXT('9')))) {
  160. return E_INVALIDARG;
  161. }
  162. val = _tcstol(VerString,&VerPtr,10);
  163. if((VerPtr == VerString) ||
  164. ((VerPtr-VerString)>5) ||
  165. (val>65535) ||
  166. (val<0)) {
  167. return E_INVALIDARG;
  168. }
  169. *VerMajor = (WORD)val;
  170. //
  171. // followed by .decimal
  172. // (version minor part)
  173. //
  174. if((VerPtr[0] != TEXT('.')) ||
  175. !((VerPtr[1]>= TEXT('0')) &&
  176. (VerPtr[1]<= TEXT('9')))) {
  177. return E_INVALIDARG;
  178. }
  179. VerString = VerPtr+1;
  180. val = _tcstol(VerString,&VerPtr,10);
  181. if((VerPtr == VerString) ||
  182. ((VerPtr-VerString)>5) ||
  183. (val>65535) ||
  184. (val<0)) {
  185. return E_INVALIDARG;
  186. }
  187. *VerMinor = (WORD)val;
  188. //
  189. // followed by .decimal
  190. // (version build, optional)
  191. //
  192. if(VerPtr[0] == TEXT('.')) {
  193. if(!((VerPtr[1]>= TEXT('0')) &&
  194. (VerPtr[1]<= TEXT('9')))) {
  195. return E_INVALIDARG;
  196. }
  197. VerString = VerPtr+1;
  198. val = _tcstol(VerString,&VerPtr,10);
  199. if((VerPtr == VerString) ||
  200. ((VerPtr-VerString)>5) ||
  201. (val>65535) ||
  202. (val<0)) {
  203. return E_INVALIDARG;
  204. }
  205. *VerBuild = (WORD)val;
  206. }
  207. //
  208. // followed by .decimal
  209. // (version qfe, optional)
  210. //
  211. if(VerPtr[0] == TEXT('.')) {
  212. if(!((VerPtr[1]>= TEXT('0')) &&
  213. (VerPtr[1]<= TEXT('9')))) {
  214. return E_INVALIDARG;
  215. }
  216. VerString = VerPtr+1;
  217. val = _tcstol(VerString,&VerPtr,10);
  218. if((VerPtr == VerString) ||
  219. ((VerPtr-VerString)>5) ||
  220. (val>65535) ||
  221. (val<0)) {
  222. return E_INVALIDARG;
  223. }
  224. *VerQFE = (WORD)val;
  225. }
  226. //
  227. // trailing white space
  228. //
  229. VerString = VerPtr;
  230. while((VerString[0] == TEXT(' ')) ||
  231. (VerString[0] == TEXT('\t'))) {
  232. VerString++;
  233. }
  234. //
  235. // not well formed?
  236. //
  237. if(VerString[0] != TEXT('\0')) {
  238. return E_INVALIDARG;
  239. }
  240. return S_OK;
  241. }
  242. int
  243. CompareCompVersion(
  244. IN INT VerMajor,
  245. IN INT VerMinor,
  246. IN INT VerBuild,
  247. IN INT VerQFE,
  248. IN PSETUP_OS_COMPONENT_DATA SetupOsComponentData
  249. )
  250. /*++
  251. Routine Description:
  252. Compare a version against component information
  253. Arguments:
  254. VerMajor/VerMinor/VerBuild/VerQFE - version to check against
  255. (can have wildcards)
  256. SetupOsComponentData - component version
  257. Return Value:
  258. -1, version not as good as component
  259. 0, version equiv to component
  260. 1, version better than component
  261. --*/
  262. {
  263. return CompareVersion(VerMajor,
  264. VerMinor,
  265. VerBuild,
  266. VerQFE,
  267. SetupOsComponentData->VersionMajor,
  268. SetupOsComponentData->VersionMinor,
  269. SetupOsComponentData->BuildNumber,
  270. SetupOsComponentData->QFENumber
  271. );
  272. }
  273. int
  274. CompareVersion(
  275. IN INT VerMajor,
  276. IN INT VerMinor,
  277. IN INT VerBuild,
  278. IN INT VerQFE,
  279. IN INT OtherMajor,
  280. IN INT OtherMinor,
  281. IN INT OtherBuild,
  282. IN INT OtherQFE
  283. )
  284. /*++
  285. Routine Description:
  286. Compare a version against component information
  287. Arguments:
  288. VerMajor/VerMinor/VerBuild/VerQFE - version to check
  289. (can have wildcards)
  290. OtherMajor/OtherMinor/OtherBuid/OtherQFE - version to check against
  291. Return Value:
  292. -1, version not as good as component
  293. 0, version equiv to component
  294. 1, version better than component
  295. --*/
  296. {
  297. if((VerMajor==-1)||(OtherMajor==-1)) {
  298. return 0;
  299. }
  300. if(VerMajor<OtherMajor) {
  301. return -1;
  302. }
  303. if(VerMajor>OtherMajor) {
  304. return 1;
  305. }
  306. if((VerMinor==-1)||(OtherMinor==-1)) {
  307. return 0;
  308. }
  309. if(VerMinor<OtherMinor) {
  310. return -1;
  311. }
  312. if(VerMinor>OtherMinor) {
  313. return 1;
  314. }
  315. if((VerBuild==-1)||(OtherBuild==-1)) {
  316. return 0;
  317. }
  318. if(VerBuild<OtherBuild) {
  319. return -1;
  320. }
  321. if(VerBuild>OtherBuild) {
  322. return 1;
  323. }
  324. if((VerQFE==-1)||(OtherQFE==-1)) {
  325. return 0;
  326. }
  327. if(VerQFE<OtherQFE) {
  328. return -1;
  329. }
  330. if(VerQFE>OtherQFE) {
  331. return 1;
  332. }
  333. return 0;
  334. }
  335. HRESULT
  336. MakeSurePathExists(
  337. IN LPTSTR Path
  338. )
  339. /*++
  340. Routine Description:
  341. Make sure named directory exists
  342. Arguments:
  343. Path - path to directory to create, must be a writable buffer
  344. Return Value:
  345. status as hresult
  346. S_OK - path created
  347. S_FALSE - path already exists
  348. --*/
  349. {
  350. DWORD dwResult;
  351. DWORD Status;
  352. HRESULT hrStatus;
  353. dwResult = GetFileAttributes(Path);
  354. if((dwResult != (DWORD)(-1)) && ((dwResult & FILE_ATTRIBUTE_DIRECTORY)!=0)) {
  355. //
  356. // directory exists
  357. //
  358. return S_FALSE;
  359. }
  360. hrStatus = MakeSureParentPathExists(Path);
  361. if(!SUCCEEDED(hrStatus)) {
  362. return hrStatus;
  363. }
  364. if(!CreateDirectory(Path,NULL)) {
  365. Status = GetLastError();
  366. return HRESULT_FROM_WIN32(Status);
  367. }
  368. return S_OK;
  369. }
  370. HRESULT
  371. MakeSureParentPathExists(
  372. IN LPTSTR Path
  373. )
  374. /*++
  375. Routine Description:
  376. Make sure parent of named directory/file exists
  377. Arguments:
  378. Path - path to directory to create, must be a writable buffer
  379. Return Value:
  380. status as hresult
  381. S_OK - path created
  382. S_FALSE - path already exists
  383. --*/
  384. {
  385. HRESULT hrStatus;
  386. LPTSTR Split;
  387. LPTSTR Base;
  388. TCHAR Save;
  389. //
  390. // make sure we don't try to create the root
  391. //
  392. if((_istalpha(Path[0]) && (Path[1]==TEXT(':')))
  393. && ((Path[2] == TEXT('\\')) || (Path[2] == TEXT('/')))
  394. && (Path[3] != TEXT('\0'))) {
  395. Base = Path+3;
  396. } else {
  397. //
  398. // at this time, this code expects X:\... format
  399. //
  400. return E_FAIL;
  401. }
  402. Split = GetSplit(Base);
  403. if(Split == Base) {
  404. //
  405. // strange, should have succeeded
  406. //
  407. return E_FAIL;
  408. }
  409. Save = *Split;
  410. *Split = TEXT('\0');
  411. hrStatus = MakeSurePathExists(Path);
  412. *Split = Save;
  413. return hrStatus;
  414. }
  415. LPTSTR GetBaseName(
  416. IN LPCTSTR FileName
  417. )
  418. /*++
  419. Routine Description:
  420. Given a full path, return basename portion
  421. Arguments:
  422. FileName - full or partial path
  423. Return Value:
  424. status as hresult
  425. --*/
  426. {
  427. LPTSTR BaseName = (LPTSTR)FileName;
  428. for(; *FileName; FileName = CharNext(FileName)) {
  429. switch (*FileName) {
  430. case TEXT(':'):
  431. case TEXT('/'):
  432. case TEXT('\\'):
  433. BaseName = (LPTSTR)CharNext(FileName);
  434. break;
  435. }
  436. }
  437. return BaseName;
  438. }
  439. LPTSTR GetSplit(
  440. IN LPCTSTR FileName
  441. )
  442. /*++
  443. Routine Description:
  444. Split path at last '/' or '\\' (similar to GetBaseName)
  445. Arguments:
  446. FileName - full or partial path
  447. Return Value:
  448. status as hresult
  449. --*/
  450. {
  451. LPTSTR SplitPos = (LPTSTR)FileName;
  452. for(SplitPos; *FileName; FileName = CharNext(FileName)) {
  453. switch (*FileName) {
  454. case TEXT('/'):
  455. case TEXT('\\'):
  456. SplitPos = (LPTSTR)FileName;
  457. break;
  458. }
  459. }
  460. return SplitPos;
  461. }
  462. BOOL
  463. WINAPI
  464. IsInteractiveWindowStation(
  465. )
  466. /*++
  467. Routine Description:
  468. Determine if we are running on an interactive station vs non-interactive
  469. // station (i.e., service)
  470. Arguments:
  471. none
  472. Return Value:
  473. True if interactive
  474. --*/
  475. {
  476. HWINSTA winsta;
  477. USEROBJECTFLAGS flags;
  478. BOOL interactive = TRUE; // true unless we determine otherwise
  479. DWORD lenNeeded;
  480. winsta = GetProcessWindowStation();
  481. if(!winsta) {
  482. return interactive;
  483. }
  484. if(GetUserObjectInformation(winsta,UOI_FLAGS,&flags,sizeof(flags),&lenNeeded)) {
  485. interactive = (flags.dwFlags & WSF_VISIBLE) ? TRUE : FALSE;
  486. }
  487. //
  488. // don't call CLoseWindowStation
  489. //
  490. return interactive;
  491. }
  492. BOOL
  493. WINAPI
  494. IsUserAdmin(
  495. VOID
  496. )
  497. /*++
  498. Routine Description:
  499. This routine returns TRUE if the caller's process has admin privs
  500. Caller is NOT expected to be impersonating anyone and IS
  501. expected to be able to open their own process and process
  502. token.
  503. Though we could use CheckTokenMembership
  504. this function has to work on NT4
  505. Arguments:
  506. None.
  507. Return Value:
  508. TRUE - Caller has Administrator privs.
  509. FALSE - Caller does not have Administrator privs.
  510. --*/
  511. {
  512. BOOL fAdmin = FALSE;
  513. HANDLE hToken = NULL;
  514. DWORD dwStatus;
  515. DWORD dwACLSize;
  516. DWORD cbps = sizeof(PRIVILEGE_SET);
  517. PACL pACL = NULL;
  518. PSID psidAdmin = NULL;
  519. PSECURITY_DESCRIPTOR psdAdmin = NULL;
  520. PRIVILEGE_SET ps;
  521. GENERIC_MAPPING gm;
  522. SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
  523. BOOL Impersonated = FALSE;
  524. //
  525. // Prepare some memory
  526. //
  527. ZeroMemory(&ps, sizeof(ps));
  528. ZeroMemory(&gm, sizeof(gm));
  529. //
  530. // Get the Administrators SID
  531. //
  532. if (AllocateAndInitializeSid(&sia, 2,
  533. SECURITY_BUILTIN_DOMAIN_RID,
  534. DOMAIN_ALIAS_RID_ADMINS,
  535. 0, 0, 0, 0, 0, 0, &psidAdmin) ) {
  536. //
  537. // Get the Asministrators Security Descriptor (SD)
  538. //
  539. psdAdmin = malloc(SECURITY_DESCRIPTOR_MIN_LENGTH);
  540. if (psdAdmin) {
  541. if(InitializeSecurityDescriptor(psdAdmin,SECURITY_DESCRIPTOR_REVISION)) {
  542. //
  543. // Compute size needed for the ACL then allocate the
  544. // memory for it
  545. //
  546. dwACLSize = sizeof(ACCESS_ALLOWED_ACE) + 8 +
  547. GetLengthSid(psidAdmin) - sizeof(DWORD);
  548. pACL = (PACL)malloc(dwACLSize);
  549. if(pACL) {
  550. //
  551. // Initialize the new ACL
  552. //
  553. if(InitializeAcl(pACL, dwACLSize, ACL_REVISION2)) {
  554. //
  555. // Add the access-allowed ACE to the DACL
  556. //
  557. if(AddAccessAllowedAce(pACL,ACL_REVISION2,
  558. (ACCESS_READ | ACCESS_WRITE),psidAdmin)) {
  559. //
  560. // Set our DACL to the Administrator's SD
  561. //
  562. if (SetSecurityDescriptorDacl(psdAdmin, TRUE, pACL, FALSE)) {
  563. //
  564. // AccessCheck is downright picky about what is in the SD,
  565. // so set the group and owner
  566. //
  567. SetSecurityDescriptorGroup(psdAdmin,psidAdmin,FALSE);
  568. SetSecurityDescriptorOwner(psdAdmin,psidAdmin,FALSE);
  569. //
  570. // Initialize GenericMapping structure even though we
  571. // won't be using generic rights
  572. //
  573. gm.GenericRead = ACCESS_READ;
  574. gm.GenericWrite = ACCESS_WRITE;
  575. gm.GenericExecute = 0;
  576. gm.GenericAll = ACCESS_READ | ACCESS_WRITE;
  577. //
  578. // AccessCheck requires an impersonation token, so lets
  579. // indulge it
  580. //
  581. Impersonated = ImpersonateSelf(SecurityImpersonation);
  582. if (OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken)) {
  583. if (!AccessCheck(psdAdmin, hToken, ACCESS_READ, &gm,
  584. &ps,&cbps,&dwStatus,&fAdmin)) {
  585. fAdmin = FALSE;
  586. }
  587. CloseHandle(hToken);
  588. }
  589. }
  590. }
  591. }
  592. free(pACL);
  593. }
  594. }
  595. free(psdAdmin);
  596. }
  597. FreeSid(psidAdmin);
  598. }
  599. if(Impersonated) {
  600. RevertToSelf();
  601. }
  602. return(fAdmin);
  603. }
  604. HRESULT
  605. ConcatPath(
  606. IN LPTSTR Path,
  607. IN DWORD Len,
  608. IN LPCTSTR NewPart
  609. )
  610. /*++
  611. Routine Description:
  612. Concat NewPart onto Path
  613. Arguments:
  614. Path - existing path
  615. Len - length of buffer
  616. NewPart - part to append
  617. Return Value:
  618. status as hresult
  619. --*/
  620. {
  621. LPTSTR end = Path+lstrlen(Path);
  622. TCHAR c;
  623. BOOL add_slash = FALSE;
  624. BOOL pre_slash = FALSE;
  625. c = *CharPrev(Path,end);
  626. if((c!= TEXT('\\')) && (c!= TEXT('/'))) {
  627. add_slash = TRUE;
  628. }
  629. if(NewPart) {
  630. c = NewPart[0];
  631. if((c== TEXT('\\')) || (c== TEXT('/'))) {
  632. if(add_slash) {
  633. add_slash = FALSE;
  634. } else {
  635. NewPart = CharNext(NewPart);
  636. }
  637. }
  638. }
  639. if((DWORD)((end-Path)+lstrlen(NewPart)+(add_slash?1:0)) >= Len) {
  640. return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  641. }
  642. if(add_slash) {
  643. end[0] = TEXT('\\');
  644. end++;
  645. }
  646. if(NewPart) {
  647. lstrcpy(end,NewPart);
  648. } else {
  649. end[0] = TEXT('\0');
  650. }
  651. return S_OK;
  652. }