1 /********************************************************************/
2 /*                                                                  */
3 /*  cmd_win.c     Command functions which call the Windows API.     */
4 /*  Copyright (C) 1989 - 2016, 2020 Thomas Mertes                   */
5 /*                                                                  */
6 /*  This file is part of the Seed7 Runtime Library.                 */
7 /*                                                                  */
8 /*  The Seed7 Runtime Library is free software; you can             */
9 /*  redistribute it and/or modify it under the terms of the GNU     */
10 /*  Lesser General Public License as published by the Free Software */
11 /*  Foundation; either version 2.1 of the License, or (at your      */
12 /*  option) any later version.                                      */
13 /*                                                                  */
14 /*  The Seed7 Runtime Library is distributed in the hope that it    */
15 /*  will be useful, but WITHOUT ANY WARRANTY; without even the      */
16 /*  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR */
17 /*  PURPOSE.  See the GNU Lesser General Public License for more    */
18 /*  details.                                                        */
19 /*                                                                  */
20 /*  You should have received a copy of the GNU Lesser General       */
21 /*  Public License along with this program; if not, write to the    */
22 /*  Free Software Foundation, Inc., 51 Franklin Street,             */
23 /*  Fifth Floor, Boston, MA  02110-1301, USA.                       */
24 /*                                                                  */
25 /*  Module: Seed7 Runtime Library                                   */
26 /*  File: seed7/src/cmd_win.c                                       */
27 /*  Changes: 2010 - 2016, 2020  Thomas Mertes                       */
28 /*  Content: Command functions which call the Windows API.          */
29 /*                                                                  */
30 /********************************************************************/
31 
32 #define LOG_FUNCTIONS 0
33 #define VERBOSE_EXCEPTIONS 0
34 
35 #include "version.h"
36 
37 #include "stdlib.h"
38 #include "stdio.h"
39 #include "windows.h"
40 #if ACLAPI_H_PRESENT
41 #include "aclapi.h"
42 #endif
43 #include "io.h"
44 #include "fcntl.h"
45 #ifdef OS_STRI_WCHAR
46 #include "wchar.h"
47 #endif
48 
49 #include "common.h"
50 #include "data_rtl.h"
51 #include "heaputl.h"
52 #include "striutl.h"
53 #include "str_rtl.h"
54 #include "rtl_err.h"
55 
56 #undef EXTERN
57 #define EXTERN
58 #include "cmd_drv.h"
59 
60 
61 #ifndef PATH_MAX
62 #define PATH_MAX 2048
63 #endif
64 
65 #if !ACLAPI_H_PRESENT
66 #define SE_FILE_OBJECT 1
67 DWORD GetNamedSecurityInfoW (LPCWSTR pObjectName,
68     int objectType, SECURITY_INFORMATION securityInfo,
69     PSID *ppsidOwner, PSID *ppsidGroup,
70     PACL *ppDacl, PACL *ppSacl,
71     PSECURITY_DESCRIPTOR *ppSecurityDescriptor);
72 DWORD SetNamedSecurityInfoW (LPWSTR pObjectName,
73     int objectType, SECURITY_INFORMATION securityInfo,
74     PSID psidOwner, PSID psidGroup,
75     PACL pDacl, PACL pSacl);
76 #endif
77 
78 
79 
80 #if defined OS_STRI_WCHAR && !defined USE_WMAIN
81 #ifdef DEFINE_COMMAND_LINE_TO_ARGV_W
82 #define CommandLineToArgvW MyCommandLineToArgvW
83 /**
84  *  Special handling of backslash characters for CommandLineToArgvW.
85  *  CommandLineToArgvW reads arguments in two modes. Inside and
86  *  outside quotation mode. The following rules apply if a
87  *  backslash is encountered:
88  *  - 2n backslashes followed by a quotation mark produce
89  *    n backslashes and a switch from inside to outside quotation
90  *    mode and vice versa. In this case the quotation mark is not
91  *    added to the argument.
92  *  - (2n) + 1 backslashes followed by a quotation mark produce
93  *    n backslashes followed by a quotation mark. In this case the
94  *    quotation mark is added to the argument and the quotation mode
95  +    is not changed.
96  *  - n backslashes not followed by a quotation mark simply produce
97  *    n backslashes.
98  */
processBackslash(const_os_striType * sourcePos,os_striType * destPos)99 static void processBackslash (const_os_striType *sourcePos, os_striType *destPos)
100 
101   {
102     memSizeType backslashCount;
103     memSizeType count;
104 
105   /* processBackslash */
106     backslashCount = 1;
107     (*sourcePos)++;
108     while (**sourcePos == '\\') {
109       backslashCount++;
110       (*sourcePos)++;
111     } /* while */
112     if (**sourcePos == '"') {
113       /* Backslashes in the result: backslashCount / 2   */
114       for (count = backslashCount >> 1; count > 0; count--) {
115         **destPos = '\\';
116         (*destPos)++;
117       } /* for */
118       if (backslashCount & 1) {
119         /* Add a quotation mark (") to the result.       */
120         **destPos = '"';
121         (*destPos)++;
122         /* Stay in current quotation mode                */
123         (*sourcePos)++;
124       } else {
125         /* Ignore the quotation mark (").                */
126         /* Switch from inside to outside quotation mode  */
127         /* and vice versa.                               */
128       } /* if */
129     } else {
130       /* N backslashes not followed by a quotation mark  */
131       /* simply produce n backslashes.                   */
132       for (count = backslashCount; count > 0; count--) {
133         **destPos = '\\';
134         (*destPos)++;
135       } /* for */
136     } /* if */
137   } /* processBackslash */
138 
139 
140 
141 /**
142  *  Parse commandLine and generate an array of pointers to the arguments.
143  *  The parameter w_argc and the returned array of pointers (w_argv)
144  *  correspond to the parameters argc and argv of main().
145  *  The rules to recognize the first argument (the command) are
146  *  different from the rules to recognize the other (normal) arguments.
147  *  Arguments can be quoted or unquoted. Normal arguments (all except
148  *  the first argument) can consist of quoted and unquoted parts. The
149  *  quoted and unquoted parts that are concatenated to form one argument.
150  *  To handle quoted and unquoted parts the function works with two
151  *  modes: Inside and outside quotation mode.
152  *  @param w_argc Address to which the argument count is copied.
153  *  @return an array of pointers to the arguments of commandLine.
154  */
CommandLineToArgvW(const_os_striType commandLine,int * w_argc)155 static os_striType *CommandLineToArgvW (const_os_striType commandLine, int *w_argc)
156 
157   {
158     size_t command_line_size;
159     const_os_striType sourcePos;
160     os_striType destPos;
161     os_striType destBuffer;
162     memSizeType argumentCount;
163     os_striType *w_argv;
164 
165   /* CommandLineToArgvW */
166     command_line_size = os_stri_strlen(commandLine);
167     argumentCount = 0;
168     w_argv = (os_striType *) malloc(command_line_size * sizeof(os_striType *));
169     if (w_argv != NULL) {
170       sourcePos = commandLine;
171       while (*sourcePos == ' ') {
172         sourcePos++;
173       } /* while */
174       if (*sourcePos == 0) {
175         w_argv[0] = NULL;
176       } else {
177         if (unlikely(!os_stri_alloc(destBuffer, command_line_size))) {
178           free(w_argv);
179           w_argv = NULL;
180         } else {
181           /* Set pointer to first char of first argument */
182           w_argv[0] = destBuffer;
183           argumentCount = 1;
184           destPos = destBuffer;
185           if (*sourcePos == '"') {
186             sourcePos++;
187             while (*sourcePos != '"' && *sourcePos != 0) {
188               *destPos = *sourcePos;
189               sourcePos++;
190               destPos++;
191             } /* if */
192           } else {
193             while (*sourcePos != ' ' && *sourcePos != 0) {
194               *destPos = *sourcePos;
195               sourcePos++;
196               destPos++;
197             } /* if */
198           } /* if */
199           if (*sourcePos != 0) {
200             do {
201               sourcePos++;
202             } while (*sourcePos == ' ');
203             if (*sourcePos != 0) {
204               /* Terminate the current argument */
205               *destPos = 0;
206               destPos++;
207               /* Set pointer to first char of next argument */
208               w_argv[argumentCount] = destPos;
209               argumentCount++;
210             } /* if */
211           } /* if */
212           while (*sourcePos != 0) {
213             /* printf("source char: %d\n", *sourcePos); */
214             if (*sourcePos == '"') {
215               /* Inside quotation mode */
216               sourcePos++;
217               while (*sourcePos != '"' && *sourcePos != 0) {
218                 if (*sourcePos == '\\') {
219                   processBackslash(&sourcePos, &destPos);
220                 } else {
221                   *destPos = *sourcePos;
222                   sourcePos++;
223                   destPos++;
224                 } /* if */
225               } /* while */
226               if (*sourcePos == '"') {
227                 /* Consume the terminating quotation mark */
228                 sourcePos++;
229               } /* if */
230             } /* if */
231             if (*sourcePos != ' ' && *sourcePos != 0) {
232               /* Outside quotation mode */
233               do {
234                 if (*sourcePos == '\\') {
235                   processBackslash(&sourcePos, &destPos);
236                 } else {
237                   *destPos = *sourcePos;
238                   sourcePos++;
239                   destPos++;
240                 } /* if */
241               } while (*sourcePos != ' ' && *sourcePos != '"' && *sourcePos != 0);
242             } /* if */
243             if (*sourcePos == ' ') {
244               do {
245                 sourcePos++;
246               } while (*sourcePos == ' ');
247               if (*sourcePos != 0) {
248                 /* Terminate the current argument */
249                 *destPos = 0;
250                 destPos++;
251                 /* Set pointer to first char of next argument */
252                 w_argv[argumentCount] = destPos;
253                 argumentCount++;
254               } /* if */
255             } /* if */
256           } /* while */
257           /* Terminate the last argument */
258           *destPos = 0;
259           w_argv[argumentCount] = NULL;
260         } /* if */
261       } /* if */
262     } /* if */
263     *w_argc = argumentCount;
264     return w_argv;
265   } /* CommandLineToArgvW */
266 
267 
268 
freeUtf16Argv(os_striType * w_argv)269 void freeUtf16Argv (os_striType *w_argv)
270 
271   { /* freeUtf16Argv */
272     if (w_argv != NULL) {
273       os_stri_free(w_argv[0]);
274       free(w_argv);
275     } /* if */
276   } /* freeUtf16Argv */
277 
278 #else
279 
280 
281 
freeUtf16Argv(os_striType * w_argv)282 void freeUtf16Argv (os_striType *w_argv)
283 
284   { /* freeUtf16Argv */
285     LocalFree(w_argv);
286   } /* freeUtf16Argv */
287 #endif
288 
289 
290 
getUtf16Argv(int * w_argc)291 os_striType *getUtf16Argv (int *w_argc)
292 
293   {
294     os_striType commandLine;
295     os_striType *w_argv;
296 
297   /* getUtf16Argv */
298     commandLine = GetCommandLineW();
299     w_argv = CommandLineToArgvW(commandLine, w_argc);
300     return w_argv;
301   } /* getUtf16Argv */
302 #endif
303 
304 
305 
306 /**
307  *  Get the absolute path of the executable of the current process.
308  *  @param arg_0 Parameter argv[0] from the function main() as string.
309  *  @return the absolute path of the current process.
310  */
getExecutablePath(const const_striType arg_0)311 striType getExecutablePath (const const_striType arg_0)
312 
313   {
314     os_charType buffer[PATH_MAX];
315     errInfoType err_info = OKAY_NO_ERROR;
316     striType executablePath;
317 
318   /* getExecutablePath */
319     if (unlikely(GetModuleFileNameW(NULL, buffer, PATH_MAX) == 0)) {
320       raise_error(FILE_ERROR);
321       executablePath = NULL;
322     } else {
323       executablePath = cp_from_os_path(buffer, &err_info);
324       if (unlikely(executablePath == NULL)) {
325         raise_error(err_info);
326       } /* if */
327     } /* if */
328     return executablePath;
329   } /* getExecutablePath */
330 
331 
332 
333 #if USE_GET_ENVIRONMENT
getEnvironment(void)334 os_striType *getEnvironment (void)
335 
336   {
337     os_striType envBuffer;
338     os_striType currPos;
339     memSizeType length;
340     memSizeType numElems = 0;
341     memSizeType currIdx = 0;
342     os_striType *env;
343 
344   /* getEnvironment */
345     logFunction(printf("getEnvironment()"););
346     envBuffer = GetEnvironmentStringsW();
347     if (envBuffer == NULL) {
348       env = NULL;
349     } else {
350       /* printf("envBuffer: \"" FMT_S_OS "\"\n", envBuffer); */
351       currPos = envBuffer;
352       do {
353         length = os_stri_strlen(currPos);
354         currPos = &currPos[length + 1];
355         numElems++;
356       } while (length != 0);
357       /* printf("numElems: " FMT_U_MEM "\n", numElems); */
358       env = (os_striType *) malloc(numElems * sizeof(os_striType));
359       if (env != NULL) {
360         currPos = envBuffer;
361         do {
362           env[currIdx] = currPos;
363           length = os_stri_strlen(currPos);
364           currPos = &currPos[length + 1];
365           currIdx++;
366         } while (length != 0);
367         env[currIdx - 1] = NULL;
368         /* for (currIdx = 0; env[currIdx] != NULL; currIdx++) {
369           printf("env[" FMT_U_MEM "]: \"" FMT_S_OS "\"\n", currIdx, env[currIdx]);
370         } */
371       } /* if */
372       if (env == NULL || env[0] == NULL) {
373         if (FreeEnvironmentStringsW(envBuffer) == 0) {
374           logError(printf("getEnvironment: FreeEnvironmentStrings() failed.\n"););
375         } /* if */
376       } /* if */
377     } /* if */
378     return env;
379   }  /* getEnvironment */
380 
381 
382 
freeEnvironment(os_striType * environment)383 void freeEnvironment (os_striType *environment)
384 
385   { /* freeEnvironment */
386     if (environment != NULL) {
387       if (environment[0] != NULL) {
388         if (FreeEnvironmentStringsW(environment[0]) == 0) {
389           logError(printf("getEnvironment: FreeEnvironmentStrings() failed.\n"););
390         } /* if */
391       } /* if */
392       free(environment);
393     } /* if */
394   } /* freeEnvironment */
395 #endif
396 
397 
398 
399 #ifdef DEFINE_WGETENV
wgetenv(const const_os_striType name)400 os_striType wgetenv (const const_os_striType name)
401 
402   {
403     memSizeType value_size;
404     os_striType value;
405 
406   /* wgetenv */
407     value_size = GetEnvironmentVariableW(name, NULL, 0);
408     if (value_size == 0) {
409       value = NULL;
410     } else {
411       if (ALLOC_WSTRI(value, value_size - 1)) {
412         if (GetEnvironmentVariableW(name, value, value_size) != value_size - 1) {
413           FREE_OS_STRI(value);
414           value = NULL;
415         } /* if */
416       } /* if */
417     } /* if */
418     return value;
419   } /* wgetenv */
420 #endif
421 
422 
423 
424 #ifdef DEFINE_WSETENV
wsetenv(const const_os_striType name,const const_os_striType value,int overwrite)425 int wsetenv (const const_os_striType name, const const_os_striType value,
426     int overwrite)
427 
428   {
429     int result;
430 
431   /* wsetenv */
432     logFunction(printf("wsetenv(\"" FMT_S_OS "\", \"" FMT_S_OS "\", &d)\n",
433                        name, value, overwrite););
434     result = !SetEnvironmentVariableW(name, value);
435     return result;
436   } /* wsetenv */
437 #endif
438 
439 
440 
441 #ifdef DEFINE_WUNSETENV
wunsetenv(const const_os_striType name)442 int wunsetenv (const const_os_striType name)
443 
444   {
445     int result;
446 
447   /* wunsetenv */
448     logFunction(printf("wunsetenv(\"" FMT_S_OS "\")\n", name););
449     result = !SetEnvironmentVariableW(name, NULL);
450     return result;
451   } /* wunsetenv */
452 #endif
453 
454 
455 
getNameFromSid(PSID sid)456 static striType getNameFromSid (PSID sid)
457 
458   {
459     LPWSTR AcctName;
460     DWORD dwAcctName = 0;
461     LPWSTR DomainName;
462     DWORD dwDomainName = 0;
463     SID_NAME_USE eUse = SidTypeUnknown;
464     errInfoType err_info = OKAY_NO_ERROR;
465     striType name;
466 
467   /* getNameFromSid */
468     LookupAccountSidW(NULL, sid,
469                       NULL, (LPDWORD) &dwAcctName,
470                       NULL, (LPDWORD) &dwDomainName, &eUse);
471     AcctName = (LPWSTR) GlobalAlloc(GMEM_FIXED, dwAcctName * sizeof(os_charType));
472     DomainName = (LPWSTR) GlobalAlloc(GMEM_FIXED, dwDomainName * sizeof(os_charType));
473     if (unlikely(AcctName == NULL || DomainName == NULL)) {
474       logError(printf("getNameFromSid: GlobalAlloc() failed:\n"
475                       "lastError=" FMT_U32 "\n",
476                       (uint32Type) GetLastError()););
477       if (AcctName != NULL) {
478         GlobalFree(AcctName);
479       } /* if */
480       raise_error(MEMORY_ERROR);
481       name = NULL;
482     } else if (unlikely(
483       LookupAccountSidW(NULL, sid,
484                         AcctName, (LPDWORD) &dwAcctName,
485                         DomainName, (LPDWORD) &dwDomainName,
486                         &eUse) == FALSE)) {
487       logError(printf("getNameFromSid: LookupAccountSidW() failed:\n"
488                       "lastError=" FMT_U32 "\n",
489                       (uint32Type) GetLastError()););
490       GlobalFree(AcctName);
491       GlobalFree(DomainName);
492       raise_error(FILE_ERROR);
493       name = NULL;
494     } else {
495       name = os_stri_to_stri(AcctName, &err_info);
496       GlobalFree(AcctName);
497       GlobalFree(DomainName);
498       if (unlikely(name == NULL)) {
499         raise_error(err_info);
500       } /* if */
501     } /* if */
502     return name;
503   } /* getNameFromSid */
504 
505 
506 
getSidFromName(const const_striType name,errInfoType * err_info)507 static PSID getSidFromName (const const_striType name, errInfoType *err_info)
508 
509   {
510     os_striType accountName;
511     DWORD numberOfBytesForSid = 0;
512     DWORD numberOfCharsForDomainName = 0;
513     os_striType domainName;
514     SID_NAME_USE sidNameUse = SidTypeInvalid;
515     PSID sid = NULL;
516 
517   /* getSidFromName */
518     logFunction(printf("getSidFromName(\"%s\", %d)\n",
519                        striAsUnquotedCStri(name), *err_info););
520     accountName = stri_to_os_stri(name, err_info);
521     if (likely(accountName != NULL)) {
522       LookupAccountNameW(NULL, accountName, NULL, &numberOfBytesForSid,
523                          NULL, &numberOfCharsForDomainName, &sidNameUse);
524       sid = (PSID) malloc(numberOfBytesForSid);
525       if (unlikely(sid == NULL)) {
526         *err_info = MEMORY_ERROR;
527       } else if (unlikely(!ALLOC_OS_STRI(domainName, numberOfCharsForDomainName))) {
528         free(sid);
529         *err_info = MEMORY_ERROR;
530         sid = NULL;
531       } else {
532         if (unlikely(LookupAccountNameW(NULL, accountName, sid, &numberOfBytesForSid,
533                                         domainName, &numberOfCharsForDomainName, &sidNameUse) == 0)) {
534           logError(printf("getSidFromName: LookupAccountNameW failed:\n"
535                           "lastError=" FMT_U32 "\n",
536                           (uint32Type) GetLastError()););
537           free(sid);
538           *err_info = FILE_ERROR;
539           sid = NULL;
540         } /* if */
541         FREE_OS_STRI(domainName);
542       } /* if */
543       os_stri_free(accountName);
544     } /* if */
545     return sid;
546   } /* getSidFromName */
547 
548 
549 
cmdGetGroup(const const_striType filePath)550 striType cmdGetGroup (const const_striType filePath)
551 
552   {
553     os_striType os_path;
554     int path_info = PATH_IS_NORMAL;
555     errInfoType err_info = OKAY_NO_ERROR;
556     PSECURITY_DESCRIPTOR pSD = NULL;
557     PSID pSidGroup = NULL;
558     striType group;
559 
560   /* cmdGetGroup */
561     logFunction(printf("cmdGetGroup(\"%s\")", striAsUnquotedCStri(filePath));
562                 fflush(stdout););
563     os_path = cp_to_os_path(filePath, &path_info, &err_info);
564     if (unlikely(os_path == NULL)) {
565       logError(printf("cmdGetGroup: cp_to_os_path(\"%s\", *, *) failed:\n"
566                       "path_info=%d, err_info=%d\n",
567                       striAsUnquotedCStri(filePath), path_info, err_info););
568       raise_error(err_info);
569       group = NULL;
570     } else if (unlikely(
571       GetNamedSecurityInfoW(os_path, SE_FILE_OBJECT,
572                             GROUP_SECURITY_INFORMATION, NULL,
573                             &pSidGroup, NULL, NULL, &pSD) != ERROR_SUCCESS)) {
574       logError(printf("cmdGetGroup: "
575                       "GetNamedSecurityInfoW(\"" FMT_S_OS "\", ...) failed:\n"
576                       "lastError=" FMT_U32 "\n",
577                       os_path, (uint32Type) GetLastError()););
578       os_stri_free(os_path);
579       raise_error(FILE_ERROR);
580       group = NULL;
581     } else {
582       os_stri_free(os_path);
583       group = getNameFromSid(pSidGroup);
584       /* The SID referenced by pSidOwner is located */
585       /* inside of the PSECURITY_DESCRIPTOR pSD.    */
586       /* Therefore it is freed together with pSD.   */
587       LocalFree(pSD);
588     } /* if */
589     logFunctionResult(printf("\"%s\"\n", striAsUnquotedCStri(group)););
590     return group;
591   } /* cmdGetGoup */
592 
593 
594 
cmdGetOwner(const const_striType filePath)595 striType cmdGetOwner (const const_striType filePath)
596 
597   {
598     os_striType os_path;
599     int path_info = PATH_IS_NORMAL;
600     errInfoType err_info = OKAY_NO_ERROR;
601     PSECURITY_DESCRIPTOR pSD = NULL;
602     PSID pSidOwner = NULL;
603     striType owner;
604 
605   /* cmdGetOwner */
606     logFunction(printf("cmdGetOwner(\"%s\")", striAsUnquotedCStri(filePath));
607                 fflush(stdout););
608     os_path = cp_to_os_path(filePath, &path_info, &err_info);
609     if (unlikely(os_path == NULL)) {
610       logError(printf("cmdGetOwner: cp_to_os_path(\"%s\", *, *) failed:\n"
611                       "path_info=%d, err_info=%d\n",
612                       striAsUnquotedCStri(filePath), path_info, err_info););
613       raise_error(err_info);
614       owner = NULL;
615     } else if (unlikely(
616       GetNamedSecurityInfoW(os_path, SE_FILE_OBJECT,
617                             OWNER_SECURITY_INFORMATION, &pSidOwner,
618                             NULL, NULL, NULL, &pSD) != ERROR_SUCCESS)) {
619       logError(printf("cmdGetOwner: "
620                       "GetNamedSecurityInfoW(\"" FMT_S_OS "\", ...) failed:\n"
621                       "lastError=" FMT_U32 "\n",
622                       os_path, (uint32Type) GetLastError()););
623       os_stri_free(os_path);
624       raise_error(FILE_ERROR);
625       owner = NULL;
626     } else {
627       os_stri_free(os_path);
628       owner = getNameFromSid(pSidOwner);
629       /* The SID referenced by pSidOwner is located */
630       /* inside of the PSECURITY_DESCRIPTOR pSD.    */
631       /* Therefore it is freed together with pSD.   */
632       LocalFree(pSD);
633     } /* if */
634     logFunctionResult(printf("\"%s\"\n", striAsUnquotedCStri(owner)););
635     return owner;
636   } /* cmdGetOwner */
637 
638 
639 
cmdSetGroup(const const_striType filePath,const const_striType group)640 void cmdSetGroup (const const_striType filePath, const const_striType group)
641 
642   {
643     os_striType os_path;
644     int path_info = PATH_IS_NORMAL;
645     errInfoType err_info = OKAY_NO_ERROR;
646     PSID pSidGroup;
647 
648   /* cmdSetGroup */
649     logFunction(printf("cmdSetGroup(\"%s\", ", striAsUnquotedCStri(filePath));
650                 printf("\"%s\")\n", striAsUnquotedCStri(group)));
651     os_path = cp_to_os_path(filePath, &path_info, &err_info);
652     if (unlikely(os_path == NULL)) {
653       logError(printf("cmdSetGroup: cp_to_os_path(\"%s\", *, *) failed:\n"
654                       "path_info=%d, err_info=%d\n",
655                       striAsUnquotedCStri(filePath), path_info, err_info););
656       raise_error(err_info);
657     } else {
658       pSidGroup = getSidFromName(group, &err_info);
659       if (unlikely(pSidGroup == NULL)) {
660         os_stri_free(os_path);
661         raise_error(err_info);
662       } else {
663         SetNamedSecurityInfoW(os_path, SE_FILE_OBJECT,
664                               GROUP_SECURITY_INFORMATION, NULL,
665                               pSidGroup, NULL, NULL);
666         free(pSidGroup);
667         os_stri_free(os_path);
668       } /* if */
669     } /* if */
670   } /* cmdSetGroup */
671 
672 
673 
cmdSetOwner(const const_striType filePath,const const_striType owner)674 void cmdSetOwner (const const_striType filePath, const const_striType owner)
675 
676   {
677     os_striType os_path;
678     int path_info = PATH_IS_NORMAL;
679     errInfoType err_info = OKAY_NO_ERROR;
680     PSID pSidOwner;
681 
682   /* cmdSetOwner */
683     logFunction(printf("cmdSetOwner(\"%s\", ", striAsUnquotedCStri(filePath));
684                 printf("\"%s\")\n", striAsUnquotedCStri(owner)));
685     os_path = cp_to_os_path(filePath, &path_info, &err_info);
686     if (unlikely(os_path == NULL)) {
687       logError(printf("cmdSetOwner: cp_to_os_path(\"%s\", *, *) failed:\n"
688                       "path_info=%d, err_info=%d\n",
689                       striAsUnquotedCStri(filePath), path_info, err_info););
690       raise_error(err_info);
691     } else {
692       pSidOwner = getSidFromName(owner, &err_info);
693       if (unlikely(pSidOwner == NULL)) {
694         os_stri_free(os_path);
695         raise_error(err_info);
696       } else {
697         SetNamedSecurityInfoW(os_path, SE_FILE_OBJECT,
698                               OWNER_SECURITY_INFORMATION, pSidOwner,
699                               NULL, NULL, NULL);
700         free(pSidOwner);
701         os_stri_free(os_path);
702       } /* if */
703     } /* if */
704   } /* cmdSetOwner */
705 
706 
707 
cmdUser(void)708 striType cmdUser (void)
709 
710   {
711     HANDLE hToken = NULL;
712     TOKEN_USER *ptu = NULL;
713     DWORD dwSize = 0;
714     striType user;
715 
716   /* cmdUser */
717     if (unlikely(OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken) == 0 &&
718                  OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) == 0)) {
719       logError(printf("cmdUser: OpenThreadToken() and OpenProcessToken() failed."););
720       raise_error(FILE_ERROR);
721       user = NULL;
722     } else {
723       if (unlikely(GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize) != 0 ||
724                    ERROR_INSUFFICIENT_BUFFER != GetLastError())) {
725         logError(printf("cmdUser: GetTokenInformation() "
726                         "should fail with ERROR_INSUFFICIENT_BUFFER.\n"
727                         "lastError=" FMT_U32 "\n",
728                         (uint32Type) GetLastError()););
729         raise_error(FILE_ERROR);
730         user = NULL;
731       } else {
732         ptu = (TOKEN_USER *) LocalAlloc(LPTR, dwSize);
733         if (unlikely(ptu == NULL)) {
734           raise_error(MEMORY_ERROR);
735           user = NULL;
736         } else {
737           if (GetTokenInformation(hToken, TokenUser, ptu, dwSize, &dwSize) == 0) {
738             logError(printf("cmdUser: GetNamedSecurityInfoW() failed:\n"
739                             "lastError=" FMT_U32 "\n",
740                             (uint32Type) GetLastError()););
741             LocalFree((HLOCAL) ptu);
742             raise_error(FILE_ERROR);
743             user = NULL;
744           } else {
745             user = getNameFromSid(ptu->User.Sid);
746             LocalFree((HLOCAL) ptu);
747           } /* if */
748         } /* if */
749       } /* if */
750     } /* if */
751     return user;
752   } /* cmdUser */
753