~leighman/ubuntu/raring/workrave/fix-desktop-file-2

« back to all changes in this revision

Viewing changes to frontend/gtkmm/win32/setup/src/ChangeAutorun.c

  • Committer: Package Import Robot
  • Author(s): Michael Terry
  • Date: 2013-01-24 11:04:41 UTC
  • mfrom: (1.2.10)
  • Revision ID: package-import@ubuntu.com-20130124110441-rbrq0e0y6p71asoc
Tags: 1.10-0ubuntu1
* New upstream release
* debian/control, debian/rules, debian/workrave.install:
  - Enable support for an indicator in Unity (LP: #796824)
* debian/patches/fix-format-security.patch:
  - Fix FTBFS due to -Werror=format-security

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
* ChangeAutorun.c - Change autorun for a new and/or existing user
 
3
*
 
4
* Copyright (C) 2012 Ray Satiro on behalf of the Workrave project
 
5
* All rights reserved.
 
6
*
 
7
* This program is free software: you can redistribute it and/or modify
 
8
* it under the terms of the GNU General Public License as published by
 
9
* the Free Software Foundation, either version 3 of the License, or
 
10
* (at your option) any later version.
 
11
*
 
12
* This program is distributed in the hope that it will be useful,
 
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
* GNU General Public License for more details.
 
16
*
 
17
* You should have received a copy of the GNU General Public License
 
18
* along with this program.  If not, see <http:*www.gnu.org/licenses/>.
 
19
*/
 
20
 
 
21
 
 
22
/*****
 
23
* README, CHANGES REQUIRED
 
24
 
25
* This program, ChangeAutorun, is called by Active Setup to change the autorun settings for a new 
 
26
* and/or existing user of your program.
 
27
 
28
* Your installer should have added to its Active Setup key a StubPath value with data that will run 
 
29
* this program. For more information search the internet for how to configure Active Setup.
 
30
* Example:
 
31
* "StubPath"="\"C:\\Program Files\\Workrave\\lib\\ChangeAutorun.exe\" -b"
 
32
 
33
* Typically you'd set your Active Setup StubPath to call ChangeAutorun with 'a' or 'b' or 'u'.
 
34
* Run ChangeAutorun /? for all options.
 
35
 
36
* Options 'v' and 'z' are for testing purposes and must NOT be options in your ActiveSetup StubPath.
 
37
* Either of those options will routinely show MessageBoxes with information only a developer could 
 
38
* care about and require user input to click 'OK' to the messages, stalling explorer initialization.
 
39
 
40
* REQUIRED CHANGES
 
41
* If this is not the Workrave project you MUST change everything below (until the /END block), and 
 
42
* not use the GUID 180B0AC5-6FDA-438B-9466-C9894322B6BA. Generate your own GUID.
 
43
*/
 
44
 
 
45
/* This is the Active Setup GUID subkey generated by your installer to store its Active Setup. */
 
46
#define ACTIVE_SETUP_GUID   "{180B0AC5-6FDA-438B-9466-C9894322B6BA}"
 
47
 
 
48
/* This is the autorun value stored in the key HKCU_AUTORUN_KEY. The value must be unique.
 
49
This program will add a value of AUTORUN_VALUE to the key with data pointing to the target, eg:
 
50
"Workrave"="\"C:\\Program Files\\Workrave\\lib\\workrave.exe\""
 
51
*/
 
52
#define AUTORUN_VALUE   "Workrave"
 
53
 
 
54
/* This is the name of your project. It is the name that appears in this program's verbose output.
 
55
*/
 
56
#define PROJECT   "Workrave"
 
57
 
 
58
/* This is an HKCU key that has been set by your program after it is run by the user. It should not 
 
59
be a key that is set by your installer. If ChangeAutorun is run with the -b option it needs to 
 
60
determine whether or not the target program has previously been run by the user. It checks for the 
 
61
existence of this key to determine that.
 
62
*/
 
63
#define HKCU_PROJECT_KEY   "AppEvents\\Schemes\\Apps\\Workrave"
 
64
 
 
65
/* This is your target program's executable name, with extension, and without path. It must be in 
 
66
the same directory as this program.
 
67
*/
 
68
#define TARGET   "workrave.exe"
 
69
 
 
70
/* These are the options to pass to the target program. 
 
71
For example:
 
72
"--somearg \"abc\" -asdf"
 
73
If no options use ""
 
74
*/
 
75
#define TARGET_OPTIONS   ""
 
76
 
 
77
/*****
 
78
* /END REQUIRED CHANGES
 
79
* You shouldn't need to change anything below here.
 
80
*/
 
81
 
 
82
 
 
83
/*****
 
84
* COMPILING
 
85
 
86
* I wrote this to create an autorun entry for an x86 target program (TARGET). When compiled x86, 
 
87
* and run on x86 or x64 platform it will access the 32-bit ACTIVE_SETUP_GUID, HKCU_PROJECT_KEY, etc.
 
88
 
89
* You could probably use this program with an x64 TARGET if you compile it x64, and your installer 
 
90
* writes to the 64-bit ACTIVE_SETUP_GUID. In that case this program should access the 64-bit keys.
 
91
* I haven't tested that. If you do test it let me know what happens.
 
92
 
93
* cl /O2 /W4 /DUNICODE ChangeAutorun.c
 
94
* gcc -O2 -Wall -Wextra -Wno-unknown-pragmas -Wno-unused-parameter -DUNICODE -mwindows -o ChangeAutorun.exe ChangeAutorun.c -lpsapi
 
95
*/
 
96
 
 
97
 
 
98
/* Disable cl unused parameter warnings */
 
99
#pragma warning( disable : 4100 )
 
100
 
 
101
#pragma comment( lib, "psapi.lib" )
 
102
#pragma comment( lib, "user32.lib" )
 
103
#pragma comment( lib, "advapi32.lib" )
 
104
 
 
105
#pragma comment( linker, "/SUBSYSTEM:WINDOWS" )
 
106
 
 
107
 
 
108
/* Define both UNICODEs before any includes.
 
109
http://blogs.msdn.com/b/oldnewthing/archive/2004/02/12/71851.aspx#73016
 
110
http://en.wikibooks.org/wiki/Windows_Programming/Unicode#Unicode_Environment
 
111
*/
 
112
#if defined UNICODE && !defined _UNICODE
 
113
#define _UNICODE
 
114
#endif
 
115
 
 
116
#if defined _UNICODE && !defined UNICODE
 
117
#define UNICODE
 
118
#endif
 
119
 
 
120
#if defined _UNICODE && defined _MBCS
 
121
#error Both _UNICODE and _MBCS are defined. Those defines are mutually exclusive.
 
122
#endif
 
123
 
 
124
/* Use the original GetModuleFilenameEx() location.
 
125
http://msdn.microsoft.com/en-us/library/windows/desktop/ms683198.aspx
 
126
*/
 
127
#define PSAPI_VERSION 1
 
128
 
 
129
#define _CRT_SECURE_NO_WARNINGS
 
130
#define _WIN32_WINNT 0x0501
 
131
 
 
132
/* INCLUDES */
 
133
#include <windows.h>
 
134
#include <tchar.h>
 
135
#include <psapi.h>
 
136
#include <stdio.h>
 
137
#include <stdlib.h>
 
138
/* /INCLUDES */
 
139
 
 
140
 
 
141
/* MinGW has KEY_WOW64 defines only when >= 0x502 */
 
142
#ifndef KEY_WOW64_64KEY
 
143
#define KEY_WOW64_64KEY 0x0100
 
144
#endif
 
145
 
 
146
#ifndef KEY_WOW64_32KEY
 
147
#define KEY_WOW64_32KEY 0x0200
 
148
#endif
 
149
 
 
150
 
 
151
#define VERBOSE_ERR(msg)   VERBOSE_ERR_DATA2(msg,NULL,NULL)
 
152
#define VERBOSE_ERR_DATA(msg,tstr1)   VERBOSE_ERR_DATA2(msg,tstr1,NULL)
 
153
#define VERBOSE_ERR_DATA2(msg,tstr1,tstr2)   \
 
154
        if( g_verbose ) \
 
155
                show_message( __LINE__, __FUNCTION__, msg, _T("Error"), tstr1, tstr2 )
 
156
 
 
157
#define VERBOSE_MSG(msg)   VERBOSE_MSG_DATA2(msg,NULL,NULL)
 
158
#define VERBOSE_MSG_DATA(msg,tstr1)   VERBOSE_MSG_DATA2(msg,tstr1,NULL)
 
159
#define VERBOSE_MSG_DATA2(msg,tstr1,tstr2)   \
 
160
        if( g_verbose ) \
 
161
                show_message( __LINE__, __FUNCTION__, msg, _T("Message"), tstr1, tstr2 )
 
162
 
 
163
 
 
164
#define HKCU_AUTORUN_KEY   "Software\\Microsoft\\Windows\\CurrentVersion\\Run"
 
165
 
 
166
 
 
167
/* if _UNICODE then the lengths of these global variables will be a count of wide characters in the 
 
168
string. if not _UNICODE then the lengths will be a count of single byte characters. lengths here 
 
169
will not be a count of multibyte characters even if _MBCS.
 
170
*/
 
171
 
 
172
/* The target's full image name. Initialized at runtime. Example:
 
173
C:\Program Files\Workrave\lib\workrave.exe
 
174
*/
 
175
TCHAR *target_fullname;
 
176
        int length_target_fullname;
 
177
 
 
178
/* The target's directory. Initialized at runtime. Example:
 
179
C:\Program Files\Workrave\lib\
 
180
*/
 
181
TCHAR *target_directory;
 
182
        int length_target_directory;
 
183
 
 
184
/* The command line for the autorun entry. Initialized at runtime. Example:
 
185
"C:\Program Files\Workrave\lib\workrave.exe" -whatever "some arg with spaces" -abc 
 
186
*/
 
187
TCHAR *target_command;
 
188
        int length_target_command;
 
189
 
 
190
/* Verbosity */
 
191
BOOL g_verbose = FALSE;
 
192
 
 
193
 
 
194
enum users
 
195
{
 
196
        IGNORE_THIS_TAG = -1, /* force gcc signed enum */
 
197
        ALL_USERS = 0,
 
198
        NEW_USERS,
 
199
        UPDATE_EXISTING_AUTORUN_ONLY,
 
200
        INVALID
 
201
};
 
202
 
 
203
 
 
204
 
 
205
/* Shows a MessageBox with information. Used by the VERBOSE_ macro functions. */
 
206
void show_message(
 
207
        const int line,
 
208
        const char *function,
 
209
        const TCHAR *message,
 
210
        const TCHAR *title,
 
211
        const TCHAR *data,
 
212
        const TCHAR *data2
 
213
        )
 
214
{
 
215
        TCHAR *buffer = NULL;
 
216
        int length_buffer = 0;
 
217
        int max_length_buffer = 1024;
 
218
        
 
219
        
 
220
        if( data )
 
221
                max_length_buffer += _tcslen( data );
 
222
        
 
223
        if( data2 )
 
224
                max_length_buffer += _tcslen( data2 );
 
225
        
 
226
        buffer = malloc( ( max_length_buffer + 1 ) * sizeof( TCHAR ) );
 
227
        if( !buffer )
 
228
                return;
 
229
        
 
230
        length_buffer = 
 
231
                _sntprintf(
 
232
                        buffer,
 
233
                        max_length_buffer,
 
234
                        _T("%s - ChangeAutorun\n")
 
235
                                _T("Line: %d\n")
 
236
                                _T("Function: %hs()\n")
 
237
                                _T("Project: ") _T(PROJECT) _T("\n")
 
238
                                _T("\n%s")
 
239
                                _T("%s%s\n%s"),
 
240
                        ( ( !title || !*title ) ? _T("<no title>") : title ),
 
241
                        line,
 
242
                        ( ( !function || !*function ) ? "<no function>" : function ),
 
243
                        ( ( !message || !*message ) ? _T("<no message>") : message ),
 
244
                        ( ( data || data2 ) ? _T("\n\nRelated data:\n") : _T("") ),
 
245
                        ( data ? data : _T("") ),
 
246
                        ( data2 ? data2 : _T("") )
 
247
                        );
 
248
        
 
249
        if( length_buffer < 0 )
 
250
                length_buffer = max_length_buffer;
 
251
        
 
252
        buffer[ length_buffer ] = _T('\0');
 
253
        
 
254
        MessageBox( 0, buffer, ( ( !title || !*title ) ? _T("<no title>") : title ), 0 );
 
255
        
 
256
        free( buffer );
 
257
        return;
 
258
}
 
259
 
 
260
 
 
261
 
 
262
/* Check if a file exists. Returns TRUE on success. */
 
263
BOOL file_exists( const TCHAR *filename )
 
264
{
 
265
        HANDLE hFile = NULL;
 
266
        
 
267
        
 
268
        hFile = CreateFile(
 
269
                filename,
 
270
                0,
 
271
                FILE_SHARE_READ,
 
272
                NULL,
 
273
                OPEN_EXISTING,
 
274
                0,
 
275
                NULL
 
276
                );
 
277
        
 
278
        if( hFile == INVALID_HANDLE_VALUE )
 
279
                return FALSE;
 
280
        
 
281
        CloseHandle( hFile );
 
282
        return TRUE;
 
283
}
 
284
 
 
285
 
 
286
 
 
287
/* Check if a registry key exists and can be opened for read. Returns TRUE on success. */
 
288
BOOL regkey_test_read( HKEY mainkey, const TCHAR *subkey )
 
289
{
 
290
        HKEY hkey = NULL;
 
291
        LONG ret = 0;
 
292
        
 
293
        ret = RegOpenKeyEx(
 
294
                mainkey,
 
295
                subkey,
 
296
                0,
 
297
                STANDARD_RIGHTS_READ,
 
298
                &hkey
 
299
                );
 
300
        
 
301
        if( ret || !hkey )
 
302
                return FALSE;
 
303
        
 
304
        if( hkey )
 
305
                RegCloseKey( hkey );
 
306
        
 
307
        return TRUE;
 
308
}
 
309
 
 
310
 
 
311
 
 
312
/* Frees and zeroes all global variables except g_verbose and any const. */
 
313
void free_global_variables()
 
314
{
 
315
        if( target_directory )
 
316
        {
 
317
                free( target_directory );
 
318
                target_directory = NULL;
 
319
        }
 
320
        length_target_directory = 0;
 
321
        
 
322
        if( target_fullname )
 
323
        {
 
324
                free( target_fullname );
 
325
                target_fullname = NULL;
 
326
        }
 
327
        length_target_fullname = 0;
 
328
        
 
329
        if( target_command )
 
330
        {
 
331
                free( target_command );
 
332
                target_command = NULL;
 
333
        }
 
334
        length_target_command = 0;
 
335
        
 
336
        return;
 
337
}
 
338
 
 
339
 
 
340
 
 
341
/* init_global_variables()
 
342
 
 
343
Initialize all global variables except g_verbose and any const.
 
344
 
 
345
Returns TRUE if all variables were successfully initialized. If only some variables were 
 
346
initialized, those that couldn't be initialized will be cleared and this function will return FALSE.
 
347
*/
 
348
BOOL init_global_variables()
 
349
{
 
350
        int i = 0;
 
351
        TCHAR *temp = NULL;
 
352
        int length_target = 0;
 
353
        int max_length_target_command = 0;
 
354
        
 
355
        
 
356
        free_global_variables();
 
357
        
 
358
        
 
359
        /* target_directory
 
360
        Get this program's path from GetModuleFileNameEx().
 
361
        When using that function there's no sure way to know the exact size beforehand.
 
362
        */
 
363
        for( i = 512; i <= 65536; i *= 2, length_target_directory = 0 )
 
364
        {
 
365
                temp = realloc( target_directory, ( i * sizeof( TCHAR ) ) );
 
366
                
 
367
                if( !temp )
 
368
                {
 
369
                        VERBOSE_ERR( _T("realloc() failed. Could not initialize target_directory.") );
 
370
                        goto cleanup;
 
371
                }
 
372
                
 
373
                target_directory = temp;
 
374
                
 
375
                length_target_directory =
 
376
                        GetModuleFileNameEx(
 
377
                                GetCurrentProcess(),
 
378
                                NULL,
 
379
                                target_directory,
 
380
                                i
 
381
                                );
 
382
                
 
383
                if( length_target_directory
 
384
                        && ( ( length_target_directory + 1 ) < i )
 
385
                        )
 
386
                        break;
 
387
        }
 
388
        
 
389
        if( !length_target_directory )
 
390
        {
 
391
                VERBOSE_ERR( _T("GetModuleFileNameEx() failed. Could not initialize target_directory.") );
 
392
                goto cleanup;
 
393
        }
 
394
        
 
395
        target_directory[ length_target_directory ] = _T('\0');
 
396
        
 
397
        if( !file_exists( target_directory ) )
 
398
        {
 
399
                VERBOSE_ERR_DATA(
 
400
                        _T("File not found. Could not initialize target_directory."),
 
401
                        target_directory
 
402
                        );
 
403
                
 
404
                length_target_directory = 0;
 
405
                goto cleanup;
 
406
        }
 
407
        
 
408
        temp = _tcsrchr( target_directory, _T('\\') );
 
409
        
 
410
        if( !temp )
 
411
        {
 
412
                VERBOSE_ERR_DATA(
 
413
                        _T("Backslash not found in string. Could not initialize target_directory."),
 
414
                        target_directory
 
415
                        );
 
416
                
 
417
                length_target_directory = 0;
 
418
                goto cleanup;
 
419
        }
 
420
        
 
421
        *++temp = _T('\0');
 
422
        
 
423
        length_target_directory = temp - target_directory;
 
424
        
 
425
        
 
426
        /* target_fullname
 
427
        Append the executable name (TARGET) to target_directory.
 
428
        */
 
429
        length_target = _tcslen( _T(TARGET) );
 
430
        length_target_fullname = length_target_directory + length_target;
 
431
        
 
432
        target_fullname = malloc( ( length_target_fullname + 1 ) * sizeof( TCHAR ) );
 
433
        if( !target_fullname )
 
434
        {
 
435
                VERBOSE_ERR( _T("malloc() failed. Could not initialize target_fullname.") );
 
436
                
 
437
                length_target_fullname = 0;
 
438
                goto cleanup;
 
439
        }
 
440
        
 
441
        temp = target_fullname;
 
442
        
 
443
        memcpy( temp, target_directory, ( length_target_directory * sizeof( TCHAR ) ) );
 
444
        temp += length_target_directory;
 
445
        
 
446
        memcpy( temp, _T(TARGET), ( length_target * sizeof( TCHAR ) ) );
 
447
        temp += length_target;
 
448
        
 
449
        *temp = _T('\0');
 
450
        
 
451
        if( !file_exists( target_fullname ) )
 
452
        {
 
453
                VERBOSE_ERR_DATA(
 
454
                        _T("File not found. Could not initialize target_fullname."),
 
455
                        target_fullname
 
456
                        );
 
457
                
 
458
                length_target_fullname = 0;
 
459
                goto cleanup;
 
460
        }
 
461
        
 
462
        
 
463
        /* target_command
 
464
        Make the target command to execute from the target_fullname and TARGET_OPTIONS
 
465
        */
 
466
        max_length_target_command = 1024 + length_target_fullname;
 
467
        
 
468
        target_command = malloc( ( max_length_target_command + 1 ) * sizeof( TCHAR ) );
 
469
        if( !target_command )
 
470
        {
 
471
                VERBOSE_ERR( _T("malloc() failed. Could not initialize target_command.") );
 
472
                
 
473
                length_target_command = 0;
 
474
                goto cleanup;
 
475
        }
 
476
        
 
477
        /* what follows target_fullname cannot be all trailing spaces.
 
478
        "\"C:\whatever.exe\" "
 
479
        the legacy run key will not handle that properly and would not start whatever.exe
 
480
        it will not start a program with trailing spaces. if there are options then trailing spaces can 
 
481
        follow that, so this is ok:
 
482
        "\"C:\whatever.exe\" --arf "
 
483
        */
 
484
        for( temp = _T(TARGET_OPTIONS); *temp == _T(' '); ++temp )
 
485
        ;
 
486
        
 
487
        length_target_command =
 
488
                _sntprintf(
 
489
                        target_command,
 
490
                        max_length_target_command,
 
491
                        _T("\"%s\"%s%s"),
 
492
                        target_fullname,
 
493
                        ( *temp ? _T(" ") : _T("") ),
 
494
                        temp
 
495
                        );
 
496
        
 
497
        if( length_target_command < 0 )
 
498
        {
 
499
                VERBOSE_ERR_DATA2(
 
500
                        _T("_sntprintf() failed. Could not initialize target_command."),
 
501
                        target_fullname,
 
502
                        _T(TARGET_OPTIONS)
 
503
                        );
 
504
                
 
505
                length_target_command = 0;
 
506
                goto cleanup;
 
507
        }
 
508
        
 
509
        target_command[ length_target_command ] = _T('\0');
 
510
        
 
511
cleanup:
 
512
        if( !length_target_directory )
 
513
        {
 
514
                free( target_directory );
 
515
                target_directory = NULL;
 
516
        }
 
517
        
 
518
        if( !target_directory )
 
519
                length_target_directory = 0;
 
520
        
 
521
        if( !length_target_fullname )
 
522
        {
 
523
                free( target_fullname );
 
524
                target_fullname = NULL;
 
525
        }
 
526
        
 
527
        if( !target_fullname )
 
528
                length_target_fullname = 0;
 
529
        
 
530
        if( !length_target_command )
 
531
        {
 
532
                free( target_command );
 
533
                target_command = NULL;
 
534
        }
 
535
        
 
536
        if( !target_command )
 
537
                length_target_command = 0;
 
538
        
 
539
        return( target_directory && target_fullname && target_command );
 
540
}
 
541
 
 
542
 
 
543
 
 
544
/* add_autorun_entry()
 
545
 
 
546
Adds an autorun entry for your program. Returns TRUE on success.
 
547
 
 
548
if 'users' == NEW_USERS then add only if TARGET has never before been started by the user.
 
549
if 'users' == ALL_USERS then add always.
 
550
if 'users' == UPDATE_EXISTING_AUTORUN_ONLY then only update an existing entry.
 
551
 
 
552
regardless of the value of 'users', if the user already has an autorun entry it is updated with the 
 
553
new location.
 
554
 
 
555
To determine if your TARGET program has ever before been run by the user, this function checks for 
 
556
the existence of HKCU registry key HKCU_PROJECT_KEY.
 
557
*/
 
558
BOOL add_autorun_entry( enum users users )
 
559
{
 
560
        LONG ret = 0;
 
561
        HKEY hkey = NULL;
 
562
        
 
563
        
 
564
        if( !target_command )
 
565
        {
 
566
                VERBOSE_ERR( _T("Parameter validation failed. target_command == NULL") );
 
567
                return FALSE;
 
568
        }
 
569
        
 
570
        if( ( users < 0 ) || ( users >= INVALID ) )
 
571
        {
 
572
                VERBOSE_ERR( _T("Parameter validation failed. users enumeration tag unrecognized.") );
 
573
                return FALSE;
 
574
        }
 
575
        
 
576
        
 
577
        ret = RegCreateKeyEx(
 
578
                HKEY_CURRENT_USER,
 
579
                _T(HKCU_AUTORUN_KEY),
 
580
                0,
 
581
                NULL,
 
582
                0,
 
583
                ( KEY_READ | KEY_WRITE ),
 
584
                NULL,
 
585
                &hkey,
 
586
                NULL
 
587
                );
 
588
        
 
589
        if( ret )
 
590
        {
 
591
                VERBOSE_ERR_DATA(
 
592
                        _T("RegCreateKeyEx() failed. The HKCU autorun key couldn't be opened for writing."),
 
593
                        _T(HKCU_AUTORUN_KEY)
 
594
                        );
 
595
                
 
596
                return FALSE;
 
597
        }
 
598
        
 
599
        
 
600
        /* if the autorun value doesn't exist */
 
601
        if( RegQueryValueEx( hkey, _T(AUTORUN_VALUE), NULL, NULL, NULL, NULL ) )
 
602
        {
 
603
                /* if setting an autorun entry for new users, and the user isn't new (project key exists) */
 
604
                if( ( users == NEW_USERS )
 
605
                        && regkey_test_read( HKEY_CURRENT_USER, _T(HKCU_PROJECT_KEY) )
 
606
                        )
 
607
                {
 
608
                        VERBOSE_MSG_DATA( 
 
609
                                _T("Existing project key and no existing autorun entry. No entry has been added."),
 
610
                                _T(HKCU_PROJECT_KEY)
 
611
                                );
 
612
                        
 
613
                        return FALSE;
 
614
                }
 
615
                else if( users == UPDATE_EXISTING_AUTORUN_ONLY )
 
616
                {
 
617
                        VERBOSE_ERR( _T("No existing autorun entry to update.") );
 
618
                        
 
619
                        return FALSE;
 
620
                }
 
621
        }
 
622
        
 
623
        
 
624
        ret = RegSetValueEx(
 
625
                hkey,
 
626
                _T(AUTORUN_VALUE),
 
627
                0,
 
628
                REG_SZ,
 
629
                (const BYTE *)target_command,
 
630
                ( ( length_target_command + 1 ) * sizeof( TCHAR ) )
 
631
                );
 
632
        
 
633
        RegCloseKey( hkey );
 
634
        
 
635
        if( ret )
 
636
        {
 
637
                VERBOSE_ERR_DATA2(
 
638
                        _T("RegSetValueEx() failed. The autorun value couldn't be written."),
 
639
                        _T(AUTORUN_VALUE),
 
640
                        target_command
 
641
                        );
 
642
                
 
643
                return FALSE;
 
644
        }
 
645
        
 
646
        VERBOSE_MSG_DATA( _T("The autorun data was successfully added."), target_command );
 
647
        return TRUE;
 
648
}
 
649
 
 
650
 
 
651
 
 
652
/* Returns TRUE if your project's HKCU autorun entry was deleted. */
 
653
BOOL remove_autorun_entry()
 
654
{
 
655
        LONG ret = 0;
 
656
        HKEY hkey = NULL;
 
657
        
 
658
        
 
659
        ret = RegOpenKeyEx(
 
660
                HKEY_CURRENT_USER,
 
661
                _T(HKCU_AUTORUN_KEY),
 
662
                0,
 
663
                ( KEY_READ | KEY_WRITE ),
 
664
                &hkey
 
665
                );
 
666
        
 
667
        if( ret || !hkey )
 
668
        {
 
669
                VERBOSE_ERR_DATA(
 
670
                        _T("RegOpenKeyEx() failed. The HKCU autorun key doesn't exist or couldn't be read."),
 
671
                        _T(HKCU_AUTORUN_KEY)
 
672
                        );
 
673
                
 
674
                return FALSE;
 
675
        }
 
676
        
 
677
        ret = RegQueryValueEx( hkey, _T(AUTORUN_VALUE), NULL, NULL, NULL, NULL );
 
678
        
 
679
        if( ret )
 
680
        {
 
681
                if( ( ret == ERROR_FILE_NOT_FOUND ) || ( ret == ERROR_PATH_NOT_FOUND ) )
 
682
                {
 
683
                        VERBOSE_ERR_DATA(
 
684
                                _T("The autorun value does not exist. There is nothing to delete."),
 
685
                                _T(AUTORUN_VALUE)
 
686
                                );
 
687
                }
 
688
                else
 
689
                {
 
690
                        VERBOSE_ERR_DATA(
 
691
                                _T("RegQueryValueEx() failed. The value could not be read."),
 
692
                                _T(AUTORUN_VALUE)
 
693
                                );
 
694
                }
 
695
                
 
696
                return FALSE;
 
697
        }
 
698
        
 
699
        ret = RegDeleteValue( hkey, _T(AUTORUN_VALUE) );
 
700
        
 
701
        RegCloseKey( hkey );
 
702
        
 
703
        if( ret )
 
704
        {
 
705
                VERBOSE_ERR_DATA(
 
706
                        _T("RegDeleteValue() failed. The autorun value doesn't exist or could not be read."),
 
707
                        _T(AUTORUN_VALUE)
 
708
                        );
 
709
                
 
710
                return FALSE;
 
711
        }
 
712
        
 
713
        VERBOSE_MSG( _T("Your project's autorun entry was successfully deleted.") );
 
714
        return TRUE;
 
715
}
 
716
 
 
717
 
 
718
 
 
719
/* Returns TRUE if your project's HKCU Active Setup key was deleted. */
 
720
BOOL remove_activesetup_entry()
 
721
{
 
722
        BOOL deleted = FALSE;
 
723
        LONG ( WINAPI *pRegDeleteKeyEx )( HKEY, LPCTSTR, REGSAM, DWORD ) = NULL;
 
724
        
 
725
        TCHAR *subkey_default =
 
726
                _T("SOFTWARE\\Microsoft\\Active Setup\\Installed Components\\")
 
727
                        _T(ACTIVE_SETUP_GUID);
 
728
        
 
729
        TCHAR *subkey_wow =
 
730
                _T("SOFTWARE\\Wow6432Node\\Microsoft\\Active Setup\\Installed Components\\")
 
731
                        _T(ACTIVE_SETUP_GUID);
 
732
        
 
733
        
 
734
        if( !RegDeleteKey( HKEY_CURRENT_USER, subkey_default ) )
 
735
                        deleted = TRUE;
 
736
        
 
737
        /* This one probably won't work. */
 
738
        if( !RegDeleteKey( HKEY_CURRENT_USER, subkey_wow ) )
 
739
                        deleted = TRUE;
 
740
        
 
741
        
 
742
        pRegDeleteKeyEx = ( LONG ( WINAPI * )( HKEY, LPCTSTR, REGSAM, DWORD ) )
 
743
                GetProcAddress(
 
744
                        GetModuleHandleA( "Advapi32" ),
 
745
                        ( ( sizeof( TCHAR ) == 1 ) ? "RegDeleteKeyExA" : "RegDeleteKeyExW" )
 
746
                        );
 
747
        
 
748
        if( pRegDeleteKeyEx )
 
749
        {
 
750
                if( !pRegDeleteKeyEx( HKEY_CURRENT_USER, subkey_default, KEY_WOW64_32KEY, 0 ) )
 
751
                        deleted = TRUE;
 
752
                
 
753
                if( !pRegDeleteKeyEx( HKEY_CURRENT_USER, subkey_default, KEY_WOW64_64KEY, 0 ) )
 
754
                        deleted = TRUE;
 
755
        }
 
756
        
 
757
        
 
758
        if( !deleted )
 
759
        {
 
760
                VERBOSE_ERR_DATA( 
 
761
                        _T("Your project's Active Setup key either does not exist or could not be deleted."),
 
762
                        subkey_default
 
763
                        );
 
764
                
 
765
                return FALSE;
 
766
        }
 
767
        
 
768
        VERBOSE_MSG( _T("Your project's Active Setup key was successfully deleted.") );
 
769
        return TRUE;
 
770
}
 
771
 
 
772
 
 
773
 
 
774
/* Returns FALSE if tstring is NULL or is empty or contains only whitespace. */
 
775
BOOL param_check_tstring( const TCHAR *tstring )
 
776
{
 
777
        if( !tstring )
 
778
                return FALSE;
 
779
        
 
780
        while( ( *tstring == _T(' ') ) || ( *tstring == _T('\t') ) )
 
781
                ++tstring;
 
782
        
 
783
        return !!*tstring;
 
784
}
 
785
 
 
786
 
 
787
 
 
788
/* Returns FALSE if some string literal is empty that shouldn't be. */
 
789
BOOL check_global_literals()
 
790
{
 
791
        BOOL pass = TRUE;
 
792
        
 
793
#define CHECK_LITERAL(literal) \
 
794
        if( !param_check_tstring( _T(literal) ) ) \
 
795
        { \
 
796
                pass = FALSE; \
 
797
                VERBOSE_ERR_DATA( \
 
798
                        _T("Program to fail. tstring literal is empty or contains only whitespace."), \
 
799
                        _T(#literal) \
 
800
                        ); \
 
801
        }
 
802
        
 
803
        CHECK_LITERAL( HKCU_AUTORUN_KEY );
 
804
        CHECK_LITERAL( ACTIVE_SETUP_GUID );
 
805
        CHECK_LITERAL( AUTORUN_VALUE );
 
806
        CHECK_LITERAL( PROJECT );
 
807
        CHECK_LITERAL( HKCU_PROJECT_KEY );
 
808
        CHECK_LITERAL( TARGET );
 
809
        /* TARGET_OPTIONS can be empty */
 
810
        
 
811
        return pass;
 
812
}
 
813
 
 
814
 
 
815
 
 
816
void show_help()
 
817
{
 
818
        MessageBoxA( 
 
819
                0,
 
820
                "This is a configuration tool added by this project's installer.\n"
 
821
                        "This program is invoked by Microsoft's undocumented Active Setup.\n"
 
822
                        "If you do not understand what this program does don't use it.\n"
 
823
                        "\n"
 
824
                        "ACTIVE_SETUP_GUID: " ACTIVE_SETUP_GUID "\n"
 
825
                        "AUTORUN_VALUE: " AUTORUN_VALUE "\n"
 
826
                        "PROJECT: " PROJECT "\n"
 
827
                        "HKCU_PROJECT_KEY: " HKCU_PROJECT_KEY "\n"
 
828
                        "TARGET: " TARGET "\n"
 
829
                        "TARGET_OPTIONS: " TARGET_OPTIONS "\n"
 
830
                        "\n"
 
831
                        "Options:\n"
 
832
                        "-a" "\t" "Add autorun always.\n"
 
833
                        "-b" "\t" "Add autorun only if user has never before used your project.\n"
 
834
                        "-d" "\t" "Remove the autorun entry.\n"
 
835
                        "-r" "\t" "Remove the Active Setup entry.\n"
 
836
                        "-u" "\t" "Update existing autorun entry.\n"
 
837
                        "-v" "\t" "Be verbose. If multiple arguments this must be the first.\n"
 
838
                        "-z" "\t" "Show each passed in argument for testing purposes.\n"
 
839
                        "\n"
 
840
                        "The 'Add autorun' options are mutually exclusive. Using either \n"
 
841
                        "implies option 'u', which updates an existing autorun entry, if any.\n"
 
842
                        "\n"
 
843
                        "Option 'r' removes the HKCU Active Setup entry, if any, and not the\n"
 
844
                        "HKLM Active Setup entry. What that means is Active Setup will be\n"
 
845
                        "reset for the user, and will run the next time the user logs on.\n",
 
846
                "Help - ChangeAutorun",
 
847
                0
 
848
        );
 
849
        
 
850
        return;
 
851
}
 
852
 
 
853
 
 
854
 
 
855
void just_testing( int argc, char **argv )
 
856
{
 
857
        int i = 0;
 
858
        
 
859
        for( i = 0; i < argc; ++i )
 
860
                MessageBoxA( 0, argv[ i ], argv[ i ], 0 );
 
861
        
 
862
        if( argv[ i ] )
 
863
                MessageBoxA( 0, "Final argv pointer is not NULL", "WARNING", 0 );
 
864
        
 
865
        return;
 
866
}
 
867
 
 
868
int _CRT_glob = 0;
 
869
 
 
870
int APIENTRY WinMain(
 
871
        HINSTANCE hInstance,
 
872
        HINSTANCE hPrevInstance,
 
873
        LPSTR lpCmdLine,
 
874
        int nCmdShow
 
875
        )
 
876
{
 
877
        int i = 0, j = 0;
 
878
        int argc = 0;
 
879
        char **argv = NULL;
 
880
        
 
881
        
 
882
        SetErrorMode( 
 
883
                ( SEM_FAILCRITICALERRORS 
 
884
                        | SEM_NOGPFAULTERRORBOX
 
885
                        | SEM_NOOPENFILEERRORBOX )
 
886
                );
 
887
        
 
888
        argv = __argv;
 
889
        argc = __argc;
 
890
        if( argc <= 1 )
 
891
                return 1;
 
892
        
 
893
        if( argc >= 2 
 
894
                && ( ( argv[ 1 ][ 0 ] == '/' )
 
895
                        || ( argv[ 1 ][ 0 ] == '-' ) )
 
896
                )
 
897
        {
 
898
                if( ( argv[ 1 ][ 1 ] == 'v' )
 
899
                        || ( argv[ 1 ][ 1 ] == 'V' )
 
900
                        )
 
901
                {
 
902
                        g_verbose = TRUE;
 
903
                }
 
904
                else if( ( argv[ 1 ][ 1 ] == '?' )
 
905
                        || ( argv[ 1 ][ 1 ] == 'h' )
 
906
                        || ( argv[ 1 ][ 1 ] == 'H' )
 
907
                        )
 
908
                {
 
909
                        show_help();
 
910
                        return 0;
 
911
                }
 
912
        }
 
913
        
 
914
        
 
915
        if( !check_global_literals() )
 
916
                return 1;
 
917
        
 
918
        init_global_variables();
 
919
        
 
920
        for( i = 1; i < argc; ++i )
 
921
        {
 
922
                if( argv[ i ][ 0 ] != '-' && argv[ i ][ 0 ] != '/' )
 
923
                        continue;
 
924
                
 
925
                for( j = 1; argv[ i ][ j ]; ++j )
 
926
                {
 
927
                        switch( argv[ i ][ j ] )
 
928
                        {
 
929
                                case 'a':
 
930
                                case 'A':
 
931
                                        add_autorun_entry( ALL_USERS );
 
932
                                        break;
 
933
                                
 
934
                                case 'b':
 
935
                                case 'B':
 
936
                                        add_autorun_entry( NEW_USERS );
 
937
                                        break;
 
938
                                
 
939
                                case 'd':
 
940
                                case 'D':
 
941
                                        remove_autorun_entry();
 
942
                                        break;
 
943
                                
 
944
                                case 'r':
 
945
                                case 'R':
 
946
                                        remove_activesetup_entry();
 
947
                                        break;
 
948
                                
 
949
                                case 'u':
 
950
                                case 'U':
 
951
                                        add_autorun_entry( UPDATE_EXISTING_AUTORUN_ONLY );
 
952
                                        break;
 
953
                                
 
954
                                case 'z':
 
955
                                case 'Z':
 
956
                                        just_testing( argc, argv );
 
957
                                        break;
 
958
                        }
 
959
                }
 
960
        }
 
961
        
 
962
        free_global_variables();
 
963
        
 
964
        return 0;
 
965
}