다음을 통해 공유


재해 복구에 VSS 자동화된 시스템 복구 사용

재해 복구(완전 복구라고도 함)를 수행하는 VSS 백업 및 복구 애플리케이션은 ASR(자동화된 시스템 복구) 기록기를 Windows PE(Windows 사전 설치 환경)와 함께 사용하여 부팅 가능한 시스템 상태의 중요한 볼륨 및 기타 구성 요소를 백업하고 복원할 수 있습니다. 백업 애플리케이션은 VSS 요청자로 구현됩니다.

참고 ASR을 사용하는 애플리케이션은 Windows PE에 라이선스를 부여해야 합니다.

Windows Server 2003 및 Windows XP: ASR은 VSS 기록기로 구현되지 않습니다.

ASR에서 사용할 수 있는 추적 도구에 대한 자세한 내용은 VSS ASR 애플리케이션에서 추적 도구 사용을 참조하세요.

문서 내용:

백업 단계 작업 개요

백업 시 요청자는 다음 단계를 수행합니다.

참고

달리 명시되지 않는 한 모든 단계가 필요합니다.

 

  1. CreateVssBackupComponents 함수를 호출하여 IVssBackupComponents 인터페이스의 instance 만들고 IVssBackupComponents::InitializeForBackup 메서드를 호출하여 백업을 관리하는 instance 초기화합니다.

  2. IVssBackupComponents::SetContext를 호출하여 섀도 복사 작업에 대한 컨텍스트를 설정합니다.

  3. IVssBackupComponents::SetBackupState를 호출하여 백업을 구성합니다. bBackupBootableSystemState 매개 변수를 true로 설정하여 백업에 부팅 가능한 시스템 상태가 포함되었음을 나타냅니다.

  4. ASR 기록기의 기록기 메타데이터 문서에서 각 구성 요소에 대해 IVssBackupComponents::AddComponent를 백업하고 호출할 중요한 구성 요소를 선택합니다.

  5. IVssBackupComponents::StartSnapshotSet을 호출하여 빈 새 섀도 복사본 집합을 만듭니다.

  6. IVssBackupComponents::GatherWriterMetadata를 호출하여 기록기와의 비동기 접촉을 시작합니다.

  7. IVssBackupComponents::GetWriterMetadata를 호출하여 ASR 작성기의 기록기 메타데이터 문서를 검색합니다. ASR 기록기에 대한 기록기 ID는 BE000CBE-11FE-4426-9C58-531AA6355FC4이고 작성기 이름 문자열은 "ASR 기록기"입니다.

  8. IVssExamineWriterMetadata::SaveAsXML을 호출하여 ASR 기록기의 기록기 메타데이터 문서의 복사본을 저장합니다.

  9. 섀도 복사본에 참여할 수 있는 각 볼륨에 대해 IVssBackupComponents::AddToSnapshotSet 을 호출하여 볼륨을 섀도 복사본 집합에 추가합니다.

  10. IVssBackupComponents::P repareForBackup을 호출하여 기록기에 백업 작업을 준비하도록 알립니다.

  11. IVssBackupComponents::GatherWriterStatusIVssBackupComponents::GetWriterStatus(또는 IVssBackupComponentsEx3::GetWriterStatus)를 호출하여 ASR 작성기의 상태 확인합니다.

  12. 이 시점에서 작성기가 CVssWriter::OnPrepareBackup 메서드에서 설정한 실패 메시지를 쿼리할 수 있습니다. 이러한 메시지를 보는 방법을 보여 주는 예제 코드는 IVssComponentEx::GetPrepareForBackupFailureMsg를 참조하세요.

  13. IVssBackupComponents::D oSnapshotSet을 호출하여 볼륨 섀도 복사본을 만듭니다.

  14. IVssBackupComponents::GatherWriterStatusIVssBackupComponents::GetWriterStatus를 호출하여 ASR 기록기의 상태 확인합니다.

  15. 데이터를 백업합니다.

  16. IVssBackupComponents::SetBackupSucceeded를 호출하여 백업 작업이 성공했는지 여부를 나타냅니다.

  17. IVssBackupComponents::BackupComplete를 호출하여 백업 작업이 완료되었음을 나타냅니다.

  18. IVssBackupComponents::GatherWriterStatusIVssBackupComponents::GetWriterStatus를 호출합니다. 기록기 세션 상태 메모리는 제한된 리소스이며 작성기는 결국 세션 상태를 다시 사용해야 합니다. 이 단계에서는 기록기 백업 세션 상태가 완료된 것으로 표시하고 VSS에 이 백업 세션 슬롯을 후속 백업 작업에서 다시 사용할 수 있음을 알 수 있습니다.

    참고

    이는 WINDOWS Server 2008 SP2(서비스 팩 2) 이하에서만 필요합니다.

     

  19. IVssBackupComponents::SaveAsXML을 호출하여 요청자의 백업 구성 요소 문서의 복사본을 저장합니다. 백업 구성 요소 문서의 정보는 요청자가 IVssBackupComponents::InitializeForRestore 메서드를 호출할 때 복원 시 사용됩니다.

