~ubuntu-branches/ubuntu/utopic/gridengine/utopic

« back to all changes in this revision

Viewing changes to source/utilbin/windows/SGE_Helper_Service/JobStart.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Mark Hymers
  • Date: 2008-06-25 22:36:13 UTC
  • Revision ID: james.westby@ubuntu.com-20080625223613-tvd9xlhuoct9kyhm
Tags: upstream-6.2~beta2
ImportĀ upstreamĀ versionĀ 6.2~beta2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*___INFO__MARK_BEGIN__*/
 
2
/*************************************************************************
 
3
 *
 
4
 *  The Contents of this file are made available subject to the terms of
 
5
 *  the Sun Industry Standards Source License Version 1.2
 
6
 *
 
7
 *  Sun Microsystems Inc., March, 2001
 
8
 *
 
9
 *
 
10
 *  Sun Industry Standards Source License Version 1.2
 
11
 *  =================================================
 
12
 *  The contents of this file are subject to the Sun Industry Standards
 
13
 *  Source License Version 1.2 (the "License"); You may not use this file
 
14
 *  except in compliance with the License. You may obtain a copy of the
 
15
 *  License at http://gridengine.sunsource.net/Gridengine_SISSL_license.html
 
16
 *
 
17
 *  Software provided under this License is provided on an "AS IS" basis,
 
18
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 
19
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 
20
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 
21
 *  See the License for the specific provisions governing your rights and
 
22
 *  obligations concerning the Software.
 
23
 *
 
24
 *   The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 
25
 *
 
26
 *   Copyright: 2001 by Sun Microsystems, Inc.
 
27
 *
 
28
 *   All Rights Reserved.
 
29
 *
 
30
 ************************************************************************/
 
31
/*___INFO__MARK_END__*/
 
32
 
 
33
#include <afxtempl.h>
 
34
#include <afxmt.h>
 
35
#include <winsock2.h>
 
36
#include <stdio.h>
 
37
#include <fcntl.h>
 
38
#include <sys/types.h>
 
39
#include <sys/stat.h>
 
40
#include <io.h>
 
41
#include <direct.h>
 
42
#include <stdlib.h>
 
43
#include <stdio.h>
 
44
 
 
45
 
 
46
#include "Job.h"
 
47
#include "JobList.h"
 
48
#include "JobStart.h"
 
49
#include "SGE_Helper_Service.h"
 
50
#include "Communication.h"
 
51
 
 
52
#define DESKTOP_ALL (DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW | \
 
53
DESKTOP_CREATEMENU | DESKTOP_HOOKCONTROL | DESKTOP_JOURNALRECORD | \
 
54
DESKTOP_JOURNALPLAYBACK | DESKTOP_ENUMERATE | DESKTOP_WRITEOBJECTS | \
 
55
DESKTOP_SWITCHDESKTOP | STANDARD_RIGHTS_REQUIRED)
 
56
 
 
57
#define WINSTA_ALL (WINSTA_ENUMDESKTOPS | WINSTA_READATTRIBUTES | \
 
58
WINSTA_ACCESSCLIPBOARD | WINSTA_CREATEDESKTOP | WINSTA_WRITEATTRIBUTES | \
 
59
WINSTA_ACCESSGLOBALATOMS | WINSTA_EXITWINDOWS | WINSTA_ENUMERATE | \
 
60
WINSTA_READSCREEN | STANDARD_RIGHTS_REQUIRED)
 
61
 
 
62
#define GENERIC_ACCESS (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | \
 
63
GENERIC_ALL)
 
64
 
 
65
// function forward declarations
 
66
static BOOL GetLogonSID(HANDLE hToken, PSID &pSid);
 
67
static void FreeLogonSID(PSID &pSid);
 
68
static BOOL AddAceToWindowStation(HWINSTA hWinsta, PSID pSid);
 
69
static BOOL AddAceToDesktop(HDESK hDesk, PSID pSid);
 
70
static BOOL RemoveAceFromWindowStation(HWINSTA hWinsta, PSID pSid);
 
71
static BOOL RemoveAceFromDesktop(HDESK hDesk, PSID pSid);
 
72
 
 
73
static BOOL GetJobStartModeFromConf(char **conf, int nconf);
 
74
static BOOL GetModeFromEnv(const char *mode, char **env, int nenv);
 
75
static void WriteEnvToFile(char *pszEnv, char *pszFile);
 
76
static DWORD RedirectStdHandles(const C_Job& Job, HANDLE &hStdout, HANDLE &hStderr);
 
77
 
 
78
// external variables
 
79
extern C_JobList       g_JobList;
 
80
extern C_Communication g_Communication;
 
81
extern HANDLE          g_hWinstaACLMutex;
 
82
extern HANDLE          g_hDeskACLMutex;
 
83
 
 
84
/****** JobStarterThread() ****************************************************
 
85
*  NAME
 
86
*     JobStarterThread() -- starting point of job starter thread
 
87
*
 
88
*  SYNOPSIS
 
89
*     DWORD WINAPI JobStarterThread(LPVOID lpParameter)
 
90
*
 
91
*  FUNCTION
 
92
*     This is the starting point for the job starter thread
 
93
*     It searches a job with js_Received from the job list and tries to
 
94
*     start it. It sends a response to the sge_shepherd if job was
 
95
*     successfully or unsuccessfully started.
 
96
*
 
97
*  INPUTS
 
98
*     LPVOID lpParameter - unused
 
99
*
 
100
*  RESULT
 
101
*     DWORD - exit status of the job starter thread
 
102
*     0:  no errors
 
103
*     >0: GetLastError() value
 
104
*
 
105
*  NOTES
 
106
*******************************************************************************/
 
107
DWORD WINAPI JobStarterThread(LPVOID lpParameter)
 
108
{
 
109
   C_Job    *pJob = NULL;
 
110
   DWORD    ret = 1;
 
111
 
 
112
   // lock access to job list
 
113
   CSingleLock singleLock(&g_JobList.m_JobListMutex);
 
114
   singleLock.Lock();
 
115
 
 
116
   // get job from job list that still is to be executed
 
117
   pJob = g_JobList.GetFirstJobInReceivedState();
 
118
   if(pJob != NULL) {
 
119
      pJob->m_JobStatus = js_ToBeStarted;
 
120
   }
 
121
 
 
122
   // unlock access to job list
 
123
   singleLock.Unlock();
 
124
 
 
125
   if(pJob != NULL) {
 
126
      // start job
 
127
      ret = StartJob(*pJob);
 
128
      
 
129
      // send exit code to sge_shepherd
 
130
      g_Communication.SendExitStatus(*pJob);
 
131
      g_Communication.ShutdownSocket(&(pJob->m_comm_sock));
 
132
   }
 
133
   return ret;
 
134
}
 
135
 
 
136
/****** StartJob() ************************************************************
 
137
*  NAME
 
138
*     StartJob() -- starts the job
 
139
*
 
140
*  SYNOPSIS
 
141
*     DWORD StartJob(C_Job &Job)
 
142
*
 
143
*  FUNCTION
 
144
*     Gives job user full access to the visible desktop, starts the job
 
145
*     waits for job end, reads usage data, withdraws access to visible
 
146
*     desktop from job user.
 
147
*
 
148
*  INPUTS
 
149
*     C_Job &Job - all informations about the job that is to be started
 
150
*
 
151
*  RESULT
 
152
*     DWORD - exit status of the job starter thread
 
153
*     0:  no errors
 
154
*     >0: GetLastError() value
 
155
*
 
156
*  NOTES
 
157
*******************************************************************************/
 
