1 // Copyright 2007, Google Inc.
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
6 // 1. Redistributions of source code must retain the above copyright notice,
7 // this list of conditions and the following disclaimer.
8 // 2. Redistributions in binary form must reproduce the above copyright notice,
9 // this list of conditions and the following disclaimer in the documentation
10 // and/or other materials provided with the distribution.
11 // 3. Neither the name of Google Inc. nor the names of its contributors may be
12 // used to endorse or promote products derived from this software without
13 // specific prior written permission.
15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // Implementation of Windows specific functions that don't exist in Windows
29 // TODO(andreip): remove platform-specific #ifdef guards when OS-specific
30 // sources (e.g. WIN32_CPPSRCS) are implemented
32 #include "gears/base/common/wince_compatibility.h"
36 #include "gears/base/common/common.h"
37 #include "gears/base/common/paths.h"
38 #include "gears/base/common/string_utils.h"
40 HANDLE
CMutexWince::global_mutex_
= NULL
;
41 CriticalSection
CMutexWince::lock_
;
42 const char16
* kGlobalMutexName
=
43 STRING16(PRODUCT_SHORT_NAME L
"GearsGlobalMutexWince");
45 // Used by SHCreateDirectoryEx.
46 static void SkipTokens(const std::string16
&path
,
48 bool skip_separators
);
50 // GetSystemTimeAsFileTime does not exist on Windows Mobile,
51 // so we implement it here by getting the system time and
52 // then converting it to file time.
53 void GetSystemTimeAsFileTime(LPFILETIME filetime
) {
54 SYSTEMTIME systemtime
;
55 GetSystemTime(&systemtime
);
56 SystemTimeToFileTime(&systemtime
, filetime
);
59 // There seem to be no way to implement this properly on Windows Mobile
60 // since the algorithm for path shortening isn't fully specified, according
61 // to http://en.wikipedia.org/wiki/8.3_filename. Using FindFirstFileA isn't
62 // an alternative either since that method isn't exported by coredll.lib.
63 // FindFirstFileW uses a different structure to return the file information
64 // and that structure is missing exactly the cAlternateFilename field, which
65 // would have been the one that contained the short name.
66 DWORD
GetShortPathNameW(LPCTSTR path_long
,
68 DWORD path_short_max_size
) {
69 int long_path_size
= wcslen(path_long
) + 1; // +1 for the ending \0
70 if (long_path_size
<= static_cast<int>(path_short_max_size
)) {
71 wcsncpy(path_short
, path_long
, path_short_max_size
);
72 return long_path_size
- 1;
74 return long_path_size
;
78 // This function creates a file system folder whose fully qualified
79 // path is given by full_dirpath. If one or more of the intermediate folders
80 // do not exist, they are created as well.
81 // According to http://msdn2.microsoft.com/en-us/library/aa365247.aspx
82 // Windows API functions accept both "\" and "/", so we will do the same.
83 int SHCreateDirectoryEx(HWND window
,
85 const SECURITY_ATTRIBUTES
*security_attributes
) {
86 std::string16
path(full_dirpath
);
87 if (!path
.length()) return ERROR_BAD_PATHNAME
;
89 // Traverse the path and create the directories one by one.
91 // Skip leading separators.
92 SkipTokens(path
, pos
, true);
93 while (pos
< static_cast<int>(path
.length())) {
94 // Find next separator.
95 SkipTokens(path
, pos
, false);
96 // Skip next consecutive separators, if any.
97 SkipTokens(path
, pos
, true);
98 // Create the directory.
99 if (!CreateDirectory(path
.substr(0, pos
).c_str(), NULL
)) {
100 DWORD error
= GetLastError();
101 if (error
!= ERROR_ALREADY_EXISTS
) return error
;
104 return GetLastError();
107 HRESULT
SHGetFolderPath(HWND hwndOwner
,
112 return SHGetSpecialFolderPath(hwndOwner
, pszPath
, nFolder
, false);
115 BOOL
IsNetworkAlive(LPDWORD lpdwFlags
) {
117 CONNMGR_CONNECTION_DETAILED_STATUS
* status_buffer_ptr
= NULL
;
119 HRESULT hr
= ConnMgrQueryDetailedStatus(status_buffer_ptr
, &size
);
120 if (hr
== HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
)) {
121 uint8
* buffer
= new uint8
[size
];
122 status_buffer_ptr
= reinterpret_cast<CONNMGR_CONNECTION_DETAILED_STATUS
*>
124 ZeroMemory(status_buffer_ptr
, size
);
125 hr
= ConnMgrQueryDetailedStatus(status_buffer_ptr
, &size
);
127 while (status_buffer_ptr
) {
128 if (status_buffer_ptr
->dwConnectionStatus
== CONNMGR_STATUS_CONNECTED
&&
129 (status_buffer_ptr
->pIPAddr
!= NULL
||
130 status_buffer_ptr
->dwType
== CM_CONNTYPE_PROXY
)) {
131 // We conclude that the network is alive if there is one
132 // connection in the CONNMGR_STATUS_CONNECTED state and
133 // the device has an IP address or it is connected in
134 // proxy mode (e.g. ActiveSync).
138 status_buffer_ptr
= status_buffer_ptr
->pNext
;
146 BOOL
CMutexWince::Open(DWORD dwAccess
, BOOL bInheritHandle
, LPCTSTR pszName
) {
147 // On Windows Mobile we are forced to implement CMutex::Open() using
148 // the CreateMutex() win32 API function. This will open an existing mutex
149 // or, if one doesn't exist already, will create a new mutex. However,
150 // given the semantics of ATL CMutex::Open(), the creation of a new mutex
151 // is an unwanted side-effect and we need to hide it from other processes
152 // that are simultaneously calling this method. We therefore need to
153 // serialize Open method calls using a global mutex. Furthermore,
154 // we also need to use a critical section to guard against
155 // concurrent initialization of this global mutex by different threads.
156 CritSecLock
locker(lock_
);
158 if (!global_mutex_
) {
159 global_mutex_
= CreateMutex(NULL
, FALSE
, kGlobalMutexName
);
160 if (!global_mutex_
) return false; // Returning early!
162 // We now have a handle to the global mutex. We may have created
163 // it or may have opened the existing one if another process had
164 // already created it. Although we cannot have multiple instances
165 // of IE mobile running at the same time, the browser control
166 // (together with Gears) may be embedded in some other application.
167 BOOL success
= false;
168 DWORD result
= WaitForSingleObject(global_mutex_
, INFINITE
);
169 if (result
== WAIT_OBJECT_0
) {
170 // We have ownership of global_mutex_.
171 m_h
= CreateMutex(NULL
, FALSE
, pszName
);
173 // If m_h is not NULL, GetLastError() can only return
174 // ERROR_ALREADY_EXISTS or success.
175 if (GetLastError() != ERROR_ALREADY_EXISTS
) {
176 // We didn't mean to create a mutex here, so let's close it.
183 // Give up ownership of global_mutex_.
184 ReleaseMutex(global_mutex_
);
191 static bool IsSeparator(const char16 token
) {
192 static const char16 kPathSeparatorAlternative
= L
'/';
193 return ((token
== kPathSeparator
) || (token
== kPathSeparatorAlternative
));
196 // Skips tokens of the given type (separators or non-separators).
197 static void SkipTokens(const std::string16
&path
,
199 bool skip_separators
) {
200 while (pos
< static_cast<int>(path
.length()) &&
201 (IsSeparator(path
[pos
]) == skip_separators
)) {