예제 #1
0
PBYTE WINAPI duWindowManager::GetZipResource(LPCTSTR lpszResName, HANDLE &hMem, IStream *&pStream)
{
	if (lpszResName == NULL || m_hZip == NULL)
		return NULL;
	
	TCHAR szDir[1024];
	_tcsncpy(szDir, lpszResName, MAX_PATH);
	
	TCHAR *lpStartChar = szDir; 
	TCHAR *lpChar = _tcschr(lpStartChar, '\\');
	while (lpChar)
	{
		*lpChar = 0;
		if (SetUnzipBaseDir(m_hZip, lpStartChar) != ZR_OK)
			return NULL;
		
		lpChar++;
		lpStartChar = lpChar;
		lpChar = _tcschr(lpStartChar, '\\');
	}

	_tcsncpy(szDir, lpszResName, MAX_PATH);
	lpChar = szDir;
	while (*lpChar)
	{
		if (*lpChar == '\\') 
			*lpChar = '/';
		lpChar++;
	}
	
	int nIndex = 0;
	ZIPENTRY ze;
	if (FindZipItem(m_hZip, szDir, true, &nIndex, &ze) != ZR_OK || nIndex == -1)
		return NULL;
	
	hMem = ::GlobalAlloc(GMEM_FIXED, ze.unc_size);
	::CreateStreamOnHGlobal(hMem, FALSE, &pStream);
	if (pStream == NULL)
	{
		::GlobalFree(hMem);
		hMem = NULL;
		return NULL;
	}

	PBYTE pByte = (PBYTE)::GlobalLock(hMem);
	if (UnzipItem(m_hZip, nIndex, pByte, ze.unc_size) != ZR_OK)
	{
		pStream->Release();
		pStream = NULL;
		
		::GlobalFree(hMem);
		hMem = NULL;
		return NULL;
	}
	
	SetUnzipBaseDir(m_hZip, _T(""));
	return pByte;
}
예제 #2
0
파일: ZipObj.cpp 프로젝트: jf4210/src2-test
bool CZipObj::UnZipFile(CString strZipPath, CString strUnzipPath)
{
	USES_CONVERSION;
	int nPos = strZipPath.ReverseFind('.');
	CString strPath = strZipPath.Left(nPos);		//.zip		strZipPath.GetLength() - 4
	if (strUnzipPath != "")
		strPath = strUnzipPath;
	std::string strUtf8Path = CMyCodeConvert::Gb2312ToUtf8(T2A(strPath));

	try
	{
		Poco::File p(strUtf8Path);	//T2A(strPath)
		if (p.exists())
			p.remove(true);
	}
	catch (Poco::Exception)
	{
	}
	
	HZIP hz = OpenZip(strZipPath, _strPwd.c_str());
	ZIPENTRY ze;
	GetZipItem(hz, -1, &ze);
	int numitems = ze.index;
	SetUnzipBaseDir(hz, strPath);
	for (int i = 0; i < numitems; i++)
	{
		GetZipItem(hz, i, &ze);
		UnzipItem(hz, i, ze.name);
	}
	CloseZip(hz);

	return true;
}
예제 #3
0
//
// Locks the currently loaded resource file and unzips it.
//  
// This function should only be used when the resource file
// is a zip file and you want to extract one or more files within it.
//
void DLLResourceManager::OpenMainResourceZipFile()
{
	void *zipbuf=LockResource(hglob);
	unsigned int ziplen=SizeofResource(handleToDll,hRsrc);
	hz = OpenZip(zipbuf, ziplen, 0);  
	SetUnzipBaseDir(hz,_T("\\"));
}
예제 #4
0
void CAppManager::ReloadRhoBundle(const char* szUrl, const char* szZipPassword)
{
	if ( szUrl )
	{
		//get zip file with rhodes
		DWORD dwDataSize = 0;
		char* zipData = remote_data( L"GET", const_cast<char*>(szUrl), NULL, 0, false, true, false, &dwDataSize );

		LPWSTR rootw = wce_mbtowc(RhoGetRootPath());  

		//TODO: Add error handling
		if ( zipData && dwDataSize > 0 )
		{
			ZIPENTRY ze; 
			// Open zip file
			HZIP hz = OpenZip(zipData, dwDataSize, szZipPassword);
			
			if ( hz )
			{
				//Stop HTTP Server
				CHttpServer::Instance()->FreezeThread();

				// Set base for unziping
				SetUnzipBaseDir(hz, rootw);
				
				// Get info about the zip
				// -1 gives overall information about the zipfile
				GetZipItem(hz,-1,&ze);
				int numitems = ze.index;
				
				// Iterate through items and unzip them
				for (int zi = 0; zi<numitems; zi++)
				{ 
					// fetch individual details, e.g. the item's name.
					GetZipItem(hz,zi,&ze); 
					// unzip item
					UnzipItem(hz, zi, ze.name);         
				}
				
				CloseZip(hz);

				//Show MessageBox
				MessageBox(NULL, _T("Rhobundle has been updated successfully.\n\nPlease restart application."), _T("Information"), MB_OK | MB_ICONINFORMATION );
			}
		}

		if ( rootw )
			free(rootw);

		if ( zipData )
			delete zipData;
	}
}
예제 #5
0
int rho_unzip_file(const char* szZipPath)
{
#ifdef  UNICODE
    rho::StringW strZipPathW;
    rho::common::convertToStringW(szZipPath, strZipPathW);
    HZIP hz = OpenZipFile(strZipPathW.c_str(), "");
    if ( !hz )
        return 0;

	// Set base for unziping
    SetUnzipBaseDir(hz, rho::common::convertToStringW(RHODESAPPBASE().getDBDirPath()).c_str() );
#else
    HZIP hz = OpenZipFile(szZipPath, "");
    if ( !hz )
        return 0;

	// Set base for unziping
    SetUnzipBaseDir(hz, RHODESAPPBASE().getDBDirPath().c_str() );
#endif

    ZIPENTRY ze;
    ZRESULT res = 0;
	// Get info about the zip
	// -1 gives overall information about the zipfile
	res = GetZipItem(hz,-1,&ze);
	int numitems = ze.index;

	// Iterate through items and unzip them
	for (int zi = 0; zi<numitems; zi++)
	{ 
		// fetch individual details, e.g. the item's name.
		res = GetZipItem(hz,zi,&ze); 
        if ( res == ZR_OK )
    		res = UnzipItem(hz, zi, ze.name);         
	}

	CloseZip(hz);

    return res == ZR_OK ? 1 : 0;
}
예제 #6
0
파일: DlgView.cpp 프로젝트: SoyPay/DacrsUI
bool CDlgView::UnZipFile(string unzipfilename,string zipfilepath)
{
    HZIP hz; //DWORD writ;

    // EXAMPLE 2 - unzip it with the names suggested in the zip
    hz = OpenZip(unzipfilename.c_str(),0);
    string path = zipfilepath +"\\";
    SetUnzipBaseDir(hz,path.c_str());
    ZIPENTRY ze;
    GetZipItem(hz,-1,&ze);
    int numitems=ze.index;
    for (int zi=0; zi<numitems; zi++)
    {   GetZipItem(hz,zi,&ze);
        UnzipItem(hz,zi,ze.name);
    }
    CloseZip(hz);
    return true;
}
예제 #7
0
bool CZip::extract(const QString & filePath, const QString & extDirPath, const QString & singleFileName, const QString &password)
{
    HZIP hz = OpenZip(filePath.toStdString().c_str(), password.isEmpty() ? 0 : password.toStdString().c_str());

    if(!hz) {
        return false;
    }

    SetUnzipBaseDir(hz,extDirPath.toStdString().c_str());

    if (!singleFileName.isEmpty())
    {
        ZIPENTRY ze;
        int i; 
        FindZipItem(hz, singleFileName.toStdString().c_str(), true, &i, &ze);
        UnzipItem(hz, i, ze.name);
        CloseZip(hz);

        return true;
    }

    for (int i = 0; ;i++)
    { 
        ZIPENTRY ze;
        ZRESULT zr = GetZipItem(hz, i, &ze); 

        if (zr != ZR_OK) {

            if(zr == ZR_FAILED || zr == ZR_NOTFOUND) {
                CloseZip(hz);
                return false;
            }

            break; // no more
        }
        UnzipItem(hz, i, ze.name);
    }

    CloseZip(hz);

    return true;
}
예제 #8
0
	void FileUtils::Unzip(std::string& source, std::string& destination, 
		UnzipCallback callback, void *data)
	{
		std::wstring wideSource = UTILS_NS::UTF8ToWide(source);
		std::wstring wideDestination = UTILS_NS::UTF8ToWide(destination);

		HZIP handle = OpenZip(wideSource.c_str(), 0);
		SetUnzipBaseDir(handle, wideDestination.c_str());

		ZIPENTRY zipEntry; ZeroMemory(&zipEntry, sizeof(ZIPENTRY));

		GetZipItem(handle, -1, &zipEntry);
		int numItems = zipEntry.index;
		if (callback != NULL)
		{ 
			std::ostringstream message;
			message << "Starting extraction of " << numItems 
				<< " items from " << source << "to " << destination;
			std::string messageString = message.str();
			callback((char*) messageString.c_str(), 0, numItems, data);
		}
		
		for (int zi = 0; zi < numItems; zi++) 
		{ 
			ZeroMemory(&zipEntry, sizeof(ZIPENTRY));
			GetZipItem(handle, zi, &zipEntry);
			
			if (callback != NULL)
			{
				std::string name = WideToUTF8(zipEntry.name);
				std::string message = "Extracting ";
				message.append(name);
				message.append("...");
				callback((char*) message.c_str(), zi, numItems, data);
			}
			
			UnzipItem(handle, zi, zipEntry.name);
		}
		CloseZip(handle);
	}