158
DWORD StartJob(C_Job &Job)
 
159
{
 
160
   STARTUPINFO         si; 
 
161
   PROCESS_INFORMATION pi; 
 
162
   DWORD               dwWait;
 
163
   HANDLE              hToken  = INVALID_HANDLE_VALUE;
 
164
   HANDLE              hStdout = INVALID_HANDLE_VALUE;
 
165
   HANDLE              hStderr = INVALID_HANDLE_VALUE;
 
166
   char                *pszEnv = NULL;
 
167
   char                *pszCmdLine = NULL;
 
168
   char                szError[4096];
 
169
   char                szErrorPart[1024];
 
170
   BOOL                bError      = TRUE;
 
171
   DWORD               dwError     = ERROR_SUCCESS;
 
172
   HWINSTA             hWinstaSave = NULL;
 
173
   HWINSTA             hWinsta     = NULL;
 
174
   HDESK               hDesk       = NULL;
 
175
   PSID                pSid        = NULL;
 
176
   BOOL                bResult     = FALSE;
 
177
   char                *pFileName  = NULL;
 
178
   const char          *pszCurDir  = NULL;
 
179
   DWORD               BytesRead   = 0;
 
180
   BOOL                bBackgndMode = FALSE;
 
181
   CSingleLock         singleLock(&g_JobList.m_JobListMutex);
 
182
 
 
183
   if(GetJobStartModeFromConf(Job.conf, Job.nconf) == FALSE) {
 
184
      Job.m_JobStatus = js_Failed;
 
185
      return 1;
 
186
   }
 
187
 
 
188
   // Build environment as local Administrator
 
189
   Job.BuildEnvironment(pszEnv);
 
190
   Job.BuildCommandLine(pszCmdLine);
 
191
   pszCurDir = Job.GetConfValue("cwd");
 
192
 
 
193
   ZeroMemory(&si, sizeof(si));
 
194
   ZeroMemory(&pi, sizeof(pi));
 
195
   ZeroMemory(szErrorPart, sizeof(szErrorPart));
 
196
 
 
197
   if(!LogonUser(
 
198
         Job.user,
 
199
         Job.domain,
 
200
         Job.pass,
 
201
         LOGON32_LOGON_INTERACTIVE,
 
202
         LOGON32_PROVIDER_DEFAULT, 
 
203
         &hToken)) {
 
204
      sprintf(szErrorPart, "LogonUser failed:");
 
205
      goto Cleanup;
 
206
   }
 
207
 
 
208
   bBackgndMode = GetModeFromEnv("SGE_BACKGND_MODE", Job.env, Job.nenv);
 
209
   if(bBackgndMode == FALSE) {
 
210
      // Save a handle to the caller's current window station.
 
211
      if((hWinstaSave = GetProcessWindowStation()) == NULL) {
 
212
         sprintf(szErrorPart, "GetProcessWindowStation failed:");
 
213
         goto Cleanup;
 
214
      }
 
215
 
 
216
      // Get a handle to the interactive window station.
 
217
      hWinsta = OpenWindowStation(
 
218
         "winsta0",                   // the interactive window station 
 
219
         FALSE,                       // handle is not inheritable
 
220
         READ_CONTROL | WRITE_DAC);   // rights to read/write the DACL
 
221
 
 
222
      if(hWinsta == NULL) { 
 
223
         sprintf(szErrorPart, "OpenWindowStation failed:");
 
224
         goto Cleanup;
 
225
      }
 
226
 
 
227
      // To get the correct default desktop, set the caller's 
 
228
      // window station to the interactive window station.
 
229
      if(!SetProcessWindowStation(hWinsta)) {
 
230
         sprintf(szErrorPart, "SetProcessWindowStation(hWinsta) failed:");
 
231
         goto Cleanup;
 
232
      }
 
233
 
 
234
      // Get a handle to the interactive desktop.
 
235
      hDesk = OpenDesktop(
 
236
         "default",     // the interactive window station 
 
237
         0,             // no interaction with other desktop processes
 
238
         FALSE,         // handle is not inheritable
 
239
         READ_CONTROL | // request the rights to read and write the DACL
 
240
         WRITE_DAC | 
 
241
         DESKTOP_WRITEOBJECTS | 
 
242
         DESKTOP_READOBJECTS);
 
243
 
 
244
      // Restore the caller's window station.
 
245
      if(!SetProcessWindowStation(hWinstaSave)) {
 
246
         sprintf(szErrorPart, "SetProcessWindowStation(hWinstaSave) failed:");
 
247
         goto Cleanup;
 
248
      }
 
249
 
 
250
      if(hDesk == NULL) {
 
251
         sprintf(szErrorPart, "OpenDesktop failed:");
 
252
         goto Cleanup;
 
253
      }
 
254
 
 
255
      // Get the SID for the client's logon session.
 
256
      if(!GetLogonSID(hToken, pSid)) {
 
257
         sprintf(szErrorPart, "GetLogonSID failed:");
 
258
         goto Cleanup;
 
259
      }
 
260
 
 
261
      // Allow logon SID full access to interactive window station.
 
262
      if(!AddAceToWindowStation(hWinsta, pSid))  {
 
263
         sprintf(szErrorPart, "AddAceToWindowStation failed:");
 
264
         goto Cleanup;
 
265
      }
 
266
 
 
267
      // Allow logon SID full access to interactive desktop.
 
268
      if(!AddAceToDesktop(hDesk, pSid)) {
 
269
         sprintf(szErrorPart, "AddAceToDesktop failed:");
 
270
         goto Cleanup;
 
271
      }
 
272
   }
 
273
 
 
274
   // Impersonate client to ensure access to executable file.
 
275
   if(!ImpersonateLoggedOnUser(hToken))  {
 
276
      sprintf(szErrorPart, "ImpersonateLoggedOnUser failed:");
 
277
      goto Cleanup;
 
278
   }
 
279
 
 
280
   // Redirect stdout and stderr
 
281
   if(RedirectStdHandles(Job, hStdout, hStderr)!=0) {
 
282
      sprintf(szErrorPart, "Redirecting File Handles failed:");
 
283
      goto Cleanup;
 
284
   }
 
285
 
 
286
   si.cb          = sizeof(STARTUPINFO); 
 
287
   si.dwFlags     |= STARTF_USESTDHANDLES;
 
288
   si.hStdOutput  = hStdout;
 
289
   si.hStdError   = hStderr;
 
290
   si.wShowWindow = SW_SHOW; 
 
291
 
 
292
   if(bBackgndMode == TRUE) {
 
293
      si.lpDesktop = "";
 
294
   } else {
 
295
      si.lpDesktop   = "WinSta0\\Default"; 
 
296
   }
 
297
 
 
298
   // To avoid a race condition with a signal here, lock Job list, check if
 
299
   // this job has been killed in the meanwhile. If job is not locked, start
 
300
   // it (job may not get killed in the meanwhile, because list is locked),
 
301
   // but unlock before the blocking wait. After the job has been started,
 
302
   // killing it will not lead to unexpected resultst.
 
303
   singleLock.Lock();
 
304
   
 
305
   if(Job.m_JobStatus == js_Deleted) {
 
306
      singleLock.Unlock();
 
307
      goto Cleanup;
 
308
   }
 
309
 
 
310
   Job.m_hJobObject = CreateJobObject(NULL, NULL);
 
311
 
 
312
   // Launch the process in the client's logon session.
 
313
   bResult = CreateProcessAsUser(hToken,
 
314
      NULL,
 
315
      pszCmdLine,
 
316
      NULL,
 
317
      NULL,
 
318
      TRUE,
 
319
      NORMAL_PRIORITY_CLASS,//|CREATE_NO_WINDOW,//|CREATE_NEW_CONSOLE,
 
320
      pszEnv,
 
321
      pszCurDir,
 
322
      &si,
 
323
      &pi);
 
324
 
 
325
   if(!bResult) {
 
326
      dwError = GetLastError();
 
327
 
 
328
      RevertToSelf();
 
329
      sprintf(szErrorPart, "CreateProcessAsUser failed:");
 
330
      singleLock.Unlock();
 
331
 
 
332
      SetLastError(dwError);
 
333
      goto Cleanup;
 
334
   }
 
335
 
 
336
   AssignProcessToJobObject(Job.m_hJobObject, pi.hProcess);
 
337
 
 
338
   // End impersonation of client.
 
339
   RevertToSelf();
 
340
 
 
341
   Job.m_JobStatus = js_Started;
 
342
   Job.m_hProcess  = pi.hProcess;
 
343
 
 
344
   // unlock access to job list
 
345
   singleLock.Unlock();
 
346
 
 
347
   // Wait blocking for job end
 
348
   if(bResult && pi.hProcess != INVALID_HANDLE_VALUE) {
 
349
      WriteToLogFile("Waiting for job end.");
 
350
      dwWait = WaitForSingleObjectEx(pi.hProcess, INFINITE, FALSE);
 
351
      if(dwWait==WAIT_OBJECT_0) {
 
352
         Job.StoreUsage(pi.hProcess);
 
353
      }
 
354
      WriteToLogFile("Job ended.");
 
355
      CloseHandle(pi.hProcess); 
 
356
      CloseHandle(Job.m_hJobObject);
 
357
      Job.m_hProcess = INVALID_HANDLE_VALUE;
 
358
      Job.m_hJobObject = INVALID_HANDLE_VALUE;
 
359
      Job.m_JobStatus = js_Finished;
 
360
   }
 
361
   if(pi.hThread != INVALID_HANDLE_VALUE) {
 
362
      CloseHandle(pi.hThread); 
 
363
   }
 
364
 
 
365
   if(bBackgndMode == FALSE) {
 
366
      // Disallow logon SID full access to interactive desktop.
 
367
      if(!RemoveAceFromDesktop(hDesk, pSid)) {
 
368
         sprintf(szErrorPart, "RemoveAceFromDesktop failed:");
 
369
         goto Cleanup;
 
370
      }
 
371
      // Disallow logon SID full access to interactive window station.
 
372
      if(!RemoveAceFromWindowStation(hWinsta, pSid))  {
 
373
         sprintf(szErrorPart, "RemoveAceFromWindowStation failed:");
 
374
         goto Cleanup;
 
375
      }
 
376
   }
 
377
   if(bResult) {
 
378
      bError = FALSE;
 
379
   }
 
380
 
 
381
Cleanup: 
 
382
   if(bError == TRUE) {   
 
383
      char szLastError[501];
 
384
 
 
385
      dwError = GetLastError();
 
386
 
 
387
      if(dwError == 193) {
 
388
         // FormatMessage doesn't provide an error message for errno=193
 
389
         // The table of System Errors from the MSDN Libary tells us:
 
390
         // 193 Is not a valid application.  ERROR_BAD_EXE_FORMAT 
 
391
         strcpy(szLastError, "Is not a valid application.");
 
392
      } else {
 
393
         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 
 
394
            NULL, dwError, 0, szLastError, 500, NULL);
 
395
      }
 
396
 
 
397
      if(strlen(szLastError) > 0) {
 
398
         if(szLastError[strlen(szLastError)-2] == '\r') {
 
399
            szLastError[strlen(szLastError)-2] = '\0';
 
400
         }
 
401
      } else {
 
402
         strcpy(szLastError, "(no error message available from system)");
 
403
      }
 
404
 
 
405
      sprintf(szError, "%s %s (errno=%d)",
 
406
         szErrorPart,
 
407
         szLastError,
 
408
         dwError);
 
409
      WriteToLogFile(szError);
 
410
 
 
411
      Job.szError     = strdup(szError);
 
412
      Job.m_JobStatus = js_Failed;
 
413
   }
 
