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

1330 lines
31 KiB

  1. #include "pch.h"
  2. #pragma hdrstop
  3. #ifndef CSC_ON_NT
  4. #ifndef DBG
  5. #define DBG 0
  6. #endif
  7. #if DBG
  8. #define DEBUG
  9. #else
  10. //if we don't do this DEBUG is defined in shdsys.h....sigh
  11. #define NONDEBUG
  12. #endif
  13. #endif
  14. #include "shdsys.h"
  15. #include "utils.h"
  16. #include "lib3.h"
  17. #include "reint.h"
  18. #include "regstr.h"
  19. #include "record.h"
  20. #include "oslayeru.h"
  21. #define PUBLIC FAR PASCAL
  22. #define PRIVATE NEAR PASCAL
  23. #define cNull 0
  24. #define SIGN_BIT 0x80000000
  25. #define cBackSlash _T('\\')
  26. #define DEFAULT_CACHE_PERCENTAGE 10
  27. extern char vrgchBuff[1024];
  28. extern HWND vhwndMain;
  29. static TCHAR vszTemp[] = _TEXT("TEMP");
  30. static TCHAR vszPrefix[] = _TEXT("C");
  31. static const char vszCSCDirName[]="CSC";
  32. AssertData;
  33. AssertError;
  34. static const _TCHAR szStarDotStar[] = _TEXT("\\*.*");
  35. #ifdef CSC_ON_NT
  36. #else
  37. const TCHAR vszRNAKey[] = REGSTR_PATH_SERVICES "\\RemoteAccess";
  38. const TCHAR vszRNAValue[] = "Remote Connection";
  39. const TCHAR VREDIR_DEVICE_NAME[] = "\\\\.\\VREDIR";
  40. #endif
  41. PWCHAR TempDirs[] = {
  42. L"TEMP",
  43. L"TMP",
  44. L"USERPROFILE",
  45. NULL };
  46. BOOL
  47. GetCSCFixedDisk(
  48. TCHAR *lptzDrive
  49. );
  50. #ifdef LATER
  51. LPSTR PUBLIC LpGetServerPart(
  52. LPSTR lpPath,
  53. LPSTR lpBuff,
  54. int cBuff
  55. )
  56. {
  57. LPSTR lp = lpPath;
  58. char c;
  59. int count;
  60. if ((*lp++ != cBackSlash)||(*lp++ != cBackSlash))
  61. return NULL;
  62. lp = MyStrChr(lp, cBackSlash);
  63. if (cBuff && lp)
  64. {
  65. count = (int)((unsigned long)lp, (unsigned long)lpPath)
  66. count = min(cBuff-1, count);
  67. // Nobody should give us bad cBuff values
  68. Assert(count >=0);
  69. strncpy(lpBuff, lpPath, count);
  70. lpBuff[count] = cNull;
  71. }
  72. return lp; // Points to '\' if succeeded
  73. }
  74. #endif //LATER
  75. LPTSTR PUBLIC LpGetServerPart(
  76. LPTSTR lpPath,
  77. LPTSTR lpBuff,
  78. int cBuff
  79. )
  80. {
  81. LPTSTR lp = lpPath;
  82. if (*(lp+1)!=_T(':'))
  83. return NULL;
  84. if (*(lp+2)!=_T('\\'))
  85. return NULL;
  86. if (cBuff)
  87. {
  88. *lpBuff = *lp;
  89. *(lpBuff+1) = *(lp+1);
  90. *(lpBuff+2) = cNull;
  91. }
  92. lp += 2;
  93. return lp; // Points to '\' if succeeded
  94. }
  95. LPTSTR PUBLIC LpGetNextPathElement(
  96. LPTSTR lpPath,
  97. LPTSTR lpBuff,
  98. int cBuff
  99. )
  100. {
  101. LPTSTR lp;
  102. int bytecount;
  103. if (*lpPath == cBackSlash)
  104. ++lpPath;
  105. lp = MyStrChr(lpPath, cBackSlash);
  106. if (cBuff)
  107. {
  108. // Is this a leaf?
  109. if (lp)
  110. { // No
  111. Assert(*lp == cBackSlash);
  112. bytecount = (int)((ULONG_PTR)lp-(ULONG_PTR)lpPath);
  113. bytecount = min(cBuff-1, bytecount);
  114. }
  115. else // Yes
  116. bytecount = lstrlen(lpPath) * sizeof(_TCHAR);
  117. Assert(bytecount >= 0);
  118. memcpy(lpBuff, lpPath, bytecount);
  119. lpBuff[bytecount/sizeof(_TCHAR)] = cNull;
  120. }
  121. return lp;
  122. }
  123. LPTSTR PUBLIC GetLeafPtr(
  124. LPTSTR lpPath
  125. )
  126. {
  127. LPTSTR lp, lpLeaf;
  128. // Prune the server part
  129. if (!(lp=LpGetServerPart(lpPath, NULL, 0)))
  130. lp = lpPath;
  131. for (;lp;)
  132. {
  133. // Step over the '\'
  134. if (*lp==cBackSlash)
  135. lp++;
  136. // call this the leaf, pending confirmation
  137. lpLeaf = lp;
  138. // See if there is another element
  139. lp = LpGetNextPathElement(lp, NULL, 0);
  140. }
  141. return (lpLeaf);
  142. }
  143. //
  144. //
  145. LPTSTR
  146. LpBreakPath(
  147. LPTSTR lpszNextPath,
  148. BOOL fFirstTime,
  149. BOOL *lpfDone
  150. )
  151. {
  152. LPTSTR lpT = lpszNextPath;
  153. if(fFirstTime)
  154. {
  155. if (MyPathIsUNC(lpT))
  156. {
  157. lpT +=2; /* step over \ */
  158. /* look for \\server\ <------------- */
  159. lpT = MyStrChr(lpT, cBackSlash);
  160. if (lpT)
  161. {
  162. ++lpT; /* step over \ */
  163. lpT = MyStrChr(lpT, cBackSlash);
  164. if (!lpT)
  165. {
  166. /* \\server\share */
  167. *lpfDone = TRUE;
  168. }
  169. else
  170. {
  171. /* \\server\\share\foo...... */
  172. if (!*(lpT+1))
  173. {
  174. /* \\server\share\ */
  175. *lpfDone = TRUE;
  176. }
  177. *lpT = 0;
  178. }
  179. }
  180. }
  181. else
  182. {
  183. lpT = NULL;
  184. }
  185. }
  186. else // not the first time
  187. {
  188. Assert(*lpT != cBackSlash);
  189. lpT = MyStrChr(lpT, cBackSlash);
  190. if(!lpT)
  191. {
  192. *lpfDone=TRUE;
  193. }
  194. else
  195. {
  196. if(*(lpT+1) == 0)
  197. {// ends in a slash
  198. *lpfDone = TRUE;
  199. }
  200. *lpT = (char) 0;
  201. }
  202. }
  203. return (lpT);
  204. }
  205. void
  206. RestorePath(
  207. LPTSTR lpszPtr
  208. )
  209. {
  210. *lpszPtr = cBackSlash;
  211. }
  212. BOOL
  213. FindCreateShadowFromPath(
  214. LPCTSTR lpszFile,
  215. BOOL fCreate, // create if necessary
  216. LPWIN32_FIND_DATA lpFind32,
  217. LPSHADOWINFO lpSI,
  218. BOOL *lpfCreated
  219. )
  220. {
  221. HANDLE hShadowDB = INVALID_HANDLE_VALUE, hFind;
  222. int done=0, first=1, fWasFirst;
  223. HSHADOW hDir=0, hShadow=0;
  224. TCHAR szParsePath[MAX_PATH], szSave[sizeof(szStarDotStar)];
  225. LPTSTR lpszCurrent, lpszNext;
  226. BOOL fInCreateMode = FALSE, fRet = FALSE, fDisabledShadowing = FALSE;
  227. DWORD dwError = ERROR_SUCCESS, dwT;
  228. // do basic check
  229. if (lstrlen(lpszFile) >= MAX_PATH)
  230. {
  231. SetLastError(ERROR_INVALID_PARAMETER);
  232. return (FALSE);
  233. }
  234. hShadowDB = OpenShadowDatabaseIO();
  235. if (hShadowDB == INVALID_HANDLE_VALUE)
  236. {
  237. return FALSE;
  238. }
  239. if (lpfCreated)
  240. {
  241. *lpfCreated = FALSE;
  242. }
  243. #ifndef CSC_ON_NT
  244. if (fCreate)
  245. {
  246. if (!DisableShadowingForThisThread(hShadowDB))
  247. {
  248. dwError = ERROR_NO_SYSTEM_RESOURCES;
  249. goto bailout;
  250. }
  251. fDisabledShadowing = TRUE;
  252. }
  253. #endif
  254. // make a copy so we can party on it
  255. lstrcpy(szParsePath, lpszFile);
  256. lpszCurrent = szParsePath;
  257. do
  258. {
  259. hDir = hShadow;
  260. lpszNext = LpBreakPath(lpszCurrent, first, &done);
  261. if (!lpszNext && !done)
  262. {
  263. dwError = (ERROR_INVALID_PARAMETER);
  264. goto bailout;
  265. }
  266. fWasFirst = first;
  267. first = 0; // not first anymore
  268. lstrcpy(lpFind32->cFileName, lpszCurrent);
  269. lpFind32->cAlternateFileName[0] = 0; // !!!! very important, otherwise all CSC APIs
  270. // may AV on win9x becuase of multibytetowidechar translation
  271. // in Find32AToFind32W in lib3\misc.c
  272. if (!fInCreateMode)
  273. {
  274. if (!GetShadowEx(hShadowDB, hDir, lpFind32, lpSI))
  275. {
  276. dwError = GetLastError();
  277. goto bailout;
  278. }
  279. else
  280. {
  281. if (!lpSI->hShadow)
  282. {
  283. fInCreateMode = TRUE;
  284. }
  285. else
  286. {
  287. Assert(hDir == lpSI->hDir);
  288. hShadow = lpSI->hShadow;
  289. }
  290. }
  291. }
  292. if (fInCreateMode)
  293. {
  294. if (fCreate)
  295. {
  296. fInCreateMode = TRUE;
  297. if (fWasFirst)
  298. {
  299. if (!GetWin32Info(szParsePath, lpFind32))
  300. {
  301. dwError = GetLastError();
  302. goto bailout;
  303. }
  304. lstrcpy(lpFind32->cFileName, szParsePath);
  305. lpFind32->cAlternateFileName[0] = 0;
  306. }
  307. else
  308. {
  309. hFind = FindFirstFile(szParsePath, lpFind32);
  310. // this would fail if we are in disconnected state
  311. // becuase we don't have the shadow yet
  312. if(INVALID_HANDLE_VALUE == hFind)
  313. {
  314. dwError = GetLastError();
  315. goto bailout;
  316. }
  317. else
  318. {
  319. FindClose(hFind);
  320. }
  321. }
  322. if (!CreateShadow(
  323. hShadowDB,
  324. hDir,
  325. lpFind32,
  326. SHADOW_SPARSE,
  327. &hShadow))
  328. {
  329. dwError = GetLastError();
  330. goto bailout;
  331. }
  332. // there can be a situation where, the share is also newly created, in which case
  333. // the hShare is not set. This is our way of doing that.
  334. if (!lpSI->hShare)
  335. {
  336. if (!GetShadowEx(hShadowDB, hDir, lpFind32, lpSI))
  337. {
  338. dwError = GetLastError();
  339. goto bailout;
  340. }
  341. }
  342. #ifdef CSC_ON_NT
  343. // on NT we open the file to get the right
  344. // security credentials
  345. if (!(lpFind32->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  346. {
  347. HANDLE hFile;
  348. // this should be the last guy
  349. hFile = CreateFile(szParsePath,
  350. GENERIC_READ,
  351. FILE_SHARE_READ,
  352. NULL,
  353. OPEN_EXISTING,
  354. 0,
  355. NULL);
  356. if (hFile != INVALID_HANDLE_VALUE)
  357. {
  358. CloseHandle(hFile);
  359. }
  360. else
  361. {
  362. dwError = GetLastError();
  363. DeleteShadow(hShadowDB, hDir, hShadow);
  364. goto bailout;
  365. }
  366. #endif
  367. }
  368. }
  369. else
  370. {
  371. // check if we were just supposed to report the status
  372. // of a connected share which is not in the database
  373. if (!(fWasFirst && done))
  374. {
  375. dwError = ERROR_FILE_NOT_FOUND;
  376. }
  377. else if (lpSI->uStatus & SHARE_CONNECTED)
  378. {
  379. fRet = TRUE;
  380. }
  381. goto bailout;
  382. }
  383. lpSI->hDir = hDir;
  384. lpSI->hShadow = hShadow;
  385. lpSI->uStatus = SHADOW_SPARSE;
  386. lpSI->ulHintPri = 0;
  387. }
  388. if (lpszNext)
  389. {
  390. RestorePath(lpszNext);
  391. lpszCurrent = lpszNext+1;
  392. }
  393. else
  394. {
  395. Assert(done);
  396. }
  397. } while (hShadow && !done);
  398. fRet = TRUE;
  399. if (lpfCreated)
  400. {
  401. *lpfCreated = fInCreateMode;
  402. }
  403. bailout:
  404. if (fDisabledShadowing)
  405. {
  406. EnableShadowingForThisThread(hShadowDB);
  407. }
  408. CloseShadowDatabaseIO(hShadowDB);
  409. if (!fRet)
  410. {
  411. SetLastError(dwError);
  412. }
  413. return fRet;
  414. }
  415. BOOL
  416. IsShareReallyConnected(
  417. LPCTSTR lpszShareName
  418. )
  419. {
  420. WIN32_FIND_DATA sFind32;
  421. HSHADOW hShadow;
  422. ULONG uStatus;
  423. memset(&sFind32, 0, sizeof(sFind32));
  424. lstrcpyn(sFind32.cFileName, lpszShareName, MAX_PATH-1);
  425. if (GetShadow(INVALID_HANDLE_VALUE, 0, &hShadow, &sFind32, &uStatus))
  426. {
  427. if ((uStatus & SHARE_CONNECTED) && !(uStatus & SHARE_SHADOWNP))
  428. {
  429. return TRUE;
  430. }
  431. }
  432. return FALSE;
  433. }
  434. BOOL
  435. AnyActiveNets(
  436. BOOL *lpfSlowLink
  437. )
  438. {
  439. BOOL fOffline;
  440. if(IsServerOfflineW(INVALID_HANDLE_VALUE, NULL, &fOffline)) {
  441. // DbgPrint("AnyActiveNets returning %d\n", fOffline);
  442. return fOffline;
  443. }
  444. // DbgPrint("AnyActiveNets: IsServerOffline errored out!!\n");
  445. return FALSE;
  446. }
  447. BOOL
  448. GetWideStringFromRegistryString(
  449. IN LPSTR lpszKeyName,
  450. IN LPSTR lpszParameter, // value name
  451. OUT LPWSTR *lplpwzList, // wide character string
  452. OUT LPDWORD lpdwLength // length in bytes
  453. )
  454. /*++
  455. Routine Description:
  456. reads a registry string and converts it to widechar
  457. Arguments:
  458. lpszParameter - registry parameter
  459. lplpwzList - wide character string
  460. lpdwLength - size of the widechar string
  461. Return Value:
  462. DWORD
  463. Success - TRUE
  464. Failure - FALSE, GetLastError() returns the actual error
  465. --*/
  466. {
  467. HKEY hKey = NULL;
  468. DWORD dwData=1;
  469. DWORD dwLen = 0;
  470. LPSTR lpszString = NULL;
  471. BOOL fRet = FALSE;
  472. *lplpwzList = NULL;
  473. *lpdwLength = 0;
  474. ReintKdPrint(INIT, ("Opening key\r\n"));
  475. if (RegCreateKeyExA(HKEY_LOCAL_MACHINE,
  476. (lpszKeyName)?lpszKeyName:REG_KEY_CSC_SETTINGS_A,
  477. 0,
  478. NULL,
  479. REG_OPTION_NON_VOLATILE,
  480. KEY_READ,
  481. NULL,
  482. &hKey,
  483. &dwData) == ERROR_SUCCESS)
  484. {
  485. ReintKdPrint(INIT, ("getting size for value %s\r\n", lpszParameter));
  486. if(RegQueryValueExA(hKey, lpszParameter, NULL, NULL, NULL, &dwLen)==
  487. ERROR_SUCCESS)
  488. {
  489. lpszString = (LPSTR)LocalAlloc(LPTR, dwLen+1);
  490. if (lpszString)
  491. {
  492. dwData = dwLen+1;
  493. ReintKdPrint(INIT, ("getting value %s\r\n", lpszParameter));
  494. if(RegQueryValueExA(hKey, lpszParameter, NULL, NULL, lpszString, &dwData)
  495. ==ERROR_SUCCESS)
  496. {
  497. ReintKdPrint(INIT, ("value for %s is %s\r\n", lpszParameter, lpszString));
  498. *lplpwzList = LocalAlloc(LPTR, *lpdwLength = dwData * sizeof(WCHAR));
  499. if (*lplpwzList)
  500. {
  501. if (MultiByteToWideChar(CP_ACP, 0, lpszString, dwLen, *lplpwzList, *lpdwLength))
  502. {
  503. fRet = TRUE;
  504. ReintKdPrint(INIT, ("Unicode value for %s is %ls\r\n", lpszParameter, *lplpwzList));
  505. }
  506. }
  507. }
  508. }
  509. }
  510. }
  511. if (lpszString)
  512. {
  513. LocalFree(lpszString);
  514. }
  515. if(hKey)
  516. {
  517. RegCloseKey(hKey);
  518. }
  519. if (!fRet)
  520. {
  521. if (*lplpwzList)
  522. {
  523. LocalFree(*lplpwzList);
  524. *lplpwzList = NULL;
  525. }
  526. }
  527. return fRet;
  528. }
  529. LPTSTR
  530. GetTempFileForCSC(
  531. LPTSTR lpszBuff
  532. )
  533. /*++
  534. Routine Description:
  535. Generates a temporary filename prototype. Checks %temp%, %tmp% and then
  536. %userprofiles%. The temp directory has to be local.
  537. Arguments:
  538. lpszBuff If NULL, the routine will allocate space for returning the path
  539. If non-NULL this must be big enough to fit MAX_PATH characters
  540. Returns:
  541. returns NULL if failed
  542. returns pointer to the buffer containing the path to use.
  543. If lpszBuff was non-NULL, the return value is the same as lpszBuff
  544. Notes:
  545. --*/
  546. {
  547. LPTSTR TempName = NULL;
  548. DWORD nRet = 0;
  549. ULONG i;
  550. WCHAR TmpPath[MAX_PATH];
  551. WCHAR TmpPrefix[32];
  552. WCHAR Drive[4] = L"X:\\";
  553. BOOLEAN GotOne = FALSE;
  554. // check if caller wants us to allocate
  555. if (lpszBuff) {
  556. TempName = lpszBuff;
  557. } else {
  558. // caller must free
  559. TempName = LocalAlloc(LPTR, MAX_PATH * sizeof(TCHAR));
  560. if (TempName == NULL)
  561. return NULL;
  562. }
  563. wsprintf(TmpPrefix, L"%ws%x", vszPrefix, (GetCurrentThreadId() & 0xff));
  564. //
  565. // Find the temp directory
  566. //
  567. for (i = 0; TempDirs[i] != NULL && GotOne == FALSE; i++) {
  568. // DbgPrint("Trying %ws\n", TempDirs[i]);
  569. nRet = GetEnvironmentVariable(TempDirs[i], TmpPath, MAX_PATH);
  570. if (nRet >= 4 && nRet <= MAX_PATH) {
  571. // DbgPrint("%ws=%ws\n", TempDirs[i], TmpPath);
  572. Drive[0] = TmpPath[0];
  573. if (
  574. TmpPath[1] == L':'
  575. &&
  576. TmpPath[2] == L'\\'
  577. &&
  578. GetDriveType(Drive) == DRIVE_FIXED
  579. ) {
  580. if (GetTempFileName(TmpPath, TmpPrefix, 0, TempName)) {
  581. // DbgPrint("CSC TempName=%ws\n", TempName);
  582. GotOne = TRUE;
  583. }
  584. }
  585. }
  586. }
  587. if (GotOne == FALSE) {
  588. // Cleanup if we failed
  589. LocalFree(TempName);
  590. TempName = NULL;
  591. } else {
  592. // Delete file on success, as it might be encrypted
  593. DeleteFile(TempName);
  594. }
  595. return TempName;
  596. }
  597. BOOL
  598. GetCSCFixedDisk(
  599. TCHAR *lptzDrive
  600. )
  601. /*++
  602. Routine Description:
  603. Looks for a fixed disk drive.
  604. Arguments:
  605. lptzDrive retruns drive letter if successful.
  606. Returns:
  607. TRUE if successful, FALSE if no fixed disk is found
  608. Notes:
  609. OBSOLETE uses a hacky way of finding out the fixed disk. RemoteBoot lies to us and tells us that
  610. c: is a fixed disk.
  611. --*/
  612. {
  613. int i;
  614. WIN32_FIND_DATA sFind32;
  615. if (GetShadowDatabaseLocation(INVALID_HANDLE_VALUE, &sFind32))
  616. {
  617. if (sFind32.cFileName[1] == _TEXT(':'))
  618. {
  619. lptzDrive[0] = sFind32.cFileName[0];
  620. lptzDrive[1] = sFind32.cFileName[1];
  621. lptzDrive[2] = sFind32.cFileName[2];
  622. lptzDrive[3] = 0;
  623. return TRUE;
  624. }
  625. else
  626. {
  627. lptzDrive[0] = _TEXT('d');
  628. }
  629. lptzDrive[1] = _TEXT(':');lptzDrive[2] = _TEXT('\\');lptzDrive[3] = 0;
  630. for (i=0; i<24; ++i)
  631. {
  632. if(GetDriveType(lptzDrive) == DRIVE_FIXED)
  633. {
  634. return TRUE;
  635. }
  636. lptzDrive[0]++;
  637. }
  638. }
  639. return FALSE;
  640. }
  641. BOOL
  642. SetRegValueDWORDA(
  643. IN HKEY hKey,
  644. IN LPCSTR lpSubKey,
  645. IN LPCSTR lpValueName,
  646. IN DWORD dwValue
  647. )
  648. /*++
  649. Routine Description:
  650. Helper regsistry routine
  651. Arguments:
  652. Returns:
  653. TRUE if successful. If FALSE, GetLastError() gives the actual error code
  654. Notes:
  655. --*/
  656. {
  657. HKEY hSubKey = 0;
  658. DWORD dwType;
  659. BOOL fRet = FALSE;
  660. if(RegOpenKeyA(hKey, lpSubKey, &hSubKey) == ERROR_SUCCESS)
  661. {
  662. if (RegSetValueExA(hSubKey, lpValueName, 0, REG_DWORD, (PBYTE)&dwValue, sizeof(DWORD))
  663. == ERROR_SUCCESS)
  664. {
  665. fRet = TRUE;
  666. }
  667. RegCloseKey(hSubKey);
  668. }
  669. return fRet;
  670. }
  671. BOOL
  672. QueryRegValueDWORDA(
  673. IN HKEY hKey,
  674. IN LPCSTR lpSubKey,
  675. IN LPCSTR lpValueName,
  676. OUT LPDWORD lpdwValue
  677. )
  678. /*++
  679. Routine Description:
  680. Helper regsistry routine
  681. Arguments:
  682. Returns:
  683. TRUE if successful. If FALSE, GetLastError() gives the actual error code
  684. Notes:
  685. --*/
  686. {
  687. HKEY hSubKey;
  688. DWORD dwType, dwSize;
  689. BOOL fRet = FALSE;
  690. if(RegOpenKeyA(hKey, lpSubKey, &hSubKey) == ERROR_SUCCESS)
  691. {
  692. dwSize = sizeof(DWORD);
  693. if (RegQueryValueExA(hSubKey, lpValueName, 0, &dwType, (PBYTE)lpdwValue, &dwSize)
  694. == ERROR_SUCCESS)
  695. {
  696. fRet = TRUE;
  697. }
  698. RegCloseKey(hSubKey);
  699. }
  700. return fRet;
  701. }
  702. BOOL
  703. DeleteRegValueA(
  704. IN HKEY hKey,
  705. IN LPCSTR lpSubKey,
  706. IN LPCSTR lpValueName
  707. )
  708. /*++
  709. Routine Description:
  710. Helper regsistry routine
  711. Arguments:
  712. Returns:
  713. TRUE if successful. If FALSE, GetLastError() gives the actual error code
  714. Notes:
  715. --*/
  716. {
  717. HKEY hSubKey;
  718. BOOL fRet = FALSE;
  719. if(RegOpenKeyA(hKey, lpSubKey, &hSubKey) == ERROR_SUCCESS)
  720. {
  721. if(RegDeleteValueA(hSubKey, lpValueName) == ERROR_SUCCESS)
  722. {
  723. fRet = TRUE;
  724. }
  725. RegCloseKey(hSubKey);
  726. }
  727. return fRet;
  728. }
  729. BOOL
  730. QueryFormatDatabase(
  731. VOID
  732. )
  733. /*++
  734. Routine Description:
  735. Helper regsistry routine
  736. Arguments:
  737. Returns:
  738. TRUE if successful. If FALSE, GetLastError() gives the actual error code
  739. Notes:
  740. --*/
  741. {
  742. DWORD dwSize, dwTemp=0;
  743. HKEY hKey = NULL;
  744. BOOL fFormat = FALSE;
  745. if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  746. REG_STRING_NETCACHE_KEY,
  747. 0,
  748. KEY_READ | KEY_WRITE,
  749. &hKey
  750. ) == ERROR_SUCCESS)
  751. {
  752. dwSize = sizeof(dwTemp);
  753. dwTemp = 0;
  754. if (RegQueryValueEx(hKey, REG_VALUE_FORMAT_DATABASE, NULL, NULL, (void *)&dwTemp, &dwSize) == ERROR_SUCCESS)
  755. {
  756. if(RegDeleteValue(hKey, REG_VALUE_FORMAT_DATABASE) != ERROR_SUCCESS)
  757. {
  758. // deliberte print to catch it in free builds as well
  759. OutputDebugStringA("Not Formatting.. Failed to delete REG_VALUE_FORMAT_DATABASE_A \n");
  760. }
  761. else
  762. {
  763. fFormat = TRUE;
  764. }
  765. }
  766. RegCloseKey(hKey);
  767. hKey = NULL;
  768. }
  769. else
  770. {
  771. hKey = NULL;
  772. }
  773. if(hKey)
  774. {
  775. RegCloseKey(hKey);
  776. }
  777. return fFormat;
  778. }
  779. BOOL
  780. InitValues(
  781. LPSTR lpszDBDir,
  782. DWORD cbDBDirSize,
  783. LPDWORD lpdwDBCapacity,
  784. LPDWORD lpdwClusterSize
  785. )
  786. /*++
  787. Routine Description:
  788. Returns init values to init CSC database and enable CSC
  789. Arguments:
  790. Returns:
  791. TRUE if successful. If FALSE, GetLastError() gives the actual error code
  792. Notes:
  793. --*/
  794. {
  795. HKEY hKeyShadow;
  796. int iSize;
  797. DWORD dwType;
  798. UINT lenDir;
  799. BOOL fInitedDir = FALSE, fInitedSize=FALSE;
  800. unsigned uPercent;
  801. if(RegOpenKeyA(HKEY_LOCAL_MACHINE, REG_STRING_NETCACHE_KEY_A, &hKeyShadow) == ERROR_SUCCESS)
  802. {
  803. iSize = (int)cbDBDirSize;
  804. if(RegQueryValueExA(hKeyShadow, REG_STRING_DATABASE_LOCATION_A, NULL, &dwType, lpszDBDir, &iSize)==ERROR_SUCCESS)
  805. {
  806. if ((iSize+SUBDIR_STRING_LENGTH+2)<MAX_PATH)
  807. {
  808. iSize = sizeof(DWORD);
  809. fInitedDir = TRUE;
  810. if(RegQueryValueExA(hKeyShadow, REG_VALUE_DATABASE_SIZE_A, NULL, &dwType, (LPBYTE)&uPercent, &iSize)==ERROR_SUCCESS)
  811. {
  812. if ((uPercent <= 100) &&
  813. GetDiskSizeFromPercentage(lpszDBDir, uPercent, lpdwDBCapacity, lpdwClusterSize))
  814. {
  815. fInitedSize = TRUE;
  816. }
  817. }
  818. }
  819. }
  820. RegCloseKey(hKeyShadow);
  821. }
  822. if (!fInitedDir)
  823. {
  824. // try the default
  825. if(!(lenDir=GetWindowsDirectoryA(lpszDBDir, cbDBDirSize)))
  826. {
  827. DEBUG_PRINT(("InitValuse: GetWindowsDirectory failed, error=%x \r\n", GetLastError()));
  828. Assert(FALSE);
  829. return FALSE;
  830. }
  831. else
  832. {
  833. if ((lenDir+SUBDIR_STRING_LENGTH+2)>=MAX_PATH)
  834. {
  835. DEBUG_PRINT(("InbCreateDir: Windows dir name too big\r\n"));
  836. Assert(FALSE);
  837. // if even the default fails do the worst case thing.
  838. // this may also not be good enough as apparently in Japan
  839. // c: is not mandatory
  840. return FALSE;
  841. }
  842. else
  843. {
  844. if (lpszDBDir[lenDir-1]!='\\')
  845. {
  846. lpszDBDir[lenDir++] = '\\';
  847. lpszDBDir[lenDir] = 0;
  848. }
  849. lstrcatA(lpszDBDir, vszCSCDirName);
  850. }
  851. }
  852. }
  853. Assert(lpszDBDir[1]==':');
  854. if (!fInitedSize)
  855. {
  856. if(!GetDiskSizeFromPercentage(lpszDBDir, DEFAULT_CACHE_PERCENTAGE, lpdwDBCapacity, lpdwClusterSize))
  857. {
  858. return FALSE;
  859. }
  860. }
  861. // DEBUG_PRINT(("InitValues: CSCDb at %s Size = %d \r\n", lpszDBDir, *lpdwDBCapacity));
  862. return TRUE;
  863. }
  864. BOOL
  865. GetDiskSizeFromPercentage(
  866. LPSTR lpszDir,
  867. unsigned uPercent,
  868. DWORD *lpdwSize,
  869. DWORD *lpdwClusterSize
  870. )
  871. {
  872. char szDrive[4];
  873. DWORD dwSPC, dwBPS, dwFreeC, dwTotalC;
  874. ULONGLONG ullSize = 0;
  875. *lpdwSize = 0;
  876. memset(szDrive, 0, sizeof(szDrive));
  877. memcpy(szDrive, lpszDir, 3);
  878. if(!GetDiskFreeSpaceA(szDrive, &dwSPC, &dwBPS, &dwFreeC, &dwTotalC )){
  879. return FALSE;
  880. }
  881. else
  882. {
  883. // DEBUG_PRINT(("dwSPC=%d dwBPS=%d uPercent=%d dwTotalC=%d \r\n",
  884. // dwSPC, dwBPS, uPercent, dwTotalC));
  885. ullSize = (((ULONGLONG)dwSPC * dwBPS * uPercent)/100)*dwTotalC;
  886. // our max limit is 2GB
  887. if (ullSize > 0x7fffffff)
  888. {
  889. *lpdwSize = 0x7fffffff;
  890. }
  891. else
  892. {
  893. *lpdwSize = (DWORD)ullSize;
  894. }
  895. *lpdwClusterSize = dwBPS * dwSPC;
  896. }
  897. return (TRUE);
  898. }
  899. #ifdef MAYBE_USEFULE
  900. typedef struct tagCSC_NAME_CACHE_ENTRY
  901. {
  902. DWORD dwFlags;
  903. DWORD dwTick;
  904. HSHADOW hDir;
  905. DWORD dwSize;
  906. TCHAR *lptzName;
  907. }
  908. CSC_NAME_CACHE_ENTRY, *LPCSC_NAME_CACHE_ENTRY;
  909. CSC_NAME_CACHE_ENTRY rgCSCNameCache[16];
  910. HANDLE vhNameCacheMutex;
  911. #define CSC_NAME_CACHE_EXPIRY_DELTA 1000*10 // 10 seconds
  912. BOOL
  913. FindCreateCSCNameCacheEntry(
  914. LPTSTR lptzName,
  915. DWORD dwSize,
  916. HSHADOW *lphDir,
  917. BOOL fCreate
  918. );
  919. BOOL
  920. FindCreateShadowFromPathEx(
  921. LPCTSTR lpszFile,
  922. BOOL fCreate, // create if necessary
  923. LPWIN32_FIND_DATA lpFind32,
  924. LPSHADOWINFO lpSI,
  925. BOOL *lpfCreated
  926. )
  927. {
  928. BOOL fRet = FALSE, fIsShare, fFoundInCache = FALSE;
  929. TCHAR *lpT;
  930. DWORD cbSize;
  931. lpT = GetLeafPtr((LPTSTR)lpszFile);
  932. if (fIsShare = ((DWORD_PTR)lpT == (DWORD_PTR)lpszFile))
  933. {
  934. cbSize = lstrlen(lpT) * sizeof(_TCHAR);
  935. }
  936. else
  937. {
  938. cbSize = (DWORD_PTR)lpT - (DWORD_PTR)lpszFile - sizeof(_TCHAR);
  939. }
  940. if (!fIsShare)
  941. {
  942. if (!fCreate)
  943. {
  944. HSHADOW hDir;
  945. // just look it up first
  946. if (FindCreateCSCNameCacheEntry((LPTSTR)lpszFile, cbSize, &hDir, FALSE))
  947. {
  948. if (hDir != 0xffffffff)
  949. {
  950. // found it
  951. if (lpfCreated)
  952. {
  953. *lpfCreated = FALSE;
  954. }
  955. //Bug 5512822 - navjotv
  956. cbSize = min(MAX_PATH-1,(lstrlen(lpT)));
  957. lstrcpyn(lpFind32->cFileName, lpT, cbSize);
  958. lpFind32->cFileName[cbSize+1] = 0;
  959. lpFind32->cAlternateFileName[0] = 0;
  960. fRet = GetShadowEx(INVALID_HANDLE_VALUE, hDir, lpFind32, lpSI);
  961. }
  962. else
  963. {
  964. DbgPrint("Found negative cache entry %ls \n", lpszFile);
  965. }
  966. fFoundInCache = TRUE;
  967. }
  968. }
  969. }
  970. if (!fFoundInCache)
  971. {
  972. // not found, do the normal thing
  973. fRet = FindCreateShadowFromPath((LPTSTR)lpszFile, fCreate, lpFind32, lpSI, lpfCreated);
  974. if (!fRet)
  975. {
  976. lpSI->hDir = lpSI->hShadow = 0xffffffff;
  977. }
  978. if (fRet || (GetLastError() == ERROR_FILE_NOT_FOUND))
  979. {
  980. FindCreateCSCNameCacheEntry((LPTSTR)lpszFile, cbSize, (lpSI->hDir)?&lpSI->hDir:&lpSI->hShadow, TRUE);
  981. }
  982. }
  983. return fRet;
  984. }
  985. BOOL
  986. FindCreateCSCNameCacheEntry(
  987. LPTSTR lptzName,
  988. DWORD dwSize,
  989. HSHADOW *lphDir,
  990. BOOL fCreate
  991. )
  992. {
  993. int i, indx=-1;
  994. DWORD dwTick = GetTickCount();
  995. BOOL fRet = FALSE;
  996. if (!vhNameCacheMutex)
  997. {
  998. return FALSE;
  999. }
  1000. WaitForSingleObject(vhNameCacheMutex, INFINITE);
  1001. for (i=0; i<(sizeof(rgCSCNameCache)/sizeof(CSC_NAME_CACHE_ENTRY)); ++i)
  1002. {
  1003. if (!rgCSCNameCache[i].dwSize)
  1004. {
  1005. if (indx == -1)
  1006. {
  1007. indx = i;
  1008. }
  1009. }
  1010. else if ((rgCSCNameCache[i].dwSize == dwSize ))
  1011. {
  1012. //non-zero size must mean a string has been allocated
  1013. Assert(rgCSCNameCache[i].lptzName);
  1014. if ((dwTick < rgCSCNameCache[i].dwTick)||
  1015. ((dwTick > (rgCSCNameCache[i].dwTick+CSC_NAME_CACHE_EXPIRY_DELTA))))
  1016. {
  1017. DbgPrint("%ls expired\n", rgCSCNameCache[i].lptzName);
  1018. // the entry has expired, nuke it
  1019. rgCSCNameCache[i].dwSize = 0;
  1020. FreeMem(rgCSCNameCache[i].lptzName);
  1021. rgCSCNameCache[i].lptzName = NULL;
  1022. continue;
  1023. }
  1024. // do a caseinsensitve comparison
  1025. if ((CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
  1026. lptzName, dwSize/sizeof(_TCHAR),
  1027. rgCSCNameCache[i].lptzName,dwSize/sizeof(_TCHAR))
  1028. == CSTR_EQUAL))
  1029. {
  1030. // match found
  1031. DbgPrint("Match Found %ls\n", rgCSCNameCache[i].lptzName);
  1032. if (fCreate)
  1033. {
  1034. rgCSCNameCache[i].hDir = *lphDir;
  1035. // update the tick count
  1036. rgCSCNameCache[i].dwTick = dwTick;
  1037. }
  1038. else
  1039. {
  1040. // we want to find it, return the directory
  1041. *lphDir = rgCSCNameCache[i].hDir;
  1042. }
  1043. fRet = TRUE;
  1044. break;
  1045. }
  1046. }
  1047. }
  1048. // didn't find it, we are supposed to create and there is an empty slot
  1049. if (!fRet && fCreate && (indx >= 0) )
  1050. {
  1051. rgCSCNameCache[indx].lptzName = AllocMem(dwSize+sizeof(_TCHAR));
  1052. if (rgCSCNameCache[indx].lptzName)
  1053. {
  1054. memcpy(rgCSCNameCache[indx].lptzName, lptzName, dwSize);
  1055. rgCSCNameCache[indx].dwSize = dwSize;
  1056. rgCSCNameCache[indx].dwTick = dwTick;
  1057. rgCSCNameCache[indx].hDir = *lphDir;
  1058. fRet = TRUE;
  1059. DbgPrint("Inserted %ls\n", rgCSCNameCache[indx].lptzName);
  1060. }
  1061. }
  1062. ReleaseMutex(vhNameCacheMutex);
  1063. return fRet;
  1064. }
  1065. #endif