summaryrefslogtreecommitdiff
path: root/magick/command.c
diff options
context:
space:
mode:
Diffstat (limited to 'magick/command.c')
-rw-r--r--magick/command.c287
1 files changed, 207 insertions, 80 deletions
diff --git a/magick/command.c b/magick/command.c
index f51017a..1b51eac 100644
--- a/magick/command.c
+++ b/magick/command.c
@@ -1,5 +1,5 @@
/*
-% Copyright (C) 2003 - 2022 GraphicsMagick Group
+% Copyright (C) 2003 - 2023 GraphicsMagick Group
% Copyright (C) 2002 ImageMagick Studio
%
% This program is covered by multiple licenses, which are described in
@@ -129,13 +129,19 @@ typedef int (*CommandLineParser)(FILE *in, int acmax, char **av);
#define SIZE_OPTION_VALUE 256
typedef struct _BatchOptions {
- MagickBool stop_on_error,
- is_feedback_enabled,
- is_echo_enabled;
- char prompt[SIZE_OPTION_VALUE],
- pass[SIZE_OPTION_VALUE],
- fail[SIZE_OPTION_VALUE];
- CommandLineParser command_line_parser;
+ MagickBool
+ stop_on_error,
+ is_feedback_enabled,
+ is_echo_enabled,
+ is_tap_mode;
+
+ char
+ prompt[SIZE_OPTION_VALUE],
+ pass[SIZE_OPTION_VALUE],
+ fail[SIZE_OPTION_VALUE];
+
+ CommandLineParser
+ command_line_parser;
} BatchOptions;
typedef MagickPassFail (*CommandVectorHandler)(ImageInfo *image_info,
@@ -1161,7 +1167,11 @@ MagickExport MagickPassFail AnimateImageCommand(ImageInfo *image_info,
{
if (LocaleCompare("map",option+1) == 0)
{
- (void) strcpy(argv[i]+1,"sans");
+ /*
+ Indicate that option was already handled so
+ MogrifyImage() will ignore it.
+ */
+ (void) strlcpy(argv[i]+1,"Z",strlen(argv[i]+1)+1);
resource_info.map_type=(char *) NULL;
if (*option == '-')
{
@@ -1470,6 +1480,7 @@ MagickExport MagickPassFail AnimateImageCommand(ImageInfo *image_info,
(void) CatchImageException(image);
AppendImageToList(&image_list,image);
}
+ image_list=GetFirstImageInList(image_list);
if (resource_info.window_id != (char *) NULL)
MagickXAnimateBackgroundImage(display,&resource_info,image_list);
else
@@ -1542,6 +1553,7 @@ static MagickPassFail BatchCommand(int argc, char **argv)
MagickBool hasInputFile;
int ac;
char *av[MAX_PARAM+1];
+ unsigned int line_no = 0;
#if defined(MSWINDOWS)
InitializeMagick((char *) NULL);
@@ -1595,9 +1607,15 @@ static MagickPassFail BatchCommand(int argc, char **argv)
(void) fflush(stdout);
}
+
while (!(ferror(stdin) || ferror(stdout) || ferror(stderr) || feof(stdin)))
{
- if (batch_options.prompt[0])
+ if (batch_options.is_tap_mode)
+ {
+ (void) fputs("# ", stdout);
+ (void) fflush(stdout);
+ }
+ else if (batch_options.prompt[0])
{
(void) fputs(batch_options.prompt, stdout);
(void) fflush(stdout);
@@ -1609,7 +1627,7 @@ static MagickPassFail BatchCommand(int argc, char **argv)
result = MagickPass;
break;
};
- if (batch_options.is_echo_enabled)
+ if (batch_options.is_tap_mode || batch_options.is_echo_enabled)
{
int i;
for (i = 1; i < ac; i++)
@@ -1636,8 +1654,14 @@ static MagickPassFail BatchCommand(int argc, char **argv)
MAX_PARAM);
result = MagickFail;
}
+ ++line_no;
- if (batch_options.is_feedback_enabled)
+ if (batch_options.is_tap_mode)
+ {
+ /* FIXME: Support TAP test description */
+ (void) fprintf(stdout, "%s %u\n", result ? "ok" : "not ok", line_no);
+ }
+ else if (batch_options.is_feedback_enabled)
{
(void) fputs(result ? batch_options.pass : batch_options.fail, stdout);
(void) fputc('\n', stdout);
@@ -1649,7 +1673,7 @@ static MagickPassFail BatchCommand(int argc, char **argv)
break;
}
- if (batch_options.prompt[0])
+ if (!batch_options.is_tap_mode && batch_options.prompt[0])
{
(void) fputs("\n", stdout);
(void) fflush(stdout);
@@ -1697,6 +1721,12 @@ static void BatchOptionUsage(void)
" -stop-on-error on|off\n"
" when turned on, batch execution quits prematurely when\n"
" any command returns error\n"
+ " -tap-mode on|off\n"
+ " when turned on, a simple implementation of Test Anything\n"
+ " Protocol (TAP) is enabled to produce \"ok N\" and \n"
+ " \"not ok N\" feedback to indicate the test number, and to\n"
+ " supplant the function of -fail, -pass, -feedback in order\n"
+ " to support simple TAP output messaging\n"
"\n"
"Unix escape allows the use backslash(\\), single quote(') and double quote(\") in\n"
"the command line. Windows escape only uses double quote(\"). For example,\n"
@@ -3796,8 +3826,12 @@ MagickExport MagickPassFail CompositeImageCommand(ImageInfo *image_info,
break;
if (LocaleCompare("noop",option+1) == 0)
{
+ if (image == NULL)
+ ThrowCompositeException(OptionError,NoImagesDefined,
+ "no images in composite image list");
+
status&=CompositeImageList(image_info,&image,composite_image,
- mask_image,&option_info,exception);
+ mask_image,&option_info,exception);
if (composite_image != (Image *) NULL)
{
DestroyImageList(composite_image);
@@ -5590,6 +5624,11 @@ MagickExport MagickPassFail ConvertImageCommand(ImageInfo *image_info,
ThrowConvertException(OptionError,MissingArgument,
option);
}
+ else
+ {
+ ThrowConvertException(OptionError,MissingArgument,
+ option);
+ }
break;
}
if (LocaleCompare("ordered-dither",option+1) == 0)
@@ -5778,7 +5817,7 @@ MagickExport MagickPassFail ConvertImageCommand(ImageInfo *image_info,
if (*option == '-')
{
i++;
- if ((i == (argc-1)) || !IsGeometry(argv[i]))
+ if ((i == argc) || !IsGeometry(argv[i]))
ThrowConvertException(OptionError,MissingArgument,option);
}
break;
@@ -6215,15 +6254,18 @@ MagickExport MagickPassFail ConvertImageCommand(ImageInfo *image_info,
ThrowConvertException(OptionError,MissingAnImageFilename,(char *) NULL);
if (image == (Image *) NULL)
{
- status&=MogrifyImages(image_info,i-j,argv+j,&image_list);
+ if (!ping)
+ status&=MogrifyImages(image_info,i-j,argv+j,&image_list);
GetImageException(image_list,exception);
}
else
{
- status&=MogrifyImages(image_info,i-j,argv+j,&image);
+ if (!ping)
+ status&=MogrifyImages(image_info,i-j,argv+j,&image);
GetImageException(image,exception);
AppendImageToList(&image_list,image);
}
+ image_list=GetFirstImageInList(image_list);
status&=WriteImages(image_info,image_list,argv[argc-1],exception);
if (metadata != (char **) NULL)
{
@@ -6481,7 +6523,7 @@ static void ConjureUsage(void)
(void) puts(" -verbose print detailed information about the image");
(void) puts(" -version print version information");
(void) puts("");
- (void) puts("In additiion, define any key value pairs required by your script. For");
+ (void) puts("In addition, define any key value pairs required by your script. For");
(void) puts("example,");
(void) puts("");
(void) puts(" conjure -size 100x100 -color blue -foo bar script.msl");
@@ -6582,10 +6624,12 @@ MagickExport MagickPassFail ConjureImageCommand(ImageInfo *image_info,
Persist key/value pair.
*/
(void) SetImageAttribute(image_info->attributes,option+1,(char *) NULL);
- status&=SetImageAttribute(image_info->attributes,option+1,argv[i+1]);
+ i++;
+ if (i == argc)
+ MagickFatalError(OptionFatalError,MissingArgument,option);
+ status&=SetImageAttribute(image_info->attributes,option+1,argv[i]);
if (status == MagickFail)
MagickFatalError(ImageFatalError,UnableToPersistKey,option);
- i++;
continue;
}
/*
@@ -6922,7 +6966,7 @@ MagickExport MagickPassFail DisplayImageCommand(ImageInfo *image_info,
(void) MagickSceneFileName(filename,image_info->filename,".%lu",MagickTrue,scene);
(void) strlcpy(image_info->filename,filename,MaxTextExtent);
}
- (void) strcpy(image_info->magick,"MIFF");
+ (void) strlcpy(image_info->magick,"MIFF",sizeof(image_info->magick));
image_info->colorspace=quantize_info->colorspace;
image_info->dither=quantize_info->dither;
DestroyExceptionInfo(exception);
@@ -7590,7 +7634,11 @@ MagickExport MagickPassFail DisplayImageCommand(ImageInfo *image_info,
}
if (LocaleCompare("map",option+1) == 0)
{
- (void) strcpy(argv[i]+1,"sans");
+ /*
+ Indicate that option was already handled so
+ MogrifyImage() will ignore it.
+ */
+ (void) strlcpy(argv[i]+1,"Z",strlen(argv[i]+1)+1);
resource_info.map_type=(char *) NULL;
if (*option == '-')
{
@@ -8834,15 +8882,15 @@ static void IdentifyUsage(void)
*/
static void InitializeBatchOptions(MagickBool prompt)
{
- strcpy(batch_options.pass, "PASS");
- strcpy(batch_options.fail, "FAIL");
+ strlcpy(batch_options.pass, "PASS", sizeof(batch_options.pass));
+ strlcpy(batch_options.fail, "FAIL", sizeof(batch_options.fail));
#if defined(MSWINDOWS)
batch_options.command_line_parser = ParseWindowsCommandLine;
#else
batch_options.command_line_parser = ParseUnixCommandLine;
#endif
if (prompt)
- strcpy(batch_options.prompt, "GM> ");
+ strlcpy(batch_options.prompt, "GM> ", sizeof(batch_options.prompt));
}
@@ -8942,12 +8990,9 @@ MagickExport MagickPassFail MagickCommand(ImageInfo *image_info,
char
command_name[MaxTextExtent];
- const char
- *pos;
-
/*
- Append subcommand name to existing client name if end of
- existing client name is not identical to subcommand name.
+ Append subcommand name to existing client name if existing
+ client name is not identical to subcommand name.
*/
LockSemaphoreInfo(command_semaphore);
if (run_mode == BatchMode)
@@ -8955,9 +9000,7 @@ MagickExport MagickPassFail MagickCommand(ImageInfo *image_info,
else
{
GetPathComponent(GetClientName(),BasePath,command_name);
- pos=strrchr(command_name,' ');
- if ((pos == (const char *) NULL) ||
- (LocaleCompare(commands[i].command,pos+1) != 0))
+ if (LocaleCompare(commands[i].command,command_name) != 0)
{
char
client_name[MaxTextExtent];
@@ -9421,6 +9464,11 @@ MagickExport MagickPassFail MogrifyImage(const ImageInfo *image_info,
type=(*option);
option=argv[++i];
colorspace=StringToColorspaceType(option);
+ if (colorspace == UndefinedColorspace)
+ {
+ ThrowException(&(*image)->exception,OptionError,MissingArgument,"colorspace");
+ break;
+ }
quantize_info.colorspace=colorspace;
/* Never quantize in CMYK colorspace */
if (IsCMYKColorspace(colorspace))
@@ -9681,7 +9729,12 @@ MagickExport MagickPassFail MogrifyImage(const ImageInfo *image_info,
*/
MagickFreeMemory(draw_info->primitive);
draw_info->primitive=AmpersandTranslateText(clone_info,*image,argv[++i]);
- (void) DrawImage(*image,draw_info);
+ if (draw_info->primitive == (char *) NULL)
+ {
+ ThrowException(&(*image)->exception,OptionError,MissingArgument,option);
+ break;
+ }
+ (void) DrawImage(*image,draw_info);
continue;
}
break;
@@ -10093,10 +10146,16 @@ MagickExport MagickPassFail MogrifyImage(const ImageInfo *image_info,
/*
Local adaptive threshold image.
*/
- offset=0;
- height=3;
- width=3;
- (void) sscanf(argv[++i],"%lux%lu%lf",&width,&height,&offset);
+ if (sscanf(argv[++i],"%lux%lu%lf",&width,&height,&offset) != 3)
+ {
+ ThrowException(&(*image)->exception,OptionError,MissingArgument,option);
+ break;
+ }
+ if ((width == 0) || (height == 0))
+ {
+ ThrowException3(&(*image)->exception,OptionError,UnableToThresholdImage,NonzeroWidthAndHeightRequired);
+ break;
+ }
if (strchr(argv[i],'%') != (char *) NULL)
offset*=((double) MaxRGB/100.0);
threshold_image=AdaptiveThresholdImage(*image,width,height,offset,
@@ -10360,34 +10419,53 @@ MagickExport MagickPassFail MogrifyImage(const ImageInfo *image_info,
}
if (LocaleCompare("operator",option+1) == 0)
{
- ChannelType
- channel;
+ if (*option == '-')
+ {
+ ChannelType
+ channel;
- QuantumOperator
- quantum_operator;
+ QuantumOperator
+ quantum_operator;
- double
- rvalue;
+ double
+ rvalue;
- /* channel */
- channel=StringToChannelType(argv[++i]);
+ if (i+3 > argc)
+ {
+ ThrowException(&(*image)->exception,OptionError,MissingArgument,option+1);
+ break;
+ }
- /* operator id */
- quantum_operator=StringToQuantumOperator(argv[++i]);
+ /* channel */
+ channel=StringToChannelType(argv[++i]);
- /* rvalue */
- option=argv[++i];
- rvalue=StringToDouble(option,MaxRGB);
- (void) QuantumOperatorImage(*image,channel,quantum_operator,
- rvalue,&(*image)->exception);
+ /* operator id */
+ quantum_operator=StringToQuantumOperator(argv[++i]);
- continue;
+ /* rvalue */
+ option=argv[++i];
+ rvalue=StringToDouble(option,MaxRGBDouble);
+ (void) QuantumOperatorImage(*image,channel,quantum_operator,
+ rvalue,&(*image)->exception);
+
+ continue;
+ }
+ else
+ {
+ ThrowException(&(*image)->exception,OptionError,MissingArgument,option+1);
+ break;
+ }
}
if (LocaleCompare("ordered-dither",option+1) == 0)
{
/*
Ordered-dither image.
*/
+ if (i+2 > argc)
+ {
+ ThrowException(&(*image)->exception,OptionError,MissingArgument,option+1);
+ break;
+ }
(void) RandomChannelThresholdImage(*image,argv[i+1],argv[i+2],
&(*image)->exception);
i+=2;
@@ -10589,6 +10667,11 @@ MagickExport MagickPassFail MogrifyImage(const ImageInfo *image_info,
/*
Threshold image.
*/
+ if (i+2 > argc)
+ {
+ ThrowException(&(*image)->exception,OptionError,MissingArgument,option+1);
+ break;
+ }
(void) RandomChannelThresholdImage(*image,argv[i+1],argv[i+2],
&(*image)->exception);
i+=2;
@@ -10685,6 +10768,7 @@ MagickExport MagickPassFail MogrifyImage(const ImageInfo *image_info,
region_geometry.y);
DestroyImage(*image);
*image=region_image;
+ region_image=(Image *) NULL;
}
if (*option == '+')
continue;
@@ -10896,9 +10980,6 @@ MagickExport MagickPassFail MogrifyImage(const ImageInfo *image_info,
NormalizeSamplingFactor(clone_info);
continue;
}
- if (LocaleCompare("sans",option+1) == 0)
- if (*option == '-')
- i++;
if (LocaleCompare("scale",option+1) == 0)
{
Image
@@ -10930,10 +11011,20 @@ MagickExport MagickPassFail MogrifyImage(const ImageInfo *image_info,
*key,
*value;
+ if (i+1 > argc)
+ {
+ ThrowException(&(*image)->exception,OptionError,MissingArgument,option+1);
+ break;
+ }
key=argv[++i];
(void) SetImageAttribute(*image,key,(char *) NULL);
if (*option == '-')
{
+ if (i+1 > argc)
+ {
+ ThrowException(&(*image)->exception,OptionError,MissingArgument,option+1);
+ break;
+ }
value=argv[++i];
(void) SetImageAttribute(*image,key,value);
}
@@ -11388,11 +11479,25 @@ MagickExport MagickPassFail MogrifyImage(const ImageInfo *image_info,
}
break;
}
+ case 'Z':
+ {
+ /*
+ Option -Z (used to be "sans") indicates an already handled
+ option (so ignore it).
+ */
+ if (LocaleCompare("Z",option+1) == 0)
+ if (*option == '-')
+ {
+ i++;
+ continue;
+ }
+ break;
+ }
default:
break;
}
}
- if (region_image != (Image *) NULL)
+ if ((region_image != (Image *) NULL) && (region_image != *image))
{
/*
Composite transformed region onto image.
@@ -11564,6 +11669,7 @@ MagickExport MagickPassFail MogrifyImages(const ImageInfo *image_info,
}
AppendImageToList(&mogrify_images,image);
}
+ mogrify_images=GetFirstImageInList(mogrify_images);
/*
Apply options to the entire image list.
@@ -11945,7 +12051,7 @@ static MagickPassFail* TransmogrifyImage(TransmogrifyOptions *options)
if (IsWriteable(output_filename))
{
(void) strlcpy(temporary_filename,output_filename,MaxTextExtent);
- (void) strcat(temporary_filename,"~");
+ (void) strlcat(temporary_filename,"~",sizeof(temporary_filename));
if (rename(output_filename,temporary_filename) == 0)
{
if (image_info->verbose)
@@ -12671,7 +12777,7 @@ MagickExport MagickPassFail MogrifyImageCommand(ImageInfo *image_info,
option);
(void) CloneString(&format,argv[i]);
(void) strlcpy(image_info->filename,format,MaxTextExtent);
- (void) strcat(image_info->filename,":");
+ (void) strlcat(image_info->filename,":",sizeof(image_info->filename));
(void) SetImageInfo(image_info,SETMAGICK_WRITE,exception);
if (*image_info->magick == '\0')
ThrowMogrifyException(OptionError,UnrecognizedImageFormat,format);
@@ -13202,6 +13308,11 @@ MagickExport MagickPassFail MogrifyImageCommand(ImageInfo *image_info,
ThrowMogrifyException(OptionError,MissingArgument,
option);
}
+ else
+ {
+ ThrowMogrifyException(OptionError,MissingArgument,
+ option);
+ }
break;
}
if (LocaleCompare("ordered-dither",option+1) == 0)
@@ -13378,16 +13489,6 @@ MagickExport MagickPassFail MogrifyImageCommand(ImageInfo *image_info,
if (*option == '-')
{
i++;
- if ((i == (argc-1)) || !IsGeometry(argv[i]))
- ThrowMogrifyException(OptionError,MissingArgument,option);
- }
- break;
- }
- if (LocaleCompare("resize",option+1) == 0)
- {
- if (*option == '-')
- {
- i++;
if ((i == argc) || !IsGeometry(argv[i]))
ThrowMogrifyException(OptionError,MissingArgument,option);
}
@@ -13399,8 +13500,7 @@ MagickExport MagickPassFail MogrifyImageCommand(ImageInfo *image_info,
{
i++;
if ((i == argc) || !IsGeometry(argv[i]))
- ThrowMogrifyException(OptionError,MissingArgument,
- option);
+ ThrowMogrifyException(OptionError,MissingArgument,option);
}
break;
}
@@ -14584,7 +14684,11 @@ MagickExport MagickPassFail MontageImageCommand(ImageInfo *image_info,
if (LocaleCompare("frame",option+1) == 0)
{
(void) CloneString(&montage_info->frame,(char *) NULL);
- (void) strcpy(argv[i]+1,"sans");
+ /*
+ Indicate that option was already handled so
+ MogrifyImage() will ignore it.
+ */
+ (void) strlcpy(argv[i]+1,"Z",strlen(argv[i]+1)+1);
if (*option == '-')
{
i++;
@@ -14813,6 +14917,10 @@ MagickExport MagickPassFail MontageImageCommand(ImageInfo *image_info,
break;
ThrowMontageException(OptionError,UnrecognizedOption,option)
}
+ case 'o':
+ {
+ ThrowMontageException(OptionError,UnrecognizedOption,option)
+ }
case 'p':
{
if (LocaleCompare("page",option+1) == 0)
@@ -15031,7 +15139,11 @@ MagickExport MagickPassFail MontageImageCommand(ImageInfo *image_info,
if (LocaleCompare("tile",option+1) == 0)
{
(void) CloneString(&montage_info->tile,(char *) NULL);
- (void) strcpy(argv[i]+1,"sans");
+ /*
+ Indicate that option was already handled so
+ MogrifyImage() will ignore it.
+ */
+ (void) strlcpy(argv[i]+1,"Z",strlen(argv[i]+1)+1);
if (*option == '-')
{
i++;
@@ -15097,7 +15209,11 @@ MagickExport MagickPassFail MontageImageCommand(ImageInfo *image_info,
}
break;
}
- ThrowMontageException(OptionError,UnrecognizedOption,option)
+ ThrowMontageException(OptionError,UnrecognizedOption,option);
+ }
+ case 'u':
+ {
+ ThrowMontageException(OptionError,UnrecognizedOption,option);
}
case 'v':
{
@@ -15168,6 +15284,7 @@ MagickExport MagickPassFail MontageImageCommand(ImageInfo *image_info,
*/
(void) strlcpy(montage_info->filename,argv[argc-1],MaxTextExtent);
/* (void) memmove(montage_info->filename,argv[argc-1],strlen(argv[argc-1])+1); */
+ image_list=GetFirstImageInList(image_list);
montage_image=MontageImages(image_list,montage_info,exception);
if (montage_image == (Image *) NULL)
ThrowMontageException(OptionError,RequestDidNotReturnAnImage,(char *) NULL);
@@ -16061,7 +16178,11 @@ MagickExport MagickPassFail ImportImageCommand(ImageInfo *image_info,
}
if (LocaleCompare("snaps",option+1) == 0)
{
- (void) strcpy(argv[i]+1,"sans");
+ /*
+ Indicate that option was already handled so
+ MogrifyImage() will ignore it.
+ */
+ (void) strlcpy(argv[i]+1,"Z",strlen(argv[i]+1)+1);
i++;
if ((i == argc) || !sscanf(argv[i],"%ld",&x))
MagickFatalError(OptionFatalError,MissingArgument,option);
@@ -16178,8 +16299,8 @@ MagickExport MagickPassFail ImportImageCommand(ImageInfo *image_info,
status&=next_image != (Image *) NULL;
if (next_image == (Image *) NULL)
continue;
- (void) strlcpy(next_image->filename,filename,MaxTextExtent);
- (void) strcpy(next_image->magick,"PS");
+ (void) strlcpy(next_image->filename,filename,sizeof(next_image->filename));
+ (void) strlcpy(next_image->magick,"PS",sizeof(next_image->magick));
next_image->scene=i;
next_image->previous=image;
if (image != (Image *) NULL)
@@ -16665,6 +16786,10 @@ static int ProcessBatchOptions(int argc, char **argv, BatchOptions *options)
if (LocaleCompare(option = "-stop-on-error", p) == 0)
status = GetOnOffOptionValue(option, argv[++i], &options->stop_on_error);
break;
+ case 't':
+ if (LocaleCompare(option = "-tap-mode", p) == 0)
+ status = GetOnOffOptionValue(option, argv[++i], &options->is_tap_mode);
+ break;
}
if (status == OptionSuccess)
continue;
@@ -16741,6 +16866,8 @@ static unsigned int SetCommand(ImageInfo *image_info,
printf("stop-on-error : %s\n", on_off_option_values[batch_options.stop_on_error]);
printf("pass : %s\n", batch_options.pass);
printf("prompt : %s\n", batch_options.prompt);
+ printf("tap-mode : %s\n", on_off_option_values[batch_options.is_tap_mode]);
+
return MagickTrue;
}
@@ -17366,8 +17493,8 @@ static MagickPassFail RegisterCommand(ImageInfo *image_info,
ARG_NOT_USED(exception);
memset(szKey, 0, _MAX_PATH*2*sizeof(char));
- strcpy(szKey, szRegPath);
- strcat(szKey, "GraphicsMagick");
+ strlcpy(szKey, szRegPath, sizeof(szKey));
+ strlcat(szKey, "GraphicsMagick", sizeof(szKey));
/* open the registry event source key */
lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, NULL,