414
 
 
415
   if(hStdout != INVALID_HANDLE_VALUE) {
 
416
      CloseHandle(hStdout);
 
417
   }
 
418
   if(hStderr != INVALID_HANDLE_VALUE) {
 
419
      CloseHandle(hStderr);
 
420
   }
 
421
 
 
422
   if(hWinstaSave != NULL) {
 
423
      SetProcessWindowStation(hWinstaSave);
 
424
   }
 
425
 
 
426
   // Free the buffer for the logon SID.
 
427
   if(pSid) {
 
428
      FreeLogonSID(pSid);
 
429
   }
 
430
 
 
431
   // Close the handles to the interactive window station and desktop.
 
432
   if(hWinsta != NULL) {
 
433
      CloseWindowStation(hWinsta);
 
434
   }
 
435
   if(hDesk != NULL) {
 
436
      CloseDesktop(hDesk);
 
437
   }
 
438
   // Close the handle to the client's access token.
 
439
   if(hToken != INVALID_HANDLE_VALUE) {
 
440
      CloseHandle(hToken);  
 
441
   }
 
442
 
 
443
   free(pszEnv);
 
444
   free(pszCmdLine);
 
445
   return dwError;
 
446
}
 
447
 
 
448
/****** GetLogonSID() *********************************************************
 
449
*  NAME
 
450
*     GetLogonSID() -- retrieve SID of logged on user
 
451
*
 
452
*  SYNOPSIS
 
453
*     static BOOL GetLogonSID(HANDLE hToken, PSID &pSid)
 
454
*
 
455
*  FUNCTION
 
456
*     Retrieves the SID of the logged on user represented by the logon
 
457
*     token.
 
458
*
 
459
*  INPUTS
 
460
*     HANDLE hToken - token of the logged on user
 
461
*     
 
462
*  OUTPUTS
 
463
*     PSID &pSid - SID of the logged on user
 
464
*
 
465
*  RESULT
 
466
*     BOOL - true if SID could be retrieved, false if not
 
467
*
 
468
*  NOTES
 
469
*******************************************************************************/
 
470
static BOOL GetLogonSID(HANDLE hToken, PSID &pSid) 
 
471
{
 
472
   BOOL          bRet = FALSE;
 
473
   DWORD         dwIndex;
 
474
   DWORD         dwLength = 0;
 
475
   PTOKEN_GROUPS ptg      = NULL;
 
476
 
 
477
   // Get required buffer size and allocate the TOKEN_GROUPS buffer.
 
478
   if(!GetTokenInformation(hToken, TokenGroups,
 
479
                           (LPVOID)ptg, 0, &dwLength)) {
 
480
      if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
 
481
         goto Cleanup;
 
482
      }
 
483
      ptg = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), 
 
484
                                     HEAP_ZERO_MEMORY, dwLength);
 
485
      if(ptg == NULL) {
 
486
         goto Cleanup;
 
487
      }
 
488
   }
 
489
 
 
490
   // Get the token group information from the access token.
 
491
   if(!GetTokenInformation(hToken, TokenGroups,
 
492
                           (LPVOID)ptg, dwLength, &dwLength)) {
 
493
      goto Cleanup;
 
494
   }
 
495
 
 
496
   // Loop through the groups to find the logon SID.
 