백업할 중요한 구성 요소 선택

백업 초기화 단계에서 ASR 작성기는 기록기 메타데이터 문서에서 다음과 같은 유형의 구성 요소를 보고합니다.

  • 부팅, 시스템 및 Windows 복구 환경(Windows RE) 볼륨 및 현재 실행 중인 Windows Vista 또는 Windows Server 2008의 instance 연결된 Windows RE 파티션과 같은 중요한 볼륨 볼륨은 시스템 상태 정보가 포함된 경우 중요한 볼륨 입니다. 부팅 및 시스템 볼륨이 자동으로 포함됩니다. 요청자는 Active Directory를 포함하는 볼륨과 같이 기록기에서 보고한 시스템 중요 구성 요소가 포함된 모든 볼륨을 포함해야 합니다. 시스템에 중요한 구성 요소는 "백업을 위해 선택할 수 없음"으로 표시됩니다. VSS에서 "선택할 수 없음"은 "선택 사항이 아님"을 의미합니다. 따라서 요청자는 시스템 상태의 일부로 백업해야 합니다. 자세한 내용은 시스템 상태 백업 및 복원을 참조하세요. VSS_CF_NOT_SYSTEM_STATE 플래그가 설정된 구성 요소는 시스템에 중요하지 않습니다.

    참고

    ASR 구성 요소는 ASR 작성기에서 보고하는 시스템에 중요한 구성 요소입니다.

     

  • 디스크 컴퓨터의 모든 고정 디스크는 ASR의 구성 요소로 노출됩니다. 백업 중에 디스크가 제외되지 않은 경우 복원 중에 할당되며 다시 만들어 다시 포맷할 수 있습니다. 복원하는 동안 요청자는 IVssBackupComponents::SetRestoreOptions 메서드를 호출하여 백업 중에 제외된 디스크를 다시 만들 수 있습니다. 동적 디스크 팩에 있는 하나의 디스크를 선택한 경우 해당 팩의 다른 모든 디스크도 선택해야 합니다. 볼륨이 중요한 볼륨(즉, 시스템 상태 정보를 포함하는 볼륨)이므로 볼륨을 선택한 경우 해당 볼륨에 대한 익스텐트를 포함하는 모든 디스크도 선택해야 합니다. 볼륨의 범위를 찾으려면 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS 제어 코드를 사용합니다.

    참고

    백업하는 동안 요청자는 모든 고정 디스크를 포함해야 합니다. 요청자의 백업 집합이 포함된 디스크가 로컬 디스크인 경우 이 디스크를 포함해야 합니다. 복원하는 동안 요청자는 요청자의 백업 집합이 포함된 디스크를 제외하여 덮어쓰지 않도록 해야 합니다.

     

    클러스터링 환경에서 ASR은 클러스터의 공유 디스크 레이아웃을 다시 만들지 않습니다. 이러한 디스크는 Windows RE 운영 체제를 복원한 후 온라인으로 복원해야 합니다.

  • BCD(부팅 구성 데이터) 저장소. 이 구성 요소는 BCD 저장소를 포함하는 디렉터리의 경로를 지정합니다. 요청자는 이 구성 요소를 지정하고 BCD 저장소 디렉터리의 모든 파일을 백업해야 합니다. BCD 저장소에 대한 자세한 내용은 BCD 정보를 참조하세요.

    참고

    EFI(확장 펌웨어 인터페이스)를 사용하는 컴퓨터에서는 EFI ESP(시스템 파티션)가 항상 숨겨지고 볼륨 섀도 복사본에 포함될 수 없습니다. 요청자는 이 파티션의 콘텐츠를 백업해야 합니다. 이 파티션은 볼륨 섀도 복사본에 포함할 수 없으므로 섀도 복사본이 아닌 라이브 볼륨에서만 백업을 수행할 수 있습니다. EFI 및 ESP에 대한 자세한 내용은 가져오기 가이드를 참조하세요.

