PageRenderTime 52ms CodeModel.GetById 10ms app.highlight 38ms RepoModel.GetById 1ms app.codeStats 1ms

/platform/win/scaffold/directory.d

http://github.com/wilkie/djehuty
D | 495 lines | 297 code | 81 blank | 117 comment | 27 complexity | e4a2856cb602873b51a2198be18c62fb MD5 | raw file
  1/*
  2 * directory.d
  3 *
  4 * This file implements the Scaffold for platform specific Directory
  5 * traversal in Windows.
  6 *
  7 * Author: Dave Wilkinson
  8 *
  9 */
 10
 11module scaffold.directory;
 12
 13pragma(lib, "netapi32.lib");
 14pragma(lib, "mpr.lib");
 15
 16import platform.win.common;
 17
 18import platform.vars.directory;
 19
 20import core.string;
 21import core.main;
 22import core.unicode;
 23
 24import io.console;
 25import io.file;
 26
 27bool DirectoryOpen(ref DirectoryPlatformVars dirVars, ref string path) {
 28	if (DirectoryFileIsDir(path)) {
 29		return true;
 30	}
 31
 32	return false;
 33}
 34
 35bool DirectoryCreate(ref DirectoryPlatformVars dirVars, ref string path) {
 36	wchar[] strArr = _ConvertFrameworkPath(Unicode.toUtf16(path));
 37	strArr ~= '\0';
 38	
 39	if (DirectoryFileIsDir(path)) {
 40		return false;
 41	}
 42
 43	if(CreateDirectoryW(strArr.ptr,null) != 0){
 44		return true;
 45	}
 46	
 47	return false;
 48}
 49
 50bool DirectoryClose(ref DirectoryPlatformVars dirVars) {
 51	return false;
 52}
 53
 54string DirectoryGetBinary() {
 55	static string cached;
 56
 57	// %PROGRAMFILES%
 58
 59	if (cached is null) {
 60		wchar[] str;
 61
 62		int ret = GetEnvironmentVariableW("PROGRAMFILES\0"w.ptr, null, 0);
 63
 64		str = new wchar[ret];
 65		ret = GetEnvironmentVariableW("PROGRAMFILES\0"w.ptr, str.ptr, ret);
 66
 67		str = _SanitizeWindowsPath(str[0..ret]);
 68
 69		cached = Unicode.toUtf8(str) ~ "/" ~ Djehuty.app.name;
 70	}
 71
 72	return cached;
 73}
 74
 75string DirectoryGetAppData() {
 76	static string cached;
 77
 78	// %PROGRAMFILES%
 79
 80	if (cached is null) {
 81		wchar[] str = new wchar[5];
 82
 83		int ret = GetEnvironmentVariableW("PROGRAMFILES\0"w.ptr, str.ptr, 0);
 84
 85		str = new wchar[ret];
 86		ret = GetEnvironmentVariableW("PROGRAMFILES\0"w.ptr, str.ptr, ret);
 87
 88		str = _SanitizeWindowsPath(str[0..ret]);
 89
 90		cached = Unicode.toUtf8(str) ~ "/" ~ Djehuty.app.name;
 91	}
 92
 93	return cached;
 94}
 95
 96string DirectoryGetTempData() {
 97	static string cached;
 98
 99	if (cached is null) {
100		int ret = GetTempPathW(0, null);
101		ret++;
102
103		wchar[] str = new wchar[ret];
104
105		ret = GetTempPathW(ret, str.ptr);
106		str = _SanitizeWindowsPath(str[0..ret]);
107
108		cached = Unicode.toUtf8(str) ~ "/dpj" ~ toStr(GetCurrentProcessId());
109	}
110
111	return cached;
112}
113
114string DirectoryGetUserData() {
115	static string cached;
116
117	// %APPDATA%
118
119	if (cached is null) {
120		wchar[] str;
121
122		int ret = GetEnvironmentVariableW("APPDATA\0"w.ptr, null, 0);
123
124		str = new wchar[ret];
125		ret = GetEnvironmentVariableW("APPDATA\0"w.ptr, str.ptr, ret);
126
127		str = _SanitizeWindowsPath(str[0..ret]);
128
129		cached = Unicode.toUtf8(str) ~ "/" ~ Djehuty.app.name;
130	}
131
132	return cached;
133}
134
135string DirectoryGetApp() {
136	int size = 512;
137	int ret = 0;
138
139	wchar[] dir;
140
141	do {
142		dir = new wchar[size];
143		ret = GetModuleFileNameW(null, dir.ptr, size);
144		size <<= 2;
145	} while (size == ret)
146
147	if (ret > 0) {
148		dir = dir[0..ret-1];
149	}
150
151	dir = _SanitizeWindowsPath(dir);
152	dir = _TruncateFileName(dir);
153
154	return Unicode.toUtf8(dir);
155}
156
157string DirectoryGetCWD() {
158	int size = GetCurrentDirectoryW(0, null);
159	wchar[] cwd = new wchar[size];
160	GetCurrentDirectoryW(size, cwd.ptr);
161	cwd = cwd[0..$-1];
162
163	cwd = _SanitizeWindowsPath(cwd);
164
165	return Unicode.toUtf8(cwd);
166}
167
168bool DirectoryFileIsDir(string path) {
169	wchar[] strArr = _ConvertFrameworkPath(Unicode.toUtf16(path));
170	strArr ~= '\0';
171
172	DWORD ret = GetFileAttributesW(strArr.ptr);
173
174	return (ret & FILE_ATTRIBUTE_DIRECTORY) > 0;
175}
176
177bool DirectoryRename(ref string path, string newName) {
178	string old = path.dup;
179	old ~= '\0';
180
181	string str;
182
183	foreach_reverse(int i, chr; path) {
184		if (chr == '/') {
185			// truncate
186			str = path[0..i];
187			break;
188		}
189	}
190
191	if (str is null) {
192		return false;
193	}
194
195	str ~= '/';
196	str ~= newName;
197	str ~= '\0';
198
199	wchar[] strArr = _ConvertFrameworkPath(Unicode.toUtf16(str));
200	wchar[] oldArr = _ConvertFrameworkPath(Unicode.toUtf16(old));
201
202	MoveFileW(oldArr.ptr, strArr.ptr);
203	return true;
204}
205
206bool DirectoryMove(ref string path, string newPath) {
207	string old = path.dup;
208	old ~= '\0';
209
210	string str = newPath.dup;
211	str ~= '\0';
212
213	wchar[] strArr = _ConvertFrameworkPath(Unicode.toUtf16(str));
214	wchar[] oldArr = _ConvertFrameworkPath(Unicode.toUtf16(old));
215
216	MoveFileW(oldArr.ptr, strArr.ptr);
217	return true;
218}
219
220bool DirectoryCopy(ref string path, string newPath) {
221	string old = path.dup;
222	old ~= '\0';
223
224	string str = newPath.dup;
225	str ~= '\0';
226
227	wchar[] strArr = _ConvertFrameworkPath(Unicode.toUtf16(str));
228	wchar[] oldArr = _ConvertFrameworkPath(Unicode.toUtf16(old));
229
230	CopyFileW(oldArr.ptr, strArr.ptr, 0);
231	return true;
232}
233
234string[] _ReturnSharedFolders(wchar[] serverName) {
235	// Read all drives on this server
236	string[] ret;
237/*
238	SHARE_INFO_0* bufptr;
239
240	DWORD dwEntriesRead;
241	DWORD dwTotalEntries;
242	DWORD dwResumeHandle;
243
244	uint MAX_PREFERRED_LENGTH = short.max;
245
246	NetShareEnum(serverName.ptr, 0, cast(void**)&bufptr, -1,
247		&dwEntriesRead, &dwTotalEntries, &dwResumeHandle);
248
249	NetApiBufferFree(cast(void*)bufptr);
250
251	foreach(shareItem; bufptr[0..dwEntriesRead]) {
252		wchar[] pcchrs = shareItem.shi0_netname[0..strlen(shareItem.shi0_netname)];
253		if (pcchrs.length > 0 && pcchrs[$-1] != '$') {
254			ret ~= new String(Unicode.toUtf8(pcchrs));
255		}
256	}
257*/
258	return ret;
259}
260
261string[] _ReturnNetworkComputers() {
262	string[] ret;
263/*
264	HANDLE enumWorkgroupHandle;
265
266	DWORD bufferSize = 16284;
267
268	NETRESOURCEW[16284 / NETRESOURCEW.sizeof] networkResource;
269	WNetOpenEnumW(RESOURCE_GLOBALNET, RESOURCETYPE_ANY, 0, null, &enumWorkgroupHandle);
270
271	DWORD numEntries = -1;
272	WNetEnumResourceW(enumWorkgroupHandle, &numEntries, cast(void*)networkResource.ptr, &bufferSize);
273
274	foreach(item; networkResource[0..numEntries]) {
275		HANDLE subWorkgroupHandle;
276		WNetOpenEnumW(RESOURCE_GLOBALNET, RESOURCETYPE_ANY, 0, &item, &subWorkgroupHandle);
277		DWORD subEntries = -1;
278		NETRESOURCEW[16284 / NETRESOURCEW.sizeof] subResource;
279		DWORD subSize = 16284;
280		WNetEnumResourceW(subWorkgroupHandle, &subEntries, cast(void*)subResource.ptr, &subSize);
281
282		foreach(subitem; subResource[0..subEntries]) {
283			if (subitem.lpRemoteName !is null && subitem.dwDisplayType & RESOURCEDISPLAYTYPE_GROUP) {
284
285				// Read all computers on this workgroup
286
287				SERVER_INFO_101* bufptr;
288
289				DWORD dwEntriesRead;
290				DWORD dwTotalEntries;
291				DWORD dwResumeHandle;
292
293				uint MAX_PREFERRED_LENGTH = short.max;
294				NetServerEnum(null, 101, cast(void**)&bufptr, MAX_PREFERRED_LENGTH,
295					&dwEntriesRead, &dwTotalEntries, SV_TYPE_ALL, subitem.lpRemoteName, &dwResumeHandle);
296
297				SERVER_INFO_101* tmpptr = bufptr;
298				foreach(pcitem; tmpptr[0..dwEntriesRead]) {
299					wchar[] pcchrs = pcitem.sv101_name[0..strlen(pcitem.sv101_name)];
300					ret ~= new String(Unicode.toUtf8(pcchrs));
301				}
302
303				NetApiBufferFree(cast(void*)bufptr);
304			}
305		}
306
307		WNetCloseEnum(subWorkgroupHandle);
308	}
309
310	WNetCloseEnum(enumWorkgroupHandle);
311
312	SERVER_INFO_101* bufptr;
313
314	DWORD dwEntriesRead;
315	DWORD dwTotalEntries;
316	DWORD dwResumeHandle;
317
318	uint MAX_PREFERRED_LENGTH = short.max;
319	NetServerEnum(null, 101, cast(void**)&bufptr, MAX_PREFERRED_LENGTH,
320		&dwEntriesRead, &dwTotalEntries, SV_TYPE_ALL, null, &dwResumeHandle);
321
322	SERVER_INFO_101* tmpptr = bufptr;
323	foreach(pcitem; tmpptr[0..dwEntriesRead]) {
324		wchar[] pcchrs = pcitem.sv101_name[0..strlen(pcitem.sv101_name)];
325		// do not let in a duplicate
326		String thisPC = new String(Unicode.toUtf8(pcchrs));
327		bool isThere = false;
328		foreach(strFound; ret) {
329			if (strFound == thisPC) {
330				isThere = true;
331				break;
332			}
333		}
334		if (!isThere) {
335			ret ~= thisPC;
336		}
337	}
338
339	NetApiBufferFree(cast(void*)bufptr);
340*/
341	return ret;
342}
343
344wchar[] _SanitizeWindowsPath(wchar[] tmp) {
345	if (tmp.length == 0) { return tmp; }
346
347	// Handle networks
348
349	if (tmp.length > 1 && tmp[0..2] == "\\\\") {
350		tmp = "/network" ~ tmp[1..$];
351	}
352
353	// Change C: to /c
354
355	if (tmp.length > 1 && tmp[0] != '/') {
356		tmp[1] = tmp[0];
357		tmp[0] = '/';
358	}
359
360	// Convert slashes
361
362	foreach(int i, chr; tmp) {
363     	if(chr == '\\') {
364         	tmp[i] = '/';
365		}
366	}
367
368	// Remove final slash
369	if (tmp[tmp.length-1] == '/') {
370		tmp = tmp[0..tmp.length-1];
371	}
372
373	return tmp;
374}
375
376wchar[] _TruncateFileName(wchar[] tmp) {
377	if (tmp.length == 0) { return tmp; }
378
379	foreach_reverse(int i, chr; tmp) {
380     	if(chr == '/') {
381			return tmp[0..i];
382		}
383	}
384
385	return tmp;
386}
387
388wchar[] _ConvertFrameworkPath(wchar[] tmp) {
389	if (tmp.length == 0) { return tmp; }
390
391	// Handle networks
392
393	if (tmp.length > 9 && tmp[0..9] == "/network/") {
394		tmp = "\\\\" ~ tmp[9..$];
395	}
396
397	// Change /c to C:
398
399	if (tmp.length > 1 && tmp[0] == '/') {
400		tmp[0] = tmp[1];
401		tmp[1] = ':';
402	}
403
404	// No need to convert slashes, windows api accepts POSIX paths
405
406	return tmp;
407}
408
409string[] DirectoryList(ref DirectoryPlatformVars dirVars, string path) {
410
411	// trim trailing slash
412	if (path.length > 0 && path[path.length - 1] == '/' || path[path.length - 1] == '\\') {
413		path = path[0..path.length-1];
414	}
415
416	string newpath = path.dup;
417	newpath = Unicode.toUtf8(_ConvertFrameworkPath(Unicode.toUtf16(newpath)));
418
419	string[] list;
420
421	if (newpath == "") {
422		// root directory listing
423		// that is, list the network folder and all drives
424
425		int logicaldrives = GetLogicalDrives();
426
427		string curDrive = ['a'];
428
429		while(logicaldrives != 0) {
430			if ((logicaldrives & 1) == 1) {
431				list ~= curDrive;
432			}
433
434			if (curDrive[0] == 'z') { break; }
435
436			curDrive[0]++;
437			logicaldrives >>= 1;
438		}
439
440		list ~= "network";
441		return list;
442	}
443	/*else if (path.length >= 8 && path[0..8] == "/network") {
444		// Get relative path to /network
445		if (path.length == 8) {
446			return _ReturnNetworkComputers;
447		}
448		else {
449			String newPath = path.subString(9);
450			// find next slash (if there is one)
451			int pos = newPath.find("/");
452			if (pos == -1) {
453				// Just a pcname
454				return _ReturnSharedFolders(newPath.toUtf16 ~ "\0"w);
455			}
456			else {
457				// Fall through to normal directory listing
458			}
459		}
460	}*/
461	// regular directory listing
462	DirectoryOpen(dirVars, newpath);
463
464	WIN32_FIND_DATAW ffd;
465
466	wstring pn = Unicode.toUtf16(newpath);
467	pn ~= "/*";
468	pn ~= '\0';
469
470	HANDLE h = FindFirstFileW(pn.ptr, &ffd);
471	bool cont = true;
472
473	while(cont) {
474		// Caculate Length of d_name
475		int len;
476
477		foreach(chr; ffd.cFileName) {
478			if (chr == '\0') {
479				break;
480			}
481			len++;
482		}
483
484		// Add to list
485		if (ffd.cFileName[0..len] != "." && ffd.cFileName[0..len] != "..") {
486			list ~= Unicode.toUtf8(ffd.cFileName[0..len]);
487		}
488
489		// Retrieve next item in the directory
490		cont = FindNextFileW(h, &ffd) > 0;
491	}
492
493	DirectoryClose(dirVars);
494	return list;
495}