497
   for(dwIndex = 0; dwIndex < ptg->GroupCount; dwIndex++) {
 
498
      if((ptg->Groups[dwIndex].Attributes&SE_GROUP_LOGON_ID) == SE_GROUP_LOGON_ID) {
 
499
         // Found the logon SID; make a copy of it.
 
500
         dwLength = GetLengthSid(ptg->Groups[dwIndex].Sid);
 
501
         pSid = (PSID)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength);
 
502
 
 
503
         if(pSid == NULL) {
 
504
             goto Cleanup;
 
505
         }
 
506
         if(!CopySid(dwLength, pSid, ptg->Groups[dwIndex].Sid)) {
 
507
             HeapFree(GetProcessHeap(), 0, (LPVOID)pSid);
 
508
             goto Cleanup;
 
509
         }
 
510
         break;
 
511
      }
 
512
   }
 
513
   bRet = TRUE;
 
514
 
 
515
Cleanup: 
 
516
   // Free the buffer for the token groups.
 
517
   if(ptg != NULL) {
 
518
      HeapFree(GetProcessHeap(), 0, (LPVOID)ptg);
 
519
   }
 
520
   return bRet;
 
521
}
 
522
 
 
523
/****** FreeLogonSID() ****************************************************++++
 
524
*  NAME
 
525
*     FreeLogonSID() -- frees the buffer of the SID 
 
526
*
 
527
*  SYNOPSIS
 
528
*     static void FreeLogonSID(PSID &pSid)
 
529
*
 
530
*  FUNCTION
 
531
*     Frees the buffer of the SID allocated by GetLogonSID()
 
532
*
 
533
*  INPUTS
 
534
*     PSID &pSid - the SID to be freed.
 
535
*     
 
536
*  RESULT
 
537
*     void - no result
 
538
*
 
539
*  NOTES
 
540
*******************************************************************************/
 
541
static void FreeLogonSID(PSID &pSid)
 
542
{
 
543
    HeapFree(GetProcessHeap(), 0, (LPVOID)pSid);
 
544
}
 
545
 
 
546
/****** AddAceToWindowStation() ************************************************
 
547
*  NAME
 
548
*     AddAceToWindowStation() -- adds the ACE of the job user to the ACL of the 
 
549
*                                visible window station.
 
550
*
 
551
*  SYNOPSIS
 
552
*     static BOOL AddAceToWindowStation(HWINSTA hWinsta, PSID pSid)
 
553
*
 
554
*  FUNCTION
 
555
*    Adds the ACE (Access Control Entry) of the job user to the ACL
 
556
*    (Access Control List) of the visible window station.
 
557
*
 
558
*  INPUTS
 
559
*     HWINSTA hWinsta - Handle of the visible window station
 
560
*     PSID    pSid    - SID (Security Identifier) of the job user
 
561
*     
 
562
*  RESULT
 
563
*     BOOL - true if adding succeeded, false if it failed
 
564
*
 
565
*  NOTES
 
566
*******************************************************************************/
 
567
static BOOL AddAceToWindowStation(HWINSTA hWinsta, PSID pSid)
 
568
{
 
569
   ACCESS_ALLOWED_ACE   *pAce;
 
570
   ACL_SIZE_INFORMATION aclSizeInfo;
 
571
   BOOL                 bDaclExist;
 
572
   BOOL                 bDaclPresent;
 
573
   BOOL                 bRet = FALSE;
 
574
   DWORD                dwNewAclSize;
 
575
   DWORD                dwSidSize = 0;
 
576
   DWORD                dwSdSizeNeeded;
 
577
   PACL                 pAcl;
 
578
   PACL                 pNewAcl;
 
579
   PSECURITY_DESCRIPTOR pSd = NULL;
 
580
   PSECURITY_DESCRIPTOR pSdNew = NULL;
 
581
   PVOID                pTempAce;
 
582
   SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;
 
583
   unsigned int         i;
 
584
 
 
585
   if(WaitForSingleObject(g_hWinstaACLMutex, INFINITE) == WAIT_OBJECT_0) {
 
586
      __try
 
587
      {
 
588
         // Obtain the DACL for the window station.
 
589
         if(!GetUserObjectSecurity(hWinsta, &si, pSd, dwSidSize, &dwSdSizeNeeded)) {
 
590
            if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
 
591
               pSd = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(),
 
592
                                       HEAP_ZERO_MEMORY, dwSdSizeNeeded);
 
593
            }
 
594
 
 
595
            if (pSd == NULL) {
 
596
               __leave;
 
597
            }
 
598
 
 
599
            pSdNew = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(),
 
600
                                       HEAP_ZERO_MEMORY, dwSdSizeNeeded);
 
601
 
 
602
            if(pSdNew == NULL) {
 
603
               __leave;
 
604
            }
 
605
 
 
606
            dwSidSize = dwSdSizeNeeded;
 
607
            if(!GetUserObjectSecurity(hWinsta, &si, pSd, dwSidSize, &dwSdSizeNeeded)) {
 
608
               __leave;
 
609
            }
 
610
         } else {
 
611
            __leave;
 
612
         }
 
613
 
 
614
         // Create a new DACL.
 
615
         if(!InitializeSecurityDescriptor(pSdNew, SECURITY_DESCRIPTOR_REVISION)) {
 
616
            __leave;
 
617
         }
 
618
 
 
619
         // Get the DACL from the security descriptor.
 
620
         if(!GetSecurityDescriptorDacl(pSd, &bDaclPresent, &pAcl, &bDaclExist)) {
 
621
            __leave;
 
622
         }
 
623
 
 
624
         // Initialize the ACL.
 
625
         ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION));
 
626
         aclSizeInfo.AclBytesInUse = sizeof(ACL);
 
627
 
 
628
         // Call only if the DACL is not NULL.
 
629
         if (pAcl != NULL) {
 
630
            // get the file ACL size info
 
631
            if(!GetAclInformation(pAcl, (LPVOID)&aclSizeInfo,
 
632
                  sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) {
 
633
               __leave;
 
634
            }
 
635
         }
 
636
 
 
637
         // Compute the size of the new ACL.
 
638
         dwNewAclSize = aclSizeInfo.AclBytesInUse 
 
639
                        + (2*sizeof(ACCESS_ALLOWED_ACE)) 
 
640
                        + (2*GetLengthSid(pSid)) - (2*sizeof(DWORD));
 
641
 
 
642
         // Allocate memory for the new ACL.
 
643
         pNewAcl = (PACL)HeapAlloc(GetProcessHeap(),  
 
644
                           HEAP_ZERO_MEMORY, dwNewAclSize);
 
645
 
 
646
         if(pNewAcl == NULL) {
 
647
            __leave;
 
648
         }
 
649
 
 
650
         // Initialize the new DACL.
 
651
         if(!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION)) {
 
652
            __leave;
 
653
         }
 
654
 
 
655
         // If DACL is present, copy it to a new DACL.
 
656
         if(bDaclPresent) {
 
657
            // Copy the ACEs to the new ACL.
 
658
            if(aclSizeInfo.AceCount) {
 
659
               for(i=0; i < aclSizeInfo.AceCount; i++) {
 
660
                  if(!GetAce(pAcl, i, &pTempAce)) {
 
661
                     __leave;
 
662
                  }
 
663
 
 
664
                  // Add the ACE to the new ACL.
 
665
                  if(!AddAce(pNewAcl, ACL_REVISION, MAXDWORD,
 
666
                        pTempAce, ((PACE_HEADER)pTempAce)->AceSize)) {
 
667
                     __leave;
 
668
                  }
 
669
               }
 
670
            }
 
671
         }
 
672
 
 
673
         // Add the first ACE to the window station.
 
