System.Data.SQLite
Check-in [2e3be13ffa]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Enhance the native library pre-loader platform abstraction subsystem to support querying the machine name.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | netStandard20
Files: files | file ages | folders
SHA1:2e3be13ffaa031ff07f4bba5648f96d141185e32
User & Date: mistachkin 2018-04-25 22:33:03
Context
2018-04-26
01:16
Add preliminary support for .NET Core 2.0 and the .NET Standard 2.0. Pursuant to [5c89cecd1b]. check-in: ec79fb3446 user: mistachkin tags: trunk
2018-04-25
22:33
Enhance the native library pre-loader platform abstraction subsystem to support querying the machine name. Closed-Leaf check-in: 2e3be13ffa user: mistachkin tags: netStandard20
21:20
Merge updates from trunk. check-in: b8d9f46daa user: mistachkin tags: netStandard20
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to System.Data.SQLite/UnsafeNativeMethods.cs.

896
897
898
899
900
901
902











903
904
905
906
907
908
909
...
920
921
922
923
924
925
926







































927
928
929
930
931
932
933
...
938
939
940
941
942
943
944

































945
946
947
948
949
950
951
...
966
967
968
969
970
971
972




















973
974
975
976
977
978
979
...
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
....
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267






1268
1269
1270
1271
1272
1273
1274
1275
....
1298
1299
1300
1301
1302
1303
1304

1305



1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
....
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
....
2857
2858
2859
2860
2861
2862
2863

2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886

2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918

2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
      /// </param>
      /// <returns>
      /// The native module handle upon success -OR- IntPtr.Zero on failure.
      /// </returns>
      private delegate IntPtr LoadLibraryCallback(
          string fileName
      );











      #endregion

      /////////////////////////////////////////////////////////////////////////

      #region Private Methods
      /// <summary>
      /// Attempts to load the specified native library file using the Win32
................................................................................
          )
      {
          return UnsafeNativeMethodsWin32.LoadLibrary(fileName);
      }

      /////////////////////////////////////////////////////////////////////////








































#if !PLATFORM_COMPACTFRAMEWORK
      /// <summary>
      /// Attempts to load the specified native library file using the POSIX
      /// API.
      /// </summary>
      /// <param name="fileName">
      /// The file name of the native library to load.
................................................................................
      private static IntPtr LoadLibraryPosix(
          string fileName
          )
      {
          return UnsafeNativeMethodsPosix.dlopen(
              fileName, UnsafeNativeMethodsPosix.RTLD_DEFAULT);
      }

































#endif
      #endregion

      /////////////////////////////////////////////////////////////////////////

      #region Public Methods
      /// <summary>
................................................................................
#if !PLATFORM_COMPACTFRAMEWORK
          if (!HelperMethods.IsWindows())
              callback = LoadLibraryPosix;
#endif

          return callback(fileName);
      }




















      #endregion
  }
  #endregion

  /////////////////////////////////////////////////////////////////////////////

  #region Unmanaged Interop Methods Static Class (POSIX)
................................................................................
  {
      /// <summary>
      /// This structure is used when running on POSIX operating systems
      /// to store information about the current machine, including the
      /// human readable name of the operating system as well as that of
      /// the underlying hardware.
      /// </summary>
      internal struct utsname
      {
          public string sysname;  /* Name of this implementation of
                                   * the operating system. */
          public string nodename; /* Name of this node within the
                                   * communications network to which
                                   * this node is attached, if any. */
          public string release;  /* Current release level of this
................................................................................
      /// The native module handle upon success -OR- IntPtr.Zero on failure.
      /// </returns>
#if !PLATFORM_COMPACTFRAMEWORK
      [DllImport("kernel32",
#else
      [DllImport("coredll",
#endif
 CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto,
#if !PLATFORM_COMPACTFRAMEWORK
          BestFitMapping = false, ThrowOnUnmappableChar = true,
#endif
          SetLastError = true)]
      internal static extern IntPtr LoadLibrary(string fileName);

      /////////////////////////////////////////////////////////////////////////

#if PLATFORM_COMPACTFRAMEWORK
      /// <summary>
      /// This is the P/Invoke method that wraps the native Win32 GetSystemInfo
      /// function.  See the MSDN documentation for full details on what it
      /// does.
      /// </summary>
      /// <param name="systemInfo">
      /// The system information structure to be filled in by the function.
      /// </param>






      [DllImport("coredll", CallingConvention = CallingConvention.Winapi)]
      internal static extern void GetSystemInfo(out SYSTEM_INFO systemInfo);

      /////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// This enumeration contains the possible values for the processor
      /// architecture field of the system information structure.
      /// </summary>
................................................................................
      internal struct SYSTEM_INFO
      {
          public ProcessorArchitecture wProcessorArchitecture;
          public ushort wReserved; /* NOT USED */
          public uint dwPageSize; /* NOT USED */
          public IntPtr lpMinimumApplicationAddress; /* NOT USED */
          public IntPtr lpMaximumApplicationAddress; /* NOT USED */

          public uint dwActiveProcessorMask; /* NOT USED */



          public uint dwNumberOfProcessors; /* NOT USED */
          public uint dwProcessorType; /* NOT USED */
          public uint dwAllocationGranularity; /* NOT USED */
          public ushort wProcessorLevel; /* NOT USED */
          public ushort wProcessorRevision; /* NOT USED */
      }
#endif
  }
  #endregion

  /////////////////////////////////////////////////////////////////////////////

  #region Unmanaged Interop Methods Static Class (SQLite)
  /// <summary>