구성 요소 이름은 다음 형식을 사용합니다.

  • 디스크 구성 요소의 경우 형식은 입니다.

    <COMPONENT logicalPath="Disks" componentName="harddiskn" componentType="filegroup" />

    여기서 n 은 디스크 번호입니다. 디스크 번호만 기록됩니다. 디스크 번호를 얻으려면 IOCTL_STORAGE_GET_DEVICE_NUMBER 제어 코드를 사용합니다.

  • 볼륨 구성 요소의 경우 형식은 입니다.

    <COMPONENT logicalPath="Volumes" componentName="Volume{GUID}" componentType="filegroup" />

    여기서 GUID 는 볼륨 GUID입니다.

  • BCD 저장소 구성 요소의 경우 형식은 입니다.

    <COMPONENT logicalPath="BCD" componentName="BCD" componentType="filegroup" componentCaption = "부팅 BCD 저장소 및 부팅 관리자의 경로입니다... 이 디렉터리의 모든 파일을 백업해야 합니다...">

    시스템 파티션에 볼륨 GUID 이름이 있는 경우 이 구성 요소를 선택할 수 있습니다. 그렇지 않으면 선택할 수 없습니다.

    참고

    ASR은 다음과 같이 BCD 저장소 구성 요소의 파일 그룹에 파일을 추가합니다.

    • EFI 디스크의 경우 ASR은

      SystemPartitionPath\EFI\Microsoft\Boot\*.*

      여기서 SystemPartitionPath 는 시스템 파티션의 경로입니다.

    • GPT 디스크의 경우 ASR은

      SystemPartitionPath\Boot\*.*

      여기서 SystemPartitionPath 는 시스템 파티션의 경로입니다.

    • 시스템 파티션 경로는 다음 레지스트리 키에서 찾을 수 있습니다. HKEY_LOCAL_MACHINE\시스템\설정\SystemPartition

     

복원할 때 중요한 볼륨으로 표시된 모든 구성 요소를 복원해야 합니다. 하나 이상의 중요한 볼륨을 복원할 수 없는 경우 복원 작업이 실패합니다.

복원 시퀀스의 PreRestore 단계에서 백업 중에 제외되지 않은 디스크는 기본적으로 다시 만들어지고 다시 포맷됩니다. 그러나 다음 조건을 충족하는 경우 다시 만들거나 다시 포맷되지 않습니다.

  • 디스크 레이아웃이 그대로 유지되거나 추가 변경만 적용된 경우 기본 디스크가 다시 만들어지지 않습니다. 다음 조건이 true인 경우 디스크 레이아웃은 그대로 유지됩니다.

    • 디스크 서명, 디스크 스타일(GPT 또는 MBR), 논리 섹터 크기 및 볼륨 시작 오프셋은 변경되지 않습니다.
    • 볼륨 크기가 줄어들지 않습니다.
    • GPT 디스크의 경우 파티션 식별자는 변경되지 않습니다.
  • 디스크 레이아웃이 그대로 유지되거나 추가 변경만 적용된 경우 동적 디스크가 다시 만들어지지 않습니다. 동적 디스크가 그대로 유지되려면 기본 디스크에 대한 모든 조건을 충족해야 합니다. 또한 전체 디스크 팩의 볼륨 구조는 그대로 유지되어야 합니다. 디스크 팩의 볼륨 구조는 MBR 및 GPT 디스크 모두에 적용되는 다음 조건을 충족하는 경우 그대로 유지됩니다.

    • 복원하는 동안 실제 팩에서 사용할 수 있는 볼륨 수는 백업 중에 ASR 기록기 메타데이터에 지정된 볼륨 수보다 크거나 같아야 합니다.

    • 볼륨당 플렉스 수는 변경되지 않아야 합니다.

    • 멤버 수는 변경되지 않아야 합니다.

    • 실제 디스크 익스텐트 수는 ASR 기록기 메타데이터에 지정된 디스크 익스텐트 수보다 커야 합니다.

    • 추가 볼륨이 추가되거나 팩의 볼륨이 확장된 경우(예: 단순 볼륨에서 스팬 볼륨으로) 그대로 유지됩니다.

      참고

      단순 볼륨이 미러링된 경우 팩은 그대로 유지되지 않으며 복원 후 BCD 및 부팅 볼륨 상태가 일관되게 유지되도록 다시 만들어집니다. 볼륨이 삭제되면 팩이 다시 만들어집니다.

       

  • 동적 디스크 팩의 볼륨 구조가 그대로 유지되고 추가 변경만 적용된 경우 팩의 디스크가 다시 만들어지지 않습니다.

    Windows Vista: 동적 디스크는 항상 다시 만들어집니다. 이 동작은 Windows Server 2008 및 Windows Vista sp1(서비스 팩 1)에서 변경되었습니다.

