2 * PROJECT: ReactOS AT utility
3 * COPYRIGHT: See COPYING in the top level directory
4 * FILE: base/applications/cmdutils/at/at.c
5 * PURPOSE: ReactOS AT utility
6 * PROGRAMMERS: Eric Kohl <eric.kohl@reactos.org>
24 PWSTR pszDaysOfWeekArray
[7] = {NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
29 FreeDaysOfWeekArray(VOID
)
33 for (i
= 0; i
< 7; i
++)
35 if (pszDaysOfWeekArray
[i
] != NULL
)
36 HeapFree(GetProcessHeap(), 0, pszDaysOfWeekArray
[i
]);
43 InitDaysOfWeekArray(VOID
)
47 for (i
= 0; i
< 7; i
++)
49 nLength
= GetLocaleInfo(LOCALE_USER_DEFAULT
,
50 LOCALE_SABBREVDAYNAME1
+ i
,
54 pszDaysOfWeekArray
[i
] = HeapAlloc(GetProcessHeap(),
56 nLength
* sizeof(WCHAR
));
57 if (pszDaysOfWeekArray
[i
] == NULL
)
59 FreeDaysOfWeekArray();
63 GetLocaleInfo(LOCALE_USER_DEFAULT
,
64 LOCALE_SABBREVDAYNAME1
+ i
,
65 pszDaysOfWeekArray
[i
],
80 PWSTR startPtr
, endPtr
;
81 ULONG ulHour
= 0, ulMinute
= 0;
86 ulHour
= wcstoul(startPtr
, &endPtr
, 10);
87 if (ulHour
< 24 && endPtr
!= NULL
&& *endPtr
== L
':')
89 startPtr
= endPtr
+ 1;
91 ulMinute
= wcstoul(startPtr
, &endPtr
, 10);
92 if (ulMinute
< 60 && endPtr
!= NULL
&& *endPtr
== UNICODE_NULL
)
96 if (pulJobHour
!= NULL
)
99 if (pulJobMinute
!= NULL
)
100 *pulJobMinute
= ulMinute
;
114 PWSTR startPtr
, endPtr
;
116 BOOL bResult
= FALSE
;
120 ulId
= wcstoul(startPtr
, &endPtr
, 10);
121 if (endPtr
!= NULL
&& *endPtr
== UNICODE_NULL
)
137 PULONG pulDaysOfMonth
)
139 PWSTR startPtr
, endPtr
;
142 if (wcslen(pszBuffer
) == 0)
145 startPtr
= pszBuffer
;
149 ulValue
= wcstoul(startPtr
, &endPtr
, 10);
153 if (ulValue
> 0 && ulValue
<= 31)
154 *pulDaysOfMonth
|= (1 << (ulValue
- 1));
156 if (endPtr
!= NULL
&& *endPtr
== UNICODE_NULL
)
159 startPtr
= endPtr
+ 1;
171 PUCHAR pucDaysOfWeek
)
173 PWSTR startPtr
, endPtr
;
176 if (wcslen(pszBuffer
) == 0)
179 startPtr
= pszBuffer
;
183 endPtr
= wcschr(startPtr
, L
',');
185 nLength
= wcslen(startPtr
);
187 nLength
= (INT
)((ULONG_PTR
)endPtr
- (ULONG_PTR
)startPtr
) / sizeof(WCHAR
);
189 for (i
= 0; i
< 7; i
++)
191 if (nLength
== wcslen(pszDaysOfWeekArray
[i
]) &&
192 _wcsnicmp(startPtr
, pszDaysOfWeekArray
[i
], nLength
) == 0)
194 *pucDaysOfWeek
|= (1 << i
);
202 startPtr
= endPtr
+ 1;
215 PWSTR pszBuffer
= NULL
;
217 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
,
225 ConPrintf(StdErr
, L
"%s\n", pszBuffer
);
226 LocalFree(pszBuffer
);
232 PrintHorizontalLine(VOID
)
237 for (i
= 0; i
< 79; i
++)
239 szBuffer
[79] = UNICODE_NULL
;
241 ConPrintf(StdOut
, L
"%s\n", szBuffer
);
247 GetTimeAsJobTime(VOID
)
254 JobTime
= (DWORD_PTR
)Time
.wHour
* 3600000 +
255 (DWORD_PTR
)Time
.wMinute
* 60000;
263 GetCurrentDayOfMonth(VOID
)
269 return 1UL << (Time
.wDay
- 1);
281 SYSTEMTIME Time
= {0, 0, 0, 0, 0, 0, 0, 0};
284 Time
.wMinute
= wMinute
;
286 GetTimeFormat(LOCALE_USER_DEFAULT
,
298 PWSTR pszComputerName
,
301 PAT_INFO pBuffer
= NULL
;
302 DWORD_PTR CurrentTime
;
303 WCHAR szStatusBuffer
[16];
304 WCHAR szScheduleBuffer
[60];
305 WCHAR szTimeBuffer
[16];
306 WCHAR szInteractiveBuffer
[16];
307 WCHAR szDateBuffer
[8];
308 INT i
, nDateLength
, nScheduleLength
;
310 NET_API_STATUS Status
;
312 Status
= NetScheduleJobGetInfo(pszComputerName
,
315 if (Status
!= NERR_Success
)
317 PrintErrorMessage(Status
);
321 hInstance
= GetModuleHandle(NULL
);
323 if (pBuffer
->Flags
& JOB_EXEC_ERROR
)
324 LoadStringW(hInstance
, IDS_ERROR
, szStatusBuffer
, _countof(szStatusBuffer
));
326 LoadStringW(hInstance
, IDS_OK
, szStatusBuffer
, _countof(szStatusBuffer
));
328 if (pBuffer
->DaysOfMonth
!= 0)
330 if (pBuffer
->Flags
& JOB_RUN_PERIODICALLY
)
331 LoadStringW(hInstance
, IDS_EVERY
, szScheduleBuffer
, _countof(szScheduleBuffer
));
333 LoadStringW(hInstance
, IDS_NEXT
, szScheduleBuffer
, _countof(szScheduleBuffer
));
335 nScheduleLength
= wcslen(szScheduleBuffer
);
336 for (i
= 0; i
< 31; i
++)
338 if (pBuffer
->DaysOfMonth
& (1 << i
))
340 swprintf(szDateBuffer
, L
" %d", i
+ 1);
341 nDateLength
= wcslen(szDateBuffer
);
342 if (nScheduleLength
+ nDateLength
<= 55)
344 wcscat(szScheduleBuffer
, szDateBuffer
);
345 nScheduleLength
+= nDateLength
;
349 wcscat(szScheduleBuffer
, L
"...");
355 else if (pBuffer
->DaysOfWeek
!= 0)
357 if (pBuffer
->Flags
& JOB_RUN_PERIODICALLY
)
358 LoadStringW(hInstance
, IDS_EVERY
, szScheduleBuffer
, _countof(szScheduleBuffer
));
360 LoadStringW(hInstance
, IDS_NEXT
, szScheduleBuffer
, _countof(szScheduleBuffer
));
362 nScheduleLength
= wcslen(szScheduleBuffer
);
363 for (i
= 0; i
< 7; i
++)
365 if (pBuffer
->DaysOfWeek
& (1 << i
))
367 swprintf(szDateBuffer
, L
" %s", pszDaysOfWeekArray
[i
]);
368 nDateLength
= wcslen(szDateBuffer
);
369 if (nScheduleLength
+ nDateLength
<= 55)
371 wcscat(szScheduleBuffer
, szDateBuffer
);
372 nScheduleLength
+= nDateLength
;
376 wcscat(szScheduleBuffer
, L
"...");
384 CurrentTime
= GetTimeAsJobTime();
385 if (CurrentTime
> pBuffer
->JobTime
)
386 LoadStringW(hInstance
, IDS_TOMORROW
, szScheduleBuffer
, _countof(szScheduleBuffer
));
388 LoadStringW(hInstance
, IDS_TODAY
, szScheduleBuffer
, _countof(szScheduleBuffer
));
391 JobTimeToTimeString(szTimeBuffer
,
392 _countof(szTimeBuffer
),
393 (WORD
)(pBuffer
->JobTime
/ 3600000),
394 (WORD
)((pBuffer
->JobTime
% 3600000) / 60000));
396 if (pBuffer
->Flags
& JOB_NONINTERACTIVE
)
397 LoadStringW(hInstance
, IDS_NO
, szInteractiveBuffer
, _countof(szInteractiveBuffer
));
399 LoadStringW(hInstance
, IDS_YES
, szInteractiveBuffer
, _countof(szInteractiveBuffer
));
401 ConResPrintf(StdOut
, IDS_TASKID
, ulJobId
);
402 ConResPrintf(StdOut
, IDS_STATUS
, szStatusBuffer
);
403 ConResPrintf(StdOut
, IDS_SCHEDULE
, szScheduleBuffer
);
404 ConResPrintf(StdOut
, IDS_TIME
, szTimeBuffer
);
405 ConResPrintf(StdOut
, IDS_INTERACTIVE
, szInteractiveBuffer
);
406 ConResPrintf(StdOut
, IDS_COMMAND
, pBuffer
->Command
);
408 NetApiBufferFree(pBuffer
);
417 PWSTR pszComputerName
)
419 PAT_ENUM pBuffer
= NULL
;
420 DWORD dwRead
= 0, dwTotal
= 0;
421 DWORD dwResume
= 0, i
;
422 DWORD_PTR CurrentTime
;
423 NET_API_STATUS Status
;
425 WCHAR szScheduleBuffer
[32];
426 WCHAR szTimeBuffer
[16];
427 WCHAR szDateBuffer
[8];
429 INT j
, nDateLength
, nScheduleLength
;
431 Status
= NetScheduleJobEnum(pszComputerName
,
433 MAX_PREFERRED_LENGTH
,
437 if (Status
!= NERR_Success
)
439 PrintErrorMessage(Status
);
445 ConResPrintf(StdOut
, IDS_NO_ENTRIES
);
449 ConResPrintf(StdOut
, IDS_JOBS_LIST
);
450 PrintHorizontalLine();
452 hInstance
= GetModuleHandle(NULL
);
454 for (i
= 0; i
< dwRead
; i
++)
456 if (pBuffer
[i
].DaysOfMonth
!= 0)
458 if (pBuffer
[i
].Flags
& JOB_RUN_PERIODICALLY
)
459 LoadStringW(hInstance
, IDS_EVERY
, szScheduleBuffer
, _countof(szScheduleBuffer
));
461 LoadStringW(hInstance
, IDS_NEXT
, szScheduleBuffer
, _countof(szScheduleBuffer
));
463 nScheduleLength
= wcslen(szScheduleBuffer
);
464 for (j
= 0; j
< 31; j
++)
466 if (pBuffer
[i
].DaysOfMonth
& (1 << j
))
468 swprintf(szDateBuffer
, L
" %d", j
+ 1);
469 nDateLength
= wcslen(szDateBuffer
);
470 if (nScheduleLength
+ nDateLength
<= 19)
472 wcscat(szScheduleBuffer
, szDateBuffer
);
473 nScheduleLength
+= nDateLength
;
477 wcscat(szScheduleBuffer
, L
"...");
483 else if (pBuffer
[i
].DaysOfWeek
!= 0)
485 if (pBuffer
[i
].Flags
& JOB_RUN_PERIODICALLY
)
486 LoadStringW(hInstance
, IDS_EVERY
, szScheduleBuffer
, _countof(szScheduleBuffer
));
488 LoadStringW(hInstance
, IDS_NEXT
, szScheduleBuffer
, _countof(szScheduleBuffer
));
490 nScheduleLength
= wcslen(szScheduleBuffer
);
491 for (j
= 0; j
< 7; j
++)
493 if (pBuffer
[i
].DaysOfWeek
& (1 << j
))
495 swprintf(szDateBuffer
, L
" %s", pszDaysOfWeekArray
[j
]);
496 nDateLength
= wcslen(szDateBuffer
);
497 if (nScheduleLength
+ nDateLength
<= 55)
499 wcscat(szScheduleBuffer
, szDateBuffer
);
500 nScheduleLength
+= nDateLength
;
504 wcscat(szScheduleBuffer
, L
"...");
512 CurrentTime
= GetTimeAsJobTime();
513 if (CurrentTime
> pBuffer
[i
].JobTime
)
514 LoadStringW(hInstance
, IDS_TOMORROW
, szScheduleBuffer
, _countof(szScheduleBuffer
));
516 LoadStringW(hInstance
, IDS_TODAY
, szScheduleBuffer
, _countof(szScheduleBuffer
));
519 JobTimeToTimeString(szTimeBuffer
,
520 _countof(szTimeBuffer
),
521 (WORD
)(pBuffer
[i
].JobTime
/ 3600000),
522 (WORD
)((pBuffer
[i
].JobTime
% 3600000) / 60000));
525 L
" %6lu %-21s %-11s %s\n",
532 NetApiBufferFree(pBuffer
);
541 PWSTR pszComputerName
,
546 BOOL bInteractiveJob
,
552 NET_API_STATUS Status
;
554 InfoBuffer
.JobTime
= (DWORD_PTR
)ulJobHour
* 3600000 +
555 (DWORD_PTR
)ulJobMinute
* 60000;
556 InfoBuffer
.DaysOfMonth
= ulDaysOfMonth
;
557 InfoBuffer
.DaysOfWeek
= ucDaysOfWeek
;
558 InfoBuffer
.Flags
= (bInteractiveJob
? 0 : JOB_NONINTERACTIVE
) |
559 (bPeriodicJob
? JOB_RUN_PERIODICALLY
: 0);
560 InfoBuffer
.Command
= pszCommand
;
562 Status
= NetScheduleJobAdd(pszComputerName
,
565 if (Status
!= NERR_Success
)
567 PrintErrorMessage(Status
);
571 ConResPrintf(StdOut
, IDS_NEW_JOB
, ulJobId
);
580 PWSTR pszComputerName
,
584 NET_API_STATUS Status
;
586 if (ulJobId
== (ULONG
)-1 && bForceDelete
== FALSE
)
588 ConResPrintf(StdOut
, IDS_CONFIRM_DELETE
);
592 Status
= NetScheduleJobDel(pszComputerName
,
593 (ulJobId
== (ULONG
)-1) ? 0 : ulJobId
,
594 (ulJobId
== (ULONG
)-1) ? -1 : ulJobId
);
595 if (Status
!= NERR_Success
)
597 PrintErrorMessage(Status
);
605 int wmain(int argc
, WCHAR
**argv
)
607 PWSTR pszComputerName
= NULL
;
608 PWSTR pszCommand
= NULL
;
609 ULONG ulJobId
= (ULONG
)-1;
610 ULONG ulJobHour
= (ULONG
)-1;
611 ULONG ulJobMinute
= (ULONG
)-1;
612 BOOL bDeleteJob
= FALSE
, bForceDelete
= FALSE
;
613 BOOL bInteractiveJob
= FALSE
, bPeriodicJob
= FALSE
;
614 BOOL bPrintUsage
= FALSE
;
615 ULONG ulDaysOfMonth
= 0;
616 UCHAR ucDaysOfWeek
= 0;
620 /* Initialize the Console Standard Streams */
623 if (!InitDaysOfWeekArray())
626 /* Parse the computer name */
630 argv
[i
][0] == L
'\\' &&
633 pszComputerName
= argv
[i
];
638 /* Parse the time or job id */
639 if (i
< argc
&& argv
[i
][0] != L
'/')
641 if (ParseTime(argv
[i
], &ulJobHour
, &ulJobMinute
))
646 else if (ParseId(argv
[i
], &ulJobId
))
653 /* Parse the options */
654 for (; i
< argc
; i
++)
656 if (argv
[i
][0] == L
'/')
658 if (_wcsicmp(argv
[i
], L
"/?") == 0)
663 else if (_wcsicmp(argv
[i
], L
"/delete") == 0)
667 else if (_wcsicmp(argv
[i
], L
"/yes") == 0)
671 else if (_wcsicmp(argv
[i
], L
"/interactive") == 0)
673 bInteractiveJob
= TRUE
;
675 else if (_wcsnicmp(argv
[i
], L
"/every:", 7) == 0)
678 if (ParseDaysOfMonth(&(argv
[i
][7]), &ulDaysOfMonth
) == FALSE
)
680 if (ParseDaysOfWeek(&(argv
[i
][7]), &ucDaysOfWeek
) == FALSE
)
682 ulDaysOfMonth
= GetCurrentDayOfMonth();
686 else if (_wcsnicmp(argv
[i
], L
"/next:", 6) == 0)
688 bPeriodicJob
= FALSE
;
689 if (ParseDaysOfMonth(&(argv
[i
][6]), &ulDaysOfMonth
) == FALSE
)
691 if (ParseDaysOfWeek(&(argv
[i
][6]), &ucDaysOfWeek
) == FALSE
)
693 ulDaysOfMonth
= GetCurrentDayOfMonth();
706 /* Parse the command */
707 if (argc
> minIdx
&& argv
[argc
- 1][0] != L
'/')
709 pszCommand
= argv
[argc
- 1];
712 if (bDeleteJob
== TRUE
)
714 /* Check for invalid options or arguments */
715 if (bInteractiveJob
== TRUE
||
716 ulJobHour
!= (ULONG
)-1 ||
717 ulJobMinute
!= (ULONG
)-1 ||
718 ulDaysOfMonth
!= 0 ||
727 nResult
= DeleteJob(pszComputerName
,
733 if (ulJobHour
!= (ULONG
)-1 && ulJobMinute
!= (ULONG
)-1)
735 /* Check for invalid options or arguments */
736 if (bForceDelete
== TRUE
||
744 nResult
= AddJob(pszComputerName
,
755 /* Check for invalid options or arguments */
756 if (bForceDelete
== TRUE
||
757 bInteractiveJob
== TRUE
||
758 ulDaysOfMonth
!= 0 ||
767 if (ulJobId
== (ULONG
)-1)
769 nResult
= PrintAllJobs(pszComputerName
);
773 nResult
= PrintJobDetails(pszComputerName
,
780 FreeDaysOfWeekArray();
782 if (bPrintUsage
== TRUE
)
783 ConResPuts(StdOut
, IDS_USAGE
);