00001 /* 00002 * Copyright (C) Sergey P. Derevyago, 2008. 00003 * 00004 * Permission to copy, use, modify, sell and distribute this software is granted 00005 * provided this copyright notice appears in all copies. 00006 * This software is provided "as is" without express or implied warranty, and 00007 * with no claim as to its suitability for any purpose. 00008 * 00009 */ 00010 00015 #include <windows.h> 00016 #include <ders/dir.hpp> 00017 #include <ders/file.hpp> 00018 #include <ders/text_buf.hpp> 00019 00020 namespace { 00021 00022 using namespace ders; 00023 00024 error errTbl[]={ 00025 ezero, // 0 ERROR_SUCCESS 00026 einval, // 1 ERROR_INVALID_FUNCTION 00027 enoent, // 2 ERROR_FILE_NOT_FOUND 00028 enoent, // 3 ERROR_PATH_NOT_FOUND 00029 emfile, // 4 ERROR_TOO_MANY_OPEN_FILES 00030 eacces, // 5 ERROR_ACCESS_DENIED 00031 ebadf, // 6 ERROR_INVALID_HANDLE 00032 enomem, // 7 ERROR_ARENA_TRASHED 00033 enomem, // 8 ERROR_NOT_ENOUGH_MEMORY 00034 enomem, // 9 ERROR_INVALID_BLOCK 00035 e2big, // 10 ERROR_BAD_ENVIRONMENT 00036 enoexec, // 11 ERROR_BAD_FORMAT 00037 einval, // 12 ERROR_INVALID_ACCESS 00038 einval, // 13 ERROR_INVALID_DATA 00039 enomem, // 14 ERROR_OUTOFMEMORY 00040 enoent, // 15 ERROR_INVALID_DRIVE 00041 eacces, // 16 ERROR_CURRENT_DIRECTORY 00042 exdev, // 17 ERROR_NOT_SAME_DEVICE 00043 enoent, // 18 ERROR_NO_MORE_FILES 00044 erofs, // 19 ERROR_WRITE_PROTECT 00045 enxio, // 20 ERROR_BAD_UNIT 00046 ebusy, // 21 ERROR_NOT_READY 00047 eio, // 22 ERROR_BAD_COMMAND 00048 eio, // 23 ERROR_CRC 00049 eio, // 24 ERROR_BAD_LENGTH 00050 eio, // 25 ERROR_SEEK 00051 eio, // 26 ERROR_NOT_DOS_DISK 00052 enxio, // 27 ERROR_SECTOR_NOT_FOUND 00053 ebusy, // 28 ERROR_OUT_OF_PAPER 00054 eio, // 29 ERROR_WRITE_FAULT 00055 eio, // 30 ERROR_READ_FAULT 00056 eio, // 31 ERROR_GEN_FAILURE 00057 eacces, // 32 ERROR_SHARING_VIOLATION 00058 eacces, // 33 ERROR_LOCK_VIOLATION 00059 enxio, // 34 ERROR_WRONG_DISK 00060 enfile, // 35 ERROR_FCB_UNAVAILABLE 00061 enfile, // 36 ERROR_SHARING_BUFFER_EXCEEDED 00062 efault, // 37 ERROR_CODE_PAGE_MISMATCHED 00063 eio, // 38 ERROR_HANDLE_EOF 00064 enospc, // 39 ERROR_HANDLE_DISK_FULL 00065 eunkn, // 40 00066 eunkn, // 41 00067 eunkn, // 42 00068 eunkn, // 43 00069 eunkn, // 44 00070 eunkn, // 45 00071 eunkn, // 46 00072 eunkn, // 47 00073 eunkn, // 48 00074 eunkn, // 49 00075 enodev, // 50 ERROR_NOT_SUPPORTED 00076 ebusy, // 51 ERROR_REM_NOT_LIST 00077 eexist, // 52 ERROR_DUP_NAME 00078 enoent, // 53 ERROR_BAD_NETPATH 00079 ebusy, // 54 ERROR_NETWORK_BUSY 00080 enodev, // 55 ERROR_DEV_NOT_EXIST 00081 eagain, // 56 ERROR_TOO_MANY_CMDS 00082 eio, // 57 ERROR_ADAP_HDW_ERR 00083 eio, // 58 ERROR_BAD_NET_RESP 00084 eio, // 59 ERROR_UNEXP_NET_ERR 00085 einval, // 60 ERROR_BAD_REM_ADAP 00086 efbig, // 61 ERROR_PRINTQ_FULL 00087 enospc, // 62 ERROR_NO_SPOOL_SPACE 00088 enoent, // 63 ERROR_PRINT_CANCELLED 00089 enoent, // 64 ERROR_NETNAME_DELETED 00090 eacces, // 65 ERROR_NETWORK_ACCESS_DENIED 00091 enodev, // 66 ERROR_BAD_DEV_TYPE 00092 enoent, // 67 ERROR_BAD_NET_NAME 00093 enfile, // 68 ERROR_TOO_MANY_NAMES 00094 eio, // 69 ERROR_TOO_MANY_SESS 00095 eagain, // 70 ERROR_SHARING_PAUSED 00096 einval, // 71 ERROR_REQ_NOT_ACCEP 00097 eagain, // 72 ERROR_REDIR_PAUSED 00098 efault, // 73 ERROR_SBCS_ATT_WRITE_PROT 00099 efault, // 74 ERROR_SBCS_GENERAL_FAILURE 00100 efault, // 75 ERROR_XGA_OUT_MEMORY 00101 eunkn, // 76 00102 eunkn, // 77 00103 eunkn, // 78 00104 eunkn, // 79 00105 eexist, // 80 ERROR_FILE_EXISTS 00106 efault, // 81 ERROR_DUP_FCB 00107 eacces, // 82 ERROR_CANNOT_MAKE 00108 eacces, // 83 ERROR_FAIL_I24 00109 enfile, // 84 ERROR_OUT_OF_STRUCTURES 00110 eexist, // 85 ERROR_ALREADY_ASSIGNED 00111 eperm, // 86 ERROR_INVALID_PASSWORD 00112 einval, // 87 ERROR_INVALID_PARAMETER 00113 eio, // 88 ERROR_NET_WRITE_FAULT 00114 eagain, // 89 ERROR_NO_PROC_SLOTS 00115 eunkn, // 90 ERROR_NOT_FROZEN 00116 eunkn, // 91 ERR_TSTOVFL 00117 eunkn, // 92 ERR_TSTDUP 00118 eunkn, // 93 ERROR_NO_ITEMS 00119 eunkn, // 94 00120 eintr, // 95 ERROR_INTERRUPT 00121 eunkn, // 96 00122 eunkn, // 97 00123 eunkn, // 98 00124 ebusy, // 99 ERROR_DEVICE_IN_USE 00125 eagain, // 100 ERROR_TOO_MANY_SEMAPHORES 00126 eagain, // 101 ERROR_EXCL_SEM_ALREADY_OWNED 00127 eunkn, // 102 ERROR_SEM_IS_SET 00128 eunkn, // 103 ERROR_TOO_MANY_SEM_REQUESTS 00129 eunkn, // 104 ERROR_INVALID_AT_INTERRUPT_TIME 00130 eunkn, // 105 ERROR_SEM_OWNER_DIED 00131 eunkn, // 106 ERROR_SEM_USER_LIMIT 00132 exdev, // 107 ERROR_DISK_CHANGE 00133 eacces, // 108 ERROR_DRIVE_LOCKED 00134 epipe, // 109 ERROR_BROKEN_PIPE 00135 enoent, // 110 ERROR_OPEN_FAILED 00136 eunkn, // 111 ERROR_BUFFER_OVERFLOW 00137 enospc, // 112 ERROR_DISK_FULL 00138 emfile, // 113 ERROR_NO_MORE_SEARCH_HANDLES 00139 ebadf, // 114 ERROR_INVALID_TARGET_HANDLE 00140 efault, // 115 ERROR_PROTECTION_VIOLATION 00141 eunkn, // 116 ERROR_VIOKBD_REQUEST 00142 eunkn, // 117 ERROR_INVALID_CATEGORY 00143 eunkn, // 118 ERROR_INVALID_VERIFY_SWITCH 00144 eunkn, // 119 ERROR_BAD_DRIVER_LEVEL 00145 eunkn, // 120 ERROR_CALL_NOT_IMPLEMENTED 00146 eunkn, // 121 ERROR_SEM_TIMEOUT 00147 eunkn, // 122 ERROR_INSUFFICIENT_BUFFER 00148 enoent, // 123 ERROR_INVALID_NAME 00149 einval, // 124 ERROR_INVALID_LEVEL 00150 eunkn, // 125 ERROR_NO_VOLUME_LABEL 00151 eunkn, // 126 ERROR_MOD_NOT_FOUND 00152 esrch, // 127 ERROR_PROC_NOT_FOUND 00153 echild, // 128 ERROR_WAIT_NO_CHILDREN 00154 echild, // 129 ERROR_CHILD_NOT_COMPLETE 00155 ebadf, // 130 ERROR_DIRECT_ACCESS_HANDLE 00156 einval, // 131 ERROR_NEGATIVE_SEEK 00157 eacces, // 132 ERROR_SEEK_ON_DEVICE 00158 eunkn, // 133 ERROR_IS_JOIN_TARGET 00159 eunkn, // 134 ERROR_IS_JOINED 00160 eunkn, // 135 ERROR_IS_SUBSTED 00161 eunkn, // 136 ERROR_NOT_JOINED 00162 eunkn, // 137 ERROR_NOT_SUBSTED 00163 eunkn, // 138 ERROR_JOIN_TO_JOIN 00164 eunkn, // 139 ERROR_SUBST_TO_SUBST 00165 eunkn, // 140 ERROR_JOIN_TO_SUBST 00166 eunkn, // 141 ERROR_SUBST_TO_JOIN 00167 eagain, // 142 ERROR_BUSY_DRIVE 00168 eunkn, // 143 ERROR_SAME_DRIVE 00169 eunkn, // 144 ERROR_DIR_NOT_ROOT 00170 enotempty, // 145 ERROR_DIR_NOT_EMPTY 00171 eunkn, // 146 ERROR_IS_SUBST_PATH 00172 eunkn, // 147 ERROR_IS_JOIN_PATH 00173 eunkn, // 148 ERROR_PATH_BUSY 00174 eunkn, // 149 ERROR_IS_SUBST_TARGET 00175 eunkn, // 150 ERROR_SYSTEM_TRACE 00176 eunkn, // 151 ERROR_INVALID_EVENT_COUNT 00177 eunkn, // 152 ERROR_TOO_MANY_MUXWAITERS 00178 eunkn, // 153 ERROR_INVALID_LIST_FORMAT 00179 eunkn, // 154 ERROR_LABEL_TOO_LONG 00180 eunkn, // 155 ERROR_TOO_MANY_TCBS 00181 eunkn, // 156 ERROR_SIGNAL_REFUSED 00182 eunkn, // 157 ERROR_DISCARDED 00183 eacces, // 158 ERROR_NOT_LOCKED 00184 eunkn, // 159 ERROR_BAD_THREADID_ADDR 00185 eunkn, // 160 ERROR_BAD_ARGUMENTS 00186 enoent, // 161 ERROR_BAD_PATHNAME 00187 eunkn, // 162 ERROR_SIGNAL_PENDING 00188 eunkn, // 163 ERROR_UNCERTAIN_MEDIA 00189 eagain, // 164 ERROR_MAX_THRDS_REACHED 00190 eunkn, // 165 ERROR_MONITORS_NOT_SUPPORTED 00191 eunkn, // 166 ERROR_UNC_DRIVER_NOT_INSTALLED 00192 eacces, // 167 ERROR_LOCK_FAILED 00193 eunkn, // 168 ERROR_SWAPIO_FAILED 00194 eunkn, // 169 ERROR_SWAPIN_FAILED 00195 eunkn, // 170 ERROR_BUSY 00196 eunkn, // 171 00197 eunkn, // 172 00198 eunkn, // 173 ERROR_CANCEL_VIOLATION 00199 eunkn, // 174 ERROR_ATOMIC_LOCK_NOT_SUPPORTED 00200 eunkn, // 175 ERROR_READ_LOCKS_NOT_SUPPORTED 00201 eunkn, // 176 00202 eunkn, // 177 00203 eunkn, // 178 00204 eunkn, // 179 00205 eunkn, // 180 ERROR_INVALID_SEGMENT_NUMBER 00206 eunkn, // 181 ERROR_INVALID_CALLGATE 00207 eunkn, // 182 ERROR_INVALID_ORDINAL 00208 eexist, // 183 ERROR_ALREADY_EXISTS 00209 echild, // 184 ERROR_NO_CHILD_PROCESS 00210 eunkn, // 185 ERROR_CHILD_ALIVE_NOWAIT 00211 eunkn, // 186 ERROR_INVALID_FLAG_NUMBER 00212 eunkn, // 187 ERROR_SEM_NOT_FOUND 00213 eunkn, // 188 ERROR_INVALID_STARTING_CODESEG 00214 eunkn, // 189 ERROR_INVALID_STACKSEG 00215 eunkn, // 190 ERROR_INVALID_MODULETYPE 00216 eunkn, // 191 ERROR_INVALID_EXE_SIGNATURE 00217 eunkn, // 192 ERROR_EXE_MARKED_INVALID 00218 eunkn, // 193 ERROR_BAD_EXE_FORMAT 00219 eunkn, // 194 ERROR_ITERATED_DATA_EXCEEDS_64k 00220 eunkn, // 195 ERROR_INVALID_MINALLOCSIZE 00221 eunkn, // 196 ERROR_DYNLINK_FROM_INVALID_RING 00222 eunkn, // 197 ERROR_IOPL_NOT_ENABLED 00223 eunkn, // 198 ERROR_INVALID_SEGDPL 00224 eunkn, // 199 ERROR_AUTODATASEG_EXCEEDS_64k 00225 eunkn, // 200 ERROR_RING2SEG_MUST_BE_MOVABLE 00226 eunkn, // 201 ERROR_RELOC_CHAIN_XEEDS_SEGLIM 00227 eunkn, // 202 ERROR_INFLOOP_IN_RELOC_CHAIN 00228 eunkn, // 203 ERROR_ENVVAR_NOT_FOUND 00229 eunkn, // 204 ERROR_NOT_CURRENT_CTRY 00230 eunkn, // 205 ERROR_NO_SIGNAL_SENT 00231 enoent, // 206 ERROR_FILENAME_EXCED_RANGE 00232 eunkn, // 207 ERROR_RING2_STACK_IN_USE 00233 eunkn, // 208 ERROR_META_EXPANSION_TOO_LONG 00234 eunkn, // 209 ERROR_INVALID_SIGNAL_NUMBER 00235 eunkn, // 210 ERROR_THREAD_1_INACTIVE 00236 eunkn, // 211 ERROR_INFO_NOT_AVAIL 00237 eunkn, // 212 ERROR_LOCKED 00238 eunkn, // 213 ERROR_BAD_DYNALINK 00239 eunkn, // 214 ERROR_TOO_MANY_MODULES 00240 eagain, // 215 ERROR_NESTING_NOT_ALLOWED 00241 eunkn, // 216 ERROR_CANNOT_SHRINK 00242 eunkn, // 217 ERROR_ZOMBIE_PROCESS 00243 eunkn, // 218 ERROR_STACK_IN_HIGH_MEMORY 00244 eunkn, // 219 ERROR_INVALID_EXITROUTINE_RING 00245 eunkn, // 220 ERROR_GETBUF_FAILED 00246 eunkn, // 221 ERROR_FLUSHBUF_FAILED 00247 eunkn, // 222 ERROR_TRANSFER_TOO_LONG 00248 eunkn, // 223 ERROR_FORCENOSWAP_FAILED 00249 eunkn, // 224 ERROR_SMG_NO_TARGET_WINDOW 00250 eunkn, // 225 ERROR_VIRUS_INFECTED 00251 eunkn, // 226 ERROR_VIRUS_DELETED 00252 eunkn, // 227 00253 eunkn, // 228 ERROR_NO_CHILDREN 00254 eunkn, // 229 ERROR_INVALID_SCREEN_GROUP 00255 epipe, // 230 ERROR_BAD_PIPE 00256 eagain, // 231 ERROR_PIPE_BUSY 00257 eunkn, // 232 ERROR_NO_DATA 00258 epipe, // 233 ERROR_PIPE_NOT_CONNECTED 00259 }; 00260 00261 error convertWinError(unsigned val) 00262 { 00263 return (val<sizeof(errTbl)/sizeof(*errTbl)) ? errTbl[val] : eunkn; 00264 } 00265 00266 shException createException(mem_pool& mp, const FileLine& location) 00267 { 00268 DWORD le=GetLastError(); 00269 00270 char* buf; 00271 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, 00272 le, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&buf, 0, NULL); 00273 00274 sh_text msg=text_buf(mp)+le+": "+buf; 00275 LocalFree(buf); 00276 00277 while (msg->back()=='\r' || msg->back()=='\n') 00278 msg->uninitialized_resize(msg->size()-1); 00279 00280 return newException(mp, location, msg); 00281 } 00282 00283 struct win_dir : public dir { 00284 sh_text mask; 00285 WIN32_FIND_DATA fd; 00286 HANDLE hn; 00287 00288 win_dir(sh_text dname); 00289 ~win_dir(); 00290 00291 virtual bool find_next(entry&); 00292 virtual sh_text full_name(const entry& dent); 00293 00294 virtual void destroy(mem_pool& mp2) { destroy_this(this, mp2); } 00295 }; 00296 00297 win_dir::win_dir(sh_text dname) : mask(dname), hn(INVALID_HANDLE_VALUE) 00298 { 00299 if (mask->size()>0 && mask->back()!='\\' && mask->back()!=':') 00300 mask->append('\\'); 00301 mask->append('*'); 00302 } 00303 00304 win_dir::~win_dir() 00305 { 00306 if (hn!=INVALID_HANDLE_VALUE) FindClose(hn); 00307 } 00308 00309 bool win_dir::find_next(entry& dent) 00310 { 00311 mem_pool& mp=mask.pool(); 00312 00313 if (hn==INVALID_HANDLE_VALUE) { 00314 hn=FindFirstFile(mask->c_str(), &fd); 00315 00316 if (hn==INVALID_HANDLE_VALUE) { 00317 throw newFileErrorException(_FLINE_, "Can't find first file", 00318 convertWinError(GetLastError()), mask, createException(mp, _FLINE_)); 00319 } 00320 } 00321 else { 00322 if (!FindNextFile(hn, &fd)) { 00323 if (GetLastError()==ERROR_NO_MORE_FILES) 00324 return false; 00325 00326 throw newFileErrorException(_FLINE_, "Can't find next file", 00327 convertWinError(GetLastError()), mask, createException(mp, _FLINE_)); 00328 } 00329 } 00330 00331 *dent.name=fd.cFileName; 00332 dent.isdir=fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY; 00333 dent.size=fd.nFileSizeLow; 00334 00335 return true; 00336 } 00337 00338 sh_text win_dir::full_name(const entry& dent) 00339 { 00340 return text_buf(mask.pool())+ch_rng(mask->begin(), mask->end()-1)+dent.name; 00341 } 00342 00343 } // unnamed 00344 00345 namespace ders { // ::ders 00346 00347 sh_dir new_dir(mem_pool& mp, const ch_rng& dname) 00348 { 00349 mp_newbuf<win_dir> buf(mp); 00350 return sh_dir(buf.pool(), buf.rls(::new(buf.get()) win_dir(nt(mp, dname)))); 00351 } 00352 00353 error make_dir(mem_pool& mp, const ch_rng& dname) 00354 { 00355 return (CreateDirectory(text(mp, dname).c_str(), NULL)) ? ezero : 00356 convertWinError(GetLastError()); 00357 } 00358 00359 } // namespace ::ders 00360