/*++

Copyright (C) 2000 Microsoft Corporation

Module Name:

    ftcomp.cpp

Abstract:

    This compatibility dll is used by winnt32.exe in order to decide 
    whether the installation process should be aborted because of FT 
    sets present in the system.

Author:

    Cristian Teodorescu   (cristiat)  6-July-2000
    
Environment:

    compatibility dll for winnt32.exe

Notes:

Revision History:

--*/

#include <initguid.h>
#include <winnt32.h>
#include <ntddft.h>
#include <ntddft2.h>

#include "ftcomp.h"
#include "ftcomprc.h"


HINSTANCE g_hinst;
WCHAR g_FTCOMP50_ERROR_HTML_FILE[] = L"compdata\\ftcomp1.htm";
WCHAR g_FTCOMP50_ERROR_TEXT_FILE[] = L"compdata\\ftcomp1.txt";
WCHAR g_FTCOMP40_ERROR_HTML_FILE[] = L"compdata\\ftcomp2.htm";
WCHAR g_FTCOMP40_ERROR_TEXT_FILE[] = L"compdata\\ftcomp2.txt";
WCHAR g_FTCOMP40_WARNING_HTML_FILE[] = L"compdata\\ftcomp3.htm";
WCHAR g_FTCOMP40_WARNING_TEXT_FILE[] = L"compdata\\ftcomp3.txt";

extern "C"
BOOL WINAPI 
DllMain(
    HINSTANCE   hInstance,
    DWORD       dwReasonForCall,
    LPVOID      lpReserved
    )
{
    BOOL    status = TRUE;
    
    switch( dwReasonForCall )
    {
    case DLL_PROCESS_ATTACH:
        g_hinst = hInstance;
	    DisableThreadLibraryCalls(hInstance);       
        break;

    case DLL_PROCESS_DETACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
        break;
    }

    return status;
}

BOOL WINAPI 
FtCompatibilityCheckError(
    IN PCOMPAIBILITYCALLBACK    CompatibilityCallback,
    IN LPVOID                   Context
    )

/*++

Routine Description:

    This routine is called by winnt32.exe in order to decide whether 
    the installation process should be aborted because of FT sets present 
    in a Windows 2000 system or later. It also aborts the installation on
    NT 4.0 systems if the boot/system/pagefile volumes are FT sets

Arguments:

    CompatibilityCallback   - Supplies the winnt32 callback

    Context                 - Supplies the compatibility context

Return Value:

    FALSE   if the installation can continue
    TRUE    if the installation must be aborted

--*/

{   
    OSVERSIONINFO       osvi;
    BOOL                ftPresent;
    BOOL                result;
    COMPATIBILITY_ENTRY ce;
    WCHAR               description[100];
    
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    if (!GetVersionEx(&osvi)) {
        return FALSE;
    }

    if (osvi.dwPlatformId != VER_PLATFORM_WIN32_NT ||
        osvi.dwMajorVersion < 4) {
        return FALSE;
    }

    if (osvi.dwMajorVersion == 4) {

        //
        // On NT 4.0 look for boot/system/pagefile FT sets
        //

        result = FtBootSystemPagefilePresent40(&ftPresent);

    } else {

        //
        //  On Windows 2000 or later look for any FT sets.
        //

        result = FtPresent50(&ftPresent);
    }
    
    if (result && !ftPresent) {

        // 
        // The setup can continue.
        //
        
        return FALSE;
    }    
    
    //
    // FT sets are present in the system or a fatal error occured. 
    // Queue the incompatibility error
    //
    
    ZeroMemory((PVOID) &ce, sizeof(COMPATIBILITY_ENTRY));
    if (osvi.dwMajorVersion == 4) {
        if (!LoadString(g_hinst, FTCOMP_STR_ERROR40_DESCRIPTION, description, 100)) {
            description[0] = 0;
        }
        ce.HtmlName = g_FTCOMP40_ERROR_HTML_FILE;
        ce.TextName = g_FTCOMP40_ERROR_TEXT_FILE; 
    } else {
        if (!LoadString(g_hinst, FTCOMP_STR_ERROR50_DESCRIPTION, description, 100)) {
            description[0] = 0;
        }
        ce.HtmlName = g_FTCOMP50_ERROR_HTML_FILE;
        ce.TextName = g_FTCOMP50_ERROR_TEXT_FILE; 
    }
    ce.Description = description;
    ce.RegKeyName = NULL;
    ce.RegValName = NULL;
    ce.RegValDataSize = 0;
    ce.RegValData = NULL;
    ce.SaveValue = NULL;
    ce.Flags = 0;
    CompatibilityCallback(&ce, Context);

    return TRUE;
}

