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.

3031 lines
101 KiB

  1. #include "stdafx.h"
  2. #include <setupapi.h>
  3. #include <shlobj.h>
  4. #include <ole2.h>
  5. #include "lzexpand.h"
  6. #include "log.h"
  7. #include "dcomperm.h"
  8. #include "strfn.h"
  9. #include "other.h"
  10. #include <direct.h>
  11. #include <aclapi.h>
  12. typedef struct _QUEUECONTEXT {
  13. HWND OwnerWindow;
  14. DWORD MainThreadId;
  15. HWND ProgressDialog;
  16. HWND ProgressBar;
  17. BOOL Cancelled;
  18. PTSTR CurrentSourceName;
  19. BOOL ScreenReader;
  20. BOOL MessageBoxUp;
  21. WPARAM PendingUiType;
  22. PVOID PendingUiParameters;
  23. UINT CancelReturnCode;
  24. BOOL DialogKilled;
  25. //
  26. // If the SetupInitDefaultQueueCallbackEx is used, the caller can
  27. // specify an alternate handler for progress. This is useful to
  28. // get the default behavior for disk prompting, error handling, etc,
  29. // but to provide a gas gauge embedded, say, in a wizard page.
  30. //
  31. // The alternate window is sent ProgressMsg once when the copy queue
  32. // is started (wParam = 0. lParam = number of files to copy).
  33. // It is then also sent once per file copied (wParam = 1. lParam = 0).
  34. //
  35. // NOTE: a silent installation (i.e., no progress UI) can be accomplished
  36. // by specifying an AlternateProgressWindow handle of INVALID_HANDLE_VALUE.
  37. //
  38. HWND AlternateProgressWindow;
  39. UINT ProgressMsg;
  40. UINT NoToAllMask;
  41. HANDLE UiThreadHandle;
  42. #ifdef NOCANCEL_SUPPORT
  43. BOOL AllowCancel;
  44. #endif
  45. } QUEUECONTEXT, *PQUEUECONTEXT;
  46. //-------------------------------------------------------------------
  47. // purpose: install an section in an .inf file
  48. //-------------------------------------------------------------------
  49. int InstallInfSection_NoFiles(HINF InfHandle,TCHAR szINFFileName[],TCHAR szSectionName[])
  50. {
  51. HWND Window = NULL;
  52. BOOL bReturn = FALSE;
  53. BOOL bReturnTemp = FALSE; // assume failure.
  54. TCHAR ActualSection[1000];
  55. DWORD ActualSectionLength;
  56. BOOL bPleaseCloseInfHandle = FALSE;
  57. iisDebugOut_Start1(_T("InstallInfSection_NoFiles"),szSectionName,LOG_TYPE_PROGRAM_FLOW);
  58. __try {
  59. // Check if a valid infhandle as passed in....
  60. // if so, use that, otherwise, use the passed in filename...
  61. if(InfHandle == INVALID_HANDLE_VALUE)
  62. {
  63. // Try to use the filename.
  64. if (_tcsicmp(szINFFileName, _T("")) == 0)
  65. {
  66. goto c1;
  67. }
  68. // we have a filename entry. let's try to use it.
  69. // Check if the file exists
  70. if (!IsFileExist(szINFFileName))
  71. {
  72. //MessageBox(NULL, "unable to find file", "cannot find file", MB_OK);
  73. goto c1;
  74. }
  75. // Load the inf file and get the handle
  76. InfHandle = SetupOpenInfFile(szINFFileName, NULL, INF_STYLE_WIN4, NULL);
  77. bPleaseCloseInfHandle = TRUE;
  78. }
  79. if(InfHandle == INVALID_HANDLE_VALUE) {goto c1;}
  80. //
  81. // See if there is an nt-specific section
  82. //
  83. SetupDiGetActualSectionToInstall(InfHandle,szSectionName,ActualSection,sizeof(ActualSection)/sizeof(TCHAR),&ActualSectionLength,NULL);
  84. //
  85. // Perform non-file operations for the section passed on the cmd line.
  86. //
  87. bReturn = SetupInstallFromInfSection(Window,InfHandle,ActualSection,SPINST_ALL & ~SPINST_FILES,NULL,NULL,0,NULL,NULL,NULL,NULL);
  88. if(!bReturn) {goto c1;}
  89. //
  90. // Install any services for the section
  91. //
  92. bReturn = SetupInstallServicesFromInfSection(InfHandle,ActualSection,0);
  93. if(!bReturn)
  94. {
  95. iisDebugOut((LOG_TYPE_TRACE, _T("SetupInstallServicesFromInfSection failed.Ret=%d.\n"), GetLastError()));
  96. }
  97. //
  98. // Refresh the desktop.
  99. //
  100. SHChangeNotify(SHCNE_ASSOCCHANGED,SHCNF_FLUSHNOWAIT,0,0);
  101. //
  102. // If we get to here, then this routine has been successful.
  103. //
  104. bReturnTemp = TRUE;
  105. c1:
  106. //
  107. // If the bReturnTemp failed and it was because the user cancelled, then we don't want to consider
  108. // that as an bReturnTemp (i.e., we don't want to give an bReturnTemp popup later).
  109. //
  110. if((bReturnTemp != TRUE) && (GetLastError() == ERROR_CANCELLED)) {bReturnTemp = TRUE;}
  111. if (bPleaseCloseInfHandle == TRUE)
  112. {
  113. if(InfHandle != INVALID_HANDLE_VALUE) {SetupCloseInfFile(InfHandle);InfHandle = INVALID_HANDLE_VALUE;}
  114. }
  115. ;}
  116. __except(EXCEPTION_EXECUTE_HANDLER)
  117. {
  118. if (bPleaseCloseInfHandle == TRUE)
  119. {
  120. if(InfHandle != INVALID_HANDLE_VALUE) {SetupCloseInfFile(InfHandle);InfHandle = INVALID_HANDLE_VALUE;}
  121. }
  122. }
  123. //
  124. // If the bReturnTemp failed because the user cancelled, then we don't want to consider
  125. // that as an bReturnTemp (i.e., we don't want to give an bReturnTemp popup later).
  126. //
  127. if((bReturnTemp != TRUE) && (GetLastError() == ERROR_CANCELLED)) {bReturnTemp = TRUE;}
  128. // Display installation failed message
  129. //if(bReturnTemp) {MyMessageBox(NULL, _T("IDS_INF_FAILED"), MB_OK);}
  130. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("InstallInfSection_NoFiles.[%s].End.Ret=%d.\n"), szSectionName, bReturnTemp));
  131. return bReturnTemp;
  132. }
  133. //-------------------------------------------------------------------
  134. // purpose: install an section in an .inf file
  135. //-------------------------------------------------------------------
  136. int InstallInfSection(HINF InfHandle,TCHAR szINFFileName[],TCHAR szSectionName[])
  137. {
  138. HWND Window = NULL;
  139. PTSTR SourcePath = NULL;
  140. //HINF InfHandle = INVALID_HANDLE_VALUE;
  141. HSPFILEQ FileQueue = INVALID_HANDLE_VALUE;
  142. PQUEUECONTEXT QueueContext = NULL;
  143. BOOL bReturn = FALSE;
  144. BOOL bReturnTemp = FALSE; // assume failure.
  145. TCHAR ActualSection[1000];
  146. DWORD ActualSectionLength;
  147. BOOL bPleaseCloseInfHandle = FALSE;
  148. iisDebugOut_Start1(_T("InstallInfSection"),szSectionName,LOG_TYPE_PROGRAM_FLOW);
  149. __try {
  150. // Check if a valid infhandle as passed in....
  151. // if so, use that, otherwise, use the passed in filename...
  152. if(InfHandle == INVALID_HANDLE_VALUE)
  153. {
  154. // Try to use the filename.
  155. if (_tcsicmp(szINFFileName, _T("")) == 0)
  156. {
  157. goto c1;
  158. }
  159. // we have a filename entry. let's try to use it.
  160. // Check if the file exists
  161. if (!IsFileExist(szINFFileName))
  162. {
  163. //MessageBox(NULL, "unable to find file", "cannot find file", MB_OK);
  164. goto c1;
  165. }
  166. // Load the inf file and get the handle
  167. InfHandle = SetupOpenInfFile(szINFFileName, NULL, INF_STYLE_WIN4, NULL);
  168. bPleaseCloseInfHandle = TRUE;
  169. }
  170. if(InfHandle == INVALID_HANDLE_VALUE) {goto c1;}
  171. //
  172. // See if there is an nt-specific section
  173. //
  174. SetupDiGetActualSectionToInstall(InfHandle,szSectionName,ActualSection,sizeof(ActualSection)/sizeof(TCHAR),&ActualSectionLength,NULL);
  175. //
  176. // Create a setup file queue and initialize the default queue callback.
  177. //
  178. FileQueue = SetupOpenFileQueue();
  179. if(FileQueue == INVALID_HANDLE_VALUE) {goto c1;}
  180. //QueueContext = SetupInitDefaultQueueCallback(Window);
  181. //if(!QueueContext) {goto c1;}
  182. QueueContext = (PQUEUECONTEXT) SetupInitDefaultQueueCallbackEx(Window,NULL,0,0,0);
  183. if(!QueueContext) {goto c1;}
  184. QueueContext->PendingUiType = IDF_CHECKFIRST;
  185. //
  186. // Enqueue file operations for the section passed on the cmd line.
  187. //
  188. //SourcePath = NULL;
  189. // SP_COPY_NOPRUNE = setupapi has a new deal which will prune files from the copyqueue if they already exist on the system.
  190. // however, the problem with the new deal is that the pruning code does not check if you have the same file
  191. // queued in the delete or rename queue. specify SP_COPY_NOPRUNE to make sure that our file never gets
  192. // pruned (removed) from the copy queue. aaronl 12/4/98
  193. //bReturn = SetupInstallFilesFromInfSection(InfHandle,NULL,FileQueue,ActualSection,SourcePath,SP_COPY_NEWER | SP_COPY_NOPRUNE);
  194. bReturn = SetupInstallFilesFromInfSection(InfHandle,NULL,FileQueue,ActualSection,SourcePath, SP_COPY_NOPRUNE);
  195. if(!bReturn) {goto c1;}
  196. //
  197. // Commit file queue.
  198. //
  199. if(!SetupCommitFileQueue(Window, FileQueue, SetupDefaultQueueCallback, QueueContext)) {goto c1;}
  200. //
  201. // Perform non-file operations for the section passed on the cmd line.
  202. //
  203. bReturn = SetupInstallFromInfSection(Window,InfHandle,ActualSection,SPINST_ALL & ~SPINST_FILES,NULL,NULL,0,NULL,NULL,NULL,NULL);
  204. if(!bReturn) {goto c1;}
  205. //
  206. // Refresh the desktop.
  207. //
  208. SHChangeNotify(SHCNE_ASSOCCHANGED,SHCNF_FLUSHNOWAIT,0,0);
  209. //
  210. // If we get to here, then this routine has been successful.
  211. //
  212. bReturnTemp = TRUE;
  213. c1:
  214. //
  215. // If the bReturnTemp failed and it was because the user cancelled, then we don't want to consider
  216. // that as an bReturnTemp (i.e., we don't want to give an bReturnTemp popup later).
  217. //
  218. if((bReturnTemp != TRUE) && (GetLastError() == ERROR_CANCELLED)) {bReturnTemp = TRUE;}
  219. if(QueueContext) {SetupTermDefaultQueueCallback(QueueContext);QueueContext = NULL;}
  220. if(FileQueue != INVALID_HANDLE_VALUE) {SetupCloseFileQueue(FileQueue);FileQueue = INVALID_HANDLE_VALUE;}
  221. if (bPleaseCloseInfHandle == TRUE)
  222. {
  223. if(InfHandle != INVALID_HANDLE_VALUE) {SetupCloseInfFile(InfHandle);InfHandle = INVALID_HANDLE_VALUE;}
  224. }
  225. ;}
  226. __except(EXCEPTION_EXECUTE_HANDLER)
  227. {
  228. if(QueueContext) {SetupTermDefaultQueueCallback(QueueContext);}
  229. if(FileQueue != INVALID_HANDLE_VALUE) {SetupCloseFileQueue(FileQueue);}
  230. if (bPleaseCloseInfHandle == TRUE)
  231. {
  232. if(InfHandle != INVALID_HANDLE_VALUE) {SetupCloseInfFile(InfHandle);InfHandle = INVALID_HANDLE_VALUE;}
  233. }
  234. }
  235. //
  236. // If the bReturnTemp failed because the user cancelled, then we don't want to consider
  237. // that as an bReturnTemp (i.e., we don't want to give an bReturnTemp popup later).
  238. //
  239. if((bReturnTemp != TRUE) && (GetLastError() == ERROR_CANCELLED)) {bReturnTemp = TRUE;}
  240. // Display installation failed message
  241. //if(bReturnTemp) {MyMessageBox(NULL, _T("IDS_INF_FAILED"), MB_OK);}
  242. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("InstallInfSection.[%s].End.Ret=%d.\n"), szSectionName, bReturnTemp));
  243. return bReturnTemp;
  244. }
  245. BOOL IsValidDriveType(LPTSTR szRoot)
  246. {
  247. BOOL fReturn = FALSE;
  248. int i;
  249. i = GetDriveType(szRoot);
  250. if (i == DRIVE_FIXED) {fReturn = TRUE;}
  251. if (i == DRIVE_REMOVABLE)
  252. {
  253. BOOL b;
  254. ULONGLONG TotalSpace;
  255. DWORD SectorsPerCluster, BytesPerSector, NumberOfFreeClusters, TotalNumberOfClusters;
  256. DWORD FloppySpace = 10 * 1024 * 1024;// use 10MB to distinguish a floppy from other drives, like JAZ drive 1GB
  257. b = GetDiskFreeSpace(szRoot,&SectorsPerCluster, &BytesPerSector, &NumberOfFreeClusters, &TotalNumberOfClusters);
  258. if (b)
  259. {
  260. TotalSpace = (ULONGLONG) TotalNumberOfClusters * SectorsPerCluster * BytesPerSector;
  261. if (TotalSpace > (ULONGLONG) FloppySpace)
  262. {fReturn = TRUE;}
  263. else
  264. {
  265. iisDebugOutSafeParams((LOG_TYPE_ERROR, _T("GetDiskFreeSpace():Drive=DRIVE_REMOVABLE:Not Sufficient space on drive '%1!s!'. FAIL\n"), szRoot));
  266. }
  267. }
  268. else
  269. {
  270. iisDebugOutSafeParams((LOG_TYPE_ERROR, _T("GetDiskFreeSpace(Drive=DRIVE_REMOVABLE) on %1!s! returns err: 0x%2!x!. FAILURE\n"), szRoot, GetLastError()));
  271. }
  272. }
  273. return (fReturn);
  274. }
  275. // If lpszPath is a valid directory, return TRUE, and pass back the valid path in lpszPath to caller
  276. // Otherwise, return FALSE.
  277. BOOL IsValidDirectoryName(LPTSTR lpszPath)
  278. {
  279. DWORD err = 0;
  280. BOOL bReturn = FALSE;
  281. TCHAR szFullPath[_MAX_PATH];
  282. LPTSTR p;
  283. iisDebugOutSafeParams((LOG_TYPE_TRACE_WIN32_API, _T("IsValidDirectoryName %1!s!\n"), lpszPath));
  284. err = GetFullPathName(lpszPath, _MAX_PATH, szFullPath, &p);
  285. if (err != 0)
  286. {
  287. if (szFullPath[1] == _T(':')) { // good, not a UNC name
  288. // make sure it is a FIXED drive
  289. TCHAR szRoot[4];
  290. _tcsncpy(szRoot, szFullPath, 3);
  291. szRoot[3] = _T('\0');
  292. if (IsValidDriveType(szRoot))
  293. {
  294. // OK, ready to create each layered directory
  295. TCHAR szBuffer[_MAX_PATH];
  296. LPTSTR token, tail;
  297. CStringArray aDir;
  298. int i, n;
  299. tail = szBuffer;
  300. token = _tcstok(szFullPath, _T("\\"));
  301. if (token)
  302. {
  303. _tcscpy(tail, token);
  304. tail += _tcslen(token);
  305. bReturn = TRUE; /* return TRUE if in the form of C:\ */
  306. while ( ( token = _tcstok(NULL, _T("\\")) ) != NULL )
  307. {
  308. *tail = _T('\\');
  309. tail = _tcsinc(tail);
  310. _tcscpy(tail, token);
  311. // create it & rememeber it
  312. err = GetFileAttributes(szBuffer);
  313. if (err == 0xFFFFFFFF)
  314. {
  315. // szBuffer contains a non-existing path
  316. // create it
  317. if (CreateDirectory(szBuffer, NULL))
  318. {
  319. // succeed, remember the directory in an array
  320. aDir.Add(szBuffer);
  321. }
  322. else
  323. {
  324. iisDebugOutSafeParams((LOG_TYPE_ERROR, _T("IsValidDirectory:CreateDirectory failed on %1!s!, err=%2!x!.\n"), szBuffer, GetLastError()));
  325. bReturn = FALSE;
  326. break;
  327. }
  328. } else {
  329. // szBuffer contains an existing path,
  330. // make sure it is a directory
  331. if (!(err & FILE_ATTRIBUTE_DIRECTORY))
  332. {
  333. iisDebugOutSafeParams((LOG_TYPE_ERROR, _T("IsValidDirectory failure. %1!s! is not a valid directory.\n"), szBuffer));
  334. bReturn = FALSE;
  335. break;
  336. }
  337. }
  338. tail += _tcslen(token);
  339. }
  340. if (bReturn)
  341. {
  342. // pass the valid directory to the caller
  343. if (*(tail-1) == _T(':'))
  344. {
  345. *tail = _T('\\');
  346. tail = _tcsinc(tail);
  347. }
  348. _tcscpy(lpszPath, szBuffer);
  349. }
  350. }
  351. // remove the created directories we remembered in the array
  352. n = (int)aDir.GetSize();
  353. for (i = n-1; i >= 0; i--)
  354. RemoveDirectory(aDir[i]);
  355. } else {
  356. iisDebugOutSafeParams((LOG_TYPE_ERROR, _T("IsValidDirectory failure. %1!s! is not on a valid drive.\n"), szFullPath));
  357. }
  358. } else {
  359. iisDebugOutSafeParams((LOG_TYPE_ERROR, _T("IsValidDirectory failure. UNC name %1!s! is not allowed.\n"), szFullPath));
  360. }
  361. } else {
  362. iisDebugOutSafeParams((LOG_TYPE_ERROR, _T("IsValidDirectory:GetFullPathName failed on %1!s!, err=%2!x!.\n"), lpszPath, GetLastError()));
  363. }
  364. return (bReturn);
  365. }
  366. BOOL IsValidNumber(LPCTSTR szValue)
  367. {
  368. LPTSTR p = (LPTSTR)szValue;
  369. while (*p)
  370. {
  371. if ( *p >= _T('0') && *p <= _T('9') )
  372. {
  373. p = _tcsinc(p);
  374. continue;
  375. } else
  376. return FALSE;
  377. }
  378. return TRUE;
  379. }
  380. // Calculate the size of a Multi-String in TCHAR, including the ending 2 '\0's.
  381. int GetMultiStrSize(LPTSTR p)
  382. {
  383. int c = 0;
  384. while (1) {
  385. if (*p) {
  386. p++;
  387. c++;
  388. } else {
  389. c++;
  390. if (*(p+1)) {
  391. p++;
  392. } else {
  393. c++;
  394. break;
  395. }
  396. }
  397. }
  398. return c;
  399. }
  400. BOOL IsFileExist(LPCTSTR szFile)
  401. {
  402. // Check if the file has expandable Environment strings
  403. LPTSTR pch = NULL;
  404. pch = _tcschr( (LPTSTR) szFile, _T('%'));
  405. if (pch)
  406. {
  407. TCHAR szValue[_MAX_PATH];
  408. _tcscpy(szValue,szFile);
  409. if (!ExpandEnvironmentStrings( (LPCTSTR)szFile, szValue, sizeof(szValue)/sizeof(TCHAR)))
  410. {_tcscpy(szValue,szFile);}
  411. return (GetFileAttributes(szValue) != 0xFFFFFFFF);
  412. }
  413. else
  414. {
  415. return (GetFileAttributes(szFile) != 0xFFFFFFFF);
  416. }
  417. }
  418. void InetGetFilePath(LPCTSTR szFile, LPTSTR szPath)
  419. {
  420. // if UNC name \\computer\share\local1\local2
  421. if (*szFile == _T('\\') && *(_tcsinc(szFile)) == _T('\\')) {
  422. TCHAR szTemp[_MAX_PATH], szLocal[_MAX_PATH];
  423. TCHAR *p = NULL;
  424. int i = 0;
  425. _tcscpy(szTemp, szFile);
  426. p = szTemp;
  427. while (*p) {
  428. if (*p == _T('\\'))
  429. i++;
  430. if (i == 4) {
  431. *p = _T('\0');
  432. p = _tcsinc(p); // p is now pointing at local1\local2
  433. break;
  434. }
  435. p = _tcsinc(p);
  436. }
  437. _tcscpy(szPath, szTemp); // now szPath contains \\computer\share
  438. if (i == 4 && *p) { // p is pointing the local path now
  439. _tcscpy(szLocal, p);
  440. p = _tcsrchr(szLocal, _T('\\'));
  441. if (p)
  442. *p = _T('\0');
  443. _tcscat(szPath, _T("\\"));
  444. _tcscat(szPath, szLocal); // szPath contains \\computer\share\local1
  445. }
  446. } else { // NOT UNC name
  447. TCHAR *p;
  448. if (GetFullPathName(szFile, _MAX_PATH, szPath, &p)) {
  449. p = _tcsrchr(szPath, _T('\\'));
  450. if (p)
  451. {
  452. TCHAR *p2 = NULL;
  453. p2 = _tcsdec(szPath, p);
  454. if (p2)
  455. {
  456. if (*p2 == _T(':') )
  457. {p = _tcsinc(p);}
  458. }
  459. *p = _T('\0');
  460. }
  461. } else {
  462. iisDebugOutSafeParams((LOG_TYPE_WARN, _T("GetFullPathName: szFile=%1!s!, err=%2!d!\n"), szFile, GetLastError()));
  463. MyMessageBox(NULL, _T("GetFullPathName"), GetLastError(), MB_OK | MB_SETFOREGROUND);
  464. }
  465. }
  466. return;
  467. }
  468. BOOL InetDeleteFile(LPCTSTR szFileName)
  469. {
  470. // if file exists but DeleteFile() fails
  471. if ( IsFileExist(szFileName) && !(::DeleteFile(szFileName)) ) {
  472. // if we cannot delete it, then move delay until reboot
  473. // move it to top level dir on the same drive, and mark it as hidden
  474. // Note: MoveFileEx() works only on the same drive if dealing with file-in-use
  475. TCHAR TmpName[_MAX_PATH];
  476. TCHAR csTmpPath[5] = _T("C:\\.");
  477. csTmpPath[0] = *szFileName;
  478. if ( GetTempFileName( (LPCTSTR)csTmpPath, _T("INT"), 0, TmpName ) == 0 ||
  479. !MoveFileEx( szFileName, TmpName, MOVEFILE_REPLACE_EXISTING|MOVEFILE_COPY_ALLOWED|MOVEFILE_WRITE_THROUGH ) ) {
  480. return FALSE;
  481. }
  482. MoveFileEx( TmpName, NULL, MOVEFILE_DELAY_UNTIL_REBOOT );
  483. SetFileAttributes(TmpName, FILE_ATTRIBUTE_HIDDEN);
  484. }
  485. return TRUE;
  486. }
  487. BOOL InetCopyFile( LPCTSTR szSrc, LPCTSTR szDest)
  488. {
  489. INT err;
  490. INT fSrc;
  491. INT fDest;
  492. OFSTRUCT ofstruct;
  493. do {
  494. // open source file
  495. iisDebugOut_Start((_T("LZ32.dll:LZOpenFile()")));
  496. if (( fSrc = LZOpenFile( (LPTSTR)szSrc, &ofstruct, OF_READ | OF_SHARE_DENY_NONE )) < 0 )
  497. {
  498. iisDebugOut_End((_T("LZ32.dll:LZOpenFile")));
  499. // cannot open src file
  500. LZClose(fSrc);
  501. UINT iMsg = MyMessageBox( NULL, IDS_CANNOT_OPEN_SRC_FILE, szSrc, MB_ABORTRETRYIGNORE | MB_SETFOREGROUND );
  502. switch ( iMsg )
  503. {
  504. case IDABORT:
  505. return FALSE;
  506. case IDRETRY:
  507. break;
  508. case IDIGNORE:
  509. default:
  510. return TRUE;
  511. }
  512. }
  513. else
  514. {
  515. iisDebugOut_End((_T("LZ32.dll:LZOpenFile")));
  516. break;
  517. }
  518. } while (TRUE);
  519. // move the desintation file
  520. CFileStatus status;
  521. if ( CFile::GetStatus( szDest, status ))
  522. {
  523. // try to remove it
  524. if ( !InetDeleteFile( szDest ))
  525. {
  526. LZClose( fSrc );
  527. return TRUE;
  528. }
  529. }
  530. // open desination file
  531. do {
  532. iisDebugOut_Start((_T("LZ32.dll:LZOpenFile()")));
  533. if (( fDest = LZOpenFile( (LPTSTR)szDest, &ofstruct, OF_CREATE | OF_WRITE | OF_SHARE_DENY_NONE )) < 0 )
  534. {
  535. iisDebugOut_End((_T("LZ32.dll:LZOpenFile")));
  536. LZClose(fDest);
  537. UINT iMsg = MyMessageBox( NULL, IDS_CANNOT_OPEN_DEST_FILE, szDest, MB_ABORTRETRYIGNORE | MB_SETFOREGROUND );
  538. switch ( iMsg )
  539. {
  540. case IDABORT:
  541. LZClose(fSrc);
  542. return FALSE;
  543. case IDRETRY:
  544. break;
  545. case IDIGNORE:
  546. default:
  547. LZClose(fSrc);
  548. return TRUE;
  549. }
  550. }
  551. else
  552. {
  553. iisDebugOut_End((_T("LZ32.dll:LZOpenFile")));
  554. break;
  555. }
  556. } while (TRUE);
  557. do {
  558. iisDebugOut_Start((_T("LZ32.dll:LZCopy()")));
  559. if (( err = LZCopy( fSrc, fDest )) < 0 )
  560. {
  561. iisDebugOut_End((_T("LZ32.dll:LZCopy")));
  562. LZClose( fSrc );
  563. LZClose( fDest );
  564. UINT iMsg = MyMessageBox( NULL, IDS_CANNOT_COPY_FILE, szSrc,szDest,ERROR_CANNOT_COPY, MB_ABORTRETRYIGNORE | MB_SETFOREGROUND );
  565. switch ( iMsg )
  566. {
  567. case IDABORT:
  568. return FALSE;
  569. case IDRETRY:
  570. break;
  571. case IDIGNORE:
  572. default:
  573. return TRUE;
  574. }
  575. }
  576. else
  577. {
  578. iisDebugOut_End((_T("LZ32.dll:LZCopy")));
  579. LZClose( fSrc );
  580. LZClose( fDest );
  581. break;
  582. }
  583. } while (TRUE);
  584. return TRUE;
  585. }
  586. // Given a fullpathname of a directory, remove any empty dirs under it including itself
  587. BOOL RecRemoveEmptyDir(LPCTSTR szName)
  588. {
  589. BOOL fReturn = FALSE;
  590. DWORD retCode;
  591. BOOL fRemoveDir = TRUE;
  592. WIN32_FIND_DATA FindFileData;
  593. HANDLE hFile = INVALID_HANDLE_VALUE;
  594. TCHAR szSubDir[_MAX_PATH] = _T("");
  595. TCHAR szDirName[_MAX_PATH] = _T("");
  596. retCode = GetFileAttributes(szName);
  597. if (retCode == 0xFFFFFFFF || !(retCode & FILE_ATTRIBUTE_DIRECTORY))
  598. return FALSE;
  599. _stprintf(szDirName, _T("%s\\*"), szName);
  600. hFile = FindFirstFile(szDirName, &FindFileData);
  601. if (hFile != INVALID_HANDLE_VALUE) {
  602. do {
  603. if (_tcsicmp(FindFileData.cFileName, _T(".")) != 0 &&
  604. _tcsicmp(FindFileData.cFileName, _T("..")) != 0 ) {
  605. if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  606. _stprintf(szSubDir, _T("%s\\%s"), szName, FindFileData.cFileName);
  607. fRemoveDir = RecRemoveEmptyDir(szSubDir) && fRemoveDir;
  608. } else {
  609. CString csFileName = FindFileData.cFileName;
  610. CString csPrefix = csFileName.Left(3);
  611. CString csSuffix = csFileName.Right(4);
  612. if (_tcsicmp(csPrefix, _T("INT")) == 0 &&
  613. _tcsicmp(csSuffix, _T(".tmp")) == 0 ) { // this is an INT*.tmp created by IIS
  614. _stprintf(szSubDir, _T("%s\\%s"), szName, FindFileData.cFileName);
  615. if (!::DeleteFile(szSubDir))
  616. fRemoveDir = FALSE; // this dir is not empty
  617. } else
  618. fRemoveDir = FALSE; // it is a file, this Dir is not empty
  619. }
  620. }
  621. if (!FindNextFile(hFile, &FindFileData)) {
  622. FindClose(hFile);
  623. break;
  624. }
  625. } while (TRUE);
  626. }
  627. if (fRemoveDir) {
  628. TCHAR szDirName[_MAX_PATH];
  629. GetCurrentDirectory( _MAX_PATH, szDirName );
  630. SetCurrentDirectory(g_pTheApp->m_csSysDir);
  631. fReturn = ::RemoveDirectory(szName);
  632. SetCurrentDirectory(szDirName);
  633. }
  634. return fReturn;
  635. }
  636. // Given a fullpathname of a directory, remove the directory node
  637. //
  638. // Parameters
  639. // szName - The name of file or directory
  640. // bRemoveDirectoryItself - Should the directory itself be removed
  641. //
  642. BOOL RecRemoveDir(LPCTSTR szName, BOOL bRemoveDirectoryItself /* = TRUE */ )
  643. {
  644. DWORD retCode;
  645. WIN32_FIND_DATA FindFileData;
  646. HANDLE hFile = INVALID_HANDLE_VALUE;
  647. TCHAR szSubDir[_MAX_PATH] = _T("");
  648. TCHAR szDirName[_MAX_PATH] = _T("");
  649. retCode = GetFileAttributes(szName);
  650. if (retCode == 0xFFFFFFFF)
  651. return FALSE;
  652. if (!(retCode & FILE_ATTRIBUTE_DIRECTORY)) {
  653. InetDeleteFile(szName);
  654. return TRUE;
  655. }
  656. _stprintf(szDirName, _T("%s\\*"), szName);
  657. hFile = FindFirstFile(szDirName, &FindFileData);
  658. if (hFile != INVALID_HANDLE_VALUE) {
  659. do {
  660. if ( _tcsicmp(FindFileData.cFileName, _T(".")) != 0 &&
  661. _tcsicmp(FindFileData.cFileName, _T("..")) != 0 ) {
  662. _stprintf(szSubDir, _T("%s\\%s"), szName, FindFileData.cFileName);
  663. RecRemoveDir(szSubDir, TRUE);
  664. }
  665. if ( !FindNextFile(hFile, &FindFileData) ) {
  666. FindClose(hFile);
  667. break;
  668. }
  669. } while (TRUE);
  670. }
  671. if ( bRemoveDirectoryItself )
  672. {
  673. return( ::RemoveDirectory(szName) );
  674. }
  675. return TRUE;
  676. }
  677. //
  678. // Given a directory path, this subroutine will create the direct layer by layer
  679. //
  680. BOOL CreateLayerDirectory( CString &str )
  681. {
  682. BOOL fReturn = TRUE;
  683. iisDebugOutSafeParams((LOG_TYPE_TRACE_WIN32_API, _T("CreateLayerDirectory %1!s!\n"), (LPCTSTR)str));
  684. do
  685. {
  686. INT index=0;
  687. // INT iLength = str.GetLength();
  688. INT iLength = _tcslen(str);
  689. // first find the index for the first directory
  690. if ( iLength > 2 )
  691. {
  692. if ( *_tcsninc(str,1) == _T(':'))
  693. {
  694. // assume the first character is driver letter
  695. if ( *_tcsninc(str,2) == _T('\\'))
  696. {
  697. index = 2;
  698. } else
  699. {
  700. index = 1;
  701. }
  702. } else if ( *_tcsninc(str,0) == _T('\\'))
  703. {
  704. if ( *_tcsninc(str,1) == _T('\\'))
  705. {
  706. BOOL fFound = FALSE;
  707. INT i;
  708. INT nNum = 0;
  709. // unc name
  710. for (i = 2; i < iLength; i++ )
  711. {
  712. if ( *_tcsninc(str,i) == _T('\\'))
  713. {
  714. // find it
  715. nNum ++;
  716. if ( nNum == 2 )
  717. {
  718. fFound = TRUE;
  719. break;
  720. }
  721. }
  722. }
  723. if ( fFound )
  724. {
  725. index = i;
  726. } else
  727. {
  728. // bad name
  729. break;
  730. }
  731. } else
  732. {
  733. index = 1;
  734. }
  735. }
  736. } else if ( *_tcsninc(str,0) == _T('\\'))
  737. {
  738. index = 0;
  739. }
  740. // okay ... build directory
  741. do
  742. {
  743. // find next one
  744. do
  745. {
  746. if ( index < ( iLength - 1))
  747. {
  748. index ++;
  749. } else
  750. {
  751. break;
  752. }
  753. } while ( *_tcsninc(str,index) != _T('\\'));
  754. TCHAR szCurrentDir[_MAX_PATH+1];
  755. TCHAR szLeftDir[_MAX_PATH+1];
  756. ZeroMemory( szLeftDir, _MAX_PATH+1 );
  757. GetCurrentDirectory( _MAX_PATH+1, szCurrentDir );
  758. _tcsncpy( szLeftDir, str, index + 1 );
  759. if ( !SetCurrentDirectory(szLeftDir) )
  760. {
  761. if (( fReturn = CreateDirectory( szLeftDir, NULL )) != TRUE )
  762. {
  763. break;
  764. }
  765. }
  766. SetCurrentDirectory( szCurrentDir );
  767. if ( index >= ( iLength - 1 ))
  768. {
  769. fReturn = TRUE;
  770. break;
  771. }
  772. } while ( TRUE );
  773. } while (FALSE);
  774. return(fReturn);
  775. }
  776. // szResult = szParentDir \ szSubDir
  777. BOOL AppendDir(LPCTSTR szParentDir, LPCTSTR szSubDir, LPTSTR szResult)
  778. {
  779. LPTSTR p = (LPTSTR)szParentDir;
  780. ASSERT(szParentDir);
  781. ASSERT(szSubDir);
  782. ASSERT(*szSubDir && *szSubDir != _T('\\'));
  783. if (*szParentDir == _T('\0'))
  784. _tcscpy(szResult, szSubDir);
  785. else {
  786. _tcscpy(szResult, szParentDir);
  787. p = szResult;
  788. while (*p)
  789. p = _tcsinc(p);
  790. if (*(_tcsdec(szResult, p)) != _T('\\'))
  791. _tcscat(szResult, _T("\\"));
  792. _tcscat(szResult, szSubDir);
  793. }
  794. return TRUE;
  795. }
  796. //***************************************************************************
  797. //*
  798. //* purpose: add's filename onto path
  799. //*
  800. //***************************************************************************
  801. void AddPath(LPTSTR szPath, LPCTSTR szName )
  802. {
  803. LPTSTR p = szPath;
  804. LPTSTR pPrev;
  805. ASSERT(szPath);
  806. ASSERT(szName);
  807. // Find end of the string
  808. while (*p){p = _tcsinc(p);}
  809. // If no trailing backslash then add one
  810. pPrev = _tcsdec(szPath, p);
  811. if ( (!pPrev) ||
  812. (*(pPrev) != _T('\\'))
  813. )
  814. {_tcscat(szPath, _T("\\"));}
  815. // if there are spaces precluding szName, then skip
  816. while ( *szName == ' ' ) szName = _tcsinc(szName);;
  817. // Add new name to existing path string
  818. _tcscat(szPath, szName);
  819. }
  820. CString AddPath(CString szPath, LPCTSTR szName )
  821. {
  822. TCHAR szPathCopy[_MAX_PATH] = _T("");
  823. _tcscpy(szPathCopy,szPath);
  824. LPTSTR p = szPathCopy;
  825. ASSERT(szPathCopy);
  826. ASSERT(szName);
  827. // Find end of the string
  828. while (*p){p = _tcsinc(p);}
  829. // If no trailing backslash then add one
  830. if (*(_tcsdec(szPathCopy, p)) != _T('\\'))
  831. {_tcscat(szPathCopy, _T("\\"));}
  832. // if there are spaces precluding szName, then skip
  833. while ( *szName == _T(' ') ) szName = _tcsinc(szName);;
  834. // make sure that the szName
  835. // does not look like this "\filename"
  836. CString csTempString = szName;
  837. if (_tcsicmp(csTempString.Left(1), _T("\\")) == 0)
  838. {
  839. csTempString = csTempString.Right( csTempString.GetLength() - 1);
  840. }
  841. // Add new name to existing path string
  842. _tcscat(szPathCopy, csTempString);
  843. return szPathCopy;
  844. //szPath = szPathCopy;
  845. }
  846. BOOL ReturnFileNameOnly(LPCTSTR lpFullPath, LPTSTR lpReturnFileName)
  847. {
  848. int iReturn = FALSE;
  849. TCHAR pfilename_only[_MAX_FNAME];
  850. TCHAR pextention_only[_MAX_EXT];
  851. _tcscpy(lpReturnFileName, _T(""));
  852. _tsplitpath( lpFullPath, NULL, NULL, pfilename_only, pextention_only);
  853. if (pextention_only) {_tcscat(pfilename_only,pextention_only);}
  854. if (pfilename_only)
  855. {
  856. _tcscpy(lpReturnFileName, pfilename_only);
  857. iReturn = TRUE;
  858. }
  859. else
  860. {
  861. // well, we don't have anything in pfilename_only
  862. // that's probably because we got some strange path name like:
  863. // /??/c:\somethng\filename.txt
  864. // so... let's just return everything after the last "\" character.
  865. LPTSTR pszTheLastBackSlash = _tcsrchr((LPTSTR) lpFullPath, _T('\\'));
  866. _tcscpy(lpReturnFileName, pszTheLastBackSlash);
  867. iReturn = TRUE;
  868. }
  869. return iReturn;
  870. }
  871. BOOL ReturnFilePathOnly(LPCTSTR lpFullPath, LPTSTR lpReturnPathOnly)
  872. {
  873. int iReturn = FALSE;
  874. TCHAR szDrive_only[_MAX_DRIVE];
  875. TCHAR szPath_only[_MAX_PATH];
  876. TCHAR szFilename_only[_MAX_PATH];
  877. TCHAR szFilename_ext_only[_MAX_EXT];
  878. _tcscpy(lpReturnPathOnly, _T(""));
  879. _tsplitpath( lpFullPath, szDrive_only, szPath_only, szFilename_only, szFilename_ext_only);
  880. _tcscpy(lpReturnPathOnly, szDrive_only);
  881. _tcscat(lpReturnPathOnly, szPath_only);
  882. iReturn = TRUE;
  883. return iReturn;
  884. }
  885. void DeleteFilesWildcard(TCHAR *szDir, TCHAR *szFileName)
  886. {
  887. WIN32_FIND_DATA FindFileData;
  888. HANDLE hFile = INVALID_HANDLE_VALUE;
  889. TCHAR szFileToBeDeleted[_MAX_PATH];
  890. _stprintf(szFileToBeDeleted, _T("%s\\%s"), szDir, szFileName);
  891. hFile = FindFirstFile(szFileToBeDeleted, &FindFileData);
  892. if (hFile != INVALID_HANDLE_VALUE)
  893. {
  894. do {
  895. if ( _tcsicmp(FindFileData.cFileName, _T(".")) != 0 && _tcsicmp(FindFileData.cFileName, _T("..")) != 0 )
  896. {
  897. if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  898. {
  899. // this is a directory, so let's skip it
  900. }
  901. else
  902. {
  903. // this is a file, so let's Delete it.
  904. TCHAR szTempFileName[_MAX_PATH];
  905. _stprintf(szTempFileName, _T("%s\\%s"), szDir, FindFileData.cFileName);
  906. // set to normal attributes, so we can delete it
  907. SetFileAttributes(szTempFileName, FILE_ATTRIBUTE_NORMAL);
  908. // delete it, hopefully
  909. InetDeleteFile(szTempFileName);
  910. }
  911. }
  912. // get the next file
  913. if ( !FindNextFile(hFile, &FindFileData) )
  914. {
  915. FindClose(hFile);
  916. break;
  917. }
  918. } while (TRUE);
  919. }
  920. return;
  921. }
  922. int IsThisDriveNTFS(IN LPTSTR FileName)
  923. {
  924. BOOL Ntfs = FALSE;
  925. TCHAR szDriveRootPath[_MAX_DRIVE + 5];
  926. DWORD DontCare;
  927. TCHAR NameBuffer[100];
  928. // get the Drive only.
  929. _tsplitpath( FileName, szDriveRootPath, NULL, NULL, NULL);
  930. _tcscat(szDriveRootPath, _T("\\"));
  931. //
  932. // find out what the file system is
  933. //
  934. if (0 != GetVolumeInformation(szDriveRootPath,NULL,0,NULL,&DontCare,&DontCare,NameBuffer,sizeof(NameBuffer)/sizeof(TCHAR)))
  935. {
  936. if (0 == _tcsicmp(NameBuffer,_T("NTFS")))
  937. {Ntfs = TRUE;}
  938. }
  939. return Ntfs;
  940. }
  941. // take something like
  942. // e:\winnt\system32 and return back %systemroot%\system23
  943. // e:\winnt\system32\inetsrv and return back %systemroot%\system23\inetsrv
  944. int ReverseExpandEnvironmentStrings(LPTSTR szOriginalDir,LPTSTR szNewlyMungedDir)
  945. {
  946. int iReturn = FALSE;
  947. int iWhere = 0;
  948. TCHAR szSystemDir[_MAX_PATH];
  949. CString csTempString;
  950. CString csTempString2;
  951. // default it with the input string
  952. _tcscpy(szNewlyMungedDir, szOriginalDir);
  953. // get the c:\winnt\system32 dir
  954. if (0 == GetSystemDirectory(szSystemDir, _MAX_PATH))
  955. {
  956. // we weren't able to get the systemdirectory, so just return whatever was put in
  957. iReturn = TRUE;
  958. goto ReverseExpandEnvironmentStrings_Exit;
  959. }
  960. csTempString = szOriginalDir;
  961. csTempString2 = szSystemDir;
  962. // Find the "e:\winnt\system32"
  963. iWhere = csTempString.Find(szSystemDir);
  964. if (-1 != iWhere)
  965. {
  966. CString AfterString;
  967. // there is a "e:\winnt\system32" in the string
  968. // Get the after e:\winnt\system32 stuff
  969. AfterString = csTempString.Right(csTempString.GetLength() - (iWhere + csTempString2.GetLength()));
  970. // Take everything after the string and append it to our new string.
  971. _tcscpy(szNewlyMungedDir, _T("%SystemRoot%\\System32"));
  972. _tcscat(szNewlyMungedDir, AfterString);
  973. // return true!
  974. iReturn = TRUE;
  975. }
  976. ReverseExpandEnvironmentStrings_Exit:
  977. return iReturn;
  978. }
  979. DWORD ReturnFileSize(LPCTSTR myFileName)
  980. {
  981. DWORD dwReturn = 0xFFFFFFFF;
  982. HANDLE hFile = CreateFile(myFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, NULL);
  983. if (hFile != INVALID_HANDLE_VALUE)
  984. {
  985. dwReturn = GetFileSize(hFile, NULL);
  986. CloseHandle(hFile);
  987. }
  988. return dwReturn;
  989. }
  990. BOOL IsFileExist_NormalOrCompressed(LPCTSTR szFile)
  991. {
  992. int iReturn = FALSE;
  993. TCHAR szDrive_only[_MAX_DRIVE];
  994. TCHAR szPath_only[_MAX_PATH];
  995. TCHAR szFilename_only[_MAX_PATH];
  996. TCHAR szFilename_ext_only[_MAX_EXT];
  997. TCHAR szCompressedName[_MAX_PATH];
  998. // Check if the file exsts
  999. // if it doesn't, check if maybe the compressed file exists.
  1000. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("IsFileExist_NormalOrCompressed:%s.\n"), szFile));
  1001. if (IsFileExist(szFile) != TRUE)
  1002. {
  1003. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("IsFileExist_NormalOrCompressed:%s not exist.\n"), szFile));
  1004. // check if maybe the compressed file exists
  1005. _tsplitpath( szFile, szDrive_only, szPath_only, szFilename_only, szFilename_ext_only);
  1006. // Replace the last character with an '_'
  1007. int nLen = 0;
  1008. nLen = _tcslen(szFilename_ext_only);
  1009. *_tcsninc(szFilename_ext_only, nLen-1) = _T('_');
  1010. _stprintf(szCompressedName,_T("%s%s%s%s"),szDrive_only, szPath_only, szFilename_only, szFilename_ext_only);
  1011. // see if it exists
  1012. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("IsFileExist_NormalOrCompressed:%s.\n"), szCompressedName));
  1013. if (IsFileExist(szCompressedName) != TRUE)
  1014. {
  1015. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("IsFileExist_NormalOrCompressed:%s. no exist.\n"), szCompressedName));
  1016. goto IsFileExist_RegOrCompressed_Exit;
  1017. }
  1018. else
  1019. {
  1020. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("IsFileExist_NormalOrCompressed:%s. exist.\n"), szCompressedName));
  1021. }
  1022. }
  1023. // we got this far, that must mean things are okay.
  1024. iReturn = TRUE;
  1025. IsFileExist_RegOrCompressed_Exit:
  1026. return iReturn;
  1027. }
  1028. // Clean leading & trailing spaces
  1029. // Clean trailing backslashes
  1030. BOOL CleanPathString(LPTSTR szPath)
  1031. {
  1032. CString csPath = szPath;
  1033. csPath.TrimLeft();
  1034. csPath.TrimRight();
  1035. _tcscpy(szPath, (LPCTSTR)csPath);
  1036. return TRUE;
  1037. }
  1038. //
  1039. // Return 0 if there was nothing to compare
  1040. // Return 1 if Source is Equal to Destination
  1041. // Return 2 if Source is Larger than Destination
  1042. // Return 3 if Source is Less than Destination
  1043. //
  1044. INT VerCmp(LPTSTR szSrcVerString, LPTSTR szDestVerString)
  1045. {
  1046. INT iReturn = 0;
  1047. const DWORD MAX_NUM_OF_VER_FIELDS = 32;
  1048. DWORD dwSrcVer[MAX_NUM_OF_VER_FIELDS], dwDestVer[MAX_NUM_OF_VER_FIELDS];
  1049. memset( (PVOID)dwSrcVer, 0, sizeof(dwSrcVer));
  1050. memset( (PVOID)dwDestVer, 0, sizeof(dwDestVer));
  1051. int i=0;
  1052. TCHAR szSeps[] = _T(".");
  1053. TCHAR *token;
  1054. BOOL bNotEqual = FALSE;
  1055. // expand src version string into a dword arrary
  1056. i = 0;
  1057. token = _tcstok(szSrcVerString, szSeps);
  1058. while ( token && (i < MAX_NUM_OF_VER_FIELDS) ) {
  1059. dwSrcVer[i++] = _ttoi(token);
  1060. token = _tcstok(NULL, szSeps);
  1061. }
  1062. // expand dest version string into a dword arrary
  1063. i = 0;
  1064. token = _tcstok(szDestVerString, szSeps);
  1065. while ( token && (i < MAX_NUM_OF_VER_FIELDS) ) {
  1066. dwDestVer[i++] = _ttoi(token);
  1067. token = _tcstok(NULL, szSeps);
  1068. }
  1069. // Check for Equality
  1070. for (i=0; i<MAX_NUM_OF_VER_FIELDS; i++)
  1071. {
  1072. if (dwSrcVer[i] != dwDestVer[i])
  1073. {
  1074. bNotEqual = TRUE;
  1075. break;
  1076. }
  1077. }
  1078. if (TRUE == bNotEqual)
  1079. {
  1080. // int compare each field
  1081. for (i=0; i<MAX_NUM_OF_VER_FIELDS; i++)
  1082. {
  1083. if (dwSrcVer[i] > dwDestVer[i])
  1084. {return 2;}
  1085. if (dwSrcVer[i] < dwDestVer[i])
  1086. {return 3;}
  1087. }
  1088. // if we haven't return here, then
  1089. // there probably wasn't anything to loop thru (for 0=0 till 0)
  1090. return 0;
  1091. }
  1092. else
  1093. {
  1094. // it is equal so return so
  1095. return 1;
  1096. }
  1097. }
  1098. DWORD atodw(LPCTSTR lpszData)
  1099. {
  1100. DWORD i = 0, sum = 0;
  1101. TCHAR *s, *t;
  1102. s = (LPTSTR)lpszData;
  1103. t = (LPTSTR)lpszData;
  1104. while (*t)
  1105. t = _tcsinc(t);
  1106. t = _tcsdec(lpszData, t);
  1107. if (*s == _T('0') && (*(_tcsinc(s)) == _T('x') || *(_tcsinc(s)) == _T('X')))
  1108. s = _tcsninc(s, 2);
  1109. while (s <= t) {
  1110. if ( *s >= _T('0') && *s <= _T('9') )
  1111. i = *s - _T('0');
  1112. else if ( *s >= _T('a') && *s <= _T('f') )
  1113. i = *s - _T('a') + 10;
  1114. else if ( *s >= _T('A') && *s <= _T('F') )
  1115. i = *s - _T('A') + 10;
  1116. else
  1117. break;
  1118. sum = sum * 16 + i;
  1119. s = _tcsinc(s);
  1120. }
  1121. return sum;
  1122. }
  1123. void MakePath(LPTSTR lpPath)
  1124. {
  1125. LPTSTR lpTmp;
  1126. lpTmp = CharPrev( lpPath, lpPath + _tcslen(lpPath));
  1127. // chop filename off
  1128. while ( (lpTmp > lpPath) && *lpTmp && (*lpTmp != '\\') )
  1129. lpTmp = CharPrev( lpPath, lpTmp );
  1130. if ( *CharPrev( lpPath, lpTmp ) != ':' )
  1131. *lpTmp = '\0';
  1132. else
  1133. *CharNext(lpTmp) = '\0';
  1134. return;
  1135. }
  1136. CString ReturnUniqueFileName(CString csInputFullName)
  1137. {
  1138. TCHAR szPathCopy[_MAX_PATH] = _T("");
  1139. _tcscpy(szPathCopy,csInputFullName);
  1140. long iNum = 1;
  1141. do
  1142. {
  1143. _stprintf(szPathCopy,TEXT("%s.%d"),csInputFullName,iNum);
  1144. // Check if the file exists
  1145. if (!IsFileExist(szPathCopy)){goto ReturnUniqueFileName_Exit;}
  1146. iNum++;
  1147. } while (iNum <= 50);
  1148. ReturnUniqueFileName_Exit:
  1149. // returns %s50 if there are fifty copies aleady!
  1150. return szPathCopy;
  1151. }
  1152. /*---------------------------------------------------------------------------*
  1153. Description: Displays the current running version of setup to the debug
  1154. output and setup log.
  1155. -----------------------------------------------------------------------------*/
  1156. void DisplayVerOnCurrentModule()
  1157. {
  1158. TCHAR tszModuleName[_MAX_PATH+1];
  1159. if ( GetModuleFileName((HINSTANCE)g_MyModuleHandle, tszModuleName, _MAX_PATH+1) != 0 )
  1160. {
  1161. LogFileVersion(tszModuleName, TRUE);
  1162. }
  1163. return;
  1164. }
  1165. void MyGetVersionFromFile(LPCTSTR lpszFilename, LPDWORD pdwMSVer, LPDWORD pdwLSVer, LPTSTR pszReturnLocalizedVersion)
  1166. {
  1167. struct TRANSARRAY {
  1168. WORD wLanguageID;
  1169. WORD wCharacterSet;
  1170. };
  1171. unsigned uiSize;
  1172. DWORD dwVerInfoSize;
  1173. DWORD dwHandle;
  1174. VS_FIXEDFILEINFO * lpVSFixedFileInfo;
  1175. LPTSTR lpBuffer = NULL;
  1176. LPVOID lpVerBuffer = NULL;
  1177. LPTSTR pszTheResult = NULL;
  1178. TCHAR QueryString[48] = _T("");
  1179. TRANSARRAY *lpTransArray;
  1180. *pdwMSVer = *pdwLSVer = 0L;
  1181. dwVerInfoSize = GetFileVersionInfoSize( (LPTSTR) lpszFilename, &dwHandle);
  1182. if (dwVerInfoSize)
  1183. {
  1184. // Alloc the memory for the version stamping
  1185. lpBuffer = (LPTSTR) LocalAlloc(LPTR, dwVerInfoSize);
  1186. if (lpBuffer)
  1187. {
  1188. int iTemp = 0;
  1189. iTemp = GetFileVersionInfo( (LPTSTR) lpszFilename, dwHandle, dwVerInfoSize, lpBuffer);
  1190. // Read version stamping info
  1191. if (iTemp)
  1192. {
  1193. // Get the value for Translation
  1194. if (VerQueryValue(lpBuffer, _T("\\"), (LPVOID*)&lpVSFixedFileInfo, &uiSize) && (uiSize))
  1195. {
  1196. *pdwMSVer = lpVSFixedFileInfo->dwFileVersionMS;
  1197. *pdwLSVer = lpVSFixedFileInfo->dwFileVersionLS;
  1198. }
  1199. // get a pointer to the translation table information
  1200. if (VerQueryValue(lpBuffer, _T("\\VarFileInfo\\Translation"), &lpVerBuffer, &uiSize) && (uiSize))
  1201. {
  1202. lpTransArray = (TRANSARRAY *) lpVerBuffer;
  1203. // lpTransArray points to the translation array. dwFixedLength has number of bytes in array
  1204. _stprintf(QueryString, _T("\\StringFileInfo\\%04x%04x\\FileVersion"), lpTransArray[0].wLanguageID, lpTransArray[0].wCharacterSet);
  1205. if (VerQueryValue(lpBuffer, QueryString, (LPVOID*) &pszTheResult, &uiSize))
  1206. {
  1207. _tcscpy(pszReturnLocalizedVersion, pszTheResult);
  1208. }
  1209. }
  1210. }
  1211. }
  1212. }
  1213. if(lpBuffer) {LocalFree(lpBuffer);lpBuffer=NULL;}
  1214. return ;
  1215. }
  1216. BOOL MyGetDescriptionFromFile(LPCTSTR lpszFilename, LPTSTR pszReturnDescription)
  1217. {
  1218. BOOL bRet = FALSE;
  1219. struct TRANSARRAY {
  1220. WORD wLanguageID;
  1221. WORD wCharacterSet;
  1222. };
  1223. unsigned uiSize;
  1224. DWORD dwVerInfoSize;
  1225. DWORD dwHandle;
  1226. LPTSTR lpBuffer = NULL;
  1227. LPVOID lpTempBuffer = NULL;
  1228. LPTSTR pszTheResult = NULL;
  1229. TCHAR QueryString[52] = _T("");
  1230. TRANSARRAY *lpTransArray;
  1231. dwVerInfoSize = GetFileVersionInfoSize( (LPTSTR) lpszFilename, &dwHandle);
  1232. if (dwVerInfoSize)
  1233. {
  1234. // Alloc the memory for the version stamping
  1235. lpBuffer = (LPTSTR) LocalAlloc(LPTR, dwVerInfoSize);
  1236. if (lpBuffer)
  1237. {
  1238. int iTemp = 0;
  1239. iTemp = GetFileVersionInfo( (LPTSTR) lpszFilename, dwHandle, dwVerInfoSize, lpBuffer);
  1240. // Read version stamping info
  1241. if (iTemp)
  1242. {
  1243. // get a pointer to the translation table information
  1244. if (VerQueryValue(lpBuffer, _T("\\VarFileInfo\\Translation"), &lpTempBuffer, &uiSize) && (uiSize))
  1245. {
  1246. lpTransArray = (TRANSARRAY *) lpTempBuffer;
  1247. // lpTransArray points to the translation array. dwFixedLength has number of bytes in array
  1248. _stprintf(QueryString, _T("\\StringFileInfo\\%04x%04x\\FileDescription"), lpTransArray[0].wLanguageID, lpTransArray[0].wCharacterSet);
  1249. if (VerQueryValue(lpBuffer, QueryString, (LPVOID*) &pszTheResult, &uiSize))
  1250. {
  1251. _tcscpy(pszReturnDescription, pszTheResult);
  1252. bRet = TRUE;
  1253. }
  1254. }
  1255. }
  1256. }
  1257. }
  1258. if(lpBuffer) {LocalFree(lpBuffer);lpBuffer=NULL;}
  1259. return bRet;
  1260. }
  1261. //
  1262. // Returns True if the filename has a version stamp which is part of ntop4.0
  1263. //
  1264. int IsFileLessThanThisVersion(IN LPCTSTR lpszFullFilePath, IN DWORD dwNtopMSVer, IN DWORD dwNtopLSVer)
  1265. {
  1266. int iReturn = FALSE;
  1267. DWORD dwMSVer, dwLSVer;
  1268. TCHAR szLocalizedVersion[100] = _T("");
  1269. // if the filename has a version number
  1270. // and it's larger than the release version of ntop 4.2.622.1, 4.02.0622 (localized version)
  1271. // return back true! if not, then return back false.
  1272. // see if the file exists
  1273. if (!IsFileExist(lpszFullFilePath))
  1274. {goto iFileWasPartOfIIS4_Exit;}
  1275. // get the fileinformation
  1276. // includes version and localizedversion
  1277. MyGetVersionFromFile(lpszFullFilePath, &dwMSVer, &dwLSVer, szLocalizedVersion);
  1278. if (!dwMSVer)
  1279. {
  1280. iisDebugOut((LOG_TYPE_TRACE, _T("iFileWasPartOfIIS4:%s.No version."), lpszFullFilePath));
  1281. goto iFileWasPartOfIIS4_Exit;
  1282. }
  1283. // okay, there is a version on this.
  1284. iisDebugOut((LOG_TYPE_TRACE, _T("iFileWasPartOfIIS4:%d.%d.%d.%d, %s, %s"), HIWORD(dwMSVer), LOWORD(dwMSVer), HIWORD(dwLSVer), LOWORD(dwLSVer), szLocalizedVersion, lpszFullFilePath));
  1285. // Check if the version is smaller than what was shipped with iis4.0
  1286. // NTOP versions were 4.02.0622
  1287. if (dwMSVer < dwNtopMSVer)
  1288. {goto iFileWasPartOfIIS4_Exit;}
  1289. // check if the file has a smaller minor version number
  1290. if ( (dwMSVer == dwNtopMSVer) && (dwLSVer < dwNtopLSVer) )
  1291. {goto iFileWasPartOfIIS4_Exit;}
  1292. // this is a ntop 4.0 or greater versioned file
  1293. iReturn = TRUE;
  1294. iFileWasPartOfIIS4_Exit:
  1295. return iReturn;
  1296. }
  1297. void MakeSureDirAclsHaveAtLeastRead(LPTSTR lpszDirectoryPath)
  1298. {
  1299. iisDebugOut_Start1(_T("MakeSureDirAclsHaveAtLeastRead"),lpszDirectoryPath, LOG_TYPE_TRACE);
  1300. DWORD err;
  1301. TCHAR szThePath[_MAX_PATH];
  1302. if (FALSE == IsThisDriveNTFS(lpszDirectoryPath))
  1303. {
  1304. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("MakeSureDirAclsHaveAtLeastRead:filesys is not ntfs.")));
  1305. goto MakeSureDirAclsHaveAtLeastRead_Exit;
  1306. }
  1307. do
  1308. {
  1309. //
  1310. // Loop through all the files in the physical path
  1311. //
  1312. _tcscpy(szThePath, lpszDirectoryPath);
  1313. _tcscat(szThePath, _T("\\*"));
  1314. WIN32_FIND_DATA w32data;
  1315. HANDLE hFind = ::FindFirstFile(szThePath, &w32data);
  1316. if (hFind == INVALID_HANDLE_VALUE)
  1317. {
  1318. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("MakeSureDirAclsHaveAtLeastRead:WARNING.filenotfound:%s"),lpszDirectoryPath));
  1319. // No files...
  1320. break;
  1321. }
  1322. //
  1323. // First, set the new ACL on the folder itself.
  1324. //
  1325. err = SetAccessOnFile(lpszDirectoryPath, TRUE);
  1326. err = SetAccessOnFile(lpszDirectoryPath, FALSE);
  1327. err = ERROR_SUCCESS;
  1328. //if (err != ERROR_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("MakeSureDirAclsHaveAtLeastRead:%s:FAILED WARNING.ret=0x%x."),lpszDirectoryPath,err));}
  1329. //
  1330. // Now do all the files in it
  1331. //
  1332. do
  1333. {
  1334. //
  1335. // Only set the acl on files, not sub-directories
  1336. //
  1337. if (w32data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  1338. {
  1339. continue;
  1340. }
  1341. //
  1342. // Build the current file's full path name
  1343. //
  1344. _tcscpy(szThePath, lpszDirectoryPath);
  1345. _tcscat(szThePath, _T("\\"));
  1346. _tcscat(szThePath, w32data.cFileName);
  1347. err = SetAccessOnFile(szThePath, TRUE);
  1348. err = SetAccessOnFile(szThePath, FALSE);
  1349. err = ERROR_SUCCESS;
  1350. //if (err != ERROR_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("MakeSureDirAclsHaveAtLeastRead:%s:FAILED WARNING.ret=0x%x."),szThePath,err));}
  1351. } while(SUCCEEDED(err) && FindNextFile(hFind, &w32data));
  1352. FindClose(hFind);
  1353. } while(FALSE);
  1354. MakeSureDirAclsHaveAtLeastRead_Exit:
  1355. return;
  1356. }
  1357. DWORD SetAccessOnFile(IN LPTSTR FileName, BOOL bDoForAdmin)
  1358. {
  1359. DWORD dwError = 0;
  1360. TCHAR TrusteeName[50];
  1361. PACL ExistingDacl = NULL;
  1362. PACL NewAcl = NULL;
  1363. PSECURITY_DESCRIPTOR psd = NULL;
  1364. // access stuff.
  1365. DWORD AccessMask = GENERIC_ALL;
  1366. EXPLICIT_ACCESS explicitaccess;
  1367. ACCESS_MODE option;
  1368. DWORD InheritFlag = NO_INHERITANCE;
  1369. // other
  1370. PSID principalSID = NULL;
  1371. BOOL bWellKnownSID = FALSE;
  1372. // other other
  1373. LPCTSTR ServerName = NULL; // local machine
  1374. DWORD cbName = 200;
  1375. TCHAR lpGuestGrpName[200];
  1376. TCHAR ReferencedDomainName[200];
  1377. DWORD cbReferencedDomainName = sizeof(ReferencedDomainName);
  1378. SID_NAME_USE sidNameUse = SidTypeUser;
  1379. // get current Dacl on specified file
  1380. dwError = GetNamedSecurityInfo(FileName,SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,&ExistingDacl,NULL,&psd);
  1381. if(dwError != ERROR_SUCCESS)
  1382. {
  1383. iisDebugOut((LOG_TYPE_WARN, _T("SetAccessOnFile: GetNamedSecurityInfo failed on %s. err=0x%x\n"),FileName,dwError));
  1384. goto SetAccessOnFile_Exit;
  1385. }
  1386. // set defaults
  1387. option = GRANT_ACCESS;
  1388. InheritFlag = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  1389. if (bDoForAdmin)
  1390. {
  1391. // Do for Administrators -- should be more access
  1392. AccessMask = SYNCHRONIZE ;
  1393. AccessMask |= GENERIC_ALL;
  1394. _tcscpy(TrusteeName,_T("BUILTIN\\ADMINISTRATORS"));
  1395. _tcscpy(TrusteeName,_T("administrators"));
  1396. }
  1397. else
  1398. {
  1399. // Do for Administrators -- should be more access
  1400. AccessMask = SYNCHRONIZE ;
  1401. AccessMask |= GENERIC_READ;
  1402. _tcscpy(TrusteeName,_T("EVERYONE"));
  1403. }
  1404. // Get the SID for the certain string (administrator or everyone)
  1405. dwError = GetPrincipalSID(TrusteeName, &principalSID, &bWellKnownSID);
  1406. if (dwError != ERROR_SUCCESS)
  1407. {
  1408. iisDebugOut((LOG_TYPE_WARN, _T("SetAccessOnFile:GetPrincipalSID(%s) FAILED. Error()= 0x%x\n"), TrusteeName, dwError));
  1409. goto SetAccessOnFile_Exit;
  1410. }
  1411. // using Sid, get the "localized" name
  1412. if (0 == LookupAccountSid(ServerName, principalSID, lpGuestGrpName, &cbName, ReferencedDomainName, &cbReferencedDomainName, &sidNameUse))
  1413. {
  1414. iisDebugOut((LOG_TYPE_WARN, _T("SetAccessOnFile:LookupAccountSid(%s) FAILED. GetLastError()= 0x%x\n"), TrusteeName, GetLastError()));
  1415. goto SetAccessOnFile_Exit;
  1416. }
  1417. // using the "localized" name, build explicit access structure
  1418. BuildExplicitAccessWithName(&explicitaccess,lpGuestGrpName,AccessMask,option,InheritFlag);
  1419. explicitaccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
  1420. explicitaccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
  1421. explicitaccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
  1422. // set the acl with this certain access stuff
  1423. dwError = SetEntriesInAcl(1,&explicitaccess,ExistingDacl,&NewAcl);
  1424. if(dwError != ERROR_SUCCESS)
  1425. {
  1426. // it may error because the user is already there
  1427. //iisDebugOut((LOG_TYPE_WARN, _T("SetAccessOnFile: SetEntriesInAcl failed on %s. for trustee=%s. err=0x%x\n"),FileName,explicitaccess.Trustee.ptstrName,dwError));
  1428. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("SetAccessOnFile: SetEntriesInAcl failed on %s. for trustee=%s. err=0x%x\n"),FileName,explicitaccess.Trustee.ptstrName,dwError));
  1429. goto SetAccessOnFile_Exit;
  1430. }
  1431. // apply new security to file
  1432. dwError = SetNamedSecurityInfo(FileName,SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,NewAcl,NULL);
  1433. if(dwError != ERROR_SUCCESS)
  1434. {
  1435. iisDebugOut((LOG_TYPE_WARN, _T("SetAccessOnFile: SetNamedSecurityInfo failed on %s. err=0x%x\n"),FileName,dwError));
  1436. goto SetAccessOnFile_Exit;
  1437. }
  1438. // everything is kool!
  1439. dwError = ERROR_SUCCESS;
  1440. SetAccessOnFile_Exit:
  1441. if(NewAcl != NULL){LocalFree(NewAcl);}
  1442. if(psd != NULL){LocalFree(psd);}
  1443. if (principalSID)
  1444. {
  1445. if (bWellKnownSID)
  1446. FreeSid (principalSID);
  1447. else
  1448. free (principalSID);
  1449. }
  1450. return dwError;
  1451. }
  1452. int CreateAnEmptyFile(CString strTheFullPath)
  1453. {
  1454. int iReturn = FALSE;
  1455. HANDLE hFile = NULL;
  1456. if (IsFileExist(strTheFullPath) == TRUE)
  1457. {
  1458. return TRUE;
  1459. }
  1460. // Open existing file or create a new one.
  1461. hFile = CreateFile(strTheFullPath,GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
  1462. if (hFile == INVALID_HANDLE_VALUE)
  1463. {
  1464. hFile = NULL;
  1465. iisDebugOutSafeParams((LOG_TYPE_WARN, _T("CreateAnEmptyFile:() failed to CreateFile %1!s!. POTENTIAL PROBLEM. FAILURE.\n"), strTheFullPath));
  1466. }
  1467. else
  1468. {
  1469. // write to the file
  1470. if (hFile)
  1471. {
  1472. iReturn = TRUE;
  1473. /*
  1474. DWORD dwBytesWritten = 0;
  1475. char szTestData[2];
  1476. strcpy(szTestData, " ");
  1477. if (WriteFile(hFile,szTestData,strlen(szTestData),&dwBytesWritten,NULL))
  1478. {
  1479. // everything is hunky dory. don't print anything
  1480. iReturn = TRUE;
  1481. }
  1482. else
  1483. {
  1484. // error writing to the file.
  1485. iisDebugOutSafeParams((LOG_TYPE_WARN, _T("CreateAnEmptyFile:WriteFile(%1!s!) Failed. POTENTIAL PROBLEM. FAILURE. Error=0x%2!x!.\n"), strTheFullPath, GetLastError()));
  1486. }
  1487. */
  1488. }
  1489. }
  1490. if (hFile)
  1491. {
  1492. CloseHandle(hFile);
  1493. }
  1494. return iReturn;
  1495. }
  1496. DWORD GrantUserAccessToFile(IN LPTSTR FileName,IN LPTSTR TrusteeName)
  1497. {
  1498. iisDebugOut_Start1(_T("GrantUserAccessToFile"),FileName,LOG_TYPE_TRACE);
  1499. DWORD dwError = 0;
  1500. PACL ExistingDacl = NULL;
  1501. PACL NewAcl = NULL;
  1502. PSECURITY_DESCRIPTOR psd = NULL;
  1503. // access stuff.
  1504. DWORD AccessMask = GENERIC_ALL;
  1505. EXPLICIT_ACCESS explicitaccess;
  1506. ACCESS_MODE option;
  1507. DWORD InheritFlag = NO_INHERITANCE;
  1508. // other
  1509. PSID principalSID = NULL;
  1510. BOOL bWellKnownSID = FALSE;
  1511. // other other
  1512. LPCTSTR ServerName = NULL; // local machine
  1513. DWORD cbName = 200;
  1514. TCHAR lpGuestGrpName[200];
  1515. TCHAR ReferencedDomainName[200];
  1516. DWORD cbReferencedDomainName = sizeof(ReferencedDomainName);
  1517. SID_NAME_USE sidNameUse = SidTypeUser;
  1518. if (IsFileExist(FileName) != TRUE)
  1519. {
  1520. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("GrantUserAccessToFile:file doesn't exist.")));
  1521. goto GrantUserAccessToFile_Exit;
  1522. }
  1523. if (FALSE == IsThisDriveNTFS(FileName))
  1524. {
  1525. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("GrantUserAccessToFile:filesys is not ntfs.")));
  1526. goto GrantUserAccessToFile_Exit;
  1527. }
  1528. // get current Dacl on specified file
  1529. dwError = GetNamedSecurityInfo(FileName,SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,&ExistingDacl,NULL,&psd);
  1530. if(dwError != ERROR_SUCCESS)
  1531. {
  1532. psd = NULL;
  1533. iisDebugOut((LOG_TYPE_WARN, _T("GrantUserAccessToFile: GetNamedSecurityInfo failed on %s.\n"),FileName));
  1534. goto GrantUserAccessToFile_Exit;
  1535. }
  1536. // set defaults
  1537. option = GRANT_ACCESS;
  1538. InheritFlag = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  1539. // assign access
  1540. AccessMask = SYNCHRONIZE ;
  1541. AccessMask |= GENERIC_ALL;
  1542. //AccessMask = MAXIMUM_ALLOWED;
  1543. // Get the SID for the certain string (administrator or everyone)
  1544. dwError = GetPrincipalSID(TrusteeName, &principalSID, &bWellKnownSID);
  1545. if (dwError != ERROR_SUCCESS)
  1546. {
  1547. principalSID = NULL;
  1548. iisDebugOut((LOG_TYPE_WARN, _T("GrantUserAccessToFile:GetPrincipalSID(%s) FAILED. Error()= 0x%x\n"), TrusteeName, dwError));
  1549. goto GrantUserAccessToFile_Exit;
  1550. }
  1551. // using Sid, get the "localized" name
  1552. if (0 == LookupAccountSid(ServerName, principalSID, lpGuestGrpName, &cbName, ReferencedDomainName, &cbReferencedDomainName, &sidNameUse))
  1553. {
  1554. iisDebugOut((LOG_TYPE_WARN, _T("GrantUserAccessToFile:LookupAccountSid(%s) FAILED. GetLastError()= 0x%x\n"), TrusteeName, GetLastError()));
  1555. goto GrantUserAccessToFile_Exit;
  1556. }
  1557. // using the "localized" name, build explicit access structure
  1558. BuildExplicitAccessWithName(&explicitaccess,lpGuestGrpName,AccessMask,option,InheritFlag);
  1559. explicitaccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
  1560. explicitaccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
  1561. explicitaccess.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
  1562. if (_tcsicmp(TrusteeName, _T("administrators")) == 0 || _tcsicmp(TrusteeName, _T("everyone")) == 0)
  1563. {
  1564. explicitaccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
  1565. }
  1566. // set the acl with this certain access stuff
  1567. dwError = SetEntriesInAcl(1,&explicitaccess,ExistingDacl,&NewAcl);
  1568. if(dwError != ERROR_SUCCESS)
  1569. {
  1570. NewAcl = NULL;
  1571. // it may error because the user is already there
  1572. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("GrantUserAccessToFile: SetEntriesInAcl failed on %s. for trustee=%s. err=0x%x\n"),FileName,explicitaccess.Trustee.ptstrName,dwError));
  1573. goto GrantUserAccessToFile_Exit;
  1574. }
  1575. // apply new security to file
  1576. dwError = SetNamedSecurityInfo(FileName,SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,NewAcl,NULL);
  1577. if(dwError != ERROR_SUCCESS)
  1578. {
  1579. iisDebugOut((LOG_TYPE_WARN, _T("GrantUserAccessToFile: SetNamedSecurityInfo failed on %s. err=0x%x\n"),FileName,dwError));
  1580. goto GrantUserAccessToFile_Exit;
  1581. }
  1582. // everything is kool!
  1583. dwError = ERROR_SUCCESS;
  1584. GrantUserAccessToFile_Exit:
  1585. if(NewAcl != NULL){LocalFree(NewAcl);}
  1586. if(psd != NULL){LocalFree(psd);}
  1587. if (principalSID)
  1588. {
  1589. if (bWellKnownSID)
  1590. FreeSid (principalSID);
  1591. else
  1592. free (principalSID);
  1593. }
  1594. iisDebugOut_End1(_T("GrantUserAccessToFile"),FileName);
  1595. return dwError;
  1596. }
  1597. #ifndef _CHICAGO_
  1598. DWORD SetDirectorySecurity(
  1599. IN LPCTSTR szDirPath,
  1600. IN LPCTSTR szPrincipal,
  1601. IN INT iAceType,
  1602. IN DWORD dwAccessMask,
  1603. IN DWORD dwInheritMask,
  1604. IN BOOL DontInheritFromParentAndOverWriteAccess
  1605. )
  1606. {
  1607. DWORD dwStatus = ERROR_FILE_NOT_FOUND;
  1608. if (ACCESS_ALLOWED_ACE_TYPE == iAceType || ACCESS_DENIED_ACE_TYPE == iAceType)
  1609. {
  1610. if (IsFileExist(szDirPath) == TRUE)
  1611. {
  1612. PSID principalSID = NULL;
  1613. BOOL bWellKnownSID = FALSE;
  1614. dwStatus = GetPrincipalSID((LPTSTR) szPrincipal, &principalSID, &bWellKnownSID);
  1615. if (dwStatus == ERROR_SUCCESS)
  1616. {
  1617. PSECURITY_DESCRIPTOR psd = NULL;
  1618. dwStatus = SetAccessOnDirOrFile((TCHAR*) szDirPath,principalSID,iAceType,dwAccessMask,dwInheritMask,&psd,DontInheritFromParentAndOverWriteAccess);
  1619. //DumpAdminACL(INVALID_HANDLE_VALUE,psd);
  1620. if (psd) {free(psd);psd=NULL;}
  1621. }
  1622. }
  1623. }
  1624. return dwStatus;
  1625. }
  1626. // -------------------------------------------------------------------------------------
  1627. // Function: RemovePrincipalFromFileAcl
  1628. //
  1629. // Remove a Access Control Entry from an Access Control List for a file/directory for a
  1630. // particular SID
  1631. //
  1632. // -------------------------------------------------------------------------------------
  1633. DWORD RemovePrincipalFromFileAcl(IN TCHAR *pszFile,IN LPTSTR szPrincipal)
  1634. {
  1635. PACL pdacl;
  1636. SECURITY_DESCRIPTOR_CONTROL sdc;
  1637. PSECURITY_DESCRIPTOR psdRelative = NULL;
  1638. PSECURITY_DESCRIPTOR psdAbsolute = NULL;
  1639. DWORD cbSize = 0;
  1640. BOOL bRes = 0;
  1641. DWORD dwSecurityDescriptorRevision;
  1642. BOOL fHasDacl = FALSE;
  1643. BOOL fDaclDefaulted = FALSE;
  1644. BOOL bUserExistsToBeDeleted;
  1645. DWORD dwError = ERROR_SUCCESS;
  1646. // get the size of the security descriptor
  1647. bRes = GetFileSecurity(pszFile,DACL_SECURITY_INFORMATION,psdRelative,0,&cbSize);
  1648. if ( !bRes )
  1649. {
  1650. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  1651. {
  1652. psdRelative = malloc(cbSize);
  1653. if (!psdRelative)
  1654. {
  1655. return ERROR_INSUFFICIENT_BUFFER;
  1656. }
  1657. bRes = GetFileSecurity(pszFile,DACL_SECURITY_INFORMATION,psdRelative,cbSize,&cbSize);
  1658. }
  1659. }
  1660. if (!bRes)
  1661. {
  1662. if (psdRelative)
  1663. {
  1664. free(psdRelative);
  1665. }
  1666. return (GetLastError());
  1667. }
  1668. // get security descriptor control from the security descriptor
  1669. if (!GetSecurityDescriptorControl(psdRelative, (PSECURITY_DESCRIPTOR_CONTROL) &sdc,(LPDWORD) &dwSecurityDescriptorRevision))
  1670. {
  1671. dwError = GetLastError();
  1672. }
  1673. else if (SE_DACL_PRESENT & sdc)
  1674. {
  1675. // Acl's are present, so we will attempt to remove the one passes in.
  1676. if (GetSecurityDescriptorDacl(psdRelative, (LPBOOL) &fHasDacl,(PACL *) &pdacl, (LPBOOL) &fDaclDefaulted))
  1677. {
  1678. // Remove ACE from Acl
  1679. dwError = RemovePrincipalFromACL(pdacl,szPrincipal,&bUserExistsToBeDeleted);
  1680. if (dwError == ERROR_SUCCESS)
  1681. {
  1682. psdAbsolute = (PSECURITY_DESCRIPTOR) malloc(GetSecurityDescriptorLength(psdRelative));
  1683. if (psdAbsolute)
  1684. {
  1685. if ( !(InitializeSecurityDescriptor(psdAbsolute, SECURITY_DESCRIPTOR_REVISION)) ||
  1686. !(SetSecurityDescriptorDacl(psdAbsolute, TRUE, pdacl, fDaclDefaulted)) ||
  1687. !(IsValidSecurityDescriptor(psdAbsolute)) ||
  1688. !(SetFileSecurity(pszFile,(SECURITY_INFORMATION)(DACL_SECURITY_INFORMATION),psdAbsolute))
  1689. )
  1690. {
  1691. dwError = GetLastError();
  1692. }
  1693. if (psdAbsolute)
  1694. {
  1695. free(psdAbsolute);
  1696. }
  1697. }
  1698. else
  1699. {
  1700. dwError = ERROR_INSUFFICIENT_BUFFER;
  1701. }
  1702. }
  1703. }
  1704. else
  1705. {
  1706. dwError = GetLastError();
  1707. }
  1708. }
  1709. if (psdRelative)
  1710. {
  1711. free(psdRelative);
  1712. }
  1713. return dwError;
  1714. }
  1715. DWORD SetAccessOnDirOrFile(IN TCHAR *pszFile,PSID psidGroup,INT iAceType,DWORD dwAccessMask,DWORD dwInheritMask,PSECURITY_DESCRIPTOR* ppsd,BOOL DontInheritFromParentAndOverWriteAccess)
  1716. {
  1717. PSECURITY_DESCRIPTOR psdAbsolute = NULL;
  1718. PACL pdacl;
  1719. DWORD cbSecurityDescriptor = 0;
  1720. DWORD dwSecurityDescriptorRevision;
  1721. DWORD cbDacl = 0;
  1722. SECURITY_DESCRIPTOR_CONTROL sdc;
  1723. PACL pdaclNew = NULL;
  1724. DWORD cbAddDaclLength = 0;
  1725. BOOL fAceFound = FALSE;
  1726. BOOL fHasDacl = FALSE;
  1727. BOOL fDaclDefaulted = FALSE;
  1728. ACCESS_ALLOWED_ACE* pAce;
  1729. DWORD i;
  1730. BOOL fAceForGroupPresent = FALSE;
  1731. DWORD dwMask;
  1732. PSECURITY_DESCRIPTOR psdRelative = NULL;
  1733. DWORD cbSize = 0;
  1734. BOOL bRes = 0;
  1735. // get the size of the security descriptor
  1736. bRes = GetFileSecurity(pszFile,DACL_SECURITY_INFORMATION,psdRelative,0,&cbSize);
  1737. DWORD dwError = GetLastError();
  1738. if (ERROR_INSUFFICIENT_BUFFER == dwError)
  1739. {
  1740. psdRelative = malloc(cbSize);
  1741. if (!psdRelative)
  1742. {
  1743. return ERROR_INSUFFICIENT_BUFFER;
  1744. }
  1745. bRes = GetFileSecurity(pszFile,DACL_SECURITY_INFORMATION,psdRelative,cbSize,&cbSize);
  1746. }
  1747. if (!bRes)
  1748. {
  1749. if (psdRelative){free(psdRelative);}
  1750. return (GetLastError());
  1751. }
  1752. // get security descriptor control from the security descriptor
  1753. if (!GetSecurityDescriptorControl(psdRelative, (PSECURITY_DESCRIPTOR_CONTROL) &sdc,(LPDWORD) &dwSecurityDescriptorRevision))
  1754. {
  1755. return (GetLastError());
  1756. }
  1757. // check if DACL is present
  1758. if (SE_DACL_PRESENT & sdc)
  1759. {
  1760. ACE_HEADER *pAceHeader;
  1761. // get dacl
  1762. if (!GetSecurityDescriptorDacl(psdRelative, (LPBOOL) &fHasDacl,(PACL *) &pdacl, (LPBOOL) &fDaclDefaulted))
  1763. {
  1764. return ( GetLastError());
  1765. }
  1766. // check if pdacl is null
  1767. // if it is then security is wide open -- this could be a fat drive.
  1768. if (NULL == pdacl)
  1769. {
  1770. return ERROR_SUCCESS;
  1771. }
  1772. // get dacl length
  1773. cbDacl = pdacl->AclSize;
  1774. // now check if SID's ACE is there
  1775. for (i = 0; i < pdacl->AceCount; i++)
  1776. {
  1777. if (!GetAce(pdacl, i, (LPVOID *) &pAce))
  1778. {
  1779. return ( GetLastError());
  1780. }
  1781. pAceHeader = (ACE_HEADER *)pAce;
  1782. // check if group sid is already there
  1783. if (EqualSid((PSID) &(pAce->SidStart), psidGroup))
  1784. {
  1785. if (ACCESS_DENIED_ACE_TYPE == iAceType)
  1786. {
  1787. if (pAceHeader->AceType == ACCESS_DENIED_ACE_TYPE)
  1788. {
  1789. // If the correct access is present, return success
  1790. if ((pAce->Mask & dwAccessMask) == dwAccessMask)
  1791. {
  1792. return ERROR_SUCCESS;
  1793. }
  1794. fAceForGroupPresent = TRUE;
  1795. break;
  1796. }
  1797. }
  1798. else
  1799. {
  1800. if (pAceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
  1801. {
  1802. if (FALSE == DontInheritFromParentAndOverWriteAccess)
  1803. {
  1804. // If the correct access is present, return success
  1805. if ((pAce->Mask & dwAccessMask) == dwAccessMask)
  1806. {
  1807. return ERROR_SUCCESS;
  1808. }
  1809. }
  1810. fAceForGroupPresent = TRUE;
  1811. break;
  1812. }
  1813. }
  1814. }
  1815. }
  1816. // if the group did not exist, we will need to add room
  1817. // for another ACE
  1818. if (!fAceForGroupPresent)
  1819. {
  1820. // get length of new DACL
  1821. cbAddDaclLength = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(psidGroup);
  1822. }
  1823. }
  1824. else
  1825. {
  1826. // get length of new DACL
  1827. cbAddDaclLength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid (psidGroup);
  1828. }
  1829. // get memory needed for new DACL
  1830. //pdaclNew = (PACL) malloc (cbDacl + cbAddDaclLength);
  1831. pdaclNew = (PACL) LocalAlloc(LMEM_FIXED, cbDacl + cbAddDaclLength);
  1832. if (!pdaclNew)
  1833. {
  1834. return (GetLastError());
  1835. }
  1836. // get the sd length
  1837. cbSecurityDescriptor = GetSecurityDescriptorLength(psdRelative);
  1838. // get memory for new SD
  1839. psdAbsolute = (PSECURITY_DESCRIPTOR) malloc(cbSecurityDescriptor + cbAddDaclLength);
  1840. if (!psdAbsolute)
  1841. {
  1842. dwError = GetLastError();
  1843. goto ErrorExit;
  1844. }
  1845. // change self-relative SD to absolute by making new SD
  1846. if (!InitializeSecurityDescriptor(psdAbsolute, SECURITY_DESCRIPTOR_REVISION))
  1847. {
  1848. dwError = GetLastError();
  1849. goto ErrorExit;
  1850. }
  1851. // init new DACL
  1852. if (!InitializeAcl(pdaclNew, cbDacl + cbAddDaclLength, ACL_REVISION))
  1853. {
  1854. dwError = GetLastError();
  1855. goto ErrorExit;
  1856. }
  1857. // Add a new ACE for our SID if one was not already present
  1858. if ( (!fAceForGroupPresent) && (ACCESS_DENIED_ACE_TYPE == iAceType) )
  1859. {
  1860. if (!AddAccessDeniedAce(pdaclNew, ACL_REVISION, dwAccessMask,psidGroup))
  1861. {
  1862. dwError = GetLastError();
  1863. goto ErrorExit;
  1864. }
  1865. }
  1866. // now add in all of the ACEs into the new DACL (if org DACL is there)
  1867. if (SE_DACL_PRESENT & sdc)
  1868. {
  1869. ACE_HEADER *pAceHeader;
  1870. DWORD aceHeader_Flags = 0;
  1871. for (i = 0; i < pdacl->AceCount; i++)
  1872. {
  1873. // get ace from original dacl
  1874. if (!GetAce(pdacl, i, (LPVOID*) &pAce))
  1875. {
  1876. dwError = GetLastError();
  1877. goto ErrorExit;
  1878. }
  1879. pAceHeader = (ACE_HEADER *)pAce;
  1880. aceHeader_Flags = pAce->Header.AceFlags;
  1881. if (pAceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
  1882. {
  1883. dwMask = pAce->Mask;
  1884. if (ACCESS_ALLOWED_ACE_TYPE == iAceType)
  1885. {
  1886. // If an ACE for our SID exists, we just need to bump
  1887. // up the access level instead of creating a new ACE
  1888. if (EqualSid((PSID) &(pAce->SidStart), psidGroup))
  1889. {
  1890. if (FALSE == DontInheritFromParentAndOverWriteAccess)
  1891. {
  1892. dwMask = dwAccessMask | pAce->Mask;
  1893. }
  1894. else
  1895. {
  1896. dwMask = dwAccessMask;
  1897. aceHeader_Flags = dwInheritMask;
  1898. }
  1899. }
  1900. }
  1901. if (!AddAccessAllowedAceEx(pdaclNew, ACL_REVISION, aceHeader_Flags,dwMask,(PSID) &(pAce->SidStart)))
  1902. {
  1903. dwError = GetLastError();
  1904. goto ErrorExit;
  1905. }
  1906. }
  1907. else if (pAceHeader->AceType == ACCESS_DENIED_ACE_TYPE)
  1908. {
  1909. dwMask = pAce->Mask;
  1910. if (ACCESS_DENIED_ACE_TYPE == iAceType)
  1911. {
  1912. // If an ACE for our SID exists, we just need to bump
  1913. // up the access level instead of creating a new ACE
  1914. if (EqualSid((PSID) &(pAce->SidStart), psidGroup))
  1915. {
  1916. dwMask = dwAccessMask | pAce->Mask;
  1917. }
  1918. }
  1919. if (!AddAccessDeniedAceEx(pdaclNew, ACL_REVISION, pAce->Header.AceFlags,dwMask,(PSID) &(pAce->SidStart)))
  1920. {
  1921. dwError = GetLastError();
  1922. goto ErrorExit;
  1923. }
  1924. }
  1925. else
  1926. {
  1927. // copy denied or audit ace.
  1928. if (!AddAce(pdaclNew, ACL_REVISION, 0xFFFFFFFF,pAce, pAceHeader->AceSize ))
  1929. {
  1930. dwError = GetLastError();
  1931. goto ErrorExit;
  1932. }
  1933. }
  1934. //iisDebugOut((LOG_TYPE_TRACE, _T("OrgAce[%d]=0x%x\n"),i,pAce->Header.AceFlags));
  1935. }
  1936. }
  1937. // Add a new ACE for our SID if one was not already present
  1938. if ( (!fAceForGroupPresent) && (ACCESS_ALLOWED_ACE_TYPE == iAceType) )
  1939. {
  1940. if (!AddAccessAllowedAce(pdaclNew, ACL_REVISION, dwAccessMask,psidGroup))
  1941. {
  1942. dwError = GetLastError();
  1943. goto ErrorExit;
  1944. }
  1945. }
  1946. // change the header on an existing ace to have inherit
  1947. for (i = 0; i < pdaclNew->AceCount; i++)
  1948. {
  1949. if (!GetAce(pdaclNew, i, (LPVOID *) &pAce))
  1950. {
  1951. return ( GetLastError());
  1952. }
  1953. // CONTAINER_INHERIT_ACE = Other containers that are contained by the primary object inherit the entry.
  1954. // INHERIT_ONLY_ACE = The ACE does not apply to the primary object to which the ACL is attached, but objects contained by the primary object inherit the entry.
  1955. // NO_PROPAGATE_INHERIT_ACE = The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE flags are not propagated to an inherited entry.
  1956. // OBJECT_INHERIT_ACE = Noncontainer objects contained by the primary object inherit the entry.
  1957. // SUB_CONTAINERS_ONLY_INHERIT = Other containers that are contained by the primary object inherit the entry. This flag corresponds to the CONTAINER_INHERIT_ACE flag.
  1958. // SUB_OBJECTS_ONLY_INHERIT = Noncontainer objects contained by the primary object inherit the entry. This flag corresponds to the OBJECT_INHERIT_ACE flag.
  1959. // SUB_CONTAINERS_AND_OBJECTS_INHERIT = Both containers and noncontainer objects that are contained by the primary object inherit the entry. This flag corresponds to the combination of the CONTAINER_INHERIT_ACE and OBJECT_INHERIT_ACE flags.
  1960. //iisDebugOut((LOG_TYPE_TRACE, _T("NewAce[%d]=0x%x\n"),i,pAce->Header.AceFlags));
  1961. // if it's our SID, then change the header to be inherited
  1962. if (EqualSid((PSID) &(pAce->SidStart), psidGroup))
  1963. {
  1964. pAce->Header.AceFlags |= dwInheritMask;
  1965. }
  1966. }
  1967. if (TRUE == DontInheritFromParentAndOverWriteAccess)
  1968. {
  1969. // Reorder ace's
  1970. // -------------
  1971. // ugly.
  1972. dwError = ReOrderACL(&pdaclNew);
  1973. if (ERROR_SUCCESS != dwError)
  1974. {
  1975. goto ErrorExit;
  1976. }
  1977. }
  1978. // check if everything went ok
  1979. if (!IsValidAcl(pdaclNew))
  1980. {
  1981. dwError = ERROR_INVALID_ACL;
  1982. goto ErrorExit;
  1983. }
  1984. // now set security descriptor DACL
  1985. if (!SetSecurityDescriptorDacl(psdAbsolute, TRUE, pdaclNew, fDaclDefaulted))
  1986. {
  1987. dwError = GetLastError();
  1988. goto ErrorExit;
  1989. }
  1990. // check if everything went ok
  1991. if (!IsValidSecurityDescriptor(psdAbsolute))
  1992. {
  1993. dwError = ERROR_INVALID_SECURITY_DESCR;
  1994. goto ErrorExit;
  1995. }
  1996. // now set the reg key security (this will overwrite any existing security)
  1997. bRes = SetFileSecurity(pszFile,(SECURITY_INFORMATION)(DACL_SECURITY_INFORMATION),psdAbsolute);
  1998. if (bRes)
  1999. {
  2000. dwError = ERROR_SUCCESS;
  2001. }
  2002. if (ppsd)
  2003. {
  2004. *ppsd = psdRelative;
  2005. }
  2006. ErrorExit:
  2007. // free memory
  2008. if (psdAbsolute)
  2009. {
  2010. free (psdAbsolute);
  2011. if (pdaclNew)
  2012. {
  2013. //free((VOID*) pdaclNew);
  2014. LocalFree(pdaclNew);pdaclNew=NULL;
  2015. }
  2016. }
  2017. return dwError;
  2018. }
  2019. //+--------------------------------------------------------------------------
  2020. //
  2021. // Function: SetAccessOnRegKey
  2022. //
  2023. // Purpose: Adds access for a specified SID to a registry key
  2024. //
  2025. // Arguments:
  2026. // hkey [in] The registry key that will receive the
  2027. // modified security descriptor
  2028. // psidGroup [in] The SID (in self-relative mode) that will be
  2029. // granted access to the key
  2030. // dwAccessMask [in] The access level to grant
  2031. // ppsd [out] The previous security descriptor
  2032. //
  2033. // Returns: DWORD. ERROR_SUCCESS or a failure code from winerror.h
  2034. //
  2035. //+--------------------------------------------------------------------------
  2036. DWORD
  2037. SetAccessOnRegKey(HKEY hkey, PSID psidGroup,
  2038. DWORD dwAccessMask,
  2039. DWORD dwInheritMask,
  2040. PSECURITY_DESCRIPTOR* ppsd)
  2041. {
  2042. PSECURITY_DESCRIPTOR psdAbsolute = NULL;
  2043. PACL pdacl;
  2044. DWORD cbSecurityDescriptor = 0;
  2045. DWORD dwSecurityDescriptorRevision;
  2046. DWORD cbDacl = 0;
  2047. SECURITY_DESCRIPTOR_CONTROL sdc;
  2048. PACL pdaclNew = NULL;
  2049. DWORD cbAddDaclLength = 0;
  2050. BOOL fAceFound = FALSE;
  2051. BOOL fHasDacl = FALSE;
  2052. BOOL fDaclDefaulted = FALSE;
  2053. ACCESS_ALLOWED_ACE* pAce;
  2054. DWORD i;
  2055. BOOL fAceForGroupPresent = FALSE;
  2056. DWORD dwMask;
  2057. PSECURITY_DESCRIPTOR psdRelative = NULL;
  2058. DWORD cbSize = 0;
  2059. // Get the current security descriptor for hkey
  2060. //
  2061. DWORD dwError = RegGetKeySecurity(hkey, DACL_SECURITY_INFORMATION, psdRelative, &cbSize);
  2062. if (ERROR_INSUFFICIENT_BUFFER == dwError)
  2063. {
  2064. psdRelative = malloc(cbSize);
  2065. if (!psdRelative)
  2066. {
  2067. return ERROR_INSUFFICIENT_BUFFER;
  2068. }
  2069. dwError = RegGetKeySecurity(hkey, DACL_SECURITY_INFORMATION, psdRelative, &cbSize);
  2070. }
  2071. // get security descriptor control from the security descriptor
  2072. if ( (!psdRelative) ||
  2073. (dwError != ERROR_SUCCESS) ||
  2074. (!GetSecurityDescriptorControl(psdRelative, (PSECURITY_DESCRIPTOR_CONTROL) &sdc,(LPDWORD) &dwSecurityDescriptorRevision))
  2075. )
  2076. {
  2077. return (GetLastError());
  2078. }
  2079. // check if DACL is present
  2080. if (SE_DACL_PRESENT & sdc)
  2081. {
  2082. ACE_HEADER *pAceHeader;
  2083. // get dacl
  2084. if (!GetSecurityDescriptorDacl(psdRelative, (LPBOOL) &fHasDacl,(PACL *) &pdacl, (LPBOOL) &fDaclDefaulted))
  2085. {
  2086. return ( GetLastError());
  2087. }
  2088. // check if pdacl is null
  2089. // if it is then security is wide open -- this could be a fat drive.
  2090. if (NULL == pdacl)
  2091. {
  2092. return ERROR_SUCCESS;
  2093. }
  2094. // get dacl length
  2095. cbDacl = pdacl->AclSize;
  2096. // now check if SID's ACE is there
  2097. for (i = 0; i < pdacl->AceCount; i++)
  2098. {
  2099. if (!GetAce(pdacl, i, (LPVOID *) &pAce))
  2100. {
  2101. return ( GetLastError());
  2102. }
  2103. pAceHeader = (ACE_HEADER *)pAce;
  2104. if (pAceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
  2105. {
  2106. // check if group sid is already there
  2107. if (EqualSid((PSID) &(pAce->SidStart), psidGroup))
  2108. {
  2109. // If the correct access is present, return success
  2110. if ((pAce->Mask & dwAccessMask) == dwAccessMask)
  2111. {
  2112. return ERROR_SUCCESS;
  2113. }
  2114. fAceForGroupPresent = TRUE;
  2115. break;
  2116. }
  2117. }
  2118. }
  2119. // if the group did not exist, we will need to add room
  2120. // for another ACE
  2121. if (!fAceForGroupPresent)
  2122. {
  2123. // get length of new DACL
  2124. cbAddDaclLength = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(psidGroup);
  2125. }
  2126. }
  2127. else
  2128. {
  2129. // get length of new DACL
  2130. cbAddDaclLength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid (psidGroup);
  2131. }
  2132. // get memory needed for new DACL
  2133. //pdaclNew = (PACL) malloc (cbDacl + cbAddDaclLength);
  2134. pdaclNew = (PACL) LocalAlloc(LMEM_FIXED, cbDacl + cbAddDaclLength);
  2135. if (!pdaclNew)
  2136. {
  2137. return (GetLastError());
  2138. }
  2139. // get the sd length
  2140. cbSecurityDescriptor = GetSecurityDescriptorLength(psdRelative);
  2141. // get memory for new SD
  2142. psdAbsolute = (PSECURITY_DESCRIPTOR) malloc(cbSecurityDescriptor + cbAddDaclLength);
  2143. if (!psdAbsolute)
  2144. {
  2145. dwError = GetLastError();
  2146. goto ErrorExit;
  2147. }
  2148. // change self-relative SD to absolute by making new SD
  2149. if (!InitializeSecurityDescriptor(psdAbsolute, SECURITY_DESCRIPTOR_REVISION))
  2150. {
  2151. dwError = GetLastError();
  2152. goto ErrorExit;
  2153. }
  2154. // init new DACL
  2155. if (!InitializeAcl(pdaclNew, cbDacl + cbAddDaclLength, ACL_REVISION))
  2156. {
  2157. dwError = GetLastError();
  2158. goto ErrorExit;
  2159. }
  2160. // now add in all of the ACEs into the new DACL (if org DACL is there)
  2161. if (SE_DACL_PRESENT & sdc)
  2162. {
  2163. ACE_HEADER *pAceHeader;
  2164. for (i = 0; i < pdacl->AceCount; i++)
  2165. {
  2166. // get ace from original dacl
  2167. if (!GetAce(pdacl, i, (LPVOID*) &pAce))
  2168. {
  2169. dwError = GetLastError();
  2170. goto ErrorExit;
  2171. }
  2172. pAceHeader = (ACE_HEADER *)pAce;
  2173. if (pAceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
  2174. {
  2175. // If an ACE for our SID exists, we just need to bump
  2176. // up the access level instead of creating a new ACE
  2177. //
  2178. if (EqualSid((PSID) &(pAce->SidStart), psidGroup))
  2179. {
  2180. dwMask = dwAccessMask | pAce->Mask;
  2181. }
  2182. else
  2183. {
  2184. dwMask = pAce->Mask;
  2185. }
  2186. //iisDebugOut((LOG_TYPE_TRACE, _T("OrgAce[%d]=0x%x\n"),i,pAce->Header.AceFlags));
  2187. // now add ace to new dacl
  2188. if (!AddAccessAllowedAceEx(pdaclNew, ACL_REVISION, pAce->Header.AceFlags,dwMask,(PSID) &(pAce->SidStart)))
  2189. {
  2190. dwError = GetLastError();
  2191. goto ErrorExit;
  2192. }
  2193. }
  2194. else
  2195. {
  2196. // copy denied or audit ace.
  2197. if (!AddAce(pdaclNew, ACL_REVISION, 0xFFFFFFFF, pAce, pAceHeader->AceSize ))
  2198. {
  2199. dwError = GetLastError();
  2200. goto ErrorExit;
  2201. }
  2202. }
  2203. }
  2204. }
  2205. // Add a new ACE for our SID if one was not already present
  2206. if (!fAceForGroupPresent)
  2207. {
  2208. // now add new ACE to new DACL
  2209. if (!AddAccessAllowedAce(pdaclNew, ACL_REVISION, dwAccessMask,psidGroup))
  2210. {
  2211. dwError = GetLastError();
  2212. goto ErrorExit;
  2213. }
  2214. }
  2215. // change the header on an existing ace to have inherit
  2216. for (i = 0; i < pdaclNew->AceCount; i++)
  2217. {
  2218. if (!GetAce(pdaclNew, i, (LPVOID *) &pAce))
  2219. {
  2220. return ( GetLastError());
  2221. }
  2222. // CONTAINER_INHERIT_ACE = Other containers that are contained by the primary object inherit the entry.
  2223. // INHERIT_ONLY_ACE = The ACE does not apply to the primary object to which the ACL is attached, but objects contained by the primary object inherit the entry.
  2224. // NO_PROPAGATE_INHERIT_ACE = The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE flags are not propagated to an inherited entry.
  2225. // OBJECT_INHERIT_ACE = Noncontainer objects contained by the primary object inherit the entry.
  2226. // SUB_CONTAINERS_ONLY_INHERIT = Other containers that are contained by the primary object inherit the entry. This flag corresponds to the CONTAINER_INHERIT_ACE flag.
  2227. // SUB_OBJECTS_ONLY_INHERIT = Noncontainer objects contained by the primary object inherit the entry. This flag corresponds to the OBJECT_INHERIT_ACE flag.
  2228. // SUB_CONTAINERS_AND_OBJECTS_INHERIT = Both containers and noncontainer objects that are contained by the primary object inherit the entry. This flag corresponds to the combination of the CONTAINER_INHERIT_ACE and OBJECT_INHERIT_ACE flags.
  2229. //iisDebugOut((LOG_TYPE_TRACE, _T("NewAce[%d]=0x%x\n"),i,pAce->Header.AceFlags));
  2230. // if it's our SID, then change the header to be inherited
  2231. if (EqualSid((PSID) &(pAce->SidStart), psidGroup))
  2232. {
  2233. //pAce->Header.AceFlags |= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE | INHERITED_ACE;
  2234. //pAce->Header.AceFlags |= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE | dwInheritMask;
  2235. pAce->Header.AceFlags |= dwInheritMask;
  2236. }
  2237. }
  2238. // ugly.
  2239. dwError = ReOrderACL(&pdaclNew);
  2240. if (ERROR_SUCCESS != dwError)
  2241. {
  2242. goto ErrorExit;
  2243. }
  2244. // check if everything went ok
  2245. if (!IsValidAcl(pdaclNew))
  2246. {
  2247. dwError = ERROR_INVALID_ACL;
  2248. goto ErrorExit;
  2249. }
  2250. // now set security descriptor DACL
  2251. if (!SetSecurityDescriptorDacl(psdAbsolute, TRUE, pdaclNew, fDaclDefaulted))
  2252. {
  2253. dwError = GetLastError();
  2254. goto ErrorExit;
  2255. }
  2256. // check if everything went ok
  2257. if (!IsValidSecurityDescriptor(psdAbsolute))
  2258. {
  2259. dwError = ERROR_INVALID_SECURITY_DESCR;
  2260. goto ErrorExit;
  2261. }
  2262. // now set the reg key security (this will overwrite any
  2263. // existing security)
  2264. dwError = RegSetKeySecurity(hkey, (SECURITY_INFORMATION)(DACL_SECURITY_INFORMATION), psdAbsolute);
  2265. if (ppsd)
  2266. {
  2267. *ppsd = psdRelative;
  2268. }
  2269. ErrorExit:
  2270. // free memory
  2271. if (psdAbsolute)
  2272. {
  2273. free (psdAbsolute);
  2274. if (pdaclNew)
  2275. {
  2276. //free((VOID*) pdaclNew);
  2277. LocalFree(pdaclNew);pdaclNew=NULL;
  2278. }
  2279. }
  2280. return dwError;
  2281. }
  2282. BOOL
  2283. AddUserAccessToSD(
  2284. IN PSECURITY_DESCRIPTOR pSd,
  2285. IN PSID pSid,
  2286. IN DWORD NewAccess,
  2287. IN UCHAR TheAceType,
  2288. OUT PSECURITY_DESCRIPTOR *ppSdNew
  2289. )
  2290. {
  2291. ULONG i;
  2292. BOOL bReturn = FALSE;
  2293. BOOL Result;
  2294. BOOL DaclPresent;
  2295. BOOL DaclDefaulted;
  2296. DWORD Length;
  2297. DWORD NewAclLength;
  2298. ACCESS_ALLOWED_ACE* OldAce;
  2299. PACE_HEADER NewAce;
  2300. ACL_SIZE_INFORMATION AclInfo;
  2301. PACL Dacl = NULL;
  2302. PACL NewDacl = NULL;
  2303. PACL NewAceDacl = NULL;
  2304. PSECURITY_DESCRIPTOR NewSD = NULL;
  2305. PSECURITY_DESCRIPTOR OldSD = NULL;
  2306. PSECURITY_DESCRIPTOR outpSD = NULL;
  2307. DWORD cboutpSD = 0;
  2308. BOOL fAceForGroupPresent = FALSE;
  2309. DWORD dwMask;
  2310. OldSD = pSd;
  2311. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("AddUserAccessToSD start\n")));
  2312. // only do if the ace is allowed/denied
  2313. if (ACCESS_ALLOWED_ACE_TYPE != TheAceType && ACCESS_DENIED_ACE_TYPE != TheAceType)
  2314. {
  2315. iisDebugOut((LOG_TYPE_TRACE, _T("AddUserAccessToSD useless param\n")));
  2316. goto AddUserAccessToSD_Exit;
  2317. }
  2318. // Convert SecurityDescriptor to absolute format. It generates
  2319. // a new SecurityDescriptor for its output which we must free.
  2320. if ( !MakeAbsoluteCopyFromRelative(OldSD, &NewSD) )
  2321. {
  2322. iisDebugOut((LOG_TYPE_ERROR, _T("MakeAbsoluteCopyFromRelative failed\n")));
  2323. goto AddUserAccessToSD_Exit;
  2324. }
  2325. // Must get DACL pointer from new (absolute) SD
  2326. if(!GetSecurityDescriptorDacl(NewSD,&DaclPresent,&Dacl,&DaclDefaulted))
  2327. {
  2328. iisDebugOut((LOG_TYPE_ERROR, _T("GetSecurityDescriptorDacl failed with 0x%x\n"),GetLastError()));
  2329. goto AddUserAccessToSD_Exit;
  2330. }
  2331. // If no DACL, no need to add the user since no DACL
  2332. // means all accesss
  2333. if( !DaclPresent )
  2334. {
  2335. bReturn = TRUE;
  2336. goto AddUserAccessToSD_Exit;
  2337. }
  2338. // Code can return DaclPresent, but a NULL which means
  2339. // a NULL Dacl is present. This allows all access to the object.
  2340. if( Dacl == NULL )
  2341. {
  2342. bReturn = TRUE;
  2343. goto AddUserAccessToSD_Exit;
  2344. }
  2345. // Get the current ACL's size
  2346. if( !GetAclInformation(Dacl,&AclInfo,sizeof(AclInfo),AclSizeInformation) )
  2347. {
  2348. iisDebugOut((LOG_TYPE_ERROR, _T("GetAclInformation failed with 0x%x\n"),GetLastError()));
  2349. goto AddUserAccessToSD_Exit;
  2350. }
  2351. // Check if access is already there
  2352. // --------------------------------
  2353. // Check to see if this SID already exists in there
  2354. // if it does (and it has the right access we want) then forget it, we don't have to do anything more.
  2355. for (i = 0; i < AclInfo.AceCount; i++)
  2356. {
  2357. ACE_HEADER *pAceHeader;
  2358. ACCESS_ALLOWED_ACE* pAce = NULL;
  2359. if (!GetAce(Dacl, i, (LPVOID *) &pAce))
  2360. {
  2361. iisDebugOut((LOG_TYPE_ERROR, _T("GetAce failed with 0x%x\n"),GetLastError()));
  2362. goto AddUserAccessToSD_Exit;
  2363. }
  2364. pAceHeader = (ACE_HEADER *)pAce;
  2365. // check if group sid is already there
  2366. if (EqualSid((PSID) &(pAce->SidStart), pSid))
  2367. {
  2368. if (pAceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
  2369. {
  2370. // If the correct access is present, return success
  2371. if ((pAce->Mask & NewAccess) == NewAccess)
  2372. {
  2373. //iisDebugOut((LOG_TYPE_TRACE, _T("AddUserAccessToSD:correct access already present. Exiting,1=0x%x,2=0x%x,3=0x%x\n"),pAce->Mask,NewAccess,(pAce->Mask & NewAccess)));
  2374. bReturn = TRUE;
  2375. goto AddUserAccessToSD_Exit;
  2376. }
  2377. else
  2378. {
  2379. // the ace that exist doesn't have the permissions that we want.
  2380. // If an ACE for our SID exists, we just need to bump
  2381. // up the access level instead of creating a new ACE
  2382. fAceForGroupPresent = TRUE;
  2383. }
  2384. }
  2385. break;
  2386. }
  2387. }
  2388. // If we have to create a new ACE
  2389. // (because our user isn't listed in the existing ACL)
  2390. // then let's Create a new ACL to put the new access allowed ACE on
  2391. // --------------------------------
  2392. if (!fAceForGroupPresent)
  2393. {
  2394. NewAclLength = sizeof(ACL) +
  2395. sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG) +
  2396. GetLengthSid( pSid );
  2397. NewAceDacl = (PACL) LocalAlloc( LMEM_FIXED, NewAclLength );
  2398. if ( NewAceDacl == NULL )
  2399. {
  2400. iisDebugOut((LOG_TYPE_ERROR, _T("LocalAlloc failed\n")));
  2401. goto AddUserAccessToSD_Exit;
  2402. }
  2403. if(!InitializeAcl( NewAceDacl, NewAclLength, ACL_REVISION ))
  2404. {
  2405. iisDebugOut((LOG_TYPE_ERROR, _T("InitializeAcl failed with 0x%x\n"),GetLastError()));
  2406. goto AddUserAccessToSD_Exit;
  2407. }
  2408. if (ACCESS_DENIED_ACE_TYPE == TheAceType)
  2409. {
  2410. Result = AddAccessDeniedAce(NewAceDacl,ACL_REVISION,NewAccess,pSid);
  2411. }
  2412. else
  2413. {
  2414. Result = AddAccessAllowedAce(NewAceDacl,ACL_REVISION,NewAccess,pSid);
  2415. }
  2416. if( !Result )
  2417. {
  2418. iisDebugOut((LOG_TYPE_ERROR, _T("AddAccessAllowedAce failed with 0x%x\n"),GetLastError()));
  2419. goto AddUserAccessToSD_Exit;
  2420. }
  2421. // Grab the 1st ace from the Newly created Dacl
  2422. if(!GetAce( NewAceDacl, 0, (void **)&NewAce ))
  2423. {
  2424. iisDebugOut((LOG_TYPE_ERROR, _T("GetAce failed with 0x%x\n"),GetLastError()));
  2425. goto AddUserAccessToSD_Exit;
  2426. }
  2427. // add CONTAINER_INHERIT_ACE TO AceFlags
  2428. //NewAce->AceFlags |= CONTAINER_INHERIT_ACE;
  2429. Length = AclInfo.AclBytesInUse + NewAce->AceSize;
  2430. }
  2431. else
  2432. {
  2433. Length = AclInfo.AclBytesInUse;
  2434. }
  2435. // Allocate new DACL
  2436. NewDacl = (PACL) LocalAlloc( LMEM_FIXED, Length );
  2437. if(NewDacl == NULL)
  2438. {
  2439. iisDebugOut((LOG_TYPE_ERROR, _T("LocalAlloc failed\n")));
  2440. goto AddUserAccessToSD_Exit;
  2441. }
  2442. if(!InitializeAcl( NewDacl, Length, ACL_REVISION ))
  2443. {
  2444. iisDebugOut((LOG_TYPE_ERROR, _T("InitializeAcl failed with 0x%x\n"),GetLastError()));
  2445. goto AddUserAccessToSD_Exit;
  2446. }
  2447. // Insert new ACE at the front of the new DACL
  2448. if (!fAceForGroupPresent)
  2449. {
  2450. if(!AddAce( NewDacl, ACL_REVISION, 0, NewAce, NewAce->AceSize ))
  2451. {
  2452. iisDebugOut((LOG_TYPE_ERROR, _T("AddAce failed with 0x%x\n"),GetLastError()));
  2453. goto AddUserAccessToSD_Exit;
  2454. }
  2455. }
  2456. // ----------------------------------------
  2457. // Read thru the old Dacl and get the ACE's
  2458. // add it to the new Dacl
  2459. // ----------------------------------------
  2460. for ( i = 0; i < AclInfo.AceCount; i++ )
  2461. {
  2462. ACE_HEADER *pAceHeader;
  2463. Result = GetAce( Dacl, i, (LPVOID*) &OldAce );
  2464. if( !Result )
  2465. {
  2466. iisDebugOut((LOG_TYPE_ERROR, _T("GetAce failed with 0x%x\n"),GetLastError()));
  2467. goto AddUserAccessToSD_Exit;
  2468. }
  2469. pAceHeader = (ACE_HEADER *)OldAce;
  2470. // If an ACE for our SID exists, we just need to bump
  2471. // up the access level instead of creating a new ACE
  2472. //
  2473. if (pAceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
  2474. {
  2475. dwMask = OldAce->Mask;
  2476. if (fAceForGroupPresent)
  2477. {
  2478. if (EqualSid((PSID) &(OldAce->SidStart), pSid))
  2479. {
  2480. dwMask = NewAccess | OldAce->Mask;
  2481. }
  2482. }
  2483. // now add ace to new dacl
  2484. Result = AddAccessAllowedAceEx(NewDacl, ACL_REVISION, OldAce->Header.AceFlags,dwMask,(PSID) &(OldAce->SidStart));
  2485. if( !Result )
  2486. {
  2487. iisDebugOut((LOG_TYPE_ERROR, _T("AddAccessAllowedAceEx failed with 0x%x\n"),GetLastError()));
  2488. goto AddUserAccessToSD_Exit;
  2489. }
  2490. }
  2491. else
  2492. {
  2493. // copy denied or audit ace.
  2494. if (!AddAce(NewDacl, ACL_REVISION, 0xFFFFFFFF,OldAce, pAceHeader->AceSize ))
  2495. {
  2496. iisDebugOut((LOG_TYPE_ERROR, _T("AddAce failed with 0x%x\n"),GetLastError()));
  2497. goto AddUserAccessToSD_Exit;
  2498. }
  2499. }
  2500. }
  2501. // Set new DACL for Security Descriptor
  2502. if(!SetSecurityDescriptorDacl(NewSD,TRUE,NewDacl,FALSE))
  2503. {
  2504. iisDebugOut((LOG_TYPE_ERROR, _T("SetSecurityDescriptorDacl failed with 0x%x\n"),GetLastError()));
  2505. goto AddUserAccessToSD_Exit;
  2506. }
  2507. // The new SD is in absolute format. change it to Relative before we pass it back
  2508. cboutpSD = 0;
  2509. MakeSelfRelativeSD(NewSD, outpSD, &cboutpSD);
  2510. outpSD = (PSECURITY_DESCRIPTOR)GlobalAlloc(GPTR, cboutpSD);
  2511. if ( !outpSD )
  2512. {
  2513. iisDebugOut((LOG_TYPE_ERROR, _T("GlobalAlloc failed\n")));
  2514. goto AddUserAccessToSD_Exit;
  2515. }
  2516. if (!MakeSelfRelativeSD(NewSD, outpSD, &cboutpSD))
  2517. {
  2518. iisDebugOut((LOG_TYPE_ERROR, _T("MakeSelfRelativeSD failed with 0x%x\n"),GetLastError()));
  2519. goto AddUserAccessToSD_Exit;
  2520. }
  2521. // The new SD is passed back in relative format,
  2522. *ppSdNew = outpSD;
  2523. bReturn = TRUE;
  2524. AddUserAccessToSD_Exit:
  2525. if (NewSD){free( NewSD );NewSD = NULL;}
  2526. if (NewDacl){LocalFree( NewDacl );NewDacl = NULL;}
  2527. if (NewAceDacl){LocalFree( NewAceDacl );NewAceDacl = NULL;}
  2528. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("AddUserAccessToSD end\n")));
  2529. return bReturn;
  2530. }
  2531. DWORD SetRegistryKeySecurityAdmin(HKEY hkey, DWORD samDesired,PSECURITY_DESCRIPTOR* ppsdOld)
  2532. {
  2533. PSID psid;
  2534. SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_NT_AUTHORITY;
  2535. DWORD dwError = ERROR_SUCCESS;
  2536. // Get sid for the local Administrators group
  2537. if (!AllocateAndInitializeSid(&sidAuth, 2,SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,0, 0, 0, 0, 0, 0, &psid) )
  2538. {
  2539. dwError = GetLastError();
  2540. }
  2541. if (ERROR_SUCCESS == dwError)
  2542. {
  2543. // Add all access privileges for the local administrators group
  2544. dwError = SetAccessOnRegKey(hkey, psid, samDesired, CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE | INHERITED_ACE, ppsdOld);
  2545. }
  2546. return dwError;
  2547. }
  2548. DWORD SetRegistryKeySecurity(
  2549. IN HKEY hkeyRootKey,
  2550. IN LPCTSTR szKeyPath,
  2551. IN LPCTSTR szPrincipal,
  2552. IN DWORD dwAccessMask,
  2553. IN DWORD dwInheritMask,
  2554. IN BOOL bDoSubKeys,
  2555. IN LPTSTR szExclusiveList
  2556. )
  2557. {
  2558. DWORD dwStatus;
  2559. HKEY hkeyThisKey;
  2560. DWORD dwKeyIndex;
  2561. DWORD dwSubKeyLen;
  2562. TCHAR szSubKeyName[_MAX_PATH];
  2563. FILETIME FileTime;
  2564. TCHAR *szExclusiveStart;
  2565. BOOL fSetSecurityRec;
  2566. dwStatus = RegOpenKeyEx(hkeyRootKey,szKeyPath,0L,KEY_ALL_ACCESS,&hkeyThisKey);
  2567. if (ERROR_SUCCESS == dwStatus)
  2568. {
  2569. PSID principalSID = NULL;
  2570. BOOL bWellKnownSID = FALSE;
  2571. if (ERROR_SUCCESS == GetPrincipalSID((LPTSTR) szPrincipal, &principalSID, &bWellKnownSID))
  2572. {
  2573. PSECURITY_DESCRIPTOR psd = NULL;
  2574. SetAccessOnRegKey(hkeyThisKey,principalSID,dwAccessMask,dwInheritMask,&psd);
  2575. if (psd) {free(psd);}
  2576. if (bDoSubKeys)
  2577. {
  2578. dwKeyIndex = 0;
  2579. dwSubKeyLen = sizeof(szSubKeyName) / sizeof(TCHAR);
  2580. while (RegEnumKeyEx (hkeyThisKey,dwKeyIndex,szSubKeyName,&dwSubKeyLen,NULL,NULL,NULL,&FileTime) == ERROR_SUCCESS)
  2581. {
  2582. // subkey found so set subkey security
  2583. // attach on the inherited ace attribute since everything under this will be inherited
  2584. dwInheritMask |= INHERITED_ACE;
  2585. fSetSecurityRec = TRUE;
  2586. szExclusiveStart = szExclusiveList;
  2587. while ( szExclusiveStart != NULL )
  2588. {
  2589. szExclusiveStart = _tcsstr(szExclusiveStart,szSubKeyName);
  2590. // If we have found the substring, and the character after it is a NULL terminator or a ',', and
  2591. // it is at the begining of the string, or it had a , before it, then it is a match.
  2592. if ( ( szExclusiveStart != NULL ) &&
  2593. ( ( *(szExclusiveStart + dwSubKeyLen) == '\0' ) || ( *(szExclusiveStart + dwSubKeyLen) == ',' ) ) &&
  2594. ( ( szExclusiveStart == szExclusiveList) || (*(szExclusiveStart - 1) == ',') )
  2595. )
  2596. {
  2597. fSetSecurityRec = FALSE;
  2598. break;
  2599. }
  2600. // Increment to move past current search result
  2601. if (szExclusiveStart)
  2602. {
  2603. szExclusiveStart = szExclusiveStart + dwSubKeyLen;
  2604. }
  2605. }
  2606. if ( fSetSecurityRec )
  2607. {
  2608. dwStatus = SetRegistryKeySecurity(hkeyThisKey,szSubKeyName,szPrincipal,dwAccessMask,dwInheritMask,bDoSubKeys,szExclusiveList);
  2609. }
  2610. // set variables for next call
  2611. dwKeyIndex++;
  2612. dwSubKeyLen = sizeof(szSubKeyName) / sizeof(TCHAR);
  2613. }
  2614. }
  2615. }
  2616. RegCloseKey(hkeyThisKey);
  2617. }
  2618. return dwStatus;
  2619. }
  2620. #endif