win32/dirimpl.cpp

Go to the documentation of this file.
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 

Generated on Tue Dec 8 11:35:32 2009 for derslib by  doxygen 1.5.5