osutil.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. #include "precompile.h"
  2. #include "osutil.h"
  3. #include "memutil.h"
  4. #include "strutil.h"
  5. #include "toolkit.h"
  6. #ifdef _WIN32
  7. #include <Pdh.h>
  8. #include <TlHelp32.h>
  9. #define DIV (1024 * 1024)
  10. #define DAY_DIV (24 * 60 * 60)
  11. #define HOURS_DIV (60 * 60)
  12. #define MINUS_DIV (60)
  13. TOOLKIT_API int osutil_detect_unique_app(char** pNames, int nNum, int* alive, alive_process_info* alive_process_arr)
  14. {
  15. HANDLE hSnapshot;
  16. int rc = TRUE;
  17. DWORD dwCurProcID = GetCurrentProcessId();
  18. int count = 0;
  19. if (alive) *alive = 0;
  20. hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  21. if (hSnapshot) {
  22. PROCESSENTRY32 pe;
  23. pe.dwSize = sizeof(pe);
  24. if (Process32First(hSnapshot, &pe)) {
  25. do {
  26. int i;
  27. for (i = 0; i < nNum; i++) {
  28. if (stricmp(&pe.szExeFile[0], pNames[i]) == 0 && pe.th32ProcessID != dwCurProcID) {
  29. rc = FALSE;
  30. count++;
  31. break;
  32. }
  33. }
  34. } while (Process32Next(hSnapshot, &pe));
  35. }
  36. CloseHandle(hSnapshot);
  37. }
  38. if (alive) *alive = count;
  39. return rc;
  40. }
  41. TOOLKIT_API int osutil_restart_system()
  42. {
  43. HANDLE hToken;
  44. TOKEN_PRIVILEGES tkp;
  45. BOOL fResult;
  46. // Get the current process token handle so we can get shutdown privilege.
  47. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
  48. fprintf(stderr, "get proc token fail");
  49. return -1;
  50. }
  51. // Get the LUID for shutdown privilege.
  52. LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
  53. tkp.PrivilegeCount = 1; // one privilege to set
  54. tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  55. // Get shutdown privilege for this process.
  56. AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
  57. // Cannot test the return value of AdjustTokenPrivileges.
  58. if (GetLastError() != ERROR_SUCCESS) {
  59. fprintf(stderr, "adjust proc token privilege fail");
  60. return -1;
  61. }
  62. // Display the shutdown dialog box and start the countdown.
  63. fResult = InitiateSystemShutdown(
  64. NULL, // shut down local computer
  65. NULL, // message for user
  66. 0, // time-out period, in seconds
  67. FALSE, // ask user to close apps
  68. TRUE); // reboot after shutdown
  69. if (!fResult) {
  70. fprintf(stderr, "request windows reboot fail");
  71. return -1;
  72. }
  73. // Disable shutdown privilege.
  74. tkp.Privileges[0].Attributes = 0;
  75. AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
  76. return 0;
  77. }
  78. TOOLKIT_API void osutil_terminate_related_process(char** process_array, const int array_size, int force)
  79. {
  80. const DWORD dwCurProcessID = GetCurrentProcessId();
  81. DWORD relateProcessIDs[256];
  82. DWORD dwIdx = 0;
  83. char szCmd[256];
  84. DWORD relateProcessNum = 0;
  85. HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  86. memset(relateProcessIDs, 0, sizeof(relateProcessIDs));
  87. if (hSnapshot)
  88. {
  89. PROCESSENTRY32 pe;
  90. pe.dwSize = sizeof(pe);
  91. if (Process32First(hSnapshot, &pe)) {
  92. do {
  93. int i;
  94. for (i = 0; i < array_size; i++) {
  95. if (stricmp(&pe.szExeFile[0], process_array[i]) == 0 && pe.th32ProcessID != dwCurProcessID) {
  96. relateProcessIDs[relateProcessNum++] = pe.th32ProcessID;
  97. break;
  98. }
  99. }
  100. } while (Process32Next(hSnapshot, &pe));
  101. }
  102. CloseHandle(hSnapshot);
  103. }
  104. for (dwIdx = 0; dwIdx < relateProcessNum; ++dwIdx) {
  105. sprintf_s(szCmd, 256, "TASKKILL /PID %d /F", relateProcessIDs[dwIdx]);
  106. WinExec(szCmd, SW_HIDE);
  107. }
  108. }
  109. TOOLKIT_API int osutil_uname(tk_utsname_t* buffer)
  110. {
  111. return TOOLKIT_UNKNOWN;
  112. }
  113. TOOLKIT_API int osutil_is32r64_platform()
  114. {
  115. int isWow64 = -1;
  116. typedef BOOL(WINAPI* LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);
  117. BOOL bIsWow64 = FALSE;
  118. LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle("kernel32"), "IsWow64Process");
  119. if (NULL != fnIsWow64Process) {
  120. if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64)) {
  121. return -1;
  122. }
  123. else {
  124. isWow64 = bIsWow64 ? 1 : 0;
  125. }
  126. }
  127. return isWow64;
  128. }
  129. TOOLKIT_API ostuile_void_ptr osutil_sure_redirect_32sys_in_wow64()
  130. {
  131. ostuile_void_ptr value = NULL;
  132. if (osutil_is32r64_platform() == 1) {
  133. if (!Wow64DisableWow64FsRedirection(&value)) {
  134. value = NULL;
  135. }
  136. }
  137. return value;
  138. }
  139. TOOLKIT_API void osutil_reset_redirect_32sys_in_wow64(ostuile_void_ptr* value)
  140. {
  141. if (value != NULL && (*value) != NULL) {
  142. Wow64RevertWow64FsRedirection(*value);
  143. }
  144. return;
  145. }
  146. #else
  147. #include <unistd.h>
  148. #include <dirent.h>
  149. #include <sys/types.h> // for opendir(), readdir(), closedir()
  150. #include <sys/stat.h> // for stat()
  151. #include <strings.h>
  152. #include <signal.h>
  153. #include <winpr/wtypes.h>
  154. #include <sys/reboot.h>
  155. #include <sys/utsname.h>
  156. #include <sys/sysinfo.h>
  157. #define DEFAULT_PROCESS_CMDLINE_SIZE 56
  158. #define DEFAULT_PROCESS_PATH_SIZE 8192
  159. #define DEFAULT_PROCESS_NAME_SIZE 1024
  160. static inline int is_num(const char* chars)
  161. {
  162. for (; *chars; chars++)
  163. if (*chars < '0' || *chars > '9')
  164. return 0; // false
  165. return 1; // true
  166. }
  167. static int execute_cmd_return_result(const char* cmd, char* result)
  168. {
  169. char buf_ps[1024];
  170. char ps[1024] = { 0 };
  171. FILE* ptr;
  172. strcpy(ps, cmd);
  173. if ((ptr = popen(ps, "r")) != NULL) {
  174. while (fgets(buf_ps, 1024, ptr) != NULL) {
  175. strcat(result, buf_ps);
  176. if (strlen(result) > 1024)
  177. break;
  178. }
  179. int len = strlen(result);
  180. int i;
  181. for (i = len - 1; i >= 0 && result[i] == '\n'; --i) {
  182. result[i] = '\0';
  183. }
  184. pclose(ptr);
  185. return 0;
  186. } else {
  187. printf("popen %s error\n", ps);
  188. return -1;
  189. }
  190. }
  191. static int private_get_running_process_ids(int* alive, alive_process_info* alive_process_arr, const char* process_name)
  192. {
  193. int ret = 0, capacity, count, idx;
  194. char content[1025];
  195. char cmd[256];
  196. const int cur_pid = (int)getpid();
  197. memset(content, 0, sizeof(content));
  198. capacity = *alive;
  199. *alive = 0;
  200. idx = count = 0;
  201. sprintf(cmd, "pgrep -u root -d '|' %s", process_name);
  202. ret = execute_cmd_return_result(cmd, content);
  203. if (ret == 0 && strlen(content) > 0) {
  204. char** elems = strsplit(content, "|");
  205. if (elems != NULL) {
  206. char** p;
  207. for (p = elems; *p != NULL; ++p) {
  208. int pid;
  209. pid = atoi(*p);
  210. if(pid == cur_pid)
  211. continue;
  212. printf("%d: %s, %d\n", count, *p, pid);
  213. if (count < capacity) {
  214. alive_process_arr[count].pid = pid;
  215. strcpy(alive_process_arr[count].name, process_name);
  216. strcpy(alive_process_arr[count].path, process_name);
  217. idx++;
  218. }
  219. count++;
  220. }
  221. strfreev(elems);
  222. }
  223. }
  224. *alive = idx;
  225. return count;
  226. }
  227. #ifdef NEW_FEATURE
  228. TOOLKIT_API int osutil_detect_unique_app(char** pNames, int nNum, int* alive, alive_process_info* alive_process_arr)
  229. {
  230. int i = 0;
  231. int count = 0, capacity = 0;
  232. int real = 0;
  233. if (alive) {
  234. if (alive_process_arr) capacity = *alive;
  235. *alive = 0;
  236. }
  237. for (i = 0; i < nNum; ++i) {
  238. int cap = capacity - count;
  239. int result = private_get_running_process_ids(&cap, alive_process_arr + count, pNames[i]);
  240. count += cap;
  241. real += result;
  242. }
  243. if (alive) {
  244. *alive = real;
  245. }
  246. return (real > 0) ? FALSE : TRUE;
  247. }
  248. #else
  249. TOOLKIT_API int osutil_detect_unique_app(char** pNames, int nNum, int* alive, alive_process_info* alive_process_arr)
  250. {
  251. int rc = TRUE;
  252. DIR* dir_proc = NULL;
  253. struct dirent* dir_entity = NULL;
  254. int i = 0;
  255. int count = 0, capacity = 0;
  256. char cmdLinePath[DEFAULT_PROCESS_CMDLINE_SIZE] = { 0 };
  257. char processName[DEFAULT_PROCESS_NAME_SIZE] = { 0 };
  258. char processPath[DEFAULT_PROCESS_PATH_SIZE] = { 0 };
  259. pid_t pid = (pid_t)-1;
  260. const pid_t cur_pid = getpid();
  261. if (alive) {
  262. if (alive_process_arr) capacity = *alive;
  263. *alive = 0;
  264. }
  265. dir_proc = opendir("/proc/");
  266. if (dir_proc == NULL) {
  267. return FALSE;
  268. }
  269. while ((dir_entity = readdir(dir_proc))) {
  270. if (dir_entity->d_type == DT_DIR) {
  271. if (is_num(dir_entity->d_name)) {
  272. pid = (pid_t)atoi(dir_entity->d_name);
  273. if (pid == getpid()) {
  274. continue;
  275. }
  276. strcpy(cmdLinePath, "/proc/");
  277. strcat(cmdLinePath, dir_entity->d_name);
  278. strcat(cmdLinePath, "/cmdline");
  279. //printf("%s: open(%s)...\n", __FUNCTION__, cmdLinePath);
  280. FILE* fd_cmdline = fopen(cmdLinePath, "rt");
  281. if (fd_cmdline != NULL) {
  282. memset(processName, 0, DEFAULT_PROCESS_NAME_SIZE);
  283. memset(processPath, 0, DEFAULT_PROCESS_PATH_SIZE);
  284. ///**TODO(Gifur@1/10/2022): 读文件的所有内容并通过结束符0x00去拆分 */
  285. fscanf(fd_cmdline, "%s", processPath);
  286. //printf("%s: close(%p)...\n", __FUNCTION__, fd_cmdline);
  287. fclose(fd_cmdline);
  288. //printf("%s: close(%p) done!\n", __FUNCTION__, fd_cmdline);
  289. if (strrchr(processPath, '/')) {
  290. strcpy(processName, strrchr(processPath, '/') + 1);
  291. } else {
  292. strcpy(processName, processPath);
  293. }
  294. for (i = 0; i < nNum; i++) {
  295. if (strcasecmp(processName, pNames[i]) == 0) {
  296. printf("%s, %s, %d, %d\n", processPath, processName, pid, cur_pid);
  297. if (count < capacity) {
  298. if (strlen(processPath) > ALIVE_PROCESS_PATH_LEN - 1) {
  299. processPath[ALIVE_PROCESS_PATH_LEN - 1] = '\0';
  300. processPath[ALIVE_PROCESS_PATH_LEN - 2] = '.';
  301. processPath[ALIVE_PROCESS_PATH_LEN - 3] = '.';
  302. processPath[ALIVE_PROCESS_PATH_LEN - 4] = '.';
  303. }
  304. strcpy(alive_process_arr[count].path, processPath);
  305. alive_process_arr[count].pid = pid;
  306. strcpy(alive_process_arr[count].name, processName);
  307. }
  308. count++;
  309. rc = FALSE;
  310. break;
  311. }
  312. }
  313. } else {
  314. printf("%s: open(%s) failed %d!!\n", __FUNCTION__, cmdLinePath, errno);
  315. }
  316. }
  317. }
  318. if (!rc && !alive) {
  319. break;
  320. }
  321. }
  322. printf("%s: closedir(%p)...\n", __FUNCTION__, dir_proc);
  323. closedir(dir_proc);
  324. printf("%s: closedir(%p) done!\n", __FUNCTION__, dir_proc);
  325. if (alive) *alive = count;
  326. printf("%s: exit!\n", __FUNCTION__);
  327. return rc;
  328. }
  329. #endif
  330. TOOLKIT_API int osutil_restart_system()
  331. {
  332. int result = -1;
  333. sync();
  334. result = reboot(RB_AUTOBOOT);
  335. return result;
  336. }
  337. #ifdef NEW_FEATURE
  338. TOOLKIT_API void osutil_terminate_related_process(char** process_array, const int array_size, int force)
  339. {
  340. int i, j, k;
  341. const pid_t cur_pid = getpid();
  342. k = 0;
  343. for (i = 0; i < array_size; ++i) {
  344. int count = 50;
  345. alive_process_info processes[50];
  346. memset(processes, 0, sizeof(processes));
  347. int result = private_get_running_process_ids(&count, processes, process_array[i]);
  348. for (j = 0; j < count; ++j) {
  349. printf("kill %s, %s, %d, %d\n", processes[j].path, processes[j].name, processes[j].pid, cur_pid);
  350. int r = kill(processes[j].pid, SIGKILL);
  351. if (r != 0) {
  352. printf("kill of pid=%d failed:%d\n", processes[j].pid, errno);
  353. } else {
  354. k++;
  355. }
  356. }
  357. }
  358. printf("total kill process count: %d\n", k);
  359. }
  360. #else
  361. TOOLKIT_API void osutil_terminate_related_process(char** process_array, const int array_size, int force)
  362. {
  363. DIR* dir_proc = NULL;
  364. struct dirent* dir_entity = NULL;
  365. int i = 0;
  366. int count = 0;
  367. char cmdLinePath[DEFAULT_PROCESS_CMDLINE_SIZE] = { 0 };
  368. char processName[DEFAULT_PROCESS_NAME_SIZE] = { 0 };
  369. char processPath[DEFAULT_PROCESS_PATH_SIZE] = { 0 };
  370. const pid_t cur_pid = getpid();
  371. dir_proc = opendir("/proc/");
  372. if (dir_proc == NULL) {
  373. goto finished;
  374. }
  375. while ((dir_entity = readdir(dir_proc))) {
  376. if (dir_entity->d_type == DT_DIR) {
  377. if (is_num(dir_entity->d_name)) {
  378. pid_t pid = (pid_t)atoi(dir_entity->d_name);
  379. if (pid == getpid()) {
  380. continue;
  381. }
  382. strcpy(cmdLinePath, "/proc/");
  383. strcat(cmdLinePath, dir_entity->d_name);
  384. strcat(cmdLinePath, "/cmdline");
  385. FILE* fd_cmdline = fopen(cmdLinePath, "rt");
  386. if (fd_cmdline != NULL) {
  387. memset(processName, 0, DEFAULT_PROCESS_NAME_SIZE);
  388. memset(processPath, 0, DEFAULT_PROCESS_PATH_SIZE);
  389. fscanf(fd_cmdline, "%s", processPath);
  390. fclose(fd_cmdline);
  391. if (strrchr(processPath, '/')) {
  392. strcpy(processName, strrchr(processPath, '/') + 1);
  393. } else {
  394. strcpy(processName, processPath);
  395. }
  396. for (i = 0; i < array_size; i++) {
  397. if (strcasecmp(processName, process_array[i]) == 0) {
  398. printf("kill %s, %s, %d, %d, type: %s\n", processPath, processName, pid, cur_pid, !!force ? "SIGKILL" : "SIGTERM");
  399. int r = kill(pid, !!force ? SIGKILL : SIGTERM);
  400. if (r != 0) {
  401. printf("kill of pid=%d failed:%d\n", pid, errno);
  402. }
  403. else {
  404. Sleep(200);
  405. count++;
  406. }
  407. break;
  408. }
  409. }
  410. } else if(errno != 2) {
  411. printf("%s: open(%s) failed %d!!\n", __FUNCTION__, cmdLinePath, errno);
  412. }
  413. }
  414. }
  415. }
  416. closedir(dir_proc);
  417. finished:
  418. printf("total kill process count: %d\n", count);
  419. }
  420. #endif
  421. /*cat /ect/os-release*/
  422. TOOLKIT_API int osutil_uname(tk_utsname_t* buffer)
  423. {
  424. struct utsname buf;
  425. int r;
  426. if (buffer == NULL)
  427. return TOOLKIT_EINVAL;
  428. if (uname(&buf) == -1) {
  429. r = TOOLKIT__ERR(errno);
  430. goto error;
  431. }
  432. r = strscpy(buffer->sysname, buf.sysname, sizeof(buffer->sysname));
  433. if (r == TOOLKIT_E2BIG)
  434. goto error;
  435. r = strscpy(buffer->release, buf.release, sizeof(buffer->release));
  436. if (r == TOOLKIT_E2BIG)
  437. goto error;
  438. r = strscpy(buffer->version, buf.version, sizeof(buffer->version));
  439. if (r == TOOLKIT_E2BIG)
  440. goto error;
  441. r = strscpy(buffer->machine, buf.machine, sizeof(buffer->machine));
  442. if (r == TOOLKIT_E2BIG)
  443. goto error;
  444. return 0;
  445. error:
  446. buffer->sysname[0] = '\0';
  447. buffer->release[0] = '\0';
  448. buffer->version[0] = '\0';
  449. buffer->machine[0] = '\0';
  450. return r;
  451. }
  452. TOOLKIT_API int osutil_is32r64_platform()
  453. {
  454. return 0;
  455. }
  456. TOOLKIT_API ostuile_void_ptr osutil_sure_redirect_32sys_in_wow64()
  457. {
  458. ostuile_void_ptr value = NULL;
  459. return value;
  460. }
  461. TOOLKIT_API void osutil_reset_redirect_32sys_in_wow64(ostuile_void_ptr* value)
  462. {
  463. return;
  464. }
  465. #endif
  466. TOOLKIT_API int osutil_shutdown_system()
  467. {
  468. //system("poweroff");
  469. system("shutdown -h now");
  470. return 0;
  471. }
  472. TOOLKIT_API int osutil_system_boot_time(tk_systime_t* ptr_boot_time)
  473. {
  474. int result = -1;
  475. #if defined(_MSC_VER)
  476. const char* SystemElapsedQuery = "\\System\\System Up Time";
  477. PDH_STATUS Status;
  478. HQUERY Query = NULL;
  479. HCOUNTER hcElapsedTimeCount;
  480. /** 杀毒软件会对附件这几个系统调用函数有所监控,导致有时会耗费5s时间 Gifur@20221019]*/
  481. Status = PdhOpenQuery(NULL, NULL, &Query);
  482. PDH_FMT_COUNTERVALUE counterValue;
  483. if (Status != ERROR_SUCCESS) {
  484. return result;
  485. }
  486. Status = PdhAddCounter(Query, SystemElapsedQuery, NULL, &hcElapsedTimeCount);
  487. if (Status != ERROR_SUCCESS) {
  488. return result;
  489. }
  490. Status = PdhCollectQueryData(Query);
  491. if (Status != ERROR_SUCCESS) {
  492. goto Cleanup;
  493. }
  494. Status = PdhGetFormattedCounterValue(hcElapsedTimeCount, PDH_FMT_LARGE, NULL, &counterValue);
  495. if (Status == ERROR_SUCCESS) {
  496. FILETIME ftCurTime, ftStartTime;
  497. GetSystemTimeAsFileTime(&ftCurTime);
  498. ULARGE_INTEGER uliCurTime;
  499. uliCurTime.HighPart = ftCurTime.dwHighDateTime;
  500. uliCurTime.LowPart = ftCurTime.dwLowDateTime;
  501. uliCurTime.QuadPart -= counterValue.largeValue * 1e7;
  502. ftStartTime.dwHighDateTime = uliCurTime.HighPart;
  503. ftStartTime.dwLowDateTime = uliCurTime.LowPart;
  504. SYSTEMTIME stUTC, stLocal;
  505. FileTimeToSystemTime(&ftStartTime, &stUTC);
  506. SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);
  507. ptr_boot_time->year = stLocal.wYear;
  508. ptr_boot_time->month = stLocal.wMonth;
  509. ptr_boot_time->dayofweek = stLocal.wDayOfWeek;
  510. ptr_boot_time->day = stLocal.wDay;
  511. ptr_boot_time->hour = stLocal.wHour;
  512. ptr_boot_time->minute = stLocal.wMinute;
  513. ptr_boot_time->second = stLocal.wSecond;
  514. ptr_boot_time->milli_seconds = stLocal.wMilliseconds;
  515. result = 0;
  516. }
  517. Cleanup:
  518. Status = PdhRemoveCounter(hcElapsedTimeCount);
  519. if (Query) {
  520. PdhCloseQuery(Query);
  521. }
  522. #else
  523. DWORD ticks = 0;
  524. struct sysinfo info;
  525. time_t curTime = 0;
  526. time_t bootTime = 0;
  527. struct tm* ptm = NULL;
  528. if (sysinfo(&info)) {
  529. return result;
  530. }
  531. time(&curTime);
  532. if (curTime > info.uptime) {
  533. bootTime = curTime - info.uptime;
  534. }
  535. else
  536. {
  537. bootTime = info.uptime - curTime;
  538. }
  539. ptm = localtime(&bootTime);
  540. ptr_boot_time->year = (WORD)(ptm->tm_year + 1900);
  541. ptr_boot_time->month = (WORD)(ptm->tm_mon + 1);
  542. ptr_boot_time->dayofweek = (WORD)ptm->tm_wday;
  543. ptr_boot_time->day = (WORD)ptm->tm_mday;
  544. ptr_boot_time->hour = (WORD)ptm->tm_hour;
  545. ptr_boot_time->minute = (WORD)ptm->tm_min;
  546. ptr_boot_time->second = (WORD)ptm->tm_sec;
  547. struct timespec ts;
  548. if (!clock_gettime(CLOCK_MONOTONIC_RAW, &ts)) {//获取毫秒的数据不太准确
  549. ticks = (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000);
  550. }
  551. ptr_boot_time->milli_seconds = (WORD)(ticks % 1000);
  552. result = 0;
  553. #endif //_MSC_VER
  554. return result;
  555. }