예제 #1
0
        static void MountVolumeSpecialAndUpload(string volumeName, string guidPath, ProgramConfig config)
        {
            if (Directory.CreateDirectory($".\\{volumeName}") != null)
            {
                Native.SetVolumeMountPoint($".\\{volumeName}\\", guidPath);

                if (IsVolumeMountPointForUploadValid($".\\{volumeName}\\"))
                {
                    try
                    {
                        HandleVolumeMountForUpload($".\\{volumeName}\\", config);
                    } catch (Exception ex)
                    {
                        // Get out and turn it off so we do not overheat the device
                        // from continual processing through an infinite cycle of reading
                        // and erroring.
                        Console.WriteLine("HandleVolumeMountForUpload Exception:");
                        Console.WriteLine(ex.ToString());
                        Console.WriteLine(ex.StackTrace);
                        Console.WriteLine("Ejecting the device.");
                    }

                    // https://msdn.microsoft.com/en-us/library/aa363216(VS.85).aspx
                    const uint GENERIC_READ                = 0x80000000;
                    const uint GENERIC_WRITE               = 0x40000000;
                    const int  FILE_SHARE_READ             = 0x1;
                    const int  FILE_SHARE_WRITE            = 0x2;
                    const int  FSCTL_LOCK_VOLUME           = 0x00090018;
                    const int  FSCTL_DISMOUNT_VOLUME       = 0x00090020;
                    const int  IOCTL_STORAGE_EJECT_MEDIA   = 0x2D4808;
                    const int  IOCTL_STORAGE_MEDIA_REMOVAL = 0x002D4804;

https:              //msdn.microsoft.com/en-us/library/windows/desktop/aa365461(v=vs.85).aspx
                    var devicePath = new StringBuilder(256);

                    var guidOnly = guidPath.Substring(4);

                    guidOnly = guidOnly.Substring(0, guidOnly.Length - 1);

                    // Note: Microsoft's historic naming reasons lead to decreased ability to recognize the needed API functions
                    //       unless I have been doing WIN32 development for the past 40 years.
                    Native.QueryDosDevice(guidOnly, devicePath, 256);

                    Native.DeleteVolumeMountPoint($".\\{volumeName}\\");

                    var neededDeviceString = devicePath.ToString();

                    neededDeviceString = neededDeviceString.Substring(neededDeviceString.LastIndexOf('\\') + 1);

                    var f = Native.CreateFile(
                        $"\\\\.\\{neededDeviceString}",
                        GENERIC_READ | GENERIC_WRITE,
                        FILE_SHARE_READ | FILE_SHARE_WRITE,
                        IntPtr.Zero, 0x3, 0x40000000, IntPtr.Zero
                        );

                    uint bytesReturned;

                    int tryCount = 0;

                    while (!Native.DeviceIoControl(f, FSCTL_LOCK_VOLUME, IntPtr.Zero, 0, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero))
                    {
                        Console.WriteLine("Trying to lock the volume.");
                        Thread.Sleep(1000);
                        tryCount++;

                        if (tryCount > 30)
                        {
                            break;
                        }
                    }

                    Native.DeviceIoControl(f, FSCTL_DISMOUNT_VOLUME, IntPtr.Zero, 0, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero);

                    byte[] buf = new byte[1];
                    uint   retVal;

                    buf[0] = 1;

                    Native.DeviceIoControl(f, IOCTL_STORAGE_MEDIA_REMOVAL, buf, 1, IntPtr.Zero, 0, out retVal, IntPtr.Zero);
                    Native.DeviceIoControl(f, IOCTL_STORAGE_EJECT_MEDIA, IntPtr.Zero, 0, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero);
                }
                else
                {
                    Native.DeleteVolumeMountPoint($".\\{volumeName}\\");
                }
            }
        }
예제 #2
0
        static bool HandleVolumeMountForUpload(string path, ProgramConfig config)
        {
            Console.WriteLine($"HandleVolumeMountForUpload: handling volume at path {path} for upload");

            if (!IsVolumeMountPointForUploadValid(path))
            {
                Console.WriteLine($"HandleVolumeMountForUpload: mount point for volume failed inner validity check");
                return(false);
            }

            var configText   = File.ReadAllText($"{path}MISC\\settings.json");
            var configParsed = JsonConvert.DeserializeObject <JObject>(configText);
            var serialNumber = configParsed["info"]["serial-number"].ToObject <string>();

            var creds = new ServerCredentials()
            {
                serverUrl = config.dbUrl,
            };

            var serverConfig = ServerUtility.GetConfiguration(creds, serialNumber, configText);

            if (IsBC300ConfigTheSame(configText, serverConfig.deviceConfig))
            {
                File.WriteAllText($"{path}MISC\\settings.json", serverConfig.deviceConfig);
            }

            var serverReportedUserId = serverConfig.userId;

            // Scan for data files.
            foreach (var sdir in Directory.EnumerateDirectories($"{path}DCIM\\"))
            {
                foreach (var sfile in Directory.EnumerateFiles(sdir))
                {
                    var baseName  = Path.GetFileNameWithoutExtension(sfile);
                    var baseParts = baseName.Split('_');

                    if (baseParts.Length < 3)
                    {
                        continue;
                    }

                    var fullPath   = sfile;
                    var dataSize   = new FileInfo(fullPath).Length;
                    var dataType   = Path.GetExtension(sfile).Substring(1).ToLower();
                    var dateString = baseParts[2].Substring(0, 8);
                    var dateDay    = dateString.Substring(2, 2);
                    var dateMonth  = dateString.Substring(0, 2);
                    var dateYear   = dateString.Substring(4, 4);

                    dateString = $"{dateYear}-{dateMonth}-{dateDay}";

                    var timeString = baseParts[2].Substring(8, 6);

                    var dataStream = File.OpenRead(fullPath);

                    Console.WriteLine($"Uploading {fullPath}");

                    var uploadTask = MDACS.API.Database.UploadAsync(
                        config.authUrl, config.dbUrl,
                        config.username, config.password,
                        dataSize, dataType,
                        dateString, serialNumber, timeString,
                        serverReportedUserId,
                        dataStream
                        );

                    Console.WriteLine("Waiting...");

                    uploadTask.Wait();

                    Console.WriteLine("Done upload..");

                    var uploadResult = uploadTask.Result;

                    dataStream.Close();

                    if (uploadResult.success && uploadResult.security_id.Length != 0)
                    {
                        Console.WriteLine("Upload success");
                        File.Delete(fullPath);
                    }
                    else
                    {
                        Console.WriteLine("Upload failure");
                    }
                }
            }

            // Would be nice to be able to run a chkdsk /F command on the volume just to help over time correct some issues.

            /*var processInfo = new ProcessStartInfo()
             * {
             *  FileName = "chkdsk.exe",
             *  Arguments = $"{path} /f /r /x",
             * };
             *
             * var chkdskProcess = Process.Start(processInfo);
             * chkdskProcess.StandardInput.WriteLine("Y");
             * chkdskProcess.StandardInput.WriteLine("Y");
             * chkdskProcess.StandardInput.WriteLine("Y");
             * chkdskProcess.WaitForExit(1000 * 60 * 5);
             */

            return(true);
        }