openModeller  Version 1.4.0
os_specific_win.cpp
Go to the documentation of this file.
00001 
00030 #ifdef WIN32
00031 // avoid warnings caused by problems in VC headers
00032 #define _SCL_SECURE_NO_DEPRECATE
00033 #endif
00034 
00035 #include <os_specific.hh>
00036 #include <openmodeller/Log.hh>
00037 #include <openmodeller/AlgorithmFactory.hh>
00038 #include <openmodeller/Settings.hh>
00039 
00040 #include <stdio.h>
00041 #include <fstream>
00042 #include <windows.h>
00043 #include <direct.h>
00044 #include <cpl_conv.h> // for setting gdal options
00045 #include <proj_api.h> // for setting proj options
00046 
00047 using std::vector;
00048 using std::string;
00049 
00050 /****************************************************************/
00051 /********************* Dynamic Linking Loader *******************/
00052 
00053 /****************/
00054 /*** dll Open ***/
00055 DLLHandle
00056 dllOpen( char const *dll_file_name )
00057 {
00058 #ifdef MINGW_QT 
00059   //Added by Tim because under mingw wchar is expected
00060   return LoadLibraryA( dll_file_name );
00061 #else
00062   return LoadLibraryA( dll_file_name );
00063 #endif
00064 }
00065 
00066 
00067 /********************/
00068 /*** dll Function ***/
00069 void *
00070 dllFunction( DLLHandle handle, char const *function_name )
00071 {
00072   return (void *) GetProcAddress( handle, function_name );
00073 }
00074 
00075 
00076 /*****************/
00077 /*** dll Close ***/
00078 int
00079 dllClose( DLLHandle handle )
00080 {
00081   return FreeLibrary( handle );
00082 }
00083 
00084 
00085 /*****************/
00086 /*** dll Error ***/
00087 const char *
00088 dllError( DLLHandle )
00089 {
00090   char * szBuf = NULL;
00091   long error = GetLastError();
00092 
00093   if (error)
00094   {
00095     szBuf = new char[1024]; 
00096     FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
00097                  NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &szBuf, 0, NULL );
00098   }
00099   return szBuf;
00100 }
00101 
00102 /*********************************/
00103 /*** set up External Resources ***/
00104 void setupExternalResources()
00105 {
00106   // Get directory where the .exe resides
00107   char initial_path[FILENAME_MAX];
00108 
00109   int bytes = GetModuleFileName( NULL, initial_path, FILENAME_MAX );
00110 
00111   if ( bytes == 0 ) {
00112         
00113       return;
00114   }
00115 
00116   // Remove file name from path
00117   string initial_path_str( initial_path );
00118         
00119   size_t last_sep;
00120         
00121   last_sep = initial_path_str.find_last_of("/\\");
00122         
00123   if ( ! last_sep ) {
00124         
00125       return;
00126   }
00127 
00128   string path = initial_path_str.substr( 0, last_sep+1 );
00129         
00130   // Set algorithms path
00131   string alg_path = path;
00132   alg_path.append( "algs" );
00133   AlgorithmFactory::setDefaultAlgDir( alg_path );
00134 
00135   // Set data path
00136   string data_path = path;
00137   data_path.append( "data" );
00138   omDataPath( data_path );
00139 
00140   // Set GDAL_DATA for openModeller lib
00141   string gdal_data_path = path;
00142   gdal_data_path.append( "gdal" );
00143   CPLSetConfigOption( "GDAL_DATA", gdal_data_path.c_str() );
00144 
00145   // Set PROJ_LIB for openModeller lib
00146   string proj_data_path = path;
00147   proj_data_path.append( "nad" );
00148   const char * char_path = proj_data_path.c_str();
00149   const char ** paths;
00150   paths = &char_path;
00151   pj_set_searchpath( 1, paths );
00152 }
00153 
00154 /********************/
00155 /*** om Data Path ***/
00156 std::string omDataPath( std::string dir )
00157 {
00158   static string data_path;
00159 
00160   // Set default directory, if specified through parameter
00161   if ( ! dir.empty() ) {
00162 
00163     data_path = dir;
00164 
00165     return data_path;
00166   }
00167 
00168   // Check configuration
00169   if ( Settings::count( "DATA_DIRECTORY" ) == 1 ) {
00170 
00171     return Settings::get( "DATA_DIRECTORY" );
00172   }
00173 
00174   // Check env variable
00175   char *env = getenv( "OM_DATA_DIR" );
00176 
00177   if ( env != 0 ) {
00178 
00179     string om_data_path = (char const *)env;
00180 
00181     if ( ! om_data_path.empty() ) {
00182 
00183       return om_data_path;
00184     }
00185   }
00186 
00187   // Finally compiler constant
00188   return OM_DATA_DIR;
00189 }
00190 
00191 /***************************/
00192 /*** initial Plugin Path ***/
00193 vector<string>
00194 initialPluginPath()
00195 {
00196   Log::instance()->debug( "Determining algorithms plugin path\n" );
00197 
00198   vector<string> entries;
00199 
00200   // Default location can be set programatically
00201   std::string default_dir = AlgorithmFactory::getDefaultAlgDir();
00202     
00203   if ( ! default_dir.empty() ) {
00204 
00205     Log::instance()->debug( "Using programatic setting for algorithms location\n" );
00206 
00207     entries.push_back( default_dir );
00208     return entries;
00209   }
00210 
00211   // Otherwise check configuration
00212   if ( Settings::count( "ALGS_DIRECTORY" ) == 1 ) {
00213 
00214     Log::instance()->debug( "Using configuration setting for algorithms location\n" );
00215     entries.push_back( Settings::get( "ALGS_DIRECTORY" ) );
00216     return entries;
00217   }
00218 
00219   // Or environment variable
00220   char *env = getenv( "OM_ALGS_DIR" );
00221 
00222   if ( env != 0 ) {
00223 
00224     string envpath( (char const *)env );
00225 
00226     // Ignore empty string
00227     if ( ! envpath.empty() ) {
00228 
00229       Log::instance()->debug( "Using environment setting for algorithms location\n" );
00230 
00231       // Parse the OM_ALGS_DIR with semi-colon (';') delimiters just like all other 
00232       // Windows path structures.
00233 
00234       // string::size_type start marks the beginning of the substring.
00235       // initial value is beginning of string, iterate value is one past the ';'
00236       for ( string::size_type start = 0; start < envpath.length() ; ) {
00237       
00238         // Find the next ';' after start
00239         string::size_type it = envpath.find( ';', start );
00240 
00241         // If no ';' is found..
00242         if ( it == string::npos ) {
00243 
00244           // the substring is (start, end-of-string)
00245           entries.push_back( envpath.substr( start ) );
00246           break;
00247         }
00248         // Else, test that the substring is non empty.
00249         else if ( it > start ) {
00250         
00251           string::size_type len = it - start;
00252           entries.push_back( envpath.substr( start, len ) );
00253         }
00254 
00255         // move the start of the next substring to one after the ':'
00256         start = it+1;
00257       }
00258 
00259       return entries;
00260     }
00261   }
00262 
00263   // Finally compiler constant
00264   Log::instance()->debug( "Using default algorithms location\n" );
00265 
00266   entries.reserve(1);
00267   entries.push_back( OM_ALGS_DIR );
00268   return entries;
00269 }
00270 
00271 /****************************************************************/
00272 /********************* Scan Directory Entries *******************/
00273 
00274 #include <io.h>
00275 #include <string.h>
00276 #include <stdlib.h>
00277 
00278 
00279 /****************/
00280 /*** scan Dir ***/
00281 
00282 vector<string> 
00283 scanDirectory( string dir )
00284 {
00285   string filepattern(dir);
00286   long dirhandle;
00287   struct _finddata_t fileinfo;
00288 
00289   vector<string> entries;
00290 
00291   // check for empty string
00292   if (!dir.length())
00293   {
00294     return entries;
00295   }
00296 
00297   // check for slashes at the end of directory name
00298   if ( (filepattern.find_last_of("/")  != filepattern.length() - 1) && 
00299      (filepattern.find_last_of("\\") != filepattern.length() - 1) )
00300     filepattern.append("\\");
00301 
00302     // Windows findfirst and findnext calls.
00303   filepattern.append("*.dll");
00304   dirhandle = _findfirst(filepattern.c_str(), &fileinfo); 
00305 
00306   if (dirhandle == -1L)
00307     return entries;
00308 
00309   int nent = 1;
00310   while (!_findnext(dirhandle, &fileinfo))
00311   { nent++; }
00312 
00313   // Directory path size - not used so remove this!
00314   //int dir_size = dir.size();
00315 
00316   // Windows findfirst and findnext calls.
00317   dirhandle = _findfirst(filepattern.c_str(), &fileinfo); 
00318 
00319   if (dirhandle == -1L)
00320     return entries;
00321 
00322   // Copy from windows structure to the return structure.
00323   for ( int i = 0; i < nent; i++ )
00324     {
00325       char *found = fileinfo.name;
00326 
00327       string name = dir;
00328       name += "\\";
00329       name += found;
00330 
00331       entries.push_back(name);
00332 
00333       _findnext(dirhandle, &fileinfo);
00334     }
00335 
00336   _findclose(dirhandle);
00337 
00338   return entries;
00339 }
00340 
00341 
00342 
00343 
00344 /****************************************************************/
00345 /*********************** Random Generation **********************/
00346 
00347 #include <time.h>
00348 
00349 
00350 /*******************/
00351 /*** init Random ***/
00352 dllexp int initRandom()
00353 {
00354   unsigned int seed;
00355   seed = (unsigned int) time( NULL );
00356   srand( seed );
00357   return 1;
00358 }
00359 
00360 /*******************/
00361 /*** init Random ***/
00362 dllexp int
00363 initRandom( unsigned int new_seed )
00364 {
00365   static unsigned int seed = 0;
00366 
00367   if ( seed && !new_seed ) {
00368 
00369     // reseeding rand can decrease the randomness, so avoid doing it
00370     return 1;
00371   }
00372 
00373   if ( new_seed ) {
00374 
00375     seed = new_seed;
00376   }
00377   else {
00378 
00379     seed = (unsigned int) time( NULL );
00380   }
00381 
00382   Log::instance()->debug( "Setting random seed %u\n", seed );
00383 
00384   srand( seed );
00385 
00386   return 1;
00387 }
00388 
00389 /*****************************************/
00390 /*** rand_r implementation for Windows ***/
00391 dllexp int
00392 rand_r( unsigned * seed )
00393 {
00394   * seed = (* seed) * 1103515245 + 12345;
00395   return ((unsigned)(*seed / 65536) % 32768);
00396 }
00397 
00398 /************************/
00399 /*** get Working path ***/
00400 std::string
00401 getWorkingPath()
00402 {
00403    char temp[MAX_PATH];
00404    return ( _getcwd(temp, MAX_PATH) ? std::string( temp ) : std::string("") );
00405 }
00406 
00407 /*******************/
00408 /*** path Exists ***/
00409 bool
00410 pathExists( const std::string path )
00411 {
00412   DWORD ftyp = GetFileAttributesA( path.c_str() );
00413 
00414   if ( ftyp == INVALID_FILE_ATTRIBUTES ) {
00415 
00416     return false; // something is wrong with the path
00417   }
00418 
00419   if ( ftyp & FILE_ATTRIBUTE_DIRECTORY ) {
00420 
00421     return true; // this is a directory
00422   }
00423 
00424   return false; // not a directoy
00425 }
00426 
00427 /*******************/
00428 /*** create Path ***/
00429 bool
00430 createPath( const std::string path )
00431 {
00432   static const std::string separators("\\/");
00433  
00434   DWORD file_attr = ::GetFileAttributes( (LPCSTR) path.c_str() );
00435 
00436   // If the specified directory name doesn't exist
00437   if ( file_attr == INVALID_FILE_ATTRIBUTES ) {
00438  
00439     // Recursively do it all again for the parent directory, if any
00440     std::size_t slash_idx = path.find_last_of( separators.c_str() );
00441 
00442     if ( slash_idx != std::string::npos ) {
00443 
00444       createPath( path.substr(0, slash_idx) );
00445     }
00446  
00447     // Create the last directory on the path (the recursive calls will have taken
00448     // care of the parent directories by now)
00449     ::CreateDirectory( (LPCSTR) path.c_str(), NULL );
00450     return pathExists( path );
00451   }
00452 
00453   // Specified directory name already exists as a file or directory
00454   return false;
00455 }