................................................................................
      #region Private Data
      /// <summary>
      /// This lock is used to protect the static _SQLiteNativeModuleFileName,
      /// _SQLiteNativeModuleHandle, and processorArchitecturePlatforms fields.
      /// </summary>
      private static readonly object staticSyncRoot = new object();

      /////////////////////////////////////////////////////////////////////////

#if (SQLITE_STANDARD || USE_INTEROP_DLL) && PRELOAD_NATIVE_LIBRARY && !PLATFORM_COMPACTFRAMEWORK
      /// <summary>
      /// This structure is used to cache the human readable strings extracted
      /// from the raw buffer passed to the uname P/Invoke method.  It is only
      /// used on POSIX operating systems.
      /// </summary>
      private static UnsafeNativeMethodsPosix.utsname utsName;
#endif

      /////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// This dictionary stores the mappings between processor architecture
      /// names and platform names.  These mappings are now used for two
      /// purposes.  First, they are used to determine if the assembly code
      /// base should be used instead of the location, based upon whether one
      /// or more of the named sub-directories exist within the assembly code
................................................................................
              }
              catch
              {
                  // do nothing.
              }
#endif
          }


          //
          // NOTE: When running on POSIX (non-Windows), attempt to query the
          //       machine from the operating system via uname().
          //
          if ((processorArchitecture == null) && !HelperMethods.IsWindows())
          {
              lock (staticSyncRoot)
              {
                  if ((utsName.machine != null) ||
                      UnsafeNativeMethodsPosix.GetOsVersionInfo(ref utsName))
                  {
                      processorArchitecture = utsName.machine;
                  }
              }
          }
#else
          if (processorArchitecture == null)
          {
              //
              // NOTE: On the .NET Compact Framework, attempt to use the native
              //       Win32 API function (via P/Invoke) that can provide us
              //       with the processor architecture.

              //
              try
              {
                  //
                  // NOTE: The output of the GetSystemInfo function will be
                  //       placed here.  Only the processor architecture field
                  //       is used by this method.
                  //
                  UnsafeNativeMethodsWin32.SYSTEM_INFO systemInfo;

                  //
                  // NOTE: Query the system information via P/Invoke, thus
                  //       filling the structure.
                  //
                  UnsafeNativeMethodsWin32.GetSystemInfo(out systemInfo);

                  //
                  // NOTE: Return the processor architecture value as a string.
                  //
                  processorArchitecture =
                      systemInfo.wProcessorArchitecture.ToString();
              }
              catch
              {
                  // do nothing.
              }

              //
              // NOTE: Upon failure, return an empty string.  This will prevent
              //       the calling method from considering this method call a
              //       "failure".
              //

              processorArchitecture = String.Empty;
          }
#endif

          /////////////////////////////////////////////////////////////////////

          return processorArchitecture;
      }

      /////////////////////////////////////////////////////////////////////////







>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|







 







|








<








>
>
>
>
>
>
|







 







>

>
>
>






<







 







<
<
<
<
<
<
<
<
<
<
<







 







>

<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<



<
<
|
>

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
<
<
<
<
<