674
         pAce = (ACCESS_ALLOWED_ACE *)HeapAlloc(
 
675
               GetProcessHeap(),
 
676
               HEAP_ZERO_MEMORY,
 
677
               sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pSid) -
 
678
                     sizeof(DWORD));
 
679
 
 
680
         if (pAce == NULL)
 
681
            __leave;
 
682
 
 
683
         pAce->Header.AceType  = ACCESS_ALLOWED_ACE_TYPE;
 
684
         pAce->Header.AceFlags = CONTAINER_INHERIT_ACE |
 
685
                                    INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE;
 
686
         pAce->Header.AceSize  = (WORD)(sizeof(ACCESS_ALLOWED_ACE) +
 
687
                                    GetLengthSid(pSid) - sizeof(DWORD));
 
688
         pAce->Mask            = GENERIC_ACCESS;
 
689
 
 
690
         if (!CopySid(GetLengthSid(pSid), &pAce->SidStart, pSid))
 
691
            __leave;
 
692
 
 
693
         if (!AddAce(
 
694
               pNewAcl,
 
695
               ACL_REVISION,
 
696
               MAXDWORD,
 
697
               (LPVOID)pAce,
 
698
               pAce->Header.AceSize)
 
699
         )
 
700
            __leave;
 
701
 
 
702
         // Add the second ACE to the window station.
 
703
         pAce->Header.AceFlags = NO_PROPAGATE_INHERIT_ACE;
 
704
         pAce->Mask            = WINSTA_ALL;
 
705
 
 
706
         if (!AddAce(
 
707
               pNewAcl,
 
708
               ACL_REVISION,
 
709
               MAXDWORD,
 
710
               (LPVOID)pAce,
 
711
               pAce->Header.AceSize)
 
712
         )
 
713
            __leave;
 
714
 
 
715
         // Set a new DACL for the security descriptor.
 
716
         if (!SetSecurityDescriptorDacl(
 
717
               pSdNew,
 
718
               TRUE,
 
719
               pNewAcl,
 
720
               FALSE)
 
721
         )
 
722
            __leave;
 
723
 
 
724
         // Set the new security descriptor for the window station.
 
725
         if(!SetUserObjectSecurity(hWinsta, &si, pSdNew)) {
 
726
            DWORD dwError;
 
727
            char  szLastError[501];
 
728
 
 
729
            dwError = GetLastError();
 
730
            FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0, szLastError, 500, NULL);
 
731
            __leave;
 
732
         }
 
733
         // Indicate success.
 
734
         bRet = TRUE;
 
735
      }
 
736
      __finally
 
737
      {
 
738
         // Free the allocated buffers.
 
739
 
 
740
         if (pAce != NULL)
 
741
            HeapFree(GetProcessHeap(), 0, (LPVOID)pAce);
 
742
 
 
743
         if (pNewAcl != NULL)
 
744
            HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl);
 
745
 
 
746
         if (pSd != NULL)
 
747
            HeapFree(GetProcessHeap(), 0, (LPVOID)pSd);
 
748
 
 
749
         if (pSdNew != NULL)
 
750
            HeapFree(GetProcessHeap(), 0, (LPVOID)pSdNew);
 
751
      }
 
752
      ReleaseMutex(g_hWinstaACLMutex);
 
753
   }
 
754
   return bRet;
 
755
}
 
756
 
 
757
/****** AddAceToDesktop() ******************************************************
 
758
*  NAME
 
759
*     AddAceToDesktop() -- adds the ACE of the job user to the ACL of the 
 
760
*                          visible desktop.
 
761
*
 
762
*  SYNOPSIS
 
763
*     static BOOL AddAceToDesktop(HDESK hDesk, PSID pSid)
 
764
*
 
765
*  FUNCTION
 
766
*    Adds the ACE (Access Control Entry) of the job user to the ACL
 
767
*    (Access Control List) of the visible desktop.
 
768
*
 
769
*  INPUTS
 
770
*     HDESK hDesk - Handle of the visible desktop
 
771
*     PSID  pSid  - SID (Security Identifier) of the job user
 
772
*     
 
773
*  RESULT
 
774
*     BOOL - true if adding succeeded, false if it failed
 
775
*
 
776
*  NOTES
 
777
*******************************************************************************/
 
778
static BOOL AddAceToDesktop(HDESK hDesk, PSID pSid)
 
779
{
 
780
   ACL_SIZE_INFORMATION aclSizeInfo;
 
781
   BOOL                 bDaclExist;
 
782
   BOOL                 bDaclPresent;
 
783
   BOOL                 bRet      = FALSE;
 
784
   DWORD                dwSidSize = 0;
 
785
   DWORD                dwNewAclSize;
 
786
   DWORD                dwSdSizeNeeded;
 
787
   PVOID                pTempAce;
 
788
   PACL                 pAcl;
 
789
   PACL                 pNewAcl;
 
790
   PSECURITY_DESCRIPTOR pSd    = NULL;
 
791
   PSECURITY_DESCRIPTOR pSdNew = NULL;
 
792
   SECURITY_INFORMATION si     = DACL_SECURITY_INFORMATION;
 
793
   unsigned int         i;
 
794
 
 
795
   if(WaitForSingleObject(g_hDeskACLMutex, INFINITE) == WAIT_OBJECT_0) {
 
796
      __try
 
797
      {
 
798
         // Obtain the security descriptor for the desktop object.
 
799
         if(!GetUserObjectSecurity(hDesk, &si, pSd, dwSidSize, &dwSdSizeNeeded)) {
 
800
            if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
 
801
               pSd = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(),
 
802
                                       HEAP_ZERO_MEMORY, dwSdSizeNeeded);
 
803
               if(pSd == NULL) {
 
804
                  __leave;
 
805
               }
 
806
 
 
807
               pSdNew = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(),
 
808
                                          HEAP_ZERO_MEMORY, dwSdSizeNeeded);
 
809
               if(pSdNew == NULL) {
 
810
                  __leave;
 
811
               }
 
812
 
 
813
               dwSidSize = dwSdSizeNeeded;
 
814
               if(!GetUserObjectSecurity(hDesk, &si, pSd,
 
815
                                       dwSidSize, &dwSdSizeNeeded)) {
 
816
                  __leave;
 
817
               }
 
818
            } else {
 
819
               __leave;
 
820
            }
 
821
         }
 
822
 
 
823
         // Create a new security descriptor.
 
824
         if(!InitializeSecurityDescriptor(pSdNew, SECURITY_DESCRIPTOR_REVISION)) {
 
825
            __leave;
 
826
         }
 
827
 
 
828
         // Obtain the DACL from the security descriptor.
 
829
         if (!GetSecurityDescriptorDacl(pSd, &bDaclPresent, &pAcl, &bDaclExist)) {
 
830
            __leave;
 
831
         }
 
832
 
 
833
         // Initialize.
 
834
         ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION));
 
835
         aclSizeInfo.AclBytesInUse = sizeof(ACL);
 
836
 
 
837
         if(pAcl != NULL) {
 
838
            // Determine the size of the ACL information.
 
839
            if (!GetAclInformation(pAcl, (LPVOID)&aclSizeInfo,
 
840
                     sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) {
 
841
               __leave;
 
842
            }
 
843
         }
 
844
 
 
845
         // Compute the size of the new ACL and allocate buffer
 
846
         dwNewAclSize = aclSizeInfo.AclBytesInUse
 
847
                        + sizeof(ACCESS_ALLOWED_ACE)
 
848
                        + GetLengthSid(pSid) - sizeof(DWORD);
 
849
 
 
850
         pNewAcl = (PACL)HeapAlloc(GetProcessHeap(), 
 
851
                        HEAP_ZERO_MEMORY, dwNewAclSize);
 
852
 
 
853
         if(pNewAcl == NULL) {
 
854
            __leave;
 
855
         }
 
856
 
 
857
         if(!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION)) {
 
858
            __leave;
 
859
         }
 
