// folder_util.h : include utilities for manage folders // // Author: Gongbing // // Date: 2016-09-21 #pragma once #include #include #include #ifndef _INCLUDED_REF_ #define _INCLUDED_REF_ #include "../ref/ref.h" #endif namespace file_util { // 1 - all paths returned by these apis ended with '\\' typedef struct _path_file { wchar_t path[MAX_PATH]; }PATHFILE, *LPPATHFILE; enum file_coding { FILE_CODING_ANSI = 1, FILE_CODING_UTF8, FILE_CODING_UNICODE, }; __declspec(novtable) struct IFileFinder : public ref_util::IRef { // found_file: to receive the found file with full path // NOTE: child folder will always be in the found queue wherever you given the 'mark' !!! // filter '*.*' will not match the file which without extension, so use '*' as default filter for mark COM_API_DECLARE(int, find_first(const wchar_t* dir, LPPATHFILE found_file, const wchar_t* mark = L"*", bool recursive = true, bool depth_first = true, bool ignore_dot_folder = true)); COM_API_DECLARE(int, find_next(LPPATHFILE found_file)); COM_API_DECLARE(int, current_file_attr(WIN32_FILE_ATTRIBUTE_DATA* attr)); // return file attributes, -1 is error COM_API_DECLARE(int, current_root(LPPATHFILE root)); // root: full path with last '\\' of current finding path COM_API_DECLARE(int, stop_find(void)); COM_API_DECLARE(bool, is_current_folder(void)); }; __declspec(novtable) struct ISimpleShareMemory : public ref_util::IRef { // for monitor using, called should before write_result COM_API_DECLARE(int, wait_result(const wchar_t* id, inter_module_data::set_data notify, void* notify_param, DWORD wait_milliseconds = -1, size_t max_size = -1/*one page*/)); // for notifier using COM_API_DECLARE(int, write_result(const wchar_t* id, const char* data, size_t data_bytes)); }; __declspec(novtable) struct IGroupFile : public ref_util::IRef // to write grp_0000.txt, grp_0001.txt, ... files { COM_API_DECLARE(int, set_read_param(inter_module_data::set_data set_d, file_coding fc = FILE_CODING_ANSI)); COM_API_DECLARE(int, to_line(int line/*ZERO-based*/, int file_ind = -1)); // locate in read, return ERROR_SUCCESS in success COM_API_DECLARE(int, read_line(void* param, bool next = true)); // param is used in the set_d callback; get the first line if next was true COM_API_DECLARE(int, write(const char* data, size_t len)); COM_API_DECLARE(int, next_file(void)); COM_API_DECLARE(DWORD, cur_size(void)); COM_API_DECLARE(DWORD, cur_index(void)); // return current file index COM_API_DECLARE(DWORD, cur_line(void)); // return current line in file }; __declspec(novtable) struct IOvlHandler : public ref_util::IRef { COM_API_DECLARE(long, on_data_arrived(const char* data, size_t bytes, void* user_key)); // return how many bytes used, -1 to stop receiving !!! COM_API_DECLARE(bool, on_data_sent(char* data, size_t bytes, size_t data_buf_len/*for reuse inner_buffer*/, void* user_key)); // return whether to keep the data buffer in use. true - use again, false - default value, should free it COM_API_DECLARE(void, on_error(int err)); }; __declspec(novtable) struct IPipe : public ref_util::IRef { COM_API_DECLARE(int, read(void)); // data returned by IOvlHandler::on_data_arrived COM_API_DECLARE(int, write(const char* data, size_t bytes, bool inner_buf/*whether the 'data' is returned by get_write_buf*/)); COM_API_DECLARE(int, close(void)); COM_API_DECLARE(char*, get_write_buf(size_t bytes)); COM_API_DECLARE(void, free_got_write_buf(void* buf/*returned by get_write_buf*/)); }; PORT_API(int) get_special_folder(int clsidl, LPPATHFILE path); PORT_API(int) desktop(bool current_user, LPPATHFILE path); PORT_API(int) start_menu(bool current_user, LPPATHFILE path); PORT_API(int) start_menu_program(bool current_user, LPPATHFILE path); PORT_API(int) start_menu_startup(bool current_user, LPPATHFILE path); PORT_API(int) start_menu_recently(LPPATHFILE path); PORT_API(int) application_data(bool current_user, LPPATHFILE path); PORT_API(int) my_documents(bool current_user, LPPATHFILE path); PORT_API(int) self_path(LPPATHFILE path); PORT_API(int) local_application_data(LPPATHFILE path); PORT_API(int) program_files(LPPATHFILE path); PORT_API(int) windows(LPPATHFILE path); PORT_API(int) system(LPPATHFILE path); PORT_API(int) start_menu_program(LPPATHFILE path); PORT_API(int) quick_launch(bool current_user, LPPATHFILE path, LPPATHFILE path_pin = NULL/*full path*/); PORT_API(int) temporary_file(LPPATHFILE path, const wchar_t* prefix = NULL); PORT_API(int) get_currentLoginUser_AppdataPath(LPPATHFILE path);//add by weidongli on 2019-6-3 PORT_API(void) simplify_path(wchar_t* path, size_t path_buf_len = 0/*as lstrlenW(path) + 1*/); PORT_API(void) to_absolute_path(LPPATHFILE path); // convert './', '%WINDOWS%', '%SYSTEM%', ... to absolute path PORT_API(void) to_relative_path(const wchar_t* path_file_base, const wchar_t* path_file_tobe, LPPATHFILE rel_path); PORT_API(void) to_known_path(LPPATHFILE path); // convert absolute path to './', '%WINDOWS%', '%SYSTEM%', ... PORT_API(void) append_name(const wchar_t* path_file, const wchar_t* append, LPPATHFILE result); // to insert string 'append' before extension name PORT_API(bool) is_file_existing(const wchar_t* path_file); PORT_API(bool) is_valid_file_name_character(wchar_t file_name_char); PORT_API(int) force_rename_file(const wchar_t* from, const wchar_t* to); PORT_API(int) force_copy_file(const wchar_t* from, const wchar_t* to); PORT_API(int) force_move_file(const wchar_t* from, const wchar_t* to); PORT_API(int) force_delete_file(const wchar_t* file); PORT_API(int) force_create_file(const wchar_t* path_file, HANDLE* ret, DWORD acc = GENERIC_WRITE | GENERIC_READ, DWORD share = 0, DWORD method = CREATE_ALWAYS , DWORD attr = FILE_ATTRIBUTE_NORMAL, LPSECURITY_ATTRIBUTES psa = NULL); PORT_API(int) force_create_folder(const wchar_t* path_folder, SECURITY_ATTRIBUTES* psa = NULL, bool default_psa = true); PORT_API(bool) initialize_commonplace_security(SECURITY_ATTRIBUTES* psa); PORT_API(bool) is_valid_path(const wchar_t* path); PORT_API(bool) is_dir(DWORD attr); PORT_API(bool) is_dir(const wchar_t* path); PORT_API(int) get_file_attributes(const wchar_t* path_file, WIN32_FILE_ATTRIBUTE_DATA* attr); PORT_API(bool) get_file_version(const wchar_t* path_file, WORD* lpver_hh, WORD* lpver_hl, WORD* lpver_lh, WORD* lpver_ll, bool file_ver = true/*false is product version*/); PORT_API(UINT64) get_file_size(const wchar_t* path_file); PORT_API(UINT64) get_disk_available_space(const wchar_t* disk_path); // when return false, 'err' can be: // // 1: ERROR_DISK_FULL - the free space in 'disk' is not enough // // 2: ERROR_FILE_SYSTEM_LIMITATION - 'bytes' exceedes the maximum of the file-system's limitation // PORT_API(bool) is_disk_space_enough_for_single_file(const wchar_t* disk, UINT64 bytes, int* err = NULL); PORT_API(bool) is_parent_path(const wchar_t* path_to_check, const wchar_t* file); // to check whether the path 'path_to_check' is the parent path of 'file' PORT_API(int) parent_folder(const wchar_t* path_file, LPPATHFILE path); // without last '\\' PORT_API(int) common_parent_folder(const wchar_t* path_file1, const wchar_t* path_file2, LPPATHFILE parent); PORT_API(int) file_name(const wchar_t* path_file, LPPATHFILE path, bool with_ext = NULL); PORT_API(int) file_extension(const wchar_t* path_file, LPPATHFILE path); // without '.' PORT_API(int) load_file(const wchar_t* file, inter_module_data::set_data result, void* param); PORT_API(int) save_2_file(const char* data, size_t len, const wchar_t* file); PORT_API(void*) map_file_to_memory(const wchar_t* path_file, bool read_only = true, DWORD expand_size = 0, HANDLE *file_handle = NULL, HANDLE *map_handle = NULL); // clipboard PORT_API(int) set_clipboard(const void* data, size_t bytes, int format = CF_TEXT, HWND owner = NULL); PORT_API(int) set_clipboard_directly(HANDLE data, int format = CF_TEXT, HWND owner = NULL); PORT_API(int) get_clipboard(void* buf, size_t* bytes/*[in]-bytes of buf, [out]-content bytes in clipboard*/, int format = CF_TEXT, HWND owner = NULL); // parameter of result: // // data: real data of the clipboard format // // len: bytes of the data // // total: clipboard fromat, support CF_TEXT - (char*)data // CF_UNICODETEXT - (wchar_t*)data // CF_BITMAP - 'data' contains contents of PNG file // CF_DIB - 'data' contains contents of BMP file // CF_HDROP - (wchar_t*)data, copying files list, separated by "\r\n" // // flag: DATA_FLAG_FINAL // // param: same as 'user' // PORT_API(int) get_clipboard(inter_module_data::set_data result, void* user); PORT_API(bool) browser_file(HWND owner, LPPATHFILE file, const wchar_t *filter = L"All Files(*.*)\0\0", bool open = true, const wchar_t* title = NULL, WNDPROC cust_proc = NULL, LPARAM proc_param = NULL); // function: monitor file & folder // // path: full path, can be a folder or a file // // mask: FILE_NOTIFY_CHANGE_FILE_NAME FILE_NOTIFY_CHANGE_DIR_NAME FILE_NOTIFY_CHANGE_ATTRIBUTES FILE_NOTIFY_CHANGE_SIZE FILE_NOTIFY_CHANGE_LAST_WRITE FILE_NOTIFY_CHANGE_LAST_ACCESS FILE_NOTIFY_CHANGE_CREATION FILE_NOTIFY_CHANGE_SECURITY // // result: data - (const wchar_t*)path_file_name // len - bytes of data // total - unused // flag - DATA_FLAG_FINAL // param - the same as 'param' of this function // // return: monitor key , NULL if failed. should call un_monitor to free the return value // PORT_API(void*) monitor_files(const wchar_t* path, int mask, bool sub_dir, inter_module_data::set_data result, void* param); PORT_API(void) un_monitor(void* key); PORT_API(void) display_file_in_explorer(const wchar_t* path_file); PORT_API(UINT64) get_filesystem_maximum_file_bytes(const wchar_t* disk, wchar_t* fs_name = NULL/*provids NULL or not less than "MAX_PATH + 2"*/); PORT_API(IFileFinder*) create_file_finder(void); PORT_API(ISimpleShareMemory*) create_simple_share_memory(void); PORT_API(IGroupFile*) create_group_files(const wchar_t* first_file, bool for_read, int sn_digits = 4, DWORD limit_bytes = 0); // the limit_bytes would be ommited if fro_read was true PORT_API(IPipe*) open_pipe(IOvlHandler* handler, const wchar_t* name); } #define STR_SIMPLIFY_PATH(str) \ { \ file_util::PATHFILE pf = { 0 }; \ wcscpy_s(pf.path, _countof(pf.path) - 1, (str).c_str()); \ file_util::simplify_path(pf.path); \ (str) = pf.path; \ } #define STR_TO_ABSOLUTE_PATH(str) \ { \ file_util::PATHFILE pf = { 0 }; \ wcscpy_s(pf.path, _countof(pf.path) - 1, (str).c_str()); \ file_util::to_absolute_path(&pf); \ (str) = pf.path; \ } #define STR_TO_KNOWN_PATH(str) \ { \ file_util::PATHFILE pf = { 0 }; \ wcscpy_s(pf.path, _countof(pf.path) - 1, (str).c_str()); \ file_util::to_known_path(&pf); \ (str) = pf.path; \ } #define STR_PARENT_FOLDER(str) \ { \ file_util::PATHFILE pf = { 0 }; \ file_util::parent_folder((str).c_str(), &pf); \ (str) = pf.path; \ } #define STR_FILE_NAME(str, with_ext) \ { \ file_util::PATHFILE pf = { 0 }; \ file_util::file_name((str).c_str(), &pf, with_ext); \ (str) = pf.path; \ } #define STR_FILE_EXTENSION(str) \ { \ file_util::PATHFILE pf = { 0 }; \ file_util::file_extension((str).c_str(), &pf); \ (str) = pf.path; \ }