// Viewer.cpp: implementation of the CViewer class.
//
//////////////////////////////////////////////////////////////////////

#include "Viewer.h"
#include "DUiMan.h"
#include "dbt.h"
#include "winioctl.h"
#include "winbase.h"
#include "FileInfo.h"
#include "wininet.h"
#include "EXCPT.H"
#define REGISTRY_TEXT L"Registry"
#define FILE_TEXT L"File"

#include "CDHelper.h"

CCDHelper *g_pCDHelper = NULL;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CViewer::CViewer()
{
    m_pDUiMan = NULL;
    m_pDebugWindow = NULL;
    m_pHelpWindow = NULL;

    m_pMainWindow = NULL;
    m_pViewSelector = NULL;
    m_pDetails = NULL;
    m_pListBox = NULL;
    m_pTextBox = NULL;

    m_hWnd = 0;
    m_hParentInstance = 0;
    m_hCD = INVALID_HANDLE_VALUE;

    m_pbtStoredIP = NULL;
    m_pbtStoredBoot = NULL;
    m_dwStoredBootSize = 0;
}

CViewer::~CViewer()
{
    if (m_hCD != INVALID_HANDLE_VALUE)
        CloseHandle(m_hCD);

}


LRESULT CViewer::WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
    DWORD dwCode;
    switch (uMessage)
    {
    case WM_DEVICECHANGE:
        m_pDUiMan->DisplayDebugDataf(L"Got DevCha Msg %8x %8x",wParam,lParam);
        if (m_dwCurrentViewing == VIEWING_FILES)
        {
            ChangeDirectory(L"\\", m_pTextBox, m_pListBox);
        }
        break;
    case DUIM_ENTER:
        HANDLE_DUIM_ENTER(m_pListBox,OnDblclkList)
        break;
    case DUIM_LISTBOX_SELCHANGE:
        if (((CDUiListBox *)wParam) == m_pViewSelector)
        {
            OnSelChangeViewSelector();
        }
        else if (((CDUiListBox *)wParam) == m_pListBox)
        {
            OnSelChangeListBox();
        }


        break;
    case WM_KEYDOWN:
        switch (wParam)
        {
        case VK_ESCAPE:
            PostMessage(m_hWnd,WM_CLOSE,0,0);
            PostMessage(m_hWnd,WM_QUIT,0,0);
            break;
        case VK_F1:
            ToggleWindow(m_pHelpWindow);
            break;
        case VK_F2:
            ToggleWindow(m_pDebugWindow);
            break;
        case VK_F5:
            if (m_dwCurrentViewing == VIEWING_FILES)
            {
#ifdef _WIN32_WCE
                ChangeDirectory(L"\\", m_pTextBox, m_pListBox);
#else
                ChangeDirectory(L"C:\\", m_pTextBox, m_pListBox);
#endif
            }
            else
            {
                ChangeRegistryKey(L"\\");
            }
            break;
        case VK_F6:
            if (m_dwCurrentViewing == VIEWING_FILES)
            {
                //launch program 
                LaunchProgram();
            }
            break;
        case VK_F9:
            if (m_dwCurrentViewing == VIEWING_FILES)
            {
                PlayWaveFile();
            }
            break;
        case VK_F12:
            OnBootCD();
            break;
        case 'A':
            m_pDUiMan->DisplayDebugErrorf(L"Attempting CDHelper::InitDrive");
            if (g_pCDHelper)
                dwCode = g_pCDHelper->InitDrive();
            m_pDUiMan->DisplayDebugErrorf(L"CDHelper InitDrive returned %d",dwCode);
            break;
        case 'B':
            m_pDUiMan->DisplayDebugErrorf(L"Attempting CDHelper::InitCDFS");
            if (g_pCDHelper)
                dwCode = g_pCDHelper->InitCDFS();
            m_pDUiMan->DisplayDebugErrorf(L"CDHelper InitCDFS returned %d",dwCode);
            break;
        case 'L':
            if (LoadBootFiles(&m_pbtStoredIP,&m_pbtStoredBoot,&m_dwStoredBootSize) == 0)
            {
                m_pDUiMan->DisplayDebugErrorf(L"LoadBootFiles succeeded %d %d %d",m_pbtStoredIP,m_pbtStoredBoot,m_dwStoredBootSize);
            }
            else
            {
                m_pDUiMan->DisplayDebugErrorf(L"LoadBootFiles failed");
            }
            break;
        default:
            break;
        }
        break;
    }
    return 0;
}