BOOL WINAPI 
FtCompatibilityCheckWarning(
    IN PCOMPAIBILITYCALLBACK    CompatibilityCallback,
    IN LPVOID                   Context
    )

/*++

Routine Description:

    This routine is called by winnt32.exe in order to decide whether the user
    should be warned about the presence of FT sets in a Windows NT 4.0 system
    
Arguments:

    CompatibilityCallback   - Supplies the winnt32 callback

    Context                 - Supplies the compatibility context

Return Value:

    FALSE   if the installation can continue
    TRUE    if the installation must be aborted

--*/

{   
    OSVERSIONINFO       osvi;
    BOOL                ftPresent;
    BOOL                result;
    COMPATIBILITY_ENTRY ce;
    WCHAR               description[100];
    
    //
    //  This function is supposed to work only on Windows NT 4.0
    //
    
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    if (!GetVersionEx(&osvi)) {
        return FALSE;
    }

    if (osvi.dwPlatformId != VER_PLATFORM_WIN32_NT ||
        osvi.dwMajorVersion != 4) {
        return FALSE;
    }
        
    result = FtPresent40(&ftPresent);
    if (result && !ftPresent) {

        // 
        // No FT sets are present in the system. The setup can continue.
        //
        
        return FALSE;
    }

    //
    // FT sets are present in the system or a fatal error occured. 
    // Queue the incompatibility warning
    //
    
    if (!LoadString(g_hinst, FTCOMP_STR_WARNING40_DESCRIPTION, description, 100)) {
        description[0] = 0;
    }

    ZeroMemory((PVOID) &ce, sizeof(COMPATIBILITY_ENTRY));
    ce.Description = description;
    ce.HtmlName = g_FTCOMP40_WARNING_HTML_FILE;
    ce.TextName = g_FTCOMP40_WARNING_TEXT_FILE; 
    ce.RegKeyName = NULL;
    ce.RegValName = NULL;
    ce.RegValDataSize = 0;
    ce.RegValData = NULL;
    ce.SaveValue = NULL;
    ce.Flags = 0;
    CompatibilityCallback(&ce, Context);

    return TRUE;
}

BOOL
FtPresent50(
    PBOOL   FtPresent
    )

/*++

Routine Description:

    This routine looks for FT volumes on a Window 2000 or later
    system.

Arguments:

    FtPresent   - is set to true if FT sets are detected in the system

Return Value:

    TRUE    if the function is successful
    FALSE   if some fatal error occured

--*/

{
    HANDLE                              handle;
    FT_ENUMERATE_LOGICAL_DISKS_OUTPUT   output;
    BOOL                                result;
    DWORD                               bytes;
    
    *FtPresent = FALSE;

    handle = CreateFile(L"\\\\.\\FtControl", GENERIC_READ | GENERIC_WRITE,
                        FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
                        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
                        INVALID_HANDLE_VALUE);
    if (handle == INVALID_HANDLE_VALUE) {
        return FALSE;
    }
    
    memset(&output, 0, sizeof(output));
    result = DeviceIoControl(handle, FT_ENUMERATE_LOGICAL_DISKS, NULL, 0, 
                             &output, sizeof(output), &bytes, NULL);
    CloseHandle(handle);

    if (!result && GetLastError() != ERROR_MORE_DATA) {
        return FALSE;
    }
        
    if (output.NumberOfRootLogicalDisks > 0) {
        *FtPresent = TRUE;
    }

    return TRUE;
}

BOOL
FtPresent40(
    PBOOL   FtPresent
    )

/*++

Routine Description:

    This routine looks for NTFT partitions on a Window NT 4.0 system

Arguments:

    FtPresent   - is set to true if FT sets are detected in the system

Return Value:

    TRUE    if the function is successful
    FALSE   if some fatal error occured

--*/