860
 
 
861
         // If DACL is present, copy it to a new DACL.
 
862
         if(bDaclPresent) {
 
863
            // Copy the ACEs to the new ACL.
 
864
            if(aclSizeInfo.AceCount) {
 
865
               for(i=0; i < aclSizeInfo.AceCount; i++) {
 
866
                  // Get an ACE.
 
867
                  if(!GetAce(pAcl, i, &pTempAce)) {
 
868
                     __leave;
 
869
                  }
 
870
 
 
871
                  // Add the ACE to the new ACL.
 
872
                  if(!AddAce(pNewAcl, ACL_REVISION, MAXDWORD, pTempAce,
 
873
                                          ((PACE_HEADER)pTempAce)->AceSize)) {
 
874
                     __leave;
 
875
                  }
 
876
               }
 
877
            }
 
878
         }
 
879
 
 
880
         // Add ACE to the DACL, set new DACL to the new security descriptor,
 
881
         // set new security descriptor for the desktop object.
 
882
         if(!AddAccessAllowedAce(pNewAcl, ACL_REVISION, DESKTOP_ALL, pSid)) {
 
883
            __leave;
 
884
         }
 
885
         if(!SetSecurityDescriptorDacl(pSdNew, TRUE, pNewAcl, FALSE)) {
 
886
            __leave;
 
887
         }
 
888
         if(!SetUserObjectSecurity(hDesk, &si, pSdNew)) {
 
889
            __leave;
 
890
         }
 
891
         bRet = TRUE;
 
892
      }
 
893
      __finally
 
894
      {
 
895
         // Free buffers.
 
896
         if(pNewAcl != NULL) {
 
897
            HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl);
 
898
         }
 
899
 
 
900
         if(pSd != NULL) {
 
901
            HeapFree(GetProcessHeap(), 0, (LPVOID)pSd);
 
902
         }
 
903
 
 
904
         if(pSdNew != NULL) {
 
905
            HeapFree(GetProcessHeap(), 0, (LPVOID)pSdNew);
 
906
         }
 
907
      }
 
908
      ReleaseMutex(g_hDeskACLMutex);
 
909
   }
 
910
   return bRet;
 
911
}
 
912
 
 
913
/****** RemoveAceFromWindowStation() ******************************************
 
914
*  NAME
 
915
*     RemoveAceFromWindowStation() -- removes the ACE of the job user from the
 
916
*                                     ACL of the visible window station.
 
917
*
 
918
*  SYNOPSIS
 
919
*     static BOOL RemoveAceFromWindowStation(HWINSTA hWinsta, PSID pSid)
 
920
*
 
921
*  FUNCTION
 
922
*    Removes the ACE (Access Control Entry) of the job user from the ACL
 
923
*    (Access Control List) of the visible window station.
 
924
*
 
925
*  INPUTS
 
926
*     HWINSTA hWinsta - Handle of the visible window station
 
927
*     PSID    pSid    - SID (Security Identifier) of the job user
 
928
*     
 
929
*  RESULT
 
930
*     BOOL - true if removing succeeded, false if it failed
 
931
*
 
932
*  NOTES
 
933
*******************************************************************************/
 
934
static BOOL RemoveAceFromWindowStation(HWINSTA hWinsta, PSID pSid)
 
935
{
 
936
   SECURITY_DESCRIPTOR  *pSD = NULL;
 
937
   BOOL                 bSecRet;
 
938
   BOOL                 bDaclPresent = TRUE;
 
939
   BOOL                 bDaclDefaulted = FALSE;
 
940
   DWORD                SDLength = 0;
 
941
   DWORD                SDLengthNeeded = 0;
 
942
   PACL                                 pWinstaDacl;    
 
943
   LPVOID               pWinstaAce;
 
944
   SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;
 
945
   BOOL                 bRet = TRUE;
 
946
   BOOL                 bEqual;
 
947
   PSID                 pListSid;
 
948
   int                  nDeleted = 0;
 
949
 
 
950
   if(WaitForSingleObject(g_hWinstaACLMutex, INFINITE) == WAIT_OBJECT_0) {
 
951
      __try
 
952
      {
 
953
         // Obtain DACL from Windows station, search for ACE, remove ACE from DACL
 
954
         bSecRet = GetUserObjectSecurity(hWinsta, &si, pSD, SDLength, &SDLengthNeeded);
 
955
         if(!bSecRet) {
 
956
            pSD = (SECURITY_DESCRIPTOR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SDLengthNeeded);
 
957
         }
 
958
         bSecRet = GetUserObjectSecurity(hWinsta, &si, pSD, SDLengthNeeded, &SDLengthNeeded);
 
959
         bSecRet = GetSecurityDescriptorDacl(pSD, &bDaclPresent, &pWinstaDacl, &bDaclDefaulted);
 
960
 
 
961
         for(int i=pWinstaDacl->AceCount-1; i>=0; i--) {
 
962
            bSecRet = GetAce(pWinstaDacl, i, &pWinstaAce);
 
963
            if(((ACCESS_ALLOWED_ACE*)pWinstaAce)->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) {
 
964
               pListSid = (PSID)&(((ACCESS_ALLOWED_ACE*)pWinstaAce)->SidStart);
 
965
               bEqual = TRUE;
 
966
               bSecRet = IsValidSid(pSid);
 
967
               bSecRet = IsValidSid(pListSid);
 
968
               DWORD dwSidLength = GetLengthSid(pSid);
 
969
               DWORD dwListSidLength = GetLengthSid(pListSid);
 
970
 
 
971
               for(DWORD j=0; j<dwSidLength && j<dwListSidLength; j++) {
 
972
                  if(*((BYTE*)pListSid+j) != *((BYTE*)pSid+j)) {
 
973
                     bEqual = FALSE;
 
974
                     break;
 
975
                  }
 
976
               }
 
977
               if(bEqual) {
 
978
                  DeleteAce(pWinstaDacl, i);
 
979
                  nDeleted++;
 
980
                  if(nDeleted == 2) {
 
981
                     break;
 
982
                  }
 
983
               }
 
984
            }
 
985
         }
 
986
         SetUserObjectSecurity(hWinsta, &si, pSD);
 
987
      }
 
988
 
 
989
      __finally
 
990
      {
 
991
         if(pSD != NULL) {
 
992
            HeapFree(GetProcessHeap(), 0, (LPVOID)pSD);
 
993
         }
 
994
      }
 
995
 
 
996
      ReleaseMutex(g_hWinstaACLMutex);
 
997
   }         
 
998
   return bRet;
 
999
}
 
1000
 
 
1001
/****** RemoveAceFromDesktop() ************************************************
 
1002
*  NAME
 
1003
*     RemoveAceFromDesktop() -- removes the ACE of the job user from the
 
1004
*                               ACL of the visible desktop
 
1005
*
 
1006
*  SYNOPSIS
 
1007
*     static BOOL RemoveAceFromDesktop(HDESK hDesk, PSID pSid)
 
1008
*
 
1009
*  FUNCTION
 
1010
*    Removes the ACE (Access Control Entry) of the job user from the ACL
 
1011
*    (Access Control List) of the visible desktop
 
1012
*
 
1013
*  INPUTS
 
1014
*     HDESK hDesk - Handle of the visible desktop
 
1015
*     PSID  pSid  - SID (Security Identifier) of the job user
 
1016
*     
 
1017
*  RESULT
 
1018
*     BOOL - true if removing succeeded, false if it failed
 
1019
*
 
1020
*  NOTES
 
1021
*******************************************************************************/
 
