Windows CE's CESH Utility 

by Andrew Tucker





Listing One

/* Function declarations and defines for CESH remote I/O functions */



#ifdef __cplusplus

extern "C"

{

#endif



/* stolen from pkfuncs.h */

int U_ropen(const WCHAR *, UINT);

int U_rread(int, BYTE *, int);

int U_rwrite(int, BYTE *, int);

int U_rlseek(int, int, int);

int U_rclose(int);



#ifdef __cplusplus

}

#endif



/* defines stolen from the desktop VC++ header file io.h */

#define _O_RDONLY       0x0000  /* open for reading only */

#define _O_WRONLY       0x0001  /* open for writing only */

#define _O_RDWR         0x0002  /* open for reading and writing */

#define _O_APPEND       0x0008  /* writes done at eof */



#define _O_CREAT        0x0100  /* create and open file */

#define _O_TRUNC        0x0200  /* open and truncate */

#define _O_EXCL         0x0400  /* open if file doesn't exist */



/* sequential/random access hints */

#define _O_SEQUENTIAL   0x0020  /* file access is sequential */

#define _O_RANDOM       0x0010  /* file access is random */





Listing Two

/* Simple utility to dump a the registry on a Windows CE device to a desktop file via the CESH remote file I/O APIs */

#include <windows.h>

#include "ceshio.h"



/* print a debug message to the CESH console on the desktop machine */

void DbgOut(LPSTR psz)

{

    int fh = U_ropen(L"con", _O_CREAT | _O_WRONLY | _O_TRUNC );

    U_rwrite(fh, (PBYTE)psz, strlen(psz));

    U_rclose(fh);

}

/* Dump a single registry value by type */

#define LONIBBLE(x)  ((x) & 0x0f)

#define HINIBBLE(x)  (((x) & 0xf0) >> 4)



BOOL DumpRegValue(HKEY hkey, int nIndentSize, LPSTR pszValueName, 

                  DWORD dwType, PBYTE pbValueData, DWORD dwDataSize, int fh) 

{

    while ( nIndentSize-- )

        U_rwrite(fh, (PBYTE)" ", 1);

    U_rwrite(fh,(PBYTE)pszValueName, strlen(pszValueName));



    LPSTR pszType;

    LPSTR pszData = NULL;



    switch( dwType )

    {

        case REG_BINARY:

            {

                pszType = "(BINARY)";

                const char *pcszHex = "0123456789abcdef";

                pszData = (LPSTR)malloc((dwDataSize * 3) + 1);

                for ( DWORD i = 0; i < dwDataSize; i++ )

                {

                 pszData[i*3] = pcszHex[HINIBBLE(pbValueData[i])];

                 pszData[i*3+1] = pcszHex[LONIBBLE(pbValueData[i])];

                 pszData[i*3+2] = ' ';

                }

                pszData[dwDataSize*3] = 0;

            }

            break;

        case REG_DWORD_BIG_ENDIAN:

        case REG_DWORD: // same value as REG_DWORD_LITTLE_ENDIAN

            {

                if ( dwType == REG_DWORD_BIG_ENDIAN)

                    pszType = "(DWORD_BIG_ENDIAN)";

                else

                    pszType = "(DWORD)";

                wchar_t wchBuf[16];

                pszData = (LPSTR)malloc(16);

                

                wsprintf(wchBuf, _T("0x%x"), *(DWORD*)pbValueData);

                wcstombs(pszData, wchBuf, wcslen(wchBuf)+1);

            }

            break;

        case REG_MULTI_SZ:

            {

                pszType = "(MULTI_SZ)";



                LPWSTR pwsz = (LPWSTR)pbValueData;

                pszData = (LPSTR)malloc(dwDataSize+1);

                pszData[0] = 0;



                LPSTR pszIter = pszData;

                while ( *pwsz )

                {

                    wcstombs(pszIter, pwsz, wcslen(pwsz)+1);

                    pwsz += wcslen(pwsz) + 1;



                    if ( *pwsz )

                    {

                        strcat(pszIter, "\\0");

                        // make sure you overwrite previous zero terminator

                        pszIter += strlen(pszIter);  

                    }

                    else

                        strcat(pszIter, "\\0\\0");

                }

            }

            break;

        case REG_EXPAND_SZ:

        case REG_LINK:

        case REG_RESOURCE_LIST:

        case REG_SZ:

            {

                if ( dwType == REG_EXPAND_SZ )

                    pszType = "(EXPAND_SZ)";

                else if ( dwType == REG_LINK )

                    pszType = "(LINK)";

                else if ( dwType == REG_RESOURCE_LIST )

                    pszType = "(RESOURCE_LIST)";

                else

                    pszType = "(SZ)";

                if ( dwDataSize && pbValueData )

                {

                    //NOTE: have to handle specially be 

                    // cause string is not zero terminated?

                    LPWSTR pwsz = (LPWSTR)pbValueData;

                    int numchars = (dwDataSize/2)+1;

                    pszData = (LPSTR)malloc(numchars);

                    wcstombs(pszData, pwsz, numchars);

                    pszData[numchars-1] = 0;

                }

            }

            break;

        case REG_NONE:

            pszType = "(NONE)";

            break;

        default:

            pszType = "(UNKNOWN)";

            break;

    }

    U_rwrite(fh,(PBYTE)": ", 2);

    U_rwrite(fh, (PBYTE)pszType, strlen(pszType));

    if ( pszData )

    {

        U_rwrite(fh,(PBYTE)" ", 1);

        U_rwrite(fh,(PBYTE)pszData, strlen(pszData));

        free(pszData);

    }

    U_rwrite(fh,(PBYTE)"\r\n", 2);

    return TRUE;

}