{
    HKEY                hkey;
    DWORD               registrySize;
    PDISK_CONFIG_HEADER registry;
    PDISK_REGISTRY      diskRegistry;
    ULONG               i;
    WCHAR               devicePath[50];    
    NTSTATUS            status;
    HANDLE              hdev;    

    *FtPresent = FALSE;

    //
    //  Get the ftdisk database from registry.
    //  Key:    HKLM\System\Disk
    //  Value:  Information
    //

    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"System\\Disk", 0, KEY_QUERY_VALUE, &hkey) !=
        ERROR_SUCCESS) {
        return TRUE;
    }

    if (RegQueryValueEx(hkey, L"Information", NULL, NULL, NULL, &registrySize) != 
        ERROR_SUCCESS) {
        RegCloseKey(hkey);
        return TRUE;
    }
  
    registry = (PDISK_CONFIG_HEADER) LocalAlloc(0, registrySize);
    if (!registry) {
        RegCloseKey(hkey);
        return FALSE;
    }
    
    if (RegQueryValueEx(hkey, L"Information", NULL, NULL, (LPBYTE) registry, &registrySize) != 
        ERROR_SUCCESS) {
        LocalFree(registry);
        RegCloseKey(hkey);
        return TRUE;
    }

    RegCloseKey(hkey);

    //
    //  If no FT volume info is present in the registry database we are done
    //

    if (registry->FtInformationSize == 0) {
        LocalFree(registry);
        return TRUE;
    }

    diskRegistry = (PDISK_REGISTRY)
                   ((PUCHAR) registry + registry->DiskInformationOffset);
  
    
    //
    //  Enumerate all disks present in the system by opening \Device\HarddiskX\Partition0
    //  in sequence starting with disk 0. Stop when getting STATUS_OBJECT_PATH_NOT_FOUND
    //
    //

    for (i = 0;; i++) {
        
        //
        //  Open the device
        //
        
        swprintf(devicePath, L"\\Device\\Harddisk%lu\\Partition0", i);
        status = OpenDevice(devicePath, &hdev);
        
        if (status == STATUS_OBJECT_PATH_NOT_FOUND) {
            break;
        }

        if (!NT_SUCCESS(status) || hdev == NULL ||
            hdev == INVALID_HANDLE_VALUE) {
            // inaccessible device
            continue;
        }

        //
        //  Look for FT partitions on disk
        //
        
        if (!FtPresentOnDisk40(hdev, diskRegistry, FtPresent)) {
            CloseHandle(hdev);
            return FALSE;
        }
                
        CloseHandle(hdev);

        if (*FtPresent) {
            break;
        }
    }

    LocalFree(registry);
    return TRUE;
}

BOOL
FtBootSystemPagefilePresent40(
    PBOOL   FtPresent
    )

/*++

Routine Description:

    This routine looks for FT sets that are boot/system/pagefile volumes
    on a NT 4.0 system

Arguments:

    FtPresent   - is set to true if boot/system/pagefile FT sets are detected 
    in the system

Return Value:

    TRUE    if the function is successful
    FALSE   if some fatal error occured

--*/

{
    HKEY                            hkey;
    DWORD                           registrySize;
    PDISK_CONFIG_HEADER             registry;
    PDISK_REGISTRY                  diskRegistry;
    WCHAR                           buffer[MAX_PATH + 1];
    NTSTATUS                        status;
    UCHAR                           genericBuffer[0x10000];
    PSYSTEM_PAGEFILE_INFORMATION    pageFileInfo;
    PWCHAR                          p;
    WCHAR                           bootDL = 0, systemDL = 0;
    WCHAR                           dl;

    *FtPresent = FALSE;

    //
    //  Get the ftdisk database from registry.
    //  Key:    HKLM\System\Disk
    //  Value:  Information
    //

    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"System\\Disk", 0, KEY_QUERY_VALUE, &hkey) !=
        ERROR_SUCCESS) {
        return TRUE;
    }

    if (RegQueryValueEx(hkey, L"Information", NULL, NULL, NULL, &registrySize) != 
        ERROR_SUCCESS) {
        RegCloseKey(hkey);
        return TRUE;
    }
  
    registry = (PDISK_CONFIG_HEADER) LocalAlloc(0, registrySize);
    if (!registry) {
        RegCloseKey(hkey);
        return FALSE;
    }
    
    if (RegQueryValueEx(hkey, L"Information", NULL, NULL, (LPBYTE) registry, &registrySize) != 
        ERROR_SUCCESS) {
        LocalFree(registry);
        RegCloseKey(hkey);
        return TRUE;
    }

    RegCloseKey(hkey);

    //
    //  If no FT volume info is present in the registry database we are done
    //

    if (registry->FtInformationSize == 0) {
        LocalFree(registry);
        return TRUE;
    }

    diskRegistry = (PDISK_REGISTRY)
                   ((PUCHAR) registry + registry->DiskInformationOffset);


    //
    //  Check the boot volume
    //
    
    if (!GetSystemDirectory(buffer, MAX_PATH)) {
        goto system;
    }

    if (buffer[1] != L':') {
        goto system;
    }
    
    bootDL = (WCHAR) tolower(buffer[0]);
    if (IsFtSet40(bootDL, diskRegistry)) {
        *FtPresent = TRUE;
        goto exit;
    }