1022
static BOOL RemoveAceFromDesktop(HDESK hDesk, PSID pSid)
 
1023
{
 
1024
   SECURITY_DESCRIPTOR  *pSD = NULL;
 
1025
   BOOL                 bSecRet;
 
1026
   BOOL                 bDaclPresent = TRUE;
 
1027
   BOOL                 bDaclDefaulted = FALSE;
 
1028
   DWORD                SDLength = 0;
 
1029
   DWORD                SDLengthNeeded = 0;
 
1030
   PACL                                 pDeskDacl;    
 
1031
   LPVOID               pDeskAce;
 
1032
   SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;
 
1033
   BOOL                 bRet = TRUE;
 
1034
   BOOL                 bEqual;
 
1035
   PSID                 pListSid;
 
1036
 
 
1037
   if(WaitForSingleObject(g_hDeskACLMutex, INFINITE) == WAIT_OBJECT_0) {
 
1038
      __try
 
1039
      {
 
1040
         // Obtain DACL from Windows station, search for ACE, remove ACE from DACL
 
1041
         bSecRet = GetUserObjectSecurity(hDesk, &si, pSD, SDLength, &SDLengthNeeded);
 
1042
         if(!bSecRet) {
 
1043
            pSD = (SECURITY_DESCRIPTOR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SDLengthNeeded);
 
1044
         }
 
1045
         bSecRet = GetUserObjectSecurity(hDesk, &si, pSD, SDLengthNeeded, &SDLengthNeeded);
 
1046
         bSecRet = GetSecurityDescriptorDacl(pSD, &bDaclPresent, &pDeskDacl, &bDaclDefaulted);
 
1047
 
 
1048
         for(DWORD i=0; i<pDeskDacl->AceCount; i++) {
 
1049
            bSecRet = GetAce(pDeskDacl, i, &pDeskAce);
 
1050
            if(((ACCESS_ALLOWED_ACE*)pDeskAce)->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) {
 
1051
               pListSid = (PSID)&(((ACCESS_ALLOWED_ACE*)pDeskAce)->SidStart);
 
1052
               bEqual = TRUE;
 
1053
               bSecRet = IsValidSid(pSid);
 
1054
               bSecRet = IsValidSid(pListSid);
 
1055
               DWORD dwSidLength = GetLengthSid(pSid);
 
1056
               DWORD dwListSidLength = GetLengthSid(pListSid);
 
1057
 
 
1058
               for(DWORD j=0; j<dwSidLength && j<dwListSidLength; j++) {
 
1059
                  if(*((BYTE*)pListSid+j) != *((BYTE*)pSid+j)) {
 
1060
                     bEqual = FALSE;
 
1061
                     break;
 
1062
                  }
 
1063
               }
 
1064
               if(bEqual) {
 
1065
                  DeleteAce(pDeskDacl, i);
 
1066
                  break;
 
1067
               }
 
1068
            }
 
1069
         }
 
1070
         SetUserObjectSecurity(hDesk, &si, pSD);
 
1071
      }
 
1072
      __finally
 
1073
      {
 
1074
         if(pSD != NULL) {
 
1075
            HeapFree(GetProcessHeap(), 0, (LPVOID)pSD);
 
1076
         }
 
1077
      }
 
1078
      ReleaseMutex(g_hDeskACLMutex);
 
1079
   }
 
1080
   return bRet;
 
1081
}
 
1082
 
 
1083
/****** GetJobStartModeFromConf() *********************************************
 
1084
*  NAME
 
1085
*     GetJobStartModeFromConf() -- searches conf for display_win_gui and
 
1086
*                                   retrieves the corresponding value.
 
1087
*
 
1088
*  SYNOPSIS
 
1089
*     static BOOL GetJobStartModeFromConf(char **conf, int nconf)
 
1090
*
 
1091
*  FUNCTION
 
1092
*    Searchs conf for the complex variable display_win_gui and retrieves
 
1093
*    it's value.
 
1094
*
 
1095
*  INPUTS
 
1096
*     char **conf - the configuration that is to be searched
 
1097
*     int  nconf  - number of entries in configuration
 
1098
*     
 
1099
*  RESULT
 
1100
*     BOOL - TRUE if the value of the complex variable display_win_gui is "1",
 
1101
*            else FALSE.
 
1102
*
 
1103
*  NOTES
 
1104
*******************************************************************************/
 
1105
static BOOL GetJobStartModeFromConf(char **conf, int nconf)
 
1106
{
 
1107
   int             i;
 
1108
   char            *ptr;
 
1109
   char            *tmp;
 
1110
   BOOL            bRet = FALSE;
 
1111
   BOOL            bFound = FALSE;
 
1112
 
 
1113
   for(i=0; i<nconf && bFound==FALSE; i++) {
 
1114
      tmp = strdup(conf[i]);
 
1115
      ptr = strtok(tmp, "=");
 
1116
      if(ptr && stricmp(ptr, "display_win_gui")==0) {
 
1117
         ptr=strtok(NULL, "=");
 
1118
         if(ptr && stricmp(ptr, "1")==0) {
 
1119
            bRet = TRUE;
 
1120
            bFound = TRUE;
 
1121
         } 
 
1122
      }
 
1123
      free(tmp);
 
1124
   }
 
1125
   return bRet;
 
1126
}
 
1127
 
 
1128
/****** GetModeFromEnv() ******************************************************
 
1129
*  NAME
 
1130
*     GetModeFromEnv() -- searches env for given variable and retrieves
 
1131
*                         the corresponding value.
 
1132
*
 
1133
*  SYNOPSIS
 
1134
*     static BOOL GetModeFromEnv(const char *mode, char **env, int nenv)
 
1135
*
 
1136
*  FUNCTION
 
1137
*    Searchs env for the given variable and retrieves it's value.
 
1138
*    
 
1139
*
 
1140
*  INPUTS
 
1141
*     char **env - the environment that is to be searched
 
1142
*     int  nenv  - number of entries in environment
 
1143
*     
 
1144
*  RESULT
 
1145
*     BOOL - TRUE if the value of the environment variable is "1"
 
1146
*            or "TRUE" (not case sensitive), else FALSE.
 
1147
*
 
1148
*  NOTES
 
1149
*******************************************************************************/
 
1150
static BOOL GetModeFromEnv(const char *mode, char **env, int nenv)
 
1151
{
 
1152
   int             i;
 
1153
   char            *ptr;
 
1154
   char            *tmp;
 
1155
   BOOL            bRet = FALSE;
 
1156
   BOOL            bFound = FALSE;
 
1157
 
 
1158
   for(i=0; i<nenv && bFound==FALSE; i++) {
 
1159
      tmp = strdup(env[i]);
 
1160
      ptr = strtok(tmp, "=");
 
1161
      if(ptr && stricmp(ptr, mode)==0) {
 
1162
         ptr=strtok(NULL, "=");
 
1163
         if(ptr && (stricmp(ptr, "TRUE")==0 || stricmp(ptr, "1")==0)) {
 
1164
            bRet = TRUE;
 
1165
            bFound = TRUE;
 
1166
         } 
 
1167
      }
 
1168
      free(tmp);
 
1169
   }
 
1170
   return bRet;
 
1171
}
 
