Code/Resource
Windows Develop
Linux-Unix program
Internet-Socket-Network
Web Server
Browser Client
Ftp Server
Ftp Client
Browser Plugins
Proxy Server
Email Server
Email Client
WEB Mail
Firewall-Security
Telnet Server
Telnet Client
ICQ-IM-Chat
Search Engine
Sniffer Package capture
Remote Control
xml-soap-webservice
P2P
WEB(ASP,PHP,...)
TCP/IP Stack
SNMP
Grid Computing
SilverLight
DNS
Cluster Service
Network Security
Communication-Mobile
Game Program
Editor
Multimedia program
Graph program
Compiler program
Compress-Decompress algrithms
Crypt_Decrypt algrithms
Mathimatics-Numerical algorithms
MultiLanguage
Disk/Storage
Java Develop
assembly language
Applications
Other systems
Database system
Embeded-SCM Develop
FlashMX/Flex
source in ebook
Delphi VCL
OS Develop
MiddleWare
MPI
MacOS develop
LabView
ELanguage
Software/Tools
E-Books
Artical/Document
volume.c
Package: shell.rar [view]
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 41k
Category:
Windows Kernel
Development Platform:
Visual C++
- /*
- * volume.c - Volume ADT module.
- */
- /* Headers
- **********/
- #include "project.h"
- #pragma hdrstop
- #include "volume.h"
- /* Constants
- ************/
- /* VOLUMELIST PTRARRAY allocation parameters */
- #define NUM_START_VOLUMES (16)
- #define NUM_VOLUMES_TO_ADD (16)
- /* VOLUMELIST string table allocation parameters */
- #define NUM_VOLUME_HASH_BUCKETS (31)
- /* Types
- ********/
- /* volume list */
- typedef struct _volumelist
- {
- /* array of pointers to VOLUMEs */
- HPTRARRAY hpa;
- /* table of volume root path strings */
- HSTRINGTABLE hst;
- /* flags from RESOLVELINKINFOINFLAGS */
- DWORD dwFlags;
- /*
- * handle to parent window, only valid if RLI_IFL_ALLOW_UI is set in dwFlags
- * field
- */
- HWND hwndOwner;
- }
- VOLUMELIST;
- DECLARE_STANDARD_TYPES(VOLUMELIST);
- /* VOLUME flags */
- typedef enum _volumeflags
- {
- /* The volume root path string indicated by hsRootPath is valid. */
- VOLUME_FL_ROOT_PATH_VALID = 0x0001,
- /*
- * The net resource should be disconnected by calling DisconnectLinkInfo()
- * when finished.
- */
- VOLUME_FL_DISCONNECT = 0x0002,
- /* Any cached volume information should be verified before use. */
- VOLUME_FL_VERIFY_VOLUME = 0x0004,
- /* flag combinations */
- ALL_VOLUME_FLAGS = (VOLUME_FL_ROOT_PATH_VALID |
- VOLUME_FL_DISCONNECT |
- VOLUME_FL_VERIFY_VOLUME)
- }
- VOLUMEFLAGS;
- /* VOLUME states */
- typedef enum _volumestate
- {
- VS_UNKNOWN,
- VS_AVAILABLE,
- VS_UNAVAILABLE
- }
- VOLUMESTATE;
- DECLARE_STANDARD_TYPES(VOLUMESTATE);
- /* volume structure */
- typedef struct _volume
- {
- /* reference count */
- ULONG ulcLock;
- /* bit mask of flags from VOLUMEFLAGS */
- DWORD dwFlags;
- /* volume state */
- VOLUMESTATE vs;
- /* pointer to LinkInfo structure indentifying volume */
- PLINKINFO pli;
- /*
- * handle to volume root path string, only valid if
- * VOLUME_FL_ROOT_PATH_VALID is set in dwFlags field
- */
- HSTRING hsRootPath;
- /* pointer to parent volume list */
- PVOLUMELIST pvlParent;
- }
- VOLUME;
- DECLARE_STANDARD_TYPES(VOLUME);
- /* database volume list header */
- typedef struct _dbvolumelistheader
- {
- /* number of volumes in list */
- LONG lcVolumes;
- /* length of longest LinkInfo structure in volume list in bytes */
- UINT ucbMaxLinkInfoLen;
- }
- DBVOLUMELISTHEADER;
- DECLARE_STANDARD_TYPES(DBVOLUMELISTHEADER);
- /* database volume structure */
- typedef struct _dbvolume
- {
- /* old handle to volume */
- HVOLUME hvol;
- /* old LinkInfo structure follows */
- /* first DWORD of LinkInfo structure is total size in bytes */
- }
- DBVOLUME;
- DECLARE_STANDARD_TYPES(DBVOLUME);
- /***************************** Private Functions *****************************/
- /* Module Prototypes
- ********************/
- PRIVATE_CODE COMPARISONRESULT VolumeSortCmp(PCVOID, PCVOID);
- PRIVATE_CODE COMPARISONRESULT VolumeSearchCmp(PCVOID, PCVOID);
- PRIVATE_CODE BOOL SearchForVolumeByRootPathCmp(PCVOID, PCVOID);
- PRIVATE_CODE BOOL UnifyVolume(PVOLUMELIST, PLINKINFO, PVOLUME *);
- PRIVATE_CODE BOOL CreateVolume(PVOLUMELIST, PLINKINFO, PVOLUME *);
- PRIVATE_CODE void UnlinkVolume(PCVOLUME);
- PRIVATE_CODE BOOL DisconnectVolume(PVOLUME);
- PRIVATE_CODE void DestroyVolume(PVOLUME);
- PRIVATE_CODE void LockVolume(PVOLUME);
- PRIVATE_CODE BOOL UnlockVolume(PVOLUME);
- PRIVATE_CODE void InvalidateVolumeInfo(PVOLUME);
- PRIVATE_CODE void ClearVolumeInfo(PVOLUME);
- PRIVATE_CODE void GetUnavailableVolumeRootPath(PCLINKINFO, LPTSTR);
- PRIVATE_CODE BOOL VerifyAvailableVolume(PVOLUME);
- PRIVATE_CODE void ExpensiveResolveVolumeRootPath(PVOLUME, LPTSTR);
- PRIVATE_CODE void ResolveVolumeRootPath(PVOLUME, LPTSTR);
- PRIVATE_CODE VOLUMERESULT VOLUMERESULTFromLastError(VOLUMERESULT);
- PRIVATE_CODE TWINRESULT WriteVolume(HCACHEDFILE, PVOLUME);
- PRIVATE_CODE TWINRESULT ReadVolume(HCACHEDFILE, PVOLUMELIST, PLINKINFO, UINT, HHANDLETRANS);
- #if defined(DEBUG) || defined(VSTF)
- PRIVATE_CODE BOOL IsValidPCVOLUMELIST(PCVOLUMELIST);
- PRIVATE_CODE BOOL IsValidVOLUMESTATE(VOLUMESTATE);
- PRIVATE_CODE BOOL IsValidPCVOLUME(PCVOLUME);
- #endif
- #ifdef DEBUG
- PRIVATE_CODE BOOL IsValidPCVOLUMEDESC(PCVOLUMEDESC);
- #endif
- /*
- ** VolumeSortCmp()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- **
- ** Volumes are sorted by:
- ** 1) LinkInfo volume
- ** 2) pointer
- */
- PRIVATE_CODE COMPARISONRESULT VolumeSortCmp(PCVOID pcvol1, PCVOID pcvol2)
- {
- COMPARISONRESULT cr;
- ASSERT(IS_VALID_STRUCT_PTR(pcvol1, CVOLUME));
- ASSERT(IS_VALID_STRUCT_PTR(pcvol2, CVOLUME));
- cr = CompareLinkInfoVolumes(((PCVOLUME)pcvol1)->pli,
- ((PCVOLUME)pcvol2)->pli);
- if (cr == CR_EQUAL)
- cr = ComparePointers(pcvol1, pcvol1);
- return(cr);
- }
- /*
- ** VolumeSearchCmp()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- **
- ** Volumes are searched by:
- ** 1) LinkInfo volume
- */
- PRIVATE_CODE COMPARISONRESULT VolumeSearchCmp(PCVOID pcli, PCVOID pcvol)
- {
- ASSERT(IS_VALID_STRUCT_PTR(pcli, CLINKINFO));
- ASSERT(IS_VALID_STRUCT_PTR(pcvol, CVOLUME));
- return(CompareLinkInfoVolumes(pcli, ((PCVOLUME)pcvol)->pli));
- }
- /*
- ** SearchForVolumeByRootPathCmp()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- **
- ** Volumes are searched by:
- ** 1) available volume root path
- */
- PRIVATE_CODE BOOL SearchForVolumeByRootPathCmp(PCVOID pcszFullPath,
- PCVOID pcvol)
- {
- BOOL bDifferent;
- ASSERT(IsFullPath(pcszFullPath));
- ASSERT(IS_VALID_STRUCT_PTR(pcvol, CVOLUME));
- if (((PCVOLUME)pcvol)->vs == VS_AVAILABLE &&
- IS_FLAG_SET(((PCVOLUME)pcvol)->dwFlags, VOLUME_FL_ROOT_PATH_VALID))
- {
- LPCTSTR pcszVolumeRootPath;
- pcszVolumeRootPath = GetString(((PCVOLUME)pcvol)->hsRootPath);
- bDifferent = MyLStrCmpNI(pcszFullPath, pcszVolumeRootPath,
- lstrlen(pcszVolumeRootPath));
- }
- else
- bDifferent = TRUE;
- return(bDifferent);
- }
- /*
- ** UnifyVolume()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PRIVATE_CODE BOOL UnifyVolume(PVOLUMELIST pvl, PLINKINFO pliRoot,
- PVOLUME *ppvol)
- {
- BOOL bResult = FALSE;
- ASSERT(IS_VALID_STRUCT_PTR(pvl, CVOLUMELIST));
- ASSERT(IS_VALID_STRUCT_PTR(pliRoot, CLINKINFO));
- ASSERT(IS_VALID_WRITE_PTR(ppvol, PVOLUME));
- if (AllocateMemory(sizeof(**ppvol), ppvol))
- {
- if (CopyLinkInfo(pliRoot, &((*ppvol)->pli)))
- {
- ARRAYINDEX aiUnused;
- (*ppvol)->ulcLock = 0;
- (*ppvol)->dwFlags = 0;
- (*ppvol)->vs = VS_UNKNOWN;
- (*ppvol)->hsRootPath = NULL;
- (*ppvol)->pvlParent = pvl;
- if (AddPtr(pvl->hpa, VolumeSortCmp, *ppvol, &aiUnused))
- bResult = TRUE;
- else
- {
- FreeMemory((*ppvol)->pli);
- UNIFYVOLUME_BAIL:
- FreeMemory(*ppvol);
- }
- }
- else
- goto UNIFYVOLUME_BAIL;
- }
- ASSERT(! bResult ||
- IS_VALID_STRUCT_PTR(*ppvol, CVOLUME));
- return(bResult);
- }
- /*
- ** CreateVolume()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PRIVATE_CODE BOOL CreateVolume(PVOLUMELIST pvl, PLINKINFO pliRoot,
- PVOLUME *ppvol)
- {
- BOOL bResult;
- PVOLUME pvol;
- ARRAYINDEX aiFound;
- ASSERT(IS_VALID_STRUCT_PTR(pvl, CVOLUMELIST));
- ASSERT(IS_VALID_STRUCT_PTR(pliRoot, CLINKINFO));
- ASSERT(IS_VALID_WRITE_PTR(ppvol, PVOLUME));
- /* Does a volume for the given root path already exist? */
- if (SearchSortedArray(pvl->hpa, &VolumeSearchCmp, pliRoot, &aiFound))
- {
- pvol = GetPtr(pvl->hpa, aiFound);
- bResult = TRUE;
- }
- else
- bResult = UnifyVolume(pvl, pliRoot, &pvol);
- if (bResult)
- {
- LockVolume(pvol);
- *ppvol = pvol;
- }
- ASSERT(! bResult ||
- IS_VALID_STRUCT_PTR(*ppvol, CVOLUME));
- return(bResult);
- }
- /*
- ** UnlinkVolume()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PRIVATE_CODE void UnlinkVolume(PCVOLUME pcvol)
- {
- HPTRARRAY hpa;
- ARRAYINDEX aiFound;
- ASSERT(IS_VALID_STRUCT_PTR(pcvol, CVOLUME));
- hpa = pcvol->pvlParent->hpa;
- if (EVAL(SearchSortedArray(hpa, &VolumeSortCmp, pcvol, &aiFound)))
- {
- ASSERT(GetPtr(hpa, aiFound) == pcvol);
- DeletePtr(hpa, aiFound);
- }
- return;
- }
- /*
- ** DisconnectVolume()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PRIVATE_CODE BOOL DisconnectVolume(PVOLUME pvol)
- {
- BOOL bResult;
- ASSERT(IS_VALID_STRUCT_PTR(pvol, CVOLUME));
- if (IS_FLAG_SET(pvol->dwFlags, VOLUME_FL_DISCONNECT))
- {
- bResult = DisconnectLinkInfo(pvol->pli);
- CLEAR_FLAG(pvol->dwFlags, VOLUME_FL_DISCONNECT);
- }
- else
- bResult = TRUE;
- return(bResult);
- }
- /*
- ** DestroyVolume()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PRIVATE_CODE void DestroyVolume(PVOLUME pvol)
- {
- ASSERT(IS_VALID_STRUCT_PTR(pvol, CVOLUME));
- ClearVolumeInfo(pvol);
- FreeMemory(pvol->pli);
- FreeMemory(pvol);
- return;
- }
- /*
- ** LockVolume()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PRIVATE_CODE void LockVolume(PVOLUME pvol)
- {
- ASSERT(IS_VALID_STRUCT_PTR(pvol, CVOLUME));
- ASSERT(pvol->ulcLock < ULONG_MAX);
- pvol->ulcLock++;
- return;
- }
- /*
- ** UnlockVolume()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PRIVATE_CODE BOOL UnlockVolume(PVOLUME pvol)
- {
- ASSERT(IS_VALID_STRUCT_PTR(pvol, CVOLUME));
- if (EVAL(pvol->ulcLock > 0))
- pvol->ulcLock--;
- return(pvol->ulcLock > 0);
- }
- /*
- ** InvalidateVolumeInfo()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PRIVATE_CODE void InvalidateVolumeInfo(PVOLUME pvol)
- {
- ASSERT(IS_VALID_STRUCT_PTR(pvol, CVOLUME));
- SET_FLAG(pvol->dwFlags, VOLUME_FL_VERIFY_VOLUME);
- ASSERT(IS_VALID_STRUCT_PTR(pvol, CVOLUME));
- return;
- }
- /*
- ** ClearVolumeInfo()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PRIVATE_CODE void ClearVolumeInfo(PVOLUME pvol)
- {
- ASSERT(IS_VALID_STRUCT_PTR(pvol, CVOLUME));
- DisconnectVolume(pvol);
- if (IS_FLAG_SET(pvol->dwFlags, VOLUME_FL_ROOT_PATH_VALID))
- {
- DeleteString(pvol->hsRootPath);
- CLEAR_FLAG(pvol->dwFlags, VOLUME_FL_ROOT_PATH_VALID);
- }
- CLEAR_FLAG(pvol->dwFlags, VOLUME_FL_VERIFY_VOLUME);
- pvol->vs = VS_UNKNOWN;
- ASSERT(IS_VALID_STRUCT_PTR(pvol, CVOLUME));
- return;
- }
- /*
- ** GetUnavailableVolumeRootPath()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PRIVATE_CODE void GetUnavailableVolumeRootPath(PCLINKINFO pcli,
- LPTSTR pszRootPathBuf)
- {
- LPCSTR pcszLinkInfoData;
- ASSERT(IS_VALID_STRUCT_PTR(pcli, CLINKINFO));
- ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszRootPathBuf, STR, MAX_PATH_LEN));
- /*
- * Try unavailable volume root paths in the following order:
- * 1) last redirected device
- * 2) net resource name
- * 3) local path ...and take the _last_ good one!
- */
- if (GetLinkInfoData(pcli, LIDT_REDIRECTED_DEVICE, &pcszLinkInfoData) ||
- GetLinkInfoData(pcli, LIDT_NET_RESOURCE, &pcszLinkInfoData) ||
- GetLinkInfoData(pcli, LIDT_LOCAL_BASE_PATH, &pcszLinkInfoData))
- {
- //ASSERT(IS_VALID_STRING_PTR(pcszLinkInfoData, CSTR));
- ASSERT(lstrlenA(pcszLinkInfoData) < MAX_PATH_LEN);
- // BUGBUG somewhere, someone might need to handle unicode base paths
- #ifdef UNICODE
- {
- TCHAR szTmp[MAX_PATH] = TEXT("");
- MultiByteToWideChar(CP_ACP, 0, pcszLinkInfoData, -1, szTmp, MAX_PATH);
- ComposePath(pszRootPathBuf, szTmp, TEXT("\"));
- }
- #else
- ComposePath(pszRootPathBuf, pcszLinkInfoData, TEXT("\"));
- #endif
- }
- else
- {
- pszRootPathBuf[0] = TEXT('');
- ERROR_OUT((TEXT("GetUnavailableVolumeRootPath(): Net resource name and local base path unavailable. Using empty string as unavailable root path.")));
- }
- ASSERT(IsRootPath(pszRootPathBuf) &&
- EVAL(lstrlen(pszRootPathBuf) < MAX_PATH_LEN));
- return;
- }
- /*
- ** VerifyAvailableVolume()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PRIVATE_CODE BOOL VerifyAvailableVolume(PVOLUME pvol)
- {
- BOOL bResult = FALSE;
- PLINKINFO pli;
- ASSERT(IS_VALID_STRUCT_PTR(pvol, CVOLUME));
- ASSERT(pvol->vs == VS_AVAILABLE);
- ASSERT(IS_FLAG_SET(pvol->dwFlags, VOLUME_FL_ROOT_PATH_VALID));
- WARNING_OUT((TEXT("VerifyAvailableVolume(): Calling CreateLinkInfo() to verify volume on %s."),
- GetString(pvol->hsRootPath)));
- if (CreateLinkInfo(GetString(pvol->hsRootPath), &pli))
- {
- bResult = (CompareLinkInfoReferents(pvol->pli, pli) == CR_EQUAL);
- DestroyLinkInfo(pli);
- if (bResult)
- TRACE_OUT((TEXT("VerifyAvailableVolume(): Volume %s has not changed."),
- GetString(pvol->hsRootPath)));
- else
- WARNING_OUT((TEXT("VerifyAvailableVolume(): Volume %s has changed."),
- GetString(pvol->hsRootPath)));
- }
- else
- WARNING_OUT((TEXT("VerifyAvailableVolume(): CreateLinkInfo() failed for %s."),
- GetString(pvol->hsRootPath)));
- return(bResult);
- }
- /*
- ** ExpensiveResolveVolumeRootPath()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PRIVATE_CODE void ExpensiveResolveVolumeRootPath(PVOLUME pvol,
- LPTSTR pszVolumeRootPathBuf)
- {
- BOOL bResult;
- DWORD dwOutFlags;
- PLINKINFO pliUpdated;
- HSTRING hsRootPath;
- ASSERT(IS_VALID_STRUCT_PTR(pvol, CVOLUME));
- ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszVolumeRootPathBuf, STR, MAX_PATH_LEN));
- if (pvol->vs == VS_UNKNOWN ||
- pvol->vs == VS_AVAILABLE)
- {
- /*
- * Only request a connection if connections are still permitted in this
- * volume list.
- */
- WARNING_OUT((TEXT("ExpensiveResolveVolumeRootPath(): Calling ResolveLinkInfo() to determine volume availability and root path.")));
- bResult = ResolveLinkInfo(pvol->pli, pszVolumeRootPathBuf,
- pvol->pvlParent->dwFlags,
- pvol->pvlParent->hwndOwner, &dwOutFlags,
- &pliUpdated);
- if (bResult)
- {
- pvol->vs = VS_AVAILABLE;
- if (IS_FLAG_SET(dwOutFlags, RLI_OFL_UPDATED))
- {
- PLINKINFO pliUpdatedCopy;
- ASSERT(IS_FLAG_SET(pvol->pvlParent->dwFlags, RLI_IFL_UPDATE));
- if (CopyLinkInfo(pliUpdated, &pliUpdatedCopy))
- {
- FreeMemory(pvol->pli);
- pvol->pli = pliUpdatedCopy;
- }
- DestroyLinkInfo(pliUpdated);
- WARNING_OUT((TEXT("ExpensiveResolveVolumeRootPath(): Updating LinkInfo for volume %s."),
- pszVolumeRootPathBuf));
- }
- if (IS_FLAG_SET(dwOutFlags, RLI_OFL_DISCONNECT))
- {
- SET_FLAG(pvol->dwFlags, VOLUME_FL_DISCONNECT);
- WARNING_OUT((TEXT("ExpensiveResolveVolumeRootPath(): Volume %s must be disconnected when finished."),
- pszVolumeRootPathBuf));
- }
- TRACE_OUT((TEXT("ExpensiveResolveVolumeRootPath(): Volume %s is available."),
- pszVolumeRootPathBuf));
- }
- else
- ASSERT(GetLastError() != ERROR_INVALID_PARAMETER);
- }
- else
- {
- ASSERT(pvol->vs == VS_UNAVAILABLE);
- bResult = FALSE;
- }
- if (! bResult)
- {
- pvol->vs = VS_UNAVAILABLE;
- if (GetLastError() == ERROR_CANCELLED)
- {
- ASSERT(IS_FLAG_SET(pvol->pvlParent->dwFlags, RLI_IFL_CONNECT));
- CLEAR_FLAG(pvol->pvlParent->dwFlags, RLI_IFL_CONNECT);
- WARNING_OUT((TEXT("ExpensiveResolveVolumeRootPath(): Connection attempt cancelled. No subsequent connections will be attempted.")));
- }
- GetUnavailableVolumeRootPath(pvol->pli, pszVolumeRootPathBuf);
- WARNING_OUT((TEXT("ExpensiveResolveVolumeRootPath(): Using %s as unavailable volume root path."),
- pszVolumeRootPathBuf));
- }
- /* Add volume root path string to volume list's string table. */
- if (IS_FLAG_SET(pvol->dwFlags, VOLUME_FL_ROOT_PATH_VALID))
- {
- CLEAR_FLAG(pvol->dwFlags, VOLUME_FL_ROOT_PATH_VALID);
- DeleteString(pvol->hsRootPath);
- }
- if (AddString(pszVolumeRootPathBuf, pvol->pvlParent->hst, GetHashBucketIndex, &hsRootPath))
- {
- SET_FLAG(pvol->dwFlags, VOLUME_FL_ROOT_PATH_VALID);
- pvol->hsRootPath = hsRootPath;
- }
- else
- WARNING_OUT((TEXT("ExpensiveResolveVolumeRootPath(): Unable to save %s as volume root path."),
- pszVolumeRootPathBuf));
- return;
- }
- /*
- ** ResolveVolumeRootPath()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PRIVATE_CODE void ResolveVolumeRootPath(PVOLUME pvol,
- LPTSTR pszVolumeRootPathBuf)
- {
- ASSERT(IS_VALID_STRUCT_PTR(pvol, CVOLUME));
- ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszVolumeRootPathBuf, STR, MAX_PATH_LEN));
- /* Do we have a cached volume root path to use? */
- if (IS_FLAG_SET(pvol->dwFlags, VOLUME_FL_ROOT_PATH_VALID) &&
- (IS_FLAG_CLEAR(pvol->dwFlags, VOLUME_FL_VERIFY_VOLUME) ||
- (pvol->vs == VS_AVAILABLE &&
- VerifyAvailableVolume(pvol))))
- {
- /* Yes. */
- MyLStrCpyN(pszVolumeRootPathBuf, GetString(pvol->hsRootPath), MAX_PATH_LEN);
- ASSERT(lstrlen(pszVolumeRootPathBuf) < MAX_PATH_LEN);
- ASSERT(pvol->vs != VS_UNKNOWN);
- }
- else
- /* No. Welcome in I/O City. */
- ExpensiveResolveVolumeRootPath(pvol, pszVolumeRootPathBuf);
- CLEAR_FLAG(pvol->dwFlags, VOLUME_FL_VERIFY_VOLUME);
- ASSERT(IS_VALID_STRUCT_PTR(pvol, CVOLUME));
- return;
- }
- /*
- ** VOLUMERESULTFromLastError()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PRIVATE_CODE VOLUMERESULT VOLUMERESULTFromLastError(VOLUMERESULT vr)
- {
- switch (GetLastError())
- {
- case ERROR_OUTOFMEMORY:
- vr = VR_OUT_OF_MEMORY;
- break;
- case ERROR_BAD_PATHNAME:
- vr = VR_INVALID_PATH;
- break;
- default:
- break;
- }
- return(vr);
- }
- /*
- ** WriteVolume()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PRIVATE_CODE TWINRESULT WriteVolume(HCACHEDFILE hcf, PVOLUME pvol)
- {
- TWINRESULT tr;
- DBVOLUME dbvol;
- ASSERT(IS_VALID_HANDLE(hcf, CACHEDFILE));
- ASSERT(IS_VALID_STRUCT_PTR(pvol, CVOLUME));
- /* Write database volume followed by LinkInfo structure. */
- dbvol.hvol = (HVOLUME)pvol;
- if (WriteToCachedFile(hcf, (PCVOID)&dbvol, sizeof(dbvol), NULL) &&
- WriteToCachedFile(hcf, pvol->pli, *(PDWORD)(pvol->pli), NULL))
- tr = TR_SUCCESS;
- else
- tr = TR_BRIEFCASE_WRITE_FAILED;
- return(tr);
- }
- /*
- ** ReadVolume()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PRIVATE_CODE TWINRESULT ReadVolume(HCACHEDFILE hcf, PVOLUMELIST pvl,
- PLINKINFO pliBuf, UINT ucbLinkInfoBufLen,
- HHANDLETRANS hhtVolumes)
- {
- TWINRESULT tr = TR_CORRUPT_BRIEFCASE;
- DBVOLUME dbvol;
- DWORD dwcbRead;
- UINT ucbLinkInfoLen;
- ASSERT(IS_VALID_HANDLE(hcf, CACHEDFILE));
- ASSERT(IS_VALID_STRUCT_PTR(pvl, CVOLUMELIST));
- ASSERT(IS_VALID_WRITE_BUFFER_PTR(pliBuf, LINKINFO, ucbLinkInfoBufLen));
- ASSERT(IS_VALID_HANDLE(hhtVolumes, HANDLETRANS));
- if (ReadFromCachedFile(hcf, &dbvol, sizeof(dbvol), &dwcbRead) &&
- dwcbRead == sizeof(dbvol) &&
- ReadFromCachedFile(hcf, &ucbLinkInfoLen, sizeof(ucbLinkInfoLen), &dwcbRead) &&
- dwcbRead == sizeof(ucbLinkInfoLen) &&
- ucbLinkInfoLen <= ucbLinkInfoBufLen)
- {
- /* Read the remainder of the LinkInfo structure into memory. */
- DWORD dwcbRemainder;
- pliBuf->ucbSize = ucbLinkInfoLen;
- dwcbRemainder = ucbLinkInfoLen - sizeof(ucbLinkInfoLen);
- if (ReadFromCachedFile(hcf, (PBYTE)pliBuf + sizeof(ucbLinkInfoLen),
- dwcbRemainder, &dwcbRead) &&
- dwcbRead == dwcbRemainder &&
- IsValidLinkInfo(pliBuf))
- {
- PVOLUME pvol;
- if (CreateVolume(pvl, pliBuf, &pvol))
- {
- /*
- * To leave read volumes with 0 initial lock count, we must undo
- * the LockVolume() performed by CreateVolume().
- */
- UnlockVolume(pvol);
- if (AddHandleToHandleTranslator(hhtVolumes,
- (HGENERIC)(dbvol.hvol),
- (HGENERIC)pvol))
- tr = TR_SUCCESS;
- else
- {
- UnlinkVolume(pvol);
- DestroyVolume(pvol);
- tr = TR_OUT_OF_MEMORY;
- }
- }
- else
- tr = TR_OUT_OF_MEMORY;
- }
- }
- return(tr);
- }
- #if defined(DEBUG) || defined(VSTF)
- /*
- ** IsValidPCVOLUMELIST()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PRIVATE_CODE BOOL IsValidPCVOLUMELIST(PCVOLUMELIST pcvl)
- {
- return(IS_VALID_READ_PTR(pcvl, CVOLUMELIST) &&
- IS_VALID_HANDLE(pcvl->hpa, PTRARRAY) &&
- IS_VALID_HANDLE(pcvl->hst, STRINGTABLE) &&
- FLAGS_ARE_VALID(pcvl->dwFlags, ALL_RLI_IFLAGS) &&
- (IS_FLAG_CLEAR(pcvl->dwFlags, RLI_IFL_ALLOW_UI) ||
- IS_VALID_HANDLE(pcvl->hwndOwner, WND)));
- }
- /*
- ** IsValidVOLUMESTATE()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PRIVATE_CODE BOOL IsValidVOLUMESTATE(VOLUMESTATE vs)
- {
- BOOL bResult;
- switch (vs)
- {
- case VS_UNKNOWN:
- case VS_AVAILABLE:
- case VS_UNAVAILABLE:
- bResult = TRUE;
- break;
- default:
- ERROR_OUT((TEXT("IsValidVOLUMESTATE(): Invalid VOLUMESTATE %d."),
- vs));
- bResult = FALSE;
- break;
- }
- return(bResult);
- }
- /*
- ** IsValidPCVOLUME()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PRIVATE_CODE BOOL IsValidPCVOLUME(PCVOLUME pcvol)
- {
- return(IS_VALID_READ_PTR(pcvol, CVOLUME) &&
- FLAGS_ARE_VALID(pcvol->dwFlags, ALL_VOLUME_FLAGS) &&
- EVAL(IsValidVOLUMESTATE(pcvol->vs)) &&
- IS_VALID_STRUCT_PTR(pcvol->pli, CLINKINFO) &&
- (IS_FLAG_CLEAR(pcvol->dwFlags, VOLUME_FL_ROOT_PATH_VALID) ||
- IS_VALID_HANDLE(pcvol->hsRootPath, STRING)) &&
- IS_VALID_STRUCT_PTR(pcvol->pvlParent, CVOLUMELIST));
- }
- #endif
- #ifdef DEBUG
- /*
- ** IsValidPCVOLUMEDESC()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PRIVATE_CODE BOOL IsValidPCVOLUMEDESC(PCVOLUMEDESC pcvoldesc)
- {
- /*
- * A set dwSerialNumber may be any value. An unset dwSerialNumber must be
- * 0. A set strings may be any valid string. An unset string must be the
- * empty string.
- */
- return(IS_VALID_READ_PTR(pcvoldesc, CVOLUMEDESC) &&
- EVAL(pcvoldesc->ulSize == sizeof(*pcvoldesc)) &&
- FLAGS_ARE_VALID(pcvoldesc->dwFlags, ALL_VD_FLAGS) &&
- (IS_FLAG_SET(pcvoldesc->dwFlags, VD_FL_SERIAL_NUMBER_VALID) ||
- ! pcvoldesc->dwSerialNumber) &&
- ((IS_FLAG_CLEAR(pcvoldesc->dwFlags, VD_FL_VOLUME_LABEL_VALID) &&
- ! pcvoldesc->rgchVolumeLabel[0]) ||
- (IS_FLAG_SET(pcvoldesc->dwFlags, VD_FL_VOLUME_LABEL_VALID) &&
- IS_VALID_STRING_PTR(pcvoldesc->rgchVolumeLabel, CSTR) &&
- EVAL(lstrlen(pcvoldesc->rgchVolumeLabel) < ARRAYSIZE(pcvoldesc->rgchVolumeLabel)))) &&
- ((IS_FLAG_CLEAR(pcvoldesc->dwFlags, VD_FL_NET_RESOURCE_VALID) &&
- ! pcvoldesc->rgchNetResource[0]) ||
- (IS_FLAG_SET(pcvoldesc->dwFlags, VD_FL_NET_RESOURCE_VALID) &&
- IS_VALID_STRING_PTR(pcvoldesc->rgchNetResource, CSTR) &&
- EVAL(lstrlen(pcvoldesc->rgchNetResource) < ARRAYSIZE(pcvoldesc->rgchNetResource)))));
- }
- #endif
- /****************************** Public Functions *****************************/
- /*
- ** CreateVolumeList()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PUBLIC_CODE BOOL CreateVolumeList(DWORD dwFlags, HWND hwndOwner,
- PHVOLUMELIST phvl)
- {
- BOOL bResult = FALSE;
- PVOLUMELIST pvl;
- ASSERT(FLAGS_ARE_VALID(dwFlags, ALL_RLI_IFLAGS));
- ASSERT(IS_FLAG_CLEAR(dwFlags, RLI_IFL_ALLOW_UI) ||
- IS_VALID_HANDLE(hwndOwner, WND));
- ASSERT(IS_VALID_WRITE_PTR(phvl, HVOLUMELIST));
- if (AllocateMemory(sizeof(*pvl), &pvl))
- {
- NEWSTRINGTABLE nszt;
- /* Create string table for volume root path strngs. */
- nszt.hbc = NUM_VOLUME_HASH_BUCKETS;
- if (CreateStringTable(&nszt, &(pvl->hst)))
- {
- NEWPTRARRAY npa;
- /* Create pointer array of volumes. */
- npa.aicInitialPtrs = NUM_START_VOLUMES;
- npa.aicAllocGranularity = NUM_VOLUMES_TO_ADD;
- npa.dwFlags = NPA_FL_SORTED_ADD;
- if (CreatePtrArray(&npa, &(pvl->hpa)))
- {
- pvl->dwFlags = dwFlags;
- pvl->hwndOwner = hwndOwner;
- *phvl = (HVOLUMELIST)pvl;
- bResult = TRUE;
- }
- else
- {
- DestroyStringTable(pvl->hst);
- CREATEVOLUMELIST_BAIL:
- FreeMemory(pvl);
- }
- }
- else
- goto CREATEVOLUMELIST_BAIL;
- }
- ASSERT(! bResult ||
- IS_VALID_HANDLE(*phvl, VOLUMELIST));
- return(bResult);
- }
- /*
- ** DestroyVolumeList()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PUBLIC_CODE void DestroyVolumeList(HVOLUMELIST hvl)
- {
- ARRAYINDEX aicPtrs;
- ARRAYINDEX ai;
- ASSERT(IS_VALID_HANDLE(hvl, VOLUMELIST));
- /* First free all volumes in array. */
- aicPtrs = GetPtrCount(((PCVOLUMELIST)hvl)->hpa);
- for (ai = 0; ai < aicPtrs; ai++)
- DestroyVolume(GetPtr(((PCVOLUMELIST)hvl)->hpa, ai));
- /* Now wipe out the array. */
- DestroyPtrArray(((PCVOLUMELIST)hvl)->hpa);
- ASSERT(! GetStringCount(((PCVOLUMELIST)hvl)->hst));
- DestroyStringTable(((PCVOLUMELIST)hvl)->hst);
- FreeMemory((PVOLUMELIST)hvl);
- return;
- }
- /*
- ** InvalidateVolumeListInfo()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PUBLIC_CODE void InvalidateVolumeListInfo(HVOLUMELIST hvl)
- {
- ARRAYINDEX aicPtrs;
- ARRAYINDEX ai;
- ASSERT(IS_VALID_HANDLE(hvl, VOLUMELIST));
- aicPtrs = GetPtrCount(((PCVOLUMELIST)hvl)->hpa);
- for (ai = 0; ai < aicPtrs; ai++)
- InvalidateVolumeInfo(GetPtr(((PCVOLUMELIST)hvl)->hpa, ai));
- WARNING_OUT((TEXT("InvalidateVolumeListInfo(): Volume cache invalidated.")));
- return;
- }
- /*
- ** ClearVolumeListInfo()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PUBLIC_CODE void ClearVolumeListInfo(HVOLUMELIST hvl)
- {
- ARRAYINDEX aicPtrs;
- ARRAYINDEX ai;
- ASSERT(IS_VALID_HANDLE(hvl, VOLUMELIST));
- aicPtrs = GetPtrCount(((PCVOLUMELIST)hvl)->hpa);
- for (ai = 0; ai < aicPtrs; ai++)
- ClearVolumeInfo(GetPtr(((PCVOLUMELIST)hvl)->hpa, ai));
- WARNING_OUT((TEXT("ClearVolumeListInfo(): Volume cache cleared.")));
- return;
- }
- /*
- ** AddVolume()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PUBLIC_CODE VOLUMERESULT AddVolume(HVOLUMELIST hvl, LPCTSTR pcszPath,
- PHVOLUME phvol, LPTSTR pszPathSuffixBuf)
- {
- VOLUMERESULT vr;
- TCHAR rgchPath[MAX_PATH_LEN];
- LPTSTR pszFileName;
- DWORD dwPathLen;
- ASSERT(IS_VALID_HANDLE(hvl, VOLUMELIST));
- ASSERT(IS_VALID_STRING_PTR(pcszPath, CSTR));
- ASSERT(IS_VALID_WRITE_PTR(phvol, HVOLUME));
- ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszPathSuffixBuf, STR, MAX_PATH_LEN));
- dwPathLen = GetFullPathName(pcszPath, ARRAYSIZE(rgchPath), rgchPath,
- &pszFileName);
- if (dwPathLen > 0 && dwPathLen < ARRAYSIZE(rgchPath))
- {
- ARRAYINDEX aiFound;
- /* Does a volume for this root path already exist? */
- if (LinearSearchArray(((PVOLUMELIST)hvl)->hpa,
- &SearchForVolumeByRootPathCmp, rgchPath,
- &aiFound))
- {
- PVOLUME pvol;
- LPCTSTR pcszVolumeRootPath;
- /* Yes. */
- pvol = GetPtr(((PVOLUMELIST)hvl)->hpa, aiFound);
- LockVolume(pvol);
- ASSERT(pvol->vs == VS_AVAILABLE &&
- IS_FLAG_SET(pvol->dwFlags, VOLUME_FL_ROOT_PATH_VALID));
- pcszVolumeRootPath = GetString(pvol->hsRootPath);
- ASSERT(lstrlen(pcszVolumeRootPath) <= lstrlen(rgchPath));
- lstrcpy(pszPathSuffixBuf, rgchPath + lstrlen(pcszVolumeRootPath));
- *phvol = (HVOLUME)pvol;
- vr = VR_SUCCESS;
- }
- else
- {
- DWORD dwOutFlags;
- TCHAR rgchNetResource[MAX_PATH_LEN];
- LPTSTR pszRootPathSuffix;
- /* No. Create a new volume. */
- if (GetCanonicalPathInfo(pcszPath, rgchPath, &dwOutFlags,
- rgchNetResource, &pszRootPathSuffix))
- {
- PLINKINFO pli;
- lstrcpy(pszPathSuffixBuf, pszRootPathSuffix);
- *pszRootPathSuffix = TEXT('');
- WARNING_OUT((TEXT("AddVolume(): Creating LinkInfo for root path %s."),
- rgchPath));
- if (CreateLinkInfo(rgchPath, &pli))
- {
- PVOLUME pvol;
- if (CreateVolume((PVOLUMELIST)hvl, pli, &pvol))
- {
- TCHAR rgchUnusedVolumeRootPath[MAX_PATH_LEN];
- ResolveVolumeRootPath(pvol, rgchUnusedVolumeRootPath);
- *phvol = (HVOLUME)pvol;
- vr = VR_SUCCESS;
- }
- else
- vr = VR_OUT_OF_MEMORY;
- DestroyLinkInfo(pli);
- }
- else
- /*
- * Differentiate between VR_UNAVAILABLE_VOLUME and
- * VR_OUT_OF_MEMORY.
- */
- vr = VOLUMERESULTFromLastError(VR_UNAVAILABLE_VOLUME);
- }
- else
- vr = VOLUMERESULTFromLastError(VR_INVALID_PATH);
- }
- }
- else
- {
- ASSERT(! dwPathLen);
- vr = VOLUMERESULTFromLastError(VR_INVALID_PATH);
- }
- ASSERT(vr != VR_SUCCESS ||
- (IS_VALID_HANDLE(*phvol, VOLUME) &&
- EVAL(IsValidPathSuffix(pszPathSuffixBuf))));
- return(vr);
- }
- /*
- ** DeleteVolume()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PUBLIC_CODE void DeleteVolume(HVOLUME hvol)
- {
- ASSERT(IS_VALID_HANDLE(hvol, VOLUME));
- if (! UnlockVolume((PVOLUME)hvol))
- {
- UnlinkVolume((PVOLUME)hvol);
- DestroyVolume((PVOLUME)hvol);
- }
- return;
- }
- /*
- ** CompareVolumes()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PUBLIC_CODE COMPARISONRESULT CompareVolumes(HVOLUME hvolFirst,
- HVOLUME hvolSecond)
- {
- ASSERT(IS_VALID_HANDLE(hvolFirst, VOLUME));
- ASSERT(IS_VALID_HANDLE(hvolSecond, VOLUME));
- /* This comparison works across volume lists. */
- return(CompareLinkInfoVolumes(((PCVOLUME)hvolFirst)->pli,
- ((PCVOLUME)hvolSecond)->pli));
- }
- /*
- ** CopyVolume()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PUBLIC_CODE BOOL CopyVolume(HVOLUME hvolSrc, HVOLUMELIST hvlDest,
- PHVOLUME phvolCopy)
- {
- BOOL bResult;
- PVOLUME pvol;
- ASSERT(IS_VALID_HANDLE(hvolSrc, VOLUME));
- ASSERT(IS_VALID_HANDLE(hvlDest, VOLUMELIST));
- ASSERT(IS_VALID_WRITE_PTR(phvolCopy, HVOLUME));
- /* Is the destination volume list the source volume's volume list? */
- if (((PCVOLUME)hvolSrc)->pvlParent == (PCVOLUMELIST)hvlDest)
- {
- /* Yes. Use the source volume. */
- LockVolume((PVOLUME)hvolSrc);
- pvol = (PVOLUME)hvolSrc;
- bResult = TRUE;
- }
- else
- bResult = CreateVolume((PVOLUMELIST)hvlDest, ((PCVOLUME)hvolSrc)->pli,
- &pvol);
- if (bResult)
- *phvolCopy = (HVOLUME)pvol;
- ASSERT(! bResult ||
- IS_VALID_HANDLE(*phvolCopy, VOLUME));
- return(bResult);
- }
- /*
- ** IsVolumeAvailable()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PUBLIC_CODE BOOL IsVolumeAvailable(HVOLUME hvol)
- {
- TCHAR rgchUnusedVolumeRootPath[MAX_PATH_LEN];
- ASSERT(IS_VALID_HANDLE(hvol, VOLUME));
- ResolveVolumeRootPath((PVOLUME)hvol, rgchUnusedVolumeRootPath);
- ASSERT(IsValidVOLUMESTATE(((PCVOLUME)hvol)->vs) &&
- ((PCVOLUME)hvol)->vs != VS_UNKNOWN);
- return(((PCVOLUME)hvol)->vs == VS_AVAILABLE);
- }
- /*
- ** GetVolumeRootPath()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PUBLIC_CODE void GetVolumeRootPath(HVOLUME hvol, LPTSTR pszRootPathBuf)
- {
- ASSERT(IS_VALID_HANDLE(hvol, VOLUME));
- ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszRootPathBuf, STR, MAX_PATH_LEN));
- ResolveVolumeRootPath((PVOLUME)hvol, pszRootPathBuf);
- ASSERT(IsRootPath(pszRootPathBuf));
- return;
- }
- #ifdef DEBUG
- /*
- ** DebugGetVolumeRootPath()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- **
- ** N.b., DebugGetVolumeRootPath() must be non-intrusive.
- */
- PUBLIC_CODE LPTSTR DebugGetVolumeRootPath(HVOLUME hvol, LPTSTR pszRootPathBuf)
- {
- ASSERT(IS_VALID_HANDLE(hvol, VOLUME));
- ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszRootPathBuf, STR, MAX_PATH_LEN));
- if (IS_FLAG_SET(((PVOLUME)hvol)->dwFlags, VOLUME_FL_ROOT_PATH_VALID))
- MyLStrCpyN(pszRootPathBuf, GetString(((PVOLUME)hvol)->hsRootPath), MAX_PATH_LEN);
- else
- GetUnavailableVolumeRootPath(((PVOLUME)hvol)->pli, pszRootPathBuf);
- ASSERT(IsRootPath(pszRootPathBuf));
- return(pszRootPathBuf);
- }
- /*
- ** GetVolumeCount()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PUBLIC_CODE ULONG GetVolumeCount(HVOLUMELIST hvl)
- {
- ASSERT(IS_VALID_HANDLE(hvl, VOLUMELIST));
- return(GetPtrCount(((PCVOLUMELIST)hvl)->hpa));
- }
- #endif
- /*
- ** DescribeVolume()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PUBLIC_CODE void DescribeVolume(HVOLUME hvol, PVOLUMEDESC pvoldesc)
- {
- PCVOID pcv;
- ASSERT(IS_VALID_HANDLE(hvol, VOLUME));
- ASSERT(IS_VALID_WRITE_PTR(pvoldesc, VOLUMEDESC));
- ASSERT(pvoldesc->ulSize == sizeof(*pvoldesc));
- pvoldesc->dwFlags = 0;
- if (GetLinkInfoData(((PCVOLUME)hvol)->pli, LIDT_VOLUME_SERIAL_NUMBER, &pcv))
- {
- pvoldesc->dwSerialNumber = *(PCDWORD)pcv;
- SET_FLAG(pvoldesc->dwFlags, VD_FL_SERIAL_NUMBER_VALID);
- }
- else
- pvoldesc->dwSerialNumber = 0;
- if (GetLinkInfoData(((PCVOLUME)hvol)->pli, LIDT_VOLUME_LABELW, &pcv) && pcv)
- {
- lstrcpy(pvoldesc->rgchVolumeLabel, pcv);
- SET_FLAG(pvoldesc->dwFlags, VD_FL_VOLUME_LABEL_VALID);
- }
- else if (GetLinkInfoData(((PCVOLUME)hvol)->pli, LIDT_VOLUME_LABEL, &pcv) && pcv)
- {
- MultiByteToWideChar(CP_ACP, 0, pcv, -1, pvoldesc->rgchVolumeLabel, MAX_PATH);
- SET_FLAG(pvoldesc->dwFlags, VD_FL_VOLUME_LABEL_VALID);
- }
- else
- {
- pvoldesc->rgchVolumeLabel[0] = TEXT('');
- }
- if (GetLinkInfoData(((PCVOLUME)hvol)->pli, LIDT_NET_RESOURCEW, &pcv) && pcv)
- {
- lstrcpy(pvoldesc->rgchNetResource, pcv);
- SET_FLAG(pvoldesc->dwFlags, VD_FL_NET_RESOURCE_VALID);
- }
- else if (GetLinkInfoData(((PCVOLUME)hvol)->pli, LIDT_NET_RESOURCE, &pcv) && pcv)
- {
- MultiByteToWideChar(CP_ACP, 0, pcv, -1, pvoldesc->rgchNetResource, MAX_PATH);
- SET_FLAG(pvoldesc->dwFlags, VD_FL_NET_RESOURCE_VALID);
- }
- else
- pvoldesc->rgchNetResource[0] = TEXT('');
- ASSERT(IS_VALID_STRUCT_PTR(pvoldesc, CVOLUMEDESC));
- return;
- }
- /*
- ** WriteVolumeList()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PUBLIC_CODE TWINRESULT WriteVolumeList(HCACHEDFILE hcf, HVOLUMELIST hvl)
- {
- TWINRESULT tr = TR_BRIEFCASE_WRITE_FAILED;
- DWORD dwcbDBVolumeListHeaderOffset;
- ASSERT(IS_VALID_HANDLE(hcf, CACHEDFILE));
- ASSERT(IS_VALID_HANDLE(hvl, VOLUMELIST));
- /* Save initial file position. */
- dwcbDBVolumeListHeaderOffset = GetCachedFilePointerPosition(hcf);
- if (dwcbDBVolumeListHeaderOffset != INVALID_SEEK_POSITION)
- {
- DBVOLUMELISTHEADER dbvlh;
- /* Leave space for volume list header. */
- ZeroMemory(&dbvlh, sizeof(dbvlh));
- if (WriteToCachedFile(hcf, (PCVOID)&dbvlh, sizeof(dbvlh), NULL))
- {
- ARRAYINDEX aicPtrs;
- ARRAYINDEX ai;
- UINT ucbMaxLinkInfoLen = 0;
- LONG lcVolumes = 0;
- tr = TR_SUCCESS;
- aicPtrs = GetPtrCount(((PCVOLUMELIST)hvl)->hpa);
- /* Write all volumes. */
- for (ai = 0; ai < aicPtrs; ai++)
- {
- PVOLUME pvol;
- pvol = GetPtr(((PCVOLUMELIST)hvl)->hpa, ai);
- /*
- * As a sanity check, don't save any volume with a lock count of 0.
- * A 0 lock count implies that the volume has not been referenced
- * since it was restored from the database, or something is broken.
- */
- if (pvol->ulcLock > 0)
- {
- tr = WriteVolume(hcf, pvol);
- if (tr == TR_SUCCESS)
- {
- ASSERT(lcVolumes < LONG_MAX);
- lcVolumes++;
- if (pvol->pli->ucbSize > ucbMaxLinkInfoLen)
- ucbMaxLinkInfoLen = pvol->pli->ucbSize;
- }
- else
- break;
- }
- else
- ERROR_OUT((TEXT("WriteVolumeList(): VOLUME has 0 lock count and will not be written.")));
- }
- /* Save volume list header. */
- if (tr == TR_SUCCESS)
- {
- dbvlh.lcVolumes = lcVolumes;
- dbvlh.ucbMaxLinkInfoLen = ucbMaxLinkInfoLen;
- tr = WriteDBSegmentHeader(hcf, dwcbDBVolumeListHeaderOffset,
- &dbvlh, sizeof(dbvlh));
- TRACE_OUT((TEXT("WriteVolumeList(): Wrote %ld volumes; maximum LinkInfo length %u bytes."),
- dbvlh.lcVolumes,
- dbvlh.ucbMaxLinkInfoLen));
- }
- }
- }
- return(tr);
- }
- /*
- ** ReadVolumeList()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PUBLIC_CODE TWINRESULT ReadVolumeList(HCACHEDFILE hcf, HVOLUMELIST hvl,
- PHHANDLETRANS phht)
- {
- TWINRESULT tr;
- DBVOLUMELISTHEADER dbvlh;
- DWORD dwcbRead;
- ASSERT(IS_VALID_HANDLE(hcf, CACHEDFILE));
- ASSERT(IS_VALID_HANDLE(hvl, VOLUMELIST));
- ASSERT(IS_VALID_WRITE_PTR(phht, HHANDLETRANS));
- if (ReadFromCachedFile(hcf, &dbvlh, sizeof(dbvlh), &dwcbRead) &&
- dwcbRead == sizeof(dbvlh))
- {
- HHANDLETRANS hht;
- tr = TR_OUT_OF_MEMORY;
- if (CreateHandleTranslator(dbvlh.lcVolumes, &hht))
- {
- PLINKINFO pliBuf;
- if (AllocateMemory(dbvlh.ucbMaxLinkInfoLen, &pliBuf))
- {
- LONG l;
- tr = TR_SUCCESS;
- TRACE_OUT((TEXT("ReadPathList(): Reading %ld volumes; maximum LinkInfo length %u bytes."),
- dbvlh.lcVolumes,
- dbvlh.ucbMaxLinkInfoLen));
- for (l = 0; l < dbvlh.lcVolumes; l++)
- {
- tr = ReadVolume(hcf, (PVOLUMELIST)hvl, pliBuf,
- dbvlh.ucbMaxLinkInfoLen, hht);
- if (tr != TR_SUCCESS)
- break;
- }
- if (tr == TR_SUCCESS)
- {
- PrepareForHandleTranslation(hht);
- *phht = hht;
- ASSERT(IS_VALID_HANDLE(hvl, VOLUMELIST));
- ASSERT(IS_VALID_HANDLE(*phht, HANDLETRANS));
- }
- else
- DestroyHandleTranslator(hht);
- FreeMemory(pliBuf);
- }
- }
- }
- else
- tr = TR_CORRUPT_BRIEFCASE;
- ASSERT(tr != TR_SUCCESS ||
- (IS_VALID_HANDLE(hvl, VOLUMELIST) &&
- IS_VALID_HANDLE(*phht, HANDLETRANS)));
- return(tr);
- }
- /*
- ** IsValidHVOLUME()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PUBLIC_CODE BOOL IsValidHVOLUME(HVOLUME hvol)
- {
- return(IS_VALID_STRUCT_PTR((PCVOLUME)hvol, CVOLUME));
- }
- #if defined(DEBUG) || defined(VSTF)
- /*
- ** IsValidHVOLUMELIST()
- **
- **
- **
- ** Arguments:
- **
- ** Returns:
- **
- ** Side Effects: none
- */
- PUBLIC_CODE BOOL IsValidHVOLUMELIST(HVOLUMELIST hvl)
- {
- return(IS_VALID_STRUCT_PTR((PCVOLUMELIST)hvl, CVOLUMELIST));
- }
- #endif