예제 #9
0
DWORD WINAPI decompress(LPVOID lpParam)
{	
	//Open struct and set variables
	PMYDATA pDataArray = (PMYDATA)lpParam;				//Open the struct
	char *infilename = pDataArray -> para_infilename;	//Get input file name
	char *outfilename = pDataArray -> para_outfilename;	//Get output file name
	char *password = pDataArray -> para_password;		//Get password
	LPRDATA rdPtr = pDataArray -> para_rdPtr;			//Get rdPtr
	
	//Set non-struct variables & begin extraction
	HZIP hz = OpenZip(infilename,0); //0 = no password
	SetUnzipBaseDir(hz,outfilename); //Set the extract-to folder
	ZIPENTRY baseze;
	ZRESULT zr = GetZipItem(hz,-1,&baseze); //ZRESULT zr contains error number.

	//This part may get complicated.
	//No error with no password, so just extract
	for (int zi=0; zi<baseze.index; zi++)
	{
		ZIPENTRY ze;
		GetZipItem(hz,zi,&ze);			// fetch individual details
		zr=UnzipItem(hz, zi, ze.name);	// e.g. the item's name.
	}
	CloseZip(hz);
	if (zr==ZR_OK)
	{
		rdPtr->rRd->PushEvent(0);
		NoCurrentCompression=true;
		PasswordBeingUsed=false;
	}
	else
	{ //Error occured when extracting with no password
		if (zr==ZR_PASSWORD&&password!="0")
		{ //ZR_PASSWORD -> invalid password. So try with password, if one is provided.
			zr = ZR_OK;
			CloseZip(hz);
			hz = OpenZip(infilename,password);
			GetZipItem(hz,-1,&baseze);
			NumberOfFilesExtracted=baseze.index;
			MessageBox(NULL,"zr==ZR_PASSWORD&&password!=\"0\"", "Debug", NULL);
			PasswordBeingUsed=true;
			
			//No error when extracting with given password, so just extract.
			for (int zi=0; zi<baseze.index; zi++)
			{	//I Can Haz Stallage
				ZIPENTRY ze;
				GetZipItem(hz,zi,&ze);			// fetch individual details
				zr=UnzipItem(hz, zi, ze.name);	// e.g. the item's name.
			}
			CloseZip(hz);
			NoCurrentCompression=true;
			if (zr==ZR_OK)
			{
				rdPtr->rRd->PushEvent(0);
				MessageBox(NULL,"zr==ZR_PASSWORD&&password!=\"0\" > zr==ZR_OK", "Debug", NULL);
			}
			else
			{
				if (zr==ZR_PASSWORD)
				{ //The password provided was wrong, so report it.
					returnstring="Password incorrect or required.";
					MessageBox(NULL,"zr==ZR_PASSWORD&&password!=\"0\" > zr==ZR_PASSWORD", "Debug", NULL);
					rdPtr->rRd->PushEvent(1);
				}
				else
				{ //Password was correct but error occured anyway
					MessageBox(NULL,"zr==ZR_PASSWORD&&password!=\"0\" > zr!=ZR_PASSWORD", "Debug", NULL);
					stringstream temp; 
					temp<<"An error occured, but the provided password was correct. Error number "<<zr<<".";
					returnstring=temp.str();
					NoCurrentCompression=true;
					rdPtr->rRd->PushEvent(1);
				}
			}
		}
		else
		{ //Not a password error when we tried to open without a password...
			stringstream temp; 
			temp<<"An error occured - not a password error. Error number "<<zr<<".";
			returnstring=temp.str();
			NoCurrentCompression=true;
			rdPtr->rRd->PushEvent(1);
		}
	}
	//FormatZipMessage(zr,LastFileExtracted,sizeof(LastFileExtracted));
	return 0;
}
예제 #10
0
int CUpdateRunner::ExtractUpdaterAndRun(wchar_t* lpCommandLine)
{
	PROCESS_INFORMATION pi = { 0 };
	STARTUPINFO si = { 0 };
	CResource zipResource;
	wchar_t targetDir[MAX_PATH];
	wchar_t logFile[MAX_PATH];
	std::vector<CString> to_delete;

	ExpandEnvironmentStrings(L"%LocalAppData%\\SquirrelTemp", targetDir, _countof(targetDir));
	if (!CreateDirectory(targetDir, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) {
		goto failedExtract;
	}

	swprintf_s(logFile, L"%s\\SquirrelSetup.log", targetDir);

	if (!zipResource.Load(L"DATA", IDR_UPDATE_ZIP)) {
		goto failedExtract;
	}

	DWORD dwSize = zipResource.GetSize();
	if (dwSize < 0x100) {
		goto failedExtract;
	}

	BYTE* pData = (BYTE*)zipResource.Lock();
	HZIP zipFile = OpenZip(pData, dwSize, NULL);
	SetUnzipBaseDir(zipFile, targetDir);

	// NB: This library is kind of a disaster
	ZRESULT zr;
	int index = 0;
	do {
		ZIPENTRY zentry;
		wchar_t targetFile[MAX_PATH];

		zr = GetZipItem(zipFile, index, &zentry);
		if (zr != ZR_OK && zr != ZR_MORE) {
			break;
		}

		// NB: UnzipItem won't overwrite data, we need to do it ourselves
		swprintf_s(targetFile, L"%s\\%s", targetDir, zentry.name);
		DeleteFile(targetFile);

		if (UnzipItem(zipFile, index, zentry.name) != ZR_OK) break;
		to_delete.push_back(CString(targetFile));
		index++;
	} while (zr == ZR_MORE || zr == ZR_OK);

	CloseZip(zipFile);
	zipResource.Release();

	// nfi if the zip extract actually worked, check for Update.exe
	wchar_t updateExePath[MAX_PATH];
	swprintf_s(updateExePath, L"%s\\%s", targetDir, L"Update.exe");

	if (GetFileAttributes(updateExePath) == INVALID_FILE_ATTRIBUTES) {
		goto failedExtract;
	}

	// Run Update.exe
	si.cb = sizeof(STARTUPINFO);
	si.wShowWindow = SW_SHOW;
	si.dwFlags = STARTF_USESHOWWINDOW;

	if (!lpCommandLine || wcsnlen_s(lpCommandLine, MAX_PATH) < 1) {
		lpCommandLine = L"--install .";
	}

	wchar_t cmd[MAX_PATH];
	swprintf_s(cmd, L"%s %s", updateExePath, lpCommandLine);

	if (!CreateProcess(NULL, cmd, NULL, NULL, false, 0, NULL, targetDir, &si, &pi)) {
		goto failedExtract;
	}

	WaitForSingleObject(pi.hProcess, INFINITE);

	DWORD dwExitCode;
	if (!GetExitCodeProcess(pi.hProcess, &dwExitCode)) {
		dwExitCode = (DWORD)-1;
	}

	if (dwExitCode != 0) {
		DisplayErrorMessage(CString(
			L"There was an error while installing the application. " 
			L"Check the setup log for more information and contact the author."), logFile);
	}

	for (unsigned int i = 0; i < to_delete.size(); i++) {
		DeleteFile(to_delete[i]);
	}

	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);
	return (int) dwExitCode;

failedExtract:
	DisplayErrorMessage(CString(L"Failed to extract installer"), NULL);
	return (int) dwExitCode;
}
예제 #11
0
void main()
{ CreateFiles();
  HZIP hz; DWORD writ;

  // EXAMPLE 1 - create a zipfile from existing files
  hz = CreateZip(_T("\\simple1.zip"),0);
  ZipAdd(hz,_T("znsimple.bmp"), _T("\\simple.bmp"));
  ZipAdd(hz,_T("znsimple.txt"), _T("\\simple.txt"));
  CloseZip(hz);
  _tprintf(_T("Created '\\simple1.zip'\n"));


  // EXAMPLE 2 - unzip it with the names suggested in the zip
  hz = OpenZip(_T("\\simple1.zip"),0);
  SetUnzipBaseDir(hz,_T("\\"));
  ZIPENTRY ze; GetZipItem(hz,-1,&ze); int numitems=ze.index;
  for (int zi=0; zi<numitems; zi++)
  { GetZipItem(hz,zi,&ze);
    UnzipItem(hz,zi,ze.name);
  }
  CloseZip(hz);
  _tprintf(_T("Unzipped 'znsimple.bmp' and 'znsimple.txt' from 'simple1.zip'\n"));



  // EXAMPLE 3 - create an auto-allocated pagefile-based zip file from various sources
  // the second argument says how much address space to reserve for it. We can
  // afford to be generous: no address-space is allocated unless it's actually needed.
  hz = CreateZip(0,100000,"password");
  // adding a conventional file...
  ZipAdd(hz,_T("znsimple.txt"),  _T("\\simple.txt"));
  // adding something from memory...
  char buf[1000]; for (int zj=0; zj<1000; zj++) buf[zj]=(char)(zj&0x7F);
  ZipAdd(hz,_T("simple.dat"),  buf,1000);
  // adding something from a pipe...
#ifndef UNDER_CE
  HANDLE hread,hwrite; CreatePipe(&hread,&hwrite,NULL,0);
  DWORD WINAPI Ex3ThreadFunc(void *dat);
  HANDLE hthread = CreateThread(0,0,Ex3ThreadFunc,(void*)hwrite,0,0);
  ZipAddHandle(hz,_T("simple3.dat"),  hread,1000);  // the '1000' is optional, but it makes for nicer zip files if sizes are known in advance.
  WaitForSingleObject(hthread,INFINITE);
  CloseHandle(hthread); CloseHandle(hread); // the thread will close hwrite
#endif
  //
  // and now that the zip is created in pagefile, let's do something with it:
  void *zbuf; unsigned long zlen; ZipGetMemory(hz,&zbuf,&zlen);
  HANDLE hfz = CreateFile(_T("\\simple3 - pwd is 'password'.zip"),GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
  WriteFile(hfz,zbuf,zlen,&writ,NULL);
  CloseHandle(hfz);
  CloseZip(hz);
  _tprintf(_T("Created 'simple3.zip' via pagefile\n"));


  // EXAMPLE 4 - unzip directly from resource into a file
  // resource RT_RCDATA/#1 happens to be a zip file...
  HINSTANCE hInstance=GetModuleHandle(0);
  HRSRC hrsrc = FindResource(hInstance,MAKEINTRESOURCE(1),RT_RCDATA);
  HANDLE hglob = LoadResource(hInstance,hrsrc);
  void *zipbuf=LockResource(hglob);
  unsigned int ziplen=SizeofResource(hInstance,hrsrc);
  hz = OpenZip(zipbuf, ziplen, 0);  SetUnzipBaseDir(hz,_T("\\"));
  int i; FindZipItem(hz,_T("simple.jpg"),true,&i,&ze);
  //   - unzip to a file -
  UnzipItem(hz,i,ze.name);
  //   - unzip to a membuffer -
  char *ibuf = new char[ze.unc_size];
  UnzipItem(hz,i, ibuf, ze.unc_size);
  delete[] ibuf;
  //   - unzip to a fixed membuff, bit by bit -
  char fbuf[1024]; ZRESULT zr=ZR_MORE; unsigned long totsize=0;
  while (zr==ZR_MORE)
  { zr = UnzipItem(hz,i, fbuf,1024);
    unsigned long bufsize=1024; if (zr==ZR_OK) bufsize=ze.unc_size-totsize;
    // now do something with this chunk which we just unzipped...
    totsize+=bufsize;
  }
  //   - finished -
  CloseZip(hz);
  // note: no need to free resources obtained through Find/Load/LockResource
  _tprintf(_T("Unzipped 'simple.jpg' from resource zipfile\n"));


  
  DeleteFile(_T("\\simple.txt"));
  DeleteFile(_T("\\simple.bmp"));
  _tprintf(_T("Deleted 'simple.txt' and 'simple.bmp'\n"));
}
예제 #12
0
int CUpdateRunner::ExtractUpdaterAndRun(wchar_t* lpCommandLine, bool useFallbackDir)
{
	PROCESS_INFORMATION pi = { 0 };
	STARTUPINFO si = { 0 };
	CResource zipResource;
	wchar_t targetDir[MAX_PATH];
	wchar_t logFile[MAX_PATH];
	std::vector<CString> to_delete;

	if (!useFallbackDir) {
		SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, targetDir);
	} else {
		wchar_t username[512];
		wchar_t uid[128];
		wchar_t appDataDir[MAX_PATH];
		ULONG unameSize = _countof(username);

		SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, appDataDir);
		GetUserName(username, &unameSize);
		DWORD lastError = GetLastError();

		_swprintf_c(targetDir, _countof(targetDir), L"%s\\%s", appDataDir, username);

		if (!CreateDirectory(targetDir, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) {
			wchar_t err[4096];
			_swprintf_c(err, _countof(err), L"Unable to write to %s - IT policies may be restricting access to this folder", targetDir);
			DisplayErrorMessage(CString(err), NULL);

			return -1;
		}
	}

	wcscat_s(targetDir, _countof(targetDir), L"\\SquirrelTemp");

	if (!CreateDirectory(targetDir, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) {
		wchar_t err[4096];
		_swprintf_c(err, _countof(err), L"Unable to write to %s - IT policies may be restricting access to this folder", targetDir);

		if (useFallbackDir) {
			DisplayErrorMessage(CString(err), NULL);
		}

		goto failedExtract;
	}

	swprintf_s(logFile, L"%s\\SquirrelSetup.log", targetDir);

	if (!zipResource.Load(L"DATA", IDR_UPDATE_ZIP)) {
		goto failedExtract;
	}

	DWORD dwSize = zipResource.GetSize();
	if (dwSize < 0x100) {
		goto failedExtract;
	}

	BYTE* pData = (BYTE*)zipResource.Lock();
	HZIP zipFile = OpenZip(pData, dwSize, NULL);
	SetUnzipBaseDir(zipFile, targetDir);

	// NB: This library is kind of a disaster
	ZRESULT zr;
	int index = 0;
	do {
		ZIPENTRY zentry;
		wchar_t targetFile[MAX_PATH];

		zr = GetZipItem(zipFile, index, &zentry);
		if (zr != ZR_OK && zr != ZR_MORE) {
			break;
		}

		// NB: UnzipItem won't overwrite data, we need to do it ourselves
		swprintf_s(targetFile, L"%s\\%s", targetDir, zentry.name);
		DeleteFile(targetFile);

		if (UnzipItem(zipFile, index, zentry.name) != ZR_OK) break;
		to_delete.push_back(CString(targetFile));
		index++;
	} while (zr == ZR_MORE || zr == ZR_OK);

	CloseZip(zipFile);
	zipResource.Release();

	// nfi if the zip extract actually worked, check for Update.exe
	wchar_t updateExePath[MAX_PATH];
	swprintf_s(updateExePath, L"%s\\%s", targetDir, L"Update.exe");

	if (GetFileAttributes(updateExePath) == INVALID_FILE_ATTRIBUTES) {
		goto failedExtract;
	}

	// Run Update.exe
	si.cb = sizeof(STARTUPINFO);
	si.wShowWindow = SW_SHOW;
	si.dwFlags = STARTF_USESHOWWINDOW;

	if (!lpCommandLine || wcsnlen_s(lpCommandLine, MAX_PATH) < 1) {
		lpCommandLine = L"";
	}

	wchar_t cmd[MAX_PATH];
	swprintf_s(cmd, L"\"%s\" --install . %s", updateExePath, lpCommandLine);

	if (!CreateProcess(NULL, cmd, NULL, NULL, false, 0, NULL, targetDir, &si, &pi)) {
		goto failedExtract;
	}

	WaitForSingleObject(pi.hProcess, INFINITE);

	DWORD dwExitCode;
	if (!GetExitCodeProcess(pi.hProcess, &dwExitCode)) {
		dwExitCode = (DWORD)-1;
	}

	if (dwExitCode != 0) {
		DisplayErrorMessage(CString(
			L"There was an error while installing the application. " 
			L"Check the setup log for more information and contact the author."), logFile);
	}

	for (unsigned int i = 0; i < to_delete.size(); i++) {
		DeleteFile(to_delete[i]);
	}

	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);
	return (int) dwExitCode;

failedExtract:
	if (!useFallbackDir) {
		// Take another pass at it, using C:\ProgramData instead
		return ExtractUpdaterAndRun(lpCommandLine, true);
	}

	DisplayErrorMessage(CString(L"Failed to extract installer"), NULL);
	return (int) dwExitCode;
}