복원 단계가 시작되기 전에 언제든지 요청자는 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersionASR\RestoreSession\ 레지스트리 키를 설정하여 디스크의 서식을 빠르게 지정해야 한다고 지정할 수 있습니다. 이 키 아래에는 데이터 형식이 REG_DWORD QuickFormat 이라는 값이 있습니다. 이 값이 없으면 만들어야 합니다. 빠른 서식 지정의 경우 QuickFormat 값의 데이터를 1로, 느린 서식 지정을 위해 0으로 설정합니다.

QuickFormat 값이 없으면 디스크의 형식이 느려집니다.

빠른 서식 지정은 느린 서식 지정(전체 서식이라고도 함)보다 훨씬 빠릅니다. 그러나 빠른 서식은 볼륨의 각 섹터를 확인하지 않습니다.

복원 단계 작업 개요

복원 시 요청자는 다음 단계를 수행합니다.

참고

달리 표시되지 않는 한 모든 단계가 필요합니다.

 

  1. CreateVssBackupComponents 함수를 호출하여 IVssBackupComponents 인터페이스의 instance 만들고 IVssBackupComponents::InitializeForRestore 메서드를 호출하여 요청자의 백업 구성 요소 문서를 instance 로드하여 복원할 instance 초기화합니다.

  2. [이 단계는 요청자가 하나 이상의 디스크에 대해 "IncludeDisk" 또는 "ExcludeDisk"를 지정했는지 여부를 변경해야 하는 경우에만 필요합니다.] IVssBackupComponents::SetRestoreOptions를 호출하여 ASR 기록기 구성 요소에 대한 복원 옵션을 설정합니다. ASR 작성기는 다음 옵션을 지원합니다. "IncludeDisk"를 사용하면 요청자가 백업 단계에서 선택되지 않은 경우에도 대상 시스템에 디스크를 복원하도록 고려할 수 있습니다. "ExcludeDisk"를 사용하면 요청자가 대상 시스템의 디스크가 다시 만들어지는 것을 방지할 수 있습니다. 중요한 볼륨이 포함된 디스크에 대해 "ExcludeDisk"를 지정하면 IVssBackupComponents::P reRestore 에 대한 후속 호출이 실패합니다.

    다음 예제에서는 SetRestoreOptions 를 사용하여 디스크 0 및 디스크 1이 다시 만들어지는 것을 방지하고 복원된 부팅 볼륨에 타사 드라이버를 삽입하는 방법을 보여 줍니다.

    Windows Server 2008, Windows Vista, Windows Server 2003 및 Windows XP: 타사 드라이버의 주입은 지원되지 않습니다.

    이 예제에서는 IVssBackupComponents 포인터(m_pBackupComponents)가 유효하다고 가정합니다.

        m_pBackupComponents->SetRestoreOptions(
            AsrWriterId,
            VSS_CT_FILEGROUP,
            NULL,
            TEXT("ASR"),
            TEXT("\"ExcludeDisk\"=\"0\", \"ExcludeDisk\"=\"1\" "),
            TEXT("\"InjectDrivers\"=\"1\" ")
            );
    

    지정된 볼륨에 대한 모든 디스크를 제외하려면 다음 "볼륨에 대한 모든 디스크 제외"를 참조하세요.

  3. IVssBackupComponents::P reRestore를 호출하여 ASR 작성기에 복원 작업을 준비하도록 알립니다. pHrResult 매개 변수에 반환된 상태 값이 VSS_S_ASYNC_PENDING 않을 때까지 필요한 만큼 IVssAsync::QueryStatus를 호출합니다.

  4. 데이터를 복원합니다. 복원 단계에서 ASR은 백업 단계에서 사용된 볼륨 GUID 경로와 일치하도록 각 볼륨에 대한 볼륨 GUID 경로(\\?\Volume{GUID})를 다시 구성합니다. 그러나 드라이브 문자는 유지되지 않습니다. 이 경우 복구 환경에서 자동으로 할당되는 드라이브 문자와 충돌이 발생하므로 유지되지 않습니다. 따라서 데이터를 복원할 때 요청자는 문자 드라이브가 아닌 볼륨 GUID 경로를 사용하여 볼륨에 액세스해야 합니다.

  5. 복원되거나 다시 포맷된 볼륨 집합을 나타내려면 HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ASR\RestoreSession 레지스트리 키를 설정합니다.

    이 키 아래에는 데이터 형식이 REG_MULTI_SZ 있는 RestoredVolumes 라는 값이 있습니다. 이 값이 없으면 만들어야 합니다. 이 값에서 요청자는 복원된 각 볼륨에 대한 볼륨 GUID 항목을 만들어야 합니다. 이 항목은 \\?\Volume{78618c8f-aefd-11da-a898-806e6f6e6963} 형식이어야 합니다. 완전 복구가 수행될 때마다 ASR은 RestoredVolumes 값을 ASR이 복원한 볼륨 집합으로 설정합니다. 요청자가 추가 볼륨을 복원한 경우 이 값을 요청자가 복원한 볼륨 집합 및 ASR이 복원한 볼륨 집합의 합합으로 설정해야 합니다. 요청자가 ASR을 사용하지 않은 경우 볼륨 목록을 바꿔야 합니다.

    또한 데이터 형식이 REG_SZ LastInstance 라는 값을 만들어야 합니다. 이 키에는 현재 복원 작업을 고유하게 식별하는 임의의 쿠키가 포함되어야 합니다. 이러한 쿠키는 UuidCreateUuidToString 함수를 사용하여 만들 수 있습니다. 완전 복구가 수행될 때마다 ASR은 이 레지스트리 값을 다시 설정하여 요청자 및 비 VSS 백업 애플리케이션에 복구가 발생했음을 알립니다.

  6. IVssBackupComponents::P ostRestore를 호출하여 복원 작업의 끝을 나타냅니다. pHrResult 매개 변수에 반환된 상태 값이 VSS_S_ASYNC_PENDING 않을 때까지 필요한 만큼 IVssAsync::QueryStatus를 호출합니다.