/* Dump reg key values and recursively dump all subkeys */

BOOL DumpRegKey(HKEY hkey, int fh)

{

    BOOL bSuccess = FALSE;

    DWORD dwMaxSubkeys;

    DWORD dwMaxValues;

    DWORD dwMaxSubkeyLen;

    DWORD dwMaxValueNameLen;

    DWORD dwMaxValueLen;

    static int s_iCurIndent = 0;

    if ( RegQueryInfoKey(hkey, NULL, NULL, NULL, 

                         &dwMaxSubkeys,&dwMaxSubkeyLen, 

                         NULL, &dwMaxValues,&dwMaxValueNameLen, 

                         &dwMaxValueLen,NULL,NULL) == ERROR_SUCCESS )

    {

        // dump this key's values...

        DWORD dwValueNameLen = (dwMaxValueNameLen+1)*sizeof(wchar_t);

        LPTSTR pszValueName = (LPTSTR)malloc(dwValueNameLen);

        LPSTR pszValueNameA = (LPSTR)malloc(dwValueNameLen);

        PBYTE pbValueData = (PBYTE)malloc(dwMaxValueLen);

        DWORD       dwIndex = 0;



        while ( dwIndex < dwMaxValues )

        {

            DWORD dwSize = dwMaxValueNameLen+1;

            DWORD dwDataSize = dwMaxValueLen;

            DWORD dwType;



            if ( RegEnumValue(hkey, dwIndex, pszValueName, &dwSize, 

                   NULL, &dwType, pbValueData, &dwDataSize) != ERROR_SUCCESS )

                  break;

            wcstombs(pszValueNameA, pszValueName, wcslen(pszValueName)+1);

            if ( !DumpRegValue(hkey, s_iCurIndent, pszValueNameA, 

                               dwType, pbValueData, dwDataSize, fh) )

                break;

            dwIndex++;

        }

        free(pszValueName);

        free(pszValueNameA);

        free(pbValueData);



        // only succeeded if we did all the values

        bSuccess = ( dwIndex == dwMaxValues );



        if ( bSuccess )

        {

            // ...then enumerate other keys

            DWORD dwKeyNameLen = (dwMaxSubkeyLen+1)*sizeof(wchar_t);

            LPTSTR pszKeyName = (LPTSTR)malloc(dwKeyNameLen);

            LPSTR pszKeyNameA = (LPSTR)malloc(dwKeyNameLen);



            dwIndex = 0;



            while ( dwIndex < dwMaxSubkeys )

            {

                DWORD dwSize = dwMaxSubkeyLen+1;

                if ( RegEnumKeyEx(hkey, dwIndex, pszKeyName, &dwSize, 

                                  NULL, NULL, NULL, NULL) != ERROR_SUCCESS )

                    break;

                strcpy(pszKeyNameA, "[");

                wcstombs(pszKeyNameA+1, pszKeyName, wcslen(pszKeyName)+1);

                strcat(pszKeyNameA,"]\r\n");



                if ( s_iCurIndent )

                {

                    int i = s_iCurIndent;



                    while ( i-- )

                        U_rwrite(fh, (PBYTE)" ", 1);

                }

                if ( U_rwrite(fh, (PBYTE)pszKeyNameA, 

                     strlen(pszKeyNameA))!=(int)strlen(pszKeyNameA) )

                    break;

                // recurse into the key if we can open it

                HKEY hSubkey;

                if ( RegOpenKeyEx(hkey, pszKeyName, 

                                  0,0,&hSubkey) == ERROR_SUCCESS )

                {

                    s_iCurIndent += 4;

                    BOOL b = DumpRegKey(hSubkey, fh);

                    s_iCurIndent -= 4;

                    RegCloseKey(hSubkey);



                    if ( !b )

                        break;

                }

                else

                {

                    DbgOut("ERROR: could not open registry key '");

                    DbgOut(pszKeyNameA);

                    DbgOut("'\n");

                }

                dwIndex++;

            }

            free(pszKeyName);

            free(pszKeyNameA);



            // only succeeded if we did all the keys

            bSuccess = ( dwIndex == dwMaxSubkeys );

        }

    }

    // do an extra crlf if we're finishing the top-level key

    if ( !s_iCurIndent )

        U_rwrite(fh, (PBYTE)"\r\n", 2);

    return bSuccess;

}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

                    LPWSTR lpCmdLine, int nCmdShow)

