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
1330 lines
31 KiB
#include "pch.h"
|
|
#pragma hdrstop
|
|
|
|
#ifndef CSC_ON_NT
|
|
#ifndef DBG
|
|
#define DBG 0
|
|
#endif
|
|
#if DBG
|
|
#define DEBUG
|
|
#else
|
|
//if we don't do this DEBUG is defined in shdsys.h....sigh
|
|
#define NONDEBUG
|
|
#endif
|
|
#endif
|
|
|
|
#include "shdsys.h"
|
|
#include "utils.h"
|
|
#include "lib3.h"
|
|
#include "reint.h"
|
|
#include "regstr.h"
|
|
#include "record.h"
|
|
#include "oslayeru.h"
|
|
|
|
#define PUBLIC FAR PASCAL
|
|
#define PRIVATE NEAR PASCAL
|
|
#define cNull 0
|
|
#define SIGN_BIT 0x80000000
|
|
#define cBackSlash _T('\\')
|
|
#define DEFAULT_CACHE_PERCENTAGE 10
|
|
|
|
|
|
extern char vrgchBuff[1024];
|
|
extern HWND vhwndMain;
|
|
|
|
static TCHAR vszTemp[] = _TEXT("TEMP");
|
|
static TCHAR vszPrefix[] = _TEXT("C");
|
|
static const char vszCSCDirName[]="CSC";
|
|
|
|
|
|
AssertData;
|
|
AssertError;
|
|
|
|
static const _TCHAR szStarDotStar[] = _TEXT("\\*.*");
|
|
|
|
#ifdef CSC_ON_NT
|
|
#else
|
|
const TCHAR vszRNAKey[] = REGSTR_PATH_SERVICES "\\RemoteAccess";
|
|
const TCHAR vszRNAValue[] = "Remote Connection";
|
|
const TCHAR VREDIR_DEVICE_NAME[] = "\\\\.\\VREDIR";
|
|
#endif
|
|
|
|
PWCHAR TempDirs[] = {
|
|
L"TEMP",
|
|
L"TMP",
|
|
L"USERPROFILE",
|
|
NULL };
|
|
|
|
BOOL
|
|
GetCSCFixedDisk(
|
|
TCHAR *lptzDrive
|
|
);
|
|
|
|
|
|
#ifdef LATER
|
|
LPSTR PUBLIC LpGetServerPart(
|
|
LPSTR lpPath,
|
|
LPSTR lpBuff,
|
|
int cBuff
|
|
)
|
|
{
|
|
LPSTR lp = lpPath;
|
|
char c;
|
|
int count;
|
|
|
|
if ((*lp++ != cBackSlash)||(*lp++ != cBackSlash))
|
|
return NULL;
|
|
lp = MyStrChr(lp, cBackSlash);
|
|
if (cBuff && lp)
|
|
{
|
|
count = (int)((unsigned long)lp, (unsigned long)lpPath)
|
|
count = min(cBuff-1, count);
|
|
|
|
// Nobody should give us bad cBuff values
|
|
Assert(count >=0);
|
|
strncpy(lpBuff, lpPath, count);
|
|
lpBuff[count] = cNull;
|
|
}
|
|
return lp; // Points to '\' if succeeded
|
|
}
|
|
#endif //LATER
|
|
|
|
LPTSTR PUBLIC LpGetServerPart(
|
|
LPTSTR lpPath,
|
|
LPTSTR lpBuff,
|
|
int cBuff
|
|
)
|
|
{
|
|
LPTSTR lp = lpPath;
|
|
|
|
if (*(lp+1)!=_T(':'))
|
|
return NULL;
|
|
|
|
if (*(lp+2)!=_T('\\'))
|
|
return NULL;
|
|
|
|
if (cBuff)
|
|
{
|
|
*lpBuff = *lp;
|
|
*(lpBuff+1) = *(lp+1);
|
|
*(lpBuff+2) = cNull;
|
|
}
|
|
|
|
lp += 2;
|
|
|
|
return lp; // Points to '\' if succeeded
|
|
}
|
|
|
|
LPTSTR PUBLIC LpGetNextPathElement(
|
|
LPTSTR lpPath,
|
|
LPTSTR lpBuff,
|
|
int cBuff
|
|
)
|
|
{
|
|
LPTSTR lp;
|
|
int bytecount;
|
|
|
|
if (*lpPath == cBackSlash)
|
|
++lpPath;
|
|
|
|
lp = MyStrChr(lpPath, cBackSlash);
|
|
|
|
if (cBuff)
|
|
{
|
|
// Is this a leaf?
|
|
if (lp)
|
|
{ // No
|
|
Assert(*lp == cBackSlash);
|
|
|
|
bytecount = (int)((ULONG_PTR)lp-(ULONG_PTR)lpPath);
|
|
bytecount = min(cBuff-1, bytecount);
|
|
}
|
|
else // Yes
|
|
bytecount = lstrlen(lpPath) * sizeof(_TCHAR);
|
|
|
|
Assert(bytecount >= 0);
|
|
|
|
memcpy(lpBuff, lpPath, bytecount);
|
|
|
|
lpBuff[bytecount/sizeof(_TCHAR)] = cNull;
|
|
}
|
|
|
|
return lp;
|
|
}
|
|
|
|
LPTSTR PUBLIC GetLeafPtr(
|
|
LPTSTR lpPath
|
|
)
|
|
{
|
|
LPTSTR lp, lpLeaf;
|
|
|
|
// Prune the server part
|
|
if (!(lp=LpGetServerPart(lpPath, NULL, 0)))
|
|
lp = lpPath;
|
|
|
|
for (;lp;)
|
|
{
|
|
// Step over the '\'
|
|
if (*lp==cBackSlash)
|
|
lp++;
|
|
|
|
// call this the leaf, pending confirmation
|
|
lpLeaf = lp;
|
|
|
|
// See if there is another element
|
|
lp = LpGetNextPathElement(lp, NULL, 0);
|
|
}
|
|
|
|
return (lpLeaf);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
//
|
|
|
|
LPTSTR
|
|
LpBreakPath(
|
|
LPTSTR lpszNextPath,
|
|
BOOL fFirstTime,
|
|
BOOL *lpfDone
|
|
)
|
|
{
|
|
|
|
LPTSTR lpT = lpszNextPath;
|
|
|
|
if(fFirstTime)
|
|
{
|
|
if (MyPathIsUNC(lpT))
|
|
{
|
|
lpT +=2; /* step over \ */
|
|
|
|
/* look for \\server\ <------------- */
|
|
lpT = MyStrChr(lpT, cBackSlash);
|
|
|
|
if (lpT)
|
|
{
|
|
++lpT; /* step over \ */
|
|
|
|
lpT = MyStrChr(lpT, cBackSlash);
|
|
|
|
if (!lpT)
|
|
{
|
|
/* \\server\share */
|
|
*lpfDone = TRUE;
|
|
}
|
|
else
|
|
{
|
|
/* \\server\\share\foo...... */
|
|
if (!*(lpT+1))
|
|
{
|
|
/* \\server\share\ */
|
|
*lpfDone = TRUE;
|
|
}
|
|
|
|
*lpT = 0;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lpT = NULL;
|
|
}
|
|
}
|
|
else // not the first time
|
|
{
|
|
Assert(*lpT != cBackSlash);
|
|
|
|
lpT = MyStrChr(lpT, cBackSlash);
|
|
|
|
if(!lpT)
|
|
{
|
|
*lpfDone=TRUE;
|
|
}
|
|
else
|
|
{
|
|
if(*(lpT+1) == 0)
|
|
{// ends in a slash
|
|
*lpfDone = TRUE;
|
|
}
|
|
|
|
*lpT = (char) 0;
|
|
}
|
|
}
|
|
return (lpT);
|
|
}
|
|
|
|
void
|
|
RestorePath(
|
|
LPTSTR lpszPtr
|
|
)
|
|
{
|
|
*lpszPtr = cBackSlash;
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
FindCreateShadowFromPath(
|
|
LPCTSTR lpszFile,
|
|
BOOL fCreate, // create if necessary
|
|
LPWIN32_FIND_DATA lpFind32,
|
|
LPSHADOWINFO lpSI,
|
|
BOOL *lpfCreated
|
|
)
|
|
{
|
|
HANDLE hShadowDB = INVALID_HANDLE_VALUE, hFind;
|
|
int done=0, first=1, fWasFirst;
|
|
HSHADOW hDir=0, hShadow=0;
|
|
TCHAR szParsePath[MAX_PATH], szSave[sizeof(szStarDotStar)];
|
|
LPTSTR lpszCurrent, lpszNext;
|
|
BOOL fInCreateMode = FALSE, fRet = FALSE, fDisabledShadowing = FALSE;
|
|
DWORD dwError = ERROR_SUCCESS, dwT;
|
|
|
|
// do basic check
|
|
if (lstrlen(lpszFile) >= MAX_PATH)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return (FALSE);
|
|
}
|
|
|
|
hShadowDB = OpenShadowDatabaseIO();
|
|
|
|
if (hShadowDB == INVALID_HANDLE_VALUE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (lpfCreated)
|
|
{
|
|
*lpfCreated = FALSE;
|
|
}
|
|
|
|
#ifndef CSC_ON_NT
|
|
|
|
if (fCreate)
|
|
{
|
|
if (!DisableShadowingForThisThread(hShadowDB))
|
|
{
|
|
dwError = ERROR_NO_SYSTEM_RESOURCES;
|
|
goto bailout;
|
|
}
|
|
|
|
fDisabledShadowing = TRUE;
|
|
|
|
}
|
|
#endif
|
|
|
|
// make a copy so we can party on it
|
|
lstrcpy(szParsePath, lpszFile);
|
|
lpszCurrent = szParsePath;
|
|
|
|
do
|
|
{
|
|
hDir = hShadow;
|
|
|
|
lpszNext = LpBreakPath(lpszCurrent, first, &done);
|
|
|
|
if (!lpszNext && !done)
|
|
{
|
|
dwError = (ERROR_INVALID_PARAMETER);
|
|
|
|
goto bailout;
|
|
}
|
|
|
|
fWasFirst = first;
|
|
first = 0; // not first anymore
|
|
|
|
lstrcpy(lpFind32->cFileName, lpszCurrent);
|
|
lpFind32->cAlternateFileName[0] = 0; // !!!! very important, otherwise all CSC APIs
|
|
// may AV on win9x becuase of multibytetowidechar translation
|
|
// in Find32AToFind32W in lib3\misc.c
|
|
|
|
if (!fInCreateMode)
|
|
{
|
|
if (!GetShadowEx(hShadowDB, hDir, lpFind32, lpSI))
|
|
{
|
|
dwError = GetLastError();
|
|
goto bailout;
|
|
}
|
|
else
|
|
{
|
|
if (!lpSI->hShadow)
|
|
{
|
|
fInCreateMode = TRUE;
|
|
}
|
|
else
|
|
{
|
|
Assert(hDir == lpSI->hDir);
|
|
|
|
hShadow = lpSI->hShadow;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fInCreateMode)
|
|
{
|
|
|
|
if (fCreate)
|
|
{
|
|
fInCreateMode = TRUE;
|
|
|
|
if (fWasFirst)
|
|
{
|
|
if (!GetWin32Info(szParsePath, lpFind32))
|
|
{
|
|
dwError = GetLastError();
|
|
goto bailout;
|
|
}
|
|
|
|
lstrcpy(lpFind32->cFileName, szParsePath);
|
|
lpFind32->cAlternateFileName[0] = 0;
|
|
|
|
}
|
|
else
|
|
{
|
|
hFind = FindFirstFile(szParsePath, lpFind32);
|
|
// this would fail if we are in disconnected state
|
|
// becuase we don't have the shadow yet
|
|
if(INVALID_HANDLE_VALUE == hFind)
|
|
{
|
|
dwError = GetLastError();
|
|
goto bailout;
|
|
}
|
|
else
|
|
{
|
|
FindClose(hFind);
|
|
}
|
|
}
|
|
|
|
if (!CreateShadow(
|
|
hShadowDB,
|
|
hDir,
|
|
lpFind32,
|
|
SHADOW_SPARSE,
|
|
&hShadow))
|
|
{
|
|
dwError = GetLastError();
|
|
goto bailout;
|
|
}
|
|
|
|
// there can be a situation where, the share is also newly created, in which case
|
|
// the hShare is not set. This is our way of doing that.
|
|
|
|
if (!lpSI->hShare)
|
|
{
|
|
if (!GetShadowEx(hShadowDB, hDir, lpFind32, lpSI))
|
|
{
|
|
dwError = GetLastError();
|
|
goto bailout;
|
|
}
|
|
}
|
|
|
|
#ifdef CSC_ON_NT
|
|
// on NT we open the file to get the right
|
|
// security credentials
|
|
if (!(lpFind32->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
{
|
|
HANDLE hFile;
|
|
|
|
// this should be the last guy
|
|
hFile = CreateFile(szParsePath,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL);
|
|
if (hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseHandle(hFile);
|
|
}
|
|
else
|
|
{
|
|
dwError = GetLastError();
|
|
DeleteShadow(hShadowDB, hDir, hShadow);
|
|
goto bailout;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// check if we were just supposed to report the status
|
|
// of a connected share which is not in the database
|
|
if (!(fWasFirst && done))
|
|
{
|
|
dwError = ERROR_FILE_NOT_FOUND;
|
|
}
|
|
else if (lpSI->uStatus & SHARE_CONNECTED)
|
|
{
|
|
fRet = TRUE;
|
|
}
|
|
goto bailout;
|
|
}
|
|
|
|
lpSI->hDir = hDir;
|
|
lpSI->hShadow = hShadow;
|
|
lpSI->uStatus = SHADOW_SPARSE;
|
|
lpSI->ulHintPri = 0;
|
|
}
|
|
|
|
if (lpszNext)
|
|
{
|
|
RestorePath(lpszNext);
|
|
|
|
lpszCurrent = lpszNext+1;
|
|
}
|
|
else
|
|
{
|
|
Assert(done);
|
|
}
|
|
|
|
} while (hShadow && !done);
|
|
|
|
fRet = TRUE;
|
|
|
|
if (lpfCreated)
|
|
{
|
|
*lpfCreated = fInCreateMode;
|
|
}
|
|
|
|
bailout:
|
|
|
|
if (fDisabledShadowing)
|
|
{
|
|
EnableShadowingForThisThread(hShadowDB);
|
|
}
|
|
|
|
CloseShadowDatabaseIO(hShadowDB);
|
|
|
|
if (!fRet)
|
|
{
|
|
SetLastError(dwError);
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
BOOL
|
|
IsShareReallyConnected(
|
|
LPCTSTR lpszShareName
|
|
)
|
|
{
|
|
WIN32_FIND_DATA sFind32;
|
|
HSHADOW hShadow;
|
|
ULONG uStatus;
|
|
|
|
memset(&sFind32, 0, sizeof(sFind32));
|
|
|
|
lstrcpyn(sFind32.cFileName, lpszShareName, MAX_PATH-1);
|
|
|
|
if (GetShadow(INVALID_HANDLE_VALUE, 0, &hShadow, &sFind32, &uStatus))
|
|
{
|
|
if ((uStatus & SHARE_CONNECTED) && !(uStatus & SHARE_SHADOWNP))
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL
|
|
AnyActiveNets(
|
|
BOOL *lpfSlowLink
|
|
)
|
|
{
|
|
BOOL fOffline;
|
|
|
|
if(IsServerOfflineW(INVALID_HANDLE_VALUE, NULL, &fOffline)) {
|
|
// DbgPrint("AnyActiveNets returning %d\n", fOffline);
|
|
return fOffline;
|
|
}
|
|
// DbgPrint("AnyActiveNets: IsServerOffline errored out!!\n");
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL
|
|
GetWideStringFromRegistryString(
|
|
IN LPSTR lpszKeyName,
|
|
IN LPSTR lpszParameter, // value name
|
|
OUT LPWSTR *lplpwzList, // wide character string
|
|
OUT LPDWORD lpdwLength // length in bytes
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
reads a registry string and converts it to widechar
|
|
|
|
Arguments:
|
|
|
|
lpszParameter - registry parameter
|
|
|
|
lplpwzList - wide character string
|
|
|
|
lpdwLength - size of the widechar string
|
|
|
|
Return Value:
|
|
|
|
DWORD
|
|
Success - TRUE
|
|
|
|
Failure - FALSE, GetLastError() returns the actual error
|
|
|
|
--*/
|
|
|
|
{
|
|
HKEY hKey = NULL;
|
|
DWORD dwData=1;
|
|
DWORD dwLen = 0;
|
|
LPSTR lpszString = NULL;
|
|
BOOL fRet = FALSE;
|
|
|
|
*lplpwzList = NULL;
|
|
*lpdwLength = 0;
|
|
|
|
ReintKdPrint(INIT, ("Opening key\r\n"));
|
|
if (RegCreateKeyExA(HKEY_LOCAL_MACHINE,
|
|
(lpszKeyName)?lpszKeyName:REG_KEY_CSC_SETTINGS_A,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_READ,
|
|
NULL,
|
|
&hKey,
|
|
&dwData) == ERROR_SUCCESS)
|
|
{
|
|
ReintKdPrint(INIT, ("getting size for value %s\r\n", lpszParameter));
|
|
|
|
if(RegQueryValueExA(hKey, lpszParameter, NULL, NULL, NULL, &dwLen)==
|
|
ERROR_SUCCESS)
|
|
{
|
|
lpszString = (LPSTR)LocalAlloc(LPTR, dwLen+1);
|
|
|
|
if (lpszString)
|
|
{
|
|
dwData = dwLen+1;
|
|
|
|
ReintKdPrint(INIT, ("getting value %s\r\n", lpszParameter));
|
|
if(RegQueryValueExA(hKey, lpszParameter, NULL, NULL, lpszString, &dwData)
|
|
==ERROR_SUCCESS)
|
|
{
|
|
ReintKdPrint(INIT, ("value for %s is %s\r\n", lpszParameter, lpszString));
|
|
|
|
*lplpwzList = LocalAlloc(LPTR, *lpdwLength = dwData * sizeof(WCHAR));
|
|
|
|
if (*lplpwzList)
|
|
{
|
|
if (MultiByteToWideChar(CP_ACP, 0, lpszString, dwLen, *lplpwzList, *lpdwLength))
|
|
{
|
|
fRet = TRUE;
|
|
ReintKdPrint(INIT, ("Unicode value for %s is %ls\r\n", lpszParameter, *lplpwzList));
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
if (lpszString)
|
|
{
|
|
LocalFree(lpszString);
|
|
}
|
|
|
|
if(hKey)
|
|
{
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
if (!fRet)
|
|
{
|
|
if (*lplpwzList)
|
|
{
|
|
LocalFree(*lplpwzList);
|
|
*lplpwzList = NULL;
|
|
}
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
LPTSTR
|
|
GetTempFileForCSC(
|
|
LPTSTR lpszBuff
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Generates a temporary filename prototype. Checks %temp%, %tmp% and then
|
|
%userprofiles%. The temp directory has to be local.
|
|
|
|
Arguments:
|
|
|
|
lpszBuff If NULL, the routine will allocate space for returning the path
|
|
If non-NULL this must be big enough to fit MAX_PATH characters
|
|
|
|
Returns:
|
|
|
|
returns NULL if failed
|
|
returns pointer to the buffer containing the path to use.
|
|
If lpszBuff was non-NULL, the return value is the same as lpszBuff
|
|
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
LPTSTR TempName = NULL;
|
|
DWORD nRet = 0;
|
|
ULONG i;
|
|
WCHAR TmpPath[MAX_PATH];
|
|
WCHAR TmpPrefix[32];
|
|
WCHAR Drive[4] = L"X:\\";
|
|
BOOLEAN GotOne = FALSE;
|
|
|
|
// check if caller wants us to allocate
|
|
if (lpszBuff) {
|
|
TempName = lpszBuff;
|
|
} else {
|
|
// caller must free
|
|
TempName = LocalAlloc(LPTR, MAX_PATH * sizeof(TCHAR));
|
|
if (TempName == NULL)
|
|
return NULL;
|
|
}
|
|
|
|
wsprintf(TmpPrefix, L"%ws%x", vszPrefix, (GetCurrentThreadId() & 0xff));
|
|
|
|
//
|
|
// Find the temp directory
|
|
//
|
|
for (i = 0; TempDirs[i] != NULL && GotOne == FALSE; i++) {
|
|
// DbgPrint("Trying %ws\n", TempDirs[i]);
|
|
nRet = GetEnvironmentVariable(TempDirs[i], TmpPath, MAX_PATH);
|
|
if (nRet >= 4 && nRet <= MAX_PATH) {
|
|
// DbgPrint("%ws=%ws\n", TempDirs[i], TmpPath);
|
|
Drive[0] = TmpPath[0];
|
|
if (
|
|
TmpPath[1] == L':'
|
|
&&
|
|
TmpPath[2] == L'\\'
|
|
&&
|
|
GetDriveType(Drive) == DRIVE_FIXED
|
|
) {
|
|
if (GetTempFileName(TmpPath, TmpPrefix, 0, TempName)) {
|
|
// DbgPrint("CSC TempName=%ws\n", TempName);
|
|
GotOne = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (GotOne == FALSE) {
|
|
// Cleanup if we failed
|
|
LocalFree(TempName);
|
|
TempName = NULL;
|
|
} else {
|
|
// Delete file on success, as it might be encrypted
|
|
DeleteFile(TempName);
|
|
}
|
|
|
|
return TempName;
|
|
}
|
|
|
|
BOOL
|
|
GetCSCFixedDisk(
|
|
TCHAR *lptzDrive
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Looks for a fixed disk drive.
|
|
|
|
Arguments:
|
|
|
|
lptzDrive retruns drive letter if successful.
|
|
|
|
Returns:
|
|
|
|
TRUE if successful, FALSE if no fixed disk is found
|
|
|
|
Notes:
|
|
|
|
|
|
OBSOLETE uses a hacky way of finding out the fixed disk. RemoteBoot lies to us and tells us that
|
|
c: is a fixed disk.
|
|
|
|
|
|
--*/
|
|
{
|
|
int i;
|
|
WIN32_FIND_DATA sFind32;
|
|
|
|
if (GetShadowDatabaseLocation(INVALID_HANDLE_VALUE, &sFind32))
|
|
{
|
|
if (sFind32.cFileName[1] == _TEXT(':'))
|
|
{
|
|
lptzDrive[0] = sFind32.cFileName[0];
|
|
lptzDrive[1] = sFind32.cFileName[1];
|
|
lptzDrive[2] = sFind32.cFileName[2];
|
|
lptzDrive[3] = 0;
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
lptzDrive[0] = _TEXT('d');
|
|
}
|
|
lptzDrive[1] = _TEXT(':');lptzDrive[2] = _TEXT('\\');lptzDrive[3] = 0;
|
|
|
|
for (i=0; i<24; ++i)
|
|
{
|
|
if(GetDriveType(lptzDrive) == DRIVE_FIXED)
|
|
{
|
|
return TRUE;
|
|
}
|
|
lptzDrive[0]++;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
SetRegValueDWORDA(
|
|
IN HKEY hKey,
|
|
IN LPCSTR lpSubKey,
|
|
IN LPCSTR lpValueName,
|
|
IN DWORD dwValue
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Helper regsistry routine
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
TRUE if successful. If FALSE, GetLastError() gives the actual error code
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
HKEY hSubKey = 0;
|
|
DWORD dwType;
|
|
BOOL fRet = FALSE;
|
|
|
|
if(RegOpenKeyA(hKey, lpSubKey, &hSubKey) == ERROR_SUCCESS)
|
|
{
|
|
if (RegSetValueExA(hSubKey, lpValueName, 0, REG_DWORD, (PBYTE)&dwValue, sizeof(DWORD))
|
|
== ERROR_SUCCESS)
|
|
{
|
|
fRet = TRUE;
|
|
}
|
|
RegCloseKey(hSubKey);
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
BOOL
|
|
QueryRegValueDWORDA(
|
|
IN HKEY hKey,
|
|
IN LPCSTR lpSubKey,
|
|
IN LPCSTR lpValueName,
|
|
OUT LPDWORD lpdwValue
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Helper regsistry routine
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
TRUE if successful. If FALSE, GetLastError() gives the actual error code
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
|
|
HKEY hSubKey;
|
|
DWORD dwType, dwSize;
|
|
BOOL fRet = FALSE;
|
|
|
|
if(RegOpenKeyA(hKey, lpSubKey, &hSubKey) == ERROR_SUCCESS)
|
|
{
|
|
dwSize = sizeof(DWORD);
|
|
|
|
if (RegQueryValueExA(hSubKey, lpValueName, 0, &dwType, (PBYTE)lpdwValue, &dwSize)
|
|
== ERROR_SUCCESS)
|
|
{
|
|
fRet = TRUE;
|
|
}
|
|
|
|
RegCloseKey(hSubKey);
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
BOOL
|
|
DeleteRegValueA(
|
|
IN HKEY hKey,
|
|
IN LPCSTR lpSubKey,
|
|
IN LPCSTR lpValueName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Helper regsistry routine
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
TRUE if successful. If FALSE, GetLastError() gives the actual error code
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
HKEY hSubKey;
|
|
BOOL fRet = FALSE;
|
|
|
|
if(RegOpenKeyA(hKey, lpSubKey, &hSubKey) == ERROR_SUCCESS)
|
|
{
|
|
if(RegDeleteValueA(hSubKey, lpValueName) == ERROR_SUCCESS)
|
|
{
|
|
fRet = TRUE;
|
|
}
|
|
|
|
RegCloseKey(hSubKey);
|
|
}
|
|
|
|
return fRet;
|
|
|
|
}
|
|
|
|
BOOL
|
|
QueryFormatDatabase(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Helper regsistry routine
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
TRUE if successful. If FALSE, GetLastError() gives the actual error code
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
DWORD dwSize, dwTemp=0;
|
|
HKEY hKey = NULL;
|
|
BOOL fFormat = FALSE;
|
|
|
|
if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
REG_STRING_NETCACHE_KEY,
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
&hKey
|
|
) == ERROR_SUCCESS)
|
|
{
|
|
|
|
dwSize = sizeof(dwTemp);
|
|
dwTemp = 0;
|
|
|
|
if (RegQueryValueEx(hKey, REG_VALUE_FORMAT_DATABASE, NULL, NULL, (void *)&dwTemp, &dwSize) == ERROR_SUCCESS)
|
|
{
|
|
if(RegDeleteValue(hKey, REG_VALUE_FORMAT_DATABASE) != ERROR_SUCCESS)
|
|
{
|
|
// deliberte print to catch it in free builds as well
|
|
OutputDebugStringA("Not Formatting.. Failed to delete REG_VALUE_FORMAT_DATABASE_A \n");
|
|
}
|
|
else
|
|
{
|
|
fFormat = TRUE;
|
|
}
|
|
|
|
}
|
|
RegCloseKey(hKey);
|
|
hKey = NULL;
|
|
}
|
|
else
|
|
{
|
|
hKey = NULL;
|
|
}
|
|
|
|
|
|
if(hKey)
|
|
{
|
|
RegCloseKey(hKey);
|
|
}
|
|
return fFormat;
|
|
}
|
|
|
|
|
|
BOOL
|
|
InitValues(
|
|
LPSTR lpszDBDir,
|
|
DWORD cbDBDirSize,
|
|
LPDWORD lpdwDBCapacity,
|
|
LPDWORD lpdwClusterSize
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns init values to init CSC database and enable CSC
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
TRUE if successful. If FALSE, GetLastError() gives the actual error code
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
HKEY hKeyShadow;
|
|
int iSize;
|
|
DWORD dwType;
|
|
UINT lenDir;
|
|
BOOL fInitedDir = FALSE, fInitedSize=FALSE;
|
|
unsigned uPercent;
|
|
|
|
|
|
if(RegOpenKeyA(HKEY_LOCAL_MACHINE, REG_STRING_NETCACHE_KEY_A, &hKeyShadow) == ERROR_SUCCESS)
|
|
{
|
|
iSize = (int)cbDBDirSize;
|
|
|
|
if(RegQueryValueExA(hKeyShadow, REG_STRING_DATABASE_LOCATION_A, NULL, &dwType, lpszDBDir, &iSize)==ERROR_SUCCESS)
|
|
{
|
|
if ((iSize+SUBDIR_STRING_LENGTH+2)<MAX_PATH)
|
|
{
|
|
iSize = sizeof(DWORD);
|
|
|
|
fInitedDir = TRUE;
|
|
|
|
if(RegQueryValueExA(hKeyShadow, REG_VALUE_DATABASE_SIZE_A, NULL, &dwType, (LPBYTE)&uPercent, &iSize)==ERROR_SUCCESS)
|
|
{
|
|
if ((uPercent <= 100) &&
|
|
GetDiskSizeFromPercentage(lpszDBDir, uPercent, lpdwDBCapacity, lpdwClusterSize))
|
|
{
|
|
fInitedSize = TRUE;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
RegCloseKey(hKeyShadow);
|
|
}
|
|
|
|
if (!fInitedDir)
|
|
{
|
|
// try the default
|
|
|
|
if(!(lenDir=GetWindowsDirectoryA(lpszDBDir, cbDBDirSize)))
|
|
{
|
|
DEBUG_PRINT(("InitValuse: GetWindowsDirectory failed, error=%x \r\n", GetLastError()));
|
|
Assert(FALSE);
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
if ((lenDir+SUBDIR_STRING_LENGTH+2)>=MAX_PATH)
|
|
{
|
|
DEBUG_PRINT(("InbCreateDir: Windows dir name too big\r\n"));
|
|
Assert(FALSE);
|
|
|
|
// if even the default fails do the worst case thing.
|
|
// this may also not be good enough as apparently in Japan
|
|
// c: is not mandatory
|
|
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
if (lpszDBDir[lenDir-1]!='\\')
|
|
{
|
|
lpszDBDir[lenDir++] = '\\';
|
|
lpszDBDir[lenDir] = 0;
|
|
}
|
|
|
|
lstrcatA(lpszDBDir, vszCSCDirName);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
Assert(lpszDBDir[1]==':');
|
|
|
|
if (!fInitedSize)
|
|
{
|
|
if(!GetDiskSizeFromPercentage(lpszDBDir, DEFAULT_CACHE_PERCENTAGE, lpdwDBCapacity, lpdwClusterSize))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
// DEBUG_PRINT(("InitValues: CSCDb at %s Size = %d \r\n", lpszDBDir, *lpdwDBCapacity));
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
GetDiskSizeFromPercentage(
|
|
LPSTR lpszDir,
|
|
unsigned uPercent,
|
|
DWORD *lpdwSize,
|
|
DWORD *lpdwClusterSize
|
|
)
|
|
{
|
|
char szDrive[4];
|
|
DWORD dwSPC, dwBPS, dwFreeC, dwTotalC;
|
|
ULONGLONG ullSize = 0;
|
|
|
|
*lpdwSize = 0;
|
|
|
|
memset(szDrive, 0, sizeof(szDrive));
|
|
memcpy(szDrive, lpszDir, 3);
|
|
|
|
if(!GetDiskFreeSpaceA(szDrive, &dwSPC, &dwBPS, &dwFreeC, &dwTotalC )){
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
// DEBUG_PRINT(("dwSPC=%d dwBPS=%d uPercent=%d dwTotalC=%d \r\n",
|
|
// dwSPC, dwBPS, uPercent, dwTotalC));
|
|
|
|
ullSize = (((ULONGLONG)dwSPC * dwBPS * uPercent)/100)*dwTotalC;
|
|
|
|
// our max limit is 2GB
|
|
if (ullSize > 0x7fffffff)
|
|
{
|
|
*lpdwSize = 0x7fffffff;
|
|
}
|
|
else
|
|
{
|
|
*lpdwSize = (DWORD)ullSize;
|
|
}
|
|
*lpdwClusterSize = dwBPS * dwSPC;
|
|
}
|
|
return (TRUE);
|
|
}
|
|
|
|
#ifdef MAYBE_USEFULE
|
|
typedef struct tagCSC_NAME_CACHE_ENTRY
|
|
{
|
|
DWORD dwFlags;
|
|
DWORD dwTick;
|
|
HSHADOW hDir;
|
|
DWORD dwSize;
|
|
TCHAR *lptzName;
|
|
}
|
|
CSC_NAME_CACHE_ENTRY, *LPCSC_NAME_CACHE_ENTRY;
|
|
|
|
CSC_NAME_CACHE_ENTRY rgCSCNameCache[16];
|
|
|
|
HANDLE vhNameCacheMutex;
|
|
|
|
#define CSC_NAME_CACHE_EXPIRY_DELTA 1000*10 // 10 seconds
|
|
|
|
BOOL
|
|
FindCreateCSCNameCacheEntry(
|
|
LPTSTR lptzName,
|
|
DWORD dwSize,
|
|
HSHADOW *lphDir,
|
|
BOOL fCreate
|
|
);
|
|
|
|
BOOL
|
|
FindCreateShadowFromPathEx(
|
|
LPCTSTR lpszFile,
|
|
BOOL fCreate, // create if necessary
|
|
LPWIN32_FIND_DATA lpFind32,
|
|
LPSHADOWINFO lpSI,
|
|
BOOL *lpfCreated
|
|
)
|
|
{
|
|
BOOL fRet = FALSE, fIsShare, fFoundInCache = FALSE;
|
|
TCHAR *lpT;
|
|
DWORD cbSize;
|
|
|
|
lpT = GetLeafPtr((LPTSTR)lpszFile);
|
|
if (fIsShare = ((DWORD_PTR)lpT == (DWORD_PTR)lpszFile))
|
|
{
|
|
cbSize = lstrlen(lpT) * sizeof(_TCHAR);
|
|
}
|
|
else
|
|
{
|
|
cbSize = (DWORD_PTR)lpT - (DWORD_PTR)lpszFile - sizeof(_TCHAR);
|
|
}
|
|
|
|
if (!fIsShare)
|
|
{
|
|
if (!fCreate)
|
|
{
|
|
HSHADOW hDir;
|
|
// just look it up first
|
|
if (FindCreateCSCNameCacheEntry((LPTSTR)lpszFile, cbSize, &hDir, FALSE))
|
|
{
|
|
if (hDir != 0xffffffff)
|
|
{
|
|
// found it
|
|
if (lpfCreated)
|
|
{
|
|
*lpfCreated = FALSE;
|
|
}
|
|
//Bug 5512822 - navjotv
|
|
cbSize = min(MAX_PATH-1,(lstrlen(lpT)));
|
|
lstrcpyn(lpFind32->cFileName, lpT, cbSize);
|
|
lpFind32->cFileName[cbSize+1] = 0;
|
|
lpFind32->cAlternateFileName[0] = 0;
|
|
fRet = GetShadowEx(INVALID_HANDLE_VALUE, hDir, lpFind32, lpSI);
|
|
}
|
|
else
|
|
{
|
|
DbgPrint("Found negative cache entry %ls \n", lpszFile);
|
|
}
|
|
fFoundInCache = TRUE;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (!fFoundInCache)
|
|
{
|
|
// not found, do the normal thing
|
|
fRet = FindCreateShadowFromPath((LPTSTR)lpszFile, fCreate, lpFind32, lpSI, lpfCreated);
|
|
|
|
if (!fRet)
|
|
{
|
|
lpSI->hDir = lpSI->hShadow = 0xffffffff;
|
|
}
|
|
|
|
if (fRet || (GetLastError() == ERROR_FILE_NOT_FOUND))
|
|
{
|
|
FindCreateCSCNameCacheEntry((LPTSTR)lpszFile, cbSize, (lpSI->hDir)?&lpSI->hDir:&lpSI->hShadow, TRUE);
|
|
}
|
|
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
BOOL
|
|
FindCreateCSCNameCacheEntry(
|
|
LPTSTR lptzName,
|
|
DWORD dwSize,
|
|
HSHADOW *lphDir,
|
|
BOOL fCreate
|
|
)
|
|
{
|
|
int i, indx=-1;
|
|
DWORD dwTick = GetTickCount();
|
|
BOOL fRet = FALSE;
|
|
|
|
if (!vhNameCacheMutex)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
WaitForSingleObject(vhNameCacheMutex, INFINITE);
|
|
|
|
for (i=0; i<(sizeof(rgCSCNameCache)/sizeof(CSC_NAME_CACHE_ENTRY)); ++i)
|
|
{
|
|
if (!rgCSCNameCache[i].dwSize)
|
|
{
|
|
if (indx == -1)
|
|
{
|
|
indx = i;
|
|
}
|
|
}
|
|
else if ((rgCSCNameCache[i].dwSize == dwSize ))
|
|
{
|
|
//non-zero size must mean a string has been allocated
|
|
Assert(rgCSCNameCache[i].lptzName);
|
|
|
|
if ((dwTick < rgCSCNameCache[i].dwTick)||
|
|
((dwTick > (rgCSCNameCache[i].dwTick+CSC_NAME_CACHE_EXPIRY_DELTA))))
|
|
{
|
|
DbgPrint("%ls expired\n", rgCSCNameCache[i].lptzName);
|
|
// the entry has expired, nuke it
|
|
rgCSCNameCache[i].dwSize = 0;
|
|
FreeMem(rgCSCNameCache[i].lptzName);
|
|
rgCSCNameCache[i].lptzName = NULL;
|
|
continue;
|
|
}
|
|
|
|
// do a caseinsensitve comparison
|
|
if ((CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
|
|
lptzName, dwSize/sizeof(_TCHAR),
|
|
rgCSCNameCache[i].lptzName,dwSize/sizeof(_TCHAR))
|
|
== CSTR_EQUAL))
|
|
{
|
|
// match found
|
|
DbgPrint("Match Found %ls\n", rgCSCNameCache[i].lptzName);
|
|
if (fCreate)
|
|
{
|
|
rgCSCNameCache[i].hDir = *lphDir;
|
|
// update the tick count
|
|
rgCSCNameCache[i].dwTick = dwTick;
|
|
}
|
|
else
|
|
{
|
|
// we want to find it, return the directory
|
|
*lphDir = rgCSCNameCache[i].hDir;
|
|
}
|
|
fRet = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// didn't find it, we are supposed to create and there is an empty slot
|
|
if (!fRet && fCreate && (indx >= 0) )
|
|
{
|
|
rgCSCNameCache[indx].lptzName = AllocMem(dwSize+sizeof(_TCHAR));
|
|
if (rgCSCNameCache[indx].lptzName)
|
|
{
|
|
memcpy(rgCSCNameCache[indx].lptzName, lptzName, dwSize);
|
|
rgCSCNameCache[indx].dwSize = dwSize;
|
|
rgCSCNameCache[indx].dwTick = dwTick;
|
|
rgCSCNameCache[indx].hDir = *lphDir;
|
|
fRet = TRUE;
|
|
DbgPrint("Inserted %ls\n", rgCSCNameCache[indx].lptzName);
|
|
}
|
|
}
|
|
|
|
ReleaseMutex(vhNameCacheMutex);
|
|
|
|
return fRet;
|
|
}
|
|
|
|
#endif
|