xref: /aosp_15_r20/external/skia/src/ports/SkOSFile_win.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2013 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
9*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_BUILD_FOR_WIN)
10*c8dee2aaSAndroid Build Coastguard Worker 
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkMalloc.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkNoncopyable.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTFitsIn.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkLeanWindows.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkOSFile.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkStringUtils.h"
17*c8dee2aaSAndroid Build Coastguard Worker 
18*c8dee2aaSAndroid Build Coastguard Worker #include <io.h>
19*c8dee2aaSAndroid Build Coastguard Worker #include <new>
20*c8dee2aaSAndroid Build Coastguard Worker #include <stdio.h>
21*c8dee2aaSAndroid Build Coastguard Worker #include <sys/stat.h>
22*c8dee2aaSAndroid Build Coastguard Worker 
sk_fsync(FILE * f)23*c8dee2aaSAndroid Build Coastguard Worker void sk_fsync(FILE* f) {
24*c8dee2aaSAndroid Build Coastguard Worker     _commit(sk_fileno(f));
25*c8dee2aaSAndroid Build Coastguard Worker }
26*c8dee2aaSAndroid Build Coastguard Worker 
sk_exists(const char * path,SkFILE_Flags flags)27*c8dee2aaSAndroid Build Coastguard Worker bool sk_exists(const char *path, SkFILE_Flags flags) {
28*c8dee2aaSAndroid Build Coastguard Worker     int mode = 0; // existence
29*c8dee2aaSAndroid Build Coastguard Worker     if (flags & kRead_SkFILE_Flag) {
30*c8dee2aaSAndroid Build Coastguard Worker         mode |= 4; // read
31*c8dee2aaSAndroid Build Coastguard Worker     }
32*c8dee2aaSAndroid Build Coastguard Worker     if (flags & kWrite_SkFILE_Flag) {
33*c8dee2aaSAndroid Build Coastguard Worker         mode |= 2; // write
34*c8dee2aaSAndroid Build Coastguard Worker     }
35*c8dee2aaSAndroid Build Coastguard Worker     return (0 == _access(path, mode));
36*c8dee2aaSAndroid Build Coastguard Worker }
37*c8dee2aaSAndroid Build Coastguard Worker 
38*c8dee2aaSAndroid Build Coastguard Worker typedef struct {
39*c8dee2aaSAndroid Build Coastguard Worker     ULONGLONG fVolume;
40*c8dee2aaSAndroid Build Coastguard Worker     ULONGLONG fLsbSize;
41*c8dee2aaSAndroid Build Coastguard Worker     ULONGLONG fMsbSize;
42*c8dee2aaSAndroid Build Coastguard Worker } SkFILEID;
43*c8dee2aaSAndroid Build Coastguard Worker 
sk_ino(FILE * f,SkFILEID * id)44*c8dee2aaSAndroid Build Coastguard Worker static bool sk_ino(FILE* f, SkFILEID* id) {
45*c8dee2aaSAndroid Build Coastguard Worker     int fileno = _fileno((FILE*)f);
46*c8dee2aaSAndroid Build Coastguard Worker     if (fileno < 0) {
47*c8dee2aaSAndroid Build Coastguard Worker         return false;
48*c8dee2aaSAndroid Build Coastguard Worker     }
49*c8dee2aaSAndroid Build Coastguard Worker 
50*c8dee2aaSAndroid Build Coastguard Worker     HANDLE file = (HANDLE)_get_osfhandle(fileno);
51*c8dee2aaSAndroid Build Coastguard Worker     if (INVALID_HANDLE_VALUE == file) {
52*c8dee2aaSAndroid Build Coastguard Worker         return false;
53*c8dee2aaSAndroid Build Coastguard Worker     }
54*c8dee2aaSAndroid Build Coastguard Worker 
55*c8dee2aaSAndroid Build Coastguard Worker     //TODO: call GetFileInformationByHandleEx on Vista and later with FileIdInfo.
56*c8dee2aaSAndroid Build Coastguard Worker     BY_HANDLE_FILE_INFORMATION info;
57*c8dee2aaSAndroid Build Coastguard Worker     if (0 == GetFileInformationByHandle(file, &info)) {
58*c8dee2aaSAndroid Build Coastguard Worker         return false;
59*c8dee2aaSAndroid Build Coastguard Worker     }
60*c8dee2aaSAndroid Build Coastguard Worker     id->fVolume = info.dwVolumeSerialNumber;
61*c8dee2aaSAndroid Build Coastguard Worker     id->fLsbSize = info.nFileIndexLow + (((ULONGLONG)info.nFileIndexHigh) << 32);
62*c8dee2aaSAndroid Build Coastguard Worker     id->fMsbSize = 0;
63*c8dee2aaSAndroid Build Coastguard Worker 
64*c8dee2aaSAndroid Build Coastguard Worker     return true;
65*c8dee2aaSAndroid Build Coastguard Worker }
66*c8dee2aaSAndroid Build Coastguard Worker 
sk_fidentical(FILE * a,FILE * b)67*c8dee2aaSAndroid Build Coastguard Worker bool sk_fidentical(FILE* a, FILE* b) {
68*c8dee2aaSAndroid Build Coastguard Worker     SkFILEID aID, bID;
69*c8dee2aaSAndroid Build Coastguard Worker     return sk_ino(a, &aID) && sk_ino(b, &bID)
70*c8dee2aaSAndroid Build Coastguard Worker            && aID.fLsbSize == bID.fLsbSize
71*c8dee2aaSAndroid Build Coastguard Worker            && aID.fMsbSize == bID.fMsbSize
72*c8dee2aaSAndroid Build Coastguard Worker            && aID.fVolume == bID.fVolume;
73*c8dee2aaSAndroid Build Coastguard Worker }
74*c8dee2aaSAndroid Build Coastguard Worker 
75*c8dee2aaSAndroid Build Coastguard Worker class SkAutoNullKernelHandle : SkNoncopyable {
76*c8dee2aaSAndroid Build Coastguard Worker public:
SkAutoNullKernelHandle(const HANDLE handle)77*c8dee2aaSAndroid Build Coastguard Worker     SkAutoNullKernelHandle(const HANDLE handle) : fHandle(handle) { }
~SkAutoNullKernelHandle()78*c8dee2aaSAndroid Build Coastguard Worker     ~SkAutoNullKernelHandle() { CloseHandle(fHandle); }
operator HANDLE() const79*c8dee2aaSAndroid Build Coastguard Worker     operator HANDLE() const { return fHandle; }
isValid() const80*c8dee2aaSAndroid Build Coastguard Worker     bool isValid() const { return SkToBool(fHandle); }
81*c8dee2aaSAndroid Build Coastguard Worker private:
82*c8dee2aaSAndroid Build Coastguard Worker     HANDLE fHandle;
83*c8dee2aaSAndroid Build Coastguard Worker };
84*c8dee2aaSAndroid Build Coastguard Worker typedef SkAutoNullKernelHandle SkAutoWinMMap;
85*c8dee2aaSAndroid Build Coastguard Worker 
sk_fmunmap(const void * addr,size_t)86*c8dee2aaSAndroid Build Coastguard Worker void sk_fmunmap(const void* addr, size_t) {
87*c8dee2aaSAndroid Build Coastguard Worker     UnmapViewOfFile(addr);
88*c8dee2aaSAndroid Build Coastguard Worker }
89*c8dee2aaSAndroid Build Coastguard Worker 
sk_fdmmap(int fileno,size_t * length)90*c8dee2aaSAndroid Build Coastguard Worker void* sk_fdmmap(int fileno, size_t* length) {
91*c8dee2aaSAndroid Build Coastguard Worker     HANDLE file = (HANDLE)_get_osfhandle(fileno);
92*c8dee2aaSAndroid Build Coastguard Worker     if (INVALID_HANDLE_VALUE == file) {
93*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
94*c8dee2aaSAndroid Build Coastguard Worker     }
95*c8dee2aaSAndroid Build Coastguard Worker 
96*c8dee2aaSAndroid Build Coastguard Worker     LARGE_INTEGER fileSize;
97*c8dee2aaSAndroid Build Coastguard Worker     if (0 == GetFileSizeEx(file, &fileSize)) {
98*c8dee2aaSAndroid Build Coastguard Worker         //TODO: use SK_TRACEHR(GetLastError(), "Could not get file size.") to report.
99*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
100*c8dee2aaSAndroid Build Coastguard Worker     }
101*c8dee2aaSAndroid Build Coastguard Worker     if (!SkTFitsIn<size_t>(fileSize.QuadPart)) {
102*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
103*c8dee2aaSAndroid Build Coastguard Worker     }
104*c8dee2aaSAndroid Build Coastguard Worker 
105*c8dee2aaSAndroid Build Coastguard Worker     SkAutoWinMMap mmap(CreateFileMapping(file, nullptr, PAGE_READONLY, 0, 0, nullptr));
106*c8dee2aaSAndroid Build Coastguard Worker     if (!mmap.isValid()) {
107*c8dee2aaSAndroid Build Coastguard Worker         //TODO: use SK_TRACEHR(GetLastError(), "Could not create file mapping.") to report.
108*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
109*c8dee2aaSAndroid Build Coastguard Worker     }
110*c8dee2aaSAndroid Build Coastguard Worker 
111*c8dee2aaSAndroid Build Coastguard Worker     // Eventually call UnmapViewOfFile
112*c8dee2aaSAndroid Build Coastguard Worker     void* addr = MapViewOfFile(mmap, FILE_MAP_READ, 0, 0, 0);
113*c8dee2aaSAndroid Build Coastguard Worker     if (nullptr == addr) {
114*c8dee2aaSAndroid Build Coastguard Worker         //TODO: use SK_TRACEHR(GetLastError(), "Could not map view of file.") to report.
115*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
116*c8dee2aaSAndroid Build Coastguard Worker     }
117*c8dee2aaSAndroid Build Coastguard Worker 
118*c8dee2aaSAndroid Build Coastguard Worker     *length = static_cast<size_t>(fileSize.QuadPart);
119*c8dee2aaSAndroid Build Coastguard Worker     return addr;
120*c8dee2aaSAndroid Build Coastguard Worker }
121*c8dee2aaSAndroid Build Coastguard Worker 
sk_fileno(FILE * f)122*c8dee2aaSAndroid Build Coastguard Worker int sk_fileno(FILE* f) {
123*c8dee2aaSAndroid Build Coastguard Worker     return _fileno((FILE*)f);
124*c8dee2aaSAndroid Build Coastguard Worker }
125*c8dee2aaSAndroid Build Coastguard Worker 
sk_fmmap(FILE * f,size_t * length)126*c8dee2aaSAndroid Build Coastguard Worker void* sk_fmmap(FILE* f, size_t* length) {
127*c8dee2aaSAndroid Build Coastguard Worker     int fileno = sk_fileno(f);
128*c8dee2aaSAndroid Build Coastguard Worker     if (fileno < 0) {
129*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
130*c8dee2aaSAndroid Build Coastguard Worker     }
131*c8dee2aaSAndroid Build Coastguard Worker 
132*c8dee2aaSAndroid Build Coastguard Worker     return sk_fdmmap(fileno, length);
133*c8dee2aaSAndroid Build Coastguard Worker }
134*c8dee2aaSAndroid Build Coastguard Worker 
sk_qread(FILE * file,void * buffer,size_t count,size_t offset)135*c8dee2aaSAndroid Build Coastguard Worker size_t sk_qread(FILE* file, void* buffer, size_t count, size_t offset) {
136*c8dee2aaSAndroid Build Coastguard Worker     int fileno = sk_fileno(file);
137*c8dee2aaSAndroid Build Coastguard Worker     HANDLE fileHandle = (HANDLE)_get_osfhandle(fileno);
138*c8dee2aaSAndroid Build Coastguard Worker     if (INVALID_HANDLE_VALUE == file) {
139*c8dee2aaSAndroid Build Coastguard Worker         return SIZE_MAX;
140*c8dee2aaSAndroid Build Coastguard Worker     }
141*c8dee2aaSAndroid Build Coastguard Worker 
142*c8dee2aaSAndroid Build Coastguard Worker     OVERLAPPED overlapped;
143*c8dee2aaSAndroid Build Coastguard Worker     memset(&overlapped, 0, sizeof(overlapped));
144*c8dee2aaSAndroid Build Coastguard Worker     ULARGE_INTEGER winOffset;
145*c8dee2aaSAndroid Build Coastguard Worker     winOffset.QuadPart = offset;
146*c8dee2aaSAndroid Build Coastguard Worker     overlapped.Offset = winOffset.LowPart;
147*c8dee2aaSAndroid Build Coastguard Worker     overlapped.OffsetHigh = winOffset.HighPart;
148*c8dee2aaSAndroid Build Coastguard Worker 
149*c8dee2aaSAndroid Build Coastguard Worker     if (!SkTFitsIn<DWORD>(count)) {
150*c8dee2aaSAndroid Build Coastguard Worker         count = std::numeric_limits<DWORD>::max();
151*c8dee2aaSAndroid Build Coastguard Worker     }
152*c8dee2aaSAndroid Build Coastguard Worker 
153*c8dee2aaSAndroid Build Coastguard Worker     DWORD bytesRead;
154*c8dee2aaSAndroid Build Coastguard Worker     if (ReadFile(fileHandle, buffer, static_cast<DWORD>(count), &bytesRead, &overlapped)) {
155*c8dee2aaSAndroid Build Coastguard Worker         return bytesRead;
156*c8dee2aaSAndroid Build Coastguard Worker     }
157*c8dee2aaSAndroid Build Coastguard Worker     if (GetLastError() == ERROR_HANDLE_EOF) {
158*c8dee2aaSAndroid Build Coastguard Worker         return 0;
159*c8dee2aaSAndroid Build Coastguard Worker     }
160*c8dee2aaSAndroid Build Coastguard Worker     return SIZE_MAX;
161*c8dee2aaSAndroid Build Coastguard Worker }
162*c8dee2aaSAndroid Build Coastguard Worker 
163*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////
164*c8dee2aaSAndroid Build Coastguard Worker 
165*c8dee2aaSAndroid Build Coastguard Worker struct SkOSFileIterData {
SkOSFileIterDataSkOSFileIterData166*c8dee2aaSAndroid Build Coastguard Worker     SkOSFileIterData() : fHandle(0), fPath16(nullptr) { }
167*c8dee2aaSAndroid Build Coastguard Worker     HANDLE fHandle;
168*c8dee2aaSAndroid Build Coastguard Worker     uint16_t* fPath16;
169*c8dee2aaSAndroid Build Coastguard Worker };
170*c8dee2aaSAndroid Build Coastguard Worker static_assert(sizeof(SkOSFileIterData) <= SkOSFile::Iter::kStorageSize, "not_enough_space");
171*c8dee2aaSAndroid Build Coastguard Worker 
concat_to_16(const char src[],const char suffix[])172*c8dee2aaSAndroid Build Coastguard Worker static uint16_t* concat_to_16(const char src[], const char suffix[]) {
173*c8dee2aaSAndroid Build Coastguard Worker     size_t  i, len = strlen(src);
174*c8dee2aaSAndroid Build Coastguard Worker     size_t  len2 = 3 + (suffix ? strlen(suffix) : 0);
175*c8dee2aaSAndroid Build Coastguard Worker     uint16_t* dst = (uint16_t*)sk_malloc_throw((len + len2) * sizeof(uint16_t));
176*c8dee2aaSAndroid Build Coastguard Worker 
177*c8dee2aaSAndroid Build Coastguard Worker     for (i = 0; i < len; i++) {
178*c8dee2aaSAndroid Build Coastguard Worker         dst[i] = src[i];
179*c8dee2aaSAndroid Build Coastguard Worker     }
180*c8dee2aaSAndroid Build Coastguard Worker 
181*c8dee2aaSAndroid Build Coastguard Worker     if (i > 0 && dst[i-1] != '/') {
182*c8dee2aaSAndroid Build Coastguard Worker         dst[i++] = '/';
183*c8dee2aaSAndroid Build Coastguard Worker     }
184*c8dee2aaSAndroid Build Coastguard Worker     dst[i++] = '*';
185*c8dee2aaSAndroid Build Coastguard Worker 
186*c8dee2aaSAndroid Build Coastguard Worker     if (suffix) {
187*c8dee2aaSAndroid Build Coastguard Worker         while (*suffix) {
188*c8dee2aaSAndroid Build Coastguard Worker             dst[i++] = *suffix++;
189*c8dee2aaSAndroid Build Coastguard Worker         }
190*c8dee2aaSAndroid Build Coastguard Worker     }
191*c8dee2aaSAndroid Build Coastguard Worker     dst[i] = 0;
192*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(i + 1 <= len + len2);
193*c8dee2aaSAndroid Build Coastguard Worker 
194*c8dee2aaSAndroid Build Coastguard Worker     return dst;
195*c8dee2aaSAndroid Build Coastguard Worker }
196*c8dee2aaSAndroid Build Coastguard Worker 
Iter()197*c8dee2aaSAndroid Build Coastguard Worker SkOSFile::Iter::Iter() { new (fSelf) SkOSFileIterData; }
198*c8dee2aaSAndroid Build Coastguard Worker 
Iter(const char path[],const char suffix[])199*c8dee2aaSAndroid Build Coastguard Worker SkOSFile::Iter::Iter(const char path[], const char suffix[]) {
200*c8dee2aaSAndroid Build Coastguard Worker     new (fSelf) SkOSFileIterData;
201*c8dee2aaSAndroid Build Coastguard Worker     this->reset(path, suffix);
202*c8dee2aaSAndroid Build Coastguard Worker }
203*c8dee2aaSAndroid Build Coastguard Worker 
~Iter()204*c8dee2aaSAndroid Build Coastguard Worker SkOSFile::Iter::~Iter() {
205*c8dee2aaSAndroid Build Coastguard Worker     SkOSFileIterData& self = *reinterpret_cast<SkOSFileIterData*>(fSelf);
206*c8dee2aaSAndroid Build Coastguard Worker     sk_free(self.fPath16);
207*c8dee2aaSAndroid Build Coastguard Worker     if (self.fHandle) {
208*c8dee2aaSAndroid Build Coastguard Worker         ::FindClose(self.fHandle);
209*c8dee2aaSAndroid Build Coastguard Worker     }
210*c8dee2aaSAndroid Build Coastguard Worker     self.~SkOSFileIterData();
211*c8dee2aaSAndroid Build Coastguard Worker }
212*c8dee2aaSAndroid Build Coastguard Worker 
reset(const char path[],const char suffix[])213*c8dee2aaSAndroid Build Coastguard Worker void SkOSFile::Iter::reset(const char path[], const char suffix[]) {
214*c8dee2aaSAndroid Build Coastguard Worker     SkOSFileIterData& self = *reinterpret_cast<SkOSFileIterData*>(fSelf);
215*c8dee2aaSAndroid Build Coastguard Worker     if (self.fHandle) {
216*c8dee2aaSAndroid Build Coastguard Worker         ::FindClose(self.fHandle);
217*c8dee2aaSAndroid Build Coastguard Worker         self.fHandle = 0;
218*c8dee2aaSAndroid Build Coastguard Worker     }
219*c8dee2aaSAndroid Build Coastguard Worker     if (nullptr == path) {
220*c8dee2aaSAndroid Build Coastguard Worker         path = "";
221*c8dee2aaSAndroid Build Coastguard Worker     }
222*c8dee2aaSAndroid Build Coastguard Worker 
223*c8dee2aaSAndroid Build Coastguard Worker     sk_free(self.fPath16);
224*c8dee2aaSAndroid Build Coastguard Worker     self.fPath16 = concat_to_16(path, suffix);
225*c8dee2aaSAndroid Build Coastguard Worker }
226*c8dee2aaSAndroid Build Coastguard Worker 
is_magic_dir(const uint16_t dir[])227*c8dee2aaSAndroid Build Coastguard Worker static bool is_magic_dir(const uint16_t dir[]) {
228*c8dee2aaSAndroid Build Coastguard Worker     // return true for "." and ".."
229*c8dee2aaSAndroid Build Coastguard Worker     return dir[0] == '.' && (dir[1] == 0 || (dir[1] == '.' && dir[2] == 0));
230*c8dee2aaSAndroid Build Coastguard Worker }
231*c8dee2aaSAndroid Build Coastguard Worker 
get_the_file(HANDLE handle,SkString * name,WIN32_FIND_DATAW * dataPtr,bool getDir)232*c8dee2aaSAndroid Build Coastguard Worker static bool get_the_file(HANDLE handle, SkString* name, WIN32_FIND_DATAW* dataPtr, bool getDir) {
233*c8dee2aaSAndroid Build Coastguard Worker     WIN32_FIND_DATAW    data;
234*c8dee2aaSAndroid Build Coastguard Worker 
235*c8dee2aaSAndroid Build Coastguard Worker     if (nullptr == dataPtr) {
236*c8dee2aaSAndroid Build Coastguard Worker         if (::FindNextFileW(handle, &data))
237*c8dee2aaSAndroid Build Coastguard Worker             dataPtr = &data;
238*c8dee2aaSAndroid Build Coastguard Worker         else
239*c8dee2aaSAndroid Build Coastguard Worker             return false;
240*c8dee2aaSAndroid Build Coastguard Worker     }
241*c8dee2aaSAndroid Build Coastguard Worker 
242*c8dee2aaSAndroid Build Coastguard Worker     for (;;) {
243*c8dee2aaSAndroid Build Coastguard Worker         if (getDir) {
244*c8dee2aaSAndroid Build Coastguard Worker             if ((dataPtr->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
245*c8dee2aaSAndroid Build Coastguard Worker                 !is_magic_dir((uint16_t*)dataPtr->cFileName))
246*c8dee2aaSAndroid Build Coastguard Worker             {
247*c8dee2aaSAndroid Build Coastguard Worker                 break;
248*c8dee2aaSAndroid Build Coastguard Worker             }
249*c8dee2aaSAndroid Build Coastguard Worker         } else {
250*c8dee2aaSAndroid Build Coastguard Worker             if (!(dataPtr->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
251*c8dee2aaSAndroid Build Coastguard Worker                 break;
252*c8dee2aaSAndroid Build Coastguard Worker             }
253*c8dee2aaSAndroid Build Coastguard Worker         }
254*c8dee2aaSAndroid Build Coastguard Worker         if (!::FindNextFileW(handle, dataPtr)) {
255*c8dee2aaSAndroid Build Coastguard Worker             return false;
256*c8dee2aaSAndroid Build Coastguard Worker         }
257*c8dee2aaSAndroid Build Coastguard Worker     }
258*c8dee2aaSAndroid Build Coastguard Worker     // if we get here, we've found a file/dir
259*c8dee2aaSAndroid Build Coastguard Worker     if (name) {
260*c8dee2aaSAndroid Build Coastguard Worker         const uint16_t* utf16name = (const uint16_t*)dataPtr->cFileName;
261*c8dee2aaSAndroid Build Coastguard Worker         const uint16_t* ptr = utf16name;
262*c8dee2aaSAndroid Build Coastguard Worker         while (*ptr != 0) { ++ptr; }
263*c8dee2aaSAndroid Build Coastguard Worker         *name = SkStringFromUTF16(utf16name, ptr - utf16name);
264*c8dee2aaSAndroid Build Coastguard Worker     }
265*c8dee2aaSAndroid Build Coastguard Worker     return true;
266*c8dee2aaSAndroid Build Coastguard Worker }
267*c8dee2aaSAndroid Build Coastguard Worker 
next(SkString * name,bool getDir)268*c8dee2aaSAndroid Build Coastguard Worker bool SkOSFile::Iter::next(SkString* name, bool getDir) {
269*c8dee2aaSAndroid Build Coastguard Worker     SkOSFileIterData& self = *reinterpret_cast<SkOSFileIterData*>(fSelf);
270*c8dee2aaSAndroid Build Coastguard Worker     WIN32_FIND_DATAW    data;
271*c8dee2aaSAndroid Build Coastguard Worker     WIN32_FIND_DATAW*   dataPtr = nullptr;
272*c8dee2aaSAndroid Build Coastguard Worker 
273*c8dee2aaSAndroid Build Coastguard Worker     if (self.fHandle == 0) {  // our first time
274*c8dee2aaSAndroid Build Coastguard Worker         if (self.fPath16 == nullptr || *self.fPath16 == 0) {  // check for no path
275*c8dee2aaSAndroid Build Coastguard Worker             return false;
276*c8dee2aaSAndroid Build Coastguard Worker         }
277*c8dee2aaSAndroid Build Coastguard Worker 
278*c8dee2aaSAndroid Build Coastguard Worker         self.fHandle = ::FindFirstFileW((LPCWSTR)self.fPath16, &data);
279*c8dee2aaSAndroid Build Coastguard Worker         if (self.fHandle != 0 && self.fHandle != (HANDLE)~0) {
280*c8dee2aaSAndroid Build Coastguard Worker             dataPtr = &data;
281*c8dee2aaSAndroid Build Coastguard Worker         }
282*c8dee2aaSAndroid Build Coastguard Worker     }
283*c8dee2aaSAndroid Build Coastguard Worker     return self.fHandle != (HANDLE)~0 && get_the_file(self.fHandle, name, dataPtr, getDir);
284*c8dee2aaSAndroid Build Coastguard Worker }
285*c8dee2aaSAndroid Build Coastguard Worker 
286*c8dee2aaSAndroid Build Coastguard Worker #endif//defined(SK_BUILD_FOR_WIN)
287