SVERROR OpenExclusive()

in host/common/win32/portablehelpersmajor.cpp [618:809]


SVERROR OpenExclusive(/* out */ ACE_HANDLE *pHandleVolume,
    /* out */ std::string &outs_VolGuidName,
    /* in */  char const *pch_VolumeName,
    /* in */  char const* mountPoint,
    /* in */  bool bUnmount,
    /* in */  bool bUnbufferIO
    )
{
    std::string sDestVolume;
    std::string sVol;
    SVERROR sve = SVS_OK;
    int flags = FILE_ATTRIBUTE_NORMAL; // FILE_ATTRIBUTE_NORMAL is required for CreateFile calls
    //__asm int 3;
    do
    {
        HRESULT hr = S_OK;
        HANDLE hDevice = INVALID_HANDLE_VALUE;
        DWORD BytesReturned = 0;

        std::string  sVolumeName = "";
        if (NULL != pch_VolumeName)
        {
            sVolumeName = pch_VolumeName;
            FormatVolumeNameToGuid(sVolumeName);
        }
        else
        {
            DebugPrintf(SV_LOG_ERROR, "OpenExclusive() did not succeed, Volume passed is null string.\n");
            sve = ACE_OS::last_error();
            return sve;
        }
        // Mount point volume names don't need to be translated
        sDestVolume = sVolumeName;

        // PR#10815: Long Path support
        hDevice = SVCreateFile(sDestVolume.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
            OPEN_EXISTING, flags, NULL);

        if (INVALID_HANDLE_VALUE == hDevice)
        {
            hr = HRESULT_FROM_WIN32(GetLastError());
            DebugPrintf(SV_LOG_DEBUG, "@ LINE %d in FILE %s \n", __LINE__, __FILE__);
            DebugPrintf(SV_LOG_DEBUG, "FAILED OpenExclusive(), CreateFile() For FSCTL_DISMOUNT_VOLUME %s hr = %08X\n", sDestVolume.c_str(), hr);
        }
        //Dismount the volume. Here, issue FSCTL_DISMOUNT_VOLUME to invalidate all open handles
        else if (!DeviceIoControl((HANDLE)hDevice, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, (LPDWORD)&BytesReturned,
            (LPOVERLAPPED)NULL))
        {
            // NOTE: on fail we don't set hr because we don't want to return fail from this call to DeviceIoControlstill 
            // want to try the rest of the code and only return an error if any of the remaining code fails, otherwise 
            // we want to return success.
            DebugPrintf(SV_LOG_DEBUG, "@ LINE %d in FILE %s \n", __LINE__, __FILE__);
            DebugPrintf(SV_LOG_DEBUG, "FSCTL_DISMOUNT_VOLUME did not succeed %d\n", GetLastError());
        }
        else {
            DebugPrintf(SV_LOG_DEBUG, "@ LINE %d in FILE %s \n", __LINE__, __FILE__);
            DebugPrintf(SV_LOG_DEBUG, "OpenExclusive FSCTL_DISMOUNT_VOLUME succeeded...\n");
        }

        if (INVALID_HANDLE_VALUE != hDevice)
        {
            CloseHandle(hDevice);
        }

        if (bUnmount) {

            outs_VolGuidName = sVolumeName;

            if (!IsVolumeNameInGuidFormat(mountPoint))
            {
                DebugPrintf(SV_LOG_DEBUG, "@ LINE %d in FILE %s \n", __LINE__, __FILE__);
                DebugPrintf(SV_LOG_DEBUG, "CALLING DeleteVolumeMountPoint for volume %s\n", mountPoint);

                string tempMountPoint = mountPoint;

                FormatVolumeNameForCxReporting(tempMountPoint);

                //if( 1 == strlen( mountPoint ) )
                if (1 == strlen(tempMountPoint.c_str()))
                {
                    tempMountPoint += ":\\";
                }
                else
                {
                    tempMountPoint += "\\";
                }

                //16211 - Add the guid and drive information to a persistent file.

                std::string guid = outs_VolGuidName;
                ExtractGuidFromVolumeName(guid);
                PersistDetachedVolumeEntry(tempMountPoint, guid);

                if (!DeleteVolumeMountPoint(tempMountPoint.c_str()))
                {
                    sve = GetLastError();
                    DebugPrintf(SV_LOG_DEBUG, "@ LINE %d in FILE %s \n", __LINE__, __FILE__);
                    DebugPrintf(SV_LOG_ERROR, "FAILED OpenExclusive(), DeleteVolumeMountPoint %s; err = %s\n", sDestVolume.c_str(), sve.toString());
                    //16211 - Remove the guid and drive information from a persistent file as DeleteVolumeMountPoint is not successful.
                    RemoveAttachedVolumeEntry(tempMountPoint, guid);
                    break;
                }
            }
            sVol = outs_VolGuidName;

        }
        else
        {
            sVol = sDestVolume;
        }

        if (bUnbufferIO){
            flags |= (FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH);
        }

        // PR#10815: Long Path support
        *pHandleVolume = SVCreateFile(sVol.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

        if (INVALID_HANDLE_VALUE == *pHandleVolume)
        {
            DebugPrintf(SV_LOG_DEBUG, "@ LINE %d in FILE %s \n", __LINE__, __FILE__);
            DebugPrintf(SV_LOG_DEBUG, "CreateFile() did not succeed %d\n", GetLastError());
            sve = GetLastError();

            DebugPrintf(SV_LOG_DEBUG, "@ LINE %d in FILE %s \n", __LINE__, __FILE__);
            if (bUnmount) {
                DebugPrintf(SV_LOG_ERROR, "OpenVolumeEx() did not succeed, Volume: %s; VolGuid: %s err = %s\n", pch_VolumeName, outs_VolGuidName.c_str(), sve.toString());
            }
            else {
                DebugPrintf(SV_LOG_ERROR, "OpenVolumeEx() did not succeed, Volume: %s err= %s\n", pch_VolumeName, sve.toString());
            }

            if (bUnmount) {


                if (!IsVolumeNameInGuidFormat(mountPoint))
                {
                    // Try to restore the volume back at it's previous drive letter
                    DebugPrintf(SV_LOG_DEBUG, "Restoring the volume %s to its original drive letter.\n", pch_VolumeName);

                    std::string fmtVolName = mountPoint;
                    ToStandardFileName(fmtVolName);
                    std::string::size_type len = fmtVolName.length();
                    if ('\\' != fmtVolName[len - 1]) {
                        fmtVolName += '\\';
                    }

                    std::string volGuid = outs_VolGuidName;
                    len = volGuid.length();
                    if ('\\' != volGuid[len - 1]) {
                        volGuid += '\\';
                    }

                    if (!SVSetVolumeMountPoint(fmtVolName, volGuid))
                    {
                        sve = GetLastError();
                        DebugPrintf(SV_LOG_ERROR, "OpenVolumeEx::SVSetVolumeMountPoint failed while mounting: %s at %s err = %s\n", volGuid.c_str(), fmtVolName.c_str(), sve.toString());
                        break;
                    }
                    //16211 - Remove the volume entry from the persisted file as the volume is reattached.
                    std::string guid = outs_VolGuidName;
                    ExtractGuidFromVolumeName(guid);
                    RemoveAttachedVolumeEntry(mountPoint, guid);
                }
            }
            break;
        }
        if (!DeviceIoControl((HANDLE)(*pHandleVolume), FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, (LPDWORD)&BytesReturned,
            (LPOVERLAPPED)NULL))
        {
            DebugPrintf(SV_LOG_DEBUG, "@ LINE %d in FILE %s \n", __LINE__, __FILE__);
            DebugPrintf(SV_LOG_DEBUG, "FSCTL_LOCK_VOLUME did not succeed %d\n", GetLastError());
            if (bUnmount)
            {
                if (!DeviceIoControl((HANDLE)(*pHandleVolume), FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, (LPDWORD)&BytesReturned,
                    (LPOVERLAPPED)NULL))
                {
                    DebugPrintf(SV_LOG_DEBUG, "@ LINE %d in FILE %s \n", __LINE__, __FILE__);
                    DebugPrintf(SV_LOG_DEBUG, "FSCTL_DISMOUNT_VOLUME did not succeed  for volume %s Error %d\n", mountPoint, GetLastError());
                }
                else {
                    DebugPrintf(SV_LOG_DEBUG, "@ LINE %d in FILE %s \n", __LINE__, __FILE__);
                    DebugPrintf(SV_LOG_DEBUG, "OpenExclusive FSCTL_DISMOUNT_VOLUME succeeded for volume %s\n", mountPoint);
                }
            }
        }

    } while (FALSE);

    return sve;
}