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