[Author: zork]
[google-gears.git] / gears / base / common / wince_compatibility.cc
blob96754ac124ef2901369dbf501890d7d89224a839
1 // Copyright 2007, Google Inc.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
5 //
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
27 // Mobile 5.
29 // TODO(andreip): remove platform-specific #ifdef guards when OS-specific
30 // sources (e.g. WIN32_CPPSRCS) are implemented
31 #ifdef WINCE
32 #include "gears/base/common/wince_compatibility.h"
34 #include <shellapi.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,
47 int &pos,
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,
67 LPTSTR path_short,
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;
73 } else {
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,
84 LPCTSTR full_dirpath,
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.
90 int pos = 0;
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,
108 int nFolder,
109 HANDLE hToken,
110 DWORD dwFlags,
111 LPTSTR pszPath) {
112 return SHGetSpecialFolderPath(hwndOwner, pszPath, nFolder, false);
115 BOOL IsNetworkAlive(LPDWORD lpdwFlags) {
116 BOOL alive = false;
117 CONNMGR_CONNECTION_DETAILED_STATUS* status_buffer_ptr = NULL;
118 DWORD size = 0;
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*>
123 (buffer);
124 ZeroMemory(status_buffer_ptr, size);
125 hr = ConnMgrQueryDetailedStatus(status_buffer_ptr, &size);
126 if (SUCCEEDED(hr)) {
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).
135 alive = true;
136 break;
138 status_buffer_ptr = status_buffer_ptr->pNext;
141 delete [] buffer;
143 return alive;
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_);
157 assert(m_h == NULL);
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);
172 if (m_h) {
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.
177 CloseHandle(m_h);
178 m_h = NULL;
179 } else {
180 success = true;
183 // Give up ownership of global_mutex_.
184 ReleaseMutex(global_mutex_);
186 return success;
189 // Internal
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,
198 int &pos,
199 bool skip_separators) {
200 while (pos < static_cast<int>(path.length()) &&
201 (IsSeparator(path[pos]) == skip_separators)) {
202 pos++;
206 #endif // WINCE