This method is deprecated.
Updates the header of an FESF encrypted file, extending the file to accommodate a larger Policy Header Data size.
HRESULT
UpdateHeaderWithExtension(
[in] REFGUID Volume,
[in] BSTR Path,
[in] VARIANT * NewHeader
)
Volume [in]
A reference to a GUID that identifies the volume on which the file resides. See Remarks for further information.
Path [in]
A string containing the path of a file to update. This may be a fully qualified path or a path relative to the Volume argument. Refer to the Remarks section.
NewHeader [in]
A pointer to a VARIANT that describes a CComSafeArray of bytes holding the new header that is to be substituted for the existing header on the file.
S_OK on success
Other standard HRESULT values may be returned indicating the failure of the operation.
Important: This method is deprecated and is pending removal from FESF. Do not use it. Convert existing code that uses it as soon as possible. Use the equivalent function provided by the FesfUtil2 Library.
Important Note:
Prior to FESF V1.10 a potential
security vulnerability exists in the implementation of this function, in which a
file’s security settings (such as owner and SACL) are not always correctly
propagated from the existing file to the file with the extended header. We have
implemented fixes for this problem in FESF V1.10 and later.
This operation requires exclusive access to the file.
A Client Solution component calls UpdateHeaderWithExtension to replace the existing Policy Header Data in an FESF encrypted file with new Policy Header Data, extending the file to accommodate the new Header Data. The old Policy Header Data is discarded.
If Volume is equal to FE_SHADOW_VOLUME_GUID (indicating that Path refers to a file on a shadow volume), then Path is interpreted as either as a fully qualified path, suitable for direct evaluation or as the concatenation of the shadow device name and path.
If Volume is equal to GUID_NULL (indicating that no GUID is provided) then the path is inspected and treated as though either FE_SHADOW_VOLUME_GUID or FE_NETWORK_GUID was provided.
Otherwise, Volume represents a local volume and Path is interpreted as relative to that volume.
If the size of the Header Data to be written is less than or equal to the maximum Header Data length returned in the MaxHeaderLength parameter of the FesfDS->ReadHeader function, it is significantly less overhead for the Client Solution component to call FesfDS->UpdateHeader than to call FesfDS->UpdateHeaderWithExtension.
The new Header Data can actually be any size. While the name of this function implies that the new Header Data will be larger than the existing Header Data (with the file being extended accordingly), the new Header Data may actually be smaller than the existing Header Data. In this case, the file will be shrunk accordingly.
If the Client Solution component needs to write a header that’s larger than MaxHeaderLength bytes, it must use the FesfDS->UpdateHeaderWithExtension method.
Solutions should note that, while UpdateHeaderWithExtension makes a reasonable attempt to ensure correctness, the function is not inherently transactionally safe. Thus, the file being updated could become corrupted if an unrecoverable error occurs during the header update or file extension process. If absolute safety is required, the Client Solution component should make a private backup copy of the file being updated, call UpdateHeaderWithExtension, and when the update succeeds delete the backup copy.
Internally, UpdateHeaderWithExtension creates a new file with the newly sized header and then moves the encrypted data from the Original File to the new file. Starting with FESF V1.10, the original file’s characteristics are propagated to the new file using the Win32 function ReplaceFile. After ReplaceFile completes successfully, UpdateHeaderWithExtension propagates any explicitly set file owner, group, DACL, SACL, Label Security, Attribute Security, and Scope Security settings from the original file to the new file.
Also starting in FESF V1.10, UpdateHeaderWithExtension makes an internal backup copy of the original file (without the extended header). If the function believes that the original’s file’s characteristics have been correctly propagated, the backup copy of the original file is deleted. If a problem occurs during processing (such as, for example, the call to ReplaceFile fails or the security attributes of the original file cannot be fully propagated to the new file) UpdateHeaderWithExtension will attempt to delete the updated file and restore the original file from the backup (and an error is returned). In the unlikely scenario that the original file cannot be restored from the backup, UpdateHeaderWithExtension will return an error and will retain the backup file.
The name of this backup file is the same as that of the original file, but with the prefix “FESF_BACKUP_”; Thus, if the fully qualified path for the original file is C:\fred\bob.txt the name of the backup file will be “c:\fred\FESF_BACKUP_bob.txt” – In this version of FESF, the name of the backup file cannot be changed.
For absolute safety, solutions that call UpdateHeaderWithExtension should make their own backup copies of the original file before calling UpdateHeaderWithExtension. However, in all cases, Client Solutions should carefully check error return values when calling UpdateHeaderWithExtension, and when an error is returned should check to see if the backup file (named as described above) has been retained. If it has, Client Solution components should assume that the new file (if it exists, it will have the original file’s name) is in some way not valid and take measures to restore the original file from the backup.
Also, starting in FESF V1.10, some situations (such as in certain circumstances of accessing files over the network) UpdateHeaderWithExtension may fail, returning an error, where in past FESF versions it did not. This is not a bug, but rather a correction of previous behavior in which file characteristics were not always correctly propagated.
Please note that extending a file’s header over the network (with a file located on a server) is particularly tricky, due to potential that the privileges being used for file access on the server are different from those held by the calling application on the client. Therefore, as a best practice, we recommend Client Solutions restrict their use of this function to local files.
The calling COM client must have SE_RESTORE_NAME, SE_SECURITY_NAME, and SE_TAKE_OWNERSHIP_NAME privileges available. If the file is accessed over the network, the caller must also have these privileges available on the server where the file is located.
Client Solution developers can gain insight into errors, and the error detection and recovery behavior of the UpdateHeaderWithExtension method, by reviewing the source code as well as the ATLTRACE output in the debug build of the FesfDs Service during error situations.
//
// Now write the header back to the safe array so that we can
// write it out to the file
//
for (auto index = (ULONG)0; index < newLength; index++)
{
headerAsSafeArray.SetAt(index, newHeader[index]);
}
if (action == HeaderUpdateSeqNumber || action == HeaderUpdateSizeRandom ||
action == HeaderUpdateSizeIncreasing)
{
//
// If the header is larger than the maximum allowed size,
// we have to call a different function to do it
//
if (newLength <= maxHeaderLength)
{
hr = spDS->UpdateHeader(const_cast<GUID *>(&GUID_NULL),
GetUniversalFilePath(file),
&variantHeader);
}
else
{
hr = spDS->UpdateHeaderWithExtension(
const_cast<GUID *>(&GUID_NULL),
GetUniversalFilePath(file),
&variantHeader);
}
if (!SUCCEEDED(hr))
{
wprintf(L"%-30ws <E> UpdateHeader failed (hr=0x%x)\n", findData.cFileName, hr);
break;
}
The above snippet comes from the SampUpdateHeader example that’s provided as part of the UM_SAMPLE Solution. Refer to that example for more details.
FesfDS->UpdateHeader
Software version |
FESF V1 (and later) |
DLL/Server |
FesfDs.exe |
Supported FESF State |
FESF Online State or FESF Offline State (as long as FesfDs in accessible via COM). |
Type Library |
\UM_FESF\UMLIB\FESFDS.TLB |
IID |
IFesfDs (please use the defintion from the Type Library) |
CLSID |
FesfDs (please use the definition from the Type Library) |