{

    int fh;

    fh = U_ropen(L"regdump.txt", _O_CREAT | _O_WRONLY | _O_TRUNC );

    if ( fh == -1 )

    {

        DbgOut("error creating file\r\n");

    }

    else

    {

#define RKENTRY(x)  { #x "\r\n", strlen(#x) + 2, x }

        struct RKEntry

        {

            LPSTR psz;

            int len;

            HKEY hkey;

        } RegKeys[] = { RKENTRY( HKEY_LOCAL_MACHINE ), 

                        RKENTRY( HKEY_CURRENT_USER ), RKENTRY( HKEY_USERS ),

                        RKENTRY( HKEY_CLASSES_ROOT ),

                       };

        int nEntries = sizeof(RegKeys)/sizeof(RKEntry);

        // iterate the list of top level reg keys and dump each one

        for ( int i = 0; i < nEntries; i++ )

        {

            if ( (U_rwrite(fh, (PBYTE)RegKeys[i].psz, 

                           RegKeys[i].len) != RegKeys[i].len) ||

                 !DumpRegKey(RegKeys[i].hkey, fh) )

            {

                DbgOut("ERROR dumping key\r\n");

            }

        }

        U_rclose(fh);

    }

    return 0;

}





Listing Three

/* Example code to show how to programmatically pass cmds to CESH */

#include <windows.h>

#include <stdio.h>

#include <io.h>

#include <fcntl.h>



int main(int argc, char **argv)

{

    char szFSAUXIN[_MAX_PATH];

    char szCmd[_MAX_PATH] = {0};



    // catenate the cmd into a single string up to the max length

    if ( argc > 1 )

    {

        int iCurCmdLen = 0;

        for ( int i = 1; i < argc; i++ )

        {

            if ( (iCurCmdLen + strlen(argv[i]) + 2) > _MAX_PATH-1 )

            {

                printf("Error: cmd string is too long. "

                       "Max size is %d\n", _MAX_PATH-1);

                exit(EXIT_FAILURE);

            }

            sprintf(&szCmd[iCurCmdLen], "%s ", argv[i]);

            iCurCmdLen += strlen(argv[i]) + 1;

        }

        strcat(szCmd, "\r");

    }

    else

    {

        printf("syntax: ceshexec <cmd>\n");

        exit(EXIT_FAILURE);

    }

    // make sure we have a _FLATRELEASEDIR

    LPCSTR pcszFRD = getenv("_FLATRELEASEDIR");

    if ( !pcszFRD )

    {

        printf("Error: Environment variable "

               "_FLATRELEASEDIR must be set\n");

        exit(EXIT_FAILURE);

    }

    // build path to FSAUXIN, avoiding double slashes

    if ( pcszFRD[strlen(pcszFRD)-1] != '\\' )

        sprintf(szFSAUXIN, "%s\\fsauxin", pcszFRD);

    else

        sprintf(szFSAUXIN, "%sfsauxin", pcszFRD);

    int fh = open(szFSAUXIN,  _O_WRONLY | _O_APPEND);

    if ( fh != -1 )

    {

        write(fh, szCmd, strlen(szCmd));

        close(fh);

    }

    else

        printf("Error: could not open '%s'\n", szFSAUXIN);



    return 0;

}



Listing Four

/* Sample code to show how to get the IP and MAC address of the 

desktop machine connected via Ethernet to CESH */

#include <windows.h>

#include "ethdbg.h"

#include "halether.h"



int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

                    LPWSTR lpCmdLine, int nCmdShow)

{

    IP_INFO IpInfo;

    DWORD dwAddrType;

    DWORD dwLen = 0;



    dwAddrType = IPINFO_DOWNLOAD;

    memset(&IpInfo, 0, sizeof(IpInfo));

    if (KernelIoControl(IOCTL_HAL_GET_IP_ADDR, &dwAddrType, sizeof(dwAddrType),

                        &IpInfo, sizeof(IpInfo), &dwLen))

    {

        if ( IpInfo.dwIP == 0 )

        {

            NKDbgPrintfW(L"No peer address information available.  "

                       "Probably connected over a parallel port " "link\n");

        }

        else

        {

            NKDbgPrintfW(L"CESH peer address info: IP:%hs, "

                          "MAC:0x%02X:%02X:%02X:%02X:%02X:%02X\n",

                         inet_ntoa(IpInfo.dwIP),IpInfo.MAC[0],

                         IpInfo.MAC[1],IpInfo.MAC[2], IpInfo.MAC[3],

                         IpInfo.MAC[4],IpInfo.MAC[5]);

        }

    }

    else

        NKDbgPrintfW(L"Error getting peer address info: %u\n",

                     GetLastError());

    return 0;

}











7