|
|
|

>
|

<







896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
...
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
...
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
....
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
....
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
....
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361

1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
....
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423

1424
1425
1426
1427
1428
1429
1430
....
1499
1500
1501
1502
1503
1504
1505











1506
1507
1508
1509
1510
1511
1512
....
2957
2958
2959
2960
2961
2962
2963
2964
2965

2966



2967










2968
2969
2970


2971
2972
2973


















2974

2975





2976
2977
2978
2979
2980
2981
2982
2983

2984
2985
2986
2987
2988
2989
2990
      /// </param>
      /// <returns>
      /// The native module handle upon success -OR- IntPtr.Zero on failure.
      /// </returns>
      private delegate IntPtr LoadLibraryCallback(
          string fileName
      );

      /////////////////////////////////////////////////////////////////////////

      /// <summary>
      /// This delegate is used to wrap the concept of querying the machine
      /// name of the current process.
      /// </summary>
      /// <returns>
      /// The machine name for the current process -OR- null on failure.
      /// </returns>
      private delegate string GetMachineCallback();
      #endregion

      /////////////////////////////////////////////////////////////////////////

      #region Private Methods
      /// <summary>
      /// Attempts to load the specified native library file using the Win32
................................................................................
          )
      {
          return UnsafeNativeMethodsWin32.LoadLibrary(fileName);
      }

      /////////////////////////////////////////////////////////////////////////

      /// <summary>
      /// Attempts to determine the machine name of the current process using
      /// the Win32 API.
      /// </summary>
      /// <returns>
      /// The machine name for the current process -OR- null on failure.
      /// </returns>
      private static string GetMachineWin32()
      {
          //
          // NOTE: When running on Windows, attempt to use the native Win32
          //       API function (via P/Invoke) that can provide us with the
          //       processor architecture.
          //
          try
          {
              UnsafeNativeMethodsWin32.SYSTEM_INFO systemInfo;

              //
              // NOTE: Query the system information via P/Invoke, thus
              //       filling the structure.
              //
              UnsafeNativeMethodsWin32.GetSystemInfo(out systemInfo);

              //
              // NOTE: Return the processor architecture value as a string.
              //
              return systemInfo.wProcessorArchitecture.ToString();
          }
          catch
          {
              // do nothing.
          }

          return null;
      }

      /////////////////////////////////////////////////////////////////////////

#if !PLATFORM_COMPACTFRAMEWORK
      /// <summary>
      /// Attempts to load the specified native library file using the POSIX
      /// API.
      /// </summary>
      /// <param name="fileName">
      /// The file name of the native library to load.
................................................................................
      private static IntPtr LoadLibraryPosix(
          string fileName
          )
      {
          return UnsafeNativeMethodsPosix.dlopen(
              fileName, UnsafeNativeMethodsPosix.RTLD_DEFAULT);
      }

      /////////////////////////////////////////////////////////////////////////

      /// <summary>
      /// Attempts to determine the machine name of the current process using
      /// the POSIX API.
      /// </summary>
      /// <returns>
      /// The machine name for the current process -OR- null on failure.
      /// </returns>
      private static string GetMachinePosix()
      {
          //
          // NOTE: When running on POSIX (non-Windows), attempt to query the
          //       machine from the operating system via uname().
          //
          try
          {
              UnsafeNativeMethodsPosix.utsname utsName = null;

              if (UnsafeNativeMethodsPosix.GetOsVersionInfo(ref utsName) &&
                  (utsName != null))
              {
                  return utsName.machine;
              }
          }
          catch
          {
              // do nothing.
          }

          return null;
      }
#endif
      #endregion

      /////////////////////////////////////////////////////////////////////////

      #region Public Methods
      /// <summary>
................................................................................
#if !PLATFORM_COMPACTFRAMEWORK
          if (!HelperMethods.IsWindows())
              callback = LoadLibraryPosix;
#endif

          return callback(fileName);
      }

      /////////////////////////////////////////////////////////////////////////

      /// <summary>
      /// Attempts to determine the machine name of the current process.
      /// </summary>
      /// <returns>
      /// The machine name for the current process -OR- null on failure.
      /// </returns>
      public static string GetMachine()
      {
          GetMachineCallback callback = GetMachineWin32;

#if !PLATFORM_COMPACTFRAMEWORK
          if (!HelperMethods.IsWindows())
              callback = GetMachinePosix;
#endif

          return callback();
      }
      #endregion
  }
  #endregion

  /////////////////////////////////////////////////////////////////////////////

  #region Unmanaged Interop Methods Static Class (POSIX)