system:
    
    //
    // Check the system volume
    //
    
    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"System\\Setup", 0, KEY_QUERY_VALUE, &hkey) !=
        ERROR_SUCCESS) {
        goto paging;
    }

    registrySize = MAX_PATH * sizeof(WCHAR);
    if (RegQueryValueEx(hkey, L"SystemPartition", NULL, NULL, (LPBYTE) buffer, &registrySize) != 
        ERROR_SUCCESS) {
        RegCloseKey(hkey);
        goto paging;
    }

    RegCloseKey(hkey);
        
    if (!GetDeviceDriveLetter(buffer, &systemDL)) {
        goto paging;
    }

    systemDL = (WCHAR) tolower(systemDL);
    if (systemDL == bootDL) {
        // already checked this drive letter
        goto paging;
    }
    
    if (IsFtSet40(systemDL, diskRegistry)) {
        *FtPresent = TRUE;
        goto exit;
    }    
    
paging:
    
    //
    //  Check the paging volumes
    //

    if (!NT_SUCCESS(NtQuerySystemInformation(
                            SystemPageFileInformation,
                            genericBuffer, sizeof(genericBuffer),
                            NULL))) {
        goto exit;
    }

    pageFileInfo = (PSYSTEM_PAGEFILE_INFORMATION) genericBuffer;

    while (TRUE) {

        //
        // Since the format of the pagefile name generally
        // looks something like "\DosDevices\x:\pagefile.sys",
        // just use the first character before the column
        // and assume that's the drive letter.
        //
            
        for (p = pageFileInfo->PageFileName.Buffer; 
             p < pageFileInfo->PageFileName.Buffer + pageFileInfo->PageFileName.Length 
             && *p != L':'; p++);
            
        if (p < pageFileInfo->PageFileName.Buffer + pageFileInfo->PageFileName.Length &&
            p > pageFileInfo->PageFileName.Buffer) {

            p--;
            dl = (WCHAR) tolower(*p);
            if (dl >= L'a' && dl <= L'z') {

                //
                //  Found the drive letter of a paging volume
                //

                if (dl != bootDL && dl != systemDL) {
                    if (IsFtSet40(dl, diskRegistry)) {
                        *FtPresent = TRUE;
                        goto exit;
                    }
                }
            }
        }

        if (!pageFileInfo->NextEntryOffset) {
            break;
        }

        pageFileInfo = (PSYSTEM_PAGEFILE_INFORMATION)((PCHAR) pageFileInfo + 
                                                      pageFileInfo->NextEntryOffset);
    }

exit:
    
    LocalFree(registry);
    return TRUE;
}

NTSTATUS 
OpenDevice(
    PWSTR   DeviceName,
    PHANDLE Handle
    )

/*++

Routine Description:

    This routine opens a device for read

Arguments:

    DeviceName  - supplies the device name

    Handle      - returns a handle to the open device

Return Value:

    NTSTATUS

--*/

