![]() |
ZenWINX Architecture - Reference Manual - Guides |
|
00001 /* 00002 * ZenWINX - WIndows Native eXtended library. 00003 * Copyright (c) 2007-2010 by Dmitri Arkhangelski (dmitriar@gmail.com). 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00018 */ 00019 00027 #include "ntndk.h" 00028 #include "zenwinx.h" 00029 00030 BOOLEAN internal_open_rootdir(unsigned char letter,HANDLE *phFile); 00031 00049 int __stdcall winx_fbsize(ULONGLONG number, int digits, char *buffer, int length) 00050 { 00051 char symbols[] = {'K','M','G','T','P','E'}; 00052 char spec[] = "%u.%00u %cb"; 00053 double fn,n; 00054 unsigned int i,j,k; 00055 int result; 00056 00057 if(!buffer || !length) return (-1); 00058 if(number < 1024){ 00059 result = _snprintf(buffer,length - 1,"%u",(int)number); 00060 buffer[length - 1] = 0; 00061 return result; 00062 } 00063 /* 00064 * Because win ddk compiler doesn't have ULONGLONG -> double converter, 00065 * we need first divide an integer number and then convert in to double. 00066 */ 00067 if(number < 1024 * 1024){ 00068 if(digits){ 00069 /* we can convert a number to int here */ 00070 fn = (double)(int)number; 00071 fn /= 1024.0; 00072 k = 0; 00073 L0: 00074 /* example: fn = 128.45638, digits = 4 */ 00075 /* %.2f doesn't work in native mode */ 00076 n = 1.0; 00077 for(i = digits; i > 0; i--) 00078 n *= 10.0; 00079 fn *= n; 00080 /* example: n = 10000.0, fn = 1284563.8 */ 00081 i = (int)fn; 00082 j = (int)n; 00083 /* example: i = 1284563, j = 10000 */ 00084 spec[4] = '0' + digits / 10; 00085 spec[5] = '0' + digits % 10; 00086 result = _snprintf(buffer,length - 1,spec,i/j,i%j,symbols[k]); 00087 buffer[length - 1] = 0; 00088 return result; 00089 } else { 00090 result = _snprintf(buffer,length - 1,"%u Kb",(int)number / 1024); 00091 buffer[length - 1] = 0; 00092 return result; 00093 } 00094 return (-1); /* this point will never be reached */ 00095 } 00096 /* convert integer number to kilobytes */ 00097 number /= 1024; 00098 fn = (double)(signed __int64)number / 1024.00; 00099 for(k = 1; fn >= 1024.00; k++) fn /= 1024.00; 00100 if(k > sizeof(symbols) - 1) k = sizeof(symbols) - 1; 00101 goto L0; 00102 return (-1); /* this point will never be reached */ 00103 } 00104 00112 int __stdcall winx_dfbsize(char *string,ULONGLONG *pnumber) 00113 { 00114 char symbols[] = {'K','M','G','T','P','E'}; 00115 char t[64]; 00116 signed int i; 00117 ULONGLONG m = 1; 00118 00119 if(strlen(string) > 63) return (-1); 00120 (void)strcpy(t,string); 00121 (void)_strupr(t); 00122 for(i = 0; i < sizeof(symbols); i++) 00123 if(strchr(t,symbols[i])) break; 00124 if(i < sizeof(symbols)) /* suffix found */ 00125 for(; i >= 0; i--) m *= 1024; 00126 *pnumber = m * _atoi64(string); 00127 /* TODO: decode digits after a dot */ 00128 return 0; 00129 } 00130 00136 int __stdcall winx_get_drive_type(char letter) 00137 { 00138 short link_name[] = L"\\??\\A:"; 00139 #define MAX_TARGET_LENGTH 256 00140 short link_target[MAX_TARGET_LENGTH]; 00141 PROCESS_DEVICEMAP_INFORMATION *ppdi; 00142 FILE_FS_DEVICE_INFORMATION *pffdi; 00143 IO_STATUS_BLOCK iosb; 00144 NTSTATUS Status; 00145 int drive_type; 00146 HANDLE hFile; 00147 00148 /* An additional checks for DFS were suggested by Stefan Pendl (pendl2megabit@yahoo.de). */ 00149 /* DFS shares have DRIVE_NO_ROOT_DIR type though they are actually remote. */ 00150 00151 letter = (unsigned char)toupper((int)letter); 00152 if(letter < 'A' || letter > 'Z'){ 00153 DebugPrint("winx_get_drive_type() invalid letter %c!",letter); 00154 return (-1); 00155 } 00156 00157 /* check for the drive existence */ 00158 link_name[4] = (short)letter; 00159 if(winx_query_symbolic_link(link_name,link_target,MAX_TARGET_LENGTH) < 0) 00160 return (-1); 00161 00162 /* check for an assignment made by subst command */ 00163 if(wcsstr(link_target,L"\\??\\") == (wchar_t *)link_target) 00164 return DRIVE_ASSIGNED_BY_SUBST_COMMAND; 00165 00166 /* check for classical floppies */ 00167 if(wcsstr(link_target,L"Floppy")) 00168 return DRIVE_REMOVABLE; 00169 00170 /* allocate memory */ 00171 ppdi = winx_heap_alloc(sizeof(PROCESS_DEVICEMAP_INFORMATION)); 00172 if(!ppdi){ 00173 DebugPrint("Cannot allocate memory for winx_get_drive_type()!\n"); 00174 return (-1); 00175 } 00176 pffdi = winx_heap_alloc(sizeof(FILE_FS_DEVICE_INFORMATION)); 00177 if(!pffdi){ 00178 winx_heap_free(ppdi); 00179 DebugPrint("Cannot allocate memory for winx_get_drive_type()!\n"); 00180 return (-1); 00181 } 00182 00183 /* try to define exactly which type has a specified drive (w2k+) */ 00184 RtlZeroMemory(ppdi,sizeof(PROCESS_DEVICEMAP_INFORMATION)); 00185 Status = NtQueryInformationProcess(NtCurrentProcess(), 00186 ProcessDeviceMap,ppdi, 00187 sizeof(PROCESS_DEVICEMAP_INFORMATION), 00188 NULL); 00189 if(NT_SUCCESS(Status)){ 00190 drive_type = (int)ppdi->Query.DriveType[letter - 'A']; 00191 /* 00192 * Type DRIVE_NO_ROOT_DIR have the following drives: 00193 * 1. assigned by subst command 00194 * 2. SCSI external drives 00195 * 3. RAID volumes 00196 * 4. DFS shares 00197 * We need additional checks to know exactly. 00198 */ 00199 if(drive_type != DRIVE_NO_ROOT_DIR){ 00200 winx_heap_free(ppdi); 00201 winx_heap_free(pffdi); 00202 return drive_type; 00203 } 00204 } else { 00205 if(Status != STATUS_INVALID_INFO_CLASS){ /* on NT4 this is always false */ 00206 DebugPrintEx(Status,"winx_get_drive_type(): cannot get device map"); 00207 winx_heap_free(ppdi); 00208 winx_heap_free(pffdi); 00209 return (-1); 00210 } 00211 } 00212 00213 /* try to define exactly again which type has a specified drive (nt4+) */ 00214 /* note that the drive motor can be powered on during this check */ 00215 if(!internal_open_rootdir(letter,&hFile)){ 00216 winx_heap_free(ppdi); 00217 winx_heap_free(pffdi); 00218 return (-1); 00219 } 00220 RtlZeroMemory(pffdi,sizeof(FILE_FS_DEVICE_INFORMATION)); 00221 Status = NtQueryVolumeInformationFile(hFile,&iosb, 00222 pffdi,sizeof(FILE_FS_DEVICE_INFORMATION), 00223 FileFsDeviceInformation); 00224 NtClose(hFile); 00225 if(!NT_SUCCESS(Status)){ 00226 DebugPrintEx(Status,"winx_get_drive_type(): cannot get volume type for \'%c\'",letter); 00227 winx_heap_free(ppdi); 00228 winx_heap_free(pffdi); 00229 return (-1); 00230 } 00231 00232 /* separate remote and removable drives */ 00233 if(pffdi->Characteristics & FILE_REMOTE_DEVICE){ 00234 winx_heap_free(ppdi); 00235 winx_heap_free(pffdi); 00236 return DRIVE_REMOTE; 00237 } 00238 if(pffdi->Characteristics & FILE_REMOVABLE_MEDIA){ 00239 winx_heap_free(ppdi); 00240 winx_heap_free(pffdi); 00241 return DRIVE_REMOVABLE; 00242 } 00243 00244 /* finally define drive type exactly */ 00245 switch(pffdi->DeviceType){ 00246 case FILE_DEVICE_CD_ROM: 00247 case FILE_DEVICE_CD_ROM_FILE_SYSTEM: 00248 case FILE_DEVICE_DVD: /* ? */ 00249 winx_heap_free(ppdi); 00250 winx_heap_free(pffdi); 00251 return DRIVE_CDROM; 00252 case FILE_DEVICE_NETWORK_FILE_SYSTEM: 00253 case FILE_DEVICE_NETWORK: /* ? */ 00254 case FILE_DEVICE_NETWORK_BROWSER: /* ? */ 00255 case FILE_DEVICE_DFS_FILE_SYSTEM: 00256 case FILE_DEVICE_DFS_VOLUME: 00257 case FILE_DEVICE_DFS: 00258 winx_heap_free(ppdi); 00259 winx_heap_free(pffdi); 00260 return DRIVE_REMOTE; 00261 case FILE_DEVICE_DISK: 00262 case FILE_DEVICE_FILE_SYSTEM: /* ? */ 00263 /*case FILE_DEVICE_VIRTUAL_DISK:*/ 00264 /*case FILE_DEVICE_MASS_STORAGE:*/ 00265 case FILE_DEVICE_DISK_FILE_SYSTEM: 00266 winx_heap_free(ppdi); 00267 winx_heap_free(pffdi); 00268 return DRIVE_FIXED; 00269 case FILE_DEVICE_UNKNOWN: 00270 winx_heap_free(ppdi); 00271 winx_heap_free(pffdi); 00272 return DRIVE_UNKNOWN; 00273 } 00274 winx_heap_free(ppdi); 00275 winx_heap_free(pffdi); 00276 return DRIVE_UNKNOWN; 00277 } 00278 00288 int __stdcall winx_get_volume_size(char letter, LARGE_INTEGER *ptotal, LARGE_INTEGER *pfree) 00289 { 00290 HANDLE hRoot; 00291 NTSTATUS Status; 00292 IO_STATUS_BLOCK IoStatusBlock; 00293 FILE_FS_SIZE_INFORMATION *pffs; 00294 00295 letter = (char)toupper((int)letter); 00296 if(letter < 'A' || letter > 'Z'){ 00297 DebugPrint("winx_get_volume_size() invalid letter %c!",letter); 00298 return (-1); 00299 } 00300 if(!ptotal){ 00301 DebugPrint("winx_get_volume_size() invalid ptotal (NULL)!"); 00302 return (-1); 00303 } 00304 if(!pfree){ 00305 DebugPrint("winx_get_volume_size() invalid pfree (NULL)!"); 00306 return (-1); 00307 } 00308 00309 /* allocate memory */ 00310 pffs = winx_heap_alloc(sizeof(FILE_FS_SIZE_INFORMATION)); 00311 if(!pffs){ 00312 DebugPrint("Cannot allocate memory for winx_get_volume_size()!\n"); 00313 return (-1); 00314 } 00315 00316 if(!internal_open_rootdir(letter,&hRoot)){ 00317 winx_heap_free(pffs); 00318 return (-1); 00319 } 00320 RtlZeroMemory(pffs,sizeof(FILE_FS_SIZE_INFORMATION)); 00321 Status = NtQueryVolumeInformationFile(hRoot,&IoStatusBlock,pffs, 00322 sizeof(FILE_FS_SIZE_INFORMATION),FileFsSizeInformation); 00323 NtClose(hRoot); 00324 if(!NT_SUCCESS(Status)){ 00325 winx_heap_free(pffs); 00326 DebugPrintEx(Status,"winx_get_volume_size(): cannot get size of volume \'%c\'",letter); 00327 return (-1); 00328 } 00329 00330 ptotal->QuadPart = pffs->TotalAllocationUnits.QuadPart * \ 00331 pffs->SectorsPerAllocationUnit * pffs->BytesPerSector; 00332 pfree->QuadPart = pffs->AvailableAllocationUnits.QuadPart * \ 00333 pffs->SectorsPerAllocationUnit * pffs->BytesPerSector; 00334 winx_heap_free(pffs); 00335 return 0; 00336 } 00337 00345 int __stdcall winx_get_filesystem_name(char letter, char *buffer, int length) 00346 { 00347 #define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_ATTRIBUTE_INFORMATION)) 00348 UCHAR *buf; 00349 PFILE_FS_ATTRIBUTE_INFORMATION pFileFsAttribute; 00350 IO_STATUS_BLOCK IoStatusBlock; 00351 NTSTATUS Status; 00352 HANDLE hRoot; 00353 UNICODE_STRING us; 00354 ANSI_STRING as; 00355 ULONG len; 00356 00357 letter = (char)toupper((int)letter); 00358 if(letter < 'A' || letter > 'Z'){ 00359 DebugPrint("winx_get_filesystem_name() invalid letter %c!",letter); 00360 return (-1); 00361 } 00362 if(!buffer){ 00363 DebugPrint("winx_get_filesystem_name() invalid buffer!"); 00364 return (-1); 00365 } 00366 if(length <= 0){ 00367 DebugPrint("winx_get_filesystem_name() invalid length == %i!",length); 00368 return (-1); 00369 } 00370 00371 buffer[0] = 0; 00372 00373 /* allocate memory */ 00374 buf = winx_heap_alloc(FS_ATTRIBUTE_BUFFER_SIZE); 00375 if(!buf){ 00376 DebugPrint("Cannot allocate memory for winx_get_filesystem_name()!\n"); 00377 return(-1); 00378 } 00379 00380 if(!internal_open_rootdir(letter,&hRoot)){ 00381 winx_heap_free(buf); 00382 return (-1); 00383 } 00384 pFileFsAttribute = (PFILE_FS_ATTRIBUTE_INFORMATION)buf; 00385 RtlZeroMemory(pFileFsAttribute,FS_ATTRIBUTE_BUFFER_SIZE); 00386 Status = NtQueryVolumeInformationFile(hRoot,&IoStatusBlock,pFileFsAttribute, 00387 FS_ATTRIBUTE_BUFFER_SIZE,FileFsAttributeInformation); 00388 NtClose(hRoot); 00389 if(!NT_SUCCESS(Status)){ 00390 DebugPrintEx(Status,"Cannot get file system name for \'%c\'",letter); 00391 winx_heap_free(buf); 00392 return (-1); 00393 } 00394 00395 us.Buffer = pFileFsAttribute->FileSystemName; 00396 len = pFileFsAttribute->FileSystemNameLength; 00397 us.Length = us.MaximumLength = (USHORT)len; 00398 00399 as.Buffer = buffer; 00400 as.Length = 0; 00401 as.MaximumLength = (USHORT)length; 00402 if(RtlUnicodeStringToAnsiString(&as,&us,FALSE) != STATUS_SUCCESS){ 00403 if(length >= 2) 00404 strcpy(buffer,"?"); 00405 else 00406 buffer[0] = 0; 00407 } 00408 winx_heap_free(buf); 00409 return 0; 00410 } 00411 00419 BOOLEAN internal_open_rootdir(unsigned char letter,HANDLE *phFile) 00420 { 00421 NTSTATUS Status; 00422 unsigned short rootpath[] = L"\\??\\A:\\"; 00423 UNICODE_STRING uStr; 00424 OBJECT_ATTRIBUTES ObjectAttributes; 00425 IO_STATUS_BLOCK IoStatusBlock; 00426 00427 rootpath[4] = (short)letter; 00428 RtlInitUnicodeString(&uStr,rootpath); 00429 InitializeObjectAttributes(&ObjectAttributes,&uStr, 00430 FILE_READ_ATTRIBUTES,NULL,NULL); /* ?? */ 00431 Status = NtCreateFile(phFile,FILE_GENERIC_READ, 00432 &ObjectAttributes,&IoStatusBlock,NULL,0, 00433 FILE_SHARE_READ|FILE_SHARE_WRITE,FILE_OPEN,0, 00434 NULL,0); 00435 if(!NT_SUCCESS(Status)){ 00436 DebugPrintEx(Status,"Cannot open %ls",rootpath); 00437 return FALSE; 00438 } 00439 return TRUE; 00440 } 00441