복원 단계에서 ASR은 컴퓨터를 이전 상태로 복원하기 위해 파티션을 만들거나 제거할 수 있습니다. 요청자는 백업 단계에서 복원 단계로 디스크 번호를 매핑하려고 시도해서는 안 됩니다.

복원 시 요청자는 요청자의 백업 집합이 포함된 디스크를 제외해야 합니다. 그렇지 않으면 복원 작업을 통해 백업 집합을 덮어쓸 수 있습니다.

복원 시 백업 중에 구성 요소로 선택되지 않았거나 복원 중에 "ExcludeDisk" 옵션을 사용하여 IVssBackupComponents::SetRestoreOptions 를 호출하여 명시적으로 제외되는 경우 디스크가 제외됩니다.

WinPE 재해 복구 중에 ASR 기록기 기능이 있지만 다른 작성기를 사용할 수 없으며 VSS 서비스가 실행되고 있지 않다는 점에 유의해야 합니다. WinPE 재해 복구가 완료되면 컴퓨터가 다시 시작되고 Windows 운영 체제가 정상적으로 실행되고 VSS 서비스를 시작할 수 있으며 요청자는 ASR 기록기 이외의 작성기 참여가 필요한 추가 복원 작업을 수행할 수 있습니다.

복원 세션 중에 백업 애플리케이션이 볼륨 고유 ID가 변경되지 않은 것을 감지하여 백업 시점의 모든 볼륨이 WinPE에 존재하고 그대로 유지되는 경우 백업 애플리케이션은 ASR을 포함하지 않고 볼륨의 콘텐츠만 복원할 수 있습니다. 이 경우 백업 애플리케이션은 복원된 운영 체제에서 다음 레지스트리 키를 설정하여 컴퓨터가 복원되었음을 나타내야 합니다. HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ASR\RestoreSession