................................................................................
  {
      /// <summary>
      /// This structure is used when running on POSIX operating systems
      /// to store information about the current machine, including the
      /// human readable name of the operating system as well as that of
      /// the underlying hardware.
      /// </summary>
      internal sealed class utsname
      {
          public string sysname;  /* Name of this implementation of
                                   * the operating system. */
          public string nodename; /* Name of this node within the
                                   * communications network to which
                                   * this node is attached, if any. */
          public string release;  /* Current release level of this
................................................................................
      /// The native module handle upon success -OR- IntPtr.Zero on failure.
      /// </returns>
#if !PLATFORM_COMPACTFRAMEWORK
      [DllImport("kernel32",
#else
      [DllImport("coredll",
#endif
          CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto,
#if !PLATFORM_COMPACTFRAMEWORK
          BestFitMapping = false, ThrowOnUnmappableChar = true,
#endif
          SetLastError = true)]
      internal static extern IntPtr LoadLibrary(string fileName);

      /////////////////////////////////////////////////////////////////////////


      /// <summary>
      /// This is the P/Invoke method that wraps the native Win32 GetSystemInfo
      /// function.  See the MSDN documentation for full details on what it
      /// does.
      /// </summary>
      /// <param name="systemInfo">
      /// The system information structure to be filled in by the function.
      /// </param>
      ///
#if !PLATFORM_COMPACTFRAMEWORK
      [DllImport("kernel32",
#else
      [DllImport("coredll",
#endif
          CallingConvention = CallingConvention.Winapi)]
      internal static extern void GetSystemInfo(out SYSTEM_INFO systemInfo);

      /////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// This enumeration contains the possible values for the processor
      /// architecture field of the system information structure.
      /// </summary>
................................................................................
      internal struct SYSTEM_INFO
      {
          public ProcessorArchitecture wProcessorArchitecture;
          public ushort wReserved; /* NOT USED */
          public uint dwPageSize; /* NOT USED */
          public IntPtr lpMinimumApplicationAddress; /* NOT USED */
          public IntPtr lpMaximumApplicationAddress; /* NOT USED */
#if PLATFORM_COMPACTFRAMEWORK
          public uint dwActiveProcessorMask; /* NOT USED */
#else
          public IntPtr dwActiveProcessorMask; /* NOT USED */
#endif
          public uint dwNumberOfProcessors; /* NOT USED */
          public uint dwProcessorType; /* NOT USED */
          public uint dwAllocationGranularity; /* NOT USED */
          public ushort wProcessorLevel; /* NOT USED */
          public ushort wProcessorRevision; /* NOT USED */
      }

  }
  #endregion

  /////////////////////////////////////////////////////////////////////////////

  #region Unmanaged Interop Methods Static Class (SQLite)
  /// <summary>
................................................................................
      #region Private Data
      /// <summary>
      /// This lock is used to protect the static _SQLiteNativeModuleFileName,
      /// _SQLiteNativeModuleHandle, and processorArchitecturePlatforms fields.
      /// </summary>
      private static readonly object staticSyncRoot = new object();












      /////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// This dictionary stores the mappings between processor architecture
      /// names and platform names.  These mappings are now used for two
      /// purposes.  First, they are used to determine if the assembly code
      /// base should be used instead of the location, based upon whether one
      /// or more of the named sub-directories exist within the assembly code
................................................................................
              }
              catch
              {
                  // do nothing.
              }
#endif
          }
#endif


          /////////////////////////////////////////////////////////////////////














          if (processorArchitecture == null)
          {
              //


              // NOTE: Default to the processor architecture reported by the
              //       appropriate native operating system API, if any.
              //


















              processorArchitecture = NativeLibraryHelper.GetMachine();







              //
              // NOTE: Upon failure, return empty string.  This will prevent
              //       the calling method from considering this method call
              //       a "failure".
              //
              if (processorArchitecture == null)
                  processorArchitecture = String.Empty;
          }


          /////////////////////////////////////////////////////////////////////

          return processorArchitecture;
      }

      /////////////////////////////////////////////////////////////////////////