{
    OBJECT_ATTRIBUTES   oa;
    NTSTATUS            status;
    IO_STATUS_BLOCK     statusBlock;
    UNICODE_STRING      unicodeName;
    int                 i;
    
    status = RtlCreateUnicodeString(&unicodeName, DeviceName);
    if (!NT_SUCCESS(status)) {
        return status;
    }

    memset(&statusBlock, 0, sizeof(IO_STATUS_BLOCK));
    memset(&oa, 0, sizeof(OBJECT_ATTRIBUTES));
    oa.Length = sizeof(OBJECT_ATTRIBUTES);
    oa.ObjectName = &unicodeName;
    oa.Attributes = OBJ_CASE_INSENSITIVE;

    //
    // If a sharing violation occurs, retry it for
    // max. 10 seconds
    //

    for (i = 0; i < 5; i++) {
        status = NtOpenFile(Handle, SYNCHRONIZE | GENERIC_READ,
                            &oa, &statusBlock,
                            FILE_SHARE_READ | FILE_SHARE_WRITE,
                            FILE_SYNCHRONOUS_IO_ALERT);
        if (status == STATUS_SHARING_VIOLATION) {
            Sleep(2000);
        } else {
            break;
        }
    }

    RtlFreeUnicodeString(&unicodeName);
    return status;
}

PDISK_PARTITION
FindPartitionInRegistry40(
    PDISK_REGISTRY  DiskRegistry,
    ULONG           Signature,
    LONGLONG        Offset
    )

/*++

Routine Description:

    This routine looks for a gicen partition into the NT 4.0 ftdisk registry
    database

Arguments:

    DiskRegistry    - supplies the ftdisk registry database

    Signature       - supplies the signature of the disk where the partition resides

    Offset          - supplies the offset of the partition

Return Value:

    The partition structure in the registry database.
    NULL if the partition is not there.

--*/

{
    PDISK_DESCRIPTION   diskDescription;
    USHORT              i, j;
    PDISK_PARTITION     diskPartition;
    LONGLONG            tmp;

    diskDescription = &DiskRegistry->Disks[0];
    for (i = 0; i < DiskRegistry->NumberOfDisks; i++) {
        if (diskDescription->Signature == Signature) {
            for (j = 0; j < diskDescription->NumberOfPartitions; j++) {
                diskPartition = &diskDescription->Partitions[j];
                memcpy(&tmp, &diskPartition->StartingOffset.QuadPart,
                       sizeof(LONGLONG));
                if (tmp == Offset) {
                    return diskPartition;
                }
            }
        }

        diskDescription = (PDISK_DESCRIPTION) &diskDescription->
                          Partitions[diskDescription->NumberOfPartitions];
    }

    return NULL;
}

BOOL
FtPresentOnDisk40(
    HANDLE          Handle,
    PDISK_REGISTRY  DiskRegistry,
    PBOOL           FtPresent
    )

/*++

Routine Description:

    This routine looks for FT partitions on a disk

Arguments:

    Handle          - supplies a handle to the open disk

    DiskRegistry    - supplies the ftdisk registry database

    FtPresent       - is set to true if FT partitions are detected on the disk

Return Value:

    TRUE    if the function is successful
    FALSE   if some fatal error occured

--*/

{
    PDRIVE_LAYOUT_INFORMATION   layout;
    DWORD                       layoutSize;
    NTSTATUS                    status;
    IO_STATUS_BLOCK             statusBlock;
    ULONG                       i;
    PPARTITION_INFORMATION      partInfo;
    PDISK_PARTITION             diskPartition;
    
    *FtPresent = FALSE;

    //
    // Allocate memory for IOCTL_GET_DRIVE_LAYOUT
    //

    layoutSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry) +
                 32 * sizeof(PARTITION_INFORMATION);
    layout = (PDRIVE_LAYOUT_INFORMATION) LocalAlloc(0, layoutSize);
    if (!layout) {
        return FALSE;
    }
    
    //
    //  Read the drive layout
    //
        
    while (1) {

        status = NtDeviceIoControlFile(Handle, 0, NULL, NULL,
                                       &statusBlock,
                                       IOCTL_DISK_GET_DRIVE_LAYOUT,
                                       NULL, 0,
                                       layout, layoutSize);
        if (status != STATUS_BUFFER_TOO_SMALL) {
            break;
        }
            
        layoutSize += 32 * sizeof(PARTITION_INFORMATION);
        if (layout) {
            LocalFree(layout);
        }
        layout = (PDRIVE_LAYOUT_INFORMATION) LocalAlloc(0, layoutSize);
        if (!layout) {
            return FALSE;
        }            
    }

    if (!NT_SUCCESS(status)) {            
        // inaccessible device. Act like it has no FT volumes
        LocalFree(layout);
        return TRUE;
    }

    //
    // Look for FT partitions
    //

    for (i = 0; i < layout->PartitionCount; i++) {
        
        //
        //  We're looking after recognized partitions marked
        //  with the 0x80 flag
        //

        partInfo = &(layout->PartitionEntry[i]);
        if (!IsFTPartition(partInfo->PartitionType)) {
            continue;
        }
        
        //
        //  Check whether the partition is marked as a member
        //  of an FT volume in the registry database
        //
        
        diskPartition = FindPartitionInRegistry40(
                            DiskRegistry, layout->Signature,
                            partInfo->StartingOffset.QuadPart);
        if (!diskPartition) {
            continue;
        }
            
        if (diskPartition->FtType != NotAnFtMember) {
            *FtPresent = TRUE;
            break;
        }        
    }

    LocalFree(layout);
    return TRUE;
}

