1 /* *****************************************************************
3 * Copyright 2017 Microsoft
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 ******************************************************************/
19 #include "iotivity_config.h"
32 #include "iotivity_debug.h"
33 #include "oic_platform.h"
34 #include "oic_string.h"
35 #include "oic_malloc.h"
39 #include <Windows.Foundation.h>
40 #include <windows.storage.h>
43 using namespace ABI::Windows::Storage;
44 using namespace Microsoft::WRL;
45 using namespace Microsoft::WRL::Wrappers;
48 #define TAG "OIC_PLATFORM"
50 #define IOTIVITY_FOLDER_NAME "\\iotivity\\"
55 // This function converts a wide char string to a standard char string.
56 static std::string ConvertWStrtoStr(PCWSTR wstr)
61 int strLength = WideCharToMultiByte(
73 OIC_LOG_V(ERROR, TAG, "Failed WideCharToMultiByte(), GetLastError(): %u", GetLastError());
77 // strLength includes null char
78 str = static_cast<char*>(OICCalloc(1, strLength));
81 OIC_LOG(ERROR, TAG, "Failed to create str buffer");
85 int retLen = WideCharToMultiByte(
95 if (retLen != strLength)
97 OIC_LOG_V(ERROR, TAG, "WideCharToMultiByte failed to convert WSTR, GetLastError(): %u",
113 static bool VerifyOrCreateDir(LPCSTR dir)
115 if (!CreateDirectory(dir, nullptr))
117 DWORD err = GetLastError();
118 if (err != ERROR_ALREADY_EXISTS)
120 OIC_LOG_V(ERROR, TAG, "Failed to CreateDirectory, GetLastError(): %u", err);
128 static OICPlatformResult_t GetSysLocalAppDataPath(std::string &path, size_t &sysPathLen, bool getTempDir)
130 OICPlatformResult_t ret = OIC_PLATFORM_OK;
135 // Since we are running in a UWP app, we don't need to initialize the Windows Runtime
137 ComPtr<IApplicationDataStatics> appDataStatics;
138 hr = RoGetActivationFactory(HStringReference(L"Windows.Storage.ApplicationData").Get(),
139 __uuidof(appDataStatics), &appDataStatics);
142 OIC_LOG_V(ERROR, TAG, "Failed to get the ActivationFactory, hr: %#x", hr);
143 return OIC_PLATFORM_ERROR;
146 ComPtr<IApplicationData> appData;
147 hr = appDataStatics->get_Current(&appData);
150 OIC_LOG_V(ERROR, TAG, "Failed to get ApplicationData, hr: %#x", hr);
151 return OIC_PLATFORM_ERROR;
154 ComPtr<IStorageFolder> folder;
157 hr = appData->get_LocalFolder(&folder);
160 OIC_LOG_V(ERROR, TAG, "Failed to get Local App StorageFolder, hr: %#x", hr);
161 return OIC_PLATFORM_ERROR;
166 hr = appData->get_TemporaryFolder(&folder);
169 OIC_LOG_V(ERROR, TAG, "Failed to get Temp App StorageFolder, hr: %#x", hr);
170 return OIC_PLATFORM_ERROR;
174 ComPtr<IStorageItem> folderItem;
175 hr = folder.As(&folderItem);
178 OIC_LOG_V(ERROR, TAG, "Failed to get StorageItem, hr: %#x", hr);
179 return OIC_PLATFORM_ERROR;
182 HString folderPathHString;
183 hr = folderItem->get_Path(folderPathHString.GetAddressOf());
186 OIC_LOG_V(ERROR, TAG, "Failed to get FolderPath, hr: %#x", hr);
187 return OIC_PLATFORM_ERROR;
190 uint32_t wstrPathLength;
191 PCWSTR folderPathWStr = folderPathHString.GetRawBuffer(&wstrPathLength);
192 path = ConvertWStrtoStr(folderPathWStr);
195 OIC_LOG(ERROR, TAG, "Failed to ConvertWStrtoStr");
196 return OIC_PLATFORM_ERROR;
199 // The length of the string that the system returned. All the folders up to this point
201 sysPathLen = path.length();
203 // Unsupported for win32 apps
204 OIC_LOG(WARNING, TAG, "Unsupported platform.");
206 OC_UNUSED(sysPathLen);
207 OC_UNUSED(getTempDir);
208 ret = OIC_PLATFORM_NOTIMPL;
214 // This function returns the platform and application specific local or temp application data path.
215 // This path will be used to store the iotivity metadata.For example, the security databases.
216 // The path will contain the trailing backslash(\) and the null terminating character.
217 // To get the needed buffer size, call this function with buffer NULL.
218 static OICPlatformResult_t GetLocalAppDataPath(std::string &path, bool getTempDir, char* buffer, size_t* bufferLen)
220 if (bufferLen == nullptr)
222 OIC_LOG(ERROR, TAG, "bufferLen is NULL");
223 return OIC_PLATFORM_INVALID_PARAM;
228 // The length of the string that the system returned. All the folders up to this point
231 OICPlatformResult_t ret = GetSysLocalAppDataPath(path, sysPathLen, getTempDir);
232 // Set path to the appropriate system local or temp application data path
233 if (ret != OIC_PLATFORM_OK)
235 OIC_LOG_V(ERROR, TAG, "Failed to GetSysLocalAppDataPath, ret: %"PRIuPTR,
236 static_cast<size_t>(ret));
237 // On failure, path should be cleared in GetSysLocalAppDataPath
241 // Append \iotivity\ for UWP and Win32
242 path.append(IOTIVITY_FOLDER_NAME);
244 if (path[path.length() - 1] != '\\')
249 // At this point, the path should end with backslash (\)
250 // Verify/Create all the folders in the path.
251 // Start searching from after the path retrieved from the system APIs
252 size_t prevSlashIdx = 0;
253 size_t slashIdx = path.find("\\", sysPathLen);
254 while (slashIdx != string::npos)
256 std::string dir = path.substr(0, slashIdx);
257 if (!VerifyOrCreateDir(dir.c_str()))
259 OIC_LOG_V(ERROR, TAG, "Failed to VerifyOrCreateDir %s", dir.c_str());
260 // Revert path back to default state as we cannot create an
261 // intermediate folder
263 return OIC_PLATFORM_ERROR;
265 prevSlashIdx = slashIdx;
266 slashIdx = path.find("\\", slashIdx + 1);
269 if (prevSlashIdx != (path.length() - 1))
271 // Verify/Create the last folder
272 if (!VerifyOrCreateDir(path.c_str()))
274 OIC_LOG_V(ERROR, TAG, "Failed to VerifyOrCreateDir %s", path.c_str());
275 // Revert path back to default state as we cannot create an
276 // intermediate folder
278 return OIC_PLATFORM_ERROR;
285 // Path shouldn't be empty at this point
286 OIC_LOG(ERROR, TAG, "Path is empty");
287 return OIC_PLATFORM_ERROR;
290 if (buffer != nullptr)
292 if (*bufferLen < (path.length() + 1))
294 // Insufficient buffer size for path string
295 OIC_LOG(ERROR, TAG, "Insufficient buffer size for path string");
296 *bufferLen = path.length() + 1; // + 1 for null-character
297 return OIC_PLATFORM_INVALID_PARAM;
299 OICStrcpy(buffer, *bufferLen, path.c_str());
300 *bufferLen = path.length() + 1; // + 1 for null-character
304 *bufferLen = path.length() + 1; // + 1 for null-character
307 return OIC_PLATFORM_OK;
310 // This function returns the platform and application specific local application data path.
311 // This path will be used to store the iotivity metadata.For example, the security databases.
312 // The path will contain the trailing backslash(\) and the null terminating character.
313 // To get the needed buffer size, call this function with buffer NULL.
314 OICPlatformResult_t OICGetLocalAppDataPath(char* buffer, size_t* bufferLen)
316 static std::string localAppDataPath;
317 return GetLocalAppDataPath(localAppDataPath, false, buffer, bufferLen);
320 // This function returns the platform and application specific temp application data path.
321 // This path will be used to store the iotivity metadata.For example, the security databases.
322 // The path will contain the trailing backslash(\) and the null terminating character.
323 // To get the needed buffer size, call this function with buffer NULL.
324 OICPlatformResult_t OICGetTempAppDataPath(char* buffer, size_t* bufferLen)
326 static std::string tempAppDataPath;
327 return GetLocalAppDataPath(tempAppDataPath, true, buffer, bufferLen);