static LPWSTR get_directory_from_user() { WCHAR name[MAX_PATH+1] = {0}; LPWSTR path = NULL; PIDLIST_ABSOLUTE ret; path = (LPWSTR)calloc(2*MAX_PATH, sizeof(WCHAR)); if (path == NULL) { show_error(L"Out of memory"); return NULL; } int image = 0; BROWSEINFO bi = { NULL, NULL, name, L"Select the folder where you want to install or update Calibre Portable", BIF_RETURNONLYFSDIRS | BIF_DONTGOBELOWDOMAIN | BIF_USENEWUI, NULL, NULL, image }; ret = SHBrowseForFolder(&bi); if (ret == NULL) { return NULL; } if (!SHGetPathFromIDList(ret, path)) { show_detailed_error(L"The selected folder is not valid: ", name, 0); return NULL; } return path; }
static BOOL decompress(LPVOID src, DWORD src_sz, HANDLE out, IProgressDialog *pd) { elzma_decompress_handle h; struct DataStream ds; int rc; h = elzma_decompress_alloc(); if (h == NULL) { show_error(L"Out of memory"); return false; } ds.in_data = (unsigned char*)src; ds.in_len = src_sz; ds.out = out; ds.pd = pd; rc = elzma_decompress_run(h, input_callback, (void *) &ds, output_callback, (void *) &ds, ELZMA_lzip); if (rc != ELZMA_E_OK) { if (!output_error_shown) show_detailed_error(L"Failed to decompress portable data", L"", rc); elzma_decompress_free(&h); return false; } elzma_decompress_free(&h); return true; }
void show_last_error_crt(LPCTSTR preamble) { TCHAR buf[BUFSIZE]; int err = 0; _get_errno(&err); _tcserror_s(buf, BUFSIZE, err); show_detailed_error(preamble, buf, err); }
void show_last_error(LPCTSTR preamble) { TCHAR *msg = NULL; DWORD dw = GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&msg, 0, NULL ); show_detailed_error(preamble, msg, (int)dw); }
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) { LPVOID cdata = NULL; DWORD csz = 0; int ret = 0, argc; HRESULT hr; LPWSTR tgt = NULL, dest = NULL, *argv, unpack_dir = NULL; BOOL existing = false, launch = false, automated = false; WCHAR buf[4*MAX_PATH] = {0}, mb_msg[4*MAX_PATH] = {0}, fdest[4*MAX_PATH] = {0}; if (!load_data(&cdata, &csz)) return 0; hr = CoInitialize(NULL); if (FAILED(hr)) { show_error(L"Failed to initialize COM"); return 0; } // Get the target directory for installation argv = CommandLineToArgvW(GetCommandLine(), &argc); if (argv == NULL) { show_last_error(L"Failed to get command line"); return 0; } if (argc > 1) { tgt = argv[1]; automated = true; } else { tgt = get_directory_from_user(); if (tgt == NULL) goto end; } if (!directory_exists(tgt)) { show_detailed_error(L"The specified directory does not exist: ", tgt, 1); goto end; } // Ensure the path to Calibre Portable is not too long do { if (!find_portable_dir(tgt, &dest, &existing)) goto end; if (GetFullPathName(dest, MAX_PATH*4, fdest, NULL) == 0) { show_last_error(L"Failed to resolve target folder"); goto end; } free(dest); dest = NULL; if (wcslen(fdest) > 58) { _snwprintf_s(buf, 4*MAX_PATH, _TRUNCATE, L"Path to Calibre Portable (%s) too long. Must be less than 59 characters.", fdest); if (!existing) RemoveDirectory(fdest); show_error(buf); tgt = get_directory_from_user(); if (tgt == NULL) goto end; } } while (wcslen(fdest) > 58); // Confirm the user wants to upgrade if (existing && !automated) { _snwprintf_s(mb_msg, 4*MAX_PATH, _TRUNCATE, L"An existing install of Calibre Portable was found at %s. Do you want to upgrade it?", fdest); if (MessageBox(NULL, mb_msg, L"Upgrade Calibre Portable?", MB_ICONEXCLAMATION | MB_YESNO | MB_TOPMOST) != IDYES) goto end; } if (existing) { if (!ensure_not_running(fdest)) goto end; } // Make a temp dir to unpack into if (!SetCurrentDirectoryW(fdest)) { show_detailed_error(L"Failed to change to unzip directory: ", fdest, 0); goto end; } if ( (unpack_dir = make_unpack_dir()) == NULL ) goto end; if (!SetCurrentDirectoryW(unpack_dir)) { show_detailed_error(L"Failed to change to unpack directory: ", fdest, 0); goto end; } // Extract files if (!extract(cdata, csz)) goto end; // Move files from temp dir to the install dir if (!move_program()) goto end; _snwprintf_s(mb_msg, 4*MAX_PATH, _TRUNCATE, L"Calibre Portable successfully installed to %s. Launch calibre?", fdest); launch = MessageBox(NULL, mb_msg, L"Success", MB_ICONINFORMATION | MB_YESNO | MB_TOPMOST) == IDYES; end: if (unpack_dir != NULL) { SetCurrentDirectoryW(L".."); rmtree(unpack_dir); free(unpack_dir); } CoUninitialize(); if (launch) launch_calibre(); return 0; }