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

2980 lines
97 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),&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),&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("\\")))
  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. BOOL RecRemoveDir(LPCTSTR szName)
  638. {
  639. DWORD retCode;
  640. WIN32_FIND_DATA FindFileData;
  641. HANDLE hFile = INVALID_HANDLE_VALUE;
  642. TCHAR szSubDir[_MAX_PATH] = _T("");
  643. TCHAR szDirName[_MAX_PATH] = _T("");
  644. retCode = GetFileAttributes(szName);
  645. if (retCode == 0xFFFFFFFF)
  646. return FALSE;
  647. if (!(retCode & FILE_ATTRIBUTE_DIRECTORY)) {
  648. InetDeleteFile(szName);
  649. return TRUE;
  650. }
  651. _stprintf(szDirName, _T("%s\\*"), szName);
  652. hFile = FindFirstFile(szDirName, &FindFileData);
  653. if (hFile != INVALID_HANDLE_VALUE) {
  654. do {
  655. if ( _tcsicmp(FindFileData.cFileName, _T(".")) != 0 &&
  656. _tcsicmp(FindFileData.cFileName, _T("..")) != 0 ) {
  657. _stprintf(szSubDir, _T("%s\\%s"), szName, FindFileData.cFileName);
  658. RecRemoveDir(szSubDir);
  659. }
  660. if ( !FindNextFile(hFile, &FindFileData) ) {
  661. FindClose(hFile);
  662. break;
  663. }
  664. } while (TRUE);
  665. }
  666. return( ::RemoveDirectory(szName) );
  667. }
  668. //
  669. // Given a directory path, this subroutine will create the direct layer by layer
  670. //
  671. BOOL CreateLayerDirectory( CString &str )
  672. {
  673. BOOL fReturn = TRUE;
  674. iisDebugOutSafeParams((LOG_TYPE_TRACE_WIN32_API, _T("CreateLayerDirectory %1!s!\n"), (LPCTSTR)str));
  675. do
  676. {
  677. INT index=0;
  678. // INT iLength = str.GetLength();
  679. INT iLength = _tcslen(str);
  680. // first find the index for the first directory
  681. if ( iLength > 2 )
  682. {
  683. if ( *_tcsninc(str,1) == _T(':'))
  684. {
  685. // assume the first character is driver letter
  686. if ( *_tcsninc(str,2) == _T('\\'))
  687. {
  688. index = 2;
  689. } else
  690. {
  691. index = 1;
  692. }
  693. } else if ( *_tcsninc(str,0) == _T('\\'))
  694. {
  695. if ( *_tcsninc(str,1) == _T('\\'))
  696. {
  697. BOOL fFound = FALSE;
  698. INT i;
  699. INT nNum = 0;
  700. // unc name
  701. for (i = 2; i < iLength; i++ )
  702. {
  703. if ( *_tcsninc(str,i) == _T('\\'))
  704. {
  705. // find it
  706. nNum ++;
  707. if ( nNum == 2 )
  708. {
  709. fFound = TRUE;
  710. break;
  711. }
  712. }
  713. }
  714. if ( fFound )
  715. {
  716. index = i;
  717. } else
  718. {
  719. // bad name
  720. break;
  721. }
  722. } else
  723. {
  724. index = 1;
  725. }
  726. }
  727. } else if ( *_tcsninc(str,0) == _T('\\'))
  728. {
  729. index = 0;
  730. }
  731. // okay ... build directory
  732. do
  733. {
  734. // find next one
  735. do
  736. {
  737. if ( index < ( iLength - 1))
  738. {
  739. index ++;
  740. } else
  741. {
  742. break;
  743. }
  744. } while ( *_tcsninc(str,index) != _T('\\'));
  745. TCHAR szCurrentDir[_MAX_PATH+1];
  746. TCHAR szLeftDir[_MAX_PATH+1];
  747. ZeroMemory( szLeftDir, _MAX_PATH+1 );
  748. GetCurrentDirectory( _MAX_PATH+1, szCurrentDir );
  749. _tcsncpy( szLeftDir, str, index + 1 );
  750. if ( !SetCurrentDirectory(szLeftDir) )
  751. {
  752. if (( fReturn = CreateDirectory( szLeftDir, NULL )) != TRUE )
  753. {
  754. break;
  755. }
  756. }
  757. SetCurrentDirectory( szCurrentDir );
  758. if ( index >= ( iLength - 1 ))
  759. {
  760. fReturn = TRUE;
  761. break;
  762. }
  763. } while ( TRUE );
  764. } while (FALSE);
  765. return(fReturn);
  766. }
  767. // szResult = szParentDir \ szSubDir
  768. BOOL AppendDir(LPCTSTR szParentDir, LPCTSTR szSubDir, LPTSTR szResult)
  769. {
  770. LPTSTR p = (LPTSTR)szParentDir;
  771. ASSERT(szParentDir);
  772. ASSERT(szSubDir);
  773. ASSERT(*szSubDir && *szSubDir != _T('\\'));
  774. if (*szParentDir == _T('\0'))
  775. _tcscpy(szResult, szSubDir);
  776. else {
  777. _tcscpy(szResult, szParentDir);
  778. p = szResult;
  779. while (*p)
  780. p = _tcsinc(p);
  781. if (*(_tcsdec(szResult, p)) != _T('\\'))
  782. _tcscat(szResult, _T("\\"));
  783. _tcscat(szResult, szSubDir);
  784. }
  785. return TRUE;
  786. }
  787. //***************************************************************************
  788. //*
  789. //* purpose: add's filename onto path
  790. //*
  791. //***************************************************************************
  792. void AddPath(LPTSTR szPath, LPCTSTR szName )
  793. {
  794. LPTSTR p = szPath;
  795. LPTSTR pPrev;
  796. ASSERT(szPath);
  797. ASSERT(szName);
  798. // Find end of the string
  799. while (*p){p = _tcsinc(p);}
  800. // If no trailing backslash then add one
  801. pPrev = _tcsdec(szPath, p);
  802. if ( (!pPrev) ||
  803. (*(pPrev) != _T('\\'))
  804. )
  805. {_tcscat(szPath, _T("\\"));}
  806. // if there are spaces precluding szName, then skip
  807. while ( *szName == ' ' ) szName = _tcsinc(szName);;
  808. // Add new name to existing path string
  809. _tcscat(szPath, szName);
  810. }
  811. CString AddPath(CString szPath, LPCTSTR szName )
  812. {
  813. TCHAR szPathCopy[_MAX_PATH] = _T("");
  814. _tcscpy(szPathCopy,szPath);
  815. LPTSTR p = szPathCopy;
  816. ASSERT(szPathCopy);
  817. ASSERT(szName);
  818. // Find end of the string
  819. while (*p){p = _tcsinc(p);}
  820. // If no trailing backslash then add one
  821. if (*(_tcsdec(szPathCopy, p)) != _T('\\'))
  822. {_tcscat(szPathCopy, _T("\\"));}
  823. // if there are spaces precluding szName, then skip
  824. while ( *szName == _T(' ') ) szName = _tcsinc(szName);;
  825. // make sure that the szName
  826. // does not look like this "\filename"
  827. CString csTempString = szName;
  828. if (_tcsicmp(csTempString.Left(1), _T("\\")) == 0)
  829. {
  830. csTempString = csTempString.Right( csTempString.GetLength() - 1);
  831. }
  832. // Add new name to existing path string
  833. _tcscat(szPathCopy, csTempString);
  834. return szPathCopy;
  835. //szPath = szPathCopy;
  836. }
  837. BOOL ReturnFileNameOnly(LPCTSTR lpFullPath, LPTSTR lpReturnFileName)
  838. {
  839. int iReturn = FALSE;
  840. TCHAR pfilename_only[_MAX_FNAME];
  841. TCHAR pextention_only[_MAX_EXT];
  842. _tcscpy(lpReturnFileName, _T(""));
  843. _tsplitpath( lpFullPath, NULL, NULL, pfilename_only, pextention_only);
  844. if (pextention_only) {_tcscat(pfilename_only,pextention_only);}
  845. if (pfilename_only)
  846. {
  847. _tcscpy(lpReturnFileName, pfilename_only);
  848. iReturn = TRUE;
  849. }
  850. else
  851. {
  852. // well, we don't have anything in pfilename_only
  853. // that's probably because we got some strange path name like:
  854. // /??/c:\somethng\filename.txt
  855. // so... let's just return everything after the last "\" character.
  856. LPTSTR pszTheLastBackSlash = _tcsrchr((LPTSTR) lpFullPath, _T('\\'));
  857. _tcscpy(lpReturnFileName, pszTheLastBackSlash);
  858. iReturn = TRUE;
  859. }
  860. return iReturn;
  861. }
  862. BOOL ReturnFilePathOnly(LPCTSTR lpFullPath, LPTSTR lpReturnPathOnly)
  863. {
  864. int iReturn = FALSE;
  865. TCHAR szDrive_only[_MAX_DRIVE];
  866. TCHAR szPath_only[_MAX_PATH];
  867. TCHAR szFilename_only[_MAX_PATH];
  868. TCHAR szFilename_ext_only[_MAX_EXT];
  869. _tcscpy(lpReturnPathOnly, _T(""));
  870. _tsplitpath( lpFullPath, szDrive_only, szPath_only, szFilename_only, szFilename_ext_only);
  871. _tcscpy(lpReturnPathOnly, szDrive_only);
  872. _tcscat(lpReturnPathOnly, szPath_only);
  873. iReturn = TRUE;
  874. return iReturn;
  875. }
  876. void DeleteFilesWildcard(TCHAR *szDir, TCHAR *szFileName)
  877. {
  878. WIN32_FIND_DATA FindFileData;
  879. HANDLE hFile = INVALID_HANDLE_VALUE;
  880. TCHAR szFileToBeDeleted[_MAX_PATH];
  881. _stprintf(szFileToBeDeleted, _T("%s\\%s"), szDir, szFileName);
  882. hFile = FindFirstFile(szFileToBeDeleted, &FindFileData);
  883. if (hFile != INVALID_HANDLE_VALUE)
  884. {
  885. do {
  886. if ( _tcsicmp(FindFileData.cFileName, _T(".")) != 0 && _tcsicmp(FindFileData.cFileName, _T("..")) != 0 )
  887. {
  888. if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  889. {
  890. // this is a directory, so let's skip it
  891. }
  892. else
  893. {
  894. // this is a file, so let's Delete it.
  895. TCHAR szTempFileName[_MAX_PATH];
  896. _stprintf(szTempFileName, _T("%s\\%s"), szDir, FindFileData.cFileName);
  897. // set to normal attributes, so we can delete it
  898. SetFileAttributes(szTempFileName, FILE_ATTRIBUTE_NORMAL);
  899. // delete it, hopefully
  900. InetDeleteFile(szTempFileName);
  901. }
  902. }
  903. // get the next file
  904. if ( !FindNextFile(hFile, &FindFileData) )
  905. {
  906. FindClose(hFile);
  907. break;
  908. }
  909. } while (TRUE);
  910. }
  911. return;
  912. }
  913. int IsThisDriveNTFS(IN LPTSTR FileName)
  914. {
  915. BOOL Ntfs = FALSE;
  916. TCHAR szDriveRootPath[_MAX_DRIVE + 5];
  917. DWORD DontCare;
  918. TCHAR NameBuffer[100];
  919. // get the Drive only.
  920. _tsplitpath( FileName, szDriveRootPath, NULL, NULL, NULL);
  921. _tcscat(szDriveRootPath, _T("\\"));
  922. //
  923. // find out what the file system is
  924. //
  925. if (0 != GetVolumeInformation(szDriveRootPath,NULL,0,NULL,&DontCare,&DontCare,NameBuffer,sizeof(NameBuffer)/sizeof(TCHAR)))
  926. {
  927. if (0 == _tcsicmp(NameBuffer,_T("NTFS")))
  928. {Ntfs = TRUE;}
  929. }
  930. return Ntfs;
  931. }
  932. // take something like
  933. // e:\winnt\system32 and return back %systemroot%\system23
  934. // e:\winnt\system32\inetsrv and return back %systemroot%\system23\inetsrv
  935. int ReverseExpandEnvironmentStrings(LPTSTR szOriginalDir,LPTSTR szNewlyMungedDir)
  936. {
  937. int iReturn = FALSE;
  938. int iWhere = 0;
  939. TCHAR szSystemDir[_MAX_PATH];
  940. CString csTempString;
  941. CString csTempString2;
  942. // default it with the input string
  943. _tcscpy(szNewlyMungedDir, szOriginalDir);
  944. // get the c:\winnt\system32 dir
  945. if (0 == GetSystemDirectory(szSystemDir, _MAX_PATH))
  946. {
  947. // we weren't able to get the systemdirectory, so just return whatever was put in
  948. iReturn = TRUE;
  949. goto ReverseExpandEnvironmentStrings_Exit;
  950. }
  951. csTempString = szOriginalDir;
  952. csTempString2 = szSystemDir;
  953. // Find the "e:\winnt\system32"
  954. iWhere = csTempString.Find(szSystemDir);
  955. if (-1 != iWhere)
  956. {
  957. CString AfterString;
  958. // there is a "e:\winnt\system32" in the string
  959. // Get the after e:\winnt\system32 stuff
  960. AfterString = csTempString.Right(csTempString.GetLength() - (iWhere + csTempString2.GetLength()));
  961. // Take everything after the string and append it to our new string.
  962. _tcscpy(szNewlyMungedDir, _T("%SystemRoot%\\System32"));
  963. _tcscat(szNewlyMungedDir, AfterString);
  964. // return true!
  965. iReturn = TRUE;
  966. }
  967. ReverseExpandEnvironmentStrings_Exit:
  968. return iReturn;
  969. }
  970. DWORD ReturnFileSize(LPCTSTR myFileName)
  971. {
  972. DWORD dwReturn = 0xFFFFFFFF;
  973. HANDLE hFile = CreateFile(myFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, NULL);
  974. if (hFile != INVALID_HANDLE_VALUE)
  975. {
  976. dwReturn = GetFileSize(hFile, NULL);
  977. CloseHandle(hFile);
  978. }
  979. return dwReturn;
  980. }
  981. BOOL IsFileExist_NormalOrCompressed(LPCTSTR szFile)
  982. {
  983. int iReturn = FALSE;
  984. TCHAR szDrive_only[_MAX_DRIVE];
  985. TCHAR szPath_only[_MAX_PATH];
  986. TCHAR szFilename_only[_MAX_PATH];
  987. TCHAR szFilename_ext_only[_MAX_EXT];
  988. TCHAR szCompressedName[_MAX_PATH];
  989. // Check if the file exsts
  990. // if it doesn't, check if maybe the compressed file exists.
  991. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("IsFileExist_NormalOrCompressed:%s.\n"), szFile));
  992. if (IsFileExist(szFile) != TRUE)
  993. {
  994. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("IsFileExist_NormalOrCompressed:%s not exist.\n"), szFile));
  995. // check if maybe the compressed file exists
  996. _tsplitpath( szFile, szDrive_only, szPath_only, szFilename_only, szFilename_ext_only);
  997. // Replace the last character with an '_'
  998. int nLen = 0;
  999. nLen = _tcslen(szFilename_ext_only);
  1000. *_tcsninc(szFilename_ext_only, nLen-1) = _T('_');
  1001. _stprintf(szCompressedName,_T("%s%s%s%s"),szDrive_only, szPath_only, szFilename_only, szFilename_ext_only);
  1002. // see if it exists
  1003. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("IsFileExist_NormalOrCompressed:%s.\n"), szCompressedName));
  1004. if (IsFileExist(szCompressedName) != TRUE)
  1005. {
  1006. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("IsFileExist_NormalOrCompressed:%s. no exist.\n"), szCompressedName));
  1007. goto IsFileExist_RegOrCompressed_Exit;
  1008. }
  1009. else
  1010. {
  1011. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("IsFileExist_NormalOrCompressed:%s. exist.\n"), szCompressedName));
  1012. }
  1013. }
  1014. // we got this far, that must mean things are okay.
  1015. iReturn = TRUE;
  1016. IsFileExist_RegOrCompressed_Exit:
  1017. return iReturn;
  1018. }
  1019. // Clean leading & trailing spaces
  1020. // Clean trailing backslashes
  1021. BOOL CleanPathString(LPTSTR szPath)
  1022. {
  1023. CString csPath = szPath;
  1024. csPath.TrimLeft();
  1025. csPath.TrimRight();
  1026. _tcscpy(szPath, (LPCTSTR)csPath);
  1027. return TRUE;
  1028. }
  1029. //
  1030. // Return 0 if there was nothing to compare
  1031. // Return 1 if Source is Equal to Destination
  1032. // Return 2 if Source is Larger than Destination
  1033. // Return 3 if Source is Less than Destination
  1034. //
  1035. INT VerCmp(LPTSTR szSrcVerString, LPTSTR szDestVerString)
  1036. {
  1037. INT iReturn = 0;
  1038. const DWORD MAX_NUM_OF_VER_FIELDS = 32;
  1039. DWORD dwSrcVer[MAX_NUM_OF_VER_FIELDS], dwDestVer[MAX_NUM_OF_VER_FIELDS];
  1040. memset( (PVOID)dwSrcVer, 0, sizeof(dwSrcVer));
  1041. memset( (PVOID)dwDestVer, 0, sizeof(dwDestVer));
  1042. int i=0;
  1043. TCHAR szSeps[] = _T(".");
  1044. TCHAR *token;
  1045. BOOL bNotEqual = FALSE;
  1046. // expand src version string into a dword arrary
  1047. i = 0;
  1048. token = _tcstok(szSrcVerString, szSeps);
  1049. while ( token && (i < MAX_NUM_OF_VER_FIELDS) ) {
  1050. dwSrcVer[i++] = _ttoi(token);
  1051. token = _tcstok(NULL, szSeps);
  1052. }
  1053. // expand dest version string into a dword arrary
  1054. i = 0;
  1055. token = _tcstok(szDestVerString, szSeps);
  1056. while ( token && (i < MAX_NUM_OF_VER_FIELDS) ) {
  1057. dwDestVer[i++] = _ttoi(token);
  1058. token = _tcstok(NULL, szSeps);
  1059. }
  1060. // Check for Equality
  1061. for (i=0; i<MAX_NUM_OF_VER_FIELDS; i++)
  1062. {
  1063. if (dwSrcVer[i] != dwDestVer[i])
  1064. {
  1065. bNotEqual = TRUE;
  1066. break;
  1067. }
  1068. }
  1069. if (TRUE == bNotEqual)
  1070. {
  1071. // int compare each field
  1072. for (i=0; i<MAX_NUM_OF_VER_FIELDS; i++)
  1073. {
  1074. if (dwSrcVer[i] > dwDestVer[i])
  1075. {return 2;}
  1076. if (dwSrcVer[i] < dwDestVer[i])
  1077. {return 3;}
  1078. }
  1079. // if we haven't return here, then
  1080. // there probably wasn't anything to loop thru (for 0=0 till 0)
  1081. return 0;
  1082. }
  1083. else
  1084. {
  1085. // it is equal so return so
  1086. return 1;
  1087. }
  1088. }
  1089. DWORD atodw(LPCTSTR lpszData)
  1090. {
  1091. DWORD i = 0, sum = 0;
  1092. TCHAR *s, *t;
  1093. s = (LPTSTR)lpszData;
  1094. t = (LPTSTR)lpszData;
  1095. while (*t)
  1096. t = _tcsinc(t);
  1097. t = _tcsdec(lpszData, t);
  1098. if (*s == _T('0') && (*(_tcsinc(s)) == _T('x') || *(_tcsinc(s)) == _T('X')))
  1099. s = _tcsninc(s, 2);
  1100. while (s <= t) {
  1101. if ( *s >= _T('0') && *s <= _T('9') )
  1102. i = *s - _T('0');
  1103. else if ( *s >= _T('a') && *s <= _T('f') )
  1104. i = *s - _T('a') + 10;
  1105. else if ( *s >= _T('A') && *s <= _T('F') )
  1106. i = *s - _T('A') + 10;
  1107. else
  1108. break;
  1109. sum = sum * 16 + i;
  1110. s = _tcsinc(s);
  1111. }
  1112. return sum;
  1113. }
  1114. void MakePath(LPTSTR lpPath)
  1115. {
  1116. LPTSTR lpTmp;
  1117. lpTmp = CharPrev( lpPath, lpPath + _tcslen(lpPath));
  1118. // chop filename off
  1119. while ( (lpTmp > lpPath) && *lpTmp && (*lpTmp != '\\') )
  1120. lpTmp = CharPrev( lpPath, lpTmp );
  1121. if ( *CharPrev( lpPath, lpTmp ) != ':' )
  1122. *lpTmp = '\0';
  1123. else
  1124. *CharNext(lpTmp) = '\0';
  1125. return;
  1126. }
  1127. CString ReturnUniqueFileName(CString csInputFullName)
  1128. {
  1129. TCHAR szPathCopy[_MAX_PATH] = _T("");
  1130. _tcscpy(szPathCopy,csInputFullName);
  1131. long iNum = 1;
  1132. do
  1133. {
  1134. _stprintf(szPathCopy,TEXT("%s.%d"),csInputFullName,iNum);
  1135. // Check if the file exists
  1136. if (!IsFileExist(szPathCopy)){goto ReturnUniqueFileName_Exit;}
  1137. iNum++;
  1138. } while (iNum <= 50);
  1139. ReturnUniqueFileName_Exit:
  1140. // returns %s50 if there are fifty copies aleady!
  1141. return szPathCopy;
  1142. }
  1143. /*---------------------------------------------------------------------------*
  1144. Description: Displays the current running version of setup to the debug
  1145. output and setup log.
  1146. -----------------------------------------------------------------------------*/
  1147. void DisplayVerOnCurrentModule()
  1148. {
  1149. TCHAR tszModuleName[_MAX_PATH+1];
  1150. GetModuleFileName((HINSTANCE)g_MyModuleHandle, tszModuleName, _MAX_PATH+1);
  1151. LogFileVersion(tszModuleName, TRUE);
  1152. return;
  1153. }
  1154. void MyGetVersionFromFile(LPCTSTR lpszFilename, LPDWORD pdwMSVer, LPDWORD pdwLSVer, LPTSTR pszReturnLocalizedVersion)
  1155. {
  1156. struct TRANSARRAY {
  1157. WORD wLanguageID;
  1158. WORD wCharacterSet;
  1159. };
  1160. unsigned uiSize;
  1161. DWORD dwVerInfoSize;
  1162. DWORD dwHandle;
  1163. VS_FIXEDFILEINFO * lpVSFixedFileInfo;
  1164. LPTSTR lpBuffer = NULL;
  1165. LPVOID lpVerBuffer = NULL;
  1166. LPTSTR pszTheResult = NULL;
  1167. TCHAR QueryString[48] = _T("");
  1168. TRANSARRAY *lpTransArray;
  1169. *pdwMSVer = *pdwLSVer = 0L;
  1170. dwVerInfoSize = GetFileVersionInfoSize( (LPTSTR) lpszFilename, &dwHandle);
  1171. if (dwVerInfoSize)
  1172. {
  1173. // Alloc the memory for the version stamping
  1174. lpBuffer = (LPTSTR) LocalAlloc(LPTR, dwVerInfoSize);
  1175. if (lpBuffer)
  1176. {
  1177. int iTemp = 0;
  1178. iTemp = GetFileVersionInfo( (LPTSTR) lpszFilename, dwHandle, dwVerInfoSize, lpBuffer);
  1179. // Read version stamping info
  1180. if (iTemp)
  1181. {
  1182. // Get the value for Translation
  1183. if (VerQueryValue(lpBuffer, _T("\\"), (LPVOID*)&lpVSFixedFileInfo, &uiSize) && (uiSize))
  1184. {
  1185. *pdwMSVer = lpVSFixedFileInfo->dwFileVersionMS;
  1186. *pdwLSVer = lpVSFixedFileInfo->dwFileVersionLS;
  1187. }
  1188. // get a pointer to the translation table information
  1189. if (VerQueryValue(lpBuffer, _T("\\VarFileInfo\\Translation"), &lpVerBuffer, &uiSize) && (uiSize))
  1190. {
  1191. lpTransArray = (TRANSARRAY *) lpVerBuffer;
  1192. // lpTransArray points to the translation array. dwFixedLength has number of bytes in array
  1193. _stprintf(QueryString, _T("\\StringFileInfo\\%04x%04x\\FileVersion"), lpTransArray[0].wLanguageID, lpTransArray[0].wCharacterSet);
  1194. if (VerQueryValue(lpBuffer, QueryString, (LPVOID*) &pszTheResult, &uiSize))
  1195. {
  1196. _tcscpy(pszReturnLocalizedVersion, pszTheResult);
  1197. }
  1198. }
  1199. }
  1200. }
  1201. }
  1202. if(lpBuffer) {LocalFree(lpBuffer);lpBuffer=NULL;}
  1203. return ;
  1204. }
  1205. BOOL MyGetDescriptionFromFile(LPCTSTR lpszFilename, LPTSTR pszReturnDescription)
  1206. {
  1207. BOOL bRet = FALSE;
  1208. struct TRANSARRAY {
  1209. WORD wLanguageID;
  1210. WORD wCharacterSet;
  1211. };
  1212. unsigned uiSize;
  1213. DWORD dwVerInfoSize;
  1214. DWORD dwHandle;
  1215. VS_FIXEDFILEINFO * lpVSFixedFileInfo;
  1216. LPTSTR lpBuffer = NULL;
  1217. LPVOID lpTempBuffer = NULL;
  1218. LPTSTR pszTheResult = NULL;
  1219. TCHAR QueryString[52] = _T("");
  1220. TRANSARRAY *lpTransArray;
  1221. dwVerInfoSize = GetFileVersionInfoSize( (LPTSTR) lpszFilename, &dwHandle);
  1222. if (dwVerInfoSize)
  1223. {
  1224. // Alloc the memory for the version stamping
  1225. lpBuffer = (LPTSTR) LocalAlloc(LPTR, dwVerInfoSize);
  1226. if (lpBuffer)
  1227. {
  1228. int iTemp = 0;
  1229. iTemp = GetFileVersionInfo( (LPTSTR) lpszFilename, dwHandle, dwVerInfoSize, lpBuffer);
  1230. // Read version stamping info
  1231. if (iTemp)
  1232. {
  1233. // get a pointer to the translation table information
  1234. if (VerQueryValue(lpBuffer, _T("\\VarFileInfo\\Translation"), &lpTempBuffer, &uiSize) && (uiSize))
  1235. {
  1236. lpTransArray = (TRANSARRAY *) lpTempBuffer;
  1237. // lpTransArray points to the translation array. dwFixedLength has number of bytes in array
  1238. _stprintf(QueryString, _T("\\StringFileInfo\\%04x%04x\\FileDescription"), lpTransArray[0].wLanguageID, lpTransArray[0].wCharacterSet);
  1239. if (VerQueryValue(lpBuffer, QueryString, (LPVOID*) &pszTheResult, &uiSize))
  1240. {
  1241. _tcscpy(pszReturnDescription, pszTheResult);
  1242. bRet = TRUE;
  1243. }
  1244. }
  1245. }
  1246. }
  1247. }
  1248. if(lpBuffer) {LocalFree(lpBuffer);lpBuffer=NULL;}
  1249. return bRet;
  1250. }
  1251. //
  1252. // Returns True if the filename has a version stamp which is part of ntop4.0
  1253. //
  1254. int IsFileLessThanThisVersion(IN LPCTSTR lpszFullFilePath, IN DWORD dwNtopMSVer, IN DWORD dwNtopLSVer)
  1255. {
  1256. int iReturn = FALSE;
  1257. DWORD dwMSVer, dwLSVer;
  1258. TCHAR szLocalizedVersion[100] = _T("");
  1259. // if the filename has a version number
  1260. // and it's larger than the release version of ntop 4.2.622.1, 4.02.0622 (localized version)
  1261. // return back true! if not, then return back false.
  1262. // see if the file exists
  1263. if (!IsFileExist(lpszFullFilePath))
  1264. {goto iFileWasPartOfIIS4_Exit;}
  1265. // get the fileinformation
  1266. // includes version and localizedversion
  1267. MyGetVersionFromFile(lpszFullFilePath, &dwMSVer, &dwLSVer, szLocalizedVersion);
  1268. if (!dwMSVer)
  1269. {
  1270. iisDebugOut((LOG_TYPE_TRACE, _T("iFileWasPartOfIIS4:%s.No version."), lpszFullFilePath));
  1271. goto iFileWasPartOfIIS4_Exit;
  1272. }
  1273. // okay, there is a version on this.
  1274. iisDebugOut((LOG_TYPE_TRACE, _T("iFileWasPartOfIIS4:%d.%d.%d.%d, %s, %s"), HIWORD(dwMSVer), LOWORD(dwMSVer), HIWORD(dwLSVer), LOWORD(dwLSVer), szLocalizedVersion, lpszFullFilePath));
  1275. // Check if the version is smaller than what was shipped with iis4.0
  1276. // NTOP versions were 4.02.0622
  1277. if (dwMSVer < dwNtopMSVer)
  1278. {goto iFileWasPartOfIIS4_Exit;}
  1279. // check if the file has a smaller minor version number
  1280. if ( (dwMSVer == dwNtopMSVer) && (dwLSVer < dwNtopLSVer) )
  1281. {goto iFileWasPartOfIIS4_Exit;}
  1282. // this is a ntop 4.0 or greater versioned file
  1283. iReturn = TRUE;
  1284. iFileWasPartOfIIS4_Exit:
  1285. return iReturn;
  1286. }
  1287. void MakeSureDirAclsHaveAtLeastRead(LPTSTR lpszDirectoryPath)
  1288. {
  1289. iisDebugOut_Start1(_T("MakeSureDirAclsHaveAtLeastRead"),lpszDirectoryPath, LOG_TYPE_TRACE);
  1290. DWORD err;
  1291. TCHAR szThePath[_MAX_PATH];
  1292. if (FALSE == IsThisDriveNTFS(lpszDirectoryPath))
  1293. {
  1294. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("MakeSureDirAclsHaveAtLeastRead:filesys is not ntfs.")));
  1295. goto MakeSureDirAclsHaveAtLeastRead_Exit;
  1296. }
  1297. do
  1298. {
  1299. //
  1300. // Loop through all the files in the physical path
  1301. //
  1302. _tcscpy(szThePath, lpszDirectoryPath);
  1303. _tcscat(szThePath, _T("\\*"));
  1304. WIN32_FIND_DATA w32data;
  1305. HANDLE hFind = ::FindFirstFile(szThePath, &w32data);
  1306. if (hFind == INVALID_HANDLE_VALUE)
  1307. {
  1308. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("MakeSureDirAclsHaveAtLeastRead:WARNING.filenotfound:%s"),lpszDirectoryPath));
  1309. // No files...
  1310. break;
  1311. }
  1312. //
  1313. // First, set the new ACL on the folder itself.
  1314. //
  1315. err = SetAccessOnFile(lpszDirectoryPath, TRUE);
  1316. err = SetAccessOnFile(lpszDirectoryPath, FALSE);
  1317. err = ERROR_SUCCESS;
  1318. //if (err != ERROR_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("MakeSureDirAclsHaveAtLeastRead:%s:FAILED WARNING.ret=0x%x."),lpszDirectoryPath,err));}
  1319. //
  1320. // Now do all the files in it
  1321. //
  1322. do
  1323. {
  1324. //
  1325. // Only set the acl on files, not sub-directories
  1326. //
  1327. if (w32data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  1328. {
  1329. continue;
  1330. }
  1331. //
  1332. // Build the current file's full path name
  1333. //
  1334. _tcscpy(szThePath, lpszDirectoryPath);
  1335. _tcscat(szThePath, _T("\\"));
  1336. _tcscat(szThePath, w32data.cFileName);
  1337. err = SetAccessOnFile(szThePath, TRUE);
  1338. err = SetAccessOnFile(szThePath, FALSE);
  1339. err = ERROR_SUCCESS;
  1340. //if (err != ERROR_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("MakeSureDirAclsHaveAtLeastRead:%s:FAILED WARNING.ret=0x%x."),szThePath,err));}
  1341. } while(SUCCEEDED(err) && FindNextFile(hFind, &w32data));
  1342. FindClose(hFind);
  1343. } while(FALSE);
  1344. MakeSureDirAclsHaveAtLeastRead_Exit:
  1345. return;
  1346. }
  1347. DWORD SetAccessOnFile(IN LPTSTR FileName, BOOL bDoForAdmin)
  1348. {
  1349. DWORD dwError = 0;
  1350. TCHAR TrusteeName[50];
  1351. PACL ExistingDacl = NULL;
  1352. PACL NewAcl = NULL;
  1353. PSECURITY_DESCRIPTOR psd = NULL;
  1354. // access stuff.
  1355. DWORD AccessMask = GENERIC_ALL;
  1356. EXPLICIT_ACCESS explicitaccess;
  1357. ACCESS_MODE option;
  1358. DWORD InheritFlag = NO_INHERITANCE;
  1359. // other
  1360. PSID principalSID = NULL;
  1361. BOOL bWellKnownSID = FALSE;
  1362. TRUSTEE myTrustee;
  1363. // other other
  1364. LPCTSTR ServerName = NULL; // local machine
  1365. DWORD cbName = 200;
  1366. TCHAR lpGuestGrpName[200];
  1367. TCHAR ReferencedDomainName[200];
  1368. DWORD cbReferencedDomainName = sizeof(ReferencedDomainName);
  1369. SID_NAME_USE sidNameUse = SidTypeUser;
  1370. // get current Dacl on specified file
  1371. dwError = GetNamedSecurityInfo(FileName,SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,&ExistingDacl,NULL,&psd);
  1372. if(dwError != ERROR_SUCCESS)
  1373. {
  1374. iisDebugOut((LOG_TYPE_WARN, _T("SetAccessOnFile: GetNamedSecurityInfo failed on %s. err=0x%x\n"),FileName,dwError));
  1375. goto SetAccessOnFile_Exit;
  1376. }
  1377. // set defaults
  1378. option = GRANT_ACCESS;
  1379. InheritFlag = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  1380. if (bDoForAdmin)
  1381. {
  1382. // Do for Administrators -- should be more access
  1383. AccessMask = SYNCHRONIZE ;
  1384. AccessMask |= GENERIC_ALL;
  1385. _tcscpy(TrusteeName,_T("BUILTIN\\ADMINISTRATORS"));
  1386. _tcscpy(TrusteeName,_T("administrators"));
  1387. }
  1388. else
  1389. {
  1390. // Do for Administrators -- should be more access
  1391. AccessMask = SYNCHRONIZE ;
  1392. AccessMask |= GENERIC_READ;
  1393. _tcscpy(TrusteeName,_T("EVERYONE"));
  1394. }
  1395. // Get the SID for the certain string (administrator or everyone)
  1396. dwError = GetPrincipalSID(TrusteeName, &principalSID, &bWellKnownSID);
  1397. if (dwError != ERROR_SUCCESS)
  1398. {
  1399. iisDebugOut((LOG_TYPE_WARN, _T("SetAccessOnFile:GetPrincipalSID(%s) FAILED. Error()= 0x%x\n"), TrusteeName, dwError));
  1400. goto SetAccessOnFile_Exit;
  1401. }
  1402. // using Sid, get the "localized" name
  1403. if (0 == LookupAccountSid(ServerName, principalSID, lpGuestGrpName, &cbName, ReferencedDomainName, &cbReferencedDomainName, &sidNameUse))
  1404. {
  1405. iisDebugOut((LOG_TYPE_WARN, _T("SetAccessOnFile:LookupAccountSid(%s) FAILED. GetLastError()= 0x%x\n"), TrusteeName, GetLastError()));
  1406. goto SetAccessOnFile_Exit;
  1407. }
  1408. // using the "localized" name, build explicit access structure
  1409. BuildExplicitAccessWithName(&explicitaccess,lpGuestGrpName,AccessMask,option,InheritFlag);
  1410. explicitaccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
  1411. explicitaccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
  1412. explicitaccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
  1413. // set the acl with this certain access stuff
  1414. dwError = SetEntriesInAcl(1,&explicitaccess,ExistingDacl,&NewAcl);
  1415. if(dwError != ERROR_SUCCESS)
  1416. {
  1417. // it may error because the user is already there
  1418. //iisDebugOut((LOG_TYPE_WARN, _T("SetAccessOnFile: SetEntriesInAcl failed on %s. for trustee=%s. err=0x%x\n"),FileName,explicitaccess.Trustee.ptstrName,dwError));
  1419. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("SetAccessOnFile: SetEntriesInAcl failed on %s. for trustee=%s. err=0x%x\n"),FileName,explicitaccess.Trustee.ptstrName,dwError));
  1420. goto SetAccessOnFile_Exit;
  1421. }
  1422. // apply new security to file
  1423. dwError = SetNamedSecurityInfo(FileName,SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,NewAcl,NULL);
  1424. if(dwError != ERROR_SUCCESS)
  1425. {
  1426. iisDebugOut((LOG_TYPE_WARN, _T("SetAccessOnFile: SetNamedSecurityInfo failed on %s. err=0x%x\n"),FileName,dwError));
  1427. goto SetAccessOnFile_Exit;
  1428. }
  1429. // everything is kool!
  1430. dwError = ERROR_SUCCESS;
  1431. SetAccessOnFile_Exit:
  1432. if(NewAcl != NULL){LocalFree(NewAcl);}
  1433. if(psd != NULL){LocalFree(psd);}
  1434. if (principalSID)
  1435. {
  1436. if (bWellKnownSID)
  1437. FreeSid (principalSID);
  1438. else
  1439. free (principalSID);
  1440. }
  1441. return dwError;
  1442. }
  1443. int CreateAnEmptyFile(CString strTheFullPath)
  1444. {
  1445. int iReturn = FALSE;
  1446. HANDLE hFile = NULL;
  1447. if (IsFileExist(strTheFullPath) == TRUE)
  1448. {
  1449. return TRUE;
  1450. }
  1451. // Open existing file or create a new one.
  1452. hFile = CreateFile(strTheFullPath,GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
  1453. if (hFile == INVALID_HANDLE_VALUE)
  1454. {
  1455. hFile = NULL;
  1456. iisDebugOutSafeParams((LOG_TYPE_WARN, _T("CreateAnEmptyFile:() failed to CreateFile %1!s!. POTENTIAL PROBLEM. FAILURE.\n"), strTheFullPath));
  1457. }
  1458. else
  1459. {
  1460. // write to the file
  1461. if (hFile)
  1462. {
  1463. iReturn = TRUE;
  1464. /*
  1465. DWORD dwBytesWritten = 0;
  1466. char szTestData[2];
  1467. strcpy(szTestData, " ");
  1468. if (WriteFile(hFile,szTestData,strlen(szTestData),&dwBytesWritten,NULL))
  1469. {
  1470. // everything is hunky dory. don't print anything
  1471. iReturn = TRUE;
  1472. }
  1473. else
  1474. {
  1475. // error writing to the file.
  1476. iisDebugOutSafeParams((LOG_TYPE_WARN, _T("CreateAnEmptyFile:WriteFile(%1!s!) Failed. POTENTIAL PROBLEM. FAILURE. Error=0x%2!x!.\n"), strTheFullPath, GetLastError()));
  1477. }
  1478. */
  1479. }
  1480. }
  1481. if (hFile)
  1482. {
  1483. CloseHandle(hFile);
  1484. }
  1485. return iReturn;
  1486. }
  1487. DWORD GrantUserAccessToFile(IN LPTSTR FileName,IN LPTSTR TrusteeName)
  1488. {
  1489. iisDebugOut_Start1(_T("GrantUserAccessToFile"),FileName,LOG_TYPE_TRACE);
  1490. DWORD dwError = 0;
  1491. PACL ExistingDacl = NULL;
  1492. PACL NewAcl = NULL;
  1493. PSECURITY_DESCRIPTOR psd = NULL;
  1494. // access stuff.
  1495. DWORD AccessMask = GENERIC_ALL;
  1496. EXPLICIT_ACCESS explicitaccess;
  1497. ACCESS_MODE option;
  1498. DWORD InheritFlag = NO_INHERITANCE;
  1499. // other
  1500. PSID principalSID = NULL;
  1501. BOOL bWellKnownSID = FALSE;
  1502. TRUSTEE myTrustee;
  1503. // other other
  1504. LPCTSTR ServerName = NULL; // local machine
  1505. DWORD cbName = 200;
  1506. TCHAR lpGuestGrpName[200];
  1507. TCHAR ReferencedDomainName[200];
  1508. DWORD cbReferencedDomainName = sizeof(ReferencedDomainName);
  1509. SID_NAME_USE sidNameUse = SidTypeUser;
  1510. if (IsFileExist(FileName) != TRUE)
  1511. {
  1512. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("GrantUserAccessToFile:file doesn't exist.")));
  1513. goto GrantUserAccessToFile_Exit;
  1514. }
  1515. if (FALSE == IsThisDriveNTFS(FileName))
  1516. {
  1517. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("GrantUserAccessToFile:filesys is not ntfs.")));
  1518. goto GrantUserAccessToFile_Exit;
  1519. }
  1520. // get current Dacl on specified file
  1521. dwError = GetNamedSecurityInfo(FileName,SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,&ExistingDacl,NULL,&psd);
  1522. if(dwError != ERROR_SUCCESS)
  1523. {
  1524. psd = NULL;
  1525. iisDebugOut((LOG_TYPE_WARN, _T("GrantUserAccessToFile: GetNamedSecurityInfo failed on %s.\n"),FileName));
  1526. goto GrantUserAccessToFile_Exit;
  1527. }
  1528. // set defaults
  1529. option = GRANT_ACCESS;
  1530. InheritFlag = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  1531. // assign access
  1532. AccessMask = SYNCHRONIZE ;
  1533. AccessMask |= GENERIC_ALL;
  1534. //AccessMask = MAXIMUM_ALLOWED;
  1535. // Get the SID for the certain string (administrator or everyone)
  1536. dwError = GetPrincipalSID(TrusteeName, &principalSID, &bWellKnownSID);
  1537. if (dwError != ERROR_SUCCESS)
  1538. {
  1539. principalSID = NULL;
  1540. iisDebugOut((LOG_TYPE_WARN, _T("GrantUserAccessToFile:GetPrincipalSID(%s) FAILED. Error()= 0x%x\n"), TrusteeName, dwError));
  1541. goto GrantUserAccessToFile_Exit;
  1542. }
  1543. // using Sid, get the "localized" name
  1544. if (0 == LookupAccountSid(ServerName, principalSID, lpGuestGrpName, &cbName, ReferencedDomainName, &cbReferencedDomainName, &sidNameUse))
  1545. {
  1546. iisDebugOut((LOG_TYPE_WARN, _T("GrantUserAccessToFile:LookupAccountSid(%s) FAILED. GetLastError()= 0x%x\n"), TrusteeName, GetLastError()));
  1547. goto GrantUserAccessToFile_Exit;
  1548. }
  1549. // using the "localized" name, build explicit access structure
  1550. BuildExplicitAccessWithName(&explicitaccess,lpGuestGrpName,AccessMask,option,InheritFlag);
  1551. explicitaccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
  1552. explicitaccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
  1553. explicitaccess.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
  1554. if (_tcsicmp(TrusteeName, _T("administrators")) == 0 || _tcsicmp(TrusteeName, _T("everyone")) == 0)
  1555. {
  1556. explicitaccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
  1557. }
  1558. // set the acl with this certain access stuff
  1559. dwError = SetEntriesInAcl(1,&explicitaccess,ExistingDacl,&NewAcl);
  1560. if(dwError != ERROR_SUCCESS)
  1561. {
  1562. NewAcl = NULL;
  1563. // it may error because the user is already there
  1564. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("GrantUserAccessToFile: SetEntriesInAcl failed on %s. for trustee=%s. err=0x%x\n"),FileName,explicitaccess.Trustee.ptstrName,dwError));
  1565. goto GrantUserAccessToFile_Exit;
  1566. }
  1567. // apply new security to file
  1568. dwError = SetNamedSecurityInfo(FileName,SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,NewAcl,NULL);
  1569. if(dwError != ERROR_SUCCESS)
  1570. {
  1571. iisDebugOut((LOG_TYPE_WARN, _T("GrantUserAccessToFile: SetNamedSecurityInfo failed on %s. err=0x%x\n"),FileName,dwError));
  1572. goto GrantUserAccessToFile_Exit;
  1573. }
  1574. // everything is kool!
  1575. dwError = ERROR_SUCCESS;
  1576. GrantUserAccessToFile_Exit:
  1577. if(NewAcl != NULL){LocalFree(NewAcl);}
  1578. if(psd != NULL){LocalFree(psd);}
  1579. if (principalSID)
  1580. {
  1581. if (bWellKnownSID)
  1582. FreeSid (principalSID);
  1583. else
  1584. free (principalSID);
  1585. }
  1586. iisDebugOut_End1(_T("GrantUserAccessToFile"),FileName);
  1587. return dwError;
  1588. }
  1589. #ifndef _CHICAGO_
  1590. DWORD SetDirectorySecurity(
  1591. IN LPCTSTR szDirPath,
  1592. IN LPCTSTR szPrincipal,
  1593. IN INT iAceType,
  1594. IN DWORD dwAccessMask,
  1595. IN DWORD dwInheritMask
  1596. )
  1597. {
  1598. DWORD dwStatus = ERROR_FILE_NOT_FOUND;
  1599. if (ACCESS_ALLOWED_ACE_TYPE == iAceType || ACCESS_DENIED_ACE_TYPE == iAceType)
  1600. {
  1601. if (IsFileExist(szDirPath) == TRUE)
  1602. {
  1603. PSID principalSID = NULL;
  1604. BOOL bWellKnownSID = FALSE;
  1605. dwStatus = GetPrincipalSID((LPTSTR) szPrincipal, &principalSID, &bWellKnownSID);
  1606. if (dwStatus == ERROR_SUCCESS)
  1607. {
  1608. PSECURITY_DESCRIPTOR psd = NULL;
  1609. dwStatus = SetAccessOnDirOrFile((TCHAR*) szDirPath,principalSID,iAceType,dwAccessMask,dwInheritMask,&psd);
  1610. //DumpAdminACL(INVALID_HANDLE_VALUE,psd);
  1611. if (psd) {free(psd);psd=NULL;}
  1612. }
  1613. }
  1614. }
  1615. return dwStatus;
  1616. }
  1617. // -------------------------------------------------------------------------------------
  1618. // Function: RemovePrincipalFromFileAcl
  1619. //
  1620. // Remove a Access Control Entry from an Access Control List for a file/directory for a
  1621. // particular SID
  1622. //
  1623. // -------------------------------------------------------------------------------------
  1624. DWORD RemovePrincipalFromFileAcl(IN TCHAR *pszFile,IN LPTSTR szPrincipal)
  1625. {
  1626. PACL pdacl;
  1627. SECURITY_DESCRIPTOR_CONTROL sdc;
  1628. PSECURITY_DESCRIPTOR psdRelative = NULL;
  1629. PSECURITY_DESCRIPTOR psdAbsolute = NULL;
  1630. DWORD cbSize = 0;
  1631. BOOL bRes = 0;
  1632. DWORD dwSecurityDescriptorRevision;
  1633. BOOL fHasDacl = FALSE;
  1634. BOOL fDaclDefaulted = FALSE;
  1635. BOOL bUserExistsToBeDeleted;
  1636. DWORD dwError = ERROR_SUCCESS;
  1637. // get the size of the security descriptor
  1638. if ( !(bRes = GetFileSecurity(pszFile,DACL_SECURITY_INFORMATION,psdRelative,0,&cbSize)) )
  1639. {
  1640. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  1641. {
  1642. psdRelative = malloc(cbSize);
  1643. if (!psdRelative)
  1644. {
  1645. return ERROR_INSUFFICIENT_BUFFER;
  1646. }
  1647. bRes = GetFileSecurity(pszFile,DACL_SECURITY_INFORMATION,psdRelative,cbSize,&cbSize);
  1648. }
  1649. }
  1650. if (!bRes)
  1651. {
  1652. if (psdRelative)
  1653. {
  1654. free(psdRelative);
  1655. }
  1656. return (GetLastError());
  1657. }
  1658. // get security descriptor control from the security descriptor
  1659. if (!GetSecurityDescriptorControl(psdRelative, (PSECURITY_DESCRIPTOR_CONTROL) &sdc,(LPDWORD) &dwSecurityDescriptorRevision))
  1660. {
  1661. dwError = GetLastError();
  1662. }
  1663. else if (SE_DACL_PRESENT & sdc)
  1664. {
  1665. // Acl's are present, so we will attempt to remove the one passes in.
  1666. if (GetSecurityDescriptorDacl(psdRelative, (LPBOOL) &fHasDacl,(PACL *) &pdacl, (LPBOOL) &fDaclDefaulted))
  1667. {
  1668. // Remove ACE from Acl
  1669. dwError = RemovePrincipalFromACL(pdacl,szPrincipal,&bUserExistsToBeDeleted);
  1670. if (dwError == ERROR_SUCCESS)
  1671. {
  1672. psdAbsolute = (PSECURITY_DESCRIPTOR) malloc(GetSecurityDescriptorLength(psdRelative));
  1673. if (psdAbsolute)
  1674. {
  1675. if ( !(InitializeSecurityDescriptor(psdAbsolute, SECURITY_DESCRIPTOR_REVISION)) ||
  1676. !(SetSecurityDescriptorDacl(psdAbsolute, TRUE, pdacl, fDaclDefaulted)) ||
  1677. !(IsValidSecurityDescriptor(psdAbsolute)) ||
  1678. !(SetFileSecurity(pszFile,(SECURITY_INFORMATION)(DACL_SECURITY_INFORMATION),psdAbsolute))
  1679. )
  1680. {
  1681. dwError = GetLastError();
  1682. }
  1683. if (psdAbsolute)
  1684. {
  1685. free(psdAbsolute);
  1686. }
  1687. }
  1688. else
  1689. {
  1690. dwError = ERROR_INSUFFICIENT_BUFFER;
  1691. }
  1692. }
  1693. }
  1694. else
  1695. {
  1696. dwError = GetLastError();
  1697. }
  1698. }
  1699. if (psdRelative)
  1700. {
  1701. free(psdRelative);
  1702. }
  1703. return dwError;
  1704. }
  1705. DWORD SetAccessOnDirOrFile(IN TCHAR *pszFile,PSID psidGroup,INT iAceType,DWORD dwAccessMask,DWORD dwInheritMask,PSECURITY_DESCRIPTOR* ppsd)
  1706. {
  1707. PSECURITY_DESCRIPTOR psdAbsolute = NULL;
  1708. PACL pdacl;
  1709. DWORD cbSecurityDescriptor = 0;
  1710. DWORD dwSecurityDescriptorRevision;
  1711. DWORD cbDacl = 0;
  1712. SECURITY_DESCRIPTOR_CONTROL sdc;
  1713. PACL pdaclNew = NULL;
  1714. DWORD cbAddDaclLength = 0;
  1715. BOOL fAceFound = FALSE;
  1716. BOOL fHasDacl = FALSE;
  1717. BOOL fDaclDefaulted = FALSE;
  1718. ACCESS_ALLOWED_ACE* pAce;
  1719. DWORD i;
  1720. BOOL fAceForGroupPresent = FALSE;
  1721. DWORD dwMask;
  1722. PSECURITY_DESCRIPTOR psdRelative = NULL;
  1723. DWORD cbSize = 0;
  1724. BOOL bRes = 0;
  1725. // get the size of the security descriptor
  1726. bRes = GetFileSecurity(pszFile,DACL_SECURITY_INFORMATION,psdRelative,0,&cbSize);
  1727. DWORD dwError = GetLastError();
  1728. if (ERROR_INSUFFICIENT_BUFFER == dwError)
  1729. {
  1730. psdRelative = malloc(cbSize);
  1731. if (!psdRelative)
  1732. {
  1733. return ERROR_INSUFFICIENT_BUFFER;
  1734. }
  1735. bRes = GetFileSecurity(pszFile,DACL_SECURITY_INFORMATION,psdRelative,cbSize,&cbSize);
  1736. }
  1737. if (!bRes)
  1738. {
  1739. if (psdRelative){free(psdRelative);}
  1740. return (GetLastError());
  1741. }
  1742. // get security descriptor control from the security descriptor
  1743. if (!GetSecurityDescriptorControl(psdRelative, (PSECURITY_DESCRIPTOR_CONTROL) &sdc,(LPDWORD) &dwSecurityDescriptorRevision))
  1744. {
  1745. return (GetLastError());
  1746. }
  1747. // check if DACL is present
  1748. if (SE_DACL_PRESENT & sdc)
  1749. {
  1750. ACE_HEADER *pAceHeader;
  1751. // get dacl
  1752. if (!GetSecurityDescriptorDacl(psdRelative, (LPBOOL) &fHasDacl,(PACL *) &pdacl, (LPBOOL) &fDaclDefaulted))
  1753. {
  1754. return ( GetLastError());
  1755. }
  1756. // check if pdacl is null
  1757. // if it is then security is wide open -- this could be a fat drive.
  1758. if (NULL == pdacl)
  1759. {
  1760. return ERROR_SUCCESS;
  1761. }
  1762. // get dacl length
  1763. cbDacl = pdacl->AclSize;
  1764. // now check if SID's ACE is there
  1765. for (i = 0; i < pdacl->AceCount; i++)
  1766. {
  1767. if (!GetAce(pdacl, i, (LPVOID *) &pAce))
  1768. {
  1769. return ( GetLastError());
  1770. }
  1771. pAceHeader = (ACE_HEADER *)pAce;
  1772. // check if group sid is already there
  1773. if (EqualSid((PSID) &(pAce->SidStart), psidGroup))
  1774. {
  1775. if (ACCESS_DENIED_ACE_TYPE == iAceType)
  1776. {
  1777. if (pAceHeader->AceType == ACCESS_DENIED_ACE_TYPE)
  1778. {
  1779. // If the correct access is present, return success
  1780. if ((pAce->Mask & dwAccessMask) == dwAccessMask)
  1781. {
  1782. return ERROR_SUCCESS;
  1783. }
  1784. fAceForGroupPresent = TRUE;
  1785. break;
  1786. }
  1787. }
  1788. else
  1789. {
  1790. if (pAceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
  1791. {
  1792. // If the correct access is present, return success
  1793. if ((pAce->Mask & dwAccessMask) == dwAccessMask)
  1794. {
  1795. return ERROR_SUCCESS;
  1796. }
  1797. fAceForGroupPresent = TRUE;
  1798. break;
  1799. }
  1800. }
  1801. }
  1802. }
  1803. // if the group did not exist, we will need to add room
  1804. // for another ACE
  1805. if (!fAceForGroupPresent)
  1806. {
  1807. // get length of new DACL
  1808. cbAddDaclLength = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(psidGroup);
  1809. }
  1810. }
  1811. else
  1812. {
  1813. // get length of new DACL
  1814. cbAddDaclLength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid (psidGroup);
  1815. }
  1816. // get memory needed for new DACL
  1817. pdaclNew = (PACL) malloc (cbDacl + cbAddDaclLength);
  1818. if (!pdaclNew)
  1819. {
  1820. return (GetLastError());
  1821. }
  1822. // get the sd length
  1823. cbSecurityDescriptor = GetSecurityDescriptorLength(psdRelative);
  1824. // get memory for new SD
  1825. psdAbsolute = (PSECURITY_DESCRIPTOR) malloc(cbSecurityDescriptor + cbAddDaclLength);
  1826. if (!psdAbsolute)
  1827. {
  1828. dwError = GetLastError();
  1829. goto ErrorExit;
  1830. }
  1831. // change self-relative SD to absolute by making new SD
  1832. if (!InitializeSecurityDescriptor(psdAbsolute, SECURITY_DESCRIPTOR_REVISION))
  1833. {
  1834. dwError = GetLastError();
  1835. goto ErrorExit;
  1836. }
  1837. // init new DACL
  1838. if (!InitializeAcl(pdaclNew, cbDacl + cbAddDaclLength, ACL_REVISION))
  1839. {
  1840. dwError = GetLastError();
  1841. goto ErrorExit;
  1842. }
  1843. // Add a new ACE for our SID if one was not already present
  1844. if ( (!fAceForGroupPresent) && (ACCESS_DENIED_ACE_TYPE == iAceType) )
  1845. {
  1846. if (!AddAccessDeniedAce(pdaclNew, ACL_REVISION, dwAccessMask,psidGroup))
  1847. {
  1848. dwError = GetLastError();
  1849. goto ErrorExit;
  1850. }
  1851. }
  1852. // now add in all of the ACEs into the new DACL (if org DACL is there)
  1853. if (SE_DACL_PRESENT & sdc)
  1854. {
  1855. ACE_HEADER *pAceHeader;
  1856. for (i = 0; i < pdacl->AceCount; i++)
  1857. {
  1858. // get ace from original dacl
  1859. if (!GetAce(pdacl, i, (LPVOID*) &pAce))
  1860. {
  1861. dwError = GetLastError();
  1862. goto ErrorExit;
  1863. }
  1864. pAceHeader = (ACE_HEADER *)pAce;
  1865. if (pAceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
  1866. {
  1867. dwMask = pAce->Mask;
  1868. if (ACCESS_ALLOWED_ACE_TYPE == iAceType)
  1869. {
  1870. // If an ACE for our SID exists, we just need to bump
  1871. // up the access level instead of creating a new ACE
  1872. if (EqualSid((PSID) &(pAce->SidStart), psidGroup))
  1873. {
  1874. dwMask = dwAccessMask | pAce->Mask;
  1875. }
  1876. }
  1877. if (!AddAccessAllowedAceEx(pdaclNew, ACL_REVISION, pAce->Header.AceFlags,dwMask,(PSID) &(pAce->SidStart)))
  1878. {
  1879. dwError = GetLastError();
  1880. goto ErrorExit;
  1881. }
  1882. }
  1883. else if (pAceHeader->AceType == ACCESS_DENIED_ACE_TYPE)
  1884. {
  1885. dwMask = pAce->Mask;
  1886. if (ACCESS_DENIED_ACE_TYPE == iAceType)
  1887. {
  1888. // If an ACE for our SID exists, we just need to bump
  1889. // up the access level instead of creating a new ACE
  1890. if (EqualSid((PSID) &(pAce->SidStart), psidGroup))
  1891. {
  1892. dwMask = dwAccessMask | pAce->Mask;
  1893. }
  1894. }
  1895. if (!AddAccessDeniedAceEx(pdaclNew, ACL_REVISION, pAce->Header.AceFlags,dwMask,(PSID) &(pAce->SidStart)))
  1896. {
  1897. dwError = GetLastError();
  1898. goto ErrorExit;
  1899. }
  1900. }
  1901. else
  1902. {
  1903. // copy denied or audit ace.
  1904. if (!AddAce(pdaclNew, ACL_REVISION, 0xFFFFFFFF,pAce, pAceHeader->AceSize ))
  1905. {
  1906. dwError = GetLastError();
  1907. goto ErrorExit;
  1908. }
  1909. }
  1910. //iisDebugOut((LOG_TYPE_TRACE, _T("OrgAce[%d]=0x%x\n"),i,pAce->Header.AceFlags));
  1911. }
  1912. }
  1913. // Add a new ACE for our SID if one was not already present
  1914. if ( (!fAceForGroupPresent) && (ACCESS_ALLOWED_ACE_TYPE == iAceType) )
  1915. {
  1916. if (!AddAccessAllowedAce(pdaclNew, ACL_REVISION, dwAccessMask,psidGroup))
  1917. {
  1918. dwError = GetLastError();
  1919. goto ErrorExit;
  1920. }
  1921. }
  1922. // change the header on an existing ace to have inherit
  1923. for (i = 0; i < pdaclNew->AceCount; i++)
  1924. {
  1925. if (!GetAce(pdaclNew, i, (LPVOID *) &pAce))
  1926. {
  1927. return ( GetLastError());
  1928. }
  1929. // CONTAINER_INHERIT_ACE = Other containers that are contained by the primary object inherit the entry.
  1930. // 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.
  1931. // NO_PROPAGATE_INHERIT_ACE = The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE flags are not propagated to an inherited entry.
  1932. // OBJECT_INHERIT_ACE = Noncontainer objects contained by the primary object inherit the entry.
  1933. // 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.
  1934. // SUB_OBJECTS_ONLY_INHERIT = Noncontainer objects contained by the primary object inherit the entry. This flag corresponds to the OBJECT_INHERIT_ACE flag.
  1935. // 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.
  1936. //iisDebugOut((LOG_TYPE_TRACE, _T("NewAce[%d]=0x%x\n"),i,pAce->Header.AceFlags));
  1937. // if it's our SID, then change the header to be inherited
  1938. if (EqualSid((PSID) &(pAce->SidStart), psidGroup))
  1939. {
  1940. pAce->Header.AceFlags |= dwInheritMask;
  1941. }
  1942. }
  1943. // check if everything went ok
  1944. if (!IsValidAcl(pdaclNew))
  1945. {
  1946. dwError = ERROR_INVALID_ACL;
  1947. goto ErrorExit;
  1948. }
  1949. // now set security descriptor DACL
  1950. if (!SetSecurityDescriptorDacl(psdAbsolute, TRUE, pdaclNew, fDaclDefaulted))
  1951. {
  1952. dwError = GetLastError();
  1953. goto ErrorExit;
  1954. }
  1955. // check if everything went ok
  1956. if (!IsValidSecurityDescriptor(psdAbsolute))
  1957. {
  1958. dwError = ERROR_INVALID_SECURITY_DESCR;
  1959. goto ErrorExit;
  1960. }
  1961. // now set the reg key security (this will overwrite any existing security)
  1962. bRes = SetFileSecurity(pszFile,(SECURITY_INFORMATION)(DACL_SECURITY_INFORMATION),psdAbsolute);
  1963. if (bRes)
  1964. {
  1965. dwError = ERROR_SUCCESS;
  1966. }
  1967. if (ppsd)
  1968. {
  1969. *ppsd = psdRelative;
  1970. }
  1971. ErrorExit:
  1972. // free memory
  1973. if (psdAbsolute)
  1974. {
  1975. free (psdAbsolute);
  1976. if (pdaclNew)
  1977. {
  1978. free((VOID*) pdaclNew);
  1979. }
  1980. }
  1981. return dwError;
  1982. }
  1983. //+--------------------------------------------------------------------------
  1984. //
  1985. // Function: SetAccessOnRegKey
  1986. //
  1987. // Purpose: Adds access for a specified SID to a registry key
  1988. //
  1989. // Arguments:
  1990. // hkey [in] The registry key that will receive the
  1991. // modified security descriptor
  1992. // psidGroup [in] The SID (in self-relative mode) that will be
  1993. // granted access to the key
  1994. // dwAccessMask [in] The access level to grant
  1995. // ppsd [out] The previous security descriptor
  1996. //
  1997. // Returns: DWORD. ERROR_SUCCESS or a failure code from winerror.h
  1998. //
  1999. //+--------------------------------------------------------------------------
  2000. DWORD
  2001. SetAccessOnRegKey(HKEY hkey, PSID psidGroup,
  2002. DWORD dwAccessMask,
  2003. DWORD dwInheritMask,
  2004. PSECURITY_DESCRIPTOR* ppsd)
  2005. {
  2006. PSECURITY_DESCRIPTOR psdAbsolute = NULL;
  2007. PACL pdacl;
  2008. DWORD cbSecurityDescriptor = 0;
  2009. DWORD dwSecurityDescriptorRevision;
  2010. DWORD cbDacl = 0;
  2011. SECURITY_DESCRIPTOR_CONTROL sdc;
  2012. PACL pdaclNew = NULL;
  2013. DWORD cbAddDaclLength = 0;
  2014. BOOL fAceFound = FALSE;
  2015. BOOL fHasDacl = FALSE;
  2016. BOOL fDaclDefaulted = FALSE;
  2017. ACCESS_ALLOWED_ACE* pAce;
  2018. DWORD i;
  2019. BOOL fAceForGroupPresent = FALSE;
  2020. DWORD dwMask;
  2021. PSECURITY_DESCRIPTOR psdRelative = NULL;
  2022. DWORD cbSize = 0;
  2023. // Get the current security descriptor for hkey
  2024. //
  2025. DWORD dwError = RegGetKeySecurity(hkey, DACL_SECURITY_INFORMATION, psdRelative, &cbSize);
  2026. if (ERROR_INSUFFICIENT_BUFFER == dwError)
  2027. {
  2028. psdRelative = malloc(cbSize);
  2029. if (!psdRelative)
  2030. {
  2031. return ERROR_INSUFFICIENT_BUFFER;
  2032. }
  2033. dwError = RegGetKeySecurity(hkey, DACL_SECURITY_INFORMATION, psdRelative, &cbSize);
  2034. }
  2035. // get security descriptor control from the security descriptor
  2036. if ( (!psdRelative) ||
  2037. (dwError != ERROR_SUCCESS) ||
  2038. (!GetSecurityDescriptorControl(psdRelative, (PSECURITY_DESCRIPTOR_CONTROL) &sdc,(LPDWORD) &dwSecurityDescriptorRevision))
  2039. )
  2040. {
  2041. return (GetLastError());
  2042. }
  2043. // check if DACL is present
  2044. if (SE_DACL_PRESENT & sdc)
  2045. {
  2046. ACE_HEADER *pAceHeader;
  2047. // get dacl
  2048. if (!GetSecurityDescriptorDacl(psdRelative, (LPBOOL) &fHasDacl,(PACL *) &pdacl, (LPBOOL) &fDaclDefaulted))
  2049. {
  2050. return ( GetLastError());
  2051. }
  2052. // check if pdacl is null
  2053. // if it is then security is wide open -- this could be a fat drive.
  2054. if (NULL == pdacl)
  2055. {
  2056. return ERROR_SUCCESS;
  2057. }
  2058. // get dacl length
  2059. cbDacl = pdacl->AclSize;
  2060. // now check if SID's ACE is there
  2061. for (i = 0; i < pdacl->AceCount; i++)
  2062. {
  2063. if (!GetAce(pdacl, i, (LPVOID *) &pAce))
  2064. {
  2065. return ( GetLastError());
  2066. }
  2067. pAceHeader = (ACE_HEADER *)pAce;
  2068. if (pAceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
  2069. {
  2070. // check if group sid is already there
  2071. if (EqualSid((PSID) &(pAce->SidStart), psidGroup))
  2072. {
  2073. // If the correct access is present, return success
  2074. if ((pAce->Mask & dwAccessMask) == dwAccessMask)
  2075. {
  2076. return ERROR_SUCCESS;
  2077. }
  2078. fAceForGroupPresent = TRUE;
  2079. break;
  2080. }
  2081. }
  2082. }
  2083. // if the group did not exist, we will need to add room
  2084. // for another ACE
  2085. if (!fAceForGroupPresent)
  2086. {
  2087. // get length of new DACL
  2088. cbAddDaclLength = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(psidGroup);
  2089. }
  2090. }
  2091. else
  2092. {
  2093. // get length of new DACL
  2094. cbAddDaclLength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid (psidGroup);
  2095. }
  2096. // get memory needed for new DACL
  2097. pdaclNew = (PACL) malloc (cbDacl + cbAddDaclLength);
  2098. if (!pdaclNew)
  2099. {
  2100. return (GetLastError());
  2101. }
  2102. // get the sd length
  2103. cbSecurityDescriptor = GetSecurityDescriptorLength(psdRelative);
  2104. // get memory for new SD
  2105. psdAbsolute = (PSECURITY_DESCRIPTOR) malloc(cbSecurityDescriptor + cbAddDaclLength);
  2106. if (!psdAbsolute)
  2107. {
  2108. dwError = GetLastError();
  2109. goto ErrorExit;
  2110. }
  2111. // change self-relative SD to absolute by making new SD
  2112. if (!InitializeSecurityDescriptor(psdAbsolute, SECURITY_DESCRIPTOR_REVISION))
  2113. {
  2114. dwError = GetLastError();
  2115. goto ErrorExit;
  2116. }
  2117. // init new DACL
  2118. if (!InitializeAcl(pdaclNew, cbDacl + cbAddDaclLength, ACL_REVISION))
  2119. {
  2120. dwError = GetLastError();
  2121. goto ErrorExit;
  2122. }
  2123. // now add in all of the ACEs into the new DACL (if org DACL is there)
  2124. if (SE_DACL_PRESENT & sdc)
  2125. {
  2126. ACE_HEADER *pAceHeader;
  2127. for (i = 0; i < pdacl->AceCount; i++)
  2128. {
  2129. // get ace from original dacl
  2130. if (!GetAce(pdacl, i, (LPVOID*) &pAce))
  2131. {
  2132. dwError = GetLastError();
  2133. goto ErrorExit;
  2134. }
  2135. pAceHeader = (ACE_HEADER *)pAce;
  2136. if (pAceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
  2137. {
  2138. // If an ACE for our SID exists, we just need to bump
  2139. // up the access level instead of creating a new ACE
  2140. //
  2141. if (EqualSid((PSID) &(pAce->SidStart), psidGroup))
  2142. {
  2143. dwMask = dwAccessMask | pAce->Mask;
  2144. }
  2145. else
  2146. {
  2147. dwMask = pAce->Mask;
  2148. }
  2149. //iisDebugOut((LOG_TYPE_TRACE, _T("OrgAce[%d]=0x%x\n"),i,pAce->Header.AceFlags));
  2150. // now add ace to new dacl
  2151. if (!AddAccessAllowedAceEx(pdaclNew, ACL_REVISION, pAce->Header.AceFlags,dwMask,(PSID) &(pAce->SidStart)))
  2152. {
  2153. dwError = GetLastError();
  2154. goto ErrorExit;
  2155. }
  2156. }
  2157. else
  2158. {
  2159. // copy denied or audit ace.
  2160. if (!AddAce(pdaclNew, ACL_REVISION, 0xFFFFFFFF, pAce, pAceHeader->AceSize ))
  2161. {
  2162. dwError = GetLastError();
  2163. goto ErrorExit;
  2164. }
  2165. }
  2166. }
  2167. }
  2168. // Add a new ACE for our SID if one was not already present
  2169. if (!fAceForGroupPresent)
  2170. {
  2171. // now add new ACE to new DACL
  2172. if (!AddAccessAllowedAce(pdaclNew, ACL_REVISION, dwAccessMask,psidGroup))
  2173. {
  2174. dwError = GetLastError();
  2175. goto ErrorExit;
  2176. }
  2177. }
  2178. // change the header on an existing ace to have inherit
  2179. for (i = 0; i < pdaclNew->AceCount; i++)
  2180. {
  2181. if (!GetAce(pdaclNew, i, (LPVOID *) &pAce))
  2182. {
  2183. return ( GetLastError());
  2184. }
  2185. // CONTAINER_INHERIT_ACE = Other containers that are contained by the primary object inherit the entry.
  2186. // 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.
  2187. // NO_PROPAGATE_INHERIT_ACE = The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE flags are not propagated to an inherited entry.
  2188. // OBJECT_INHERIT_ACE = Noncontainer objects contained by the primary object inherit the entry.
  2189. // 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.
  2190. // SUB_OBJECTS_ONLY_INHERIT = Noncontainer objects contained by the primary object inherit the entry. This flag corresponds to the OBJECT_INHERIT_ACE flag.
  2191. // 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.
  2192. //iisDebugOut((LOG_TYPE_TRACE, _T("NewAce[%d]=0x%x\n"),i,pAce->Header.AceFlags));
  2193. // if it's our SID, then change the header to be inherited
  2194. if (EqualSid((PSID) &(pAce->SidStart), psidGroup))
  2195. {
  2196. //pAce->Header.AceFlags |= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE | INHERITED_ACE;
  2197. //pAce->Header.AceFlags |= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE | dwInheritMask;
  2198. pAce->Header.AceFlags |= dwInheritMask;
  2199. }
  2200. }
  2201. // check if everything went ok
  2202. if (!IsValidAcl(pdaclNew))
  2203. {
  2204. dwError = ERROR_INVALID_ACL;
  2205. goto ErrorExit;
  2206. }
  2207. // now set security descriptor DACL
  2208. if (!SetSecurityDescriptorDacl(psdAbsolute, TRUE, pdaclNew, fDaclDefaulted))
  2209. {
  2210. dwError = GetLastError();
  2211. goto ErrorExit;
  2212. }
  2213. // check if everything went ok
  2214. if (!IsValidSecurityDescriptor(psdAbsolute))
  2215. {
  2216. dwError = ERROR_INVALID_SECURITY_DESCR;
  2217. goto ErrorExit;
  2218. }
  2219. // now set the reg key security (this will overwrite any
  2220. // existing security)
  2221. dwError = RegSetKeySecurity(hkey, (SECURITY_INFORMATION)(DACL_SECURITY_INFORMATION), psdAbsolute);
  2222. if (ppsd)
  2223. {
  2224. *ppsd = psdRelative;
  2225. }
  2226. ErrorExit:
  2227. // free memory
  2228. if (psdAbsolute)
  2229. {
  2230. free (psdAbsolute);
  2231. if (pdaclNew)
  2232. {
  2233. free((VOID*) pdaclNew);
  2234. }
  2235. }
  2236. return dwError;
  2237. }
  2238. BOOL
  2239. AddUserAccessToSD(
  2240. IN PSECURITY_DESCRIPTOR pSd,
  2241. IN PSID pSid,
  2242. IN DWORD NewAccess,
  2243. IN UCHAR TheAceType,
  2244. OUT PSECURITY_DESCRIPTOR *ppSdNew
  2245. )
  2246. {
  2247. ULONG i;
  2248. BOOL bReturn = FALSE;
  2249. BOOL Result;
  2250. BOOL DaclPresent;
  2251. BOOL DaclDefaulted;
  2252. DWORD Length;
  2253. DWORD NewAclLength;
  2254. ACCESS_ALLOWED_ACE* OldAce;
  2255. PACE_HEADER NewAce;
  2256. ACL_SIZE_INFORMATION AclInfo;
  2257. PACL Dacl = NULL;
  2258. PACL NewDacl = NULL;
  2259. PACL NewAceDacl = NULL;
  2260. PSECURITY_DESCRIPTOR NewSD = NULL;
  2261. PSECURITY_DESCRIPTOR OldSD = NULL;
  2262. PSECURITY_DESCRIPTOR outpSD = NULL;
  2263. DWORD cboutpSD = 0;
  2264. BOOL fAceForGroupPresent = FALSE;
  2265. DWORD dwMask;
  2266. OldSD = pSd;
  2267. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("AddUserAccessToSD start\n")));
  2268. // only do if the ace is allowed/denied
  2269. if (ACCESS_ALLOWED_ACE_TYPE != TheAceType && ACCESS_DENIED_ACE_TYPE != TheAceType)
  2270. {
  2271. iisDebugOut((LOG_TYPE_TRACE, _T("AddUserAccessToSD useless param\n")));
  2272. goto AddUserAccessToSD_Exit;
  2273. }
  2274. // Convert SecurityDescriptor to absolute format. It generates
  2275. // a new SecurityDescriptor for its output which we must free.
  2276. if ( !MakeAbsoluteCopyFromRelative(OldSD, &NewSD) )
  2277. {
  2278. iisDebugOut((LOG_TYPE_ERROR, _T("MakeAbsoluteCopyFromRelative failed\n")));
  2279. goto AddUserAccessToSD_Exit;
  2280. }
  2281. // Must get DACL pointer from new (absolute) SD
  2282. if(!GetSecurityDescriptorDacl(NewSD,&DaclPresent,&Dacl,&DaclDefaulted))
  2283. {
  2284. iisDebugOut((LOG_TYPE_ERROR, _T("GetSecurityDescriptorDacl failed with 0x%x\n"),GetLastError()));
  2285. goto AddUserAccessToSD_Exit;
  2286. }
  2287. // If no DACL, no need to add the user since no DACL
  2288. // means all accesss
  2289. if( !DaclPresent )
  2290. {
  2291. bReturn = TRUE;
  2292. goto AddUserAccessToSD_Exit;
  2293. }
  2294. // Code can return DaclPresent, but a NULL which means
  2295. // a NULL Dacl is present. This allows all access to the object.
  2296. if( Dacl == NULL )
  2297. {
  2298. bReturn = TRUE;
  2299. goto AddUserAccessToSD_Exit;
  2300. }
  2301. // Get the current ACL's size
  2302. if( !GetAclInformation(Dacl,&AclInfo,sizeof(AclInfo),AclSizeInformation) )
  2303. {
  2304. iisDebugOut((LOG_TYPE_ERROR, _T("GetAclInformation failed with 0x%x\n"),GetLastError()));
  2305. goto AddUserAccessToSD_Exit;
  2306. }
  2307. // Check if access is already there
  2308. // --------------------------------
  2309. // Check to see if this SID already exists in there
  2310. // if it does (and it has the right access we want) then forget it, we don't have to do anything more.
  2311. for (i = 0; i < AclInfo.AceCount; i++)
  2312. {
  2313. ACE_HEADER *pAceHeader;
  2314. ACCESS_ALLOWED_ACE* pAce = NULL;
  2315. if (!GetAce(Dacl, i, (LPVOID *) &pAce))
  2316. {
  2317. iisDebugOut((LOG_TYPE_ERROR, _T("GetAce failed with 0x%x\n"),GetLastError()));
  2318. goto AddUserAccessToSD_Exit;
  2319. }
  2320. pAceHeader = (ACE_HEADER *)pAce;
  2321. // check if group sid is already there
  2322. if (EqualSid((PSID) &(pAce->SidStart), pSid))
  2323. {
  2324. if (pAceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
  2325. {
  2326. // If the correct access is present, return success
  2327. if ((pAce->Mask & NewAccess) == NewAccess)
  2328. {
  2329. //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)));
  2330. bReturn = TRUE;
  2331. goto AddUserAccessToSD_Exit;
  2332. }
  2333. else
  2334. {
  2335. // the ace that exist doesn't have the permissions that we want.
  2336. // If an ACE for our SID exists, we just need to bump
  2337. // up the access level instead of creating a new ACE
  2338. fAceForGroupPresent = TRUE;
  2339. }
  2340. }
  2341. break;
  2342. }
  2343. }
  2344. // If we have to create a new ACE
  2345. // (because our user isn't listed in the existing ACL)
  2346. // then let's Create a new ACL to put the new access allowed ACE on
  2347. // --------------------------------
  2348. if (!fAceForGroupPresent)
  2349. {
  2350. NewAclLength = sizeof(ACL) +
  2351. sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG) +
  2352. GetLengthSid( pSid );
  2353. NewAceDacl = (PACL) LocalAlloc( LMEM_FIXED, NewAclLength );
  2354. if ( NewAceDacl == NULL )
  2355. {
  2356. iisDebugOut((LOG_TYPE_ERROR, _T("LocalAlloc failed\n")));
  2357. goto AddUserAccessToSD_Exit;
  2358. }
  2359. if(!InitializeAcl( NewAceDacl, NewAclLength, ACL_REVISION ))
  2360. {
  2361. iisDebugOut((LOG_TYPE_ERROR, _T("InitializeAcl failed with 0x%x\n"),GetLastError()));
  2362. goto AddUserAccessToSD_Exit;
  2363. }
  2364. if (ACCESS_DENIED_ACE_TYPE == TheAceType)
  2365. {
  2366. Result = AddAccessDeniedAce(NewAceDacl,ACL_REVISION,NewAccess,pSid);
  2367. }
  2368. else
  2369. {
  2370. Result = AddAccessAllowedAce(NewAceDacl,ACL_REVISION,NewAccess,pSid);
  2371. }
  2372. if( !Result )
  2373. {
  2374. iisDebugOut((LOG_TYPE_ERROR, _T("AddAccessAllowedAce failed with 0x%x\n"),GetLastError()));
  2375. goto AddUserAccessToSD_Exit;
  2376. }
  2377. // Grab the 1st ace from the Newly created Dacl
  2378. if(!GetAce( NewAceDacl, 0, (void **)&NewAce ))
  2379. {
  2380. iisDebugOut((LOG_TYPE_ERROR, _T("GetAce failed with 0x%x\n"),GetLastError()));
  2381. goto AddUserAccessToSD_Exit;
  2382. }
  2383. // add CONTAINER_INHERIT_ACE TO AceFlags
  2384. //NewAce->AceFlags |= CONTAINER_INHERIT_ACE;
  2385. Length = AclInfo.AclBytesInUse + NewAce->AceSize;
  2386. }
  2387. else
  2388. {
  2389. Length = AclInfo.AclBytesInUse;
  2390. }
  2391. // Allocate new DACL
  2392. NewDacl = (PACL) LocalAlloc( LMEM_FIXED, Length );
  2393. if(NewDacl == NULL)
  2394. {
  2395. iisDebugOut((LOG_TYPE_ERROR, _T("LocalAlloc failed\n")));
  2396. goto AddUserAccessToSD_Exit;
  2397. }
  2398. if(!InitializeAcl( NewDacl, Length, ACL_REVISION ))
  2399. {
  2400. iisDebugOut((LOG_TYPE_ERROR, _T("InitializeAcl failed with 0x%x\n"),GetLastError()));
  2401. goto AddUserAccessToSD_Exit;
  2402. }
  2403. // Insert new ACE at the front of the new DACL
  2404. if (!fAceForGroupPresent)
  2405. {
  2406. if(!AddAce( NewDacl, ACL_REVISION, 0, NewAce, NewAce->AceSize ))
  2407. {
  2408. iisDebugOut((LOG_TYPE_ERROR, _T("AddAce failed with 0x%x\n"),GetLastError()));
  2409. goto AddUserAccessToSD_Exit;
  2410. }
  2411. }
  2412. // ----------------------------------------
  2413. // Read thru the old Dacl and get the ACE's
  2414. // add it to the new Dacl
  2415. // ----------------------------------------
  2416. for ( i = 0; i < AclInfo.AceCount; i++ )
  2417. {
  2418. ACE_HEADER *pAceHeader;
  2419. Result = GetAce( Dacl, i, (LPVOID*) &OldAce );
  2420. if( !Result )
  2421. {
  2422. iisDebugOut((LOG_TYPE_ERROR, _T("GetAce failed with 0x%x\n"),GetLastError()));
  2423. goto AddUserAccessToSD_Exit;
  2424. }
  2425. pAceHeader = (ACE_HEADER *)OldAce;
  2426. // If an ACE for our SID exists, we just need to bump
  2427. // up the access level instead of creating a new ACE
  2428. //
  2429. if (pAceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
  2430. {
  2431. dwMask = OldAce->Mask;
  2432. if (fAceForGroupPresent)
  2433. {
  2434. if (EqualSid((PSID) &(OldAce->SidStart), pSid))
  2435. {
  2436. dwMask = NewAccess | OldAce->Mask;
  2437. }
  2438. }
  2439. // now add ace to new dacl
  2440. Result = AddAccessAllowedAceEx(NewDacl, ACL_REVISION, OldAce->Header.AceFlags,dwMask,(PSID) &(OldAce->SidStart));
  2441. if( !Result )
  2442. {
  2443. iisDebugOut((LOG_TYPE_ERROR, _T("AddAccessAllowedAceEx failed with 0x%x\n"),GetLastError()));
  2444. goto AddUserAccessToSD_Exit;
  2445. }
  2446. }
  2447. else
  2448. {
  2449. // copy denied or audit ace.
  2450. if (!AddAce(NewDacl, ACL_REVISION, 0xFFFFFFFF,OldAce, pAceHeader->AceSize ))
  2451. {
  2452. iisDebugOut((LOG_TYPE_ERROR, _T("AddAce failed with 0x%x\n"),GetLastError()));
  2453. goto AddUserAccessToSD_Exit;
  2454. }
  2455. }
  2456. }
  2457. // Set new DACL for Security Descriptor
  2458. if(!SetSecurityDescriptorDacl(NewSD,TRUE,NewDacl,FALSE))
  2459. {
  2460. iisDebugOut((LOG_TYPE_ERROR, _T("SetSecurityDescriptorDacl failed with 0x%x\n"),GetLastError()));
  2461. goto AddUserAccessToSD_Exit;
  2462. }
  2463. // The new SD is in absolute format. change it to Relative before we pass it back
  2464. cboutpSD = 0;
  2465. MakeSelfRelativeSD(NewSD, outpSD, &cboutpSD);
  2466. outpSD = (PSECURITY_DESCRIPTOR)GlobalAlloc(GPTR, cboutpSD);
  2467. if ( !outpSD )
  2468. {
  2469. iisDebugOut((LOG_TYPE_ERROR, _T("GlobalAlloc failed\n")));
  2470. goto AddUserAccessToSD_Exit;
  2471. }
  2472. if (!MakeSelfRelativeSD(NewSD, outpSD, &cboutpSD))
  2473. {
  2474. iisDebugOut((LOG_TYPE_ERROR, _T("MakeSelfRelativeSD failed with 0x%x\n"),GetLastError()));
  2475. goto AddUserAccessToSD_Exit;
  2476. }
  2477. // The new SD is passed back in relative format,
  2478. *ppSdNew = outpSD;
  2479. bReturn = TRUE;
  2480. AddUserAccessToSD_Exit:
  2481. if (NewSD){free( NewSD );NewSD = NULL;}
  2482. if (NewDacl){LocalFree( NewDacl );NewDacl = NULL;}
  2483. if (NewAceDacl){LocalFree( NewAceDacl );NewAceDacl = NULL;}
  2484. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("AddUserAccessToSD end\n")));
  2485. return bReturn;
  2486. }
  2487. DWORD SetRegistryKeySecurityAdmin(HKEY hkey, DWORD samDesired,PSECURITY_DESCRIPTOR* ppsdOld)
  2488. {
  2489. PSID psid;
  2490. SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_NT_AUTHORITY;
  2491. DWORD dwError = ERROR_SUCCESS;
  2492. // Get sid for the local Administrators group
  2493. if (!AllocateAndInitializeSid(&sidAuth, 2,SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,0, 0, 0, 0, 0, 0, &psid) )
  2494. {
  2495. dwError = GetLastError();
  2496. }
  2497. if (ERROR_SUCCESS == dwError)
  2498. {
  2499. // Add all access privileges for the local administrators group
  2500. dwError = SetAccessOnRegKey(hkey, psid, samDesired, CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE | INHERITED_ACE, ppsdOld);
  2501. }
  2502. return dwError;
  2503. }
  2504. DWORD SetRegistryKeySecurity(
  2505. IN HKEY hkeyRootKey,
  2506. IN LPCTSTR szKeyPath,
  2507. IN LPCTSTR szPrincipal,
  2508. IN DWORD dwAccessMask,
  2509. IN DWORD dwInheritMask,
  2510. IN BOOL bDoSubKeys,
  2511. IN LPTSTR szExclusiveList
  2512. )
  2513. {
  2514. DWORD dwStatus;
  2515. HKEY hkeyThisKey;
  2516. DWORD dwKeyIndex;
  2517. DWORD dwSubKeyLen;
  2518. TCHAR szSubKeyName[_MAX_PATH];
  2519. FILETIME FileTime;
  2520. TCHAR *szExclusiveStart;
  2521. BOOL fSetSecurityRec;
  2522. dwStatus = RegOpenKeyEx(hkeyRootKey,szKeyPath,0L,KEY_ALL_ACCESS,&hkeyThisKey);
  2523. if (ERROR_SUCCESS == dwStatus)
  2524. {
  2525. PSID principalSID = NULL;
  2526. BOOL bWellKnownSID = FALSE;
  2527. if (ERROR_SUCCESS == GetPrincipalSID((LPTSTR) szPrincipal, &principalSID, &bWellKnownSID))
  2528. {
  2529. PSECURITY_DESCRIPTOR psd = NULL;
  2530. SetAccessOnRegKey(hkeyThisKey,principalSID,dwAccessMask,dwInheritMask,&psd);
  2531. if (psd) {free(psd);}
  2532. if (bDoSubKeys)
  2533. {
  2534. dwKeyIndex = 0;
  2535. dwSubKeyLen = sizeof(szSubKeyName) / sizeof(TCHAR);
  2536. while (RegEnumKeyEx (hkeyThisKey,dwKeyIndex,szSubKeyName,&dwSubKeyLen,NULL,NULL,NULL,&FileTime) == ERROR_SUCCESS)
  2537. {
  2538. // subkey found so set subkey security
  2539. // attach on the inherited ace attribute since everything under this will be inherited
  2540. dwInheritMask |= INHERITED_ACE;
  2541. fSetSecurityRec = TRUE;
  2542. szExclusiveStart = szExclusiveList;
  2543. while ( szExclusiveStart != NULL )
  2544. {
  2545. szExclusiveStart = _tcsstr(szExclusiveStart,szSubKeyName);
  2546. // If we have found the substring, and the character after it is a NULL terminator or a ',', and
  2547. // it is at the begining of the string, or it had a , before it, then it is a match.
  2548. if ( ( szExclusiveStart != NULL ) &&
  2549. ( ( *(szExclusiveStart + dwSubKeyLen) == '\0' ) || ( *(szExclusiveStart + dwSubKeyLen) == ',' ) ) &&
  2550. ( ( szExclusiveStart == szExclusiveList) || (*(szExclusiveStart - 1) == ',') )
  2551. )
  2552. {
  2553. fSetSecurityRec = FALSE;
  2554. break;
  2555. }
  2556. // Increment to move past current search result
  2557. if (szExclusiveStart)
  2558. {
  2559. szExclusiveStart = szExclusiveStart + dwSubKeyLen;
  2560. }
  2561. }
  2562. if ( fSetSecurityRec )
  2563. {
  2564. dwStatus = SetRegistryKeySecurity(hkeyThisKey,szSubKeyName,szPrincipal,dwAccessMask,dwInheritMask,bDoSubKeys,szExclusiveList);
  2565. }
  2566. // set variables for next call
  2567. dwKeyIndex++;
  2568. dwSubKeyLen = sizeof(szSubKeyName) / sizeof(TCHAR);
  2569. }
  2570. }
  2571. }
  2572. RegCloseKey(hkeyThisKey);
  2573. }
  2574. return dwStatus;
  2575. }
  2576. #endif