source: trunk/src/ufat32/win32.c@ 282

Last change on this file since 282 was 282, checked in by Valery V. Sedletski, 8 years ago
  • Different exFAT-related additions for CHKDSK
  • Return "unimplemented" on SYSINSTX attempts
  • Attempts to fix traps in malloc() in exFAT CHKDSK code. It appears that heap is corrupted somewhere. Also, added experimental mem_alloc2() function, to allocate memory via a CHKDSK.SYS driver (non-working, yet).
File size: 18.1 KB
Line 
1/* Win32-specific functions
2 *
3 */
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8
9#include "fat32c.h"
10
11HANDLE hDev;
12
13char msg = FALSE;
14
15void LogOutMessagePrintf(ULONG ulMsgNo, char *psz, ULONG ulParmNo, va_list va);
16
17DWORD get_vol_id (void)
18{
19 SYSTEMTIME s;
20 DWORD d;
21 WORD lo,hi,tmp;
22
23 GetLocalTime( &s );
24
25 lo = s.wDay + ( s.wMonth << 8 );
26 tmp = (s.wMilliseconds/10) + (s.wSecond << 8 );
27 lo += tmp;
28
29 hi = s.wMinute + ( s.wHour << 8 );
30 hi += s.wYear;
31
32 d = lo + (hi << 16);
33 return(d);
34}
35
36void die ( char * error, DWORD rc )
37{
38 // Retrieve the system error message for the last-error code
39
40 LPVOID lpMsgBuf;
41 DWORD dw = GetLastError();
42
43 if ( dw )
44 {
45 // Display the error message and exit the process
46 fprintf ( stderr, "%s\nGetLastError() == %d: %s\n", error, dw, get_error(dw) );
47 }
48 else
49 {
50 fprintf ( stderr, "%s\n", error );
51 }
52
53 LocalFree(lpMsgBuf);
54
55 exit (dw);
56}
57
58void seek_to_sect( HANDLE hDevice, DWORD Sector, DWORD BytesPerSect )
59{
60 LONGLONG Offset;
61 LONG HiOffset;
62
63 Offset = Sector * BytesPerSect ;
64 HiOffset = (LONG) (Offset>>32);
65 SetFilePointer ( hDevice, (LONG) Offset , &HiOffset , FILE_BEGIN );
66}
67
68
69BOOL read_file ( HANDLE hDevice, BYTE *pData, DWORD ulNumBytes, DWORD *dwRead )
70{
71 return ReadFile ( hDevice, pData, ulNumBytes, dwRead, NULL );
72}
73
74
75ULONG ReadSect ( HANDLE hDevice, LONG ulSector, USHORT nSectors, USHORT BytesPerSector, PBYTE pbSector )
76{
77 DWORD dwRead;
78 BOOL ret;
79
80 seek_to_sect ( hDevice, ulSector, BytesPerSector );
81
82 ret = ReadFile ( hDevice, pbSector, nSectors * BytesPerSector, &dwRead, NULL );
83
84 if ( !ret )
85 return GetLastError();
86
87 return 0;
88}
89
90
91ULONG WriteSect ( HANDLE hDevice, LONG ulSector, USHORT nSectors, USHORT BytesPerSector, PBYTE pbSector )
92{
93 DWORD dwWritten;
94 BOOL ret;
95
96 seek_to_sect ( hDevice, ulSector, BytesPerSector );
97 ret = WriteFile ( hDevice, pbSector, nSectors * BytesPerSector, &dwWritten, NULL );
98
99 if ( !ret )
100 return GetLastError();
101
102 return 0;
103}
104
105ULONG write_sect ( HANDLE hDevice, DWORD Sector, DWORD BytesPerSector, void *Data, DWORD NumSects )
106{
107 DWORD rc;
108
109 rc = WriteSect ( hDevice, Sector, NumSects, BytesPerSector, Data );
110
111 return rc;
112}
113
114void open_drive (char *path , HANDLE *hDevice)
115{
116 char DriveDevicePath[]="\\\\.\\Z:"; // for CreateFile
117 char *p = path;
118 ULONG cbRet;
119 BOOL bRet;
120
121 if (strlen(path) == 2 && path[1] == ':')
122 {
123 // drive letter (UNC)
124 DriveDevicePath[4] = *path;
125 p = DriveDevicePath;
126 }
127
128 // open the drive
129 *hDevice = CreateFile (
130 p,
131 GENERIC_READ | GENERIC_WRITE,
132 0,
133 NULL,
134 OPEN_EXISTING,
135 FILE_FLAG_NO_BUFFERING,
136 NULL);
137 if ( *hDevice == INVALID_HANDLE_VALUE )
138 die( "Failed to open device - close any files before formatting,\n"
139 "and make sure you have Admin rights when using fat32format\n"
140 "Are you SURE you're formatting the RIGHT DRIVE!!!\n", -1 );
141
142 hDev = *hDevice;
143
144 bRet = DeviceIoControl(
145 (HANDLE) *hDevice, // handle to device
146 FSCTL_ALLOW_EXTENDED_DASD_IO, // dwIoControlCode
147 NULL, // lpInBuffer
148 0, // nInBufferSize
149 NULL, // lpOutBuffer
150 0, // nOutBufferSize
151 &cbRet, // number of bytes returned
152 NULL // OVERLAPPED structure
153 );
154
155 if ( !bRet )
156 show_message ( "Failed to allow extended DASD on device.\n", 0, 0, 0 );
157}
158
159void lock_drive(HANDLE hDevice)
160{
161 BOOL bRet;
162 DWORD cbRet;
163
164 // lock it
165 bRet = DeviceIoControl( hDevice, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &cbRet, NULL );
166
167 if ( !bRet )
168 die( "Failed to lock device", bRet );
169}
170
171void unlock_drive(HANDLE hDevice)
172{
173 BOOL bRet;
174 DWORD cbRet;
175
176 bRet = DeviceIoControl( hDevice, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &cbRet, NULL );
177
178 if ( !bRet )
179 die( "Failed to unlock device", -8 );
180}
181
182BOOL get_drive_params(HANDLE hDevice, struct extbpb *dp)
183{
184 BOOL bRet;
185 DWORD cbRet;
186 DISK_GEOMETRY dgDrive;
187 PARTITION_INFORMATION piDrive;
188
189 PARTITION_INFORMATION_EX xpiDrive;
190 BOOL bGPTMode = FALSE;
191 SET_PARTITION_INFORMATION spiDrive;
192
193 // work out drive params
194 bRet = DeviceIoControl ( hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY,
195 NULL, 0, &dgDrive, sizeof(dgDrive),
196 &cbRet, NULL);
197
198 if ( !bRet )
199 die( "Failed to get device geometry", -10 );
200
201 bRet = DeviceIoControl ( hDevice,
202 IOCTL_DISK_GET_PARTITION_INFO,
203 NULL, 0, &piDrive, sizeof(piDrive),
204 &cbRet, NULL);
205
206 if ( !bRet )
207 {
208 show_message ( "IOCTL_DISK_GET_PARTITION_INFO failed, \n"
209 "trying IOCTL_DISK_GET_PARTITION_INFO_EX\n", 0, 0, 0 );
210
211 bRet = DeviceIoControl ( hDevice,
212 IOCTL_DISK_GET_PARTITION_INFO_EX,
213 NULL, 0, &xpiDrive, sizeof(xpiDrive),
214 &cbRet, NULL);
215
216 if (!bRet)
217 die( "Failed to get partition info (both regular and _ex)", -11 );
218
219 memset ( &piDrive, 0, sizeof(piDrive) );
220 piDrive.StartingOffset.QuadPart = xpiDrive.StartingOffset.QuadPart;
221 piDrive.PartitionLength.QuadPart = xpiDrive.PartitionLength.QuadPart;
222 piDrive.HiddenSectors = (DWORD) (xpiDrive.StartingOffset.QuadPart / dgDrive.BytesPerSector);
223
224 bGPTMode = ( xpiDrive.PartitionStyle == PARTITION_STYLE_MBR ) ? 0 : 1;
225 show_message ( "IOCTL_DISK_GET_PARTITION_INFO_EX ok, GPTMode=%d\n", 0, 0, 1, bGPTMode );
226 }
227
228 dp->BytesPerSect = dgDrive.BytesPerSector;
229 dp->TotalSectors = piDrive.PartitionLength.QuadPart / dp->BytesPerSect;
230 dp->SectorsPerTrack = dgDrive.SectorsPerTrack;
231 dp->HiddenSectors = piDrive.HiddenSectors;
232 dp->TracksPerCylinder = dgDrive.TracksPerCylinder;
233
234 return bGPTMode;
235}
236
237void set_part_type(HANDLE hDevice, struct extbpb *dp, int type)
238{
239 BOOL bRet;
240 DWORD cbRet;
241 SET_PARTITION_INFORMATION spiDrive;
242
243 spiDrive.PartitionType = type; // FAT32 LBA.
244 bRet = DeviceIoControl ( hDevice,
245 IOCTL_DISK_SET_PARTITION_INFO,
246 &spiDrive, sizeof(spiDrive),
247 NULL, 0,
248 &cbRet, NULL);
249
250 if ( !bRet )
251 {
252 // This happens because the drive is a Super Floppy
253 // i.e. with no partition table. Disk.sys creates a PARTITION_INFORMATION
254 // record spanning the whole disk and then fails requests to set the
255 // partition info since it's not actually stored on disk.
256 // So only complain if there really is a partition table to set
257 if ( dp->HiddenSectors )
258 die( "Failed to set parition info", -6 );
259 }
260}
261
262void begin_format (HANDLE hDevice)
263{
264 BOOL bRet;
265 DWORD cbRet;
266
267 bRet = DeviceIoControl( hDevice, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &cbRet, NULL );
268
269 if ( !bRet )
270 die( "Failed to dismount device", -7 );
271}
272
273void remount_media (HANDLE hDevice)
274{
275 //BOOL bRet;
276 //DWORD cbRet;
277
278 //bRet = DeviceIoControl( hDevice, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &cbRet, NULL );
279
280 //if ( !bRet )
281 // die( "Failed to dismount device", -7 );
282}
283
284void cleanup ( void )
285{
286 static int num_called = 0;
287
288 num_called++;
289
290 if (num_called > 1)
291 return;
292
293 if (hDev == 0)
294 return;
295
296 remount_media ( hDev );
297 unlock_drive ( hDev );
298 close_drive ( hDev);
299 hDev = 0;
300}
301
302void startlw(HANDLE hDevice)
303{
304 // none
305}
306
307void stoplw(HANDLE hDevice)
308{
309 // none
310}
311
312void close_drive(HANDLE hDevice)
313{
314 CloseHandle( hDevice );
315}
316
317
318int mem_alloc(void **p, ULONG cb)
319{
320 *p = (void *) VirtualAlloc ( NULL, cb, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE );
321 if (*p)
322 return 0;
323
324 return 1;
325}
326
327int mem_alloc2(void **p, ULONG cb)
328{
329 return mem_alloc(p, cb);
330}
331
332void mem_free(void *p, ULONG cb)
333{
334 if (p)
335 VirtualFree(p, cb, 0);
336}
337
338void query_freq(ULONGLONG *freq)
339{
340 LARGE_INTEGER *frequency = (LARGE_INTEGER *)freq;
341 QueryPerformanceFrequency( frequency );
342}
343
344void query_time(ULONGLONG *time)
345{
346 LARGE_INTEGER *t = (LARGE_INTEGER *)time;
347 QueryPerformanceCounter( t );
348}
349
350ULONG query_vol_label(char *path, char *pszVolLabel, int cbVolLabel)
351{
352 /* file system information buffer */
353 ULONG volSerNum;
354 ULONG maxFileNameLen;
355 ULONG fsFlags;
356 char fsName[8];
357 BOOL rc;
358
359 memset(fsName, 0, sizeof(fsName));
360
361 // Query the filesystem info,
362 // including the current volume label
363 rc = GetVolumeInformation(path, pszVolLabel, cbVolLabel,
364 &volSerNum, &maxFileNameLen,
365 &fsFlags, fsName, sizeof(fsName));
366
367 if ( ! rc )
368 return GetLastError();
369
370 return 0;
371}
372
373void set_vol_label (char *path, char *vol)
374{
375 SetVolumeLabel(path, vol);
376}
377
378void set_datetime(DIRENTRY *pDir)
379{
380 SYSTEMTIME datetime;
381
382 GetSystemTime(&datetime);
383
384 pDir->wLastWriteDate.year = datetime.wYear - 1980;
385 pDir->wLastWriteDate.month = datetime.wMonth;
386 pDir->wLastWriteDate.day = datetime.wDay;
387 pDir->wLastWriteTime.hours = datetime.wHour;
388 pDir->wLastWriteTime.minutes = datetime.wMinute;
389 pDir->wLastWriteTime.twosecs = datetime.wSecond / 2;
390
391 pDir->wCreateDate = pDir->wLastWriteDate;
392 pDir->wCreateTime = pDir->wLastWriteTime;
393 pDir->wAccessDate = pDir->wLastWriteDate;
394}
395
396
397char *get_error(USHORT rc)
398{
399 char *msgBuf = NULL;
400 static char szBuf[256];
401 size_t size;
402
403 //No error message has been recorded
404 if(rc == 0)
405 return "";
406
407 size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
408 NULL, rc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msgBuf, 0, NULL);
409
410 CharToOem(msgBuf, szBuf);
411
412 //Free the buffer.
413 LocalFree(msgBuf);
414
415 return szBuf;
416}
417
418
419void query_current_disk(char *pszDrive)
420{
421 TCHAR pBuf[MAX_PATH];
422
423 GetCurrentDirectory(sizeof(pBuf), pBuf);
424
425 pszDrive[0] = pBuf[0];
426 pszDrive[1] = ':';
427 pszDrive[2] = '\0';
428}
429
430
431#ifdef __UNICODE__
432BOOL IsDBCSLead( UCHAR uch )
433{
434 return IsDBCSLeadByte(uch);
435}
436
437
438/* Unicode to OEM */
439VOID Translate2OS2(PUSHORT pusUni, PSZ pszName, USHORT usLen)
440{
441 int cbSize;
442
443 if (! pusUni || !usLen)
444 {
445 *pszName = '\0';
446 return;
447 }
448
449 cbSize = WideCharToMultiByte(CP_OEMCP, 0, pusUni, usLen, pszName, 2 * usLen, NULL, NULL);
450
451 if (! cbSize)
452 {
453 *pszName = '\0';
454 return;
455 }
456}
457
458
459/* OEM to Unicode */
460USHORT Translate2Win(PSZ pszName, PUSHORT pusUni, USHORT usLen)
461{
462 int cbSize;
463
464 if (! pszName || !usLen)
465 {
466 *pusUni = '\0';
467 return 0;
468 }
469
470 cbSize = MultiByteToWideChar(CP_OEMCP, 0, (char *)pszName, usLen, pusUni, usLen);
471
472 if (! cbSize)
473 {
474 *pusUni = '\0';
475 return 0;
476 }
477
478 return cbSize;
479}
480#endif
481
482
483BOOL OutputToFile(HANDLE hFile)
484{
485 DWORD rc = GetFileType(hFile);
486
487 switch (rc)
488 {
489 case FILE_TYPE_DISK:
490 return TRUE;
491
492 case FILE_TYPE_CHAR:
493 case FILE_TYPE_PIPE:
494 return FALSE;
495/*
496 default:
497 return FALSE;
498*/
499 }
500
501 return FALSE;
502}
503
504
505size_t strnlen(const char * str, size_t n)
506{
507 const char *start = str;
508
509 while (*str && n-- > 0)
510 str++;
511
512 return str - start;
513}
514
515
516#define ERROR_MR_MSG_TOO_LONG 316
517#define ERROR_MR_INV_IVCOUNT 320
518#define ERROR_MR_UN_PERFORM 321
519
520
521ULONG DosInsertMessage(char **pTable, ULONG cTable,
522 char *pszMsg, ULONG cbMsg, char *pBuf,
523 ULONG cbBuf, ULONG *pcbMsg)
524{
525 int i;
526
527 // Check arguments
528 if (!pszMsg) return ERROR_INVALID_PARAMETER; // Nothing to proceed
529 if (!pBuf) return ERROR_INVALID_PARAMETER; // No target buffer
530 if ((cTable) && (!pTable)) return ERROR_INVALID_PARAMETER; // No inserting strings array
531 if (cbMsg > cbBuf) return ERROR_MR_MSG_TOO_LONG; // Target buffer too small
532
533 if (!cTable)
534 {
535 // If nothing to insert then just copy message to buffer
536 strncpy(pBuf, pszMsg, cbMsg);
537 *pcbMsg = strlen(pszMsg);
538 return NO_ERROR;
539 } else {
540 // Produce output string
541 PCHAR src;
542 PCHAR dst;
543 int srclen;
544 int dstlen;
545 int len, rest, maxlen = 0;
546 int ivcount = 0;
547 int i;
548
549 src = (char *)pszMsg;
550 dst = pBuf;
551 srclen = cbMsg;
552 maxlen = srclen;
553 dstlen = 0;
554
555 // add params lenths (without zeroes)
556 for (i = 0; i < cTable; i++)
557 maxlen += strnlen(pTable[i], cbBuf) - 1;
558
559 for (;;)
560 {
561 if (*src == '%')
562 {
563 src++;
564 srclen--;
565
566 ivcount++;
567
568 switch (*src)
569 {
570 case '0': // %0
571 srclen--;
572 src++;
573 break;
574 case '1': // %1
575 case '2': // %2
576 case '3': // %3
577 case '4': // %4
578 case '5': // %5
579 case '6': // %6
580 case '7': // %7
581 case '8': // %8
582 case '9': // %9
583 len = strnlen(pTable[*src - '1'], cbBuf);
584 strncpy(dst, pTable[*src - '1'], len);
585 src++;
586 dst += len;
587 dstlen += len;
588 break;
589 default: // Can't perfom action?
590 if (srclen <= 0)
591 break;
592
593 ivcount--;
594
595 *dst++ = '%';
596 dstlen++;
597
598 *dst++ = *src++;
599 srclen--;
600 dstlen++;
601 }
602 }
603 else
604 {
605 *dst++ = *src++;
606 srclen--;
607 dstlen++;
608 }
609
610 if (ivcount > 9)
611 return ERROR_MR_INV_IVCOUNT;
612
613 if (srclen <= 0)
614 break;
615
616 // if no bytes remaining for terminating zero, return an error
617 if (dstlen > maxlen)
618 {
619 *pcbMsg = cbBuf;
620 *dst++ = '\0';
621 dstlen++;
622 return ERROR_MR_MSG_TOO_LONG;
623 }
624 }
625
626 *dst++ = '\0';
627 dstlen++;
628 *pcbMsg = dstlen;
629
630 return NO_ERROR;
631 }
632}
633
634
635INT cdecl iShowMsg2 ( PSZ pszMsg, USHORT usNumFields, va_list va )
636{
637static BYTE szErrNo[12] = "";
638static BYTE szOut[MAX_MESSAGE];
639static BYTE rgNum[9][50];
640ULONG ulReplySize;
641ULONG rc;
642PSZ rgPSZ[9];
643USHORT usIndex;
644PSZ pszMess;
645char *p;
646int i;
647
648 pszMess = pszMsg;
649
650 memset(szOut, 0, sizeof(szOut));
651 memset(rgPSZ, 0, sizeof(rgPSZ));
652 memset(rgNum, 0, sizeof(rgNum));
653 for (usIndex = 0; usIndex < usNumFields; usIndex++)
654 {
655 USHORT usType = va_arg(va, USHORT);
656 if (usType == TYPE_PERC)
657 {
658 sprintf(rgNum[usIndex], "%3u", va_arg(va, USHORT));
659 rgPSZ[usIndex] = rgNum[usIndex];
660 }
661 else if (usType == TYPE_LONG || usType == TYPE_LONG2)
662 {
663 if (!usIndex && usType == TYPE_LONG)
664 sprintf(rgNum[usIndex], "%12lu", va_arg(va, ULONG));
665 else
666 sprintf(rgNum[usIndex], "%lu", va_arg(va, ULONG));
667 rgPSZ[usIndex] = rgNum[usIndex];
668 }
669 else if (usType == TYPE_DOUBLE || usType == TYPE_DOUBLE2)
670 {
671 PSZ p;
672 if (!usIndex && usType == TYPE_DOUBLE)
673 sprintf(rgNum[usIndex], "%12.0lf", va_arg(va, double));
674 else
675 sprintf(rgNum[usIndex], "%lf", va_arg(va, double));
676 p = strchr(rgNum[usIndex], '.');
677 if (p)
678 *p = 0;
679 rgPSZ[usIndex] = rgNum[usIndex];
680 }
681 else if (usType == TYPE_STRING)
682 {
683 rgPSZ[usIndex] = va_arg(va, PSZ);
684 }
685 }
686
687 rc = DosInsertMessage(rgPSZ,
688 usNumFields,
689 pszMess,
690 strlen(pszMess),
691 szOut + strlen(szOut),
692 sizeof(szOut) - strlen(szOut),
693 &ulReplySize);
694 printf("%s", szOut);
695
696 return ulReplySize;
697}
698
699
700int show_message (char *pszMsg, unsigned short usLogMsg, unsigned short usMsg, unsigned short usNumFields, ...)
701{
702 va_list va, va2;
703 UCHAR szBuf[1024];
704 int i, len = 0;
705 char *dummy;
706
707 va_start(va, usNumFields);
708 va_copy(va2, va);
709
710 if (pszMsg)
711 {
712 if (usMsg)
713 {
714 // output message which is not in oso001.msg
715 len = iShowMsg2 ( pszMsg, usNumFields, va );
716 }
717 else
718 {
719 vsprintf( szBuf, pszMsg, va );
720 printf("%s", szBuf);
721 len = strlen(szBuf);
722 }
723 }
724
725 // output message to CHKDSK log
726 if (usLogMsg)
727 {
728 PSZ pszString = NULL;
729 ULONG ulParmNo = usNumFields;
730
731 if (pszMsg && strstr(pszMsg, "%1"))
732 {
733 ULONG arg = va_arg(va2, ULONG);
734 if (usMsg && arg == TYPE_STRING)
735 pszString = va_arg(va2, PSZ);
736 }
737 else if (pszMsg && strstr(pszMsg, "%s"))
738 pszString = (PSZ)va_arg(va2, PSZ);
739
740 if (pszString)
741 ulParmNo--;
742
743 LogOutMessagePrintf(usLogMsg, pszString, ulParmNo, va2);
744 }
745
746 va_end(va2);
747 va_end(va);
748
749 // output additional message for /P switch specified
750 if (usMsg && msg)
751 {
752 va_start(va, usNumFields);
753 printf("\nMSG_%u", usMsg);
754
755 for (i = 0; i < usNumFields; i++)
756 {
757 USHORT usType = va_arg(va, USHORT);
758 if (usType == TYPE_PERC)
759 {
760 USHORT arg = va_arg(va, USHORT);
761 printf(",%u", arg);
762 }
763 else if (usType == TYPE_LONG || usType == TYPE_LONG2)
764 {
765 ULONG arg = va_arg(va, ULONG);
766 printf(",%lu", arg);
767 }
768 else if (usType == TYPE_DOUBLE || usType == TYPE_DOUBLE2)
769 {
770 double arg = va_arg(va, double);
771 printf(",%.0lf", arg);
772 }
773 else if (usType == TYPE_STRING)
774 {
775 PSZ arg = va_arg(va, PSZ);
776 printf(",%s", arg);
777 }
778 }
779
780 printf("\n");
781 va_end( va );
782 }
783
784 return len;
785}
Note: See TracBrowser for help on using the repository browser.