main.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <assert.h>
  4. #include <string.h>
  5. #include <windows.h>
  6. #include "partitions.h"
  7. #include "general.h"
  8. #include "debug.h"
  9. #include "dokan.h"
  10. #include "stubs.h"
  11. #include "file.h"
  12. #include "file_info.h"
  13. #include "dir.h"
  14. #include "read_write.h"
  15. #include "inode.h"
  16. #include "volume_info.h"
  17. #include "disk_image.h"
  18. #define VERSION "0.4"
  19. typedef struct
  20. {
  21. unsigned Part;
  22. unsigned Subpart;
  23. const char *Path;
  24. SUBPARTITION *pSubpart;
  25. DISK_IMG *pImg;
  26. HANDLE hEvent;
  27. volatile BOOL bMounted;
  28. } MOUNT_REQ;
  29. static DOKAN_OPERATIONS DokanCallbacks = {
  30. MxfsCreateFile, // CreateFile
  31. MxfsOpenDirectory, // OpenDirectory
  32. MxfsCreateDirectory, // CreateDirectory
  33. MxfsCleanup, // Cleanup
  34. MxfsCloseFile, // CloseFile
  35. MxfsReadFile, // ReadFile
  36. MxfsWriteFile, // WriteFile
  37. MxfsFlushFileBuffers, // FlushFileBuffers
  38. MxfsGetFileInformation, // GetFileInformation,
  39. MxfsFindFiles, // FindFiles
  40. NULL, // FindFilesWithPattern
  41. MxfsSetFileAttributes, // SetFileAttributes
  42. MxfsSetFileTime, // SetFileTime
  43. MxfsDeleteFile, // DeleteFile
  44. MxfsDeleteDirectory, // DeleteDirectory
  45. MxfsMoveFile, // MoveFile
  46. MxfsSetEndOfFile, // SetEndOfFile
  47. MxfsSetAllocationSize, // SetAllocationSize
  48. MxfsLockFile, // LockFile
  49. MxfsUnlockFile, // UnlockFile
  50. MxfsGetDiskFreeSpace, // GetDiskFreeSpace
  51. MxfsGetVolumeInformation, // GetVolumeInformation
  52. MxfsUnmount, // Unmount
  53. MxfsGetFileSecurity, // GetFileSecurity
  54. MxfsSetFileSecurity, // SetFileSecurity
  55. };
  56. static HANDLE g_Threads[16];
  57. static unsigned g_cThreads = 0;
  58. static MOUNT_REQ g_MountReq[16];
  59. static unsigned g_cMountReq = 0;
  60. static DWORD WINAPI MxfsThread(LPVOID lpParameter)
  61. {
  62. MOUNT_REQ *pReq = (MOUNT_REQ*)lpParameter;
  63. MINIX_FS *pFileSys;
  64. WCHAR wszMountPath[MAX_PATH];
  65. mbstowcs(wszMountPath, pReq->Path, sizeof(wszMountPath)/sizeof(wszMountPath[0]));
  66. pFileSys = MxfsOpen(pReq->pImg, pReq->pSubpart->Offset, pReq->pSubpart->Size);
  67. if(!pFileSys)
  68. {
  69. ERR("Failed to open Minix filesystem\n");
  70. SetEvent(pReq->hEvent);
  71. return (DWORD)-1;
  72. }
  73. DOKAN_OPTIONS Opts = {
  74. DOKAN_VERSION, // Version
  75. 1, // ThreadCount, TODO: support many threads...
  76. DOKAN_OPTION_DEBUG, // Options
  77. (ULONG64)(LONG_PTR)pFileSys, // GlobalContext
  78. wszMountPath, // MountPoint
  79. };
  80. SetEvent(pReq->hEvent);
  81. pReq->bMounted = TRUE;
  82. int err = DokanMain(&Opts, &DokanCallbacks);
  83. if(err < 0)
  84. ERR("DokanMain failed: %d\n", err);
  85. pReq->bMounted = FALSE;
  86. MxfsClose(pFileSys);
  87. return 0;
  88. }
  89. static int MxfsMount(MOUNT_REQ *pReq)
  90. {
  91. pReq->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  92. HANDLE hThread = CreateThread(NULL, 0, MxfsThread, pReq, 0, NULL);
  93. if(!hThread)
  94. return -1;
  95. WaitForSingleObject(pReq->hEvent, INFINITE);
  96. CloseHandle(pReq->hEvent);
  97. Sleep(10);
  98. g_Threads[g_cThreads++] = hThread;
  99. return 0;
  100. }
  101. static LONG WINAPI ExceptionHandler(struct _EXCEPTION_POINTERS *ExceptionInfo)
  102. {
  103. ERR("Exception!!!\n");
  104. return EXCEPTION_EXECUTE_HANDLER;
  105. }
  106. static BOOL WINAPI CtrlHandler(DWORD dwCtrlType)
  107. {
  108. printf("Console Ctrl Handler: unmounting...\n");
  109. unsigned i;
  110. WCHAR wszMountPath[MAX_PATH];
  111. for(i = 0; i < g_cMountReq; ++i)
  112. {
  113. if(!g_MountReq[i].bMounted)
  114. continue;
  115. mbstowcs(wszMountPath, g_MountReq[i].Path, sizeof(wszMountPath)/sizeof(wszMountPath[0]));
  116. BOOL Result = DokanRemoveMountPoint(wszMountPath);
  117. if(!Result)
  118. ERR("DokanRemoveMountPoint(%ls) failed!\n", wszMountPath);
  119. }
  120. return TRUE;
  121. }
  122. static void DisplayHelp(const char *pProcName)
  123. {
  124. printf("Usage: %s [-l] [-f img_path p0s0=mount_path1 p0s1=mount_path2 ...]\n", pProcName);
  125. printf("-l\t\t\tLists all partitions and subpartitions\n");
  126. printf("-f img_path\t\tSets disk image path\n");
  127. printf("p0s0=mount_path\t\tMounts subpartition 0 on partition 0 in given path\n");
  128. }
  129. static void Test()
  130. {
  131. #ifndef NDEBUG
  132. FILETIME ft;
  133. time_t t = time(NULL);
  134. MxfsFileTimeFromTimeT(&ft, t);
  135. assert(t == MxfsTimeTFromFileTime(&ft));
  136. #endif
  137. }
  138. int main(int argc, char *argv[])
  139. {
  140. const char *pszPath = NULL;
  141. unsigned i;
  142. BOOL bHelp = FALSE, bList = FALSE;
  143. printf("MINIX Filesystem Driver " VERSION " for Windows (c) 2013 Rafal Harabien\n");
  144. Test();
  145. for(i = 1; i < (unsigned)argc; ++i)
  146. {
  147. if(!strcmp(argv[i], "-f") && i + 1 < (unsigned)argc)
  148. pszPath = argv[++i];
  149. else if(!strcmp(argv[i], "-l"))
  150. bList = TRUE;
  151. else if(!strcmp(argv[i], "-h"))
  152. {
  153. bHelp = TRUE;
  154. break;
  155. }
  156. else
  157. {
  158. unsigned uPart, uSubpart;
  159. if(sscanf(argv[i], "p%us%u=", &uPart, &uSubpart) == 2 && g_cMountReq < COUNTOF(g_MountReq))
  160. {
  161. const char *pszMount = strchr(argv[i], '=') + 1;
  162. g_MountReq[g_cMountReq].Part = uPart;
  163. g_MountReq[g_cMountReq].Subpart = uSubpart;
  164. g_MountReq[g_cMountReq].Path = pszMount;
  165. g_MountReq[g_cMountReq].bMounted = FALSE;
  166. ++g_cMountReq;
  167. } else
  168. printf("Invalid argument: %s\n", argv[i]);
  169. }
  170. }
  171. if(!pszPath)
  172. bHelp = TRUE;
  173. if(bHelp)
  174. {
  175. DisplayHelp(argv[0]);
  176. return 0;
  177. }
  178. DISK_IMG *pImg = ImgOpen(pszPath);
  179. if(!pImg)
  180. {
  181. ERR("Failed to open image: %s\n", pszPath);
  182. return -1;
  183. }
  184. SUBPART_VECTOR SubpartVect;
  185. int err = FindSubpartitions(pImg, &SubpartVect);
  186. if(err < 0)
  187. {
  188. ERR("FindSubpartitions failed!\n");
  189. ImgClose(pImg);
  190. return err;
  191. }
  192. if(bList)
  193. {
  194. printf("Subpartitions:\n");
  195. for(i = 0; i < SubpartVect.Count; ++i)
  196. {
  197. SUBPARTITION *pSubpart = &SubpartVect.Entries[i];
  198. printf("p%us%u - offset 0x%x size 0x%x\n", pSubpart->PartIdx, pSubpart->SubpartIdx, pSubpart->Offset, pSubpart->Size);
  199. }
  200. }
  201. SetUnhandledExceptionFilter(ExceptionHandler);
  202. SetConsoleCtrlHandler(CtrlHandler, TRUE);
  203. for(i = 0; i < g_cMountReq; ++i)
  204. {
  205. unsigned j;
  206. for(j = 0; j < SubpartVect.Count; ++j)
  207. {
  208. if(g_MountReq[i].Part == SubpartVect.Entries[j].PartIdx && g_MountReq[i].Subpart == SubpartVect.Entries[j].SubpartIdx)
  209. break;
  210. }
  211. if(j < SubpartVect.Count)
  212. {
  213. printf("Mounting p%us%u in %s...\n", g_MountReq[i].Part, g_MountReq[i].Subpart, g_MountReq[i].Path);
  214. g_MountReq[i].pSubpart = &SubpartVect.Entries[j];
  215. g_MountReq[i].pImg = pImg;
  216. MxfsMount(&g_MountReq[i]);
  217. }
  218. }
  219. WaitForMultipleObjects(g_cThreads, g_Threads, TRUE, INFINITE);
  220. for(i = 0; i < g_cThreads; ++i)
  221. CloseHandle(g_Threads[i]);
  222. MxfsFree(SubpartVect.Entries);
  223. ImgClose(pImg);
  224. printf("Done!\n");
  225. return 0;
  226. }