source: trunk/src/kernel32/disk.cpp@ 21567

Last change on this file since 21567 was 21567, checked in by dmik, 15 years ago

kernel32: Implemented GetVolumePathName() API.

File size: 34.2 KB
Line 
1/* $Id: disk.cpp,v 1.41 2004-03-25 09:19:46 sandervl Exp $ */
2
3/*
4 * Win32 Disk API functions for OS/2
5 *
6 * Copyright 1998-2002 Sander van Leeuwen
7 *
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12
13
14#include <odin.h>
15#include <odinwrap.h>
16#include <os2sel.h>
17
18#include <os2win.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22#include <versionos2.h>
23#include "unicode.h"
24#include "oslibdos.h"
25#include "osliblvm.h"
26#include "asmutil.h"
27#include "profile.h"
28#include "hmdisk.h"
29
30#define DBG_LOCALLOG DBG_disk
31#include "dbglocal.h"
32
33
34ODINDEBUGCHANNEL(KERNEL32-DISK)
35
36
37//******************************************************************************
38//******************************************************************************
39BOOL WIN32API SetVolumeLabelA( LPCSTR arg1, LPCSTR arg2)
40{
41 dprintf(("KERNEL32: OS2SetVolumeLabelA\n"));
42 return O32_SetVolumeLabel(arg1, arg2);
43}
44//******************************************************************************
45//******************************************************************************
46BOOL WIN32API SetVolumeLabelW(LPCWSTR lpRootPathName, LPCWSTR lpVolumeName)
47{
48 char *asciiroot, *asciivolname;
49 BOOL rc;
50
51 dprintf(("KERNEL32: OS2SetVolumeLabelW\n"));
52 asciiroot = UnicodeToAsciiString((LPWSTR)lpRootPathName);
53 asciivolname = UnicodeToAsciiString((LPWSTR)lpVolumeName);
54 rc = O32_SetVolumeLabel(asciiroot, asciivolname);
55 FreeAsciiString(asciivolname);
56 FreeAsciiString(asciiroot);
57 return(rc);
58}
59
60//******************************************************************************
61//******************************************************************************
62BOOL WIN32API GetDiskFreeSpaceA(LPCSTR lpszRootPathName, PDWORD lpSectorsPerCluster,
63 PDWORD lpBytesPerSector, PDWORD lpFreeClusters,
64 PDWORD lpClusters)
65{
66 BOOL rc;
67 DWORD dwSectorsPerCluster; // address of sectors per cluster ter
68 DWORD dwBytesPerSector; // address of bytes per sector
69 DWORD dwNumberOfFreeClusters; // address of number of free clusters
70 DWORD dwTotalNumberOfClusters; // address of total number of clusters
71
72 rc = OSLibGetDiskFreeSpace((LPSTR)lpszRootPathName, &dwSectorsPerCluster, &dwBytesPerSector,
73 &dwNumberOfFreeClusters, &dwTotalNumberOfClusters);
74 if(rc)
75 {
76 if (lpSectorsPerCluster!=NULL)
77 *lpSectorsPerCluster = dwSectorsPerCluster;
78 if (lpBytesPerSector!=NULL)
79 *lpBytesPerSector = dwBytesPerSector;
80 if (lpFreeClusters!=NULL)
81 *lpFreeClusters = dwNumberOfFreeClusters;
82 if (lpClusters!=NULL)
83 *lpClusters = dwTotalNumberOfClusters;
84
85 /* CW: Windows Media Player setup complains about wrong clustersize when odin is installed on
86 a TVFS drive. This fakes the clustersizes to 32. The following
87 entry must be present in ODIN.INI:
88
89 [DRIVESPACE]
90 TVFSTOHPFS = 1
91 */
92 if(lpSectorsPerCluster!=NULL)
93 {
94 if(*lpSectorsPerCluster==1024 && PROFILE_GetOdinIniBool("DRIVESPACE","CLUSTERTO32",0))
95 {/* TVFS returns 1024 sectors per cluster */
96 dprintf(("KERNEL32: GetDiskFreeSpaceA, TVFS-Drive detected. Faking clustersize to 32.\n"));
97 *lpSectorsPerCluster=32;
98 if (lpFreeClusters!=NULL)
99 *lpFreeClusters = dwNumberOfFreeClusters<<0x5;
100 if (lpClusters!=NULL)
101 *lpClusters = dwTotalNumberOfClusters<<0x5;
102 }
103 }
104 }
105 return rc;
106}
107//******************************************************************************
108//******************************************************************************
109BOOL WIN32API GetDiskFreeSpaceW(LPCWSTR lpszRootPathName,
110 PDWORD lpSectorsPerCluster,
111 PDWORD lpBytesPerSector,
112 PDWORD lpFreeClusters,
113 PDWORD lpClusters)
114{
115 BOOL rc;
116 char *astring;
117
118 astring = UnicodeToAsciiString((LPWSTR)lpszRootPathName);
119 rc = GetDiskFreeSpaceA(astring, lpSectorsPerCluster, lpBytesPerSector, lpFreeClusters, lpClusters);
120 FreeAsciiString(astring);
121 return(rc);
122}
123
124
125/*****************************************************************************
126 * Name : GetDiskFreeSpaceEx
127 * Purpose :
128 * Parameters: lpDirectoryName [in] Pointer to a null-terminated string that
129 * specifies a directory on the disk of interest.
130 * This string can be a UNC name. If this
131 * parameter is a UNC name, you must follow it
132 * with an additional backslash. For example, you
133 * would specify \\MyServer\MyShare as
134 * \\MyServer\MyShare\.
135 * If lpDirectoryName is NULL, the
136 * GetDiskFreeSpaceEx function obtains
137 * information about the object store.
138 * Note that lpDirectoryName does not have to
139 * specify the root directory on a disk. The
140 * function accepts any directory on the disk.
141 *
142 * lpFreeBytesAvailableToCaller
143 * [out] Pointer to a variable to receive the
144 * total number of free bytes on the disk that
145 * are available to the user associated with the
146 * calling thread.
147 * lpTotalNumberOfBytes
148 * [out] Pointer to a variable to receive the
149 * total number of bytes on the disk that are
150 * available to the user associated with the
151 * calling thread.
152 * lpTotalNumberOfFreeBytes
153 * [out] Pointer to a variable to receive the
154 * total number of free bytes on the disk.
155 * This parameter can be NULL.
156 * Variables :
157 * Result : Nonzero indicates success. Zero indicates failure. To get
158 * extended error information, call GetLastError.
159 * Remark : Note that the values obtained by this function are of type
160 * ULARGE_INTEGER. Be careful not to truncate these values to
161 * 32 bits.
162 * Status :
163 *
164 * Author : Patrick Haller [Fri, 2000/01/08 23:44]
165 *****************************************************************************/
166
167BOOL WIN32API GetDiskFreeSpaceExA(LPCSTR lpDirectoryName,
168 PULARGE_INTEGER lpFreeBytesAvailableToCaller,
169 PULARGE_INTEGER lpTotalNumberOfBytes,
170 PULARGE_INTEGER lpTotalNumberOfFreeBytes )
171{
172 BOOL rc;
173 DWORD dwSectorsPerCluster; // address of sectors per cluster ter
174 DWORD dwBytesPerSector; // address of bytes per sector
175 DWORD dwNumberOfFreeClusters; // address of number of free clusters
176 DWORD dwTotalNumberOfClusters; // address of total number of clusters
177
178 rc = GetDiskFreeSpaceA(lpDirectoryName, &dwSectorsPerCluster, &dwBytesPerSector,
179 &dwNumberOfFreeClusters, &dwTotalNumberOfClusters);
180 if(rc)
181 {
182 if(lpFreeBytesAvailableToCaller!=NULL) {
183 Mul32x32to64(lpFreeBytesAvailableToCaller, dwNumberOfFreeClusters, (dwSectorsPerCluster*dwBytesPerSector));
184 dprintf(("lpFreeBytesAvailableToCaller %x%x", lpFreeBytesAvailableToCaller->HighPart, lpFreeBytesAvailableToCaller->LowPart));
185 }
186 if(lpTotalNumberOfBytes!=NULL) {
187 Mul32x32to64(lpTotalNumberOfBytes, dwTotalNumberOfClusters, (dwSectorsPerCluster*dwBytesPerSector));
188 dprintf(("lpTotalNumberOfBytes %x%x", lpTotalNumberOfBytes->HighPart, lpTotalNumberOfBytes->LowPart));
189 }
190 if(lpTotalNumberOfFreeBytes!=NULL) {
191 memcpy(lpTotalNumberOfFreeBytes, lpFreeBytesAvailableToCaller, sizeof(*lpFreeBytesAvailableToCaller));
192 dprintf(("lpTotalNumberOfFreeBytes %x%x", lpTotalNumberOfFreeBytes->HighPart, lpTotalNumberOfFreeBytes->LowPart));
193 }
194 }
195 return rc;
196}
197//******************************************************************************
198//******************************************************************************
199BOOL WIN32API GetDiskFreeSpaceExW(LPCWSTR lpDirectoryName,
200 PULARGE_INTEGER lpFreeBytesAvailableToCaller,
201 PULARGE_INTEGER lpTotalNumberOfBytes,
202 PULARGE_INTEGER lpTotalNumberOfFreeBytes )
203{
204 BOOL rc;
205 char *astring;
206
207 dprintf(("KERNEL32: OS2GetDiskFreeSpaceExW\n"));
208 astring = UnicodeToAsciiString((LPWSTR)lpDirectoryName);
209 rc = GetDiskFreeSpaceExA(astring, lpFreeBytesAvailableToCaller, lpTotalNumberOfBytes, lpTotalNumberOfFreeBytes);
210 FreeAsciiString(astring);
211 return(rc);
212}
213//******************************************************************************
214//Note: NT4, SP6 does not change the last error, regardless of the junk it receives!
215//******************************************************************************
216UINT WIN32API GetDriveTypeA(LPCSTR lpszDrive)
217{
218 UINT rc;
219 ULONG driveIndex;
220
221 if(lpszDrive == 0) {
222 driveIndex = OSLibDosQueryCurrentDisk() - 1;
223 }
224 else
225 if(*lpszDrive >= 'A' && *lpszDrive <= 'Z')
226 driveIndex = (DWORD)(*lpszDrive - 'A');
227 else
228 if(*lpszDrive >= 'a' && *lpszDrive <= 'z') {
229 driveIndex = (DWORD)(*lpszDrive - 'a');
230 }
231 else {
232 //Volume functions only available in Windows 2000 and up
233 if(VERSION_IS_WIN2000_OR_HIGHER() && !strncmp(lpszDrive, VOLUME_NAME_PREFIX, sizeof(VOLUME_NAME_PREFIX)-1))
234 {
235 char *pszVolume;
236 int length;
237
238 //strip volume name prefix (\\\\?\\Volume\\)
239 length = strlen(lpszDrive);
240 pszVolume = (char *)alloca(length);
241
242 if(OSLibLVMStripVolumeName(lpszDrive, pszVolume, length))
243 {
244 rc = OSLibLVMGetDriveType(pszVolume);
245 dprintf(("KERNEL32: GetDriveType %s = %d (LVM)", lpszDrive, rc));
246 return rc;
247 }
248 }
249 return DRIVE_NO_ROOT_DIR; //return value checked in NT4, SP6 (GetDriveType(""), GetDriveType("4");
250 }
251
252 //NOTE: Although GetDriveTypeW handles -1, GetDriveTypeA crashes in NT 4, SP6
253 rc = OSLibGetDriveType(driveIndex);
254 dprintf(("KERNEL32: GetDriveType %s = %d", lpszDrive, rc));
255 return rc;
256}
257//******************************************************************************
258//******************************************************************************
259UINT WIN32API GetDriveTypeW(LPCWSTR lpszDrive)
260{
261 UINT rc;
262 char *astring;
263
264 if(lpszDrive == (LPCWSTR)-1) {
265 return DRIVE_CANNOTDETERMINE; //NT 4, SP6 returns this (VERIFIED)
266 }
267 astring = UnicodeToAsciiString((LPWSTR)lpszDrive);
268 dprintf(("KERNEL32: GetDriveTypeW %s", astring));
269 rc = GetDriveTypeA(astring);
270 FreeAsciiString(astring);
271 return(rc);
272}
273//******************************************************************************
274static int fForce2GBFileSize = FALSE;
275//******************************************************************************
276void WIN32API CustForce2GBFileSize()
277{
278 fForce2GBFileSize = TRUE;
279}
280//******************************************************************************
281//******************************************************************************
282BOOL WIN32API GetVolumeInformationA(LPCSTR lpRootPathName,
283 LPSTR lpVolumeNameBuffer,
284 DWORD nVolumeNameSize,
285 PDWORD lpVolumeSerialNumber,
286 PDWORD lpMaximumComponentLength,
287 PDWORD lpFileSystemFlags,
288 LPSTR lpFileSystemNameBuffer,
289 DWORD nFileSystemNameSize)
290{
291 CHAR tmpstring[256];
292 CHAR szOrgFileSystemName[256] = "";
293 ULONG drive;
294 BOOL rc, fVolumeName = FALSE;
295 char *pszVolume;
296
297 dprintf(("GetVolumeInformationA %s", lpRootPathName));
298
299 if(lpRootPathName == NULL) {
300 GetCurrentDirectoryA(sizeof(tmpstring), tmpstring);
301 lpRootPathName = tmpstring;
302 }
303
304 if('A' <= *lpRootPathName && *lpRootPathName <= 'Z') {
305 drive = *lpRootPathName - 'A' + 1;
306 }
307 else
308 if('a' <= *lpRootPathName && *lpRootPathName <= 'z') {
309 drive = *lpRootPathName - 'a' + 1;
310 }
311 else {
312 //Volume functions only available in Windows 2000 and up
313 if(LOBYTE(GetVersion()) >= 5 && !strncmp(lpRootPathName, VOLUME_NAME_PREFIX, sizeof(VOLUME_NAME_PREFIX)-1))
314 {
315 int length;
316
317 //strip volume name prefix (\\\\?\\Volume\\)
318 length = strlen(lpRootPathName);
319 pszVolume = (char *)alloca(length);
320
321 if(OSLibLVMStripVolumeName(lpRootPathName, pszVolume, length))
322 {
323 pszVolume[length-2] = 0;
324 fVolumeName = TRUE;
325 goto proceed;
326 }
327 }
328 SetLastError(ERROR_INVALID_PARAMETER);
329 return FALSE;
330 }
331proceed:
332
333 if(lpVolumeSerialNumber || lpVolumeNameBuffer) {
334 if(fVolumeName) {
335 rc = OSLibLVMQueryVolumeSerialAndName(pszVolume, lpVolumeSerialNumber, lpVolumeNameBuffer, nVolumeNameSize);
336 }
337 else rc = OSLibDosQueryVolumeSerialAndName(drive, lpVolumeSerialNumber, lpVolumeNameBuffer, nVolumeNameSize);
338 if(lpVolumeSerialNumber) {
339 dprintf2(("Volume serial number: %x", *lpVolumeSerialNumber));
340 }
341 if(lpVolumeNameBuffer) {
342 dprintf2(("Volume name: %s", lpVolumeNameBuffer));
343 }
344 }
345 if(lpFileSystemNameBuffer || lpMaximumComponentLength || lpFileSystemFlags)
346 {
347 if(!lpFileSystemNameBuffer || (nFileSystemNameSize == 0)) {
348 lpFileSystemNameBuffer = tmpstring;
349 nFileSystemNameSize = sizeof(tmpstring);
350 }
351 if(fVolumeName) {
352 rc = OSLibLVMQueryVolumeFS(pszVolume, lpFileSystemNameBuffer, nFileSystemNameSize);
353 }
354 else rc = OSLibDosQueryVolumeFS(drive, lpFileSystemNameBuffer, nFileSystemNameSize);
355
356 //save original file system name
357 if(rc == ERROR_SUCCESS) strcpy(szOrgFileSystemName, lpFileSystemNameBuffer);
358
359 if(lpFileSystemNameBuffer)
360 {
361 dprintf2(("File system name: %s", lpFileSystemNameBuffer));
362 if(!strcmp(lpFileSystemNameBuffer, "JFS"))
363 {
364 strncpy(lpFileSystemNameBuffer, "NTFS", nFileSystemNameSize);
365 }
366 else
367 if(!strcmp(lpFileSystemNameBuffer, "CDFS") ||
368 !strcmp(lpFileSystemNameBuffer, "UDF") ||
369 !strcmp(lpFileSystemNameBuffer, "NTFS") ||
370 !strcmp(lpFileSystemNameBuffer, "FAT32"))
371 {
372 //do nothing
373 }
374 else
375 {//pretend everything else is FAT16 (HPFS and FAT have the same file size limit)
376 // @@VP:20040323 - nFileSystemNameSize may be 0!!!
377 strncpy(lpFileSystemNameBuffer, "FAT16", nFileSystemNameSize);
378 }
379 if(fForce2GBFileSize) {
380 if(strcmp(lpFileSystemNameBuffer, "CDFS") &&
381 strcmp(lpFileSystemNameBuffer, "UDF"))
382 {//everything is FAT -> 2 GB file size limit
383 strncpy(lpFileSystemNameBuffer, "FAT16", nFileSystemNameSize);
384 }
385 }
386 dprintf2(("Final file system name: %s", lpFileSystemNameBuffer));
387 }
388 }
389 if(lpMaximumComponentLength) {
390 if(!strcmp(szOrgFileSystemName, "FAT16") || !strcmp(szOrgFileSystemName, "FAT")) {
391 *lpMaximumComponentLength = 12; //8.3
392 }
393 else *lpMaximumComponentLength = 255; //TODO: Always correct? (CDFS?)
394 }
395 if(lpFileSystemFlags)
396 {
397 if(strcmp(lpFileSystemNameBuffer, "FAT16")) {
398 *lpFileSystemFlags = FS_CASE_IS_PRESERVED;
399 }
400 else
401 if(!strcmp(lpFileSystemNameBuffer, "CDFS")) {
402 *lpFileSystemFlags = FS_CASE_SENSITIVE; //NT4 returns this
403 }
404 else
405 if(!strcmp(lpFileSystemNameBuffer, "UDF")) {//TODO: correct?
406 *lpFileSystemFlags = FS_CASE_SENSITIVE | FS_UNICODE_STORED_ON_DISK;
407 }
408 else *lpFileSystemFlags = 0;
409
410 dprintf2(("File system flags: %x", lpFileSystemFlags));
411 }
412
413 if(rc) {
414 SetLastError(rc);
415 return FALSE;
416 }
417 SetLastError(ERROR_SUCCESS);
418 return TRUE;
419}
420//******************************************************************************
421//******************************************************************************
422BOOL WIN32API GetVolumeInformationW(LPCWSTR lpRootPathName,
423 LPWSTR lpVolumeNameBuffer,
424 DWORD nVolumeNameSize,
425 PDWORD lpVolumeSerialNumber,
426 PDWORD lpMaximumComponentLength,
427 PDWORD lpFileSystemFlags,
428 LPWSTR lpFileSystemNameBuffer,
429 DWORD nFileSystemNameSize)
430{
431 char *asciiroot,
432 *asciivol,
433 *asciifs;
434 BOOL rc;
435
436 // transform into ascii
437 asciivol = (char *)malloc(nVolumeNameSize+1);
438 asciifs = (char *)malloc(nFileSystemNameSize+1);
439
440 // clear ascii buffers
441 memset (asciivol, 0, (nVolumeNameSize + 1));
442 memset (asciifs, 0, (nFileSystemNameSize + 1));
443
444 if (lpRootPathName != NULL) // NULL is valid!
445 asciiroot = UnicodeToAsciiString((LPWSTR)lpRootPathName);
446 else
447 asciiroot = NULL;
448
449 rc = GetVolumeInformationA(asciiroot, asciivol, nVolumeNameSize, lpVolumeSerialNumber,
450 lpMaximumComponentLength, lpFileSystemFlags, asciifs, nFileSystemNameSize);
451
452 if (lpVolumeNameBuffer != NULL) /* @@@PH 98/06/07 */
453 AsciiToUnicodeN(asciivol, lpVolumeNameBuffer, nVolumeNameSize);
454
455 if (lpFileSystemNameBuffer != NULL) /* @@@PH 98/06/07 */
456 AsciiToUnicodeN(asciifs, lpFileSystemNameBuffer, nFileSystemNameSize);
457
458 if (asciiroot != NULL)
459 FreeAsciiString(asciiroot);
460
461 free(asciifs);
462 free(asciivol);
463 return(rc);
464}
465//******************************************************************************
466//******************************************************************************
467DWORD WIN32API GetLogicalDrives(void)
468{
469 dprintf(("KERNEL32: GetLogicalDrives\n"));
470 return OSLibGetLogicalDrives();
471}
472//******************************************************************************
473//******************************************************************************
474UINT WIN32API GetLogicalDriveStringsA(UINT cchBuffer, LPSTR lpszBuffer)
475{
476 dprintf(("KERNEL32: GetLogicalDriveStringsA", cchBuffer, lpszBuffer));
477 return O32_GetLogicalDriveStrings(cchBuffer, lpszBuffer);
478}
479//******************************************************************************
480//******************************************************************************
481UINT WIN32API GetLogicalDriveStringsW(UINT nBufferLength, LPWSTR lpBufferW)
482{
483 LPSTR lpBufferA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, sizeof(CHAR) * (nBufferLength + 1) );
484 DWORD dwResult = GetLogicalDriveStringsA( nBufferLength, lpBufferA );
485
486 dprintf(("KERNEL32: GetLogicalDriveStringsW %d %x", nBufferLength, lpBufferA));
487
488 if ( dwResult && dwResult <= nBufferLength )
489 MultiByteToWideChar( CP_ACP, 0, lpBufferA, dwResult + 1, lpBufferW, nBufferLength );
490
491 HeapFree( GetProcessHeap(), 0, lpBufferA );
492
493 return dwResult;
494}
495//******************************************************************************
496typedef struct {
497 HANDLE hLVMVolumeControlData;
498 DWORD lastvol;
499} VOLINFO;
500//******************************************************************************
501HANDLE WIN32API FindFirstVolumeA(LPTSTR lpszVolumeName, DWORD cchBufferLength)
502{
503 HANDLE hVolume;
504 VOLINFO *pVolInfo;
505 char szdrive[3];
506 char szVolume[256];
507
508 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
509 SetLastError(ERROR_NOT_SUPPORTED);
510 return FALSE;
511 }
512
513 hVolume = GlobalAlloc(0, sizeof(VOLINFO));
514 if(hVolume == 0) {
515 dprintf(("ERROR: FindFirstVolumeA: out of memory!!"));
516 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
517 return 0;
518 }
519 pVolInfo = (VOLINFO *)GlobalLock(hVolume);
520 pVolInfo->hLVMVolumeControlData = OSLibLVMQueryVolumeControlData();
521 pVolInfo->lastvol = 0;
522
523 if(OSLibLVMQueryVolumeName(pVolInfo->hLVMVolumeControlData, &pVolInfo->lastvol, szVolume, sizeof(szVolume)) == FALSE) {
524 SetLastError(ERROR_NO_MORE_FILES);
525 goto fail;
526 }
527 if(strlen(szVolume) + 14 + 1 > cchBufferLength) {
528 SetLastError(ERROR_INSUFFICIENT_BUFFER);
529 goto fail;
530 }
531 sprintf(lpszVolumeName, VOLUME_NAME_PREFIX"{%s}\\", szVolume);
532 dprintf(("FindFirstVolumeA returned %s", lpszVolumeName));
533 pVolInfo->lastvol++;
534 GlobalUnlock(hVolume);
535 SetLastError(ERROR_SUCCESS);
536 return hVolume;
537
538fail:
539 GlobalUnlock(hVolume);
540 GlobalFree(hVolume);
541 return 0;
542}
543//******************************************************************************
544//******************************************************************************
545HANDLE WIN32API FindFirstVolumeW(LPWSTR lpszVolumeName, DWORD cchBufferLength)
546{
547 LPSTR pszvolname = NULL;
548 HANDLE hVolume;
549
550 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
551 SetLastError(ERROR_NOT_SUPPORTED);
552 return FALSE;
553 }
554
555 if(cchBufferLength) {
556 pszvolname = (char *)alloca(cchBufferLength);
557 }
558 hVolume = FindFirstVolumeA(pszvolname, cchBufferLength);
559 if(hVolume) {
560 int len = MultiByteToWideChar( CP_ACP, 0, pszvolname, -1, NULL, 0);
561 MultiByteToWideChar(CP_ACP, 0, pszvolname, -1, lpszVolumeName, len);
562 }
563 return hVolume;
564}
565//******************************************************************************
566//******************************************************************************
567BOOL WIN32API FindNextVolumeA(HANDLE hFindVolume, LPTSTR lpszVolumeName,
568 DWORD cchBufferLength)
569{
570 VOLINFO *pVolInfo;
571 char szdrive[3];
572 DWORD DeviceType;
573 char szVolume[256];
574
575 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
576 SetLastError(ERROR_NOT_SUPPORTED);
577 return FALSE;
578 }
579
580 pVolInfo = (VOLINFO *)GlobalLock(hFindVolume);
581 if(pVolInfo == NULL) {
582 SetLastError(ERROR_INVALID_PARAMETER);
583 return FALSE;
584 }
585 if(OSLibLVMQueryVolumeName(pVolInfo->hLVMVolumeControlData, &pVolInfo->lastvol,
586 szVolume, sizeof(szVolume)) == FALSE) {
587 SetLastError(ERROR_NO_MORE_FILES);
588 GlobalUnlock(hFindVolume);
589 return FALSE;
590 }
591 if(strlen(szVolume) + 14 + 1 > cchBufferLength) {
592 SetLastError(ERROR_INSUFFICIENT_BUFFER);
593 GlobalUnlock(hFindVolume);
594 return FALSE;
595 }
596 sprintf(lpszVolumeName, VOLUME_NAME_PREFIX"{%s}\\", szVolume);
597 dprintf(("FindNextVolumeA returned %s", lpszVolumeName));
598 pVolInfo->lastvol++;
599 GlobalUnlock(hFindVolume);
600 SetLastError(ERROR_SUCCESS);
601 return TRUE;
602}
603//******************************************************************************
604//******************************************************************************
605BOOL WIN32API FindNextVolumeW(HANDLE hFindVolume, LPWSTR lpszVolumeName,
606 DWORD cchBufferLength)
607{
608 LPSTR pszvolnameA = NULL;
609 BOOL ret;
610
611 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
612 SetLastError(ERROR_NOT_SUPPORTED);
613 return FALSE;
614 }
615
616 if(cchBufferLength) {
617 pszvolnameA = (char *)alloca(cchBufferLength);
618 }
619 ret = FindNextVolumeA(hFindVolume, pszvolnameA, cchBufferLength);
620 if(ret) {
621 int len = MultiByteToWideChar( CP_ACP, 0, pszvolnameA, -1, NULL, 0);
622 MultiByteToWideChar(CP_ACP, 0, pszvolnameA, -1, lpszVolumeName, len);
623 }
624 return ret;
625}
626//******************************************************************************
627//******************************************************************************
628BOOL WIN32API FindVolumeClose(HANDLE hFindVolume)
629{
630 VOLINFO *pVolInfo;
631
632 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
633 SetLastError(ERROR_NOT_SUPPORTED);
634 return FALSE;
635 }
636
637 if(hFindVolume) {
638 pVolInfo = (VOLINFO *)GlobalLock(hFindVolume);
639 OSLibLVMFreeVolumeControlData(pVolInfo->hLVMVolumeControlData);
640 GlobalUnlock(hFindVolume);
641 GlobalFree(hFindVolume);
642 return TRUE;
643 }
644 return FALSE;
645}
646//******************************************************************************
647//******************************************************************************
648HANDLE WIN32API FindFirstVolumeMountPointA(LPTSTR lpszRootPathName,
649 LPTSTR lpszVolumeMountPoint,
650 DWORD cchBufferLength)
651{
652 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
653 SetLastError(ERROR_NOT_SUPPORTED);
654 return INVALID_HANDLE_VALUE;
655 }
656
657 SetLastError(ERROR_NO_MORE_FILES);
658 return INVALID_HANDLE_VALUE;
659}
660//******************************************************************************
661//******************************************************************************
662HANDLE WIN32API FindFirstVolumeMountPointW(LPWSTR lpszRootPathName,
663 LPWSTR lpszVolumeMountPoint,
664 DWORD cchBufferLength)
665{
666 LPSTR pszmountpointnameA = NULL;
667 LPSTR pszrootA = NULL;
668 HANDLE hVolume;
669
670 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
671 SetLastError(ERROR_NOT_SUPPORTED);
672 return INVALID_HANDLE_VALUE;
673 }
674
675 if(cchBufferLength) {
676 pszmountpointnameA = (char *)alloca(cchBufferLength);
677 }
678 if(lpszRootPathName) {
679 pszrootA = (char *)alloca(lstrlenW(lpszRootPathName)+1);
680
681 int len = WideCharToMultiByte( CP_ACP, 0, lpszRootPathName, -1, NULL, 0, 0, NULL);
682 WideCharToMultiByte(CP_ACP, 0, lpszRootPathName, -1, pszrootA, len, 0, NULL);
683 }
684
685 hVolume = FindFirstVolumeMountPointA(pszrootA, pszmountpointnameA, cchBufferLength);
686 if(hVolume) {
687 int len = MultiByteToWideChar( CP_ACP, 0, pszmountpointnameA, -1, NULL, 0);
688 MultiByteToWideChar(CP_ACP, 0, pszmountpointnameA, -1, lpszVolumeMountPoint, len);
689 }
690 return hVolume;
691}
692//******************************************************************************
693//******************************************************************************
694BOOL WIN32API FindNextVolumeMountPointA(HANDLE hFindVolumeMountPoint,
695 LPTSTR lpszVolumeMountPoint,
696 DWORD cchBufferLength)
697{
698 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
699 SetLastError(ERROR_NOT_SUPPORTED);
700 return FALSE;
701 }
702 SetLastError(ERROR_NO_MORE_FILES);
703 return FALSE;
704}
705//******************************************************************************
706//******************************************************************************
707BOOL WIN32API FindNextVolumeMountPointW(HANDLE hFindVolumeMountPoint,
708 LPWSTR lpszVolumeMountPoint,
709 DWORD cchBufferLength)
710{
711 LPSTR pszmoutpointnameA = NULL;
712 BOOL ret;
713
714 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
715 SetLastError(ERROR_NOT_SUPPORTED);
716 return FALSE;
717 }
718
719 if(cchBufferLength) {
720 pszmoutpointnameA = (char *)alloca(cchBufferLength);
721 }
722 ret = FindFirstVolumeA(pszmoutpointnameA, cchBufferLength);
723 if(ret) {
724 int len = MultiByteToWideChar( CP_ACP, 0, pszmoutpointnameA, -1, NULL, 0);
725 MultiByteToWideChar(CP_ACP, 0, pszmoutpointnameA, -1, lpszVolumeMountPoint, len);
726 }
727 return ret;
728}
729//******************************************************************************
730//******************************************************************************
731BOOL WIN32API FindVolumeMountPointClose(HANDLE hFindVolumeMountPoint)
732{
733 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
734 SetLastError(ERROR_NOT_SUPPORTED);
735 return FALSE;
736 }
737
738 if(hFindVolumeMountPoint) {
739 GlobalFree(hFindVolumeMountPoint);
740 return TRUE;
741 }
742 return FALSE;
743}
744//******************************************************************************
745//******************************************************************************
746BOOL WIN32API GetVolumeNameForVolumeMountPointA(LPCSTR lpszVolumeMountPoint,
747 LPSTR lpszVolumeName,
748 DWORD cchBufferLength)
749{
750 LPSTR pszvol;
751
752 pszvol = (char *)alloca(cchBufferLength);
753 if(pszvol == NULL) {
754 DebugInt3();
755 return FALSE;
756 }
757
758 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
759 SetLastError(ERROR_NOT_SUPPORTED);
760 return FALSE;
761 }
762
763 if(OSLibLVMGetVolumeNameForVolumeMountPoint(lpszVolumeMountPoint, pszvol,
764 cchBufferLength) == TRUE)
765 {
766 int length = strlen(pszvol);
767 if(length + sizeof(VOLUME_NAME_PREFIX) - 1 + 3 > cchBufferLength) {
768 SetLastError(ERROR_INSUFFICIENT_BUFFER);
769 return FALSE;
770 }
771 sprintf(lpszVolumeName, VOLUME_NAME_PREFIX"{%s}\\", pszvol);
772
773 dprintf(("KERNEL32: GetVolumeNameForVolumeMountPointA %s returned %s", lpszVolumeMountPoint, lpszVolumeName));
774 SetLastError(ERROR_SUCCESS);
775 return TRUE;
776 }
777 dprintf(("KERNEL32: GetVolumeNameForVolumeMountPointA: %s not found!!", lpszVolumeMountPoint));
778 SetLastError(ERROR_FILE_NOT_FOUND);
779 return FALSE;
780}
781//******************************************************************************
782//******************************************************************************
783BOOL WIN32API GetVolumeNameForVolumeMountPointW(LPCWSTR lpszVolumeMountPoint,
784 LPWSTR lpszVolumeName,
785 DWORD cchBufferLength)
786{
787 LPSTR pszmoutpointnameA = NULL;
788 LPSTR pszvolumenameA = NULL;
789 BOOL ret;
790 int len;
791
792 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
793 SetLastError(ERROR_NOT_SUPPORTED);
794 return FALSE;
795 }
796 len = WideCharToMultiByte( CP_ACP, 0, lpszVolumeMountPoint, -1, NULL, 0, 0, NULL);
797 pszmoutpointnameA = (char *)alloca(len+1);
798 WideCharToMultiByte(CP_ACP, 0, lpszVolumeMountPoint, -1, pszmoutpointnameA, len, 0, NULL);
799
800 if(cchBufferLength && lpszVolumeName) {
801 pszvolumenameA = (char *)alloca(cchBufferLength);
802 }
803 ret = GetVolumeNameForVolumeMountPointA(pszmoutpointnameA, pszvolumenameA, cchBufferLength);
804 if(ret) {
805 int len = MultiByteToWideChar( CP_ACP, 0, pszvolumenameA, -1, NULL, 0);
806 MultiByteToWideChar(CP_ACP, 0, pszvolumenameA, -1, lpszVolumeName, len);
807 }
808 return ret;
809}
810//******************************************************************************
811//******************************************************************************
812BOOL WIN32API GetVolumePathNameA(LPCSTR lpszFileName,
813 LPSTR lpszVolumePathName,
814 DWORD cchBufferLength)
815{
816 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
817 SetLastError(ERROR_NOT_SUPPORTED);
818 return FALSE;
819 }
820
821 if(!*lpszFileName) {
822 // According to MSDN:
823 SetLastError(ERROR_SUCCESS);
824 return FALSE;
825 }
826
827 // We only support drive letters as volume names
828 if(cchBufferLength < 3) {
829 SetLastError(ERROR_INSUFFICIENT_BUFFER);
830 return FALSE;
831 }
832
833 CHAR fullName[MAX_PATH];
834 DWORD rc = GetFullPathNameA(lpszFileName, sizeof(fullName), fullName, NULL);
835 if (rc == 0 || rc > sizeof(fullName))
836 return FALSE;
837
838 if(fullName[0] == '\\' && fullName[1] == '\\') {
839 // UNC path, search for the 2nd single slash: we should return "\\foo\bar\"
840 LPSTR slash1 = strchr(&fullName[2], '\\');
841 if(!slash1 || slash1 - fullName == 2) {
842 SetLastError(ERROR_INVALID_NAME);
843 return FALSE;
844 }
845 LPSTR slash2 = strchr(slash1 + 1, '\\');
846 if(!slash2 || slash2 - slash1 == 1) {
847 SetLastError(ERROR_INVALID_NAME);
848 return FALSE;
849 }
850 DWORD len = slash2 - fullName + 1; // with trailing slash
851 if(cchBufferLength < len + 1) {
852 SetLastError(ERROR_INSUFFICIENT_BUFFER);
853 return FALSE;
854 }
855 memcpy(lpszVolumePathName, fullName, len);
856 lpszVolumePathName[len] = '\0';
857 } else {
858 lpszVolumePathName[0] = fullName[0];
859 lpszVolumePathName[1] = ':';
860 if(cchBufferLength == 3) {
861 lpszVolumePathName[2] = '\0';
862 } else {
863 lpszVolumePathName[2] = '\\';
864 lpszVolumePathName[3] = '\0';
865 }
866 }
867
868 dprintf(("KERNEL32: GetVolumePathNameA %s returned %s", lpszFileName, lpszVolumePathName));
869 SetLastError(ERROR_SUCCESS);
870 return TRUE;
871}
872//******************************************************************************
873//******************************************************************************
874BOOL WIN32API GetVolumePathNameW(LPCWSTR lpszFileName,
875 LPWSTR lpszVolumePathName,
876 DWORD cchBufferLength)
877{
878 LPSTR lpszFileNameA = NULL;
879 LPSTR lpszVolumePathNameA = NULL;
880 BOOL ret;
881 int len;
882
883 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
884 SetLastError(ERROR_NOT_SUPPORTED);
885 return FALSE;
886 }
887 len = WideCharToMultiByte( CP_ACP, 0, lpszFileName, -1, NULL, 0, 0, NULL);
888 lpszFileNameA = (char *)alloca(len+1);
889 WideCharToMultiByte(CP_ACP, 0, lpszFileName, -1, lpszFileNameA, len, 0, NULL);
890
891 if(cchBufferLength && lpszVolumePathName) {
892 lpszVolumePathNameA = (char *)alloca(cchBufferLength);
893 }
894 ret = GetVolumePathNameA(lpszFileNameA, lpszVolumePathNameA, cchBufferLength);
895 if(ret) {
896 int len = MultiByteToWideChar( CP_ACP, 0, lpszVolumePathNameA, -1, NULL, 0);
897 MultiByteToWideChar(CP_ACP, 0, lpszVolumePathNameA, -1, lpszVolumePathName, len);
898 }
899 return ret;
900}
901//******************************************************************************
902//******************************************************************************
Note: See TracBrowser for help on using the repository browser.