1172
 
 
1173
/****** RedirectStdHandles() **************************************************
 
1174
*  NAME
 
1175
*     RedirectStdHandles() -- Redirects stdout and stderr
 
1176
*
 
1177
*  SYNOPSIS
 
1178
*    static DWORD RedirectStdHandles(const C_Job &Job, 
 
1179
*                                    HANDLE &hStdout, HANDLE &hStderr)
 
1180
*
 
1181
*  FUNCTION
 
1182
*    Redirects stdout and stderr of the job to files. The file names are
 
1183
*    retrieved from the job's environment.
 
1184
*
 
1185
*  INPUTS
 
1186
*     C_Job &Job - The job object of the job for whom the standard handles
 
1187
*                  are to be redirected.
 
1188
*
 
1189
*  OUTPUTS
 
1190
*     HANDLE &hStdout - The redirected stdout handle
 
1191
*     HANDLE &hStderr - The redirected stderr handle
 
1192
*     
 
1193
*  RESULT
 
1194
*     DWORD - 0: OK
 
1195
*             1: Can't create stdout file
 
1196
*             2: Can't create stderr file
 
1197
*
 
1198
*  NOTES
 
1199
*******************************************************************************/
 
1200
static DWORD RedirectStdHandles(const C_Job &Job, HANDLE &hStdout, HANDLE &hStderr)
 
1201
{
 
1202
   const char *pszStdout, *pszStderr, *pszMerge;
 
1203
   int        iMerge = 0;
 
1204
   int        ret = 0;
 
1205
 
 
1206
   try {
 
1207
      pszStdout = Job.GetConfValue("stdout_path");
 
1208
      pszStderr = Job.GetConfValue("stderr_path");
 
1209
      pszMerge  = Job.GetConfValue("merge_stderr");
 
1210
      if(pszMerge != NULL) {
 
1211
         sscanf(pszMerge, "%d", &iMerge);
 
1212
      }
 
1213
 
 
1214
      hStdout = CreateFile(
 
1215
                  pszStdout,
 
1216
                  GENERIC_WRITE,
 
1217
                  FILE_SHARE_READ|FILE_SHARE_WRITE,
 
1218
                  NULL,
 
1219
                  OPEN_ALWAYS,
 
1220
                  FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH,
 
1221
                  NULL);
 
1222
      if(hStdout == INVALID_HANDLE_VALUE) {
 
1223
         throw 1;
 
1224
      }
 
1225
      SetFilePointer(hStdout, 1, NULL, FILE_END);
 
1226
      SetHandleInformation(hStdout, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
 
1227
 
 
1228
      if(iMerge == 0) {
 
1229
         hStderr = CreateFile(
 
1230
                     pszStderr,
 
1231
                     GENERIC_WRITE,
 
1232
                     FILE_SHARE_READ|FILE_SHARE_WRITE,
 
1233
                     NULL,
 
1234
                     OPEN_ALWAYS,
 
1235
                     FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH,
 
1236
                     NULL);
 
1237
      } else {
 
1238
         DuplicateHandle(GetCurrentProcess(), hStdout, 
 
1239
                        GetCurrentProcess(), &hStderr,
 
1240
                        0, TRUE, DUPLICATE_SAME_ACCESS);
 
1241
      }
 
1242
      if(hStderr == INVALID_HANDLE_VALUE) {
 
1243
         throw 2;
 
1244
      }
 
1245
      SetFilePointer(hStderr, 1, NULL, FILE_END);
 
1246
      SetHandleInformation(hStderr, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
 
1247
   }
 
1248
   catch(int ret_val) {
 
1249
      ret = ret_val;
 
1250
   }
 
1251
   return ret;
 
1252
}
 
1253
 
 
1254
/******************************************************************************
 
1255
* Test/Debugging functions
 
1256
******************************************************************************/
 
1257
static void WriteEnvToFile(char *pszEnv, char *pszFile) 
 
1258
{
 
1259
   FILE *fp;
 
1260
   char *ptr = pszEnv;
 
1261
 
 
1262
   fp = fopen(pszFile, "w+");
 
1263
   if(fp) {
 
1264
      while(*ptr != '\0' || *(ptr+1) != '\0') {
 
1265
         if(*ptr=='\0') {
 
1266
            fwrite("\n", 1, 1, fp);
 
1267
         } else {
 
1268
            fwrite(ptr, 1, 1, fp);
 
1269
         }
 
1270
         ptr++;
 
1271
      }
 
1272
      fclose(fp);
 
1273
   }
 
1274
}
 
1275
 
 
1276
void OpenPipe()
 
1277
{
 
1278
/*      
 
1279
      // Copy current Job object to pipe
 
1280
      HANDLE hReadParent, hWriteChild;
 
1281
      HANDLE hWriteParent, hReadChild;
 
1282
      HANDLE hDuplReadParent, hDuplWriteParent;
 
1283
      SECURITY_ATTRIBUTES secAttr;
 
1284
 
 
1285
      ZeroMemory(&secAttr, sizeof(secAttr));
 
1286
      secAttr.nLength        = sizeof(secAttr);
 
1287
      secAttr.bInheritHandle = TRUE;
 
1288
 
 
1289
      // Create inheritable pipe
 
1290
      if(!CreatePipe(&hReadParent, &hWriteChild, &secAttr, 10000)) {
 
1291
         goto Cleanup;
 
1292
      }
 
1293
      // Create non-inheritable handle of one side of pipe
 
1294
      DuplicateHandle(GetCurrentProcess(),
 
1295
                        hReadParent,
 
1296
                        GetCurrentProcess(),
 
1297
                        &hDuplReadParent,
 
1298
                        DUPLICATE_SAME_ACCESS,
 
1299
                        FALSE,
 
1300
                        DUPLICATE_SAME_ACCESS);
 
1301
      // Close inheritable duplicate of handle of one side of pipe
 
1302
      CloseHandle(hReadParent);
 
1303
 
 
1304
      // Create inheritable pipe
 
1305
      if(!CreatePipe(&hReadChild, &hWriteParent, &secAttr, 10000)) {
 
1306
         goto Cleanup;
 
1307
      }
 
1308
      // Create non-inheritable handle of one side of pipe
 
1309
      DuplicateHandle(GetCurrentProcess(),
 
1310
                        hWriteParent,
 
1311
                        GetCurrentProcess(),
 
1312
                        &hDuplWriteParent,
 
1313
                        DUPLICATE_SAME_ACCESS,
 
1314
                        FALSE,
 
1315
                        DUPLICATE_SAME_ACCESS);
 
1316
      // Close inheritable duplicate of handle of one side of pipe
 
1317
      CloseHandle(hWriteParent);
 
1318
*/
 
1319
}
 
1320
 
 
1321
//ClosePipe();
 
1322
void ClosePipe()
 
1323
{
 
1324
/*
 
1325
   BOOL bRet;
 
1326
   int iRet;
 
1327
         // First wait for data on the pipe
 
1328
         WriteToLogFile("Now reading data from the pipe.");
 
1329
         iRet = Job.Unserialize(hDuplReadParent);
 
1330
         WriteToLogFile("Read data from the pipe: %d.", iRet);
 
1331
 
 
1332
         FlushFileBuffers(hDuplWriteParent);
 
1333
         bRet = CloseHandle(hDuplWriteParent);
 
1334
         WriteToLogFile("CloseHandle(hDuplWriteParent) returned %d", bRet);
 
1335
 
 
1336
         bRet = CloseHandle(hDuplReadParent);
 
1337
         WriteToLogFile("CloseHandle(hDuplReadParent) returned %d.", bRet);
 
1338
*/
 
1339
}