BOOL
IsFtSet40(
    WCHAR           DriveLetter,
    PDISK_REGISTRY  DiskRegistry
    )

/*++

Routine Description:

    This routine cheks whether the given drive letter belongs to
    an FT set

Arguments:

    DriveLetter     - supplies a drive letter

    DiskRegistry    - supplies the ftdisk registry database    

Return Value:

    TRUE    if the function is the drive letter belongs to an FT set    

--*/

{
    HANDLE                  handle;
    NTSTATUS                status;
    WCHAR                   deviceName[20];
    PARTITION_INFORMATION   partInfo;
    BOOL                    b;
    DWORD                   bytes;
    PDISK_DESCRIPTION       diskDescription;
    PDISK_PARTITION         diskPartition;
    USHORT                  i, j;

    //
    //  Open the volume and get its "partition" type
    //  If the NTFT flag is not set the volume is not an FT set
    //
    
    wsprintf(deviceName, L"\\DosDevices\\%c:", DriveLetter);    
    status = OpenDevice(deviceName, &handle);
    if (!NT_SUCCESS(status)) {
        return FALSE;
    }

    b = DeviceIoControl(handle, IOCTL_DISK_GET_PARTITION_INFO,
                        NULL, 0, &partInfo, sizeof(partInfo),
                        &bytes, NULL);
    CloseHandle(handle);

    if (!b) {
        return FALSE;
    }
    
    if (!IsFTPartition(partInfo.PartitionType)) {
        return FALSE;
    }

    //
    //  Look for the drive letter in the FT registry. See if it belongs
    //  to an FT set
    //

    diskDescription = &DiskRegistry->Disks[0];
    for (i = 0; i < DiskRegistry->NumberOfDisks; i++) {
        for (j = 0; j < diskDescription->NumberOfPartitions; j++) {
            diskPartition = &diskDescription->Partitions[j];
            if (diskPartition->AssignDriveLetter &&
                tolower(diskPartition->DriveLetter) == tolower(DriveLetter) &&
                diskPartition->FtType != NotAnFtMember) {
                return TRUE;
            }            
        }
        
        diskDescription = (PDISK_DESCRIPTION) &diskDescription->
                          Partitions[diskDescription->NumberOfPartitions];
    }
    
    return FALSE;
}

BOOL
GetDeviceDriveLetter(
    PWSTR   DeviceName, 
    PWCHAR  DriveLetter
    )

/*++

Routine Description:

    This routine returns the drive letter (if any) of a device given
    the device name (like \Device\HarddiskVolume1)

Arguments:

    DeviceName      - supplies the device name

    DriveLetter     - returns the drive letter

Return Value:

    TRUE    if the device has a drive letter

--*/

{
    DWORD   cch;
    WCHAR   dosDevices[4096];
    WCHAR   target[4096];
    PWCHAR  dosDevice;

    *DriveLetter = 0;

    if (!QueryDosDevice(NULL, dosDevices, 4096)) {
        return FALSE;
    }
    
    dosDevice = dosDevices;
    while (*dosDevice) {

        if (wcslen(dosDevice) == 2 && dosDevice[1] == L':' &&
            QueryDosDevice(dosDevice, target, 4096)) {

            if (!wcscmp(target, DeviceName)) {
                *DriveLetter = (WCHAR) tolower(dosDevice[0]);
                return TRUE;
            }
        }

        while (*dosDevice++);
    }

    return FALSE;
}