DWORD   CViewer::Initialize(HINSTANCE hInstance, HWND hWnd)
{
    m_hWnd = hWnd;
    m_hParentInstance = hInstance;
    DWORD dwCount = 0,dwHeight = 40;
    WCHAR wszTemp[200];

    g_pCDHelper = new CCDHelper();
    g_pCDHelper->SetDUIMan(m_pDUiMan);

    //create all the windows that are needed
    if (m_pMainWindow = m_pDUiMan->CreateDUiWindow(L"Primary",0,0,640,480,0))
    {
        m_pDUiMan->SetDefaultBackgroundColor(_565(0,0,0));
        m_pDUiMan->SetDefaultFontColor(_565(0,63,0));
        if (m_pDUiMan->IsFontAvailable(L"arial.ttf"))
        {
            m_pDUiMan->SetDefaultFontName(L"arial.ttf");
        }
        else
        {
            m_pDUiMan->DisplayDebugErrorf(L"Could not find Arial font");
            if (m_pDUiMan->GetFirstAvailableFont(wszTemp))
            {
                m_pDUiMan->DisplayDebugErrorf(L"Found font %s",wszTemp);
                m_pDUiMan->SetDefaultFontName(wszTemp);
            }
        }
        m_pDUiMan->SetDefaultSelectOutlineColor(_565(31,63,31));
        m_pDUiMan->SetDefaultSelectedFontColor(_565(15,32,15));
        m_pDUiMan->SelectWindow(L"Primary");

        if (m_pViewSelector = (CDUiListBox *) 
            m_pMainWindow->CreateDUiObject(DUI_LISTBOX,L"Selector",10,20,230,60,0))
        {
            m_pViewSelector->Initialize();
            m_pViewSelector->AddString(FILE_TEXT);
            m_pViewSelector->AddString(REGISTRY_TEXT);
        }

        if (m_pListBox = (CDUiListBox *) 
            m_pMainWindow->CreateDUiObject(DUI_LISTBOX,L"DirectoryViewer",10,90,230,370,0))
        {
            m_pListBox->Initialize();
        }

        if (m_pDetails = (CDUiListBox *) 
            m_pMainWindow->CreateDUiObject(DUI_LISTBOX,L"DataViewer",250,90,370,370,0))
        {
            m_pDetails->Initialize();
        }
        
        if (m_pTextBox = (CDUiText *)
            m_pMainWindow->CreateDUiObject(DUI_TEXT,L"TextBox",250,20,370,60,0))
        {
            m_pTextBox->Initialize();
        }
        

        CreateHelpWindow();
        m_pDUiMan->GetNamedObject(L"DUiDebugWindow",(CDUiObject **)&m_pDebugWindow);
        if (!m_pDebugWindow)
            m_pDetails->AddString(L"DebugWindow == NULL");

        wcscpy(m_wszCurrentRegistryKey,L"\\");
        //populate the list box with directories
#ifdef _WIN32_WCE
        ChangeDirectory(L"\\", m_pTextBox, m_pListBox);
#else
        ChangeDirectory(L"C:\\", m_pTextBox, m_pListBox);
#endif
        m_dwCurrentViewing = VIEWING_FILES;

        WCHAR wszTemp[512];
        m_hCD = CreateFile(TEXT("\\Device\\CDROM0"), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL );
        if (m_hCD != INVALID_HANDLE_VALUE)
        {
            DWORD dwTemp = 1;
            DWORD dwTemp2;
            DWORD dwCode = CTL_CODE( FILE_DEVICE_CD_ROM, 0x0410 ,METHOD_BUFFERED, FILE_READ_ACCESS);
            if (!DeviceIoControl(m_hCD, dwCode, &dwTemp, sizeof(DWORD), NULL, 0, &dwTemp2, NULL))
            {
                wsprintf(wszTemp,L"Could not set ioctl %d Error %d",dwTemp2,GetLastError());
                m_pDUiMan->DisplayDebugErrorf(wszTemp);
            }

        }
        else
        {
            wsprintf(wszTemp,L"Could not open cdrom %d",GetLastError());
            m_pDUiMan->DisplayDebugErrorf(wszTemp);
            m_pDetails->AddString(wszTemp);
        }
    }

    HANDLE hTemp = CreateFile(L"Test.txt",GENERIC_WRITE,0,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
    if (hTemp != INVALID_HANDLE_VALUE)
    {
        WriteFile(hTemp,"TEST",4,&dwCount,NULL);
        CloseHandle(hTemp);
    }
    else
        m_pDUiMan->DisplayDebugErrorf(L"Count not create text file %d",GetLastError());


    return S_OK;
}   

BOOL CViewer::CreateHelpWindow()
{
    BOOL bRetVal = TRUE;
    CDUiText *pText;
    DWORD dwCount = 0,dwTop,dwHeight = 30,dwWidth = 300,dwSpacing = dwHeight + 10;
    WCHAR *wszHelpCommands[] = 
    {
        L"F1 - Help",
        L"F2 - Debug Window",
        L"F5 - Change to Root Path",
        L"F6 - Launch Program",
        L"F9 - Play Wave Clip",
        L"F12 - Boot CD/Reboot",
        L""
    };

    dwTop = 20;
    if (m_pHelpWindow = m_pDUiMan->CreateDUiWindow(L"Help",0,0,640,480,0))
    {
        m_pHelpWindow->SetVisible(FALSE);

        dwCount = 0;
        while (wszHelpCommands[dwCount][0])
        {
            if (pText = (CDUiText *) 
                m_pHelpWindow->CreateDUiObject(DUI_TEXT,L"Static",20,dwTop,dwWidth,dwHeight,0))
            {
                pText->Initialize();
                pText->SetText(wszHelpCommands[dwCount]);
            }
            dwTop += dwSpacing;
            dwCount++;
        }
    }

    return bRetVal;
}

BOOL CViewer::ToggleWindow(CDUiWindow *pWindow)
{
    BOOL bRetVal = FALSE;
    if (pWindow)
    {
        if (pWindow->GetVisible())
        {
            m_pDUiMan->SelectWindow(L"Primary");
        }
        else
        {
            m_pDUiMan->SelectWindow(pWindow);
            bRetVal = TRUE;
        }
    }
    return bRetVal;
}

BOOL CViewer::ChangeDirectory(WCHAR *wszDirectory, CDUiText *pText, CDUiListBox *pListBox)
{
    HANDLE hFind;
    WCHAR wszPathMask[512];
    WIN32_FIND_DATA FindData;
    BOOL bCont;
    BOOL bFoundCurrentDir = FALSE;
    BOOL bFoundUpDir = FALSE;

    pListBox->Reset();
    wcscpy(m_wszCurrentDirectory,wszDirectory);
    if (wcscmp(wszDirectory,L"\\") != 0)
    {
        wsprintf(wszPathMask,L"%s\\*",m_wszCurrentDirectory);
    }
    else
    {
        wcscpy(m_wszCurrentDirectory,wszDirectory);
        wsprintf(wszPathMask,L"%s*",wszDirectory);
    }

    hFind = FindFirstFile(wszPathMask,&FindData);
    bCont = TRUE;

    while (bCont && (hFind != INVALID_HANDLE_VALUE))
    {
        //don't list the current Directory
        if (wcscmp(FindData.cFileName,L".") == 0)
        {
            bFoundCurrentDir = TRUE;
        }
        else if (wcscmp(FindData.cFileName,L"..") == 0)
        {
            bFoundUpDir = TRUE;
            pListBox->AddString(FindData.cFileName);
        }
        else
        {
            if (!bFoundUpDir && (wcslen(m_wszCurrentDirectory) > 1))
            {
                bFoundUpDir = TRUE;
                pListBox->AddString(L"..");
            }
            pListBox->AddString(FindData.cFileName);
        }
        bCont = FindNextFile(hFind,&FindData);
    }
    if (!bFoundUpDir && (wcslen(m_wszCurrentDirectory) > 1))
    {
        bFoundUpDir = TRUE;
        pListBox->AddString(L"..");
    }
    pText->SetText(m_wszCurrentDirectory);
    pListBox->SetSelectedString(0);
    OnSelChangeListBox();
    return TRUE;
}

DWORD CViewer::LoadBootFiles(BYTE **pbtIP, BYTE **pbtBoot, DWORD *pdwBootSize)
{
    DWORD dwRetVal = 0;
#ifdef _WIN32_WCE
    HANDLE hIPFile = INVALID_HANDLE_VALUE;
    HANDLE hOtherFile = INVALID_HANDLE_VALUE;

    CHAR szFileName[16];
    WCHAR wszFileOnCD[256];
    DWORD dwBytesRead;
    DWORD i;

    memset(szFileName,0,16);
    hIPFile = CreateFile(L"\\CD-ROM\\IP.bin",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
    if (hIPFile != INVALID_HANDLE_VALUE)
    {
        SetFilePointer(hIPFile,0x60,NULL,FILE_BEGIN);
        if (ReadFile(hIPFile,szFileName,16,&dwBytesRead,NULL) && dwBytesRead)
        {
            for (i = 15; i >= 0; i--)
            {
                if (szFileName[i] == ' ')
                    szFileName[i] = 0;
                else
                    break;
            }
            wsprintf(wszFileOnCD,L"\\CD-ROM\\%hs",szFileName);
            hOtherFile = CreateFile(wszFileOnCD,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
        }
    }
    else
    {
        m_pDUiMan->DisplayDebugErrorf(L"Could not open IP.bin %d",GetLastError());
        dwRetVal = 1;
    }

    if ((hIPFile != INVALID_HANDLE_VALUE) &&
        (hOtherFile != INVALID_HANDLE_VALUE))
    {
        *pdwBootSize = GetFileSize(hOtherFile,NULL);
        m_pDUiMan->DisplayDebugErrorf(L"Attempting to load and read");

        //try copying it to a physical memory location
        *pbtIP = (BYTE*) malloc(32768);
        *pbtBoot = (BYTE*) malloc(*pdwBootSize);

        SetFilePointer(hIPFile,0,NULL,FILE_BEGIN);
        ReadFile(hIPFile,*pbtIP,32768,&dwBytesRead,NULL);
        SetFilePointer(hOtherFile,0,NULL,FILE_BEGIN);
        ReadFile(hOtherFile,*pbtBoot,*pdwBootSize,&dwBytesRead,NULL);
    }
    else
    {
        m_pDUiMan->DisplayDebugErrorf(L"Could not open files %d %d %s %d",GetLastError(),hIPFile,wszFileOnCD,hOtherFile);
        dwRetVal = 2;
    }
    if (hIPFile != INVALID_HANDLE_VALUE)
    {
        CloseHandle(hIPFile);
    }
    if (hOtherFile != INVALID_HANDLE_VALUE)
    {
        CloseHandle(hOtherFile);
    }
#endif
    return dwRetVal;
}

void CViewer::OnBootCD()
{
#ifdef _WIN32_WCE
    DWORD dwOtherFileSize;
    BOOL bDontFree = FALSE;
    BOOL bRet;
    typedef DWORD (*lSetKMode) (DWORD dwEnter);
    typedef void (*RTF) (void);
    RTF pRTF;
    RTF pTemp;
    lSetKMode pFunc;
    BYTE *pbtIP = NULL;
    BYTE *pbtFile = NULL;
    HMODULE hMod = LoadLibrary(L"Coredll.dll");
    HMODULE hMod2 = LoadLibrary(L"platutil.dll");
    pFunc = (lSetKMode) GetProcAddress(hMod,L"SetKMode");
    pRTF = (RTF) GetProcAddress(hMod2,L"ResetToFirmware");
    EXCEPTION_RECORD ExRecord;
    CONTEXT ContextRecord;
    _EXCEPTION_POINTERS *pExcept;

    if (m_pbtStoredBoot && m_pbtStoredIP)
    {
        pbtIP = m_pbtStoredIP;
        pbtFile = m_pbtStoredBoot;
        dwOtherFileSize = m_dwStoredBootSize;
        bDontFree = TRUE;
    }
    else if (LoadBootFiles(&pbtIP,&pbtFile,&dwOtherFileSize) == 0)
    {

    }
    else
    {
        //KernelIoControl IOCTL_HAL_REBOOT does not work must use function from platutil
        if (pRTF)
            pRTF();
    }

    if (pbtIP && pbtFile)
    {
        if (pFunc)
            bRet = pFunc(TRUE);
        m_pDUiMan->DisplayDebugErrorf(L"SetKMode %d return %d %d",pFunc,bRet,GetLastError());
        
        __try
        {
            memcpy((void*)0x8c008000,pbtIP,32768);
            memcpy((void*)0x8c010000,pbtFile,dwOtherFileSize);
            __try
            {
                //                    pTemp = (RTF)0x8c008300;
                pTemp = (RTF)0x8c00B800; // try going to bootstrap 1
                pTemp();
            }
            __except (pExcept = GetExceptionInformation() , memcpy(&ExRecord,pExcept->ExceptionRecord,sizeof(ExRecord)),memcpy(&ContextRecord,pExcept->ContextRecord,sizeof(ContextRecord)),1)
            {
                m_pDUiMan->DisplayDebugErrorf(L"Temp Jump failed Ex Code %x (%x) at %x",ExRecord.ExceptionCode,ExRecord.ExceptionFlags,ExRecord.ExceptionAddress);
            }
            __asm("jmp @ r4;\n"
                "nop;"
                ,0x8C008300);
        }
        __except (pExcept = GetExceptionInformation() , memcpy(&ExRecord,pExcept->ExceptionRecord,sizeof(ExRecord)),memcpy(&ContextRecord,pExcept->ContextRecord,sizeof(ContextRecord)),1)
        {
            m_pDUiMan->DisplayDebugErrorf(L"memcpy failed Ex Code %x (%x) at %x",ExRecord.ExceptionCode,ExRecord.ExceptionFlags,ExRecord.ExceptionAddress);
        }
        if (pFunc)
            bRet = pFunc(FALSE);
        m_pDUiMan->DisplayDebugErrorf(L"SetKMode %d return %d %d",pFunc,bRet,GetLastError());
    }
    else 
    {
        m_pDUiMan->DisplayDebugErrorf(L"Getting boot files failed");
    }
 
    if (pbtFile && pbtIP && !bDontFree)
    {
        free(pbtFile);
        free(pbtIP);
    }
    FreeLibrary(hMod);
    FreeLibrary(hMod2);
#else
    DestroyWindow(m_hWnd);
#endif
}

void CViewer::OnDblclkList() 
{
    int iPos;
    WCHAR wszTemp[512];
    WCHAR wszTemp2[512];
    WCHAR *wszPtr;
    BOOL bCreatePath = TRUE;
    BOOL bSuccess = FALSE;

    iPos = m_pListBox->GetSelectedString();
    if (iPos != 0xFFFFFFFF)
    {
        m_pListBox->GetString(iPos,wszTemp);
        if (m_dwCurrentViewing == VIEWING_FILES)
        {
            GetChangedDirectory(m_pTextBox, m_pListBox);
        }
        else if (m_dwCurrentViewing == VIEWING_REGISTRY)
        {
            if (!IsRootKey(wszTemp) &&
                (wcscmp(wszTemp,L"..") != 0))
            {
                if (wcslen(m_wszCurrentRegistryKey))
                {
                    wsprintf(wszTemp2,L"%s\\%s",m_wszCurrentRegistryKey,wszTemp);
                }
                else
                {
                    wcscpy(wszTemp2,wszTemp);
                }
                ChangeRegistryKey(wszTemp2);
            }
            else
            {
                if (!IsRootKey(wszTemp))
                {
                    //go back to the next higher up path
                    wcscpy(wszTemp,m_wszCurrentRegistryKey);
                    wszPtr = wcsrchr(wszTemp,L'\\');
                    if (wszPtr)
                    {
                        *(wszPtr) = 0;
                    }
                    else
                    {
                        if (wcslen(wszTemp) == 0)
                        {
                            wcscpy(wszTemp,L"\\");
                        }
                        else
                        {
                            *wszTemp = 0;
                        }
                    }
                }
                ChangeRegistryKey(wszTemp);
            }
        }

    }

}

BOOL CViewer::GetChangedDirectory(CDUiText *pText, CDUiListBox *pListBox)
{
        int iPos;
    WCHAR wszTemp[512];
    WCHAR wszTemp2[512];
    WCHAR *wszPtr;
    BOOL bCreatePath = TRUE;
    BOOL bSuccess = FALSE;

    iPos = pListBox->GetSelectedString();
    if (iPos != 0xFFFFFFFF)
    {
        pListBox->GetString(iPos,wszTemp);
        if (wcscmp(wszTemp,L"..") == 0)
        {
            bCreatePath = FALSE;
#ifdef _WIN32_WCE
            wcscpy(wszTemp,m_wszCurrentDirectory+1);
#else
            wcscpy(wszTemp,m_wszCurrentDirectory+3);
#endif
            if (wszPtr = wcsrchr(wszTemp,L'\\'))
            {
                *(wszPtr) = 0;
            }
            else
            {
                wcscpy(wszTemp,L"");
            }
            
#ifdef _WIN32_WCE
            wcscpy(m_wszCurrentDirectory,L"\\");
#else
            wcscpy(m_wszCurrentDirectory,L"C:\\");
#endif
        }
        if (!IsRootPath(m_wszCurrentDirectory))
        {
            if (bCreatePath)
                wsprintf(wszTemp2,L"%s\\%s",m_wszCurrentDirectory,wszTemp);
            else
                wcscpy(wszTemp2,m_wszCurrentDirectory);
        }
        else
        {
            wsprintf(wszTemp2,L"%s%s",m_wszCurrentDirectory,wszTemp);
        }
        if (GetFileAttributes(wszTemp2) & FILE_ATTRIBUTE_DIRECTORY)
        {
            return ChangeDirectory(wszTemp2, pText, pListBox);
        }
    }
    return FALSE;   
}


void CViewer::LaunchProgram()
{
    int iPos;
    WCHAR wszTemp[512];
    WCHAR wszTemp2[512];
    BOOL bCreatePath = TRUE;
    BOOL bSuccess = FALSE;
    STARTUPINFO StartupInfo;
    PROCESS_INFORMATION *pProcessInfo;

    iPos = m_pListBox->GetSelectedString();
    if (iPos != 0xFFFFFFFF)
    {
        m_pListBox->GetString(iPos,wszTemp);
        if (m_dwCurrentViewing == VIEWING_FILES)
        {
            if (!IsRootPath(m_wszCurrentDirectory))
            {
                wsprintf(wszTemp2,L"%s\\%s",m_wszCurrentDirectory,wszTemp);
            }
            else
            {
                wsprintf(wszTemp2,L"%s%s",m_wszCurrentDirectory,wszTemp);
            }
            if (wcsstr(_wcsupr(wszTemp2),L".EXE"))
            {
                memset(&StartupInfo,0,sizeof(StartupInfo));

                StartupInfo.cb = sizeof(StartupInfo);
                pProcessInfo = (PROCESS_INFORMATION *) malloc(sizeof(PROCESS_INFORMATION));
                bSuccess = CreateProcess(wszTemp2,NULL,NULL,NULL,FALSE,0,NULL,NULL,&StartupInfo,pProcessInfo);
                if (bSuccess)
                {
                    //post a message to suspend our process 
                    //and let the other one get control of the UI
                    ShowWindow(m_hWnd,SW_HIDE);
                    PostMessage(m_hWnd,WM_SPAWNED_PROCESS,(WPARAM) pProcessInfo,0);
//                    PostMessage(m_hWnd,WM_CLOSE,0,0);
//                    PostMessage(m_hWnd,WM_QUIT,0,0);
                }
                else
                {
                    m_pDUiMan->DisplayDebugErrorf(L"CreateProcess error %d",GetLastError());
                    free(pProcessInfo);
                }
            }
        }
    }
}


void CViewer::PlayWaveFile()
{
    int iPos;
    WCHAR wszTemp[512];
    WCHAR wszTemp2[512];
    CDUiWave *pWave;

    iPos = m_pListBox->GetSelectedString();
    if (iPos != 0xFFFFFFFF)
    {
        m_pListBox->GetString(iPos,wszTemp);
        if (m_dwCurrentViewing == VIEWING_FILES)
        {
            if (!IsRootPath(m_wszCurrentDirectory))
            {
                wsprintf(wszTemp2,L"%s\\%s",m_wszCurrentDirectory,wszTemp);
            }
            else
            {
                wsprintf(wszTemp2,L"%s%s",m_wszCurrentDirectory,wszTemp);
            }
            m_pDetails->Reset();
            m_pDetails->AddString(wszTemp2);
            if (wcsstr(_wcsupr(wszTemp2),L".WAV"))
            {
                if (pWave = m_pDUiMan->CreateDUiWave(wszTemp,wszTemp2,0))
                {
                    pWave->Initialize();
                    if (!pWave->IsPlaying())
                        pWave->Play();
                    else
                        pWave->Stop();
                }
            }
        }
    }
}

BOOL CViewer::IsRootPath(WCHAR *wszDirectory)
{
    BOOL bRetVal = FALSE;
    WCHAR *wszPtr;

    if (wcscmp(wszDirectory,L"\\") == 0)
    {
        bRetVal = TRUE;
    } 
    else if ((wcslen(wszDirectory) == 3) &&
        (wszPtr = wcsstr(wszDirectory,L":\\")))
    {
        bRetVal = TRUE;
    }
    return bRetVal;
}




void CViewer::OnSelChangeViewSelector() 
{
    DWORD dwPos;
    WCHAR wszTemp[512];

    dwPos = m_pViewSelector->GetSelectedString();
    if (dwPos != 0xFFFFFFFF)
    {
        m_pViewSelector->GetString(dwPos,wszTemp);
        if (wcscmp(wszTemp,FILE_TEXT) == 0)
        {
            m_dwCurrentViewing = VIEWING_FILES;
            ChangeDirectory(m_wszCurrentDirectory, m_pTextBox, m_pListBox);
        }
        else if (wcscmp(wszTemp,REGISTRY_TEXT) == 0)
        {
            m_dwCurrentViewing = VIEWING_REGISTRY;
            ChangeRegistryKey(m_wszCurrentRegistryKey);
        }
    }
}

void CViewer::OnSelChangeListBox()
{
    DWORD dwPos;
    WCHAR wszTemp[512];
    WCHAR wszTemp2[512];
    DWORD dwAttributes = 0;
    ULARGE_INTEGER ulFreeAvailableBytes;
    ULARGE_INTEGER ulTotalBytes;
    ULARGE_INTEGER ulFreeBytes;
    HANDLE hFile;
    DWORD dwFileSize;


    if (m_dwCurrentViewing == VIEWING_FILES)
    {
        dwPos = m_pListBox->GetSelectedString();
        if (dwPos != 0xFFFFFFFF)
        {
            m_pDetails->Reset();
            m_pListBox->GetString(dwPos,wszTemp);
            if (wcscmp(L"..",wszTemp) == 0)
            {
                wcscpy(wszTemp2,m_wszCurrentDirectory);
            }
            else
            {
                if (!IsRootPath(m_wszCurrentDirectory))
                {
                    wsprintf(wszTemp2,L"%s\\%s",m_wszCurrentDirectory,wszTemp);
                }
                else
                {
                    wsprintf(wszTemp2,L"%s%s",m_wszCurrentDirectory,wszTemp);
                }
            }
            dwAttributes = GetFileAttributes(wszTemp2);
            if (dwAttributes != 0xFFFFFFFF)
            {
                if (dwAttributes & FILE_ATTRIBUTE_DIRECTORY)
                {
                    m_pDetails->AddString(L"File Size 0");
                    m_pDetails->AddString(L"Directory");
                    if (GetDiskFreeSpaceEx(wszTemp2,&ulFreeAvailableBytes,&ulTotalBytes,&ulFreeBytes))
                    {
                        wsprintf(wszTemp,L"  Free Bytes %d",ulFreeBytes.QuadPart);
                        m_pDetails->AddString(wszTemp);
                        wsprintf(wszTemp,L"  Total Bytes %d",ulTotalBytes.QuadPart);
                        m_pDetails->AddString(wszTemp);
                    }
                    else
                    {
                        wsprintf(wszTemp,L"  Could not get disk space information %d",GetLastError());
                        m_pDetails->AddString(wszTemp);
                    }
                }
                else
                {
                    hFile = CreateFile(wszTemp2,GENERIC_READ
#ifdef _WIN32_WCE
                        ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL
#else
                        ,FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE,NULL
#endif
                        ,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
                    if (hFile != INVALID_HANDLE_VALUE)
                    {
                        dwFileSize = GetFileSize(hFile,NULL);
                        if (dwFileSize == 0xFFFFFFFF)
                        {
                            wsprintf(wszTemp,L"Could not get file size %d",GetLastError());
                        }
                        else
                        {
                            wsprintf(wszTemp,L"File Size %ld",dwFileSize);
                        }
                        m_pDetails->AddString(wszTemp);
                        CloseHandle(hFile);
                    }
                    else
                    {
                        wsprintf(wszTemp,L"Could not open file %d",GetLastError());
                        m_pDetails->AddString(wszTemp);
                    }
                }
                if (dwAttributes & FILE_ATTRIBUTE_ARCHIVE)
                    m_pDetails->AddString(L"Archive");
                if (dwAttributes & FILE_ATTRIBUTE_HIDDEN)
                    m_pDetails->AddString(L"Hidden");
                if (dwAttributes & FILE_ATTRIBUTE_READONLY)
                    m_pDetails->AddString(L"Read Only");
                if (dwAttributes & FILE_ATTRIBUTE_SYSTEM)
                    m_pDetails->AddString(L"System");
#ifdef _WIN32_WCE
                if (dwAttributes & FILE_ATTRIBUTE_INROM)
                    m_pDetails->AddString(L"In Rom");
                if (dwAttributes & FILE_ATTRIBUTE_ROMMODULE)
                    m_pDetails->AddString(L"Rom Module");
#endif                 

            }
            else
            {
                wsprintf(wszTemp,L"Get Attributes failed %d",GetLastError());
                m_pDetails->AddString(wszTemp);
            }
        }
    }
}

BOOL CViewer::ChangeRegistryKey(WCHAR *wszKey)
{
    HKEY hResult;
    WCHAR wszTemp[1024];
    WCHAR wszName[512];
    WCHAR wszClass[512];
    DWORD dwNameSize;
    DWORD dwClassSize;
    DWORD dwIndex;
    DWORD dwDataType;
    BYTE  btData[512];
//    DWORD dwDataSize;

    m_pListBox->Reset();
    m_pDetails->Reset();
    if (!IsRootKey(wszKey))
    {
        wcscpy(m_wszCurrentRegistryKey,wszKey);
        m_pListBox->AddString(L"..");
#ifdef _WIN32_WCE
        if (RegOpenKeyEx(m_hkCurrentRegistryRoot,wszKey,0,0,&hResult) == ERROR_SUCCESS)
#else
        if (RegOpenKeyEx(m_hkCurrentRegistryRoot,wszKey,0,KEY_ALL_ACCESS,&hResult) == ERROR_SUCCESS)
#endif
        {
            dwNameSize = 512;
            dwClassSize = 512;
            dwIndex = 0;
            while (RegEnumKeyEx(hResult,dwIndex,wszName,&dwNameSize,NULL,wszClass,&dwClassSize,NULL) == ERROR_SUCCESS)
            {
                m_pListBox->AddString(wszName);
                dwNameSize = 512;
                dwClassSize = 512;
                dwIndex++;
            }
            dwNameSize = 512;
            dwClassSize = 512;
            dwIndex = 0;
            while (RegEnumValue(hResult,dwIndex,wszName,&dwNameSize,NULL,&dwDataType,btData,&dwClassSize) == ERROR_SUCCESS)
            {
                switch (dwDataType)
                {
                case REG_DWORD:
//                case REG_DWORD_LITTLE_ENDIAN:
                    wsprintf(wszTemp,L"%s - %d",wszName,*((DWORD *)btData));
                    break;
                case REG_SZ:
                case REG_EXPAND_SZ:
                    wsprintf(wszTemp,L"%s - %s",wszName,((WCHAR *)btData));
                    break;
                case REG_BINARY:
                case REG_DWORD_BIG_ENDIAN:
                case REG_LINK:
                case REG_MULTI_SZ:
                case REG_NONE:
                case REG_RESOURCE_LIST:
                default:
                    wsprintf(wszTemp,L"%s - Uns %d",wszName,dwDataType);
                    break;
                }
                m_pDetails->AddString(wszTemp);
                dwNameSize = 512;
                dwClassSize = 512;
                dwIndex++;
            }
            RegCloseKey(hResult);
        }
        else
        {
            wsprintf(wszTemp,L"RegOpenKeyEx of %s returned %08x",wszKey,GetLastError());
        }
    }
    else
    {
        if (wcscmp(wszKey,L"\\") == 0)
        {
            m_pListBox->AddString(L"HKEY_CLASSES_ROOT");
            m_pListBox->AddString(L"HKEY_CURRENT_USER");
            m_pListBox->AddString(L"HKEY_LOCAL_MACHINE");
            m_pListBox->AddString(L"HKEY_USERS");
            wcscpy(m_wszCurrentRegistryKey,L"\\");
        }
        else 
        {
            if (wcscmp(wszKey,L"HKEY_CLASSES_ROOT") == 0)
            {
                m_hkCurrentRegistryRoot = HKEY_CLASSES_ROOT;
            }
            else if (wcscmp(wszKey,L"HKEY_CURRENT_USER") == 0)
            {
                m_hkCurrentRegistryRoot = HKEY_CURRENT_USER;
            }
            else if (wcscmp(wszKey,L"HKEY_LOCAL_MACHINE") == 0)
            {
                m_hkCurrentRegistryRoot = HKEY_LOCAL_MACHINE;
            }
            else if (wcscmp(wszKey,L"HKEY_USERS") == 0)
            {
                m_hkCurrentRegistryRoot = HKEY_USERS;
            }
//            m_pTextBox->SetText(L"");
            return ChangeRegistryKey(L"");
/*            wszKey = "";
            if (RegOpenKeyEx(m_hkCurrentRegistryRoot,wszKey,0,0,&hResult) == ERROR_SUCCESS)
            {
                dwNameSize = 512;
                dwClassSize = 512;
                while (RegEnumKeyEx(m_hkCurrentRegistryRoot,0,wszName,&dwNameSize,NULL,wszClass,&dwClassSize,NULL) == ERROR_SUCCESS)
                {
                    m_pListBox->AddString(wszName);
                }
            }
*/      }
    }
    if (wcscmp(m_wszCurrentRegistryKey,L"\\") == 0)
    {
        m_pTextBox->SetText(m_wszCurrentRegistryKey);
    }
    else
    {
        wcscpy(wszTemp,m_wszCurrentRegistryKey);
        if (m_hkCurrentRegistryRoot == HKEY_CLASSES_ROOT)
        {
            wsprintf(wszTemp,L"\\%s\\%s",L"HKEY_CLASSES_ROOT",m_wszCurrentRegistryKey);
        }
        else if (m_hkCurrentRegistryRoot == HKEY_CURRENT_USER)
        {
            wsprintf(wszTemp,L"\\%s\\%s",L"HKEY_CURRENT_USER",m_wszCurrentRegistryKey);
        }
        else if (m_hkCurrentRegistryRoot == HKEY_LOCAL_MACHINE)
        {
            wsprintf(wszTemp,L"\\%s\\%s",L"HKEY_LOCAL_MACHINE",m_wszCurrentRegistryKey);
        }
        else if (m_hkCurrentRegistryRoot == HKEY_USERS)
        {
            wsprintf(wszTemp,L"\\%s\\%s",L"HKEY_USERS",m_wszCurrentRegistryKey);
        }
        m_pTextBox->SetText(wszTemp);
    }
    m_pListBox->SetSelectedString(0);
    return TRUE;
}

BOOL CViewer::IsRootKey(WCHAR *wszKey)
{
    BOOL bRetVal = FALSE;
    if ((wcscmp(wszKey,L"\\") == 0) ||
        (wcscmp(wszKey,L"HKEY_CLASSES_ROOT") == 0) ||
        (wcscmp(wszKey,L"HKEY_CURRENT_USER") == 0) ||
        (wcscmp(wszKey,L"HKEY_LOCAL_MACHINE") == 0) ||
        (wcscmp(wszKey,L"HKEY_USERS") == 0))
    {
        bRetVal = TRUE;
    }
    return bRetVal;
}
