[Windows Phone 7 Development and Hacking] Martin7Pro:
Simple batch line interpreter

I tried cmd.exe batch and arguments calling, but it seems does not working for me. Then I will try own attempt.

Single batch line interpreter (*.bat files interpreting precursor):

SHLine.cpp

// SHLine.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
//#include <atlstr.h>

/*CString*/
#ifdef _DEBUG
#pragma comment (lib, "libcmtd.lib")
#else
#pragma comment (lib, "libcmt.lib")
#endif
/*CString*/

#include <list>
using namespace std;
typedef list<CString> StringList;

#define SEE_MASK_NOASYNC (0x00000100)

CString ErrorString(DWORD err)
{
CString Error;
try
{
LPTSTR s;
if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,	err, 0,	(LPTSTR)&s, 0, NULL) == 0)
{
Error.AppendFormat(TEXT("Error code : %X"), err);
} /* failed */
else
{ /* success */
LPTSTR p = _tcschr(s, _T('\r'));
if(p != NULL)
{ /* lose CRLF */
*p = _T('\0');
} /* lose CRLF */
Error = s;
::LocalFree(s);
} /* success */
return Error;
}
catch (...)
{
Error.AppendFormat(TEXT("Error code : %X"), err);
return Error;
}
}

HRESULT ShellExecuteWait(const wchar_t * file, const wchar_t * args, long lTimeout)
{
TRACE(L"ShellExecuteWait file=%s, args=%s, long lTimeout=%X\n", file, args, lTimeout);
try
{

SHELLEXECUTEINFO lpExecInfo;
memset(&lpExecInfo, 0, sizeof(SHELLEXECUTEINFO));
lpExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
lpExecInfo.lpFile = file;
lpExecInfo.lpParameters = args;
lpExecInfo.lpDirectory = _T("");
lpExecInfo.lpVerb = _T("open");
lpExecInfo.nShow = SW_MINIMIZE;
lpExecInfo.fMask = 0;
lpExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NOASYNC;// | SEE_MASK_FLAG_DDEWAIT;//0;	lpExecInfo.hwnd = NULL;
lpExecInfo.hInstApp = NULL;//AfxGetInstanceHandle();
if(!ShellExecuteEx(&lpExecInfo))
{
DWORD err = GetLastError();
TRACE(L"ShellExecuteEx Error %d %s\n", err, ErrorString(err));
///	Sleep(100);
return (HRESULT)err;//ERROR_SUCCESS;

}
if (lpExecInfo.hProcess > 0)
{
TRACE(L"ShellExecuteEx WaitForSingleObject hProcess=%X\n", lpExecInfo.hProcess);

DWORD res = ::WaitForSingleObject(lpExecInfo.hProcess, lTimeout/*INFINITE*/);//5000);

TRACE(L"WaitForSingleObject lTimeout=%X, res=%X\n", lTimeout, res);
///	Sleep(100);
if (lTimeout != INFINITE && res != WAIT_OBJECT_0)
{
TerminateProcess(lpExecInfo.hProcess, 0);
TRACE(L"TerminateProcess;\n");
}
CloseHandle(lpExecInfo.hProcess);
}
TRACE(L"return ERROR_SUCCESS;\n");
return ERROR_SUCCESS;
}
catch (...)
{
DWORD err = 0x80070000 | GetLastError();
MessageBox(NULL, ErrorString(err), _T("ShellExecuteWait Error"), MB_OK);
return ERROR_SUCCESS;//(HRESULT)err;

}
}

StringList GetPathList(StringList & slPathList)
{
slPathList.clear();
slPathList.push_front(L"Program Files"); // Only for testing. HKCU\Environment PATH value will splitted instead;
slPathList.push_front(L"My Documents");

return slPathList;
}

CString GetCurrentDirectory(CString & csCurDir)
{
csCurDir = L"Program Files\\SHLine"; // Only for testing. HKCU\Environment CurrentDirectory value will readed instead;
return csCurDir;
}

bool FileExists(const wchar_t * file)
{
WIN32_FIND_DATA FindFileData;
HANDLE hFile = ::FindFirstFile(file, &FindFileData) ;
bool bFound = (hFile && (hFile != INVALID_HANDLE_VALUE));
if(bFound)
{
::FindClose(hFile);
}
return bFound;
}

int _tmain(int argc, _TCHAR* argv[])
{
TRACE(L"_tmain(int argc=%d);\n", argc);
if (argc > 1 && argv[1])
{
CString csRunPath = argv[1];
CString csRunArgs = L"";
if (argc > 2 && argv[2])
{
csRunArgs = argv[2];
for (int i = 3; i <= argc; i++)
{
if (argv[i])
{
csRunArgs = csRunArgs + L" " + argv[i];
}
}
}

CString csCurDir;
GetCurrentDirectory(csCurDir);

HRESULT hRes = ERROR_FILE_NOT_FOUND;
CString csFN = L"\\"+csCurDir+L"\\"+csRunPath/*.GetString()*/;
if (FileExists(csFN))
{
hRes = ShellExecuteWait(csFN, csRunArgs/*.GetString()*/, 60000);
}
if (hRes == ERROR_FILE_NOT_FOUND)
{
csFN = L"\\"+csRunPath;
CString csWin = L"\\Windows\\"+csRunPath;
if (FileExists(csFN) || FileExists(csWin))
{
hRes = ShellExecuteWait(csFN, csRunArgs, 60000); // Full path specified or file is known for CE Shell (included to \\Windows\ directory)
}
if (hRes == ERROR_FILE_NOT_FOUND)
{
StringList slPathList;
GetPathList(slPathList);
DWORD dwPath = 0;
for (StringList::iterator itPath = slPathList.begin(); itPath != slPathList.end(); ++itPath)
{
csFN = L"\\"+*itPath+L"\\"+csRunPath;
if (FileExists(csFN))
{
hRes = ShellExecuteWait(csFN, csRunArgs, 60000);
}
}
}
}
TRACE(L"_tmain returns 0x%X;\n", hRes);
return hRes;
}
TRACE(L"_tmain returns E_INVALIDARG;\n");
return E_INVALIDARG;
}

This interpret will be uploaded to \Windows directory to be used by any appplication. One can be batch files interpreter (call this shell with all lines as paramters), or do any controlling (lines can contain controlling directives as cycles etc.). The .bat extension registering is soluted by CE standard way on unlocked phones.

CD.exe, DIR.exe, ..., etc programs will add standard shell functionality. Output (directories listing etc.) will soluted by stdout file forwarding.

In this way one only shell interpreting application (one current directory only) will allowed immeditelly. Better something then nothing.

EDIT:

I have got batch interpreter working. But, very strange behaviour occures:

1. AygShell does not add exe extension automatically. Then I copied "copy.exe" to "\Windows\copy" etc. It works well. But, it does not work for "start" directive! Start is necessary for Iexplore and other "uncloseable" applications launching to prevent interpreter hanging up. It is interesting too "start.exe" (or "start") everytime renames automatically to "Start" with upcased first letter. Probably "\Windows\Start.html" causes this system behaviour.

2. std::list iterating for multi batch lines interpreting crashes everytime, when lauchched application contains any messagebox. Iterating replacing by numerous cyclus soles it. Unbelievable...

I will publish XAP as soon as. Any filemanager can be used for batch lauching after instllation. I recommend Phone Commander, which is able not only launch, but also edit *.bat files.