void syscreate(void) { char file[1024]; int n; ulong mode, name, perm; name = getmem_w(reg.r[REGSP]+4); mode = getmem_w(reg.r[REGSP]+8); perm = getmem_w(reg.r[REGSP]+12); memio(file, name, sizeof(file), MemReadstring); if(sysdbg) itrace("create(0x%lux='%s', 0x%lux, 0x%lux)", name, file, mode, perm); n = create(file, mode, perm); if(n < 0) errstr(errbuf, sizeof errbuf); reg.r[REGRET] = n; }
void sys_fstat(void) { char buf[ODIRLEN]; extern int _fstat(int, char*); /* old system call */ uint32_t edir; int n, fd; fd = getmem_w(reg.r[13]+4); edir = getmem_w(reg.r[13]+8); if(sysdbg) itrace("fstat(%d, 0x%lux)", fd, edir); n = _fstat(fd, buf); if(n < 0) errstr(errbuf, sizeof errbuf); else memio(buf, edir, ODIRLEN, MemWrite); reg.r[REGRET] = n; }
void sysseek(void) { int fd; uint32_t mode; uint32_t retp; int64_t v; retp = getmem_w(reg.r[13]+4); fd = getmem_w(reg.r[13]+8); v = getmem_v(reg.r[13]+16); mode = getmem_w(reg.r[13]+20); if(sysdbg) itrace("seek(%d, %lld, %d)", fd, v, mode); v = seek(fd, v, mode); if(v < 0) errstr(errbuf, sizeof errbuf); putmem_v(retp, v); }
void sysbind(void) { uint32_t pname, pold, flags; char name[1024], old[1024]; int n; pname = getmem_w(reg.r[13]+4); pold = getmem_w(reg.r[13]+8); flags = getmem_w(reg.r[13]+12); memio(name, pname, sizeof(name), MemReadstring); memio(old, pold, sizeof(old), MemReadstring); if(sysdbg) itrace("bind(0x%lux='%s', 0x%lux='%s', 0x%lux)", name, name, old, old, flags); n = bind(name, old, flags); if(n < 0) errstr(errbuf, sizeof errbuf); reg.r[REGRET] = n; }
void sys_stat(void) { char nambuf[1024]; char buf[ODIRLEN]; uint32_t edir, name; extern int _stat(char*, char*); /* old system call */ int n; name = getmem_w(reg.r[13]+4); edir = getmem_w(reg.r[13]+8); memio(nambuf, name, sizeof(nambuf), MemReadstring); if(sysdbg) itrace("stat(0x%lux='%s', 0x%lux)", name, nambuf, edir); n = _stat(nambuf, buf); if(n < 0) errstr(errbuf, sizeof errbuf); else memio(buf, edir, ODIRLEN, MemWrite); reg.r[REGRET] = n; }
/** * @brief Creates a named mutex. * @param[in] name the mutex name. * @param[out] phandle pointer to the mutex handle. * @return Zero for success, negative value otherwise. * @par Example: * @code * HANDLE h; * winx_create_mutex(L"\\BaseNamedObjects\\ultradefrag_mutex",&h); * @endcode */ int winx_create_mutex(wchar_t *name,HANDLE *phandle) { UNICODE_STRING us; NTSTATUS status; OBJECT_ATTRIBUTES oa; DbgCheck2(name,phandle,-1); *phandle = NULL; RtlInitUnicodeString(&us,name); InitializeObjectAttributes(&oa,&us,0,NULL,NULL); status = NtCreateMutant(phandle,MUTEX_ALL_ACCESS,&oa,0); if(status == STATUS_OBJECT_NAME_COLLISION){ itrace("%ws already exists",name); status = NtOpenMutant(phandle,MUTEX_ALL_ACCESS,&oa); } if(!NT_SUCCESS(status)){ *phandle = NULL; strace(status,"cannot create/open %ws",name); return (-1); } return 0; }
void syswrite(vlong offset) { int fd; ulong size, a; char *buf; int n; fd = getmem_w(reg.r[REGSP]+4); a = getmem_w(reg.r[REGSP]+8); size = getmem_w(reg.r[REGSP]+12); Bflush(bioout); buf = memio(0, a, size, MemRead); n = pwrite(fd, buf, size, offset); if(n < 0) errstr(errbuf, sizeof errbuf); if(sysdbg) itrace("write(%d, %lux, %d, 0xllx) = %d", fd, a, size, offset, n); free(buf); reg.r[REGRET] = n; }
static int save_lua_report(udefrag_job_parameters *jp) { wchar_t *path = NULL; WINX_FILE *f; wchar_t *cn; wchar_t compname[MAX_COMPUTERNAME_LENGTH + 1]; char utf8_compname[(MAX_COMPUTERNAME_LENGTH + 1) * 4]; char buffer[512]; struct prb_traverser t; winx_file_info *file; char *comment; char *status; int length; winx_time tm; /* should be enough for any path in UTF-8 encoding */ #define MAX_UTF8_PATH_LENGTH (256 * 1024) char *utf8_path; utf8_path = winx_tmalloc(MAX_UTF8_PATH_LENGTH); if(utf8_path == NULL){ mtrace(); return (-1); } path = get_report_path(jp); if(path == NULL) return UDEFRAG_NO_MEM; f = winx_fbopen(path,"w",RSB_SIZE); if(f == NULL){ f = winx_fopen(path,"w"); if(f == NULL){ winx_free(path); winx_free(utf8_path); return (-1); } } /* print header */ cn = winx_getenv(L"COMPUTERNAME"); if(cn){ wcsncpy(compname,cn,MAX_COMPUTERNAME_LENGTH + 1); compname[MAX_COMPUTERNAME_LENGTH] = 0; winx_free(cn); } else { wcscpy(compname,L"nil"); } winx_to_utf8(utf8_compname,sizeof(utf8_compname),compname); memset(&tm,0,sizeof(winx_time)); (void)winx_get_local_time(&tm); (void)_snprintf(buffer,sizeof(buffer), "-- UltraDefrag report for disk %c:\r\n\r\n" "format_version = 7\r\n\r\n" "volume_letter = \"%c\"\r\n" "computer_name = \"%hs\"\r\n\r\n" "current_time = {\r\n" "\tyear = %04i,\r\n" "\tmonth = %02i,\r\n" "\tday = %02i,\r\n" "\thour = %02i,\r\n" "\tmin = %02i,\r\n" "\tsec = %02i,\r\n" "\tisdst = false\r\n" "}\r\n\r\n" "files = {\r\n", jp->volume_letter, jp->volume_letter,utf8_compname, (int)tm.year,(int)tm.month,(int)tm.day, (int)tm.hour,(int)tm.minute,(int)tm.second ); buffer[sizeof(buffer) - 1] = 0; (void)winx_fwrite(buffer,1,strlen(buffer),f); /* print body */ prb_t_init(&t,jp->fragmented_files); file = prb_t_first(&t,jp->fragmented_files); while(file){ if(is_directory(file)) comment = "[DIR]"; else if(is_compressed(file)) comment = "[CMP]"; else comment = " - "; /* * On change of status strings don't forget * also to adjust write_file_status routine * in udreportcnv.lua file. */ if(is_locked(file)) status = "locked"; else if(is_moving_failed(file)) status = "move failed"; else if(is_in_improper_state(file)) status = "invalid"; else status = " - "; (void)_snprintf(buffer, sizeof(buffer), "\t{fragments = %u," "size = %I64u," "comment = \"%s\"," "status = \"%s\"," "path = \"", (UINT)file->disp.fragments, file->disp.clusters * jp->v_info.bytes_per_cluster, comment, status ); buffer[sizeof(buffer) - 1] = 0; (void)winx_fwrite(buffer,1,strlen(buffer),f); if(file->path != NULL){ /* skip \??\ sequence in the beginning of the path */ length = (int)wcslen(file->path); if(length > 4){ convert_to_utf8_path(utf8_path,MAX_UTF8_PATH_LENGTH,file->path + 4); } else { convert_to_utf8_path(utf8_path,MAX_UTF8_PATH_LENGTH,file->path); } (void)winx_fwrite(utf8_path,1,strlen(utf8_path),f); } (void)strcpy(buffer,"\"},\r\n"); (void)winx_fwrite(buffer,1,strlen(buffer),f); file = prb_t_next(&t); } /* print footer */ (void)strcpy(buffer,"}\r\n"); (void)winx_fwrite(buffer,1,strlen(buffer),f); itrace("report saved to %ws",path); winx_fclose(f); winx_free(path); winx_free(utf8_path); return 0; }
/** * @brief Initializes main window. */ MainFrame::MainFrame() :wxFrame(NULL,wxID_ANY,wxT("UltraDefrag")) { g_mainFrame = this; m_vList = NULL; m_cMap = NULL; m_currentJob = NULL; m_busy = false; m_paused = false; // set main window icon SetIcons(wxICON(appicon)); // read configuration ReadAppConfiguration(); ProcessCommandEvent(ID_ReadUserPreferences); // set main window title wxString *instdir = new wxString(); //genBTC re-arranged the below, A LOT. wxStandardPaths stdpaths; wxFileName exepath(stdpaths.GetExecutablePath()); wxString cd = exepath.GetPath(); if((wxGetEnv(wxT("UD_INSTALL_DIR"),instdir))&&(cd.CmpNoCase(*instdir) == 0)) { itrace("current directory matches installation location, so it isn't portable"); itrace("installation location: %ls",instdir->wc_str()); m_title = new wxString(wxT(VERSIONINTITLE)); } else { itrace("current directory differs from installation location, so it is portable"); itrace("current directory: %ls",cd.wc_str()); wxSetEnv(wxT("UD_IS_PORTABLE"),wxT("1")); m_title = new wxString(wxT(VERSIONINTITLE_PORTABLE)); } //genBTC re-arranged the above, A LOT. ProcessCommandEvent(ID_SetWindowTitle); delete instdir; // set main window size and position SetSize(m_width,m_height); if(!m_saved){ CenterOnScreen(); GetPosition(&m_x,&m_y); } Move(m_x,m_y); if(m_maximized) Maximize(true); SetMinSize(wxSize(DPI(MAIN_WINDOW_MIN_WIDTH),DPI(MAIN_WINDOW_MIN_HEIGHT))); // create menu, tool and status bars InitMenu(); InitToolbar(); InitStatusBar(); //make sizer1 to hold the the tabbed "notebook". And make the notebook wxBoxSizer* bSizer1; bSizer1 = new wxBoxSizer( wxVERTICAL ); m_notebook1 = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); //make a panel inside the notebook to hold the m_splitter m_panel1 = new wxPanel( m_notebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); // create list of volumes and cluster map (with splitter as parent) m_splitter = new wxSplitterWindow(m_panel1,wxID_ANY, wxDefaultPosition,wxDefaultSize, wxSP_3D | wxCLIP_CHILDREN); m_splitter->SetMinimumPaneSize(DPI(MIN_PANEL_HEIGHT)); m_vList = new DrivesList(m_splitter,wxLC_REPORT | wxLC_NO_SORT_HEADER | wxLC_HRULES | wxLC_VRULES | wxBORDER_NONE); m_cMap = new ClusterMap(m_splitter); m_splitter->SplitHorizontally(m_vList,m_cMap); int height = GetClientSize().GetHeight(); int maxPanelHeight = height - DPI(MIN_PANEL_HEIGHT) - m_splitter->GetSashSize(); if(m_separatorPosition < DPI(MIN_PANEL_HEIGHT)) m_separatorPosition = DPI(MIN_PANEL_HEIGHT); else if(m_separatorPosition > maxPanelHeight) m_separatorPosition = maxPanelHeight; m_splitter->SetSashPosition(m_separatorPosition); // update frame layout so we'll be able to initialize // list of volumes and cluster map properly wxSizeEvent evt(wxSize(m_width,m_height)); ProcessEvent(evt); m_splitter->UpdateSize(); InitVolList(); m_vList->SetFocus(); // populate list of volumes m_listThread = new ListThread(); //make sizer2 to Fit the splitter, and initialize it. wxBoxSizer* bSizer2; bSizer2 = new wxBoxSizer( wxVERTICAL ); bSizer2->Add( m_splitter, 1, wxEXPAND, 1 ); m_panel1->SetSizer( bSizer2 ); //Finish Tab1 - Add the Panel1(Splitter+sizer2) to the notebook. m_notebook1->AddPage( m_panel1, wxT("Drives"), false ); //make a 2nd panel inside the notebook to hold the 2nd page(a grid) m_panel2 = new wxPanel( m_notebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); m_filesList = new FilesList(m_panel2,wxLC_REPORT /* | wxLC_SINGLE_SEL | wxLC_NO_SORT_HEADER*/ \ | wxLC_VIRTUAL | wxLC_HRULES | wxLC_VRULES | wxBORDER_NONE); InitFilesList(); //make sizer3 to Fit the page2list, and initialize it. wxBoxSizer* bSizer3; bSizer3 = new wxBoxSizer( wxVERTICAL ); bSizer3->Add( m_filesList, 1, wxEXPAND, 1 ); m_panel2->SetSizer( bSizer3 ); bSizer3->Fit( m_panel2 ); //Finish Tab 2 - Add the Panel2(page2list+sizer3) to the notebook. m_notebook1->AddPage( m_panel2, wxT("Files"), false ); //Finish Notebook & initialize bSizer1->Add( m_notebook1, 1, wxEXPAND, 1 ); this->SetSizer( bSizer1 ); // check the boot time defragmenter presence wxFileName btdFile(wxT("%SystemRoot%\\system32\\defrag_native.exe")); btdFile.Normalize(); bool btd = btdFile.FileExists(); m_menuBar->FindItem(ID_BootEnable)->Enable(btd); m_menuBar->FindItem(ID_BootScript)->Enable(btd); m_toolBar->EnableTool(ID_BootEnable,btd); m_toolBar->EnableTool(ID_BootScript,btd); if(btd && ::winx_bootex_check(L"defrag_native") > 0){ m_menuBar->FindItem(ID_BootEnable)->Check(true); m_toolBar->ToggleTool(ID_BootEnable,true); m_btdEnabled = true; } else { m_btdEnabled = false; } // launch threads for time consuming operations m_btdThread = btd ? new BtdThread() : NULL; m_configThread = new ConfigThread(); m_crashInfoThread = new CrashInfoThread(); wxConfigBase *cfg = wxConfigBase::Get(); int ulevel = (int)cfg->Read(wxT("/Upgrade/Level"),1); wxMenuItem *item = m_menuBar->FindItem(ID_HelpUpgradeNone + ulevel); if(item) item->Check(); m_upgradeThread = new UpgradeThread(ulevel); // set system tray icon m_systemTrayIcon = new SystemTrayIcon(); if(!m_systemTrayIcon->IsOk()){ etrace("system tray icon initialization failed"); wxSetEnv(wxT("UD_MINIMIZE_TO_SYSTEM_TRAY"),wxT("0")); } SetSystemTrayIcon(wxT("tray"),wxT("UltraDefrag")); // set localized text ProcessCommandEvent(ID_LocaleChange + g_locale->GetLanguage()); // allow disk processing m_jobThread = new JobThread(); //create query thread to perform queries without blocking the GUI //(sort of like jobs) - may not be good to have both possibly running at once. //Create Query Tab, Tab #3. InitQueryMenu(); UD_DisableTool(ID_Stop); //change stop icon to be not always enabled. }
/** * @brief find_files helper. * @note Optimized for speed. */ static int filter(winx_file_info *f,void *user_defined_data) { udefrag_job_parameters *jp = (udefrag_job_parameters *)user_defined_data; int length; /* START OF AUX CODE */ /* skip entries with empty path, as well as their children */ if(f->path == NULL) goto skip_file_and_children; if(f->path[0] == 0) goto skip_file_and_children; /* * Remove trailing dot from the root * directory path, otherwise we'll not * be able to defragment it. */ length = (int)wcslen(f->path); if(length >= 2){ if(f->path[length - 1] == '.' && f->path[length - 2] == '\\'){ itrace("root directory detected, its trailing dot will be removed"); f->path[length - 1] = 0; } } /* skip resident streams */ if(f->disp.fragments == 0) goto skip_file; /* show debugging information about interesting cases */ /* comment it out after testing to speed things up */ /* if(is_sparse(f)) dtrace("sparse file found: %ws",f->path); if(is_reparse_point(f)) dtrace("reparse point found: %ws",f->path); if(winx_wcsistr(f->path,L"$BITMAP")) dtrace("bitmap found: %ws",f->path); if(winx_wcsistr(f->path,L"$ATTRIBUTE_LIST")) dtrace("attribute list found: %ws",f->path); */ /* START OF FILTERING */ /* skip files with invalid map */ if(f->disp.blockmap == NULL) goto skip_file; /* skip temporary files */ if(is_temporary(f)) goto skip_file; /* filter files by their sizes */ if(exclude_by_size(f,jp)) goto skip_file; /* filter files by their number of fragments */ if(exclude_by_fragments(f,jp)) goto skip_file; /* filter files by their fragment sizes */ if(exclude_by_fragment_size(f,jp)) goto skip_file; /* filter files by their paths */ if(exclude_by_path(f,jp)){ /* * Don't skip children however since * their paths may match patterns. */ goto skip_file; } goto accept_file; skip_file: f->user_defined_flags |= UD_FILE_EXCLUDED; accept_file: /* count everything in context menu handler to avoid ambiguity */ if(jp->udo.job_flags & UD_JOB_CONTEXT_MENU_HANDLER){ if(jp->udo.cut_filter.count){ if(winx_patcmp(f->path + 0x4,&jp->udo.cut_filter)) update_progress_counters(f,jp); } else { update_progress_counters(f,jp); } } return 0; skip_file_and_children: f->user_defined_flags |= UD_FILE_EXCLUDED; return 1; }
/** * @brief Retrieves all information about the volume. * @return Zero for success, negative value otherwise. * @note Resets statistics and cluster map. */ int get_volume_information(udefrag_job_parameters *jp) { char fs_name[MAX_FS_NAME_LENGTH + 1]; int i; /* reset mft zone disposition */ memset(&jp->mft_zone,0,sizeof(struct _mft_zone)); /* reset v_info structure */ memset(&jp->v_info,0,sizeof(winx_volume_information)); /* reset statistics */ jp->pi.files = 0; jp->pi.directories = 0; jp->pi.compressed = 0; jp->pi.fragmented = 0; jp->pi.fragments = 0; jp->pi.total_space = 0; jp->pi.free_space = 0; jp->pi.mft_size = 0; jp->pi.clusters_to_process = 0; jp->pi.processed_clusters = 0; jp->fs_type = FS_UNKNOWN; jp->is_fat = 0; /* reset file lists */ destroy_lists(jp); /* update global variables holding drive geometry */ if(winx_get_volume_information(jp->volume_letter,&jp->v_info) < 0) return (-1); /* don't touch dirty volumes */ if(jp->v_info.is_dirty) return UDEFRAG_DIRTY_VOLUME; jp->pi.total_space = jp->v_info.total_bytes; jp->pi.free_space = jp->v_info.free_bytes; itrace("total clusters: %I64u",jp->v_info.total_clusters); jp->pi.used_clusters = jp->v_info.total_clusters - (jp->v_info.free_bytes / jp->v_info.bytes_per_cluster); itrace("used clusters : %I64u",jp->pi.used_clusters); itrace("cluster size: %I64u",jp->v_info.bytes_per_cluster); /* validate geometry */ if(!jp->v_info.total_clusters || !jp->v_info.bytes_per_cluster){ etrace("wrong volume geometry detected"); return (-1); } adjust_move_at_once_parameter(jp); /* check partition type */ itrace("%s partition detected",jp->v_info.fs_name); strncpy(fs_name,jp->v_info.fs_name,MAX_FS_NAME_LENGTH); fs_name[MAX_FS_NAME_LENGTH] = 0; _strupr(fs_name); for(i = 0; fs_types[i].name; i++){ if(!strcmp(fs_name,fs_types[i].name)){ jp->fs_type = fs_types[i].type; jp->is_fat = fs_types[i].is_fat; break; } } if(jp->fs_type == FS_UNKNOWN){ etrace("file system type is not recognized"); etrace("type independent routines will be used to defragment it"); } jp->pi.clusters_to_process = jp->v_info.total_clusters; jp->pi.processed_clusters = 0; if(jp->udo.fragment_size_threshold){ if(jp->udo.fragment_size_threshold <= jp->v_info.bytes_per_cluster){ itrace("fragment size threshold is below the cluster size, so it will be ignored"); jp->udo.fragment_size_threshold = 0; } } /* reset cluster map */ reset_cluster_map(jp); return 0; }