1 //
2 // Copyright (C) 2001-2013 Graeme Walker <graeme_walker@users.sourceforge.net>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // ===
17 //
18 // dir_win32.cpp
19 //
20
21 #include "gdef.h"
22 #include "gconvert.h"
23 #include <shlwapi.h>
24 #include <shlobj.h>
25
26 #ifndef SHGFP_TYPE_CURRENT
27 #define SHGFP_TYPE_CURRENT 0
28 #endif
29 #ifndef CSIDL_PROGRAM_FILES
30 #define CSIDL_PROGRAM_FILES 38
31 #endif
32
33 #include "dir.h"
34 #include "gfile.h"
35 #include "gpath.h"
36 #include "glog.h"
37 #include <stdexcept>
38
windows()39 G::Path Dir::windows()
40 {
41 char buffer[MAX_PATH] = { 0 } ;
42 unsigned int n = ::GetWindowsDirectoryA( buffer , MAX_PATH ) ;
43 if( n == 0 || n > MAX_PATH )
44 throw std::runtime_error( "cannot determine the windows directory" ) ;
45 return G::Path( std::string(buffer,n) ) ;
46 }
47
dotexe()48 std::string Dir::dotexe()
49 {
50 return ".exe" ;
51 }
52
os_install()53 G::Path Dir::os_install()
54 {
55 return special("programs") + "emailrelay" ;
56 }
57
os_gui(const G::Path & base)58 G::Path Dir::os_gui( const G::Path & base )
59 {
60 return base + "emailrelay-gui.exe" ;
61 }
62
os_icon(const G::Path & base)63 G::Path Dir::os_icon( const G::Path & base )
64 {
65 return os_server( base ) ; // icon is a resource in the exe
66 }
67
os_server(const G::Path & base)68 G::Path Dir::os_server( const G::Path & base )
69 {
70 return base + "emailrelay.exe" ;
71 }
72
os_config()73 G::Path Dir::os_config()
74 {
75 return special("programs") + "emailrelay" ;
76 }
77
os_spool()78 G::Path Dir::os_spool()
79 {
80 return windows() + "system32" + "spool" + "emailrelay" ;
81 }
82
os_pid(const G::Path & config_dir)83 G::Path Dir::os_pid( const G::Path & config_dir )
84 {
85 return config_dir ;
86 }
87
os_boot()88 G::Path Dir::os_boot()
89 {
90 // empty implies no access (see call to Boot::able() in pages.cpp),
91 // so the default has to be a bogus value
92 return "services" ;
93 }
94
os_bootcopy(const G::Path &,const G::Path &)95 G::Path Dir::os_bootcopy( const G::Path & , const G::Path & )
96 {
97 return G::Path() ;
98 }
99
cwd()100 G::Path Dir::cwd()
101 {
102 DWORD n = ::GetCurrentDirectoryA( 0 , NULL ) ;
103 char * buffer = new char [n+2U] ;
104 buffer[0] = '\0' ;
105 n = ::GetCurrentDirectoryA( n+1U , buffer ) ;
106 std::string dir( buffer , n ) ;
107 delete [] buffer ;
108 if( n == 0U )
109 throw std::runtime_error( "cannot determine the current working directory" ) ;
110 return G::Path( dir ) ;
111 }
112
113 namespace
114 {
special_id(const std::string & type)115 int special_id( const std::string & type )
116 {
117 if( type == "desktop" ) return CSIDL_DESKTOPDIRECTORY ;
118 if( type == "menu" ) return CSIDL_PROGRAMS ;
119 if( type == "login" ) return CSIDL_STARTUP ;
120 throw std::runtime_error("internal error") ;
121 return 0 ;
122 }
123 }
124
special(const std::string & type)125 G::Path Dir::special( const std::string & type )
126 {
127 if( type == "programs" )
128 {
129 char buffer[MAX_PATH] = { 0 } ;
130 bool ok = S_OK == ::SHGetFolderPathA( NULL , CSIDL_PROGRAM_FILES , NULL , SHGFP_TYPE_CURRENT , buffer ) ;
131 return ok ? G::Path(buffer) : G::Path("c:/program files") ;
132 }
133 else
134 {
135 char buffer[MAX_PATH] = { 0 } ;
136 bool ok = TRUE == ::SHGetSpecialFolderPathA( NULL , buffer , special_id(type) , FALSE ) ;
137 std::string result = ok ? std::string(buffer) : std::string() ;
138 G::Path default_ = envPath("USERPROFILE",envPath("HOME")) ;
139 return result.empty() ? default_ : G::Path(result) ;
140 }
141 }
142
home()143 G::Path Dir::home()
144 {
145 return envPath( "USERPROFILE" , envPath( "HOME" , desktop() ) ) ;
146 }
147
148 /// \file dir_win32.cpp
149