이 키 아래에서 값 이름에 LastInstance 를 지정하고 값 형식에 REG_SZ 값 데이터에 대해 임의의 쿠키(예: UuidCreate 함수에서 만든 GUID)를 지정합니다.

복원 세션 중에 백업 애플리케이션이 하나 이상의 볼륨이 변경되거나 누락된 것을 감지하는 경우 백업 애플리케이션은 ASR을 사용하여 복원을 수행해야 합니다. ASR은 백업 당시와 똑같은 방식으로 볼륨을 다시 만들고 RestoreSession 레지스트리 키를 설정합니다.

볼륨에 대한 모든 디스크 제외

다음 예제에서는 지정된 볼륨에 대한 모든 디스크를 제외하는 방법을 보여 줍니다.

HRESULT BuildRestoreOptionString
(
    const WCHAR             *pwszVolumeNamePath,
    CMyString               *pstrExclusionList
)
{
    HANDLE                  hVolume           = INVALID_HANDLE_VALUE;
    DWORD                   cbSize            = 0;
    VOLUME_DISK_EXTENTS     * pExtents        = NULL;
    DISK_EXTENT             * pExtent         = NULL;
    ULONG                   i                 = 0;
    BOOL                    fIoRet            = FALSE;
    WCHAR                   wszDest[MAX_PATH] = L"";
    CMyString               strVolumeName;
    CMyString               strRestoreOption;

    // Open a handle to the volume device.
    strVolumeName.Set( pwszVolumeNamePath );
    // If the volume name contains a trailing backslash, remove it.
    strVolumeName.UnTrailing( L'\\' );
    hVolume = ::CreateFile(strVolumeName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, 0);
    // Check whether the call to CreateFile succeeded.

    // Get the list of disks used by this volume.
    cbSize = sizeof(VOLUME_DISK_EXTENTS);
    pExtents = (VOLUME_DISK_EXTENTS *)::CoTaskMemAlloc(cbSize);

    ::ZeroMemory(pExtents, cbSize);

    fIoRet = ::DeviceIoControl(hVolume, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, pExtents, cbSize, &cbSize, 0);
    if ( !fIoRet && GetLastError() == ERROR_MORE_DATA )
    {
        // Allocate more memory.
        cbSize = FIELD_OFFSET(VOLUME_DISK_EXTENTS, Extents) + pExtents->NumberOfDiskExtents * sizeof(DISK_EXTENT);
        ::CoTaskMemFree(pExtents);
        pExtents = NULL;

        pExtents = (VOLUME_DISK_EXTENTS *) ::CoTaskMemAlloc(cbSize);
        // Check whether CoTaskMemAlloc returned an out-of-memory error.
        ::ZeroMemory(pExtents, cbSize);

        // Now the buffer should be big enough.
        ::DeviceIoControl(hVolume, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, pExtents, cbSize, &cbSize, 0);
        // Check whether the IOCTL succeeded.
    }
    // Check for errors; note that the IOCTL can fail for a reason other than insufficient memory.

    // For each disk, mark it to be excluded in the Restore Option string.
    for (i = 0; i < pExtents->NumberOfDiskExtents; i++)
    {
        pExtent = &pExtents->Extents[i];

        *wszDest = L'\0';
        StringCchPrintf(wszDest, MAX_PATH, L"\"ExcludeDisk\"=\"%d\", ", pExtent->DiskNumber); // check errors

        strRestoreOption.Append(wszDest);
        // Check for an out-of-memory error.
    }

    // Remove the trailing comma.
    strRestoreOption.TrimRight();
    strRestoreOption.UnTrailing(',');

    // Set the output parameter.
    strRestoreOption.Transfer( pstrExclusionList );

Exit:
    if( pExtents )
    {
        ::CoTaskMemFree(pExtents);
        pExtents = NULL;
    }

    if( hVolume != INVALID_HANDLE_VALUE )
    {
        ::CloseHandle(hVolume);
        hVolume = INVALID_HANDLE_VALUE;
    }

    return ( hr );
}